JavaGUI简易版贪吃蛇小游戏

Posted 一切随缘~~~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaGUI简易版贪吃蛇小游戏相关的知识,希望对你有一定的参考价值。

做这个小游戏,主要是学习一下游戏制作的基本逻辑,加深对面向对象的理解。

游戏引擎:

/**
 * 大牛程序员写的游戏的公共类 
 * 使用Game.init()方法初始化游戏
 * 使用Game.gameOver()方法退出游戏
 */
public class Game extends JPanel 
    private GameEngine engine;
    private Graphics2D g2d;
    private static JFrame frame;
   
    @Override
    public void paint(Graphics g) 
        super.paint(g);
        g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        engine.renderUI(g2d);
    

    /**
     * 使用游戏引擎初始化游戏的方法
     * @param title 游戏窗体的标题
     * @param width 游戏窗体的宽度
     * @param height 游戏窗体的高度
     * @param engine 游戏引擎
     */
    public static void init(String title, int width, int height, GameEngine engine)
        frame = new JFrame(title);
        Game game = new Game();
        game.engine = engine;
        game.addKeyListener(engine.listener);
        game.setFocusable(true);
        game.setPreferredSize(new Dimension(width, height));
        frame.add(game);
        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        while (true) 
            engine.updateLogic();
            game.repaint();
            try 
                Thread.sleep(Config.SLEEP_TIME);
             catch (InterruptedException e) 
                e.printStackTrace();
            
        
    

    /**
     * 显示退出游戏对话框的方法
     * @param message 对话框提示的消息
     * @param title 对话框提示的标题
     */
    public static void gameOver(String message,String title) 
        JOptionPane.showMessageDialog(frame, message, title, JOptionPane.YES_NO_OPTION);
        System.exit(ABORT);
    

/**
 * 由大牛程序员编写的游戏引擎的抽象模板类
 * 需要调用者实现两个抽象方法, 更新逻辑方法updateLogic
 * 更新UI方法 renderUI
 */
public abstract class GameEngine 
    KeyListener listener;
    private int currentPressedKeyCode;

    /**
     * 构造方法,创建出游戏引擎
     */
    public  GameEngine()
        this.listener = new KeyListener() 
            @Override
            public void keyTyped(KeyEvent e) 
            

            @Override
            public void keyPressed(KeyEvent e) 
                currentPressedKeyCode = e.getKeyCode();
            

            @Override
            public void keyReleased(KeyEvent e) 
                currentPressedKeyCode = -1;
            
        ;
    

    /**
     * 获取当前用户的按键代码 按键代码的定义在KeyEvent对象中定义
     * @return 返回KeyEvent的按键代码
     */
    public int getCurrentPressedKeyCode()
        return  currentPressedKeyCode;
    

    /**
     * 根据用户行为或者游戏的时间更新游戏的逻辑
     */
    public abstract void updateLogic();

    /**
     * 根据用户需求更新绘制图形化界面的内容
     * 示例代码,绘制矩形:    g2d.fillRect(左上角x的坐标, 左上角y的坐标, 矩形的宽度, 矩形的高度);
     * 示例代码:绘制椭圆形:  g2d.fillOval(椭圆外包裹矩形左上角x的坐标, 椭圆外包裹矩形y的坐标, 要填充椭圆形的宽度, 要填充椭圆形的高度);
     * @param g2d
     */
    public abstract void renderUI(Graphics2D g2d);

分析过程:

其实游戏就是逻辑判断,页面更新的死循环。

我们要做的就是继承GameEngine,实现updateLogic,renderUI方法。

一开始我们可以画上网格线,方便程序的编写。等到完成之后,将网格线去除即可。

面向对象思想(指的是程序的最小单位是对象。对象之间彼此协调,相互调用,构成了程序):

我们需要什么,我们就创建什么类:我们需要一个蛇,于是创建了一个Snake类,然后蛇又是由一个个的节点组成,于是我们又创建了Node类,以此类推,我们又创建了Apple类…

贪吃蛇的具体实现代码:

public class SnakeGameEngine extends GameEngine 
    Grid grid = new Grid();
    Snake snake = new Snake();
    Apple apple = new Apple();

    @Override
    public void updateLogic() 
        boolean flag = snake.headHaveApple(apple);
        int keyCode = getCurrentPressedKeyCode();
        if (keyCode == KeyEvent.VK_RIGHT) 
            snake.moveRight(flag);
        
        if (keyCode == KeyEvent.VK_LEFT) 
            snake.moveLeft(flag);
        
        if (keyCode == KeyEvent.VK_UP) 
            snake.moveUp(flag);
        
        if (keyCode == KeyEvent.VK_DOWN) 
            snake.moveDown(flag);
        

        switch(snake.headDirection) 
            case Direction.RIGHT:
                snake.moveRight(flag);
                break;
            case Direction.LEFT:
                snake.moveLeft(flag);
                break;
            case Direction.UP:
                snake.moveUp(flag);
                break;
            case Direction.DOWN:
                snake.moveDown(flag);
                break;
        
    

    @Override
    public void renderUI(Graphics2D g2d) 
        grid.draw(g2d);
        snake.draw(g2d);
        apple.draw(g2d);
    

public class SnakeGame 
    public static void main(String[] args) 
        Game.init("贪吃蛇", Config.SCREEN_WIDTH, Config.SCREEN_HEIGHT, new SnakeGameEngine());
    

public class Snake 
    LinkedList<Node> snake;
    int headDirection = Direction.RIGHT;

    public Snake() 
        snake = new LinkedList<Node>();
        snake.add(new Node(6, 4));
        snake.addLast(new Node(5, 4));
        snake.addLast(new Node(4, 4));
        snake.addLast(new Node(3, 4));
    

    public void moveRight(boolean flag) 
        if (headDirection == Direction.LEFT) 
            return;
        
        headDirection = Direction.RIGHT;

        Node node = new Node(snake.getFirst().x + 1, snake.getFirst().y);
        snake.addFirst(node);
        if (flag == true) 

         else 
            snake.removeLast();
        
    

    public void moveLeft(boolean flag) 
        if (headDirection == Direction.RIGHT) 
            return;
        
        headDirection = Direction.LEFT;

        Node node = new Node(snake.getFirst().x - 1, snake.getFirst().y);
        snake.addFirst(node);
        if (flag == true) 

         else 
            snake.removeLast();
        
    

    public void moveUp(boolean flag) 
        if (headDirection == Direction.DOWN) 
            return;
        
        headDirection = Direction.UP;

        Node node = new Node(snake.getFirst().x, snake.getFirst().y - 1);
        snake.addFirst(node);
        if (flag == true) 

         else 
            snake.removeLast();
        
    

    public void moveDown(boolean flag) 
        if (headDirection == Direction.UP) 
            return;
        
        headDirection = Direction.DOWN;

        Node node = new Node(snake.getFirst().x, snake.getFirst().y + 1);
        snake.addFirst(node);
        if (flag == true) 

         else 
            snake.removeLast();
        
    

    public boolean headHaveApple(Apple apple) 
        if ((snake.getFirst().x == apple.getX()) && (snake.getFirst().y == apple.getY())) 
            apple.generateNext();
            return true;
         else 
            return false;
        
    


    public void draw(Graphics2D g2d) 
//        for (Node node : snake) 
//            node.draw(g2d);
//        
        g2d.drawString("蛇的长度:" + snake.size(), 50, 50);
        for (int i = 0; i < snake.size(); i ++ ) 
            if (i == 0) 
                g2d.setColor(Color.GREEN);

             else 
                g2d.setColor(Color.BLACK);
            

            snake.get(i).draw(g2d);
        
    

public class Config 
    public static final boolean DEBUG_FLAG = false;
    public static final int SCREEN_WIDTH = 1000;
    public static final int SCREEN_HEIGHT = 900;
    public static final int GRID_SiZE = 20;
    public static final int COLOUM = SCREEN_WIDTH / GRID_SiZE;
    public static final int ROW = SCREEN_HEIGHT / GRID_SiZE;
    public static final int SLEEP_TIME = 50;

apublic class Grid 
    int x1;
    int y1;
    int x2;
    int y2;

    public void draw(Graphics2D g2d) 
        if (Config.DEBUG_FLAG == true) 
            for (int i = 0; i < Config.ROW; i ++ ) 
                g2d.drawLine(0, Config.GRID_SiZE * i, Config.SCREEN_WIDTH, 
                             Config.GRID_SiZE * i);
            
            for (int i = 0; i < Config.COLOUM; i ++ ) 
                g2d.drawLine(Config.GRID_SiZE * i, 0, Config.GRID_SiZE * i,
                             Config.SCREEN_HEIGHT);
            
        
    

public class Node 
    int x;
    int y;

    public Node(int x, int y) 
        this.x = x;
        this.y = y;
    

    public void draw(Graphics2D g2d) 
        g2d.fillRect(x * Config.GRID_SiZE, y * Config.GRID_SiZE, Config.GRID_SiZE,
                     Config.GRID_SiZE);
    

public class Direction 
    public static final int UP = 1;
    public static final int DOWN = 2;
    public static final int LEFT = 3;
    public static final int RIGHT = 4;

public class Apple 
    Random random = new Random();
    Node apple;

    public Apple() 
        apple = new Node(random.nextInt(Config.COLOUM), random.nextInt(Config.ROW));
    

    public int getX() 
        return apple.x;
    

    public int getY() 
        return apple.y;
    

    public void draw(Graphics2D g2d) 
        g2d.setColor(Color.RED);
        apple.draw(g2d);
        g2d.setColor(Color.BLACK);
    

    public void generateNext() 
        apple = new Node(random.nextInt(Config.COLOUM), random.nextInt(Config.ROW));
    

最终效果:

做的很简易,还有很多不足:

蛇不能超过屏幕的范围

地图添加障碍物

添加游戏关卡,蛇移动的速度越来越快

等等…

以上是关于JavaGUI简易版贪吃蛇小游戏的主要内容,如果未能解决你的问题,请参考以下文章

JS学习——贪吃蛇代码(简易版)

JS学习——贪吃蛇代码(简易版)

JS学习——贪吃蛇代码(简易版)

JavaGUI实现贪吃蛇

swing 简易贪吃蛇小游戏开发

React-Redux自制简易贪吃蛇小游戏