cocos2d-x 横板游戏触屏人物和背景移动 方法1
大多横板游戏主角的移动都是有背景一起在移动的,不单单是主角在动。当主角的位置离地图的左端距离小于屏幕宽度的一半或者主角离地图最右端的距离小于屏幕宽度的一半时,触屏之后就人物在移动,背景没有动,当主角位于这端中间的位置时,触屏之后主角移动的同时,背景也在往主角反方向移动,一旦当主角移动到两端的内边界时,背景就停止移动,只主角移动。
这段代码放到这里做个备份,不是最终版,而且也不是性能最高的解决办法,
当主角走到两端时,背景偶尔会走多了出线黑边,
功能:每次点击屏幕之后,主角停止当前的动作,走到触屏的那个点然后停下来。
1 // 2 // GameLayer.h 3 // PlayerActionTest 4 // 5 // Created by 嘉定 on 12-12-25. 6 // 7 // 8 9 #ifndef __PlayerActionTest__GameLayer__ 10 #define __PlayerActionTest__GameLayer__ 11 12 #include "cocos2d.h" 13 #include "Player.h" 14 #include "RangeLayer.h" 15 #include "TouchMoveHandle.h" 16 17 USING_NS_CC; 18 19 class GameLayer : public cocos2d::CCLayer 20 { 21 public: 22 23 GameLayer(); 24 25 26 CCLayer *container; 27 28 CCSprite *backBg; 29 CCSprite *frontBg; 30 31 Player *player; 32 CCLayer *bg; 33 34 void showBg(); 35 void showPlayer(); 36 37 38 virtual void onEnter(); 39 virtual void registerWithTouchDispatcher(); 40 virtual void ccTouchesEnded(CCSet *pTouches,CCEvent *pEvent); 41 virtual bool ccTouchBegan(CCTouch* touch, CCEvent* event); 42 virtual void ccTouchEnded(CCTouch* touch, CCEvent* event); 43 // virtual void ccTouchCancelled(CCTouch* touch, CCEvent* event); 44 // virtual void ccTouchMoved(CCTouch* touch, CCEvent* event); 45 46 47 CREATE_FUNC(GameLayer); 48 49 private: 50 CCPoint selfTargetPos;//相对于GameLayer这个容器的本地坐标 51 52 TouchMoveHandle *currentMoveHandle; 53 54 }; 55 56 #endif /* defined(__PlayerActionTest__GameLayer__) */
1 // 2 // GameLayer.cpp 3 // PlayerActionTest 4 // 5 // Created by 嘉定 on 12-12-25. 6 // 7 // 8 9 #include "GameLayer.h" 10 #include "TouchMoveHandle.h" 11 12 GameLayer::GameLayer() 13 { 14 15 } 16 17 void GameLayer::showPlayer() 18 { 19 CCSize winSize = CCDirector::sharedDirector()->getWinSize(); 20 21 //npc 22 Player *npc = Player::create(); 23 npc->setScale(1.5); 24 npc->setPosition(ccp(850,75)); 25 npc->playAction(Player::state_idle); 26 container->addChild(npc); 27 28 29 //标出原点 30 player = Player::create(); 31 player->setScale(1.5); 32 player->setPosition(ccp(winSize.width/2,95)); 33 player->playAction(Player::state_idle); 34 container->addChild(player); 35 36 37 } 38 39 void GameLayer::onEnter() 40 { 41 CCLayer::onEnter(); 42 } 43 44 void GameLayer::registerWithTouchDispatcher() 45 { 46 CCDirector* pDirector = CCDirector::sharedDirector(); 47 pDirector->getTouchDispatcher()->addTargetedDelegate(this, 0, true); 48 } 49 50 bool GameLayer::ccTouchBegan(cocos2d::CCTouch *touch, cocos2d::CCEvent *event) 51 { 52 // CCLog("ccTouchBegan"); 53 //Gamelayer的宽度一直都是1136,而不会因为内部添加了frontBG而宽度增加 54 55 //全局坐标换算成GameLayer内部坐标系 56 selfTargetPos = ccp(touch->getLocation().x + abs(container->getPositionX()),touch->getLocation().y); 57 58 if(currentMoveHandle) 59 { 60 currentMoveHandle->destroy(); 61 currentMoveHandle->release(); 62 currentMoveHandle = NULL; 63 } 64 currentMoveHandle = TouchMoveHandle::create(); 65 currentMoveHandle->retain(); 66 currentMoveHandle->handle(player,backBg,frontBg,container,selfTargetPos); 67 68 return true; 69 } 70 71 void GameLayer::ccTouchEnded(cocos2d::CCTouch *touch, cocos2d::CCEvent *event) 72 { 73 // CCLog("ccTouchEnded"); 74 } 75 76 //void GameLayer::ccTouchCancelled(cocos2d::CCTouch *touch, cocos2d::CCEvent *event) 77 //{ 78 // CCLog("ccTouchCancelled"); 79 // 80 //} 81 82 void GameLayer::ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent) 83 { 84 // CCLog("ccTouchesEnded"); 85 86 87 // CCSetIterator it = pTouches->begin(); 88 // CCTouch *touch = (CCTouch*)(*it); 89 // CCPoint location = touch->getLocation(); 90 // player->runTo(location); 91 // 92 } 93 94 //void GameLayer::ccTouchMoved(cocos2d::CCTouch *touch, cocos2d::CCEvent *event) 95 //{ 96 // 97 //} 98 99 void GameLayer::showBg() 100 { 101 setTouchEnabled(true); 102 103 container = CCLayer::create(); 104 105 106 107 108 CCSize winSize = CCDirector::sharedDirector()->getWinSize(); 109 frontBg = CCSprite::create("map/zhongjing.png"); 110 CCSize mapSize = frontBg->getContentSize(); 111 float mapScale = winSize.height / mapSize.height; 112 frontBg->setAnchorPoint(CCPointZero); 113 frontBg->setPosition(CCPointZero); 114 115 frontBg->setScale(mapScale); 116 117 backBg = CCSprite::create("map/beijing.png"); 118 CCSize backMapSize = backBg->getContentSize(); 119 backBg->setAnchorPoint(CCPointZero); 120 backBg->setScale(mapScale); 121 backBg->setPosition(ccp(0,winSize.height - (backMapSize.height * mapScale))); 122 123 addChild(backBg); 124 addChild(container); 125 container->addChild(frontBg); 126 127 RangeLayer *range = RangeLayer::create(); 128 CCSize size = CCSizeMake(frontBg->getContentSize().width * frontBg->getScale(), winSize.height); 129 range->setContentSize(size); 130 range->setLinePox(winSize.width/2, frontBg->getContentSize().width*frontBg->getScale()- winSize.width/2); 131 container->addChild(range); 132 }
1 // 2 // TouchMoveHandle.h 3 // PlayerActionTest 4 // 5 // Created by 嘉定 on 13-1-3. 6 // 7 // 此类负责地图点击移动的执行 8 // 主要处理人物和背景的移动,都是横向移动,不包含y方向上的移动。 9 10 #ifndef __PlayerActionTest__TouchMoveHandle__ 11 #define __PlayerActionTest__TouchMoveHandle__ 12 13 #include "cocos2d.h" 14 #include "Player.h" 15 16 USING_NS_CC; 17 18 class TouchMoveHandle : public CCObject 19 { 20 public: 21 22 TouchMoveHandle(); 23 virtual ~TouchMoveHandle(); 24 25 typedef enum 26 { 27 leftToCenter = 1, 28 centerToLeft = 2, 29 rightToCenter = 3, 30 centerToRight = 4, 31 behaviorUnKnow = 5 32 }PlayerCrossBehavior; 33 34 void handle(Player *_player, CCSprite *_backBg,CCSprite *_centerBg,CCLayer *_container,CCPoint touchPoint); 35 36 37 virtual bool init(); 38 39 PlayerCrossBehavior moveBehavior; 40 41 void destroy(); 42 43 44 CREATE_FUNC(TouchMoveHandle); 45 46 private: 47 48 float winWidth; 49 Player *player; 50 CCSprite *backBg; 51 CCSprite *centerBg; 52 CCLayer *container; 53 54 55 float backBgWidth; 56 float centerBgWidth; 57 58 CCPoint targetPoint; 59 //左侧判断移动边界 60 float leftSideX; 61 //右侧判断移动边界 62 float rightSideX; 63 64 CCPoint getCrossSidePoint1(); 65 66 void moveContainer1(CCPoint target); 67 void playerCrollSideLineHandler(); 68 }; 69 70 #endif /* defined(__PlayerActionTest__TouchMoveHandle__) */
1 // 2 // TouchMoveHandle.cpp 3 // PlayerActionTest 4 // 5 // Created by 嘉定 on 13-1-3. 6 // 7 // 8 9 #include "TouchMoveHandle.h" 10 11 12 TouchMoveHandle::TouchMoveHandle(): 13 winWidth(0), 14 player(NULL), 15 backBg(NULL), 16 centerBg(NULL), 17 backBgWidth(0), 18 centerBgWidth(0), 19 leftSideX(0), 20 rightSideX(0), 21 moveBehavior(behaviorUnKnow) 22 { 23 24 } 25 26 TouchMoveHandle::~TouchMoveHandle() 27 { 28 CCLog("~TouchMoveHandle dispose"); 29 } 30 31 bool TouchMoveHandle::init() 32 { 33 CCNotificationCenter::sharedNotificationCenter()->addObserver(this, callfuncO_selector(TouchMoveHandle::playerCrollSideLineHandler),"playerIdle", NULL); 34 35 return true; 36 } 37 38 void TouchMoveHandle::destroy() 39 { 40 CCNotificationCenter::sharedNotificationCenter()->removeObserver(this, "playerIdle"); 41 42 } 43 44 void TouchMoveHandle::handle(Player *_player, CCSprite *_backBg,CCSprite *_centerBg,CCLayer *_container,CCPoint touchPoint) 45 { 46 player = _player; 47 winWidth = CCDirector::sharedDirector()->getWinSize().width; 48 backBg = _backBg; 49 centerBg = _centerBg; 50 container = _container; 51 backBgWidth = backBg->getContentSize().width * backBg->getScaleX(); 52 centerBgWidth = centerBg->getContentSize().width * centerBg->getScaleX(); 53 this->targetPoint = ccp(touchPoint.x,player->getPosition().y); 54 leftSideX = winWidth/2; 55 rightSideX = centerBgWidth - winWidth/2; 56 57 float playerCurrentX = player->getPosition().x; 58 59 //玩家在地图左侧 60 if(playerCurrentX <= leftSideX) 61 { 62 //targetPoint也在左侧,就玩家动 63 if(targetPoint.x <= leftSideX) 64 { 65 moveBehavior = behaviorUnKnow; 66 player->runTo(targetPoint); 67 68 } 69 else //touchPoint在中间,先玩家跑到边界,过界后背景和玩家一起动 70 { 71 moveBehavior = leftToCenter; 72 player->runTo(getCrossSidePoint1()); 73 } 74 } 75 else if(playerCurrentX > leftSideX && playerCurrentX < rightSideX)//玩家在中间 76 { 77 //targetPoint在左侧,先玩家背景一起动,然后再只玩家动 78 if(targetPoint.x <= leftSideX) 79 { 80 CCPoint temp = getCrossSidePoint1(); 81 player->runTo(temp); 82 moveContainer1(temp); 83 moveBehavior = centerToLeft; 84 } 85 else if(targetPoint.x > leftSideX && targetPoint.x < rightSideX)//targetPoint在中间,一起动 86 { 87 player->runTo(targetPoint); 88 moveContainer1(targetPoint); 89 moveBehavior = behaviorUnKnow; 90 } 91 else if(targetPoint.x >= rightSideX)//targetPoint在右,先玩家跑到边界,过界后背景和玩家一起动 92 { 93 CCPoint temp = ccp(rightSideX,player->getPositionY()); 94 player->runTo(temp); 95 moveContainer1(temp); 96 moveBehavior = centerToRight; 97 } 98 } 99 else if(playerCurrentX >= rightSideX)//玩家在右侧 100 { 101 if(targetPoint.x < rightSideX)//targetPoint在中间 102 { 103 CCPoint temp = ccp(rightSideX,player->getPositionY()); 104 player->runTo(temp); 105 moveBehavior = rightToCenter; 106 } 107 else if(targetPoint.x >= rightSideX) 108 { 109 player->runTo(targetPoint); 110 moveBehavior = behaviorUnKnow; 111 } 112 } 113 114 115 } 116 117 void TouchMoveHandle::playerCrollSideLineHandler() 118 { 119 if(moveBehavior == leftToCenter) 120 { 121 moveBehavior = behaviorUnKnow; 122 player->runTo(targetPoint); 123 moveContainer1(targetPoint); 124 } 125 else if(moveBehavior == centerToLeft) 126 { 127 moveBehavior = behaviorUnKnow; 128 container->stopAllActions(); 129 container->setPositionX(0); 130 backBg->stopAllActions(); 131 backBg->setPositionX(0); 132 player->runTo(targetPoint); 133 } 134 else if(moveBehavior == centerToRight) 135 { 136 moveBehavior = behaviorUnKnow; 137 container->stopAllActions(); 138 container->setPositionX(winWidth-centerBgWidth); 139 backBg->stopAllActions(); 140 backBg->setPositionX(winWidth-backBgWidth); 141 player->runTo(targetPoint); 142 } 143 else if(moveBehavior == rightToCenter) 144 { 145 moveBehavior = behaviorUnKnow; 146 player->runTo(targetPoint); 147 moveContainer1(targetPoint); 148 } 149 150 } 151 152 CCPoint TouchMoveHandle::getCrossSidePoint1() 153 { 154 CCPoint crossPoint = ccp(leftSideX,player->getPositionY()); 155 return crossPoint; 156 } 157 158 void TouchMoveHandle::moveContainer1(CCPoint target) 159 { 160 container->stopAllActions(); 161 backBg->stopAllActions(); 162 163 const float SPEED = 12; 164 float currentPlayerPosX = player->getPosition().x; 165 float disX = target.x - currentPlayerPosX; 166 float DIS_X = abs(disX); 167 float containerTartgetX = 0; 168 if(disX < 0) 169 { 170 containerTartgetX = container->getPositionX() + DIS_X; 171 } 172 else 173 { 174 containerTartgetX = container->getPositionX() - DIS_X; 175 } 176 float playerMoveTime = (DIS_X / SPEED) / 60; 177 178 CCAction *action = CCSequence::create( 179 CCMoveTo::create(playerMoveTime, ccp(containerTartgetX,0)), 180 NULL); 181 container->runAction(action); 182 183 //背景层 184 //中景层从最大横坐标到最小横坐标之间的距离 185 float maxCenterBgDis = centerBgWidth - winWidth; 186 //背景层的移动距离 187 float maxBackBgDis = backBgWidth - winWidth; 188 float backBgMoveScale = maxBackBgDis / maxCenterBgDis; 189 float backBgTargetPosx = containerTartgetX * backBgMoveScale; 190 CCAction *backBgAction = CCSequence::create(CCMoveTo::create(playerMoveTime, ccp(backBgTargetPosx,backBg->getPosition().y)),NULL); 191 backBg->runAction(backBgAction); 192 }