Cocos3.4 横版游戏制作-《KillBear》-添加敌人+简单AI实现

前端之家收集整理的这篇文章主要介绍了Cocos3.4 横版游戏制作-《KillBear》-添加敌人+简单AI实现前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。
资源为网上寻找的,仅研究学习用,若是侵犯版权请通知本人整改。


上一篇: Cocos3.4 横版游戏制作-《KillBear》-添加血条 攻击按键
上篇在状态层加入了血条,并添加了一个攻击按键
本篇将在前面的基础上添加敌人,并通过有限状态机(FSM)实现简单的AI


开发环境

win64 : vs2010
Cocos2d-x v3.4Final
TexturePackerGUI
MapEdit


代码A

角色Role

Enemy

创建一个继承基础Role类,作为敌人.

  • .h
@H_403_30@typedef enum { AI_IDLE = 0,AI_PATROL,AI_ATTACK,AI_PURSUIT }AiState;

作为AI类型

其他的代码和Hero大同小异

@H_403_30@public: Enemy(); ~Enemy(); bool init(); void updateSelf(); CREATE_FUNC(Enemy); CC_SYNTHESIZE(cocos2d::Vec2,m_moveDirection,MoveDirection); CC_SYNTHESIZE(float,m_eyeArea,EyeArea); CC_SYNTHESIZE(float,m_attackArea,AttackArea) CC_SYNTHESIZE(AiState,m_aiState,AiState); private: void decide(const cocos2d::Vec2& target,float targetBodyWidth); void execute(const cocos2d::Vec2& target,float targetBodyWidth); unsigned int m_nextDecisionTime;

由于敌人是AI,我们要给它设定一些区域,视野,最大攻击判定区,AI状态等.

  • .cpp

init类似

@H_403_30@Animation *idleAnim = this->createNomalAnimation("bear_idle_%02d.png",3,6); this->setIdleAction(RepeatForever::create(Animate::create(idleAnim))); ...

然后是类似Hero的自更新函数updateSelf刷新自己状态

@H_403_30@void Enemy::updateSelf() { //this->execute(global->hero->getPosition() + global->hero->getBodyBox().actual.origin,global->hero->getBodyBox().actual.size.width); this->execute(global->hero->getPosition(),global->hero->getBodyBox().actual.size.width);//对象坐标及body宽度 if(this->getCurrActionState() == ACTION_STATE_WALK) { Vec2 location = this->getPosition(); Vec2 direction = this->getMoveDirection(); Vec2 expectP = location + direction; float maptileHeight = global->tileMap->getTileSize().height; //if(expectP.y<0 || !global->tileAllowMove(expectP)) //这群笨蛋AI总跑出地图报错.后续再去改进吧 if(expectP.y < 0 || expectP.y > maptileHeight * 3 ) { direction.y =0; } this->setFlippedX(direction.x < 0 ? true : false); this->setPosition(location + direction); this->updateBoxes(); this->setLocalZOrder(this->getPositionY()); } if(this->getCurrActionState() == ACTION_STATE_NOMAL_ATTACK_A) { this->runNomalAttackA(); } }

之后我们给它一个执行延时,这是为了防止过快判断,判读的太过频繁不止给cpu压力,还会使效果出现问题.比如我们的敌人死追着Hero不放,撞了墙还在向着Hero的方向执行动画等.

@H_403_30@void Enemy::execute(const Vec2& target,float targetBodyWidth) { if(m_nextDecisionTime == 0)//lazy延时到0执行下一个动作判定 { this->decide(target,targetBodyWidth); }else { -- m_nextDecisionTime; } }

接下来通过FSM设定敌人的AI

@H_403_30@void Enemy::decide(const Vec2& target,float targetBodyWidth) { //Vec2 location = this->getPosition()+ this->getBodyBox().actual.origin;//获得自己的身体中心的坐标 Vec2 location = this->getPosition();//获得脚下坐标 float distance = location.getDistance(target);//与对象Body的距离 distance = distance - targetBodyWidth / 2;//距离范围应该减去body宽度 bool isFlippedX = this->isFlippedX(); bool isOnTargetLeft = (location.x < target.x ? true : false);//方向判定 if((isFlippedX && isOnTargetLeft) || (!isFlippedX && !isOnTargetLeft)) { this->m_aiState = CCRANDOM_0_1() > 0.5f ? AI_PATROL : AI_IDLE; }else { if(distance < m_eyeArea) { this->m_aiState = (distance < m_attackArea)&&((fabsf(location.y - target.y) < 15)) ? AI_ATTACK : AI_PURSUIT; }else { this->m_aiState = CCRANDOM_0_1() > 0.5f ? AI_PATROL : AI_IDLE; } } switch(m_aiState) { case AI_ATTACK: { this->runNomalAttackA(); //this->attack(); this->m_nextDecisionTime = 50; } break; case AI_IDLE: { this->runIdleAction(); this->m_nextDecisionTime = CCRANDOM_0_1() * 100; } break; case AI_PATROL: { this->runWalkAction(); this->m_moveDirection.x = CCRANDOM_MINUS1_1(); this->m_moveDirection.y = CCRANDOM_MINUS1_1(); m_moveDirection.x = m_moveDirection.x > 0 ? (m_moveDirection.x + velocity.x) : (m_moveDirection.x -velocity.x); m_moveDirection.y = m_moveDirection.y > 0 ? (m_moveDirection.y +velocity.y) : (m_moveDirection.y -velocity.y); this->m_nextDecisionTime = CCRANDOM_0_1() * 100; } break; case AI_PURSUIT: { this->runWalkAction(); this->m_moveDirection = (target - location).getNormalized(); this->setFlippedX(m_moveDirection.x < 0 ? true : false); m_moveDirection.x = m_moveDirection.x > 0 ? (m_moveDirection.x +velocity.x) : (m_moveDirection.x -velocity.x); m_moveDirection.y = m_moveDirection.y > 0 ? (m_moveDirection.y +velocity.y) : (m_moveDirection.y -velocity.y); this->m_nextDecisionTime = 10; } break; } }

distance是为了判断这个敌人和目标Body之间的距离.

下面是几个AI的判断,里面用到几个宏是随机一个数,更真实的表现敌人.

  • Attack,攻击,每次攻击延时50
  • Idle,发呆,延时随机一个0-1的数字*100
  • Patrol,巡逻,延时时间也似随机出来的
  • Pursuit,追击,当发现Hero追击的判断

主要的AI是:

  • 目标出现在正前方?(根据视野范围)发呆or巡逻
  • 是否在攻击范围内?(根据攻击范围)追击or攻击


这个图片更好理解下


接下来在GameLayer加入他们
我们每次加入多个敌人,方便起见需要使用数组来实现它(链表更好)

Game

GameLayer

  • .h
@H_403_30@#include "Enemy.h" ... void addEnemies(int number); void updateEnemies(float dt); __Array *m_pEnemies;

实现addEnemies,一次加入多个敌人通过这个数组创建.最后别忘了将这个数组注册到Global,下一章做攻击判断用

  • .cpp
@H_403_30@void GameLayer::addEnemies(int number) { m_pEnemies = __Array::createWithCapacity(number); m_pEnemies->retain(); for(int i=0;i<number;i++) { Enemy *pEnemy = Enemy::create(); pEnemy->setPosition(Vec2( random(_visibleSize.width/2,_visibleSize.width),70 )); pEnemy->runIdleAction(); pEnemy->setLocalZOrder(_visibleSize.height - pEnemy->getPositionY()); //属性设置 pEnemy->setVelocity(Vec2(0.5f,0.5f)); pEnemy->setEyeArea(300); pEnemy->setAttackArea(80); pEnemy->setDamageStrenth(5); pEnemy->setSumLifeValue(100); pEnemy->setCurtLifeValue(m_pHero->getSumLifeValue()); m_pEnemies->addObject(pEnemy); this->addChild(pEnemy,0); } global->enemies= m_pEnemies; }

init中

@H_403_30@this->addEnemies(5);

结果图A

我们看到了几个敌人呆立在地图中.(截图帧数问题,刚好每次敌人都没动)

由于我们没有刷新敌人的状态,敌人是不会动的.

继续添加刷新敌人的代码

@H_403_30@void GameLayer::updateEnemies(float dt) { Ref *Obj = NULL; Vec2 distance = Vec2::ZERO; CCARRAY_FOREACH(m_pEnemies,Obj)//遍历所有的怪物 { Enemy *pEnemy = (Enemy*)Obj; pEnemy->updateSelf();//自更新状态 //如果死了就移除他们 if(pEnemy->getDeadAction()->isDone()) m_pEnemies->removeObject(pEnemy); } }

跟新update方法

@H_403_30@void GameLayer::update(float dt) { this->updateHero(dt); this->updateEnemies(dt); }

结果B

他们开始乱跑和执行攻击动画了

ok,我们已经达到了想要的效果

结论

本片实现了添加多个敌人,并给敌人设定简单的AI让其何以自动随机巡逻或者追击或是攻击Hero. 但是目前只有各种动画,没有实现攻击判定. 下一章我们通过攻击判定,让Hero或者是Enemy受伤,生命到底还会死亡.具体的属性比如生命值,攻击力之类的.参阅上面的代码

猜你在找的Cocos2d-x相关文章