基于Cocos2dx实现的射击小游戏

Dreamlover

发布日期: 2021-03-30 08:04:59 浏览量: 171
评分:
star star star star star star star star star star_border
*转载请注明来自write-bug.com

1.概述

这是一个 1p/2p 的动作射击类游戏,玩家在不同的环境下面临怪物的追击,需要获取补给来得到武器和弹药,活下去就得杀死怪物,时间越久怪物会越来越多,看看你能拿多少分吧!

功能

  • 进入游戏有玩法介绍

  • 可选择地图、单人/双人模式

  • 通过键盘来分别控制角色移动、攻击怪物

  • 屏幕会根据角色的移动而移动

  • 怪物主动追击角色,并攻击

  • 杀死怪物可以获得分数,游戏结束后自动记录成绩

亮点

  • 枪械、子弹种类丰富

  • 角色的移动、攻击流畅

  • 界面动画丰富、美观

开发环境

  • Visual Studio2017

  • cocos2d-x-3.16

2.项目难点及解决方案

难点:tileMap 制作地图要考虑到障碍物的问题,不能让角色太随心所欲地移动

解决方法:这需要在地图上弄好要设障碍物的位置(要单独弄一个图层出来)

上图红色部分即为有障碍物的地方。这些红色的是用图块覆盖的,图块要增加自定义属性以设置成障碍物。

核心代码

先获得对应的瓦片地图中的坐标,再获得相应瓦片地图上的瓦片,判断其是否有障碍物属性,为 true 则说明这是障碍物。

难点:角色移动时,因为地图大过屏幕大小,会出现角色移动没有超过地图范围,但超过了屏幕返回的情况,但不知道为什么一开始在设置视角后又会自动跳转到别的视角,之后又可以了,调试了很久也没能发现问题源头

解决方法:角色移动时屏幕视角也应该相应移动,可得到当前视角中心与目标位置的偏移,再移 动屏幕,要注意的是不能让屏幕显示地图之外的部分,具体代码在 setViewPoint 函数中

核心代码

难点:与玩家相关的信息(枪械、分数等时)通过 label 显示时,要使其始终在窗口左(右)上角, label 位置难以设置

解决方法:要注意信息也要随着窗口移动而移动,视觉上感觉一直在屏幕左(右)上角,实现思路 来自与设置屏幕视角,在得到 actualPosition 之后,就得到了屏幕视角的中点,再加上一些偏移量 就可以实现信息的移动了

核心代码

难点:关于界面跳转时的传参问题,由于生成人物之前就需要获得一些变量,例如地图名称和单人或者双人模式,因此变量需要在创建新的场景之前传递过去,所以不能存在各个 Scene 类里,不管是否是静态或者非静态都不行

解决方法:为了便于管理,创建了一个新的类用于控制全局变量

核心代码

难点:在实现主界面点击显示帮助信息和历史成绩时,最初是产生一个新的界面并跳转,但这样会使代码结构复杂,新产生的界面没有什么实际用处

解决方法:参考最后一周的作业,改为用 TxtField 来实现

核心代码

难点:在记录历史最佳成绩时,要考虑是否三个成绩已经存满,还有是单人模式还是双人模式

解决方法:在 Userdefault 里分别存储单人和双人成绩,并根据存储数据进行逻辑判断是否有成绩空位

核心代码

难点:怪物向角色移动时,会互相卡住而不能移动

解决方法:原因是在判断怪物是否能够移动时,需要判断怪物目的地坐标(怪物位置+移动向量) 是否包含障碍物或其他怪物,而我把移动向量(距离)设置得比较小,所以一旦怪物十分接近, 判断结果就会一直为不能移动。所以增大移动向量就能解决问题

核心代码

难点:维护怪物相关列表时,容易出现越界错误

解决方法:手动判断临界条件

核心代码

难点:怪物的帧动画可能会发生冲突

解决方法: 对每个怪物使用一个互斥锁来控制帧动画的播放维护一个锁的列表;播放前,判断 isDone 为真才播放帧动画;播放后,把 isDone 设置为真

核心代码

难点

  • 八方向的位移问题:该如何做到很流畅地用四个方向键完成八方向的位移,摁住方向键不松开实现连续移动,松开摁键能实现快速停下。移动与射击的互斥问题,因为射击我也设计了帧动画,于是摁射击键的时候,人物要停下,并且执行完射击帧动画后才允许继续移动

  • 位移与帧动画的流畅结合,停下时帧动画也要停下,转向时帧动画也要转换

解决方法

  • 角色移动的帧动画是八方向的,一开始以为只要确定人物当前的朝向即可,后来发现没这么简单,因为人物朝向不代表它在动,所以还要加上是否在移动的判断。另外如果简单用 sequence:动画 MoveBy,MoveTo+八方向帧动画来实现人物移动位置和实现帧动画的话,会出现移动不够流畅的效果,于是决定改用 setPosition 来实现移动,帧动画另外分开进行 runAction (sequence),用调度器 update 来调度转向,这样实现了迅速地转向与停下,一个较为流畅的移动效果

  • 用当前的执行方向——(八方向 or stop)与之前的执行方向进行对比,分 stop,与之前不同,与之前相同三种情况进行逻辑判断

核心代码

难点

  • 移动位移+帧动画与射击帧动画的冲突

  • 6 种类型子弹的不同效果,包括样式,射程,伤害,能否连发各性质的不同

  • 子弹与怪物的碰撞条件的判断,迭代器的问题

解决方法

  • 将执行方向 string 加一个 shot 状态,当这个状态来临时,要停止之前的移动和移动帧动画,进行射击。另外增加 toward 表示现在的朝向,子弹发射沿这个方向进行旋转

  • 得到 toward 的朝向,要设置子弹精灵的锚点,旋转角度,然后设置射出轨迹,当超出范围时还要移除。另外用 Bullet 这个类来记下当前在场景飞的子弹队列,用于后续的子弹与怪物的碰撞条件判断。Bullet 还记下了剩余子弹的数目。因为有 6 种不同类型的子弹,所以要进行复杂的逻辑判断,来实现多种多样子弹的效果

  • 子弹与怪物的碰撞条件的判断的难点在于迭代器,我们先要写好 Player 类,Bullet 类和 Monster 类的 collide()函数,用来碰撞检测的辅助。然后就是遍历各种各样的队列 Vector,然后用迭代器进行响应的处理

核心代码

难点

  • Monster 打中玩家的判断,玩家如何进行扣血

  • 玩家血量降至 0 后的反应,如何判断游戏结束等

  • 游戏关卡的涉及,升级趣味性

解决方法

  • 跟角色攻击子弹与怪物的碰撞类似,这里检测的是大怪物发射的“子弹”与玩家进行碰撞检测,另外检测小怪物是否靠近了角色,是否对角色进行攻击,列出攻击玩家的队列,然后根据攻击玩家的队列的 size 进行响应的扣血。玩家扣血,血量直接减少,到 0 自然就是死亡,然后每次扣血都有响应的受伤音效

  • 角色死亡即血量到零,角色变成一个坟墓,不能再移动,也不能再射击,若单人模式,自然死了就游戏结束,双人模式要两个都死才能结束。另外为了允许玩家直接结束游戏,按键 T 可以直接返回菜单界面,并保留积分

  • 涉及每一关的关卡,每一关的通关时间随着关卡数的增加而减小,难度越来越高,生存岛看看玩家在难度逐渐增加的同时,是如何实现高分的

核心代码

总结

这次项目是对整个 cocos2d 的总结学习,界面 UI 运用了精灵的创建,Lable 的创建,菜单项的 使用,还有本地数据的存储,这里采用的是 UserDefault 来存储,界面的布局包括图标的大小、渲染 的层次,各个项之间的相对位置及绝对位置,各个场景之间的切换等等。

上传的附件 cloud_download Survivor_Island射击小游戏.7z ( 37.31mb, 8次下载 )
error_outline 下载需要10点积分

发送私信

花有重开日,人无再少年

20
文章数
27
评论数
最近文章
eject