1效果图:
这个是《Cocos2d-X by Example Beginner’s Guide》上的第一个例子,我稍微重构了下代码。是一个简单的IPad上的双人游戏,把球射入对方的球门就得分了。当然我这是在Windows上的截图,用鼠标模拟手指的触摸。这游戏做的还不行,最大速度不能控制,很容易乱窜,但作为一个简单的入门游戏还不错。
2.cocos2d-x Touch 事件
我建了一个Player的类,就是上图中的两个白色可以触摸移动的物体。需要继承CCTargetedTouchDelegate,然后主要重写ccTouchBegan,ccTouchMoved,ccTouchEnded 3个方法。
#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里主要限制了白色物体的范围。还有是设置了向量,等碰撞的时候用。
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); }
3.谈谈球与桌面的摩擦
这游戏没有用到物理引擎,球与桌面的摩擦,就是简单地把球的向量乘以0.98,这样物体最终看起来就停止了。非常的简单。
4.球的碰撞
这块可能是最难的部分,首先还是看最简单的碰撞。
4.1球与边的碰撞
仔细看上面那动态图,球碰到左右边的时候,其实它在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"); } } }
4.2球与玩家控制的白色物体碰撞
什么时候两个球会碰撞?
这还是简单的就是两个球之间的距离小于两个球的半径相加。
碰撞后红球的方向是什么?
两个球碰撞后,红球移动的方向其实就是红球和白球圆点之间的连线。
碰撞后红球移动的速度?
首先为了尽可能地跟真实情况相同,碰撞后红球移动的速度应该跟原来红球的速度和白球移动的速度都有关。
讲了这么多,下面的代码应该可以理解了,数学万岁!
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"); } }
5.项目下载
注:这项目是基于cocos2d-x 2.1.3。
下载地址:Air+Hockey.7z
文章地址:http://www.waitingfy.com/?p=608
Tags: 小游戏
608
[…] 还记得这篇文章吗?cocos2d-x Touch 事件应用的一个例子 球跟球之间的碰撞,球跟壁的碰撞使用了简单的向量。球最终停止下来也是因为向量不断地变小。这次我们要改用物理引擎Box2d来让球碰撞!先下载这个项目,打开Release.win32/Air Hockey.win32.exe先来个试玩吧。 […]
[…] 寻路这块在游戏中一直很重要,花了点时间研究了下这个问题,主要参考的是《Data Structures For Game Programmers》,其他的算法用普通Console演示就行了,寻路算法还是用一个界面比较好,最近在学Cocos2d-x,就用它了。用到Cocos2d-x中的基本画线段,画矩形就行了,还有简单的sprite拖动。这demo建了一个线条类,继承CCNode,重写draw方法就行了。在draw方法中简单地调用ccDrawColor4F函数来设置颜色,ccDrawLine来画线条,非常容易,cocos2d-x这些函数封装了opengles中的原始函数,使用非常简单。sprite拖动可以参考这篇文章《cocos2d-x Touch 事件应用的一个例子 》 […]
float force = sqrt(mag_ball + mag_player);
float angle = atan2(diffy, diffx);
setVector(ccp(force * cos(angle), force * sin(angle)));
楼主,你在计算小球碰撞后弧度偏移的时候,这块代码不是很懂,能解释一下吗? 谢谢