Cocos2d-x格斗小游戏(八) 简单的机器人AI

1、AI即Artificial Intelligence(人工智能),因为我们的这个游戏如果机器人只是站在那儿让玩家攻击,游戏的趣味性会很低。因此,我们希望机器人也能够自动地执行一些动作,譬如像玩家精灵移动,攻击玩家精灵等等。要实现这些动作,需要一个简单的AI逻辑,来确定机器人的动作序列。


2、前面我们已经将玩家精灵和机器人的5个动作都实现了,现在在计时器的update函数中写一个简单的AI函数,用于确定机器人在某一时间段内的动作(为增加可变性,配合随机数效果更好)。


3、下面贴出这个函数以及游戏结束的处理函数:

void GameBasicLayer::updateRobots(float dt)
{
	int alive = 0;
	float distanceSQ;
	int randomChoice = 0;
	CCObject *pObject = NULL;
	CCARRAY_FOREACH(_spriteRobot, pObject)
	{
		SpriteRobot *pRobot = (SpriteRobot*)pObject;
		pRobot->update(dt);
		if (pRobot->getSpriteState() != STATE_DEAD)
		{
			//1
			alive++;

			//2
			if (CURTIME> pRobot->getNextDecisionTime())
			{
				distanceSQ = ccpDistanceSQ(pRobot->getPosition(), _spritePlayer->getPosition());

				//3
				if (distanceSQ <= 50 * 50)
				{
					pRobot->setNextDecisionTime(CURTIME + frandom_range(0.1, 0.5) * 1000);
					randomChoice = random_range(0, 1);

					if (randomChoice == 0)
					{
						if (_spritePlayer->getPosition().x > pRobot->getPosition().x)
						{
							pRobot->setScaleX(1.0);
						} 
						else
						{
							pRobot->setScaleX(-1.0);
						}

						//4
						pRobot->setNextDecisionTime(pRobot->getNextDecisionTime() + frandom_range(0.1, 0.5) * 2000);
						pRobot->Attack();						
						if (pRobot->getSpriteState() == STATE_ATTACK)
						{
							if (fabsf(_spritePlayer->getPosition().y - pRobot->getPosition().y) < 10)
							{
								if (_spritePlayer->getCollosionDetectionRect().bodyRect.intersectsRect(pRobot->getCollosionDetectionRect().punchesRect))
								{
									_spritePlayer->Hurt_WithDamage(pRobot->getOnceDamage());

									// progressBar changed(Hero)
									//float cu = _spritePlayer->getProbressBar()->getPercentage();  
									//cu = cu + pRobot->getDamage();  
									//_spritePlayer->getProbressBar()->setPercentage(cu);  


									//end game checker here
									if (_spritePlayer->getSpriteState() == STATE_DEAD && _directionConSpLayer->getChildByTag(5) == NULL)
									{
										this->endGame();
									}
								}
							}
						}
					}
					else
					{
						pRobot->Normal();
					}
				}
				else if (distanceSQ <= SCREEN.width * SCREEN.width)
				{
					//5
					pRobot->setNextDecisionTime(CURTIME + frandom_range(0.5, 1.0) * 1000);
					randomChoice = random_range(0, 2);
					if (randomChoice == 0)
					{
						CCPoint moveDirection = ccpNormalize(ccpSub(_spritePlayer->getPosition(), pRobot->getPosition()));
						pRobot->Walk_WithDirection(moveDirection);
					} 
					else
					{
						pRobot->Normal();
					}
				}
			}
		}
	}

	//end game checker here
	if (alive == 0 && _directionConSpLayer->getChildByTag(5) == NULL)
	{
		this->endGame();
	}
}

void GameBasicLayer::endGame()
{
	CCLabelTTF *restartLabel = CCLabelTTF::create("RESTART", "Arial", 30);
	CCMenuItemLabel *restartItem = CCMenuItemLabel::create(restartLabel, this, menu_selector(GameBasicLayer::restartGame));
	CCMenu *menu = CCMenu::create(restartItem, NULL);
	menu->setPosition(CENTER);
	menu->setTag(5);
	_directionConSpLayer->addChild(menu, 5);
}

void GameBasicLayer::restartGame(cocos2d::CCObject* pSender)
{
	CCDirector::sharedDirector()->replaceScene(GamePlayScene::create());
}


4、另外,将一些反复使用的量定义在GameDefines.h中:

#pragma once
#include "cocos2d.h"


// 精灵状态
enum SpriteState
{
	STATE_NORMAL,
	STATE_WALK,
	STATE_ATTACK,
	STATE_HURT,
	STATE_DEAD
};


typedef struct _SurroundRect
{
	cocos2d::CCRect bodyRect;      // 身体的矩形区域
	cocos2d::CCRect punchesRect;   // 出拳的矩形区域
}SurroundRect;


#define SCREEN CCDirector::sharedDirector()->getWinSize()
#define CENTER ccp(SCREEN.width / 2, SCREEN.height / 2)
#define CURTIME GetCurTime()
inline float GetCurTime(){
	timeval time;
	gettimeofday(&time, NULL);
	unsigned long millisecs = (time.tv_sec * 1000) + (time.tv_usec / 1000);
	return (float)millisecs;
};



#ifndef UINT64_C
#define UINT64_C(val) val##ui64
#endif
#define random_range(low, high) (rand() % (high - low + 1)) + low
#define frandom (float)rand() / UINT64_C(0x100000000)
#define frandom_range(low, high) ((high - low) * frandom) + low


5、至此,这个游戏大体框架已经基本完成,由于是一块一块写的,而且还没有在全局上优化整合过,所以代码比较粗糙。


6、游戏开发到这一步,其实只算是完成了20%的工作,后面的优化性能以及客户体验是重中之重。


7、另外,关于后续功能的几点建议:

(1)背景音乐,游戏音效;

(2)添加血量条;

(3)添加游戏开始时的选择菜单(包括开始新游戏,游戏选项,帮助等内容);


8、因为最近时间比较紧,所以这个游戏暂时可能就到此为止了,因为源码比较乱,所以暂时不上传了。等我整理后在追加在本文后面。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值