上篇中我们添加两个新类,但是类并没有做任何事情事情,这篇文章主要介绍如何切换游戏的画面,比如从开始切换到游戏界面。
还是命令行新建工程
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);
}
增加一个 mainMenu的对象,主要根据名字就很容易猜出它的用途。学过C++的人很容易看到是利用vector像其中添加item,设置位置,设置字体等其它的属性。
通过lambda通知点击事件,C++11新增加的函数调用,在这里很实用。
通过Director::getInstance()->replaceScene(Chapter2::createScene())切换场景。
安卓手机上运行程序时的图片和Ubuntu上运行差不多,
这里注明一下,一般是生成电脑运行的程序进行调试,生成的手机apk进行展示,毕竟主要是在手机上玩。
点击Chapter 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的内容。