接下来来写面板,也就是显示的各种元素,积分面板、蛇、食物。
面板中我们用:init()方法来实现初始化,蛇的初始长度、初始位置,食物的初始位置、积分为0等等。无参构造方法:调用init()方法,这里要单独把初始化写入函数然后再由构造方法调用是为了方便在后面小蛇死亡重新游戏初始化小蛇。获取焦点,创建键盘监听操纵小蛇。设置定时器(后面解释)。
必须要说的贪吃蛇实现原理: 和动画片一样,都涉及一个概念:帧率。当我们连续拍下一组运动照片,这是由动到静,反过来,我们把拍好的照片以很快的速度进行切换,就会复现出人的运动。我们所要做的就是:获取图片(运动轨迹)、快速刷新。在贪吃蛇中获取运动轨迹便是小蛇运动坐标改变后的窗体图片、快速刷新便是定时器,想想这个过程:键盘按下,发出指令,小蛇坐标改变,画笔行动,图像变化,定时刷新,图像连续,形成动画。
画图函数:paintComponent(Graphics g);其中g可以理解为是“画笔”。
public class GamePanel extends JPanel{
//定义两个数组,一个存放蛇的x轴坐标,一个存放y的坐标
//初始化蛇的长度
int length;
//存放x轴坐标
int[] snakeX=new int[200];
//存放y轴坐标
int[] snakeY=new int[200];
//加入一个定时器
Timer timer;
//定义蛇头的行走方向
String direction;
//定义食物的坐标
int foodX;
int foodY;
int score;
//游戏只有两个状态:开始和暂停
boolean isStart=false;//默认游戏是暂停状态
//加入一个变量判断小蛇的状态,死亡、活着
boolean isDie=false;
init初始化函数:
public void init() {
//初始化蛇的长度
length=3;
//初始化蛇头坐标
snakeX[0]=175;
snakeY[0]=275;
//初始化第一节身子坐标
snakeX[1]=150;
snakeY[1]=275;
//初始话第二节身子坐标
snakeX[2]=125;
snakeY[2]=275;
//初始化行走方向
direction="R";
//初始化食物的坐标
foodX=300;
foodY=200;
//定义一个积分
score=0;
}
构造函数:
public GamePanel() {
init();
//将焦点定位在当前操作的面板上
this.setFocusable(true);
//插入监听
this.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
//监听键盘按下操作
super.keyPressed(e);
//监听空格
if(e.getKeyCode()==KeyEvent.VK_SPACE) {
if(isDie) {
init();
isDie=false;
}
else {
isStart=!isStart;
repaint();//重绘动作相当于又调用paintComponent方法
}
}
//监听向上箭头
if(e.getKeyCode()==KeyEvent.VK_UP&&isStart==true) {
direction="U";
repaint();
}
//监听向下箭头
if(e.getKeyCode()==KeyEvent.VK_DOWN&&isStart==true) {
direction="D";
repaint();
}
//监听向左箭头
if(e.getKeyCode()==KeyEvent.VK_LEFT&&isStart==true) {
direction="L";
repaint();
}
//监听向右箭头
if(e.getKeyCode()==KeyEvent.VK_RIGHT&&isStart==true) {
direction="R";
repaint();
}
}
});
timer=new Timer(100,new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(isStart&&isDie==false) {
//游戏是开始情况下蛇才动
for(int i=length-1;i>0;i--) {
snakeX[i]=snakeX[i-1];
snakeY[i]=snakeY[i-1];
}
//蛇头
if("R".equals(direction)) {
snakeX[0]+=25;
}
if("L".equals(direction)) {
snakeX[0]-=25;
}
if("D".equals(direction)) {
snakeY[0]+=25;
}
if("U".equals(direction)) {
snakeY[0]-=25;
}
//控制蛇出界还能回来
if(snakeX[0]>750) {
snakeX[0]=25;
}
if(snakeY[0]>725) {
snakeY[0]=100;
}
if(snakeY[0]<100) {
snakeY[0]=725;
}
if(snakeX[0]<25) {
snakeX[0]=725;
}
//检测碰撞的动作
if(snakeX[0]==foodX&&snakeY[0]==foodY) {
//蛇长度增加
length++;
//积分加10
score+=10;
//食物坐标随机生成,且坐标是25的倍数
foodX= ((int)(Math.random()*30)+1)*25;//[25,750]之间25的倍数
foodY=(new Random().nextInt(26)+4)*25;//[100,725]之间25的倍数
}
//死亡判定
for(int i=1;i<length;i++) {
if(snakeX[0]==snakeX[i]&&snakeY[0]==snakeY[i]) {
isDie=true;
}
}
repaint();//重绘
}
}
});
//定时器必须要启动
timer.start();
}
repaint()会调用paintComponet()
/* 这个方法比较特殊,这个方法属于图形版的main方法
* 自动调用 */
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// 填充背景颜色
this.setBackground(new Color(135,206,235));
//画头部的图片
/* paintIcon对应的4个参数:
* this:指当前参数
* g:指使用的画笔
* x,y指坐标*/
Images.headerImg.paintIcon(this,g,8,10);
//画一个矩形
//和我们画图一样,都是先调节颜色,在画图。
g.setColor(new Color(225,255,255));
g.fillRect(10, 70, 767, 685);
//画小蛇
//画蛇头
Images.upImg.paintIcon(this, g, snakeX[0], snakeY[0]);
/*
* //画第一节身子 Images.bodyImg.paintIcon(this, g, snakeX[1], snakeY[1]); //画第二节身子
* Images.bodyImg.paintIcon(this, g, snakeX[2], snakeY[2]);
*/
//优化为画蛇的身子
for(int i=1;i<length;i++){
Images.bodyImg.paintIcon(this, g, snakeX[i], snakeY[i]);
//画小蛇
//画蛇头
if("R".equals(direction)) {
Images.rightImg.paintIcon(this, g, snakeX[0], snakeY[0]);
}
if("L".equals(direction)) {
Images.leftImg.paintIcon(this, g, snakeX[0], snakeY[0]);
}
if("U".equals(direction)) {
Images.upImg.paintIcon(this, g, snakeX[0], snakeY[0]);
}
if("D".equals(direction)) {
Images.downImg.paintIcon(this, g, snakeX[0], snakeY[0]);
}
if(isStart==false) {
g.setColor(new Color(114,98,255));
//参数:字体,加粗,字号
g.setFont(new Font("微软雅黑",Font.BOLD,40));
//画文字
g.drawString("点击空格开始游戏", 250, 330);
}
//画食物
Images.foodImg.paintIcon(this, g, foodX, foodY);
//画积分
g.setColor(new Color(255,248,248));
g.setFont(new Font("微软雅黑",Font.BOLD,20));
g.drawString("积分:"+score, 620, 40);
//输入死亡内容
if(isDie) {
g.setColor(new Color(255,82,68));
g.setFont(new Font("微软雅黑",Font.BOLD,20));
g.drawString("小蛇死亡,游戏停止,按下空格继续游戏!", 200, 330);
}
}
}}