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

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


最近在学习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 tiled
	if(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 tiled
	else 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,英雄将无法

你可能感兴趣的:(cocos2d-x+Tiledmap中实现自由跳跃和移动)