当前位置:   article > 正文

java实现贪吃蛇小游戏_java贪吃蛇小游戏代码

java贪吃蛇小游戏代码

java实现贪吃蛇小游戏

写个小游戏练习一下。

思路

蛇头、蛇身、食物位置都是一个在背景图片上的点(坐标),再根据这个点去绘制图片;
共设计了包括测试类在内的6个类:
1、ImageUtil类: 加载所有图片,作为静态属性,通过类名直接调用;
2、DrawImage类:绘制类,绘制游戏中所有的东西;
3、Snake类:蛇类,控制蛇的移动,吃食物,判断游戏是否结束;
4、Food类:随机产生食物,食物被吃产生新的食物;
5、Listener类:监听类,时间监听,键盘监听;
6、Demo类:测试类。

遇到的问题

1、绘制图片时闪烁;解决办法:双重缓冲绘制。
2、蛇移动后如何正确绘制蛇头蛇身位置(即重新设置坐标);我的解决办法较简单:根据背景图片大小、蛇头、蛇身大小去初始化蛇头蛇身的坐标,并设置蛇每次移动的距离为蛇身大小。(可以进行优化)
3、如何确保食物可以被吃;解决办法:根据背景图片、蛇头、蛇身大小和蛇移动的距离去设置食物可以出现的坐标;食物必须出现在蛇头可以经过的坐标。(可以进行优化)
4、蛇移动速度快,待优化。

像素:960 x 640
在这里插入图片描述

像素:32 x 32
在这里插入图片描述
像素:32 x 32
在这里插入图片描述
像素:32 x 41
在这里插入图片描述

/*
 960/32 = 30;
 640/32 = 20;
 初始化蛇头蛇身
 snakeHead = new Point(160,160);
 linkedList.add(new Point(128,160));
 linkedList.add(new Point(96,160));
 蛇移动距离为32
 食物产生位置
 foodP.x = random.nextInt(30) * 32;//x:大于等于0小于等于29的随机数再乘32
 foodP.y = (random.nextInt(19) + 1) * 32;//y:大于等于1小于等于19的随机数再乘32
*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

源代码

package mySnake;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

//照片资源类
public class ImageUtil {
    public static BufferedImage background;
    public static BufferedImage food;
    public static BufferedImage snake_headR;
    public static BufferedImage snake_headL;
    public static BufferedImage snake_headU;
    public static BufferedImage snake_headD;
    public static BufferedImage snake_body;
    public static BufferedImage fail;
    public static BufferedImage iconImage;

    static {
        try {
            background = ImageIO.read(new File("src\\image\\背景.png"));//读取照片
            food = ImageIO.read(new File("src\\image\\food.png"));
            snake_headR = ImageIO.read(new File("src\\image\\蛇头-右.png"));
            snake_headL = ImageIO.read(new File("src\\image\\蛇头-左.png"));
            snake_headU = ImageIO.read(new File("src\\image\\蛇头-上.png"));
            snake_headD = ImageIO.read(new File("src\\image\\蛇头-下.png"));
            snake_body = ImageIO.read(new File("src\\image\\蛇身.png"));
            fail = ImageIO.read(new File("src\\image\\fail.png"));
            iconImage = ImageIO.read(new File("src\\image\\图标.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
package mySnake;

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.LinkedList;

//绘制所有图片的界面类
public class DrawImage extends JFrame{
    //蛇
    private Snake snake = new Snake();
    //蛇头坐标
    private Point snakeP;
    //蛇身
    private LinkedList linkedList;
    //食物
    private Food food = new Food();
    private Point foodP = new Point();
    //时间计时
    private Timer timer;
    //蛇头照片
    private BufferedImage snake_head = ImageUtil.snake_headR;//初始向右
    //监听器类的对象
    Listener listener = new Listener(this,snake,food);

    //组装
    public DrawImage(){
        super("贪吃蛇");
        //时间计时
        timer = new Timer(200,listener.getActionListener());
        timer.start();
        //注册键盘监听器
        addKeyListener(listener.getKeyListener());
        //设置窗体图标
        setIconImage(ImageUtil.iconImage);

        //设置窗体
        setSize(ImageUtil.background.getWidth(),ImageUtil.background.getHeight() );
        setLocationRelativeTo(null);
        setResizable(false);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    //双重缓冲解决图片闪烁
    //进行绘制
    @Override
    public void paint(Graphics g) {
        Image image =  this.createImage(ImageUtil.background.getWidth(), ImageUtil.background.getHeight());
        Graphics gImage = image.getGraphics();
        gImage.setColor(gImage.getColor());
        gImage.fillRect(0,0,ImageUtil.background.getWidth(),ImageUtil.background.getHeight() );
        super.paint(gImage);
        //绘制背景
        gImage.drawImage(ImageUtil.background,0 ,0 ,null );
        //判断游戏是否结束
        if(!snake.isOver()) {
            //游戏继续
            snakeP = snake.getSnakeHead();//蛇头坐标
            linkedList = snake.getLinkedList();//蛇身
            foodP = food.getFoodP();//食物坐标
            //绘制食物
            gImage.drawImage(ImageUtil.food, foodP.x, foodP.y, null);
            //绘制蛇头
            gImage.drawImage(snake_head, snakeP.x, snakeP.y, null);
            //绘制蛇身
            for (int i = 0; i < linkedList.size(); i++) {
                Point p = (Point) linkedList.get(i);
                gImage.drawImage(ImageUtil.snake_body, p.x, p.y, null);
            }
        }
        else{
            //游戏结束
            //绘制结束图片
            gImage.drawImage(ImageUtil.fail, 250, 200,null );
            //时间计时结束
            timer.stop();
        }
        //最后绘制缓冲后的图片
        g.drawImage(image,0 ,0 , null);
    }

    //改变绘制蛇头的图片
    public void setSnake_head(BufferedImage image){
        snake_head = image;
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
package mySnake;

import java.awt.*;
import java.util.LinkedList;

//蛇类
public class Snake {
    //蛇头位置用点表示
    private Point snakeHead;
    //蛇身用LinkedList进行储存
    private LinkedList<Point> linkedList = new LinkedList<>();
    //蛇头移动速度
    private int speed_x = 32;
    private int speed_y = 0;
    //蛇是否死亡
    private boolean isOver = false;
    //蛇移动方向
    //蛇头走向 1:右  -1:左  2:上  -2:下
    private int direction = 1;//默认向右
    //记录蛇最后一节身体坐标,吃到食物时添加
    private Point p = new Point();

    public Snake(){
        //初始化蛇头蛇身
        snakeHead = new Point(160,160);
        linkedList.add(new Point(128,160));
        linkedList.add(new Point(96,160));
    }
    //返回游戏是否继续
    public boolean isOver() {
        return isOver;
    }
    //返回蛇身
    public LinkedList<Point> getLinkedList() {
        return linkedList;
    }
    //返回蛇头坐标
    public Point getSnakeHead() {
        return snakeHead;
    }
    //返回蛇头移动方向
    public int getDirection(){
        return direction;
    }
    //改变蛇移动的x方向速度
    public void setSpeed_x(int speed_x) {
        this.speed_x = speed_x;
    }
    //改变蛇移动的y方向速度
    public void setSpeed_y(int speed_y) {
        this.speed_y = speed_y;
    }
    //改变蛇头移动方向
    public void setDirection(int direction) {
        this.direction = direction;
    }

    //蛇移动
    public void move(){
        //蛇身移动,在linkedList第一个添加蛇身坐标就是蛇头坐标,然后删除最后一个蛇身坐标,返回的坐标为蛇吃到食物时添加的坐标
        linkedList.addFirst(new Point(snakeHead.x,snakeHead.y));
        p = linkedList.pollLast();
        //蛇头移动
        snakeHead.move(snakeHead.x + speed_x, snakeHead.y + speed_y);
        //判断是否出界和碰到自身
        setIsOver();
        isEatOneself();
    }
    //边界问题
    //蛇头是否出界
    private void setIsOver(){
        int x = snakeHead.x;
        int y = snakeHead.y;
        if(x < 0 || y < 32)
            isOver = true;
        else if(x > (ImageUtil.background.getWidth() - 32) || y > (ImageUtil.background.getHeight() - 32))
            isOver = true;
    }
    //判断蛇头是否碰到蛇身
    private void isEatOneself(){
        //循环判断
        for(int i = 0;i < linkedList.size();i ++){
            if(snakeHead.equals(linkedList.get(i))){
                isOver = true;
                break;
            }
        }
    }
    //吃食物
    public void eatFood(Food food){
        //判断依据:蛇移动方向上蛇头与食物是否在一条线上,若在再根据之间的距离判断是否相碰
        if((direction == 1 || direction == -1) && (snakeHead.y == food.getFoodP().y)){
            if(Math.abs(snakeHead.x - food.getFoodP().x) <= 32 ){
                food.isEat();
                linkedList.addLast(p);
            }
        }
        if((direction == 2 || direction == -2) && (snakeHead.x == food.getFoodP().x)){
            if(Math.abs(snakeHead.y - food.getFoodP().y) <= 32){
                food.isEat();
                linkedList.addLast(p);
            }
        }
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
package mySnake;

import java.awt.*;
import java.util.Random;

//食物类
public class Food {
    //产生随机数对象
    Random random = new Random();
    //食物坐标
    private Point foodP = new Point();
    //代码块初始化食物
    {
        setFoodP();
    }
    //随机产生食物
    private void setFoodP(){
        foodP.x = random.nextInt(30) * 32;
        foodP.y = (random.nextInt(19) + 1) * 32;
    }
    //食物被吃
    public void isEat(){
        //重新生产食物
        setFoodP();
    }
    //返回食物坐标
    public Point getFoodP() {
        return foodP;
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
package mySnake;

import java.awt.event.*;

//外部监听类
public class Listener {
    private Snake snake;
    private Food food;
    private DrawImage drawImage;

    public Listener(DrawImage drawImage,Snake snake,Food food){
        this.drawImage = drawImage;
        this.snake = snake;
        this.food = food;
    }

    //返回ActionListener
    public ActionListener getActionListener() {
        return actionListener;
    }

    //返回KeyListener
    public KeyListener getKeyListener() {
        return keyListener;
    }

    private ActionListener actionListener = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            snake.move();
            snake.eatFood(food);
            drawImage.repaint();
        }
    };

    //键盘监听器
    private KeyListener keyListener = new KeyAdapter() {
        @Override
        public void keyPressed(KeyEvent e) {
            //获取按键对应的值
            int keyCode = e.getKeyCode();
            //获取蛇移动方向
            int direction = snake.getDirection();
            //蛇头走向 1:右  -1:左  2:上  -2:下
            //按下左键且蛇不向右走时
            if(keyCode == KeyEvent.VK_LEFT && direction != 1){
                //改变蛇移动方向
                snake.setDirection(-1);
                //改变速度
                snake.setSpeed_x(-32);
                snake.setSpeed_y(0);
                //蛇移动
                snake.move();
                //每次移动后让蛇吃食物
                snake.eatFood(food);
                //改变蛇头图片
                drawImage.setSnake_head(ImageUtil.snake_headL);
            }
            //右
            if(keyCode == KeyEvent.VK_RIGHT && direction != -1){
                snake.setDirection(1);
                snake.setSpeed_x(32);
                snake.setSpeed_y(0);
                snake.move();
                snake.eatFood(food);
                drawImage.setSnake_head(ImageUtil.snake_headR);
            }
            //上
            if(keyCode == KeyEvent.VK_UP && direction != -2){
                snake.setDirection(2);
                snake.setSpeed_x(0);
                snake.setSpeed_y(-32);
                snake.move();
                snake.eatFood(food);
                drawImage.setSnake_head(ImageUtil.snake_headU);
            }
            //下
            if(keyCode == KeyEvent.VK_DOWN && direction != 2){
                snake.setDirection(-2);
                snake.setSpeed_x(0);
                snake.setSpeed_y(32);
                snake.move();
                snake.eatFood(food);
                drawImage.setSnake_head(ImageUtil.snake_headD);
            }
        }
    };
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
package mySnake;

//测试类
public class Demo {
    public static void main(String[] args) {
        new DrawImage();
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

效果图

游戏界面
在这里插入图片描述
游戏结束界面
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/699462
推荐阅读
相关标签
  

闽ICP备14008679号