cocos2dx 2.2.6 + box2d 成就600行代码的 完整桌球游戏

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

 

你可能感兴趣的:(cocos2dx)