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 阅读学习笔记
最新推荐文章于 2024-07-08 16:02:50 发布