class Ball : public CCSprite
{
CCPoint m_velocity;
public:
Ball(void);
virtual ~Ball(void);
float radius();
// 用來移動精靈對象
void move(float delta);
// 對與paddle做碰撞處理
void collideWithPaddle(Paddle* paddle);
public:
void setVelocity(CCPoint velocity){m_velocity = velocity;}
CCPoint getVelocity(){return m_velocity;}
public:
// 綁定一個2d紋理
static Ball* ballWithTexture(CCTexture2D* aTexture);
};
// 這裏我們綁定給定的圖片紋理,在不用時自動釋放精靈對象
Ball* Ball::ballWithTexture(CCTexture2D* aTexture)
{
Ball* pBall = new Ball();
pBall->initWithTexture(aTexture);
pBall->autorelease();
return pBall;
}
void Ball::move(float delta)
{
// 計算移動距離,並設置球的位置
this->setPosition( ccpAdd(getPosition(), ccpMult(m_velocity, delta)) );
// 若球的位置越過了左邊、右邊的可視區域邊界,修正球的位置並把速度的x方向反向處理
if (getPosition().x > VisibleRect::right().x - radius())
{
setPosition( ccp( VisibleRect::right().x - radius(), getPosition().y) );
m_velocity.x *= -1;
}
else if (getPosition().x < VisibleRect::left().x + radius())
{
setPosition( ccp(VisibleRect::left().x + radius(), getPosition().y) );
m_velocity.x *= -1;
}
}
// 設定板子的邊界,
CCRect Paddle::rect()
{
CCSize s = getTexture()->getContentSize();
return CCRectMake(-s.width / 2, -s.height / 2, s.width, s.height);
}
void Ball::collideWithPaddle(Paddle* paddle)
{
// 獲取板子的邊界,精靈的默認錨點爲(0.5,0.5),position就是中心點,這裏還原爲原來的paddle邊界,取得邊界值
CCRect paddleRect = paddle->rect();
paddleRect.origin.x += paddle->getPosition().x;
paddleRect.origin.y += paddle->getPosition().y;
float lowY = paddleRect.getMinY();
float midY = paddleRect.getMidY();
float highY = paddleRect.getMaxY();
float leftX = paddleRect.getMinX();
float rightX = paddleRect.getMaxX();
// 球的x是否在碰撞範圍內
if (getPosition().x > leftX && getPosition().x < rightX) {
bool hit = false;
float angleOffset = 0.0f;
if (getPosition().y > midY && getPosition().y <= highY + radius())
{
// 碰下面的板子,設定角度偏移
setPosition( ccp(getPosition().x, highY + radius()) );
hit = true;
angleOffset = (float)M_PI / 2;
}
else if (getPosition().y < midY && getPosition().y >= lowY - radius())
{
// 碰撞上面的板子,設定角度偏移
setPosition( ccp(getPosition().x, lowY - radius()) );
hit = true;
angleOffset = -(float)M_PI / 2;
}
if (hit)
{
// 重定向速度方向和位置(下面怎麼計算的不理解,物理知識弱爆了)
CCPoint cp1 = ccpSub(paddle->getPosition(), getPosition());
float angle1 = ccpToAngle(cp1);
float hitAngle = angle1 + angleOffset;
float scalarVelocity = ccpLength(m_velocity) * 1.05f;
float angle2 = ccpToAngle(m_velocity);
float velocityAngle = -angle2 + 0.5f * hitAngle;
m_velocity = ccpMult(ccpForAngle(velocityAngle), scalarVelocity);
}
}
}
typedef enum tagPaddleState
{
kPaddleStateGrabbed,
kPaddleStateUngrabbed
} PaddleState;
class Paddle : public CCSprite, public CCTargetedTouchDelegate
{
PaddleState m_state;
public:
Paddle(void);
virtual ~Paddle(void);
CCRect rect();
bool initWithTexture(CCTexture2D* aTexture);
virtual void onEnter();
virtual void onExit();
bool containsTouchLocation(CCTouch* touch);
virtual bool ccTouchBegan(CCTouch* touch, CCEvent* event);
virtual void ccTouchMoved(CCTouch* touch, CCEvent* event);
virtual void ccTouchEnded(CCTouch* touch, CCEvent* event);
virtual CCObject* copyWithZone(CCZone *pZone);
virtual void touchDelegateRetain();
virtual void touchDelegateRelease();
static Paddle* paddleWithTexture(CCTexture2D* aTexture);
};
// 給paddle增加綁定紋理
Paddle* Paddle::paddleWithTexture(CCTexture2D* aTexture)
{
Paddle* pPaddle = new Paddle();
pPaddle->initWithTexture( aTexture );
pPaddle->autorelease();
return pPaddle;
}
// 設定未捕獲狀態
bool Paddle::initWithTexture(CCTexture2D* aTexture)
{
if( CCSprite::initWithTexture(aTexture) )
{
m_state = kPaddleStateUngrabbed;
}
return true;
}
// 註冊屏幕觸摸處理事件
onEnter : CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, true);
onExit : CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
// 若paddle包含數目點,設置捕獲狀態
bool Paddle::ccTouchBegan(CCTouch* touch, CCEvent* event)
{
if (m_state != kPaddleStateUngrabbed) return false;
if ( !containsTouchLocation(touch) ) return false;
m_state = kPaddleStateGrabbed;
return true;
}
// 捕獲paddle後,重新設置paddle位置
void Paddle::ccTouchMoved(CCTouch* touch, CCEvent* event)
{
CCAssert(m_state == kPaddleStateGrabbed, "Paddle - Unexpected state!");
CCPoint touchPoint = touch->getLocation();
setPosition( ccp(touchPoint.x, getPosition().y) );
}
// 釋放捕獲,設置狀態
void Paddle::ccTouchEnded(CCTouch* touch, CCEvent* event)
{
CCAssert(m_state == kPaddleStateGrabbed, "Paddle - Unexpected state!");
m_state = kPaddleStateUngrabbed;
}
// 創建paddle的copy處理
CCObject* Paddle::copyWithZone(CCZone *pZone)
{
this->retain();
return this;
}
void Paddle::touchDelegateRetain()
{
this->retain();
}
void Paddle::touchDelegateRelease()
{
this->release();
}
// 測試場景
class PongScene : public TestScene
{
public:
PongScene();
virtual void runThisTest();
virtual void MainMenuCallback(CCObject* pSender);
};
class Ball;
class PongLayer : public CCLayer
{
private:
Ball* m_ball;
CCArray* m_paddles;
CCPoint m_ballStartingVelocity;
public:
PongLayer();
~PongLayer();
void resetAndScoreBallForPlayer(int player);
void doStep(float delta);
};
PongLayer::PongLayer()
{
m_ballStartingVelocity = ccp(20.0f, -100.0f);
// 創建球精靈,並綁定紋理,設定速度值
m_ball = Ball::ballWithTexture( CCTextureCache::sharedTextureCache()->addImage(s_Ball) );
m_ball->setPosition( VisibleRect::center() );
m_ball->setVelocity( m_ballStartingVelocity );
addChild( m_ball );
m_ball->retain();
// 創建平板的紋理,綁定到精靈上
CCTexture2D* paddleTexture = CCTextureCache::sharedTextureCache()->addImage(s_Paddle);
CCArray *paddlesM = CCArray::createWithCapacity(4);
Paddle* paddle = Paddle::paddleWithTexture(paddleTexture);
paddle->setPosition( ccp(VisibleRect::center().x, VisibleRect::bottom().y + 15) );
paddlesM->addObject( paddle );
paddle = Paddle::paddleWithTexture( paddleTexture );
paddle->setPosition( ccp(VisibleRect::center().x, VisibleRect::top().y - kStatusBarHeight - 15) );
paddlesM->addObject( paddle );
paddle = Paddle::paddleWithTexture( paddleTexture );
paddle->setPosition( ccp(VisibleRect::center().x, VisibleRect::bottom().y + 100) );
paddlesM->addObject( paddle );
paddle = Paddle::paddleWithTexture( paddleTexture );
paddle->setPosition( ccp(VisibleRect::center().x, VisibleRect::top().y - kStatusBarHeight - 100) );
paddlesM->addObject( paddle );
// 將創建的4個精靈平板加入到數組中
m_paddles = (CCArray*)paddlesM->copy();
// 將平板對象加入到場景層中
CCObject* pObj = NULL;
CCARRAY_FOREACH(m_paddles, pObj)
{
paddle = (Paddle*)(pObj);
if(!paddle)
break;
addChild(paddle);
}
// 每幀調度doStep方法
schedule( schedule_selector(PongLayer::doStep) );
}
// 重置球數據,包括位置和速度
void PongLayer::resetAndScoreBallForPlayer(int player)
{
m_ballStartingVelocity = ccpMult(m_ballStartingVelocity, -1.0f);
m_ball->setVelocity( m_ballStartingVelocity );
m_ball->setPosition( VisibleRect::center() );
}
void PongLayer::doStep(float delta)
{
// 移動球
m_ball->move(delta);
// 檢測球與平板的碰撞與否,並作相應的處理
Paddle* paddle = NULL;
CCObject* pObj = NULL;
CCARRAY_FOREACH(m_paddles, pObj)
{
paddle = (Paddle*)(pObj);
if(!paddle)
break;
m_ball->collideWithPaddle( paddle );
}
// 球的y值超過了可視區域,重新球數據
if (m_ball->getPosition().y > VisibleRect::top().y - kStatusBarHeight + m_ball->radius())
resetAndScoreBallForPlayer( kLowPlayer );
else if (m_ball->getPosition().y < VisibleRect::bottom().y-m_ball->radius())
resetAndScoreBallForPlayer( kHighPlayer );
// 每幀繪製球
m_ball->draw();
}
TouchTest 閱讀學習筆記
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.