TouchTest 閱讀學習筆記


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();
} 








發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章