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