cocos2d-x+Tiledmap中实现自由跳跃和移动

来源:互联网 发布:南通seo招聘 编辑:程序博客网 时间:2024/06/02 21:01

最近在学习cocos2d-x,遇到一个问题:在tiledMap中,怎么实现类似超级玛丽跳跃和移动那样的算法?

游戏主角假设也是一个瓦片大小,在如下的场景中如何实现游戏主角的自由移动?



1.算法描述

1. heroPosition_nextFrame = heroPosition_currentFrame + ccp(speedX, 0) + ccp(0, speedY)
2. determinePoint[4] = CCPoint(heroPosition_nextFrame.x, heroPosition_nextFrame.y)
    CCPoint(heroPosition_nextFrame.x + heroSize.width, heroPosition_nextFrame.y)
    CCPoint(heroPosition_nextFrame.x + heroSize.width, heroPosition_nextFrame.y + heroSize.height)  
    CCPoint(heroPosition_nextFrame.x, heroPosition_nextFrame.y + heroSize.height)
3. CollisionPosition getPointCollisionPosition( cocos2d::CCPoint heroPosition_core, cocos2d::CCPoint determinedPoint, cocos2d::CCPoint&)
4. Update m_fMaxDisUp, m_fMaxDisDown, m_fMaxDisLeft, m_fMaxDisRight
5. Update HeroPosition

第一步,根据英雄当前位置+当前水平/垂直方向移动速度得到下一帧英雄的位置;
第二步,根据英雄的位置+英雄的大小获取英雄四个顶点的位置,作为监测点
第三步,任何时候,英雄都必定处于如下的九宫格之中,根据英雄的位置+监测点的位置获取碰撞类型(LeftUp, Up, RightUp, Right, RightDown, Down, LeftDown, Left, NoCollision)和碰撞块的坐标

第四步,根据碰撞和英雄到相对位置,更新m_fMaxDisUp, m_fMaxDisDown, m_fMaxDisLeft, m_fMaxDisRight,这四个值分别代表英雄上、下、左、右能移动的最大距离
第五步,根据英雄当前位置+水平/垂直方向速度+m_fMaxDisUp, m_fMaxDisDown, m_fMaxDisLeft, m_fMaxDisRight更新英雄位置

2.需要注意的细节

2.1初始化

每次预测下一帧的英雄位置的时候,都会修改m_fMaxDisUp, m_fMaxDisDown, m_fMaxDisLeft, m_fMaxDisRight,所以在第三步执行getPointCollisionPosition之前需要初始化m_fMaxDisUp, m_fMaxDisDown, m_fMaxDisLeft, m_fMaxDisRight为地图的大小:

m_pHero->InitializeMoveScope(this->m_pMap->getMapSize());void GameobjHero::InitializeMoveScope(cocos2d::CCSize mapSize){m_fMaxDisUp = mapSize.height;m_fMaxDisDown = 0;m_fMaxDisLeft = 0;m_fMaxDisRight = mapSize.width;}



2.2顶点碰撞

以右上角碰撞为例,当前的算法并没有区别如下三种碰撞。很显然,第一种碰撞需要更新的是m_fMaxDisRight,第二种碰撞需要更新的是m_fMaxDisUp,而第三种碰撞着需要更新两者。

//hero is at the right side of the collision tiledif(IS_FLOAT_POSITIVE(m_pHero->getPositionX() - (collisionTiledPosition.x + 1) * m_pMap->getTiledSize().width)&& IS_FLOAT_POSITIVE((m_pHero->getPositionY() + m_pHero->getContentSize().height) - collisionTiledPosition.y * m_pMap->getTiledSize().height)){m_pHero->setMaxDisLeft(max(m_pHero->getMaxDisLeft(), (collisionTiledPosition.x + 1) * m_pMap->getTiledSize().width));m_pHero->setLeftCollided(true);}//hero is at the down side of the collision tiledelse if(IS_FLOAT_POSITIVE((collisionTiledPosition.x + 1) * m_pMap->getTiledSize().width - m_pHero->getPositionX())&& IS_FLOAT_POSITIVE(collisionTiledPosition.y * m_pMap->getTiledSize().height - (m_pHero->getPositionY() + m_pHero->getContentSize().height))){m_pHero->setMaxDisUp(min(m_pHero->getMaxDisUp(), (collisionTiledPosition.y - 1) * m_pMap->getTiledSize().height));m_pHero->setUpCollided(true);}else{m_pHero->setMaxDisLeft(max(m_pHero->getMaxDisLeft(), (collisionTiledPosition.x + 1) * m_pMap->getTiledSize().width));m_pHero->setMaxDisUp(min(m_pHero->getMaxDisUp(), (collisionTiledPosition.y - 1) * m_pMap->getTiledSize().height));m_pHero->setLeftCollided(true);m_pHero->setUpCollided(true);}

但是右下角和左下角处理第三种碰撞的方式和上述不一样,右下角和左下角不需要设置m_fMaxDisRight和m_fMaxDisLeft,因为在移动的过程中,需要每一帧都将垂直方向的速度设置为一个负数,实现没有瓦片时的下坠效果,所以在英雄每移动一个完整的瓦片,都会发生右下角或者左下角的第三种碰撞,此时如果设置了m_fMaxDisRight或m_fMaxDisLeft,英雄将无法再移动。


原创粉丝点击