很多小伙伴玩家都不太清楚值物大僵尸游戏|用Java写一个简单的动物大战僵尸!,那么今天解雕侠小编给大家带来一篇 僵尸 相关的文章,希望大家看了之后能有所收获,最后请大家持续关注我们!
前言
谁没有玩过动物大战僵尸?
小慧的一位读者用 Java 开发了自己的 vs. 游戏。虽然系统比较简单,麻雀小而全,但是对游戏开发感兴趣的人可以学习一下哦~~
游戏设计
动物大战僵尸中有一个小游戏关卡。屏幕顶部有一个滚轮机,会随机生成动物。玩家选择动物后可以自由选择草皮放置。基于这个游戏模式,我提取了这个关卡,单独制作了一个简单版的动物大战僵尸。游戏画面如下:
将在屏幕两侧手动生成动物卡片。单击以选择并将它们放置在草皮上。僵尸将在双方手动生成。不同的僵尸有不同的连接率和血量。有的丧尸有隐藏奖励,比如:全屏丧尸静止、全屏丧尸死等。当时还没有游戏暂停功能,导致今天的截图时间很难控制。那么我们先来说说游戏暂停功能怎么做吧。
最简单的暂停方法是将键盘从屏幕上移开,然后游戏暂停。所以这里需要介绍一个键盘bug风暴。
无效(e){
//游戏运行时
如果(==开始){
//通过键盘连接电波的对象获取当前键盘位置
intx=e.getX();
inty=e.getY();
//如果键盘超出游戏界面
if(x>Game.WIDTH||y>Game.){
//将游戏状态改为暂停状态
=暂停;
}
}
}
其实,这只是一种通过点击键盘位置来改变游戏状态的简单方法。也可以使用鼠标错误,当按下一个键时游戏会暂停,以获得更好的用户体验。但是原理是一样的,这里就不展示代码了。
游戏对象
首先剖析游戏中的对象。各种动物,各种僵尸,各种炮弹。这样,这里就可以提取出三个父类,分别是动物、僵尸和子弹。在面向对象中,泛型将继承父类的所有属性和技巧。因此,可以将三个类别的共同属性和技能提取到各自的父类别中。比如僵尸父类:
类{
//僵尸父类
//僵尸共有的属性
;
int;
现场直播;
intx;
inty;
......
//僵尸状态
=0;
=1;
=2;
=生命;
/*
*添加为什么父类是具体类,比如每个僵尸都有连接方式值物大僵尸游戏,
*但是每个僵尸的连接形式不同,所以技能的模式可能不同,
*比喻模式没有模式体,可以在基类中重绘,
*但是有具体方法的类必须是具体类,所以父类通常是具体类
*/
//统一形式
空步();
....
}
动物父类和子弹父类也是如此。
如前所述,需要将基类共享的方法提取到父类中。如何处理一些泛型类型共享的方法?比如蚕豆天秤和霜冰天秤可以发射炮弹,但坚果墙没有这种射箭行为。所以这里需要用到()。
射击{
// 套接字 - 将泛型的一些常见行为提取到套接字中
//中的默认方法是yes,规范编码应该丢弃数组
[]拍摄();
}
至此,游戏对象的属性和方法基本定义好了。至于图片的显示和如何绘制,只需要使用相应的API即可,这里不再赘述。工作一年,回来看看,还有很多地方可以优化。比如目标的血量、攻击力、移动力等都可以写入到配置文件中,这样在调整游戏参数的时候就不用去修改代码相关的内容了,你只需需要修改配置文件上面的参数。
游戏内容
现在我们在游戏中有了对象,是时候开始向游戏中添加对象,然后移动它们,最后击中它们。首先,让对象添加到我做的游戏中,这里是僵尸的例子:
//首先要有僵尸集合
//僵尸合集
List=new();
//然后定义如何随机生成僵尸
(){
rand=new();
//控制不同类型僵尸出现的几率
=rand.(20);
如果(类型
新的();
}(类型
新的();
}(类型
新的();
}其他{
新的();
}
}
//僵尸入口
//设置进入间隔
/*
*在此处添加为什么要设置进入间隔
*由于游戏是基于计时器的,
*定时器每隔一段时间就会按照你添加定时器的方式执行,
*所以这里需要设置进入间隔来控制游戏的速度。
*/
int=0;
void(){
++;
//计算自增的余数
如果(%300==0){
//如果条件满足,则调用随机僵尸生成方法,将生成的僵尸加入僵尸集合中
.add(());
}
}
最早我使用的数据结构是链表,但是在后来的编码中,我发现对僵尸对象进行了大量的遍历和增删操作。链表的添加和删除非常麻烦和复杂,所以我用一个集合来代替它。 工作上也是如此,先想好编码再选择合适的数据结构,往往能事半功倍。
动物入口的设计是我当时觉得很微妙的一点。说一下当时在编码中发现的问题。首先,动物进场时是在滚轮机上,滚轮机上的连接会涉及到追、停的问题。追的方法其实就是追之前的动物卡,但是当第一张动物卡被选中放到草地上,怎么追呢?
一开始我的做法是给多加几个状态来解决这个问题,发现状态太多会大大降低if判断中的条件,但是尝试之后还是没有实现想要的效果,所以我只是把动物收藏分成了两部分。在之前的游戏功能设计中,回过头来看,将动物收藏分为滚轮机上的收藏和战场上的收藏,实在是太精致了。请听我的故事:
//滚轮机上的动物,状态为停止等待
List=new();
//战场上的动物处于生命状态,通过键盘选择并连接移动移动。这里的设计不合理,会造成之前的BUG
List=new();
//动物在滚轮上的碰撞判断
void(){
//在滚轮机上遍历动物集合,从第二个开始
for(inti=1;i
//如果第一只动物的y小于0,但处于停止状态,则状态变为等待
if(.get(0).getY()>0&&.get(0).()){
.get(0).();
}
//如果第i个动物的y大于第i-1个动物的y+,则表示遇到了,将i的状态改为停止
if((.get(i).()||.get(i).())&&
(.get(i-1).()||.get(i-1).())&&
.get(i).getY().get(i-1).getY()+.get(i-1).()){
.get(i).();
}
}
}
//检查滚轮上的动物状态
void(){
//迭代器
它=.();
while(it.()){
=it.next();
/*
*如果滚轮机收藏中有动物处于移动或生命状态
*被添加到战场动物集合中并从原始列表中删除
*/
/*
*现在我发现滚轮上处于移动状态的动物被添加到了
*战场上动物收藏的最佳操作时间应该是
*等动物状态变为生命后再添加。
*/
如果(p.()||p.()){
.add(p);
它.();
}
}
}
其实滚轮机上判断动物状态的代码已经变得僵硬了,正是在我想优化这段代码的时候值物大僵尸游戏,我萌生了分享游戏设计流程和游戏代码的想法。那么我们来谈谈如何优化这段代码:
//先描述状态
//wait-动物卡连接在滚轮机上。因为是等待被键盘选中,所以命名为wait
//stop-动物卡在滚轮机上停止,有两种情况,1-到达顶部2-打上一张卡
//开始优化以下代码
//如果第i个动物的y大于第i-1个动物的y+,则表示遇到了,将i的状态改为停止
//if((.get(i).()||.get(i).())&&
//(.get(i-1).()||.get(i-1).())&&
//.get(i).getY().()==1).(.());
让我们看看里面发生了什么。首先对数据的集合进行流式处理,然后调用过滤方法。强大的表达式让代码变得简单,但是判断条件的变化可以直接在代码中维护,不需要维护策略套接字的实现类。最后将其转换为集合,返回符合产品要求的集合。
回到题外话,你是如何让你的被摄对象抓住它的?下面是一个僵尸攻击动物的例子:
//僵尸超类定义了僵尸的攻击方式,
//因为僵尸的攻击行为是一样的,所以这里是正常的方式
//僵尸攻击动物
(植物){
intx1=this.x-p.();
intx2=this.x+this.width;
inty1=this.y-p.();
inty2=this.y+this.width;
intx=p.getX();
inty=p.getY();
x>=x1&&x=y1&&yx1&&Mxy1&&我的
//移除动物
它2.();
//取出铲子
它.();
=假;
}
}
}
}
看着这段非常复杂又看似功能强大的代码,我有了再努力玩的想法,但为了保持原汁原味,我忍了。所以我发现了一个错误。如果选择铲子后战场上唯一的动物被僵尸吞食,那么铲子会一直跟着键盘走,很难达到使用后取出的效果。解决方案其实很简单。当战场上的动物集合大小为0时,清空耙集合即可。
3.游戏可玩性优化
上面游戏设计中提到的杀死僵尸可能会随机获得奖励的类型就是通过这种方式实现的。还是从设计上分析,并不是每一种丧尸都能获得奖励,所以奖励应该放在插槽中:
奖项{
//奖励插座
/*
*这里还是有代码不规范的问题
*的方法是默认的
*中的变量默认是final的
*这个默认数组应该被丢弃
*/
//全屏静止
=0;
//全屏消除
=1;
int();
}
当僵尸死亡时,需要判断僵尸是否有奖励插槽,如果有,执行对应的奖励方法:
//检查僵尸状态
void(){
//迭代器
它=.();
while(it.()){
z=it.next();
//僵尸的HP大于0,会死,死去的僵尸会从集合中删除
if(z.() 遇到动物时跳过 -> 如果再次遇到动物,它会开始攻击。执行状态更改时,应考虑当前状态是否仍然可以跳转。
3.当动物的力量攻击范围内没有僵尸时,动物停止力量攻击
这很容易拉。当动物进行强力攻击模式时,校准是否存在Y坐标相同的僵尸就足够了。
上面就是值物大僵尸游戏|用Java写一个简单的动物大战僵尸!的全部内容了,希望能给广大手游玩家玩家们带来一些帮助,更多关于僵尸的内容,尽在解雕侠!