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

笨木头  2012-11-16 12:57   2.0游戏实例《跑跑跑》,Cocos2d-x2.0   阅读(5,960)   14条评论

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

 

笨木头花心贡献,啥?花心?不呢,是用心~

转载请注明,原文地址
 http://www.benmutou.com/archives/30

正文:

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

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

 

1. 地图卷动规则

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

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

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

 

2. 触发卷动

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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);
}

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

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

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

1
2
3
4
5
6
7
void Player::setSimplePosition( int x, int y )
{
Entity::setSimplePosition(x, y);

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

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

1
2
/* 重写父类的函数 */
virtual void setSimplePosition(int x, int y);

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

呼呼,终于有点意思了~

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

 

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

来自未来的PS(2013.01.14):

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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);
};

14 评论

  1. 为什么我这里在下面这行报 /* 地图方块数量 */ CCSize mapTiledNum = map->getMapSize(); map为空,获得不到地图的方块的数量

  2. 这里如果按教程敲有个问题
    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; //加上这句就可以了。

    }

    楼上的哥们很给力。

  3. [reply]adlovely[/reply]
    这个问题是我的错,前面我把变量放在player里,后面改到entity了,结果没有给大家说清楚,嘻嘻

  4. 这里如果按教程敲有个问题
    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; //加上这句就可以了。

    }

    楼上的哥们很给力。

  5. [reply]lovehzh[/reply]
    我是在Entity.h里声明的,protected。
    在Player里声明也行~但是你可以用private,用public确实不好呢

  6. [reply]lovehzh[/reply]
    是在Entity.h里定义的,我看了一下,我提供的源码里是有这个定义的,可能教程里忘了说,呵呵,不好意思

  7. 不过我还有个问题,我这样定义的话,这个变量是public的,是不是破坏了封装,该怎么定义比较好呢?还是那句话,刚刚从Java过来C++语法不不熟,呵呵

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

    然后在initWithTiledMap( CCTMXTiledMap* map )中
    /* 加载对象层 */
    CCTMXObjectGroup* objGroup = map->objectGroupNamed("objects");
    //加上这句
    this->map = map;

  9. [reply]musicvs[/reply]
    我也遇到这个问题,请问是在哪里声明这个变量呢,刚刚从Java转过来,不太明白。是在Entity.h 还是在Player.h呢

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

    /* 地图单个格子大小 */
    CCSize tiledSize = map->getTileSize();
    这里的map 未声明啊,也没有一个参数传进来。博主你怎么看?

发表评论

电子邮件地址不会被公开。 必填项已用*标注