本文是根据cocos2d-x 2.0.1 中的TouchesTest写的一个反弹例子。 有区别的地方。 了解反弹原理,假设小球的运动速度向量是v 那小球运动的距离s=v+ball_p(小球的向量距离);
第一个个要点是小球的碰撞:
首先要检查小球碰到木板否,
其次才是下面的,
如果小球碰到木板的上面或是下面,可以让速度向量在y轴上反向递减,也就是v .y *= -1;
如果小球碰到木板的左边或是右边,可以让速度向量在x轴上反向递减,也就是v.x *=-1;
还有第二个要点是木板的移动:
首先要让木板获取touch代理
木板的移动,然后要检查移动的焦点是否在木板内
最后看你希望是只在水平方向上移动还是随你的想法移动。
下面是附上的代码,有不足之处可以指出来。
GameLayer.h
#pragma once
#include "cocos2d.h"
#include "Ball.h"
#include "Paddle.h"
USING_NS_CC;
class GameLayer : public cocos2d::CCLayer
{
public:
GameLayer(void);
~GameLayer(void);
void doStep(float dela);
protected:
Ball *ball;
CCArray *paddles ;
};
#include "GameLayer.h"
static const char s_bg[] = "s_bg.jpg";
static const char s_pd[] ="paddle.png";
void GameLayer::doStep( float dela )
{
ball->move(dela);
CCObject *obj = NULL;
CCARRAY_FOREACH(paddles,obj)
{
Paddle *paddle = (Paddle*)obj;
ball->collidePaddle(paddle,dela);
}
ball->draw();
}
GameLayer::GameLayer(void)
{
CCSprite *b_sprite = CCSprite::create(s_bg);
CCSize size = CCDirector::sharedDirector()->getWinSize();
b_sprite->setPosition(ccp(size.width/2,size.height/2));
this->addChild(b_sprite);
ball = Ball::initBall();
ball->retain();
ball->setVelocity(CCPointMake(size.width/2,size.height/2-10));
CCTexture2D *aTexture = CCTextureCache::sharedTextureCache()->addImage(s_pd);
Paddle *paddle = Paddle::initPaddle(aTexture);
paddle->setPosition(ccp(50,size.height/2));
paddles = new CCArray();
paddles->retain();
paddles->addObject(paddle);
this->addChild(paddle);
this->addChild(ball);
schedule(schedule_selector(GameLayer::doStep));
}
GameLayer::~GameLayer(void)
{
ball->release();
ball = NULL;
paddles->release();
paddles = NULL;
}
#pragma once
#include "cocos2d.h"
USING_NS_CC;
class Paddle :public cocos2d::CCSprite, public CCTargetedTouchDelegate
{
public:
Paddle(void);
~Paddle(void);
static Paddle *initPaddle(CCTexture2D *aTexture);
bool initWithTexture(CCTexture2D* aTexture);
bool containsTouchLocation(CCTouch* touch);
virtual bool ccTouchBegan(CCTouch* touch, CCEvent* event);
virtual void ccTouchMoved(CCTouch* touch, CCEvent* event);
CCRect rect();
virtual void onEnter();
virtual void onExit();
};
paddle.cpp
#include "Paddle.h"
Paddle::Paddle(void)
{
}
Paddle::~Paddle(void)
{
}
cocos2d::CCRect Paddle::rect()
{
CCSize s = getTexture()->getContentSize();
return CCRectMake(-s.width/2,-s.height/2,s.width,s.height);
}
void Paddle::onEnter()
{
CCDirector *direct = CCDirector::sharedDirector();
direct->getTouchDispatcher()->addTargetedDelegate(this,0,true);
CCSprite::onEnter();
}
void Paddle::onExit()
{
CCDirector *direct = CCDirector::sharedDirector();
direct->getTouchDispatcher()->removeDelegate(this);
CCSprite::onExit();
}
bool Paddle::initWithTexture( CCTexture2D* aTexture )
{
if (CCSprite::initWithTexture(aTexture))
{
}
return true;
}
Paddle * Paddle::initPaddle(CCTexture2D* aTexture)
{
Paddle *paddle = new Paddle();
paddle->initWithTexture(aTexture);
paddle->autorelease();
return paddle;
}
bool Paddle::containsTouchLocation( CCTouch* touch )
{
return CCRect::CCRectContainsPoint(rect(),convertTouchToNodeSpaceAR(touch));
}
bool Paddle::ccTouchBegan( CCTouch* touch, CCEvent* event )
{
if(!containsTouchLocation(touch)) return false;
return true;
}
void Paddle::ccTouchMoved( CCTouch* touch, CCEvent* event )
{
CCDirector *direct = CCDirector::sharedDirector();
CCPoint p = direct->convertToGL(touch->locationInView());
this->setPosition(ccp(p.x,this->getPosition().y));
}
Ball.h
#pragma once
#include "cocos2d.h"
#include "Paddle.h"
USING_NS_CC;
class Ball :public cocos2d::CCSprite
{
public:
Ball(void);
~Ball(void);
static Ball * initBall();
float radius();
void move(float dela);
void collidePaddle(Paddle *paddle,float dela);
public:
void setVelocity(CCPoint velocity){m_velocity = velocity;};
CCPoint getVelocity(void){return m_velocity;};
protected:
CCPoint m_velocity; //球所在的向量
};
Ball.cpp
#include "Ball.h"
#include "cocos2d.h"
USING_NS_CC;
static const char s_ball[] ="ball_30_30.png";
Ball::Ball(void)
{
if(!this->initWithFile(s_ball))
{
CCLOG("file is not exist");
}
}
Ball::~Ball(void)
{
m_velocity .release();
}
float Ball::radius()
{
return this->getContentSize().width/2;
}
void Ball::move(float dela)
{
CCSize size = CCDirector::sharedDirector()->getWinSize();
this->setPosition(ccpAdd(getPosition(),ccpMult(m_velocity,dela)));
int x = getPosition().x;
int y = getPosition().y;
int r = radius();
if(x>=size.width-radius())
{
this->setPosition(ccp(size.width-radius(),y));
m_velocity.x *=-1;
}else if (x<=radius())
{
this->setPosition(ccp(radius(),y));
m_velocity.x *=-1;
}else if (y>=size.height-radius())
{
this->setPosition(ccp(x,size.height-radius()));
m_velocity.y *=-1;
}else if (y<=radius())
{
this->setPosition(ccp(x,radius()));
m_velocity.y *=-1;
}
}
Ball * Ball::initBall()
{
Ball * ball = new Ball();
return ball;
}
void Ball::collidePaddle( Paddle *paddle,float dela )
{
int bx = this->getPosition().x;
int by = this->getPosition().y;
CCRect rect = paddle->rect();
rect.origin.x += paddle->getPosition().x;
rect.origin.y += paddle->getPosition().y;
int leftX = CCRect::CCRectGetMinX(rect);
int midX =CCRect::CCRectGetMidX(rect);
int rightX = CCRect::CCRectGetMaxX(rect);
int topY = CCRect::CCRectGetMaxY(rect);
int midY =CCRect::CCRectGetMidY(rect);
int lowY =CCRect::CCRectGetMinY(rect);
if (leftX<=bx&&bx<=rightX)
{
if (lowY-radius()<by&&by<lowY)
{
this->setPosition(ccp(bx,lowY-radius()));
m_velocity.y *=-1;
}else if (midY<by &&by<topY+radius())
{
this->setPosition(ccp(bx,topY+radius()));
m_velocity.y *=-1;
}
}else if (lowY<=by && by<=topY)
{
if (leftX-radius()<bx&&bx<leftX)
{
this->setPosition(ccp(leftX-radius(),by));
m_velocity.x *=-1;
}else if (rightX<bx &&bx<rightX+radius())
{
this->setPosition(ccp(rightX+radius(),by));
m_velocity.x *=-1;
}
}
}