利用Java Swing实现在线游戏盒子:推箱子 + 飞机大战游戏

盒子实现游戏🎮:

  • 🔸 推箱子:一款家喻户晓的益智小游戏,玩家控制搬运工上下左右移动,来将箱子推到指定地点。
  • 🔸 飞行射击:一款操纵飞行角色发射炮弹攻击敌机的小游戏。
  • 🔸 对对碰:一款经典的消除类游戏,玩家只要通过点击人物来使人物之间互相换位,连成 3 个以上的人物来消除得分。
  • 🔸 弹弹堂:一款回合制射击类竞技游戏,玩家双方发射炮弹攻击对方,直到一方血量为零。

JAVA程序设计小游戏对战平台,实现了注册、登陆、添加好友、聊天室(弹弹堂、推箱子、雷电、对对碰).zip资源-CSDN文库

1 游戏原理 

1.1 推箱子

1.1.1 推箱子游戏介绍

推箱子是一款来自日本的古老游戏,目的是训练玩家的逻辑思考能力。在一个狭小的仓库中,要求玩家控制角色把木箱放到指定位置。

1.1.2 推箱子功能

运行游戏载入相应的地图,屏幕中出现一名推箱子的工人,其周围是围墙、人可以走的通道、几个可以移动的箱子和箱子放置的目的地。玩家通过按上下左右键控制工人推箱子,当所有的箱子都推到了目的地后出现过关信息,并显示下一关。如果推错了,玩家通过单击鼠标右键可以撤销上次的移动操作。

游戏界面如下所示:

1.1.3 推箱子实现原理

[整体结构]

public class Box_Pusher
{
static class MapFactory{}
static class Map{}
static class GameFrame{}
}

[常量定义说明]

public class Box_Pusher
{
static class MapFactory{}
static class Map{}
static class GameFrame{}
}

【状态表识🔰】

⭕ BLANK:空格;

⭕ WALL:墙壁;

⭕ BOX:箱子;

⭕ END:目的地;

⭕ BOXONEND:箱子在目的地;

⭕ MANDOWN:朝向为下的角色;

⭕ MANLEFT:朝向为左的角色;

⭕ MANRIGHT:朝向为右的角色;

⭕ MANUP:朝向为上的角色;

⭕ GRASS:可以走动的通道;

⭕ MANDOWNONEND:朝向为下且在终点的角色;

⭕ MANUPONEND:朝向为上且在终点的角色;

⭕ MANLEFTONEND:朝向为左且在终点的角色;

⭕ MANRIGHTONEND:朝向为右且在终点的角色。

[具体实现]

核心代码说明🔰:

  • 🔹 MapFactory 定义了地图数据类。三维数组 byte[][][] sampleMap,以此描述推箱子每个关卡的内容。
  • 🔹 Map 定义了地图类,用于保存当前的游戏状态,保存人的位置和游戏地图当前状态。撤销启动时,恢复地图的操作也通过这个类获取需要的人的位置、地图的当前状态和关卡数来实现。
  • 🔹 GameFrame 是游戏面板类,完成游戏的界面刷新显示,以及相应鼠标键盘的相关事件。以下为 GameFrame()中核心函数的相关说明:在构造方法 GameFrame()中,调用 initMap()方法来初始化本关游戏地图,清空悔棋信息列表 list。
  • 🔹 initMap()会调用 getMapSizeAndPosition()方法获取游戏区域大小以及显示游戏的左上角位置,还会调用 getManPosition()方法获取角色当前位置。
  • 🔹 getPic()加载要显示的图片。
  • 🔹 grassOrEnd(byte man)判断人所在的位置是通道还是目的地。
  • 🔹 moveUp(),moveDown(),moveLeft(),moveRight()是该游戏的主要逻辑,实现角色的上下左右移动。推箱子游戏的特殊性,决定了角色移动涉及 3 个位置,即角色的当前位置,角色要移动到的位置和箱子要到达的位置。以向上移动 moveUp()为例进行说明:

⚠️ 向上移动涉及的 3 个位置为角色的当前位置(map[row][column]),角色的上 一 位 的 位 置 p1(map[row-1][column]) 和 上 上 一 位 的 位 置 p2(map[row-2][column])。首先判断 p1 处的图像类型,这里的图像类型可能为 BOX BOXONEND WALL GRASS END。

(1) 如果 p1 是墙 WALL,因为不能穿墙,所以不处理直接返回。

(2) 如果 p1 是 BOX 或 BOXONEND,则判断 p2,如果 p2 是 END 或GRASS:保存当前的游戏进度于 ArrayList 的 list 变量中,用于撤销;判断 p2 是否是目的地 END,如果是则 p2 状态设置为 BOXONEND,否则为 BOX;人前进一步,如果 p1 是 BOX,则 p1 状态设置为 MANUP,否则 p1 状态设置为 MANUPONEND;将角色刚才的位置设置成GRASS 或 END;修改人的位置在 map 数组中的行坐标 row。

(3) 如果 p1 是 GRASS 或者 END:保存当前的游戏进度于 ArrayList 的list 变量中,用于撤销;判断 p1 是否是目的地 END,如果不是则 p1状态设置为 MANUP,否则 p1 状态设置为 MANUPONEND;将角色刚才的位置设置成 GRASS 或 END;修改人的位置在 map 数组中的行坐标 row。

  • 🔹 isFinished()判断是否所有的箱子都在终点上,从而判断是否过关。
  • 🔹 undo()方法用于撤销,具体原理是往前查找 ArrayList 的 list 的信息进行还原地图。
  • 🔹 nextGrade()实现下一关的初始化,并调用 repaint()方法显示游戏界面。
1.1.4 推箱子游戏中遇到的问题及解决

[问题]在游戏制作的后期,为了增加游戏的美观度而增添了背景图片的绘制,但因此该游戏在进行过程中难免地出现了屏幕闪烁现象。

[解决方案]双缓冲技术。一个动画在运行的时候,如果图像的切换是在屏幕上完成的,并且图像切换频率高于一定值,则可能会造成屏幕的闪烁,消除动画闪烁现象的最佳方法是使用双缓冲技术。双缓冲技术在屏幕外做一个图像缓冲区,事先在这个缓冲区内绘制图像,然后再将这个图像送到屏幕上,这样一来,虽然动画中的图像切换很频繁,但是双缓冲技术很好地避免了在屏幕上进行消除和刷新时候的处理工作所带来的屏幕闪烁情况。

在该程序中的实现如下:

private Image iBuffer = null;
private Graphics gBuffer = null;
…
public void paint(Graphics g)
{
gBuffer = iBuffer.getGraphics();
//之后是通过 gBuffer 在 iBuffer 这一图像缓冲区上绘制图像
g.drawImage(iBuffer, 0, 0, this); //最后把 iBuffer 画在屏幕上
}

1.2 飞行射击

1.2.1 飞行射击游戏介绍

飞行射击游戏,又称为雷电游戏,因其操作简单、节奏明快,作为纵轴射击的经典之作。玩家可以通过上下左右键盘控制自己的飞机移动,当玩家飞机的子弹碰到地方飞机,敌方飞机会出现爆炸效果,当玩家飞机被敌方飞机碰到,玩家飞机也会出现爆炸效果,并且游戏结束。飞行射击游戏的运行界面如下:

1.2.2 飞行射击游戏原理

[整体结构]

public class Thunder extends JFrame
{
class Bullet{}
class Enemy{}
class GamePanel extends JPanel{}
public Thunder(){}
}

[具体实现]

  •  💠 Bullet 是子弹类,描述了单个子弹的坐标等属性,且自带画图方法绘制。
  • 💠 Enemy 是敌机类,描述了单个敌机的位置,是否死亡等属性,自带画图方法。
  • 💠 GamePanel 是游戏的主程序,完成游戏的界面刷新显示,以及相应键盘的相关事件。以下为 GamePanel()中核心原理的相关说明:
  • 有关敌机和子弹的实现:游戏中使用到的敌机、子弹均采用对用的类实现。因为子弹的数量很多,敌机的数量也会很多,所以每一个子弹、每一个敌机都要用一个对象来实现。但是如果频繁地创建子弹对象与敌机对象,这样会造成内存泄漏等严重问题。因此该游戏在 GamePanel 中定义了两个数组mEnemy[]和 mBullet[]并且设定这两个数组的大小是 4 和 15,意思为在屏幕上最多显示 4 个敌机和 15 个子弹。此外,还维护了 reserveBullet 和 flyingBullet两个 ArrayList 对象来实现子弹逻辑。如果某个敌机对象被子弹击中,或者超出屏幕底边,这时候可以对这个对象进行属性的重置,让他重新出现在上方的战场上,子弹对象同理。
  • 💠 init()初始化分数、玩家飞机坐标等属性,加载游戏所需要的图片,创建敌机和子弹类对象并设置当前时间。
  • 💠 reinit()用于重新开始游戏的情形,重新初始化玩家的属性。
  • 💠 updateBg()更新游戏逻辑,实现了:
  •          (1) 背景图片滚动
  •         (2) 更新子弹的位置坐标
  •         (3) 确定是否要发射新的子弹
  •         (4) 更新敌机位置
  •         (5) 调用 Collision 进行碰撞检测 

💠 UtilRandom(int botton, int top)生成[botton,top)的随机数,用于指定刷新出的敌机初始横坐标。

💠Collision()检测碰撞,检测子弹是否和敌机碰撞以及自机是否和敌机碰撞,Collision()会调用 crash 方法检测两个物体是否碰撞,crash 方法的原理很简单,其可以判断图形中两个矩形是否相交。(这里没有采用像素碰撞检测是因为两种检测方法在该游戏中相差不大,且矩形碰撞检测有着更好的性能)。

💠 emitBullet()发射炮弹,每次发射之前都检测 reserveBullet 是否为空,如果不是,则从中取出一个对象放入 flyingBullet,并且将该对象“发射”出去。Thunder()进行 JFrame 的初始化工作。 

1.2.3 地图滚动原理的实现

 另外,具体的动画特效实现原理详见 3.3.4 动画实现部分,飞行射击、对对碰、弹弹堂的动画原理原则上是一样的。

  • 24
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

枫蜜柚子茶

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值