懒骨头(http://blog.csdn.net/iamlazybone QQ:124774397 )
写下这些东西的同时
旁边放了两部电影
周星驰的《还魂夜》
甄子丹的《特殊身份》
骨头听着电影读代码
别有一番风味
接上篇,今天继续看一下这个demo。
----------------------------------------------------------------------------------------------------------------------------------------------------------
GameScene.cpp类。
----------------------------------------------------------------------------------------------------------------------------------------------------------
这个类里主要有两层,上层是控制层:HudLayer,下层是游戏层:GameLayer
init初始化方法里有个输入更新函数:
this->schedule(schedule_selector(GameScene::inputUpdate));
void GameScene::inputUpdate(float dt) { CCPoint velocity = mHudLayer->mJoystick->getVelocity(); //std::cout << velocity.x << std::endl; if (velocity.x >= 0.4f || velocity.x <= -0.4f || velocity.y >= 0.4f || velocity.y <= -0.4f) { mGameLayer->mHero->walkWithDirection(velocity); } else if (mGameLayer->mHero->mActionState == kActionStateWalk) { mGameLayer->mHero->idle(); } if (attackInterval <= 0.0f) { if (mHudLayer->mButtonA->getIsActive()) { mGameLayer->mHero->attack(); attackInterval = 0.5f; if (mGameLayer->mHero->mActionState == kActionStateAttack) { CCObject* item; CCARRAY_FOREACH(mGameLayer->mRobots, item) { Robot* robot = dynamic_cast<Robot*>(item); if (robot->mActionState != kActionStateKnockedOut) { if (fabs(mGameLayer->mHero->getPositionY() - robot->getPositionY()) < 10) { //std::cout << "yew" << std::endl; if (mGameLayer->mHero->mAttackBox.actual.intersectsRect(robot->mHitBox.actual)) { robot->hurtWithDamage(mGameLayer->mHero->mDamage); //std::cout << "yew!!!!!!!!!!!!" << std::endl; } } } } } } } else { attackInterval -= dt; } }
通过Joystick虚拟摇杆获取速度
CCPoint velocity = mHudLayer->mJoystick->getVelocity();
如果x,y两个方向的速度大于0.4的话,主角移动。
否则,主角原地不动。
继续判断
如果攻击按钮被按下,则主角进行攻击。
if (mHudLayer->mButtonA->getIsActive())
mGameLayer->mHero->attack();
此时,遍历所有的robot机器人,看我们的主角击中了哪个robot,
击中的那个(矩形相交),调用受伤方法
robot->hurtWithDamage(mGameLayer->mHero->mDamage);
----------------------------------------------------------------------------------------------------------------------------------------------------------
GameLayer 主要逻辑类
----------------------------------------------------------------------------------------------------------------------------------------------------------
class GameLayer : public CCLayer { public : GameLayer(); bool init(); CCTMXTiledMap* mTileMap; void initTileMap(); void initHero(); Hero* mHero; CCSpriteBatchNode* mActors; void update(float dt); void updatePosition(float dt); void setViewpointCenter(CCPoint position); CCArray* mRobots; void initRobots(); void reorderActors(); void updateRobots(float dt); };
这个类里有瓦片地图类: CCTMXTiledMap
有主角和初始化方法:Hero* ,initHero
有更新方法:void update(float dt),void updatePosition(float dt)
一一看来
初始化机器人方法:
void GameLayer::initRobots() { int robotCount = 50; this->mRobots = new CCArray(robotCount); for (int i = 0; i < robotCount; ++i) { Robot* robot = new Robot(); //mActors->addChild(robot); this->addChild(robot); mRobots->addObject(robot); int minX = SCREEN.width + robot->mCenterToSide; int maxX = mTileMap->getMapSize().width * mTileMap->getTileSize().width - robot->mCenterToSide; int minY = robot->mCenterToBottom; int maxY = 3 * mTileMap->getTileSize().height + robot->mCenterToBottom; if (rand() % 2) robot->setFlipX(true); robot->setPosition( ccp(random_range(minX, maxX), random_range(minY, maxY))); robot->mDesiredPosition = robot->getPosition(); robot->idle(); } }
new一个Robot类,放到CCArray数组里。
然后定义机器人的活动范围:即xy的最大值最小值
如图:机器人最早出现的x位置是第二屏最近的位置,即
SCREEN.width + robot->mCenterToSide; // mCenterToSide 半个机器人宽度
最远是的位置是地图的最后边:
mTileMap->getMapSize().width * mTileMap->getTileSize().width - robot->mCenterToSide;
即 :tile的个数Xtile的宽度-机器人半个宽度
最高和最低也是同理。
然后在这个范围内随机放50个机器人。
重新排序方法 reorderActors:
void GameLayer::reorderActors() { CCObject* item; //CCARRAY_FOREACH(mActors->getChildren(), item) CCARRAY_FOREACH(this->getChildren(), item) { CCNode *node = dynamic_cast<CCNode *>(item); if (node->getTag() == ACTION_SPRITE_TAG) { ActionSprite *sprite = dynamic_cast<ActionSprite *>(item); this->reorderChild(sprite, mTileMap->getMapSize().height * mTileMap->getTileSize().height - sprite->getPositionY()); } } }
循环所有的CCSprite,从新计算z轴,来修正遮挡关系。
更新机器人方法:void GameLayer::updateRobots(float dt)
if (robot->mActionState != kActionStateKnockedOut) { ++alive; robot->mNextDecisionTime -= dt; if (robot->mNextDecisionTime <= 0.0f) { distanceSQ = ccpDistanceSQ(robot->getPosition(), mHero->getPosition()); if (distanceSQ <= 50*50) { robot->mNextDecisionTime = frandom_range(0.5f, 1.0f, 0.1f); randomChoice = random_range(0, 1); if (randomChoice == 0) { if (mHero->getPositionX() > robot->getPositionX()) { robot->setFlipX(false); } else { robot->setFlipX(true); } robot->attack(); if (robot->mActionState == kActionStateAttack) { if (fabs(mHero->getPositionY() - robot->getPositionY()) < 10) { if (mHero->mHitBox.actual.intersectsRect(robot->mAttackBox.actual)) { mHero->hurtWithDamage(robot->mDamage); } } } } else { robot->idle(); } } else if (distanceSQ <= SCREEN.width * SCREEN.width) { robot->mNextDecisionTime = frandom_range(1.0f, 1.5f, 0.1f); robot->mNextDecisionTime = random_range(5, 10) * 0.1f; randomChoice = random_range(0, 2); if (randomChoice == 0) { CCPoint moveDirection = ccpNormalize(ccpSub(mHero->getPosition(), robot->getPosition())); robot->walkWithDirection(moveDirection); } else { robot->idle(); } } }
这个方法大体流程是:
如果机器人还没死,就看看到没到行动时间,到时间了,就计算下机器人和主角之前的距离:
distanceSQ = ccpDistanceSQ(robot->getPosition(), mHero->getPosition());
如果主角在机器人左边,机器人向左走,反之,向右边走:
if (mHero->getPositionX() > robot->getPositionX()) { robot->setFlipX(false);
机器人进入攻击状态,检测下主角是否在机器人的攻击范围内:
if (mHero->mHitBox.actual.intersectsRect(robot->mAttackBox.actual)) {
如果离的远了,就往主角那走:
robot->walkWithDirection(moveDirection);
定位到地图中心
void GameLayer::setViewpointCenter(CCPoint position) { CCSize winSize = CCDirector::sharedDirector()->getWinSize(); int x = GetMAX(position.x, winSize.width / 2); int y = GetMAX(position.y, winSize.height / 2); x = GetMIN(x, (mTileMap->getMapSize().width * mTileMap->getTileSize().width - winSize.width / 2)); y = GetMIN(y, (mTileMap->getMapSize().height * mTileMap->getTileSize().height - winSize.height / 2)); CCPoint actualPosition = ccp(x, y); CCPoint centerOfView = ccp(winSize.width / 2, winSize.height / 2); CCPoint viewPoint = ccpSub(centerOfView, actualPosition); this->setPosition(viewPoint); }
如果主角往右走,如果此时移动到地图中心,那么主角保持在地图的中心,但是地图往左移动。
然后让整个地图向左移动,来表现主角向右走。this->setPosition(viewPoint);
更新位置方法
void GameLayer::updatePosition(float dt) { float posX = GetMIN(mTileMap->getMapSize().width * mTileMap->getTileSize().width - mHero->mCenterToSide, GetMAX(mHero->mCenterToSide, mHero->mDesiredPosition.x)); float posY = GetMIN(3 * mTileMap->getTileSize().height + mHero->mCenterToBottom, GetMAX(mHero->mCenterToBottom, mHero->mDesiredPosition.y)); //std::cout << mHero->mDesiredPosition.x << std::endl; mHero->setPosition(ccp(posX, posY)); CCObject* item; CCARRAY_FOREACH(mRobots, item) { Robot* robot = dynamic_cast<Robot*>(item); posX = GetMIN(mTileMap->getMapSize().width * mTileMap->getTileSize().width - robot->mCenterToSide, GetMAX(robot->mCenterToSide, robot->mDesiredPosition.x)); posY = GetMIN(3 * mTileMap->getTileSize().height + robot->mCenterToBottom, GetMAX(robot->mCenterToBottom, robot->mDesiredPosition.y)); robot->setPosition(ccp(posX, posY)); } this->setViewpointCenter(mHero->getPosition()); }
其实就是常见的2D卷轴算法,不过看起来确实费劲。
注释掉机器人的攻击方法,然后在游戏中跑一跑,看看主角的可移动范围。
GetMAX(mHero->mCenterToSide, mHero->mDesiredPosition.x) 这句的意思是:
比如英雄往左边走,他能走的左的距离是mCenterToSide,也就是半个宽度,也就是
float posX 是通过GetMIN取得的,他限制了你不能超过整个tile地图的最后边。
然后把这个合法的 xy设置到hero上。
呼呼,简简单单的分析了下游戏的主要代码。
还有个Sneaky包暂时忽略,骨头打算另开笔记学习虚拟遥控杆。
CCTMXTiledMap 相关的也是重点,这个等以后研究工具的时候好好看看。
明天就是周五了,离周末越来越近了。倍感欣慰啊。
准备休息。
------------------- 飞船起飞--------------------
Cocos2dx游戏开发系列笔记11:解刨《战神传说》完结篇
Cocos2dx游戏开发系列笔记9:android手机上运行《战神传说》,并解决横竖屏即分辨率自适应问题
Cocos2dx游戏开发系列笔记8:开搞一个射击游戏《战神传说》//就个打飞机的
Cocos2dx游戏开发系列笔记7:一个简单的跑酷游戏《萝莉快跑》的消化(附下载)
Cocos2dx游戏开发系列笔记6:怎样让《萝莉快跑》的例子运行在vs和手机上
Cocos2dx游戏开发系列笔记5:继续润色《忍者飞镖射幽灵》
Cocos2dx游戏开发系列笔记4:怎样新加一个Scene类?
Cocos2dx游戏开发系列笔记3:牛刀小试->忍者飞镖射幽灵的Demo
Cocos2dx游戏开发系列笔记2:一个刚创建的cocos2dx中的demo里都有什么
Cocos2dx游戏开发系列笔记1:一个崭新的开始,cocos2dx2.2+ndkr9+Cygwin+vs2012游戏开发环境搭建
-------------------- 飞船降落--------------------