转载请注明,原文地址: http://www.benmutou.com/archives/30
文章来源:笨木头与游戏开发

Cocos2d-x游戏实例-《跑跑跑》制作教程(第四篇)——地图卷动

 

笨木头花心贡献,啥?花心?不呢,是用心~ 转载请注明,原文地址 http://www.benmutou.com/archives/30

正文:

注:本文使用到的资源请到这里下载:http://download.csdn.net/detail/musicvs/4769412

上一篇我们已经把我们跑的主题体现出来了,但是,主角跑没多久就离开地图了,也离开屏幕了,这不靠谱啊喂,我们得让地图也动起来(难道我做这么长的地图是摆设么~)。

 

1. 地图卷动规则

首先要定一个规则,地图怎么卷动?我们定义为这样,地图只会横向往左卷动,当主角超过屏幕中点的时候地图就开始卷动。最终的效果应该是这样的:

《跑跑跑》制作教程(第4篇)截图

留意最左边,地图最左边已经有部分没有显示出来了,证明地图已经往左移动了一小段距离。

 

2. 触发卷动

我们在主角坐标改变的时候就判断是否需要移动地图,来,我们给Player类增加一个函数:

[cce_cpp]void Player::setViewPointByPlayer() { if(mSprite == NULL) { return; } CCLayer* parent = (CCLayer* )mSprite->getParent();

/* 地图方块数量 */ CCSize mapTiledNum = map->getMapSize();

/* 地图单个格子大小 */ CCSize tiledSize = map->getTileSize();

/* 地图大小 */ CCSize mapSize = CCSize::CCSize( mapTiledNum.width * tiledSize.width, mapTiledNum.height * tiledSize.height);

/* 屏幕大小 */ CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();

/* 精灵的坐标 */ CCPoint spritePos = mSprite->getPosition();

/* 如果精灵坐标小于屏幕的一半,则取屏幕中点坐标,否则取精灵的坐标 */ float x = max(spritePos.x, visibleSize.width / 2); float y = max(spritePos.y, visibleSize.height / 2);

/* 如果x、y的坐标大于右上角的极限值,则取极限值的坐标(极限值是指不让地图超出屏幕造成出现黑边的极限坐标) */ x = min(x, mapSize.width - visibleSize.width / 2); y = min(y, mapSize.height - visibleSize.height / 2);

CCPoint destPos = CCPoint::CCPoint(x, y); CCPoint centerPos = CCPoint::CCPoint(visibleSize.width / 2, visibleSize.height / 2);

/* 计算屏幕中点和所要移动的目的点之间的距离 */ CCPoint viewPos = ccpSub(centerPos, destPos);

parent->setPosition(viewPos); } [/cce_cpp]

这个函数的功能是,让地图所在图层以主角为中心进行移动,也就是,让世界的焦点停留在主角身上,屏幕随着主角移动,这样说比较清晰。

这个函数的算法解释起来可能有点繁琐,总之就是为了让地图跟随主角移动,并且要判断边界值,不能让地图超出屏幕从而导致有黑边出现。大家可以根据这个思路自己写一个算法,也许比我的更好~

然后,我们的Player要重写父类的setSimplePosition函数:

[cce_cpp]void Player::setSimplePosition( int x, int y ) { Entity::setSimplePosition(x, y);

/* 以主角为中心移动地图 */ setViewPointByPlayer(); } [/cce_cpp]

记得在头文件里加上这句:

[cce_cpp]/* 重写父类的函数 */ virtual void setSimplePosition(int x, int y); [/cce_cpp]

于是,编译运行,就能看到主角在跑,地图也随之移动!

呼呼,终于有点意思了~

《跑跑跑》制作教程(第4篇)截图

 

下一篇我们将给主角添加一个新的很帅的功能——上下移动。

来自未来的PS(2013.01.14):

多位朋友问过我为什么map变量未声明,可能是我忘记说了,map变量在Entity.h文件里声明的:

[cce_cpp]class Entity : public CCNode, public ControllerListener { public: void setSprite(CCSprite* mSprite); void setController(Controller* controller);

/* 实现SimpleMoveListener接口的方法 */ virtual void setSimplePosition(int x, int y); virtual CCPoint getCurPosition(); protected: CCSprite* mSprite; Controller* mController; CCTMXTiledMap* map; /* ------------------------ Hi,我在这里~~!!! --------------------------- */

CCTMXLayer* meta; /* 检测碰撞的地图层 */ CCTMXLayer* barrier;/* 障碍物层 */

/* 将像素坐标转换为地图格子坐标*/ CCPoint tileCoordForPosition(CCPoint pos); };[/cce_cpp]
14 条评论
  • 浪子 2013-09-17 11:08:48

    楼上的厉害
    0回复
  • 浪子 2013-09-16 19:42:09

    为什么我这里在下面这行报 /* 地图方块数量 */ CCSize mapTiledNum = map->getMapSize(); map为空,获得不到地图的方块的数量
    0回复
    • 浪子 2013-09-16 20:00:08

      博主在吗?是我哪少写了吗?
      0回复
    • 博主 糟糕_树叶的mut 2013-09-23 14:45:06

      教程中间有个地方有修改,把map变量移到entity的(没记错的话),估计你看漏了,呵呵
      0回复
  • adlovely 2013-03-28 22:00:00

    这里如果按教程敲有个问题
    CCSize mapTiledNum = map->getMapSize();
    这里会报错,由于player是继承了entity;
    CCTMXTiledMap *map是在entity中定义的;所以player里面也有一个map的对象(CCTMXTiledMap *map),但是这个map没有赋值,所以这个问题只需要

    bool Player::initWithTiledMap(CCTMXTiledMap *map)
    {
    CCTMXObjectGroup *objGroup=map ->objectGroupNamed("objects");

    this->map=map; //加上这句就可以了。

    }

    楼上的哥们很给力。
    0回复
  • start530 2013-01-10 15:22:00

    卡在player.cpp这里了
    /* 地图方块数量 */
    CCSize mapTiledNum = map->getMapSize();

    /* 地图单个格子大小 */
    CCSize tiledSize = map->getTileSize();
    这里的map 未声明啊,也没有一个参数传进来。博主你怎么看?
    0回复
  • musicvs 2013-01-10 18:27:00

    [reply]start530[/reply]
    map是成员变量呢~你仔细看看类的头文件有没有声明这个变量~
    0回复
  • lovehzh 2013-01-13 17:48:00

    [reply]musicvs[/reply]
    我也遇到这个问题,请问是在哪里声明这个变量呢,刚刚从Java转过来,不太明白。是在Entity.h 还是在Player.h呢
    0回复
  • lovehzh 2013-01-13 17:58:00

    呵呵 自己试着解决了,是这样的:
    在Player.h头文件中定义变量 CCTMXTiledMap *map;

    然后在initWithTiledMap( CCTMXTiledMap* map )中
    /* 加载对象层 */
    CCTMXObjectGroup* objGroup = map->objectGroupNamed("objects");
    //加上这句
    this->map = map;
    0回复
  • lovehzh 2013-01-13 18:00:00

    不过我还有个问题,我这样定义的话,这个变量是public的,是不是破坏了封装,该怎么定义比较好呢?还是那句话,刚刚从Java过来C++语法不不熟,呵呵
    0回复
  • musicvs 2013-01-14 08:11:00

    [reply]lovehzh[/reply]
    是在Entity.h里定义的,我看了一下,我提供的源码里是有这个定义的,可能教程里忘了说,呵呵,不好意思
    0回复
  • musicvs 2013-01-14 16:45:00

    [reply]lovehzh[/reply]
    我是在Entity.h里声明的,protected。
    在Player里声明也行~但是你可以用private,用public确实不好呢
    0回复
发表评论
粤ICP备16043700号

本博客基于 BlazorAnt Design Blazor 开发