实现功能
植物类代码编写
设计了六种植物,每种植物有其对应的一些属性,如生命值,CD等,最重要的属性为状态(int state)属性和类型属性(int type),类型对应的是具体哪一种植物,所有植物活动的变化均以state所对应的值为入口,在此状态下可能会发生某些事件
而具体的实现过程,以豌豆射手为例:
首先,将豌豆射手的各种状态画上去的过程十分巧妙,即通过不断循环十几张连续动作的图片来达到动态效果,此处借鉴了网上的方法思路。此外,通过二维数组来存放植物的位置。种植植物时,点击卡片会显示植物实体和植物虚影跟随鼠标一起移动,即待种植状态。这里植物实体跟随鼠标一起移动,而虚影只能在固定的草坪上显示,这里我的做法自认为还比较巧妙,即通过截图操作量出窗口边界到草坪左上角的长宽,再量出每块草坪的长宽,因为数据是int类型,用当前坐标减去窗口边界到草坪左上角的坐标,再除以并乘以草坪的长宽,即得到每格左上角点的坐标值,存入植物数组中,就可以使虚影固定在每块草坪上。当植物被种下时,进入摇摆状态,也就是播放摇摆的图片,设置state=1。在此状态下,可能发生的状态为看见僵尸并攻击和死亡。在判断是否看见僵尸的方法中,我利用Rectangle中的intersects方法,判断两个矩形框是否重合。由于射手的射程很长,所以此处每个射手的矩形框并非是将射手框起来,而是x值特别大的矩形框。在攻击的过程中,调用子弹列表,CD值自增,此处CD值为射手的射速,当CD自增到某个值则绘制子弹移动的动画。当植物生命值为0时,将植物从数组中移除,进入state=4,待清除状态。
除了豌豆射手外,我还设计了向日葵,樱桃炸弹,坚果墙,寒冰射手和火爆辣椒。每种植物的设计都有所不同,如向日葵CD自增会调用阳光列表产生阳光,且无攻击状态,坚果墙分为满血状态,受伤状态和严重受伤状态,樱桃炸弹通过遍历僵尸列表,判断爆炸范围矩形框是否和僵尸列表重合来清除僵尸等等。
僵尸类
僵尸类与植物类类似,具有生命值,状态等属性,同样通过state的值作为调用僵尸行为方法的一个入口。不同的是,这里僵尸存放用的是ArrayList容器,因为需要使用到遍历和增删操作,且不需要固定僵尸的具体位置,所以这样存放会比用二位数组来得方便。僵尸通过随机数概率产生,有前进,啃食,被子弹打死过程,待清除和被炸死五种状态。生成时设状态为前进,前进过程中有可能遇到植物啃食,有可能被子弹打死,有可能被炸死。在判断僵尸是否看见植物时,需要设计两种方法,否则会出现bug:
这里两种方法的区别就是,一个是判断是否碰到任一植物,一个是判断是否碰到指定植物。如果通过遍历来判断僵尸是否碰到了当前遍历的植物,也就是任一植物,那么僵尸在遍历到并非眼前的植物时,仍然继续前进,最后的效果就是前方有植物,僵尸却无视它前进。有效的做法是指定眼前植物,判断矩形框是否相撞
当僵尸生命值为0时,将其state设为4,即待清除,并在僵尸容器中将其remove出去。
开始界面
开始界面设计了五个模块,即加载界面,菜单界面,打赏作者,关于我们和排行榜。加载界面
通过鼠标监听和贴图来实现界面的切换
在菜单界面中,为每个选项卡设置对应大小的矩形框,调用Rectangle中的contains方法,若鼠标点击区域中矩形框则发生事件。
加载界面,关于我们和打赏作者即一些图片的绘制。关于我们和打赏作者加入了一些自己绘制的图片。值得一说的是,在加载界面设计了一个假的进度条,让其长度从0自增到292,中间还用sleep让它卡了一下,更加真实。当长度到达292,进度条上文字从加载游戏变为开始游戏,此时矩形框变得可以点击,点击后进入菜单界面。
总结与收获
- 通过这次课设的锻炼,让我对Java的面向对象设计有了更深的理解。对于植物大战僵尸来说,每一个个体,如植物,僵尸,子弹,阳光,就是一个个对象。而他们所带有的特征,如生命值,状态就是对象的属性。一切画面中看得见的行为,如阳光下落,僵尸啃植物,植物打僵尸,就是方法。让原本枯燥的知识变得形象生动。
- 将一个游戏中的内容抽象成一个个类,一条条代码,很大程度上提升了我的抽象能力,对以后设计项目有很大帮助。
- 在做课设的过程中大量使用到图片和鼠标监听,让我对GUI的使用更加娴熟,也增加了我可视化编程的思维和能力。