Java语言制作吃豆人游戏

(此项目源码已上传至Github网站,网址为GitHub - Ran-a/Pac-man-yar

1  游戏界面

      游戏的角色分别是追赶者和吃豆人,玩家使用方向键来控制吃豆人的运动方向并吃食物,将食物吃完视为通关。吃豆人共有五次机会,若被追赶者追到,则失去一次机会,若五次机会全部用完,食物还没有被吃完,则视为游戏失败。若吃豆人吃到特殊食物,那么吃豆人将在5秒内对追赶者免疫,即碰到追赶者不会消耗机会,5秒后恢复原来的状态。游戏运行界面如下图所示。


2  核心技术

2.1  判断人物改变方向之后是路还是墙
       在玩家按了方向键之后,判断人物在该方向的下一步是路还是墙,若是路,则人物运动方向改变为玩家所按方向键所指示的方向,若是墙,则按照原来的方向继续前进。以下是关键代码。

 public Boolean isPath(int x,int y){        
        if (x > rightBorder) {
            x=leftBorder;
        }else if (x < leftBorder) {
            x=rightBorder;
        }
        return myMap[y][x]>=pathNum;
    }

2.2  追赶者在地图路口处的可选择的上下左右方向中选择任意方向
       在阅读了GitHub网站的一位作者(Github账号为RookieStupidCat)写的吃豆人小游戏关于该功能的代码(网址为 https://github.com/RookieStupidCat/Pac_Man/blob/master/src/pac_Man/Enemy.java)之后,使用该作者的代码实现了本项目的此功能,并将该代码再次默写到项目中。以下是关键代码。

public void randomChangeDirect(){//用于随机改变enemy的运动方向
            if (GameFrame.old_myMap[this.y][this.x]==GameFrame.pointNum) {//判断是否为拐点
                if (rcd<rcdmin) {
                    rcd=rcd+everyRcd;
                }else{
                    if (xStep!=stopStep) {//横向移动时
                        if (xStep>stopStep) {//初始右向
                            if(GameFrame.old_myMap[this.y][this.x+everyStep]!=GameFrame.wallNum){//右边可通过
                                xStep=forwardStep-(int)(Math.random()*multiplyT)*multiplyT;//停止或继续走
                            }else xStep=stopStep;
                        }else if (xStep<stopStep) {//初始左向
                            if (GameFrame.old_myMap[this.y][this.x-everyStep]!=GameFrame.wallNum) {//左边可通过
                                xStep=backwardStep+(int)(Math.random()*multiplyT)*multiplyT;//停止或继续走
                            }else xStep=stopStep;
                        }
                        if (xStep == stopStep) {
                            if (GameFrame.old_myMap[this.y+everyStep][this.x]!=stopStep && GameFrame.old_myMap[this.y-everyStep][this.x]!=GameFrame.wallNum) {//此时上下都可通行
                                yStep=backwardStep+(int)(Math.random()*multiplyT)*multiplyF;//-2或2
                            }else if (GameFrame.old_myMap[this.y-everyStep][this.x]==GameFrame.wallNum) //不可上行则下行
                                yStep=forwardStep;
                            else yStep=backwardStep;//上行
                        }
                    }else if (yStep!=stopStep) {//纵向移动时
                        if (yStep>stopStep){//初始向下
                            if (GameFrame.old_myMap[this.y+everyStep][this.x]!=GameFrame.wallNum) {//下边可通过
                                yStep=forwardStep-(int)(Math.random()*multiplyT)*multiplyT;//停止或继续走
                            }else yStep=stopStep;
                        }else if (yStep<stopStep) {//初始向上
                                if (GameFrame.old_myMap[this.y-everyStep][this.x]!=GameFrame.wallNum) {//上边可通过
                                    yStep=backwardStep+(int)(Math.random()*multiplyT)*multiplyT;//停止或继续走
                                }else yStep=stopStep;
                            }
                        if (yStep == stopStep) {
                                if (GameFrame.old_myMap[this.y][this.x+everyStep]!=GameFrame.wallNum && GameFrame.old_myMap[this.y][this.x-everyStep]!=GameFrame.wallNum) {//可左可右
                                    xStep=backwardStep+(int)(Math.random()*multiplyT)*multiplyF;//-2或2
                                }else if (GameFrame.old_myMap[this.y][this.x+everyStep]==GameFrame.wallNum) //右边不通,则左行
                                    xStep=backwardStep;
                                else xStep=forwardStep;
                            }
                    }
                }
            }
    }

2.3  吃豆人与追赶者的碰撞判断
       为方便读者理解,下文所提到的“坐标互换”的情况如下图所示。


       在该游戏中,吃豆人和追赶者会出现坐标重合的情况,但也会出现吃豆人和追赶者坐标互换的情况。此时,虽然吃豆人和追赶者已经碰撞,但若碰撞检测条件仅仅是吃豆人和追赶者的坐标完全重合,那么会出现碰撞检测失灵的情况。在马洪博师兄的建议下,记录追赶者上一次运动的坐标,与这一次吃豆人的坐标进行对比,若两者发生互换,则符合碰撞检测的判断条件。以下是关键代码。

2.4  吃豆人吃特殊食物后一段时间内对追赶者免疫
       吃豆人在吃掉特殊食物后,吃豆人在5秒内对追赶者免疫,即在该时间段内,追赶者追上吃豆人后,吃豆人不会死亡。吃豆人碰到一次追赶者之后,免疫失效,若两者没有相撞,5秒后自动失效。以下是关键代码。

//是否吃到特殊食物
boolean isEatSpe=false;

//当吃到特殊食物时,吃豆人对追赶者免疫,追赶者图片变为免疫模式enemy_0.png。
if (GameFrame.myMap[this.frame.eater.y][this.frame.eater.x] == GameFrame.speNum) {
     img=Toolkit.getDefaultToolkit().getImage("image/enemy_immu.png");
     isEatSpe=true;
     //5秒后免疫失效,图片恢复之前的图片。
     new Timer().schedule(new TimerTask() {
         @Override
         public void run() {
             img=Toolkit.getDefaultToolkit().getImage("image/enemy.png");
             isEatSpe=false;
         }
     },immuTime);}
 move();
 //当吃豆人进入免疫模式时,碰到追赶者不会死亡,在碰到一次追赶者后,被碰到的追赶者免疫模式失效,图片也恢复为原来的图片。
 if (isEatSpe && frame.eater.x == frame.pursuer1.x && frame.eater.y == frame.pursuer1.y) {
     System.out.println("playing");
     this.frame.state="playing";
     move();
     img=Toolkit.getDefaultToolkit().getImage("image/enemy.png");
     isEatSpe=false;
 }


3  改进方向

3.1  代码习惯
        在项目编程中,应避免使用magic number;对已定义或即将定义的方法和变量应注释。

3.2  时间管理
       学习和编码的时间应刻意分开,以便清楚地记录项目时间;做项目过程中,若某一功能用时较长,更应该记录所用时间。

4  吃豆人游戏的WBS表格

       WBS是工作分解结构(Work Breakdown Structure)的缩写。创建WBS是把项目工作按阶段可交付成果分解成较小的,更易于管理的组成部分的过程。在吃豆人游戏开始编程之前,首先创建吃豆人游戏的WBS表格,设想要实现的功能以及估算预计完成时间,每完成一个功能之后,填写实际完成时间,与预计完成时间对比,提高以后做项目估算时间的精确度。以下是吃豆人游戏的WBS表格。

一级功能

二级功能

三级功能

预计完成时间

实际完成时间

人的移动

移动轨迹

将地图导入游戏面板

30min

23min

判断人物改变方向之后是路还是墙。若是路,则成功改变方向,若是墙,则按照原来的方向继续前进。

30min

139min

按照地图路径移动

20min

50min

移动方向

键盘控制移动方向

30min

76min

追赶者移动

移动轨迹

判断追赶者改变方向之后是路还是墙。若是路,则成功改变方向,若是墙,则按照原来的方向继续前进。

10min

15min

按照地图路径移动

10min

10min

移动方向

在地图路口处的可选择的上下左右方向中选择任意方向

30min

因花费时间太长,未记录

追赶者捉人

人与追赶者的碰撞判断

30min

25min

触发事件

游戏失败

30min

30min

食物生成

生成时间

游戏开始时生成

20min

38min

生成周期

只在游戏开始时生成一次,被吃后不会再次生成

20min

生成位置

普通食物-按照一定的距离在地图的“路”部分生成食物。

30min

特殊食物-游戏面板四个拐角处各一个

20min

12min

人吃食物

人与食物的碰撞判断

20min

33min

人吃特殊食物后一段时间内对追赶者免疫

30min

54min

分数统计

每吃一个普通食物加一分

20min

19min

每吃一个特殊食物加十分

20min

3min

通关判断

人将所有食物全部吃完则游戏胜利

30min

46min

生命消耗

吃豆人共五条性命,每失败一次就消耗一条性命。在五条性命都消耗完之前豆子吃完,则游戏成功。否则,游戏失败

显示剩余生命

15min

18min

生命消耗判定

15min

27min

新的生命开始后,吃豆人在上一条生命中所吃的豆不会再生。

20min

游戏失败判定

15min

19min


5  吃豆人PSP

       PSP是个人软件流程(Personal Software Process)的缩写。PSP是一个可用于控制、管理和改进个人工作方法的自我持续改进过程。在吃豆人游戏编程过程中,在开始某一个任务之前,记录开始时间以及对该任务的描述,若编程过程被其他事情打断,那么记录中断时间。完成该功能之后,记录结束时间。以下是作者在完成吃豆人游戏时的PSP表格。

分类开始时间结束时间中断时间/min(s)Δ/min(s)任务内容/描述
Preparing2022.11.23 10:482022.11.23 11:25532功能分解
Preparing2022.11.23 17:192022.11.23 17:39119分析技术难点以及确定开发先后次序
Preparing2022.11.23 17:432022.11.23 18:41553画WBS图以及WBS表格
Coding2022.11.25 20:162022.11.25 20:40123将地图导入游戏面板
Coding2022.11.25 20:422022.11.25 21:58476人移动以及键盘控制移动方向
Coding2022.11.27 17:052022.11.27 19:295139判断人物改变方向之后是路还是墙。
若是路,则成功改变方向,若是墙,则按照原来的方向继续前进。
Coding2022.11.27 19:312022.11.27 20:23250按照地图路径移动
Coding2022.11.28 10:162022.11.28 10:30014将用代码二进制作为元素的数组化成地图
Coding2022.11.29 20:412022.11.29 10:51010追赶者按照地图路径移动
Coding2022.11.29 20:522022.11.29 21:07015先用键盘触发事件控制追赶者,
判断追赶者改变方向后是路还是墙。
若是路,则成功改变方向,若是墙,
则按照原来的方向继续前进。
Coding2022.11.29 21:262022.11.29 21:53225在地图路口处的可选择的上下左右方
向中选择任意方向(未完成)
Coding2022.11.30 21:062022.11.30 22:17566在地图路口处的可选择的上下左右方
向中选择任意方向(未完成)
Coding2022.12.6  21:252022.12.6  22:16546在地图路口处的可选择的上下左右方
向中选择任意方向(有缺陷)
Coding2023.2.23  19:432023.2.23 20:06325吃豆人与追赶者的碰撞判断
Coding2023.2.23  20:082023.2.23 20:40230游戏失败
Coding2023.2.24  14:372023.2.24 15:20538普通食物按照一定的距离在地图的“路”部分生成
Coding2023.2.24  15:242023.2.24 17:02533人与食物的碰撞判断
Coding2023.2.25  10:252023.2.25 11:15446通关判断
Coding2023.2.25  12:562023.2.25 13:17219分数统计
Coding2023.2.26 15:302023.2.26 16:01328多个追赶者同时运动
Coding2023.2.26 20:092023.2.26 20:24015特殊食物生成
Coding2023.2.27 19:392023.2.27 20:02221游戏暂停,游戏继续
Coding2023.2.27 20:062023.2.27 21:05356游戏重新开始
Coding2023.3.01 20:162023.3.01 21:13354人吃特殊食物后在一段时间内对追赶者免疫
Coding2023.3.02 18:552023.3.02 19:13018显示剩余生命
Coding2023.3.02 19:142023.3.02 19:41527生命消耗判定;新的生命开始后,吃豆人在上一条生命中所吃的豆不会再生。游戏失败判定
Coding2023.3.02 19:522023.3.02 20:16519游戏失败判定

6  致谢

       非常感谢我的导师杨贵福老师,教会我们写项目之前的准备工作,帮助我形成了写项目PSP的好习惯,及时更正我的代码坏习惯。也很感谢实验室的韩亚光师兄、马洪博师兄以及田洪轩师兄帮助我调试代码,修改bug,提供思路;同时,感谢为我写吃豆人游戏提供思路的GitHub上的作者( Github账号为RookieStupidCat ),以上已经给出他的游戏项目地址。

  • 30
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值