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

 

posted @ 2015-01-19 16:20  VindyLeong  阅读(1473)  评论(0编辑  收藏  举报