cocos2d-x scene场景的切换

上篇中我们添加两个新类,但是类并没有做任何事情事情,这篇文章主要介绍如何切换游戏的画面,比如从开始切换到游戏界面。

还是命令行新建工程

cocos new SimpleDemo  -p com.MyCompany.SimpleDemo -l cpp -d ./MyCompany

cocos compile -s ./MyCompany/SimpleDemo -p linux -m debug -o ./MyCompany/SimpleDemo/bin

建立完成之后生成四个class文件,前面的文章有介绍,这里不再介绍。

AppDelegate.cpp基本上不需要修改,可能根据需要修改屏幕尺寸。

打开HelloWorldScene.cpp文件

#include "HelloWorldScene.h"
#include "SimpleAudioEngine.h"
#include "Chapter2Level1.h"
#include "Chapter3.h"
#include "Chapter2.h"

USING_NS_CC;

Scene* HelloWorld::createScene()
{
    // 'scene' is an autorelease object
    auto scene = Scene::create();
    
    // 'layer' is an autorelease object
    auto layer = HelloWorld::create();

    // add layer as a child to scene
    scene->addChild(layer);

    // return the scene
    return scene;
}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }
    
    auto visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();

    /////////////////////////////
    // 2. add a menu item with "X" image, which is clicked to quit the program
    //    you may modify it.

    // add a "close" icon to exit the progress. it's an autorelease object
    auto closeItem = MenuItemImage::create("CloseNormal.png", "CloseSelected.png",
                                CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
    
    closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
                                origin.y + closeItem->getContentSize().height/2));

    // create menu, it's an autorelease object
    auto menu = Menu::create(closeItem, NULL);
    menu->setPosition(Vec2::ZERO);
    this->addChild(menu, 1);

    // add main menu
	auto mainMenu = Menu::create();
	int index = 2;

	std::vector vChapters = {"Chapter 2", "Chapter 3"};
	std::vector vMenuItems;
	// create the menu items for each other
	for (unsigned int i = 0; i < vChapters.size(); i++) {
    	auto itemLabel = LabelTTF::create(vChapters.at(i), "Arial", 32);
		auto menuItemLabel = MenuItemLabel::create(itemLabel);
		menuItemLabel->setPosition(Vec2(origin.x+visibleSize.width/2, origin.x+visibleSize.height/2).x,
            (Vec2(origin.x+visibleSize.width/2, origin.y+visibleSize.height).y - (++index) * 40));
		vMenuItems.push_back(menuItemLabel);
	}

	// create the callback for eac menu item
	vMenuItems.at(0)->setCallback([&](cocos2d::Ref *sender) {
		Director::getInstance()->replaceScene(Chapter2::createScene());
	});
	vMenuItems.at(1)->setCallback([&](cocos2d::Ref *sender) {
		Director::getInstance()->replaceScene(Chapter3::createScene());
	});

	for (unsigned i = 0; i < vMenuItems.size(); i++)
		mainMenu->addChild(vMenuItems.at(i), 2);

	mainMenu->setPosition(Vec2::ZERO);
	this->addChild(mainMenu, 1);
    return true;
}


void HelloWorld::menuCloseCallback(Ref* pSender)
{
    //Close the cocos2d-x game scene and quit the application
    Director::getInstance()->end();

    #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
    
    /*To navigate back to native iOS screen(if present) without quitting the application  ,do not use Director::getInstance()->end() and exit(0) as given above,instead trigger a custom event created in RootViewController.mm as below*/
    
    //EventCustom customEndEvent("game_scene_close_event");
    //_eventDispatcher->dispatchEvent(&customEndEvent);
    
    
}

主要的修改在init函数中,头文件没有改。

增加一个 mainMenu的对象,主要根据名字就很容易猜出它的用途。学过C++的人很容易看到是利用vector像其中添加item,设置位置,设置字体等其它的属性。

通过lambda通知点击事件,C++11新增加的函数调用,在这里很实用。

通过Director::getInstance()->replaceScene(Chapter2::createScene())切换场景。

安卓手机上运行程序时的图片和Ubuntu上运行差不多,

这里注明一下,一般是生成电脑运行的程序进行调试,生成的手机apk进行展示,毕竟主要是在手机上玩。

cocos2d-x scene场景的切换_第1张图片

点击Chapter 2就会切换另外一个场景。

cocos2d-x scene场景的切换_第2张图片

源码如下:

#include "Chapter2.h"

#include "Chapter2Level1.h"

USING_NS_CC;

Scene* Chapter2::createScene()
{
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // some upfront items that we need
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();
    
    Size playingSize = Size(visibleSize.width, visibleSize.height - (visibleSize.height/8)); // actual playing size to work with
    
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // create a scene for our game to hold everything
    // 'scene' is an autorelease object
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    auto scene = Scene::create();
    
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // create the title dialog
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    auto color = Color4F(1.0f, 0.5f, 0.3f, 1);
    
    int verts = 4;
    
    Vec2 stripe1[] = {
        Vec2::ZERO,
        Vec2(0,200),
        Vec2(600,200),
        Vec2(600,0)
    };
    
    DrawNode* dotNode1 = DrawNode::create();
    dotNode1->setContentSize(Size(600, 200));
    dotNode1->drawPolygon(stripe1, verts, color, 0, color);
    
    dotNode1->setPosition(Vec2(visibleSize.width/2 - (dotNode1->getContentSize().width / 2),
                               playingSize.height - dotNode1->getContentSize().height));
    
    auto label = Label::createWithTTF("Super Cocos Aliens", "Marker Felt.ttf", 64);
    dotNode1->addChild(label, 1);
    auto dotNodeSize = dotNode1->getContentSize();
    label->setPosition(Vec2(dotNodeSize.width/2, dotNodeSize.height/2));

    scene->addChild(dotNode1, -1);

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // create a node to hold all labels
    // create the player and score labels
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    int paddingX = 20;
    int paddingY = 20;
    
    auto labelNode = Node::create();
    
    auto player1 = Label::createWithTTF("Player 1", "Marker Felt.ttf", 32);
    auto player2 = Label::createWithTTF("Player 2", "Marker Felt.ttf", 32);
    
    auto player1Score = Label::createWithTTF("00000", "Marker Felt.ttf", 32);
    auto player2Score = Label::createWithTTF("00000", "Marker Felt.ttf", 32);
    
    labelNode->addChild(player1, 0);
    labelNode->addChild(player2, 0);
    labelNode->addChild(player1Score, 0);
    labelNode->addChild(player2Score, 0);

    auto player1Size = player1->getContentSize();
    auto player1ScoreSize = player1Score->getContentSize();
    auto player2Size = player2->getContentSize();
    auto player2ScoreSize = player2Score->getContentSize();

    player1->setPosition(Vec2(0 + player1Size.width / 2 + paddingX,
                              visibleSize.height - player1Size.height / 2 - paddingY));
    
    player1Score->setPosition(Vec2(0 + player1->getPositionX() + player1ScoreSize.width + paddingX,
                                   visibleSize.height - player1ScoreSize.height / 2 - paddingY));
    
    player2Score->setPosition(Vec2(visibleSize.width - player2ScoreSize.width / 2 - paddingX,
                                   visibleSize.height - player2ScoreSize.height / 2 - paddingY));

    player2->setPosition(Vec2(player2Score->getPositionX() - player2Size.width - paddingX,
                              visibleSize.height - player2Size.height / 2 - paddingY));

    scene->addChild(labelNode, -1);
    
    
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // create a node to hold non-sprites.
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    auto nodeItems = Node::create();
    
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // create a path/walkway
    // depending upon how large the screen is we need to decide how many blocks to lay down.
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    auto testSprite = Sprite::create("ZigzagForest_Square.png");
    auto spriteSize = testSprite->getContentSize();
    
    int howMany = std::ceil(visibleSize.width / spriteSize.width);
    
    int sX = 0; // act as a counter for setPosition x coordinate.
    int sY = 0; // act as a counter for setPosition y coordinate.
    
    playingSize = Size(visibleSize.width, visibleSize.height - spriteSize.height);
    
    for (int i=0; i < howMany; i++)
    {
        auto sprite = Sprite::create("ZigzagForest_Square.png");
        sprite->setAnchorPoint(Vec2::ZERO);
        sprite->setPosition(sX,sY);
        
        sX += sprite->getContentSize().width;
        
        nodeItems->addChild(sprite, 0);
    }
    
    testSprite = NULL;
    
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // create the blocks
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    testSprite = Sprite::create("ZigzagGrass_Mud_Round.png");
    
    sX = visibleSize.width/2 - testSprite->getContentSize().width;
    sY = playingSize.height/2 - testSprite->getContentSize().height * 2;
    
    for (int i=0; i < 5; i++)
    {
        auto sprite = Sprite::create("ZigzagGrass_Mud_Round.png");
        sprite->setAnchorPoint(Vec2::ZERO);
        sprite->setPosition(sX,sY);
        
        sX += sprite->getContentSize().width;
        
        nodeItems->addChild(sprite, 0);
    }
    
    testSprite = NULL;

    scene->addChild(nodeItems, 1);
    
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // create a node to hold all sprites
    // create  a few sprites
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    auto spriteNode = Node::create();
    
    auto sprite1 = Sprite::create("Blue_Front1.png");
    sprite1->setAnchorPoint(Vec2(0,0));
    sprite1->setPosition(100, (visibleSize.height - playingSize.height));
    spriteNode->addChild(sprite1, 1);
    
    auto sprite2 = Sprite::create("LightBlue_Front1.png");
    sprite2->setAnchorPoint(Vec2(0,0));
    sprite2->setPosition(500, (visibleSize.height - playingSize.height));
    spriteNode->addChild(sprite2, 1);
    
    auto sprite3 = Sprite::create("White_Front1.png");
    sprite3->setAnchorPoint(Vec2(0,0));
    sprite3->setPosition(800, (visibleSize.height - playingSize.height));
    spriteNode->addChild(sprite3, 1);
    
    scene->addChild(spriteNode, 1);
    
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // create a node to hold menu
    // create a menu
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    auto menuNode = Node::create();
    
    auto menuItem1 = MenuItemFont::create("Start Game");
    menuItem1->setFontNameObj("Marker Felt.ttf");
    menuItem1->setFontSizeObj(64);
    
    menuItem1->setCallback([&](Ref *sender) {
       Director::getInstance()->replaceScene(Chapter2Level1::createScene());
    });
    
    auto menu = Menu::create(menuItem1, NULL);
    menuNode->addChild(menu, 0);
    
    scene->addChild(menuNode, 2);
    
    // return the scene
    return scene;
}

有点多,有点乱也写得有点乱,不过基本上运行问题不大,上传到百度网盘上。

https://pan.baidu.com/s/1i4TkAET

只留下bin目录,包涵android apk和linux app, Classes目录源码文件,和Resource目录资源文件,全部包括太大。

记住新建时需要根据之间的文章修改相应的CMakeList.txt pro.android中Android.mk文件

可以根据自己的需要增加Chapter 3的内容。




你可能感兴趣的:(coco2d-x)