用Java做一个接月饼小游戏

1,618 阅读3分钟

我正在参加中秋创意投稿大赛,详情请看:中秋创意投稿大赛

前言

当我看到中秋创意投稿大赛的时候,我一开始的想法就是做个中秋相关的小游戏。经过我的冥思苦想,最终确立了游戏的内容是接月饼。

跟我一起看一下,我是如何实现这个接月饼小游戏的吧!

tips:以下代码均已在Github上开源:Java接月饼游戏

一、游戏内容

接月饼小游戏的内容主要分为以下两个部分:

  • 场景和物体
  • 具体玩法

场景和物体

接月饼设定在一个星空中,所以背景就是一张星空的图片,如下所示:

image.png

游戏中的物体有 嫦娥月亮月饼三种,图片如下所示:

1631696447(1).jpg

a9ax7-0pxgo.png

aen8l-5mq63.png

游戏整体的效果如下所示:

image.png

具体玩法

嫦娥:作为游戏中的角色,供玩家来移动

月亮:游戏中的障碍物,如果嫦娥在移动的过程中碰到了月亮,则游戏停止

月饼:游戏中的得分道具,如果嫦娥在移动的过程中碰到了月饼,则分数 +1

玩家可以操控嫦娥来吃月饼,直到碰到了月亮,游戏结束并提示中秋快乐提示语和吃到的月饼个数

试玩动图

试玩效果的动图如下所示:

动画.gif

二、实现思路

理论上讲这个想法做一个 H5 小游戏是非常好的,还可以在线试玩。但是考虑到不会利用 JSCSS 来制作动画效果,故此方案弃用。

经过一番思考,我想到了 Java 中可以使用 Swing 来进行图形绘制,那么实现动画效果也并非难事了。故最终选择了 Swing 来实现这个小游戏。

实现的大致思路分为以下几个部分:

  • 嫦娥 可以看做一个方块,随着方向键 而移动
  • 月亮月饼 都可以看做一个圆,从上向下移动,即从 y = 0 移动到 y = Height
  • 嫦娥 碰到 月亮 时游戏结束,当 嫦娥 碰到 月饼 时分数 +1

代码实现

  1. Moon 月亮类
    /**
     * 障碍物-月亮,碰到会死亡
     */
    public class Moon extends BaseGameObj {
        private int speed = 10;
    
        public Moon(int x, int y, String imageFile) {
            super(x, y, imageFile, BaseGameObj.CIRCLE);
        }
    
    
        public void move() {
            setY(y += speed);
        }
    
    
        // getter and setter
        public int getSpeed() {
            return speed;
        }
    
        public void setSpeed(int speed) {
            this.speed = speed;
        }
    }
  1. Cake 月饼类
    /**
     * 得分物体-月饼,碰到加一分
     */
    public class Cake extends BaseGameObj {
    
        private int speed = 5; // 月饼跑慢一点,利于得分
    
        public Cake(int x, int y, String imageFile) {
            super(x, y, imageFile, CIRCLE);
        }
    
        public void move() {
            ++speed;
            setY(y += speed);
        }
    
        // getter and setter
        public int getSpeed() {
            return speed;
        }
    }
  1. ChangE 嫦娥类
    public class ChangeE extends BaseGameObj {
        private final int frameWith;
    
        public ChangeE(int x, int y, String imageFile, int frameWith) {
            super(x, y, imageFile, BaseGameObj.RECTANGLE);
            this.frameWith = frameWith;
        }
    
        public void move(int deltaX)
        {
            // 判断是否会超出左右边界
            int nextX = getX() + deltaX;
            if (nextX + getWidth() > frameWith) {
                nextX = frameWith - getWidth();
            } else if (nextX < 0) {
                nextX = 0;
            }
            setX(nextX);
        }
    }
  1. JPanel 面板中绘制图像的主要代码
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        // 绘制背景
        ImageIcon icon=new ImageIcon(Thread.currentThread().getContextClassLoader().getResource("background.png"));
        Image img=icon.getImage();
        g.drawImage(img, 0, 0, this.getWidth(), this.getHeight(), this);
        // 绘制玩家
        g.drawImage(myChangeE.getImage(), myChangeE.getX(), myChangeE.getY(), this);
        // 绘制月亮
        for(Moon moon : moons) {
            g.drawImage(moon.getImage(), moon.getX(), moon.getY(), this);
        }
        // 绘制月饼
        for (Cake cake : cakes) {
            g.drawImage(cake.getImage(), cake.getX(), cake.getY(), this);
        }
        
    }
  1. 游戏逻辑的主要代码

当月亮移动到了屏幕外,则移除该月亮
当月饼移动到了屏幕外,则移除该月饼
如果列表为空则再添加两个月亮和一个月饼

    /**
     * 更新窗口
     */
    private void updateFrame() {
        ticks++;
        for(int i = 0; i < moons.size(); i++)
        {
            Moon moon = moons.get(i);
            if(ticks % 25 == 0 && moon.getSpeed() < 10)
            {
                moon.setSpeed(moon.getSpeed() + 2);
            }
        }
        Iterator<Moon> moonIterator = moons.iterator();
        while (moonIterator.hasNext()) {
            Moon moon = moonIterator.next();
            // 超出屏幕
            if(moon.getY() > HEIGHT) {
                moonIterator.remove();
            } else
                moon.move();
        }
        Iterator<Cake> cakeIterator = cakes.iterator();
        while (cakeIterator.hasNext()) {
            Cake cake = cakeIterator.next();
            // 超出屏幕
            if(cake.getY() > HEIGHT) {
                cakeIterator.remove();
            } else
                cake.move();
        }
        if(moons.size() == 0) {
            addMoonAndCake();
        }
    }

判断嫦娥是碰到了月亮,如果碰到了月亮,则游戏结束并提示中秋快乐!
判断嫦娥是碰到了月饼,如果碰到了则让分数 +1,并移除该月饼。

    private boolean checkCollision() {
        Rectangle rectangle = (Rectangle) changeE.getShape();
        for(Moon moon : moons) {
            Ellipse2D circle = (Ellipse2D) moon.getShape();
            // 判断是否与圆形相撞
            if (circle.intersects(rectangle)) {
                gameOver = true;
            }
        }
        Iterator<Cake> cakeIterator = cakes.iterator();
        while (cakeIterator.hasNext()) {
            Cake cake = cakeIterator.next();
            Ellipse2D circle = (Ellipse2D) cake.getShape();
            if (circle.intersects(rectangle)) {
                score ++;   // 得分
                cakeIterator.remove();
            }
        }
        return gameOver;
    }

三、总结

其实这个游戏更多的是提供了一种想法,可完善的地方还有很多。

感谢你可以看到这里,非常荣幸能够帮助到你!❤