有没有好玩的塔防游戏三d利用视角的游戏叫什么什么塔

Unity VR大师课程 | 制作你的第一款VR塔防游戏 - Unity3d技术 - 精品正版课程-泰课在线 - 游戏开发、移动开发、美术CG、虚拟现实、UI平面设计、前端开发相关的在线课程|IT技术网络课堂 - Powered By EduSoho
Unity VR大师课程 | 制作你的第一款VR塔防游戏
新年伊始,我们第一场活动就来到了羊城-广州举办精品课程-VR大师课程,来自Unity总部的大师Carl和Unity官方工程师为现场学员答疑解惑并提供技术支持,带领大家在一天的时间中,完成了一款VR的塔防游戏,现在。我们就带领大家,回顾一下Carl的此次课程,一起动手来实现你的第一款VR塔防游戏吧。
本次课程,我们将实现的是一款塔防游戏,在Gear VR上的运行。玩家可以通过头部的旋转完成场景内摄像机的旋转,而点击Gear上的按键,完成炮台的射击。
我们需要提前准备:
1.Unity 5.2或更高版本
2.下载工程资源(点击阅读原文获取下载链接)
3.掌握Unity Editor的界面功能及使用具有初步理解。
4.拥有一台Gear VR或Oculus设备测试游戏是否正常运行。& && &&&
现在让我们开始吧!
1.打开Unity,创建一个新工程。将下载好的资源直接拖入Project视窗下的Assets下。
2.点击搜索标签,选择model,将其中的Environment,直接拖入到Hierarchy面板下,此时该模型的实例,将出现在场景的原点处。
注意:如果直接拖入Scene,位置不容易掌控。
3.为Environment中的子物体Plane.001,添加MeshRender组件。
4.将Inspector下Environment旁的Static打勾,在菜单栏的Window下打开Lighting面板,取消Auto(防止每次移动物体后的Bake),随后点击Build按钮对场景进行烘焙。
注意:希望快速烘焙,可以关闭Baked GI,同时将Precomputed Realtime GI分辨率调低,如下图。
(有关GI的内容可查看:&... hting-and-rendering)
5.将Assets中的WispySkyboxMobileMat拖入场景,完成天空盒的添加。
6.同理将Tower拖入场景中,放置于合适的位置,如下图。
注意:也可以通过调节Inspector下的Position实现,并为Tower添加合适大小的Box Collider。
此时场景的搭建便已初步完成。
接下来我们将完成敌人的生成与移动。
1.在菜单栏Window下,打开Navigation窗口,用以编辑敌人的寻路。将Agent Radius数值调小,使敌人拥有更多移动路径。点击Bake进行烘焙,如图。
2.在Assets中找到模型Drone,将其拖入场景(靠近地面),为其添加NavMeshAgent组件,该组件提供Bake地图范围,规划向目标点移动的功能。同时需要添加的还有EnemyNavigation脚本,添加后,将场景中的Tower拖至Inspector中EnemyNavigation脚本的Target属性,如图03。运行场景,敌人便向Tower方向移动了。
3.为Drone添加SphereCollider组件,调整碰撞体大小。创建新的Tag,命名为Enemy,将Drone的Tag更改为Enemy。同时为其添加Rigbody组件,取消Use Gravity,同时勾选Is Kinematic。
4.将Drone拖入到Project中的Prefabs文件夹内,更名为DronePrefab,形成预设。完成后,删除场景中的Drone。创建空物体,将其命名为Point,同时拖放置你所希望的敌人生成点。
5.为Point添加SpawnScript脚本,将DronePrefab,和场景中的Tower分别拖入Enemy,Target属性。根据需求,修改生成敌人间隔Spawn Interval。
6.为场景中添加更多的生成点,可以通过点击Inspector下Point旁的正方形,在场景中添 加醒目的标签,如图。运行场景,敌人便会向Tower不断靠近。
Camera的设置
1.点击场景中的Tower,在Hierarchy中添加一个空物体,将其命名为CameraPosition,将场景中的Camera作为CameraPosition的子物体,点击Camera中Transform下的Reset,此时Camera将与其父物体的位置相同。我们需要注意:
a.在VR游戏中,Camera是由设备进行控制,如果希望移动Camera,需要为其添加一个父物体,通过移动父物体,从而达到移动Camera的作用。b.CameraPosition的位置一定需要在Tower的外部,否则射击时,会出现问题。
2.在VR设备中,Camera会跟随设备进行选转。而在Editor中我们仍需要通过脚本进行控制。将脚本CameraEditorControl拖在Camera上,该脚本通过# if UNITY_EDITOR,只在编辑器运行情况下调用。
3.向场景中添加Image,点击Inspector下的stretch。按Alt键,选择扩充,将Image扩充至整个屏幕。
4.选中Image,点击Ctrl+6,为Image录制动画,在0:00时,为黑色,2:30时,为透明。
5.点击Project下的该动画,取消Loop Time选项。
Tower的攻击
1.在Canvas下继续添加一个Image,将其命名为Reticle(瞄准点)。将Assets中的Reticle图片,拖至Source Image。把Canvas的Render Mode改为Screen Space-Camera,同时新建一个Camera命名为CameraUI,把其Clear Flags设为Depth only,Culling Mask设为UI,之后把CameraUI赋给Canvas的Render Camera。Reticle与Image在Hierarchy的顺序进行更改,如图。从而先渲染Reticle,后渲染Image。然后给Reticle添加脚本AdjustSize,同时把场景Camera赋值给Cam变量,Basic Dis与Farest Dis分别设为-210和400(可以自己调节并设置为最佳效果值)
2.在Camera上添加AudioSource组件,同时将音频Rifle拖入到AudioClip。取消Play On Awake,防止场景开始时的播放。
3.将Assets中的粒子Stone_BulletImpact,拖入场景中,同时为Camera添加ShootScript脚本。将刚添加后的Stone_BulletImpact,赋予该脚本。运行场景,击中敌人后,敌人消失。
Tower的血量
1.为Tower添加BoxCollider组件,而Camera不可再BoxCollider组件内部。
2.将Rigidbody组件添加至DronePrefab,取消Use Gravity,同时将Is Kinematic勾选(两物体间发生碰撞检测,移动物体需具有Rigidbody组件)
3.为Tower添加Tower Health脚本,以及AudioSource组件。将TankExplosion音频至于AudioClip中,取消Play On Awake。
4.在Canvas下创建一个新的Image,按照前面黑色淡入Image的制作方式设为占满Canvas,并把Color设置为红色,alpha值设为0。给Tower添加Tower Health脚本,把Canvas下的Image赋值给Damage Image,然后在拖入三个Drone到场景中,放置在Tower边上作为血量显示,同时把其中两个Drone分别赋值给脚本中的Drone Life 2和Drone Life 3变量。
退出与发布
1.将QuitApplicationScript脚本,添加到Camera上。该脚本包含编辑器和GearVR的退出功能。
2.打开菜单栏File中Build Setting。针对Oculus,选择PC,将Player Setting下的Virtual Reality Supported选中既可进行发布。而对于Gear VR,则选择Android,同样勾选Virtual Reality Supported。推荐选择Multithreaded Rendering和GPU Skinning,Unity在新版本中已经对这几个选项进行了优化。
这个VR塔防游戏的开发操作过程已经介绍完毕。大家可以点击原文下载工程资源,赶紧动手操作起来吧!
(下载链接中的VRMasterDemo中包含两个文档:- &China VR&中的资源,可用于按照上述步骤进行开发-&&&本文案例&中是完整的工程文件)
来源:Unity官方社区
后发表看法
Unity VIP会员①群
Unity VIP会员②群
HTML5公开课①群(hot!)
HTML5公开课②群(new!)
Cocos2dx公开课①群(hot!)
Unity公开课①群(2000人群)
Unity公开课②群(2000人群)
Unity公开课③群(2000人群)
Unity公开课④群(2000人群)
泰斗社区求职招聘①群
工作时间: 9:00 - 17:00
北京客服: 010 -
广州客服: 020 -扫一扫,访问微社区
后使用快捷导航没有帐号?
签到成功!您今天第{todayrank}个签到,签到排名竞争激烈,记得每天都来签到哦!已连续签到:{constant}天,累计签到:{days}天
当前位置: &
查看: 2066|回复: 3
Unity3D 塔防游戏常用的 Waypoint (路点)
85749/10000排名11昨日变化主题帖子积分
常驻蛮牛, 积分 5749, 距离下一级还需 4251 积分
常驻蛮牛, 积分 5749, 距离下一级还需 4251 积分
蛮牛币178512
在线时间484 小时
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
才可以下载或查看,没有帐号?
用于解决给定路线的行走,有很多别名,比如:巡游、给定路径。。。。。。最常见的就是塔防类游戏。
& & 官方网站上有个非常好的例子,能够“完美”解决路点的需求。个人按照自己的方法做了个算法简化,没有使用 Quaternion (四元数)这个高深的类。使用的是更加方便的Vector3.
& & 实现分为两步。1:路点间的直线行走。2:解决突然转向的,让转向平滑。&&
& & 解决方案1:
& && &&&每个Waypoint是一个trigger。角色仅仅向着自己的target方向前进,就是z轴的正方向。运动的方法如下:
& && &[AppleScript] 纯文本查看 复制代码
var fMoveSpeed : float = 4.0; // 角色的移动速度
function Update()
transform.Translate( 0, 0, fMoveSpeed );
多个Waypoint之间的连线形成一条路,存储所有的Waypoint需要用到数组
var aWaypoint : Transform[]; // 路点数组
& && &&&将js代码作为组件给角色。用 gameObject 的 Cube(就是普通的立方体)作为路点。先在Scene面板内创建所有路点。然后依序拖入角色的 aWaypoint 变量内,这时此变量的长度会自增。问题是拖动的顺序必须是路点的顺序,万一错了就2了。所以可以使用更方便的方法, 在变量下面有个unity提供的变量Size,手动填入路点数量。这时Unity会在下面直接创建填入数量的列表。点击每行最后面的圆圈。会弹出一个面板“Select Transform”,这里有本场景内的所有物件,如果路点的名字比较给力那么和数组元素一一对应添加即可。为了让路点数量统一,在代码里需要有个数组长度变量,以便和这个长度相同,放置造成数组越界。
& && & [AppleScript] 纯文本查看 复制代码 var nWaypointNum : int = 0; // 路点的数量
每个路点设置为Trigger。物件添加Rigibody属性。然后扩充刚才的代码
var nWaypointNum :
var aWaypoint : Transform[];
var fMoveSpeed :
private var nTargetWaypoint : //下一个路点的索引
function Start()
nTargetWaypoint = 0;
function Update()
// 这里使用了一个技巧,就是通过向量减法,算出朝向下一个路点的方向向量。
transform.forward = aWaypoint[nTargetWaypoint].position - transform. // 朝自己的z方向移动。
transform.Translate( 0, 0, fMoveSpeed * Time.deltaTime );
function OnTriggerEnter( go : Collider )
nTargetWaypoint++;
Debug.Log(nTargetWaypoint);
if( nTargetWaypoint &= 4 ) { nTargetWaypoint = 0; }
& & 解决方案2:&&
& && &&&通过使用 Vector3 类提供的牛x函数来产生平滑的差值
& && &&&static function Slerp (from : Vector3, to : Vector3, t : float) : Vector3&&
& && &&&from------起始向量
& && &&&to------目标向量
& && &&&t------取值在0到1之间,如果为0计算出来的向量就和from向量重合,如果为1则和to向量重合。所以这个参数说的直白些就是一个偏向值。(根据测试的实际情况来看,如果t值大于1,则为1,所以当累计便宜大于1也不会出现s型运动)
& && &&&为了让角色有个转向动画,那么必须让最后的t值每帧都发生改变。 Time.deltaTime 能够获得两帧之间的毫秒时间差,单位为秒。
& && &&&与上面不同的代码仅如下&&
& && &[AppleScript] 纯文本查看 复制代码
function Update()
// 注意第一个参数是 transform.forward ,这就是为什么前面用z的正方向做朝向原因
transform.forward = Vector3.Slerp( transform.forward, aWaypoint[nTargetWaypoint].position - transform.position, Time.deltaTime * 10 ); // 朝自己的z方向移动。
transform.Translate( 0, 0, fMoveSpeed * Time.deltaTime );
unity 动态路点;unity 防塔;塔防游戏 ;u3d塔防游戏案例教程 下载;unity 塔防 格子 算法; 塔防游戏开发;unity 开发的塔防游戏;unity 塔防;unity3d怎么刷上坡路;unity 赛车插件下载;unity移动开发之3d塔防案例 密码;unity塔防;unity3d塔防游戏案例;unity赛车游戏unity塔防教程;u3d塔防游戏案例教视频下载;unity塔防游戏;unity塔防游戏教程;unity3d 塔防
每日推荐:
最近百度对文件链接审查比较严格,如果遇到链接失效情况,可以加管理员QQ,我将更新链接,补还蛮牛币,还请谅解。
下载解压包遇到密码一般为:tinytimes
5689/1000排名<font color="#FF昨日变化2主题帖子积分
熟悉之中, 积分 689, 距离下一级还需 311 积分
熟悉之中, 积分 689, 距离下一级还需 311 积分
蛮牛币1213
在线时间92 小时
最近在做赛车游戏的AI的路线
除了用waypoint的方法
大大可有良计?
每日推荐:
4454/500排名<font color="#FF昨日变化1主题帖子积分
四处流浪, 积分 454, 距离下一级还需 46 积分
四处流浪, 积分 454, 距离下一级还需 46 积分
在线时间105 小时
提问~~~偶想把这物体做成prefab靠instantiste发出~~~然后沿着路径运动~但是为啥prefab的waypoint的element老是自动就消失了呢?~~
已解决~~用find找场景中该物体就没事了~~~奇怪~~为啥prefab直接引用就不可以呢?
每日推荐:
273/150排名<font color="#FF昨日变化12主题帖子积分
初来乍到, 积分 73, 距离下一级还需 77 积分
初来乍到, 积分 73, 距离下一级还需 77 积分
在线时间16 小时
看着不错, 用的时候再来看.
每日推荐:
连续签到30天
原创精华达人
原创精华帖子总数量 ≥ 100
论坛建议之星
为论坛提出建设性的建议并被多数被采纳,必须采纳5条以上
突出贡献奖
宣传论坛,介绍更多的朋友加入≥50人
累积数量达到100000蛮牛币
游戏蛮牛QQ群会员
加入游戏蛮牛官方QQ群
在“新人报到 ”版块发过自己的照片
社区QQ达人
使用QQ帐号登录论坛的用户cocos2d-x 3.0游戏实例学习笔记《卡牌塔防》第八部---怪物出场
**1.本次游戏实例是《cocos2d-x游戏开发之旅》上的最后一个游戏,这里用3.0重写并做下笔记
**2.我也问过木头本人啦,他说:随便写,第一别完全照搬代码;第二可以说明是学习笔记---好人
**3.这里用cocos2d-x 3.0版本重写,很多地方不同,但是从重写过程中也很好的学习了cocos2d-x
***每一步对应的所有代码以及用到的资源都会打包在最后给出
***为避免代码过多,每一步的代码都做了标记--一看就晓得是第几步实现的避免出错改不回去(难不成还用Git?)
***为了方便移植到手机上,对于每一步都进行编译android测试;因为很多时候代码在win32下可以,编译就会出错,给出的代码会是测试过后的。
本次笔记内容:
1,、简单的设计思路
2、代码&效果
3、下次笔记内容
4、本次代码&资源
一:简单的设计思路
1、怪物需要移动,若全部放到Monster类里面就太复杂啦,于是乎和前面一样,也抽离出来一个移动控制器,怪物带着一个控制器就可以按照路线行走
2、关于移动控制器,是根据之前编辑好的怪物路线---也就是那些有顺序的点来行走,那么移动控制器得用update来实现自动行走
3、英雄暂时只有一种,但是怪物有5中,也有其属性
4、每一关的怪物数量,种类也通过plist文件来配置,只不过要手动
二:代码&效果
这里先有一个移动控制器的基类:
#define CHECK_MOVE_SPEED_LVL1 0.1f
//移动间隔
#define CHECK_MOVE_SPEED_LVL2 0.04f
#define CHECK_MOVE_SPEED_LVL3 0.03f
#define SPEED 1
class ControllerMoveBase : public Node{
ControllerMoveBase();
~ControllerMoveBase();
CC_SYNTHESIZE(int,_speed,Speed);
protected:
//是否在移动
bool _isXL
//x方向是否在左移
bool _isYUp;
//y方向是否在上移
int _checkMoveS//移动间隔
//根据当前Pos,以及目标点,获取下一个点坐标
Point getNextPos(Point curPos,Point destPos);
};解释一下getNextPos函数,如我们编辑好的地图,两个点,(0,0) (0,500)那么最开始curPos 就是(0,0) 到达目标点之前,目标点一直都是(0,500),一秒之后走到了(0,100);那么此时curPos就是这个,然后继续按照速度计算下一个点
ControllerMoveBase::ControllerMoveBase(){
_isMoving =
_isXLeft =
_speed = SPEED;
_checkMoveSpeed = CHECK_MOVE_SPEED_LVL2;
_entity = NULL;
ControllerMoveBase::~ControllerMoveBase(){
CC_SAFE_RELEASE(_entity);
Point ControllerMoveBase::getNextPos(Point curPos,Point destPos){
//移动方向
if(curPos.x > destPos.x){
_isXLeft =
_isXLeft =
if(curPos.y < destPos.y){
//改变坐标
if(curPos.x
destPos.x){
curPos.x = destPos.x;
else if(curPos.x > destPos.x && _isXLeft){
curPos.x -= _
if(curPos.x < destPos.x){
curPos.x = destPos.x;
if(curPos.y
destPos.y) {
curPos.y = destPos.y;
else if(curPos.y > destPos.y && _isYUp == false) {
curPos.y -= _
if(curPos.y < destPos.y) {
curPos.y = destPos.y;
return curP
}那么来一个简单的移动控制器,也就是要用到怪物身上的。h
class ControllerSimpleMove : public ControllerMoveBase{
ControllerSimpleMove();
~ControllerSimpleMove();
static ControllerSimpleMove* create(Entity* entity);
bool init(Entity* entity);
void moveByPoslist(Vector posList, int speed, int spanTime);
Vector _movePosL //根据坐标点移动
PosBase* _curDestP
//当前的目标点
float _moveS
//移动时间间隔
float _moveTimeC
//移动计时
//移动update
void checkMoveUpdate(float delta);
void nextMovePos();
ControllerSimpleMove::ControllerSimpleMove(){
_curDestPos = NULL;
_moveTimeCnt = 0;
_moveSpan = 0;
ControllerSimpleMove::~ControllerSimpleMove(){
CC_SAFE_RELEASE(_curDestPos);
ControllerSimpleMove* ControllerSimpleMove::create(Entity* entity){
ControllerSimpleMove* simpleMove = new ControllerSimpleMove();
if(simpleMove && simpleMove->init(entity)){
simpleMove->autorelease();
CC_SAFE_DELETE(simpleMove);
return simpleM
bool ControllerSimpleMove::init(Entity* entity){
CC_SAFE_RETAIN(entity);
this->_entity =
this->schedule(schedule_selector(ControllerSimpleMove::checkMoveUpdate));
void ControllerSimpleMove::checkMoveUpdate(float delta){
if(_isMoving)
_moveTimeCnt += delta*1000;
//移动时间到了
if(_moveTimeCnt >= _moveSpan)
_moveTimeCnt = 0;
//**8**移动
if(_entity != NULL)
Point entityPos = _entity->getPosition();
Point curDestPos = _curDestPos->getPos();
//根据移动速度,来获得下一个点位置
entityPos = getNextPos(entityPos,curDestPos);
_entity->setPosition(entityPos);
//当走到目标点 PosBase List 中的一个点之后,就要更新目标点
if(entityPos.x == curDestPos.x && entityPos.y == curDestPos.y)
if(_movePosList.size() > 0){
nextMovePos();
void ControllerSimpleMove::nextMovePos(){
if( _movePosList.size() <= 0){
CC_SAFE_RELEASE(_curDestPos);
_curDestPos = (PosBase*)_movePosList.front();
CC_SAFE_RETAIN(_curDestPos);
_movePosList.eraseObject(_curDestPos);
void ControllerSimpleMove::moveByPoslist(Vector posList, int speed, int spanTime){
this->_speed =
this->_moveSpan = spanT
if(posList.size() _movePosList.clear();
this->_movePosList = posL
this->_isMoving =
nextMovePos();
}总之可以先从public 成员函数moveByPosList开始看,这里才开始让_isMoving true,然后开始移动一步步移动
接触真正的怪物Monster
enum EnumMonsterPropConfType {
enMonsterPropConf_ID,
enMonsterPropConf_Name,
// 怪物名字
enMonsterPropConf_Level, // 怪物等级
enMonsterPropConf_Type,
// 怪物类型
enMonsterPropConf_ModelID, // 怪物模型ID
enMonsterPropConf_Defense, // 防御力
enMonsterPropConf_Hp,
enMonsterPropConf_Speed, // 移动速度
class Monster : public Entity{
Monster();
~Monster();
static Monster* createFromCsvByID(int monsterID);
bool initFromCsvByID(int monsterID);
//**8**有一个移动的方法,在怪物管理器中调用让其移动
void moveByPosList(Vector posList);
CC_SYNTHESIZE(int,_level,Level);
CC_SYNTHESIZE(float,_showTime,ShowTime);
ControllerSimpleMove* _moveC
};这里也有一个public成员函数,moveByPosList,这是留给在怪物管理器中,让怪物开始活动的函数
Monster::Monster(){
_moveController = NULL;
Monster::~Monster(){
CC_SAFE_RELEASE(_moveController);
Monster* Monster::createFromCsvByID(int monsterID){
Monster* monster = new Monster();
if(monster && monster->initFromCsvByID(monsterID)){
monster->autorelease();
CC_SAFE_DELETE(monster);
bool Monster::initFromCsvByID(int monsterID){
//**8**获得ID
const char* chMonsterID = __String::createWithFormat("%d",monsterID)->getCString();
//**8**绑定精灵
const char* monsterSprite = __String::createWithFormat("sprite/monster/monster_%d.png",monsterID)->getCString();
Sprite* sprite = Sprite::create(monsterSprite);
bindSprite(sprite);
//**8**绑定移动控制器
_moveController = ControllerSimpleMove::create(this);
this->addChild(_moveController);
//**8**属性
CsvUtil* csvUtil = CsvUtil::getInstance();
Size csvSize = csvUtil->getFileRowColNum("csv/Monster.csv");
int line = csvUtil->findValueInWithLine(chMonsterID,enMonsterPropConf_ID,"csv/Monster.csv");
setID(monsterID);
setLevel(csvUtil->getInt(line,enMonsterPropConf_Level,"csv/Monster.csv"));
setModeID(csvUtil->getInt(line,enMonsterPropConf_ModelID,"csv/Monster.csv"));
setDefense(csvUtil->getInt(line,enMonsterPropConf_Defense,"csv/Monster.csv"));
setHP(csvUtil->getInt(line,enMonsterPropConf_Hp,"csv/Monster.csv"));
setSpeed(csvUtil->getInt(line,enMonsterPropConf_Speed,"csv/Monster.csv"));
void Monster::moveByPosList(Vector posList){
if(posList.size() moveByPoslist(posList,2,getSpeed());那么这里的属性什么的都和英雄差不多。。。。
只不过这里需要注意一点点问题,csv/monster.csv要稍微修改:怪物ID 从上到下改为1~5,而不是、或者直接用本次的资源替换。
然后看看怪物管理器,通过plist文件加载怪物信息,update函数管理怪物出现
class MonsterManager : public Node{
MonsterManager();
~MonsterManager();
static MonsterManager* createWithLevel(int curLevel);
bool initWithLevel(int curLevel);
//**8**有多个怪物,每一个的出来的时间递增,用showTime累加,一个个登场
float _showT
//**8**所有的坐标点
Vector _monsterPosL
//**8**没有出场的怪物,一开始所有怪物都没出来
Vector _notShowMonsterL
//**8**配置文件中的所有怪物
Vector _monsterL
//**8**在init 函数中,创建怪物
void createMonsters(int curLevel);
//没有出场怪物数量
int getNotShowMonsterCnt();
//怪物的起始点
PosBase* getMonsterStartPos();
PosBase* getMonsterEndPos();
//**8**展示怪物的update函数
void showMonster(float dt);
};-----------------------------实现:
MonsterManager::MonsterManager(){
_showTime = 0;
MonsterManager::~MonsterManager(){
MonsterManager* MonsterManager::createWithLevel(int curLevel){
MonsterManager* monsterMgr = new MonsterManager();
if(monsterMgr && monsterMgr->initWithLevel(curLevel)){
monsterMgr->autorelease();
CC_SAFE_DELETE(monsterMgr);
return monsterM
bool MonsterManager::initWithLevel(int curLevel){
//**8**根据关卡级别创建怪物
createMonsters(curLevel);
//**8**开启update,让怪物有顺序出现
this->schedule(schedule_selector(MonsterManager::showMonster));
void MonsterManager::createMonsters(int curLevel){
//**8**加载路线坐标
__String* monsterPosPath = __String::createWithFormat("tollgate/monsterPos_level_%d.plist",curLevel);
PosLoadUtil::getInstance()->loadPosWithFile(_monsterPosList,enMonsterPos,monsterPosPath->getCString(),
this,10,false);
//**8**读取当前关卡的怪物配置
__String* monsterConfPath = __String::createWithFormat("tollgate/monster_level_%d.plist",curLevel);
auto monsterConfList = FileUtils::getInstance()->getValueVectorFromFile(monsterConfPath->getCString());
for(auto ref : monsterConfList){
auto temp_map = ref.asValueMap();
int id = temp_map.at("id").asInt();
float showTime = temp_map.at("showTime").asFloat();
if( id != 0 && showTime != 0.0f){
auto monster = Monster::createFromCsvByID(id);
monster->setShowTime(showTime);
monster->setVisible(false);
_monsterList.pushBack(monster);
_notShowMonsterList.pushBack(monster);
this->addChild(monster);
int MonsterManager::getNotShowMonsterCnt(){
return _notShowMonsterList.size();
PosBase* MonsterManager::getMonsterStartPos(){
return _monsterPosList.front();
PosBase* MonsterManager::getMonsterEndPos(){
return _monsterPosList.back();
void MonsterManager::showMonster(float dt){
int notShowMonsterCnt = _notShowMonsterList.size();
if(notShowMonsterCnt > 0){
_showTime +=
PosBase* monsterFirstPos = getMonsterStartPos();
//**8**把本次出场的怪物保存,然后删除,C++中不能在容器遍历的过程中删除,会出错
Vector temp_deletL
for(auto monster : _notShowMonsterList){
if(monster != NULL){
if(_showTime >= monster->getShowTime()){
temp_deletList.pushBack(monster);
monster->setPosition(monsterFirstPos->getPos());
monster->setVisible(true);
monster->moveByPosList(_monsterPosList);
for(auto deletMonster : temp_deletList){
_notShowMonsterList.eraseObject(deletMonster);
}这里可到后面的资源中game/中获取怪物的管理配置文件
---------------------------------------------
然后在MapLayer中添加成员,以及在init函数中把怪物管理加入
_monsterMgr = MonsterManager::createWithLevel(_curLevel);
this->addChild(_monsterMgr);那么最后展示如下,怪物分组出来啦......
三:下次内容
英雄没有尽职,不攻击怪物!!!
----------------------------------
----------------------------------
个人愚昧观点,欢迎指正与讨论
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'

我要回帖

更多关于 武神塔20层灵剑视角 的文章

 

随机推荐