cocos2dx - 生成怪物及AI
2015-12-19 10:55
661 查看
接上一节内容:cocos2dx - tmx地图分层移动处理
本节怪物及简单AI实现
[b]一、怪物[/b]
[b] [/b]同cocos2dx - v2.3.3编辑器骨骼动画 里创建的CPlalyer一样,新建一个CMonster类,也可以提出一个公共基类IEntity,为了以后扩展其他类型的实体做准备。
这里怪物还要有一个AI的实体类CAIModule类。
相对玩家主要添加以下:
同时对移动和攻击进行修改
以上主要在移动和攻击结束的时候调用了AI模块的动作回调。
二、AI模块
本节只是实现最简单的AI机制,直接将策略写在了update中,在间隔一个THINKTIME时间后判断当前最优行动,并执行动作。
如下:
以上直接设定AI执行对象为玩家,在距离小于200执行攻击,否则向玩家节点靠近移动。同时清楚当前 m_nThinkTime时间,在下一个决策时间到来之前怪物会根据动作步骤持续执行当前动作。
所以这里也需要设置一下动作的当前m_nStep为0,同时设置一下执行的函数m_stepFunc。
为了能够在怪物攻击或者移动结束后m_nStep执行到下一步,实现了一个OnActionCallback函数。如下:
这样即可实现简单的AI移动效果,让拥有该AI对象的怪物,不断靠近玩家并且攻击玩家。
CAIModule全代码如下:
View Code
附上实现后的效果图:
1、这是自动朝着玩家走
![](http://images2015.cnblogs.com/blog/311286/201512/311286-20151219105112021-532619819.png)
2、这是在靠近玩家后进行攻击
本节怪物及简单AI实现
[b]一、怪物[/b]
[b] [/b]同cocos2dx - v2.3.3编辑器骨骼动画 里创建的CPlalyer一样,新建一个CMonster类,也可以提出一个公共基类IEntity,为了以后扩展其他类型的实体做准备。
这里怪物还要有一个AI的实体类CAIModule类。
相对玩家主要添加以下:
//init方法中添加如下 m_pAIModule = CAIModule::create(); this->addChild(m_pAIModule);
同时对移动和攻击进行修改
void CMonster::Move(float delta) { if (isFloatZero(delta)) { PlayAction(enAction::ACT_DEFAULT); if (m_pAIModule) { // 移动结束回调 m_pAIModule->OnActionCallback(); } } else { float fspeed = 4; // px/fps float dx = delta; if (isFartherThan(dx, fspeed)) { dx = dx > 0 ? fspeed : -fspeed; } setPositionX(getPositionX() + dx); m_deltaX = delta - dx; PlayAction(ACT_RUN); // 设置当前的方向 setScaleX(delta >0? -1 : 1); } } // 攻击结束动作处理 m_pAction->play("attack", false); std::function<void()> func = [this](){ m_pAction->play("default", true); m_nActType = ACT_DEFAULT; if (m_pAIModule) { // 攻击结束回调 m_pAIModule->OnActionCallback(); } }; m_pAction->setLastFrameCallFunc(func);
以上主要在移动和攻击结束的时候调用了AI模块的动作回调。
二、AI模块
本节只是实现最简单的AI机制,直接将策略写在了update中,在间隔一个THINKTIME时间后判断当前最优行动,并执行动作。
如下:
void CAIModule::update(float dt) { m_nThinkTime += int(dt*1000); if (m_nThinkTime>THINKTIME) { if (CMonster* pMonster = dynamic_cast<CMonster*>(getParent())) { m_stepFunc = nullptr; if (CPlayer* pPlayer = CBattleMgr::getInstance()->GetPlayer()) { if (m_pTarget) { m_pTarget->release(); m_pTarget = nullptr; } m_pTarget = pPlayer; m_pTarget->retain(); m_nStep = 0; m_nThinkTime = 0; float dis = pMonster->getPosition().distance(pPlayer->getPosition()); if (dis <200) { m_stepFunc = std::bind(&CAIModule::Attack, this, std::placeholders::_1, std::placeholders::_2); Attack(pPlayer, m_nStep); //attack } else { m_stepFunc = std::bind(&CAIModule::Move2Node, this, std::placeholders::_1, std::placeholders::_2); Move2Node(pPlayer, m_nStep); //move to pos ; } } } } }
以上直接设定AI执行对象为玩家,在距离小于200执行攻击,否则向玩家节点靠近移动。同时清楚当前 m_nThinkTime时间,在下一个决策时间到来之前怪物会根据动作步骤持续执行当前动作。
所以这里也需要设置一下动作的当前m_nStep为0,同时设置一下执行的函数m_stepFunc。
为了能够在怪物攻击或者移动结束后m_nStep执行到下一步,实现了一个OnActionCallback函数。如下:
void CAIModule::OnActionCallback() { if (m_stepFunc) { ++m_nStep; m_stepFunc(m_pTarget, m_nStep); } }
这样即可实现简单的AI移动效果,让拥有该AI对象的怪物,不断靠近玩家并且攻击玩家。
CAIModule全代码如下:
#ifndef __CAIModule_H__
#define __CAIModule_H__
#include "IGameDef.h"
#include "cocos2d.h"
USING_NS_CC;
class CAIModule : public Node
{
public:
// implement the "static create()" method manually
CREATE_FUNC(CAIModule);
virtual bool init();
void update(float dt);
void OnActionCallback();
private:
void Attack(Node* pEnemy, int step);
void Move2Node(Node* pNode,int step);
CAIModule();
~CAIModule();
int m_nStep; // 当前操作的步骤数
float m_nThinkTime; // 操作的间隔事件
Node* m_pTarget;
std::function<void(Node* node, int step)> m_stepFunc;
};
#endif __CAIModule_H__
#include "AIModule.h"
#include "Monster.h"
#include "BattleMgr.h"
#define THINKTIME (1000) // 决策时间
CAIModule::CAIModule() :m_nThinkTime(THINKTIME), m_pTarget(nullptr), m_stepFunc(nullptr), m_nStep(0)
{
}
CAIModule::~CAIModule()
{
if (m_pTarget)
{
m_pTarget->release();
m_pTarget = nullptr;
}
}
bool CAIModule::init()
{
scheduleUpdate();
return true;
}
void CAIModule::update(float dt) { m_nThinkTime += int(dt*1000); if (m_nThinkTime>THINKTIME) { if (CMonster* pMonster = dynamic_cast<CMonster*>(getParent())) { m_stepFunc = nullptr; if (CPlayer* pPlayer = CBattleMgr::getInstance()->GetPlayer()) { if (m_pTarget) { m_pTarget->release(); m_pTarget = nullptr; } m_pTarget = pPlayer; m_pTarget->retain(); m_nStep = 0; m_nThinkTime = 0; float dis = pMonster->getPosition().distance(pPlayer->getPosition()); if (dis <200) { m_stepFunc = std::bind(&CAIModule::Attack, this, std::placeholders::_1, std::placeholders::_2); Attack(pPlayer, m_nStep); //attack } else { m_stepFunc = std::bind(&CAIModule::Move2Node, this, std::placeholders::_1, std::placeholders::_2); Move2Node(pPlayer, m_nStep); //move to pos ; } } } } }
void CAIModule::Attack(Node* pEnemy, int step)
{
CMonster* pMonster = dynamic_cast<CMonster*>(getParent());
if (!pMonster)
{
return;
}
switch (step)
{
case 0:
{
if (!pEnemy)
{
return;
}
// 立即攻击
if (isFartherThan(pMonster->getPositionX() < pEnemy->getPositionX(), 30))
{
Attack(pEnemy,1);
}
else
{
// 太近,移动远一点
m_nStep =1;
Move2Node(pEnemy,0);
}
}
break;
case 1:
{
if (!pEnemy)
{
return;
}
// 调整方向准备攻击
pMonster->setScaleX(pMonster->getPositionX() < pEnemy->getPositionX() ? -1 : 1);
++m_nStep;
std::function<void()> func = [this]()
{
Attack(nullptr,2);
};
this->runAction(Sequence::create(DelayTime::create(0.3), CallFunc::create(func), NULL));
}
break;
case 2:
{
// 直接攻击
pMonster->Attack();
}
break;
default:
// m_nThinkTime = THINKTIME;
break;
}
}
void CAIModule::Move2Node(Node* pNode, int step)
{
if (!pNode)
{
return;
}
CMonster* pMonster = dynamic_cast<CMonster*>(getParent());
if (!pMonster)
{
return;
}
switch (step)
{
case 0:
{
if (pMonster->getPositionX() < pNode->getPositionX())
{
pMonster->Move(pNode->getPositionX() - 50 - pMonster->getPositionX());
}
else
{
pMonster->Move(pNode->getPositionX() + 50 - pMonster->getPositionX());
}
}
break;
default:
// m_nThinkTime = THINKTIME;
break;
}
}
void CAIModule::OnActionCallback() { if (m_stepFunc) { ++m_nStep; m_stepFunc(m_pTarget, m_nStep); } }
View Code
附上实现后的效果图:
1、这是自动朝着玩家走
![](http://images2015.cnblogs.com/blog/311286/201512/311286-20151219105112021-532619819.png)
2、这是在靠近玩家后进行攻击
![](http://images2015.cnblogs.com/blog/311286/201512/311286-20151219105300099-766641566.png)
相关文章推荐
- windows下打包cocos2d-x之自动复制第三方so文件
- cocos2d-js添加百度MSSP插屏(通过jsb反射机制)
- cocos2d-x 2.x版本接入bugly的总结
- cocos2dx 读取rapidjson及解析
- cocos2d-x 音乐/音效设置
- cocos2d-x 3.x LuaBinding之LUA_FUNCTION(只为记录)
- Cocos2dx项目移植Android平台
- cocos2d-x TestLua 之 CCMenuItemLabel CCMenuItemSprite CCMenuItemFont 菜单类
- Cocos2d-x v3.9发布
- cocos2dx之UserDefault: 数据存储及加密 (上)
- Cocos2d-x优化中纹理优化
- cocos2dx
- CocosBuilder使用总结
- Cocos2dx 3.0 交流篇
- Quick-Cocos2d-x3.3配置文件分析
- cocos2d-x之动作类说明
- Cocos2d-x应用:保存背景音乐和音效设置
- quick-cocos2d-x开发工具sublime text及其强力插件QuickXDev
- 在cocos2d-x中动态绘制二维码
- cocos2d-js 在Chrome的最小字体