本文共 2578 字,大约阅读时间需要 8 分钟。
上一篇我们已经把我们跑的主题体现出来了,但是,主角跑没多久就离开地图了,也离开屏幕了,这不靠谱啊喂,我们得让地图也动起来(难道我做这么长的地图是摆设么~)。
1. 地图卷动规则
首先要定一个规则,地图怎么卷动?我们定义为这样,地图只会横向往左卷动,当主角超过屏幕中点的时候地图就开始卷动。最终的效果应该是这样的:
留意最左边,地图最左边已经有部分没有显示出来了,证明地图已经往左移动了一小段距离。
2. 触发卷动
我们在主角坐标改变的时候就判断是否需要移动地图,来,我们给Player类增加一个函数:
01 | void Player::setViewPointByPlayer() |
02 | { |
03 | if (mSprite == NULL) { |
04 | return ; |
05 | } |
06 | CCLayer* parent = (CCLayer* )mSprite->getParent(); |
07 |
08 | /* 地图方块数量 */ |
09 | CCSize mapTiledNum = map->getMapSize(); |
10 |
11 | /* 地图单个格子大小 */ |
12 | CCSize tiledSize = map->getTileSize(); |
13 |
14 | /* 地图大小 */ |
15 | CCSize mapSize = CCSize::CCSize( |
16 | mapTiledNum.width * tiledSize.width, |
17 | mapTiledNum.height * tiledSize.height); |
18 |
19 | /* 屏幕大小 */ |
20 | CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize(); |
21 |
22 | /* 精灵的坐标 */ |
23 | CCPoint spritePos = mSprite->getPosition(); |
24 |
25 | /* 如果精灵坐标小于屏幕的一半,则取屏幕中点坐标,否则取精灵的坐标 */ |
26 | float x = max(spritePos.x, visibleSize.width / 2); |
27 | float y = max(spritePos.y, visibleSize.height / 2); |
28 |
29 | /* 如果x、y的坐标大于右上角的极限值,则取极限值的坐标(极限值是指不让地图超出屏幕造成出现黑边的极限坐标) */ |
30 | x = min(x, mapSize.width - visibleSize.width / 2); |
31 | y = min(y, mapSize.height - visibleSize.height / 2); |
32 |
33 | CCPoint destPos = CCPoint::CCPoint(x, y); |
34 | CCPoint centerPos = CCPoint::CCPoint(visibleSize.width / 2, visibleSize.height / 2); |
35 |
36 | /* 计算屏幕中点和所要移动的目的点之间的距离 */ |
37 | CCPoint viewPos = ccpSub(centerPos, destPos); |
38 |
39 | parent->setPosition(viewPos); |
40 | } |
这个函数的功能是,让地图所在图层以主角为中心进行移动,也就是,让世界的焦点停留在主角身上,屏幕随着主角移动,这样说比较清晰。
这个函数的算法解释起来可能有点繁琐,总之就是为了让地图跟随主角移动,并且要判断边界值,不能让地图超出屏幕从而导致有黑边出现。大家可以根据这个思路自己写一个算法,也许比我的更好~
然后,我们的Player要重写父类的setSimplePosition函数:
1 | void Player::setSimplePosition( int x, int y ) |
2 | { |
3 | Entity::setSimplePosition(x, y); |
4 |
5 | /* 以主角为中心移动地图 */ |
6 | setViewPointByPlayer(); |
7 | } |
记得在头文件里加上这句:
1 | /* 重写父类的函数 */ |
2 | virtual void setSimplePosition( int x, int y); |
于是,编译运行,就能看到主角在跑,地图也随之移动!
呼呼,终于有点意思了~
下一篇我们将给主角添加一个新的很帅的功能——上下移动。
来自未来的PS(2013.01.14):
多位朋友问过我为什么map变量未声明,可能是我忘记说了,map变量在Entity.h文件里声明的:
01 | class Entity : public CCNode, public ControllerListener { |
02 | public : |
03 | void setSprite(CCSprite* mSprite); |
04 | void setController(Controller* controller); |
05 |
06 | /* 实现SimpleMoveListener接口的方法 */ |
07 | virtual void setSimplePosition( int x, int y); |
08 | virtual CCPoint getCurPosition(); |
09 | protected : |
10 | CCSprite* mSprite; |
11 | Controller* mController; |
12 | CCTMXTiledMap* map; /* ------------------------ Hi,我在这里~~!!! --------------------------- */ |
13 |
14 | CCTMXLayer* meta; /* 检测碰撞的地图层 */ |
15 | CCTMXLayer* barrier; /* 障碍物层 */ |
16 |
17 | /* 将像素坐标转换为地图格子坐标*/ |
18 | CCPoint tileCoordForPosition(CCPoint pos); |
19 | }; |