懒骨头(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游戏开发系列笔记10:解刨《战神传说》

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游戏开发环境搭建

-------------------- 飞船降落--------------------

最后,骨头介绍一下陪在身边的哲哲(右边就是低调的哲哲)

哲哲,小名 YIYI ,手工爱好者,文艺范,手艺人,《YiYiの妙舍》创始人,很有自己想法。

Cocos2dx游戏开发系列笔记13:一个横版拳击游戏Demo完结篇的更多相关文章

  1. (译)【Unity教程】使用Unity开发Windows Phone上的横版跑酷游戏

    译者注: 目前移动设备的跨平台游戏开发引擎基本都是采用Cocos2d-x或者Unity.一般而言2d用cocos2d-x 3d用unity,但是对于Windows Phone开发者, cocos2d- ...

  2. 《MFC游戏开发》笔记六 图像双缓冲技术:实现一个流畅的动画

    本系列文章由七十一雾央编写,转载请注明出处.  http://blog.csdn.net/u011371356/article/details/9334121 作者:七十一雾央 新浪微博:http:/ ...

  3. 《Genesis-3D开源游戏引擎--横版格斗游戏制作教程:简介及目录》(附上完整工程文件)

    介绍:讲述如何使用Genesis-3D来制作一个横版格斗游戏,涉及如何制作连招系统,如何使用包围盒实现碰撞检测,软键盘的制作,场景切换,技能读表,简单怪物AI等等,并为您提供这个框架的全套资源,源码以 ...

  4. [置顶] 《MFC游戏开发》笔记一 系列简介

    本系列文章由七十一雾央编写,转载请注明出处.  http://blog.csdn.net/u011371356/article/details/9299121 作者:七十一雾央 新浪微博:http:/ ...

  5. 《MFC游戏开发》笔记十 游戏中的碰撞检测进阶:地图类型&障碍物判定

    本系列文章由七十一雾央编写,转载请注明出处. http://blog.csdn.net/u011371356/article/details/9394465 作者:七十一雾央 新浪微博:http:// ...

  6. 《MFC游戏开发》笔记九 游戏中的碰撞判定初步&怪物运动简单AI

    本系列文章由七十一雾央编写,转载请注明出处. http://blog.csdn.net/u011371356/article/details/9374935 作者:七十一雾央 新浪微博:http:// ...

  7. 《MFC游戏开发》笔记八 游戏特效的实现(二):粒子系统

    本系列文章由七十一雾央编写,转载请注明出处. http://blog.csdn.net/u011371356/article/details/9360993 作者:七十一雾央 新浪微博:http:// ...

  8. 《MFC游戏开发》笔记七 游戏特效的实现(一):背景滚动

    本系列文章由七十一雾央编写,转载请注明出处. http://blog.csdn.net/u011371356/article/details/9344721 作者:七十一雾央 新浪微博:http:// ...

  9. 《MFC游戏开发》笔记五 定时器和简单动画

    本系列文章由七十一雾央编写,转载请注明出处. http://blog.csdn.net/u011371356/article/details/9332377 作者:七十一雾央 新浪微博:http:// ...

随机推荐

  1. sqlserver查询某一字段重复超5次的所有记录

    用的sqlserver2008 r2. SELECT  * FROM t_class WHERE id IN (SELECT  id FROM (SELECT  ROW_NUMBER() OVER ( ...

  2. 出现java.lang.NoSuchFieldException resourceEntries错误的解决方法

    JSP表单里面的表单输入<input type= "text" name="user">这里面的每一个输入都是一个Attribute,相当于setA ...

  3. 关于MySQL MyISAM 表并发

    MyISAM的锁调度 MyISAM存储引擎的读锁和写锁是互斥的,读写操作是串行的.那么,一个进程请求某个MyISAM表的读锁,同时另一个进程也请求同一表的写锁,MySQL如何处理呢?答案是写进程先获得 ...

  4. 关于wireshark的两个抓包过滤显示的基本语法

    关于wireshark的两个基本语法 关于wireshark的两个基本语法 1. Capture Filters 语法:<Protocol name><Direction>&l ...

  5. js解决click事件点击事件间隔方法

    var myTimeout = null; $("#id").click(function(){ clearTimeout(myTimeout); myTimeout = setT ...

  6. 学习笔记(一) HTML+CSS基础课程

    这个周把慕课网的<HTML+CSS基础课程>课程学完,内容都是非常非常基础的,不过还是学到了几个小知识点,记下来先. <a>超链接发送邮件 直接上把他的图片给挪过来了,我就不打 ...

  7. Android 获取有规律资源Id解决方案

    在多个有规律的资源ID获取的时候,可以使用getIdentifier方法来获取,来获取. 用到场景:工具类打成.jar包的时候,有时候会需要引用到res中的资源,这时候不能将资源一起打包,只能通过反射 ...

  8. JS中格式化数据保留两位小数

    问题:在JS中格式化数据保留两位小数的函数的多种方法 最好方法: 保留两位好像是这样吧     var   a   =   9.39393;     alert(a.toFixed(2)); 说明: ...

  9. js/jQuery实现复制到剪贴板功能,兼容所有浏览器

    因为工作的原因,需要实现这样一个功能:点击按钮,复制文本内容. 百度了一下,大都语焉不详,最终找到了一篇很好的博文,有讲解,有实例,捣鼓了一会,最终实现了功能. 网址在这里http://www.cnb ...

  10. 在Win7的IIS上搭建FTP服务及用户授权——转载!!

    原文地址:http://blog.sina.com.cn/s/blog_6cccb1630100q0qg.html FTP服务 FTP是文件传输协议(File Transfer Protocol)的简 ...