這個是《Cocos2d-X by Example Beginner's Guide》上的第一個例子,我稍微重構了下代碼。是一個簡單的IPad上的雙人遊戲,把球射入對方的球門就得分了。固然我這是在Windows上的截圖,用鼠標模擬手指的觸摸。這遊戲作的還不行,最大速度不能控制,很容易亂竄,但做爲一個簡單的入門遊戲還不錯。app
我建了一個Player的類,就是上圖中的兩個白色能夠觸摸移動的物體。須要繼承CCTargetedTouchDelegate,而後主要重寫ccTouchBegan,ccTouchMoved,ccTouchEnded 3個方法。ide
#ifndef _PLAYER_H_ #define _PLAYER_H_ #include "cocos2d.h" USING_NS_CC; class Player : public CCSprite, public CCTargetedTouchDelegate//1. need inherit CCTargetedTouchDelegate { public: Player(void); virtual ~Player(void); /** 2.Overwrite some virtual function @{ */ virtual void onEnter(); virtual void onExit(); virtual bool ccTouchBegan(CCTouch* touch, CCEvent* event); virtual void ccTouchMoved(CCTouch* touch, CCEvent* event); virtual void ccTouchEnded(CCTouch* touch, CCEvent* event); virtual void touchDelegateRetain(); virtual void touchDelegateRelease(); /** @} */ }; #endif
在ccTouchMoved裏主要限制了白色物體的範圍。還有是設置了向量,等碰撞的時候用。ui
void Player::ccTouchMoved(CCTouch* touch, CCEvent* event) { CCAssert(m_state == kPlayerStateGrabbed, "Player - Unexpected state!"); CCSize screenSize = CCDirector::sharedDirector()->getWinSize(); CCPoint tap = touch->getLocation(); CCPoint nextPosition = tap; //keep player in court nextPosition = ccp(max(nextPosition.x, radius()), max(nextPosition.y, radius())); nextPosition = ccp(min(nextPosition.x, screenSize.width - radius()) , min(nextPosition.y, screenSize.height - radius())); //keep player in its area if (getPositionY() < screenSize.height * 0.5f) { nextPosition.y = min(nextPosition.y, screenSize.height / 2 - radius()); } else { nextPosition.y = max(nextPosition.y, screenSize.height / 2 + radius()); } setNextPosition(nextPosition); setVector(ccp(tap.x - getPositionX(), tap.y - getPositionY())); //setPosition(nextPosition); }
這遊戲沒有用到物理引擎,球與桌面的摩擦,就是簡單地把球的向量乘以0.98,這樣物體最終看起來就中止了。很是的簡單。spa
這塊多是最難的部分,首先仍是看最簡單的碰撞。code
仔細看上面那動態圖,球碰到左右邊的時候,其實它在Y軸上的速度方向是不變的,只是在X軸上的速度方向變負了。繼承
void Ball::collisionWithSides(){ if(_nextPosition.x < radius()){ _nextPosition.x = radius(); setVector(ccp(getVector().x * -0.8, getVector().y)) ;//when collision with left and right side,the x direction will change //and every hits will slow down the ball, so x * -0.8 //SimpleAudioEngine::sharedEngine()->playEffect("hit.wav"); } if (_nextPosition.x > _screenSize.width - radius()) { _nextPosition.x = _screenSize.width - radius(); setVector(ccp(getVector().x * -0.8, getVector().y)) ; //SimpleAudioEngine::sharedEngine()->playEffect("hit.wav"); } }
代碼中的x * -0.8就是這樣的效果。方向變反,速度變慢。遊戲
球與上下邊的碰撞也是一樣的道理,在Y軸上的速度方向變反,變慢。X軸上不變,固然還要考慮這是在不進球的狀況下。事件
void Ball::collisionWithTop(){ if (_nextPosition.y > _screenSize.height - radius()) { if (getPosition().x < _screenSize.width * 0.5f - GOAL_WIDTH * 0.5f || getPosition().x > _screenSize.width * 0.5f + GOAL_WIDTH * 0.5f) { _nextPosition.y = _screenSize.height - radius(); setVector(ccp(getVector().x , getVector().y * -0.8)) ;//when collision with top or bottom side,the y direction will change //and every hits will slow down the ball, so y * -0.8 //SimpleAudioEngine::sharedEngine()->playEffect("hit.wav"); } } }
何時兩個球會碰撞?get
這仍是簡單的就是兩個球之間的距離小於兩個球的半徑相加。數學
碰撞後紅球的方向是什麼?
兩個球碰撞後,紅球移動的方向其實就是紅球和白球圓點之間的連線。
碰撞後紅球移動的速度?
首先爲了儘量地跟真實狀況相同,碰撞後紅球移動的速度應該跟原來紅球的速度和白球移動的速度都有關。
講了這麼多,下面的代碼應該能夠理解了,數學萬歲!
void Ball::collisionWithPlayer(Player* player){ float squared_radii = pow(player->radius() + radius(), 2); CCPoint playerNextPosition = player->getNextPosition(); CCPoint playerVector = player->getVector(); CCPoint ballVector = getVector(); float diffx = _nextPosition.x - player->getPositionX(); float diffy = _nextPosition.y - player->getPositionY(); float distance1 = pow(diffx, 2) + pow(diffy, 2);// (x1 - x2)2 + (y1 - y2)2 if (distance1 <= squared_radii) {// a collision happen float mag_ball = pow(ballVector.x, 2) + pow(ballVector.y, 2); float mag_player = pow (playerVector.x, 2) + pow (playerVector.y, 2); float force = sqrt(mag_ball + mag_player); float angle = atan2(diffy, diffx); setVector(ccp(force * cos(angle), force * sin(angle))); //SimpleAudioEngine::sharedEngine()->playEffect("hit.wav"); } }
注:這項目是基於cocos2d-x 2.1.3。