cocos2dx 的强大,本博主不需要多表明,直接上代码,但是本人保证 绝对运行不了,因为不会共享资源。
头文件
#include "Box2D/Box2D.h"
#include "GLES-Render.h"
#define PTM_RATIO 32.0f
#include <deque>
typedef deque<b2Body*> deleteBodyDeque;
#define Baiqiu_Tag 100
#define Hit_qiu_max 6
//碰撞检测器
class MyContactListener : public b2ContactListener
{
public:
MyContactListener():_shengyuqiu(Hit_qiu_max){_BodyDeque.clear();};
~MyContactListener(){};
//碰撞开始
void BeginContact(b2Contact*contact)
{ // handle begin event
if( contact->GetFixtureA()->GetBody()->GetUserData() == nullptr )
{
b2Body* CurBody = contact->GetFixtureB()->GetBody();
auto phy = static_cast<CCPhysicsSprite*>(CurBody->GetUserData() );
phy->getParent()->setVisible(false);
_BodyDeque.push_back(CurBody);
}
else if( contact->GetFixtureB()->GetBody()->GetUserData() == nullptr )
{
b2Body* CurBody = contact->GetFixtureA()->GetBody();
auto phy = static_cast<CCPhysicsSprite*>(CurBody->GetUserData() );
phy->getParent()->setVisible(false);
_BodyDeque.push_back(CurBody);
}
}
//碰撞结束
void EndContact(b2Contact* contact)
{ // handle end event
}
void PreSolve(b2Contact* contact,const b2Manifold* oldManifold)
{ // handle pre-solve event
}
void PostSolve(b2Contact* contact,const b2ContactImpulse* impulse)
{ // handle post-solve event
}
//碰撞检测后,在 box2d step()后执行删除body
void deleteBody()
{
for( auto Cur:_BodyDeque )
{
b2World* Wold = Cur->GetWorld();
auto phy = static_cast<CCPhysicsSprite*>(Cur->GetUserData());
if( phy->getTag() == 100 )
{
CCMessageBox("白球进入,Game Over!", "游戏结束");
}
else
{
_shengyuqiu --;
if(_shengyuqiu<=0)
{
CCMessageBox("完成所有目标,Good!", "游戏完成");
}
}
Wold->DestroyBody(Cur);
}
_BodyDeque.clear();
}
private:
deleteBodyDeque _BodyDeque;
int _shengyuqiu;
};
class CTableTennis: public CCLayer
{
public:
CTableTennis():_CurWorld(nullptr),_CurAngle(0.0f),_IsMiaozhun(false){}
~CTableTennis(){ delete _CurWorld; delete _Gles; delete _ContactListener; }
CREATE_FUNC(CTableTennis);
bool init();
void update( float fdt );
void draw();
virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
void registerWithTouchDispatcher(void);
//创建颜色球
void createSEqiu( int Max );
//切换坐标系
b2Vec2 changePos( CCPoint pos )
{
return b2Vec2(pos.x/PTM_RATIO, pos.y/PTM_RATIO);
}
//切换坐标系
CCPoint changePos( b2Vec2 pos )
{
return ccp(pos.x*PTM_RATIO, pos.y*PTM_RATIO);
}
//根据box2d Body创建台球精灵
bool createTaiqiu( const char* SpriteName,b2Body* body_,int Tag = 0 );
//创建球洞的刚体,用于检测进洞
void createCheckeD();
//画瞄准虚线
void drawDottedLine( CCPoint startPoint, CCPoint endPoint );
//更新瞄准虚线
void updateDottedLine( CCPoint startPoint, CCPoint endPoint, CCDrawNode* CurNode = nullptr );
//计算虚线的位置以及角度
CCPoint mathDottedLineEnd( float step, float angle );
private:
b2World* _CurWorld;
GLESDebugDraw* _Gles;
b2Body* _CurBaiqiu;
MyContactListener* _ContactListener;
float _CurAngle;
CCRect _miaozhunRect;
CCRect _yongliRect;
CCRect _preYongLi;
CCRect _preYongLi2;
bool _IsMiaozhun;
};
cpp
#include "TableTennis.h"
bool CTableTennis::init()
{
auto winSize = CCDirector::sharedDirector()->getWinSize();
if (!CCLayer::init())
{
return false;
}
_ContactListener = new MyContactListener;
_CurWorld = new b2World(b2Vec2(0,0));
_CurWorld->SetAllowSleeping(true);
_CurWorld->SetContinuousPhysics(true);
_CurWorld->SetContactListener(_ContactListener);
GB2ShapeCache::sharedGB2ShapeCache()->addShapesWithFile("NewActivity/qiutai_box2d.plist");
CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("NewActivity/billiards.plist");
b2BodyDef _bodydef;
_bodydef.position.Set((winSize.width*0.5f- 480.0f)/PTM_RATIO, 0);
b2Body* taiqiu = _CurWorld->CreateBody(&_bodydef);
GB2ShapeCache::sharedGB2ShapeCache()->addFixturesToBody(taiqiu, "qiutai");
_bodydef.type = b2_dynamicBody;
_bodydef.linearDamping = 0.8f;
//_bodydef.angularDamping = 0.1f;
b2CircleShape cs;
cs.m_radius = 0.48f;
_bodydef.position.Set((winSize.width* 0.5f - 213.0f)/PTM_RATIO, 265.0f/PTM_RATIO);
_bodydef.bullet = true;
auto zuoqiu = _CurWorld->CreateBody(&_bodydef);
b2FixtureDef zuoqiufde;
zuoqiufde.shape =&cs;
zuoqiufde.friction = 0.0f;
zuoqiufde.density = 10.0f;
zuoqiufde.restitution = 0.98f;
zuoqiu->CreateFixture(&zuoqiufde);
_CurBaiqiu = zuoqiu;
scheduleUpdate();
setTouchEnabled(true);
auto taiqiuzhuo = CCPhysicsSprite::createWithSpriteFrameName("qiutai.png");
taiqiuzhuo->setAnchorPoint(ccp(0,0));
taiqiuzhuo->setB2Body(taiqiu);
taiqiuzhuo->setPTMRatio(PTM_RATIO);
taiqiu->SetUserData(taiqiuzhuo);
addChild(taiqiuzhuo);
createTaiqiu( "baiqiu.png", _CurBaiqiu, Baiqiu_Tag );
createSEqiu(Hit_qiu_max);
createCheckeD();
drawDottedLine( changePos(_CurBaiqiu->GetPosition()), mathDottedLineEnd( 430.0f, _CurAngle ) );
_miaozhunRect = CCRect(0,0, winSize.width, winSize.height );
_yongliRect = CCRect(taiqiuzhuo->getPositionX(), taiqiuzhuo->getPositionY()+52.0f, 120.0f, 400.0f );
auto liliangkuangdise = CCSprite::createWithSpriteFrameName("liliangkuangdise.png");
liliangkuangdise->setPosition(ccp( taiqiuzhuo->getPositionX()+20.0f, taiqiuzhuo->getPositionY()+taiqiuzhuo->getContentSize().height*0.5f ));
addChild(liliangkuangdise,100);
auto liliangtiao = CCSprite::createWithSpriteFrameName("liliangtiao1.png");
liliangtiao->setAnchorPoint(ccp(0.5f,0.0f));
liliangtiao->setPosition(ccp(liliangkuangdise->getPositionX(), liliangkuangdise->getPositionY() + liliangtiao->getContentSize().height * 0.5f-2) );
liliangtiao->setRotation(180.0f);
_preYongLi = liliangtiao->getTextureRect();
liliangtiao->setTextureRect( CCRectMake(_preYongLi.origin.x, _preYongLi.origin.y, _preYongLi.size.width, _preYongLi.size.height*0.0f) );
addChild(liliangtiao,100,111 );
auto liliangkuang = CCSprite::createWithSpriteFrameName("liliangkuang1.png");
liliangkuang->setPosition(liliangkuangdise->getPosition());
addChild(liliangkuang,101);
auto liliangkuang2dise = CCSprite::createWithSpriteFrameName("liliangkuang2dise.png");
liliangkuang2dise->setPosition(ccp( winSize.width * 0.5f, 530.0f ));
addChild(liliangkuang2dise,100,201);
auto liliangtiao2 = CCSprite::createWithSpriteFrameName("liliangtiao2.png");
liliangtiao2->setAnchorPoint(ccp(0,0.5f));
liliangtiao2->setPosition(ccp( winSize.width * 0.5f-liliangtiao2->getContentSize().width*0.5f, 530.0f ));
_preYongLi2 = liliangtiao2->getTextureRect();
liliangtiao2->setTextureRect( CCRectMake(_preYongLi2.origin.x, _preYongLi2.origin.y, 0, _preYongLi2.size.height));
addChild(liliangtiao2,100,202);
auto liliangkuang2 = CCSprite::createWithSpriteFrameName("liliangkuang2.png");
liliangkuang2->setPosition(ccp( winSize.width * 0.5f, 530.0f ));
addChild(liliangkuang2,100,203);
for (int i = 0; i<3; ++i)
{
getChildByTag(i+201)->setVisible(false);
}
return true;
}
void CTableTennis::update( float fdt )
{
_CurWorld->Step( fdt, 8, 1 );
_ContactListener->deleteBody();
for (b2Body* Cur = _CurWorld->GetBodyList(); Cur; Cur = Cur->GetNext() )
{
if ( Cur->GetType() == b2_dynamicBody && Cur->IsAwake() == true )
{
if( abs(Cur->GetLinearVelocity().x) < 0.2f && abs(Cur->GetLinearVelocity().y) < 0.2f )
{
Cur->SetAwake(false);
}
}
}
if(_IsMiaozhun)
{
for (b2Body* Cur = _CurWorld->GetBodyList(); Cur; Cur = Cur->GetNext() )
{
if ( Cur->GetType() == b2_dynamicBody && Cur->IsAwake() == true )
{
return;
}
}
_IsMiaozhun = false;
}
}
void CTableTennis::draw()
{
CCLayer::draw();
}
bool CTableTennis::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
if (_IsMiaozhun)
{
return false;
}
return true;
}
void CTableTennis::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent)
{
if (_yongliRect.containsPoint(pTouch->getStartLocation()))
{
auto juli = pTouch->getStartLocation().y - pTouch->getLocation().y;
if (juli<0) {
juli = 0;
}
else if( juli > _preYongLi.size.height )
{
juli = _preYongLi.size.height;
}
auto liliangtiao = static_cast<CCSprite*>(getChildByTag(111));
liliangtiao->setTextureRect( CCRectMake(_preYongLi.origin.x, _preYongLi.origin.y, _preYongLi.size.width, juli) );
for (int i = 0; i<3; ++i)
{
getChildByTag(i+201)->setVisible(true);
}
float prelidu = juli/_preYongLi.size.height;
liliangtiao = static_cast<CCSprite*>(getChildByTag(202));
liliangtiao->setTextureRect( CCRectMake(_preYongLi2.origin.x, _preYongLi2.origin.y, _preYongLi2.size.width*prelidu, _preYongLi2.size.height) );
}
else if (_miaozhunRect.containsPoint(pTouch->getStartLocation()))
{
if (_miaozhunRect.containsPoint(pTouch->getLocation()))
{
auto startPos = changePos(_CurBaiqiu->GetPosition());
updateDottedLine( startPos, pTouch->getLocation() );
}
}
}
void CTableTennis::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
{
if (_yongliRect.containsPoint(pTouch->getStartLocation()))
{
auto liliangtiao = static_cast<CCSprite*>(getChildByTag(111));
auto CurSize = liliangtiao->getTextureRect().size.height;
float prelidu = CurSize/_preYongLi.size.height;
_CurBaiqiu->SetLinearVelocity( changePos( ccpMult( ccpForAngle(_CurAngle) , 1500.0f*prelidu)) );
liliangtiao->setTextureRect( CCRectMake(_preYongLi.origin.x, _preYongLi.origin.y, _preYongLi.size.width, 0) );
if (prelidu != 0.0f )
{
_IsMiaozhun = true;
getChildByTag( 88 )->setVisible(false);
getChildByTag( 99 )->setVisible(false);
getChildByTag( 10 )->setVisible(false);
}
for (int i = 0; i<3; ++i)
{
getChildByTag(i+201)->setVisible(false);
}
}
}
void CTableTennis::registerWithTouchDispatcher(void)
{
CCTouchDispatcher* pDispatcher = CCDirector::sharedDirector()->getTouchDispatcher();
pDispatcher->addTargetedDelegate(this, -128, true);
CCLayer::registerWithTouchDispatcher();
}
void CTableTennis::createSEqiu( int Max )
{
b2BodyDef _bodydef;
_bodydef.type = b2_dynamicBody;
_bodydef.linearDamping = 0.8f;
_bodydef.bullet = true;
b2CircleShape cs;
b2FixtureDef zuoqiufde;
cs.m_radius = 0.48f;
zuoqiufde.shape = &cs;
zuoqiufde.friction = 0.0f;
zuoqiufde.density = 10.0f;
zuoqiufde.restitution = 0.98f;
auto winSize = CCDirector::sharedDirector()->getWinSize();
CCPoint array[6] = { ccp(0.0f,0.0f), ccp( 30.0f, 15.0f ), ccp(30.0f,-15.0f),
ccp(60.0f,30.0f), ccp(60.0f,0.0f), ccp(60.0f,-30.0f) };
std::string spriteName[6] = { "huangqiu.png", "lanqiu.png", "lvqiu.png",
"hongqiu.png", "heiqiu.png", "ziqiu.png" };
for (int i = 0 ; i<Max; ++i)
{
b2Vec2 CurPos = changePos(ccp(winSize.width*0.5f + 213.0f + array[i].x, 265.0f+array[i].y));
_bodydef.position.Set(CurPos.x,CurPos.y);
auto zuoqiu = _CurWorld->CreateBody(&_bodydef);
zuoqiu->CreateFixture(&zuoqiufde);
createTaiqiu( spriteName[i].c_str(), zuoqiu );
}
}
bool CTableTennis::createTaiqiu( const char* SpriteName,b2Body* body_,int Tag )
{
b2Body* TempBody = body_;
if (!TempBody)
{
return false;
}
auto Node = CCNode::create();
addChild(Node);
auto baiqiu = CCPhysicsSprite::createWithSpriteFrameName(SpriteName);
if (!baiqiu)
{
return false;
}
auto shadow = CCPhysicsSprite::createWithSpriteFrameName("qiuying.png");
if (!shadow)
{
return false;
}
//taiqiuzhuo->setAnchorPoint(ccp(0,0));
baiqiu->setB2Body(body_);
shadow->setB2Body(body_);
body_->SetUserData(baiqiu);
baiqiu->setPTMRatio(PTM_RATIO);
shadow->setPTMRatio(PTM_RATIO);
Node->addChild(shadow,0,Tag);
Node->addChild(baiqiu,0,Tag);
return true;
}
void CTableTennis::createCheckeD()
{
b2BodyDef _bodydef;
_bodydef.position.Set(0, 0);
b2CircleShape cs;
cs.m_radius = 0.1f;
b2FixtureDef def;
def.shape = &cs;
def.density = 0.0f;
CCPoint array[6] = { ccp(-430.0f,220.0f), ccp( -430.0f,-220.0f ), ccp(0.0f,-230.0f),
ccp(430.0f,-220.0f), ccp(430.0f,220.0f), ccp(0.0f,230.0f) };
auto winSize = CCDirector::sharedDirector()->getWinSize();
for (int i = 0 ; i<6; ++i)
{
b2Vec2 CurPos = changePos(ccp(winSize.width*0.5f + array[i].x, 266.0f +array[i].y));
_bodydef.position.Set(CurPos.x,CurPos.y);
auto zuoqiu = _CurWorld->CreateBody(&_bodydef);
zuoqiu->CreateFixture(&def);
}
}
void CTableTennis::drawDottedLine( CCPoint startPoint, CCPoint endPoint )
{
auto drawNode = CCDrawNode::create();
updateDottedLine(startPoint,endPoint,drawNode );
drawNode->setZOrder(30);
drawNode->setTag(10);
this->addChild(drawNode);
}
void CTableTennis::updateDottedLine( CCPoint startPoint, CCPoint endPoint, CCDrawNode* CurNode )
{
CCDrawNode* drawNode = CurNode;
if (!CurNode)
{
drawNode = static_cast<CCDrawNode*>(getChildByTag(10));
}
drawNode->setVisible(true);
drawNode->clear();
float stepLength = 6.0f;
float spaceLength = 15;
auto CurVector = ccpNormalize( ccpSub(endPoint, startPoint) );
CCPoint nextPoint = startPoint;
CCPoint dictPoint;
while (true)
{
float endpos =ccpLength(ccpSub(endPoint, nextPoint));
if ( endpos <= spaceLength )
{
break;
}
endpos =ccpLength(ccpSub(endPoint, dictPoint));
if ( endpos <= stepLength )
{
break;
}
dictPoint = ccpAdd(nextPoint, ccpMult(CurVector, stepLength));
drawNode->drawSegment(nextPoint, dictPoint, 1, ccc4f(1.0f, 1.0f, 1.0f, 0.3f));
nextPoint = ccpAdd(dictPoint, ccpMult(CurVector, spaceLength));
}
auto zhunxing = getChildByTag( 88 );
if (!zhunxing)
{
zhunxing = CCSprite::createWithSpriteFrameName( "zhunxing.png" );
addChild(zhunxing, 20, 88 );
}
zhunxing->setVisible(true);
zhunxing->setPosition(endPoint);
auto qGan = getChildByTag( 99 );
if (!qGan)
{
qGan = CCSprite::createWithSpriteFrameName( "qiugan.png" );
qGan->setAnchorPoint( ccp(1.05f,0.5f) );
addChild(qGan, 20, 99 );
}
qGan->setVisible(true);
qGan->setPosition(startPoint);
_CurAngle = ccpToAngle(CurVector);
qGan->setRotation( CC_RADIANS_TO_DEGREES( -_CurAngle ) );
}
CCPoint CTableTennis::mathDottedLineEnd( float step, float angle )
{
auto StartPos_ = changePos(_CurBaiqiu->GetPosition());
CCPoint endPos_;
endPos_.x = step * cosf( angle ) + StartPos_.x;
endPos_.y = step * sinf(angle) + StartPos_.y;
return endPos_;
}
少量注释,看不懂那就没办法,没那个时间写!
运行gif