小游戏——贪吃蛇案例

一、案例目的 

1、实现贪吃蛇游戏基本功能,屏幕上随机出现一个“食物”,称为豆子,上下左右控制“蛇”的移动,吃到“豆子”以后“蛇”的身体加长一点。

2、“蛇”碰到边界或蛇头与蛇身相撞,蛇死亡,游戏结束。

3、为游戏设计友好的交互界面;例如欢迎界面,游戏界面,游戏结束界面。要有开始键、暂停键和停止退出的选项。

4、对蛇吃到豆子进行分值计算,可以设置游戏速度,游戏音乐等拓展元素。

二、案例1、一张地图,四周有墙体。 

2、一条蛇,由蛇身和蛇头组成。 
3、食物,蛇吃到食物后身体变长,并且重新生成一个食物。 
4、蛇需要移动,这是难实现的一个部分。 
5、蛇撞到墙或者自己的身体就会死亡

6、需要能用键盘控制蛇的运动方向。

1、新建一个贪吃蛇项目,在此项目下面新建两个包,一个包存放代码,另一个包存放素材图片。

2、先用Java代码的swing框架绘制出游戏界面。

3、再在游戏界面上,绘制出游戏区域,并把两块区域调好配色。

4、找绘制蛇头、蛇身以及食物的素材,导入到素材图片的包里面,方便后面的调用。

5、利用循环语句,控制蛇身体的增长。

6、设置键盘监听,可以用键盘控制开始以及蛇上下左右的移动。

7、设置限制条件,蛇碰到自己身体和墙就会死。

8、设置计分程序。

StartGame类代码:

package li.fox;
import javax.swing.*;
 
public class StartGames {
    public static void main(String[] args){
        JFrame frame  = new JFrame("李飒宇-贪吃小狐狸");       //绘制一个静态窗口
        frame.setBounds(10 , 10 , 900 , 720);   //设置界面大小
        frame.setResizable(false);              //窗口大小不可以改变
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    //设置关闭事件,使得游戏可以关闭
 
        frame.add(new GamePanel());  //游戏界面
 
        frame.setVisible(true);    //让窗口可以显示出来
    }
}

GamePanel类代码:

package li.fox;
 
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Objects;
import java.util.Random;
 
public class GamePanel extends JPanel implements KeyListener, ActionListener {
 
    int length;    //狐狸的长度
    int[] foxX = new int[600];    //狐狸的X坐标
    int[] foxY = new int[500];    //狐狸的Y坐标
    String direction = "R";
    boolean isStart = false;    //游戏是否开始
    Timer timer = new Timer(170, this);   //定时器:第一个参数,就是定时执行时间
    int foodx;    //定义食物的坐标
    int foody;
    Random random = new Random();
    boolean isFail = false;     //游戏是否结束
    int score;    //游戏分数
 
    //构造器
    public GamePanel() {
        init();
        this.setFocusable(true);     //获取焦点事件
        this.addKeyListener(this);    //键盘监听事件
        timer.start();
    }
 
    //初始化
    public void init() {
        length = 3;
        foxX[0] = 100;
        foxY[0] = 100;   //头部坐标
        foxX[1] = 75;
        foxY[1] = 100;    //第一节身体坐标
        foxX[2] = 50;
        foxY[2] = 100;    //第二节身体坐标
        foodx = 25 + 25 * random.nextInt(34);   //初始化食物数据
        foody = 25 + 25 * random.nextInt(25);
        score = 0;   //初始化游戏分数
    }
 
    @Override
    protected void paintComponent(Graphics g) {    //Graphics :画笔
        super.paintComponent(g);    //清屏
        this.setBackground(Color.white);   //设置背景的颜色
        g.fillRect(18, 25, 850, 625);  //绘制游戏区域
        this.setForeground(Color.DARK_GRAY);
        //绘制狐狸的头
        if (direction.equals("R")) {
            Data.right.paintIcon(this, g, foxX[0], foxY[0]);
        } else if (direction.equals("L")) {
            Data.left.paintIcon(this, g, foxX[0], foxY[0]);
        } else if (direction.equals("U")) {
            Data.up.paintIcon(this, g, foxX[0], foxY[0]);
        } else if (direction.equals("D")) {
            Data.down.paintIcon(this, g, foxX[0], foxY[0]);
        }
        for (int i = 1; i < length; i++) {         //狐狸的身体长度通过length来控制
            Data.body.paintIcon(this, g, foxX[i], foxY[i]);
        }
        //画食物
        Data.food.paintIcon(this, g, foodx, foody);
        g.setColor(Color.red);
        g.setFont(new Font("微软雅黑", Font.BOLD, 18));
        g.drawString("长度" + length, 750, 18);
        g.drawString("分数" + score, 650, 18);
        //游戏提示
        if (isStart == false) {
            g.setColor(Color.white);     //设置画笔的颜色
            g.setFont(new Font("微软雅黑", Font.BOLD, 40));   //设置字体
            g.drawString("按下空格键开始游戏!", 265, 300);
        }
        //失败判断
        if (isFail) {
            g.setColor(Color.RED);
            g.setFont(new Font("微软雅黑", Font.BOLD, 40));
            g.drawString("失败, 按下空格重新开始!", 235, 300);
        }
    }
 
    @Override
    public void keyTyped(KeyEvent e) {    //键盘按下、弹起
    }
 
    //键盘监听事件
    @Override
    public void keyPressed(KeyEvent e) {    //键盘按下,未释放
        int keyCode = e.getKeyCode();      //获取按下的键盘是哪个键
        if (keyCode == KeyEvent.VK_SPACE) {     //如果是空格
            if (isFail) {      //如果游戏失败,从头再来!
                isFail = false;
                init();     //重新初始化
            }
            else {          //否则,暂停游戏
                isStart = !isStart;
            }
            repaint();   //重新刷新界面
        }
 
        //键盘控制走向
        if (keyCode == KeyEvent.VK_LEFT && !Objects.equals(direction, "R")) {
            direction = "L";
        } else if (keyCode == KeyEvent.VK_RIGHT && !Objects.equals(direction, "L")) {
            direction = "R";
        } else if (keyCode == KeyEvent.VK_UP && !Objects.equals(direction, "D")) {
            direction = "U";
        } else if (keyCode == KeyEvent.VK_DOWN && !Objects.equals(direction, "U")) {
            direction = "D";
        }
 
    }
 
    @Override
    public void keyReleased(KeyEvent e) {    //键盘释放
    }
 
    //执行定时的操作
    @Override
    public void actionPerformed(ActionEvent e) {
        //如果游戏处于开始状态,并且没有结束,则小蛇可以移动
        if (isStart && isFail == false){
            //右移:即让后一个移到前一个的位置即可 !
            for (int i = length - 1; i > 0; i--) { //除了脑袋都往前移:身体移动
                foxX[i] = foxX[i-1]; //即第i节(后一节)的位置变为(i-1:前一节)节的位置!
                foxY[i] = foxY[i-1];
            }
            //通过方向控制,头部移动
            if (direction.equals("R")){
                foxX[0] = foxX[0] + 25;
                if (foxX[0] >= 850) { isFail = true; }
            }
            else if (direction.equals("L")){
                foxX[0] = foxX[0] - 25;
                if (foxX[0] <= 18) { isFail = true; }
            }
            else if (direction.equals("U")){
                foxY[0] = foxY[0] - 25;
                if (foxY[0] <= 25) { isFail = true; }
            }
            else if (direction.equals("D")){
                foxY[0] = foxY[0] + 25;
                if (foxY[0] >= 625) { isFail = true; }
            }
 
            //吃食物:当蛇的头和食物一样时,算吃到食物!
            if (foxX[0] == foodx && foxY[0] == foody){
                //长度加一
                length++;
                //每吃一个食物,增加积分
                score = score + 10;
                //2.重新生成食物
                foodx = 25 + 25 * random.nextInt(34);
                foody = 25 + 25 * random.nextInt(25);
            }
 
            //结束判断,头和身体撞到了
            for (int i = 1; i < length; i++) {
                //如果头和身体碰撞,那就说明游戏失败
                if (foxX[i] == foxX[0] && foxY[i] == foxY[0] ){
                    isFail = true;
                }
            }
            repaint(); //需要不断的更新页面实现动画
        }
        timer.start();//让时间动起来!
    }
}

Data类代码:

package li.fox;
 
import javax.swing.*;
import java.net.URL;
 
public class Data {
    public static URL upurl = Data.class.getResource("/statics/up.png");    //头部(向上)定位图片的地址
    public static ImageIcon up = new ImageIcon(upurl);
 
    public static URL downurl = Data.class.getResource("/statics/down.png");    //头部(向下)定位图片的地址
    public static ImageIcon down = new ImageIcon(downurl);
 
    public static URL lefturl = Data.class.getResource("/statics/left.png");    //头部(向左)定位图片的地址
    public static ImageIcon left = new ImageIcon(lefturl);
 
    public static URL righturl = Data.class.getResource("/statics/right.png");    //头部(向右)定位图片的地址
    public static ImageIcon right = new ImageIcon(righturl);
 
    public static URL bodyurl = Data.class.getResource("/statics/body.png");    //身体定位图片的地址
    public static ImageIcon body = new ImageIcon(bodyurl);
 
    public static URL foodurl = Data.class.getResource("/statics/food.png");    //头部(向右)定位图片的地址
    public static ImageIcon food = new ImageIcon(foodurl);
 
}

 

posted @ 2023-06-30 12:48  growflowers  阅读(211)  评论(0编辑  收藏  举报