游戏主场景:PlayScene

一、创建物理场景

物理场景跟关卡界面是类似的

//创建一个物理场景
_scene = Scene::createWithPhysics();
//_scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
//设置物理世界的重力
_scene->getPhysicsWorld()->setGravity(Vect(0, -1300));
//添加层到物理世界中
PlayScene *layer = PlayScene::create();
_scene->addChild(layer);
创建线状刚体

void PlayScene::initPhysicWorld(){
auto visibleSize = Director::getInstance()->getVisibleSize();
auto origin = Director::getInstance()->getVisibleOrigin();
//创建一个静态的线状刚体
auto body = PhysicsBody::createEdgeSegment(origin, Point(visibleSize.width, 0), PHYSICSBODY_MATERIAL_DEFAULT, 1);
//设置弹性 1-完全
body->getShape(0)->setRestitution(1);
//设置摩擦力
body->getShape(0)->setFriction(0);
//设置body是否受引力影响
body->setGravityEnable(false);
//类别标示掩码
body->setCategoryBitmask(0x01);
body->setCollisionBitmask(0x01);
body->setContactTestBitmask(0x01);
auto edgeNode = Node::create();
edgeNode->setPosition(0, visibleSize.height/2);
edgeNode->setPhysicsBody(body);
edgeNode->setTag(edgeNodeTag);
this->addChild(edgeNode, 2);
}
还有设置碰撞监听等

二、初始界面

1、初始球、圆盘等

//背景
auto *spriteBG = Sprite::create(PLAY_BG);
spriteBG->setPosition(centerPos);
this->addChild(spriteBG,0);
 
//球
ball = Ball::create();
 
//球的初始位置
ball->setPosition(size.width/4, size.height/2 + ball->getConSize().height / 2);
this->addChild(ball,2); 
setBallDefaultColor();

......
//cylinder管理类
m_manager = BaseManager::create();
this->addChild(m_manager,1);

//粒子
ParticleSystem *_emitter = ParticleRain::create();
_emitter->setAutoRemoveOnFinish(true);
_emitter->setPosition(size.width/2,size.height);
this->addChild(_emitter, 5);

//进度
labelTTFCardNumber = LabelTTF::create("0", "HiraKakuProN-w6", 50);
labelTTFCardNumber->setColor(Color3B::WHITE);
labelTTFCardNumber->setPosition(
    Point(size.width / 2, size.height / 2 + labelTTFCardNumber->getContentSize().height + 20));
this->addChild(labelTTFCardNumber, 2);
labelTTFCardNumber->setString(
    StringUtils::format("%d%%", 0));

2、游戏方式介绍

根据不同关卡展示不同玩法

void PlayScene::createPlayWay(){
auto size = Director::getInstance()->getVisibleSize();
auto zeroPos = Director::getInstance()->getVisibleOrigin();
auto centerPos = Point(size.width / 2, size.height / 2);
auto *menu = Menu::create();
menu->setPosition(zeroPos);
if (checkPoint == 1){
auto * menuItemPLay = MenuItemSprite::create(Sprite::create(PLAY_WAY_1), Sprite::create(PLAY_WAY_1), CC_CALLBACK_1(PlayScene::onStart, this));
menuItemPLay->setPosition(centerPos);
menu->addChild(menuItemPLay);
}
else if (checkPoint == 2){
auto * menuItemPLay = MenuItemSprite::create(Sprite::create(PLAY_WAY_2), Sprite::create(PLAY_WAY_2), CC_CALLBACK_1(PlayScene::onStart, this));
menuItemPLay->setPosition(centerPos);
menu->addChild(menuItemPLay);
}
else if (checkPoint == 3){
auto * menuItemPLay = MenuItemSprite::create(Sprite::create(PLAY_WAY_3), Sprite::create(PLAY_WAY_3), CC_CALLBACK_1(PlayScene::onStart, this));
menuItemPLay->setPosition(centerPos);
menu->addChild(menuItemPLay);
}
else if (checkPoint == 4){
auto * menuItemPLay = MenuItemSprite::create(Sprite::create(PLAY_WAY_4), Sprite::create(PLAY_WAY_4), CC_CALLBACK_1(PlayScene::onStart, this));
menuItemPLay->setPosition(centerPos);
menu->addChild(menuItemPLay);
}
else if (checkPoint == 5 ){
auto * menuItemPLay = MenuItemSprite::create(Sprite::create(PLAY_WAY_5), Sprite::create(PLAY_WAY_5), CC_CALLBACK_1(PlayScene::onStart, this));
menuItemPLay->setPosition(centerPos);
menu->addChild(menuItemPLay);
}
else if ( checkPoint == 6){
auto * menuItemPLay = MenuItemSprite::create(Sprite::create(PLAY_WAY_6), Sprite::create(PLAY_WAY_6), CC_CALLBACK_1(PlayScene::onStart, this));
menuItemPLay->setPosition(centerPos);
menu->addChild(menuItemPLay);
}
menu->setTag(playwayTag);
this->addChild(menu,10);
}
3、点击游戏玩法响应,游戏正式开始

void PlayScene::onStart(cocos2d::Ref* pSender){
isGameBegin = true;
//移除介绍游戏方式菜单
this->removeChildByTag(playwayTag);
//播放音乐
playMusicByCheckPoint();
//设置重力
setWorldGravity();
//创建控制按钮
createControlBtn();
//给小球速度
ball->jump();
//进度更新
this->schedule(schedule_selector(PlayScene::addTime), 1.0f, kRepeatForever, 1);
}
三、游戏中

游戏开始有给小球速度,由于刚体设置摩擦力为0,完全弹力等因素影响,小球将无限弹起落下到游戏结束。主要逻辑在碰撞监听函数里实现,不同的关卡游戏失败的逻辑有所区别

bool PlayScene::onContactBegin(PhysicsContact& contact){
auto size = Director::getInstance()->getVisibleSize();
if (!isGameBegin){
return true;
}
//获取碰撞物体
auto body1 = (Sprite *)contact.getShapeA()->getBody()->getNode();
auto body2 = (Sprite *)contact.getShapeB()->getBody()->getNode();
CylinderColor ballColor = normal;
CylinderColor cylinderColor = normal;

//判断是否为球
if (body1->getTag() == ballTag){
    ballColor = ball->getBallColor();
}
if (body2->getTag() == ballTag){
    ballColor = ball->getBallColor();
}

//从圆盘列表里获取当前碰撞圆盘的颜色
list <Cylinder*> cylinderList = m_manager->getCylinderList();
Cylinder* cylinder;
for (list<Cylinder*>::iterator iter = cylinderList.begin(); iter != cylinderList.end(); iter++){
    cylinder = (Cylinder*)*iter;
    if (cylinder->getPosition().x == size.width/4){
        cylinderColor = cylinder->getCylinderColor();
        break;
    }
}
//关卡
switch (checkPoint)
{
case 1:
    //如果颜色不同且圆盘不是最后一个则游戏结束
    if (cylinderColor != normal && cylinderColor != endColor  && cylinderColor != ballColor){
        CocosDenshion::SimpleAudioEngine::sharedEngine()->stopBackgroundMusic();
        GameOver();
        auto endLayer = TransitionFade::create(1, EndLayer::createScene(false, percent));
        Director::getInstance()->replaceScene(endLayer);


        return false;
    }
    else if (cylinderColor == endColor){
        if (CCUserDefault::sharedUserDefault()->getBoolForKey("sound", true)){
            CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect(MUSIC_WIN, false);
        }

        CocosDenshion::SimpleAudioEngine::sharedEngine()->stopBackgroundMusic();

        //设置下一关卡开启
        String *c_str = String::createWithFormat("checkPoint%i", checkPoint + 1);
        CCUserDefault::sharedUserDefault()->setBoolForKey(c_str->getCString(), true);
        //跳转到游戏成功结束界面
        auto endLayer = TransitionFade::create(1, EndLayer::createScene(true, percent));
        Director::getInstance()->replaceScene(endLayer);
        return true;
    }
    break;
case 2:
    //关卡2是要求球与圆盘颜色相反,所以如果相同则失败
    if (cylinderColor != normal && cylinderColor != endColor && cylinderColor == ballColor){
        CocosDenshion::SimpleAudioEngine::sharedEngine()->stopBackgroundMusic();
        GameOver();
        auto endLayer = TransitionFade::create(1, EndLayer::createScene(false, percent));
        Director::getInstance()->replaceScene(endLayer);
        return false;
    }
    else if (cylinderColor != normal && ballColor == normal){
        CocosDenshion::SimpleAudioEngine::sharedEngine()->stopBackgroundMusic();
        GameOver();
        auto endLayer = TransitionFade::create(1, EndLayer::createScene(false, percent));
        Director::getInstance()->replaceScene(endLayer);
        return false;
    }
    else if (cylinderColor == endColor){
        if (CCUserDefault::sharedUserDefault()->getBoolForKey("sound", true)){
            CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect(MUSIC_WIN, false);
        }
        CocosDenshion::SimpleAudioEngine::sharedEngine()->stopBackgroundMusic();

        String *c_str = String::createWithFormat("checkPoint%i", checkPoint + 1);
        CCUserDefault::sharedUserDefault()->setBoolForKey(c_str->getCString(), true);

        auto endLayer = TransitionFade::create(1, EndLayer::createScene(true, percent));
        Director::getInstance()->replaceScene(endLayer);
        return true;
    }
    break;
case 3:
case 4:
case 5:
    //
    if (cylinderColor != normal && cylinderColor != endColor  && cylinderColor != ballColor){
        CocosDenshion::SimpleAudioEngine::sharedEngine()->stopBackgroundMusic();
        GameOver();
        auto endLayer = TransitionFade::create(1, EndLayer::createScene(false, percent));
        Director::getInstance()->replaceScene(endLayer);
        return false;
    }
    else if (cylinderColor == endColor){
        if (CCUserDefault::sharedUserDefault()->getBoolForKey("sound", true)){
            CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect(MUSIC_WIN, false);
        }
        CocosDenshion::SimpleAudioEngine::sharedEngine()->stopBackgroundMusic();

        String *c_str = String::createWithFormat("checkPoint%i", checkPoint + 1);
        CCUserDefault::sharedUserDefault()->setBoolForKey(c_str->getCString(), true);

        auto endLayer = TransitionFade::create(1, EndLayer::createScene(true, percent));
        Director::getInstance()->replaceScene(endLayer);
        return true;
    }
    break;
case 6:
    if (cylinderColor != normal && cylinderColor != endColor  && cylinderColor != ballColor){
        CocosDenshion::SimpleAudioEngine::sharedEngine()->stopBackgroundMusic();
        GameOver();
        auto endLayer = TransitionFade::create(1, EndLayer::createScene(false, percent));
        Director::getInstance()->replaceScene(endLayer);
        return false;
    }
    else if (cylinderColor == endColor){
        if (CCUserDefault::sharedUserDefault()->getBoolForKey("sound", true)){
            CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect(MUSIC_WIN, false);
        }
        CocosDenshion::SimpleAudioEngine::sharedEngine()->stopBackgroundMusic();

        auto scene = TransitionFade::create(1, LeaveLayer::createScene());
        Director::getInstance()->replaceScene(scene);
        return true;
    }
    break;
default:
    break;
}
//球自旋转
ball->rotateAction();
//圆盘管理
m_manager->update(0);
return true;

}