基于Cocos2d-x开发guardCarrot--7 《保卫萝卜2》关卡选择页面开发

本文详细介绍了《保卫萝卜2》游戏的关卡选择页面开发过程,包括背景滚动视图的创建、UI层的布局以及各种按钮的事件监听。开发者通过Cocos2d-x引擎创建了水平滚动的背景地图,并实现了左上角按钮组、中间促销信息和右上角生命星的展示。每个元素的位置和交互都进行了细致的设置,确保了在不同屏幕尺寸下的一致性。
摘要由CSDN通过智能技术生成

《保卫萝卜2》关卡选择页面开发

  我们已经实现完《保卫萝卜2》主页面上解锁天天向上玩法(链接:https://blog.csdn.net/qq135595696/article/details/123012891),接下来我们实现关卡选择页面的开发。同样,在开发之前,我们先看一下完成后的效果图,如下如所示。

效果图

  分析《保卫萝卜2》的关卡选择页面,可以明显得到,我们应该把这个场景逻辑上分为两个层,一个是背景层,一个UI层。其中,背景层里是一个滚动视图,滚动整个地图。UI层存放一些简单的按钮和图片等节点。

  我们在项目中新建一个筛选器ChooseLevel,用来存放关卡选择场景的相关文件,如下图所示。

效果图

  其中,ChooseLevel.h、ChooseLevel.cpp用来管理关卡选择页面场景。 在该场景之上又加载了一个UI层。根据分析得出,该场景中首先需要一个ScrollView类来滚动整个背景地图,接下来我们先创建ScrollView对象,代码如下:

	//背景滚动界面
	auto scrollView = ScrollView::create();
	//设置滚动方向
	scrollView->setDirection(ScrollView::Direction::HORIZONTAL);
	//开启触摸事件
	scrollView->setTouchEnabled(true);
	//设置内容大小
	scrollView->setContentSize(Director::getInstance()->getVisibleSize());
	//隐藏滚动条
	scrollView->setScrollBarEnabled(false);
	this->addChild(scrollView);

	//创建背景地图
	Sprite* imageView = nullptr;
	string filePath;
	float nextPosX = 0.f;
	for (int i = 0; i < 14; i++)
	{
		filePath = "ChooseLevel/Map/stage_map_" + to_string(i) + ".png";
		imageView = Sprite::create(filePath);
		//更改锚点位置是因为第14张地图跟前面的13张地图宽度不一致
		imageView->setAnchorPoint(Vec2(0, 0.5));
		imageView->setPosition(nextPosX, Director::getInstance()->getVisibleSize().height / 2);
		nextPosX += imageView->getContentSize().width;
		scrollView->addChild(imageView);
	}
	//设置ScrollView的布局容器大小
	scrollView->setInnerContainerSize(Size(nextPosX, Director::getInstance()->getVisibleSize().height));

  上述代码创建了ScrollView对象,同时规定其滚动方向为水平方向,同时开启其触摸事件、设置其内容大小为整个屏幕的大小。

  紧接着,创建背景地图。在ScrollView中,子节点的坐标需要我们自己设定,这里通过一个for循环干净利索地台添加了14张背景图。最后设定了ScrollView的布局容器大小,这里nextPosX的值等于14张背景图宽度的总和。

  最后只需要在ChooseLevel类中的init()函数调用即可。接下来,实现UI层的开发。

  显然,UI层需要实现左上角的三个按钮、中间的打折信息按钮以及右上角的的生命星显示,如下图所示:

效果图

  可以明显看出,左上角的三个按钮的后面有一张背景图片,这张背景图始终位于当前屏幕的左上角,所以可以将它的锚点设置为(0,1),坐标设置为(0, Director::getInstance()->getVisibleSize().height),代码如下(首先我们创建UI层的Layer):

	//UI按钮控件
	auto layerUI = Layer::create();
	this->addChild(layerUI);
	auto leftPanelPinfo = AutoPolygon::generatePolygon("ChooseLevel/stagemap_toolbar_leftbg.png");
	//该背景图始终在屏幕的左上角
	auto leftPanel = Sprite::create(leftPanelPinfo);
	leftPanel->setAnchorPoint(Vec2(0, 1));
	leftPanel->setPosition(0, Director::getInstance()->getVisibleSize().height);
	leftPanel->setScale(0.7);
	layerUI->addChild(leftPanel);

  上面的代码保证了三个按钮的背景始终在屏幕的左上角,那么剩下的这3个按钮我们应该作为背景图片的子节点,使得三个按钮和按钮背景图片“绑”成了一个整体,这样的相对布局保证了3个按钮的坐标不会随屏幕大小的不一致而产生位置错乱,代码如下:

	//创建背景图精灵的子节点(三个按钮)
	string toolbarHomeFilePath = "ChooseLevel/stagemap_toolbar_home.png";
	_toolbarHome = Button::create(toolbarHomeFilePath, toolbarHomeFilePath, "");
	_toolbarHome->setAnchorPoint(Vec2(0, 0));
	_toolbarHome->setPosition(Vec2(10, 10));
	//启用缩放动画
	_toolbarHome->setPressedActionEnabled(true);
	leftPanel->addChild(_toolbarHome);

	string toolbarShopFilePath = "ChooseLevel/stagemap_toolbar_shop.png";
	_toolbarShop = Button::create(toolbarShopFilePath, toolbarShopFilePath, "");
	_toolbarShop->setAnchorPoint(Vec2(0, 0));
	_toolbarShop->setPosition(Vec2(125, 10));
	_toolbarShop->setPressedActionEnabled(true);
	leftPanel->addChild(_toolbarShop);
	//初始化首页按钮、商店按钮、排行榜按钮的三个事件
	_toolbarHome->addTouchEventListener([](Ref* sender, Widget::TouchEventType type) {
		if (type == ui::Widget::TouchEventType::ENDED)
		{
			auto mainScene = MainScene::createScene();
			Director::getInstance()->replaceScene(mainScene);
		}
		});

	_toolbarShop->addTouchEventListener([](Ref* sender, Widget::TouchEventType type) {
		if (type == ui::Widget::TouchEventType::ENDED)
		{
			log("open the shop");
		}
		});


	_toolbarLeaderboard->addTouchEventListener([](Ref* sender, Widget::TouchEventType type) {
		if (type == ui::Widget::TouchEventType::ENDED)
		{
			log("open the leaderboard");
		}
		});

  在代码中,我们可以发现“首页”按钮仅采用一张图片,所以我们应该给按钮启用被按下时的缩放操作。最后,给“首页”按钮添加触摸事件监听器,实现了住页面场景MainScene的切换。另外,在代码中用于判断时间是否在触摸结束时才响应实现逻辑代码,在开发中更多的按钮事件响应都应该放在触摸事件结束之后,而不是触摸释放之前。另外两个按钮同理。参考上述代码即可。

  在中间促销按钮中,需要添加一个BMFont来表示当前打多少折扣。定义私有变量cocos2d::Label* _discountText;来表示当前打多少折扣,这样就可以通过该变量来控制显示的折扣,代码如下:

	//创建中间的促销按钮
	string discountTagStoneFilePath = "ChooseLevel/zh/discount_tag_stone.png";
	_discountTagStone = Button::create(discountTagStoneFilePath, discountTagStoneFilePath, "");
	_discountTagStone->setAnchorPoint(Vec2(0.5, 1));
	_discountTagStone->setPosition(Vec2(Director::getInstance()->getVisibleSize().width / 2, Director::getInstance()->getVisibleSize().height));
	_discountTagStone->setScale(0.7);

	_discountText = Label::createWithBMFont("ChooseLevel/discount.fnt", "8");
	_discountTagStone->addChild(_discountText);
	_discountText->setAnchorPoint(Vec2(0, 0));
	_discountText->setPosition(160, 65);
	layerUI->addChild(_discountTagStone);
	//初始化中间的促销按钮
	_discountTagStone->addTouchEventListener([](Ref* sender, Widget::TouchEventType type) {
		if (type == ui::Widget::TouchEventType::ENDED)
		{
			log("open the discountTagStone");
		}
		});

  右上角的生命星组成与中间限时折扣按钮发类似,最底层为一张背景图,顶层为生命星数量文本,实现起来比较简单,代码如下:

//创建右上角 生命星按钮
	string toolbarRightbgFilePath = "ChooseLevel/stagemap_toolbar_rightbg.png";
	_toolbarRightbg = Button::create(toolbarRightbgFilePath, toolbarRightbgFilePath, "");
	_toolbarRightbg->setAnchorPoint(Vec2(1, 1));
	_toolbarRightbg->setPosition(Director::getInstance()->getVisibleSize());
	_toolbarRightbg->setScale(0.7);
	layerUI->addChild(_toolbarRightbg);

	//创建生命星星的图片背景
	auto starImage = Sprite::create("ChooseLevel/zh/stagemap_toolbar_overten.png");
	starImage->setAnchorPoint(Vec2(1, 1));
	starImage->setPosition(Director::getInstance()->getVisibleSize());
	starImage->setScale(0.7);
	layerUI->addChild(starImage);
	
	auto text = Label::createWithSystemFont("010", "Arial", 24);
	text->setAnchorPoint(Vec2(0, 0));
	text->setPosition(Vec2(220, 73));
	starImage->addChild(text);
	//初始化右上角生命星星事件
	_toolbarRightbg->addTouchEventListener([](Ref* sender, Widget::TouchEventType type) {
		if (type == ui::Widget::TouchEventType::ENDED)
		{
			log("click the toolbarRightbg");
		}
		});

  最后,在ChooseLevel类中的init()函数中调用这些方法,在运行该场景就可以得到文章开头的场景效果。

  至此,我们已经开发了主页面场景和关卡选择场景ChooseLevel。虽然ChooseLevel还未开发完,但是已经可以将两个场景串联起来,从而实现场景的切换。点击主页面中的“开始冒险”菜单按钮,可以切换到关卡选择场景。此事件可以通过“开始冒险”的事件监听器进行实现,代码如下:

	_startGameBtn->addTouchEventListener([](Ref* sender, Widget::TouchEventType type) {
		switch (type)
		{
		case ui::Widget::TouchEventType::BEGAN:
		{
			SimpleAudioEngine::getInstance()->playEffect("Sound/MainMenu/Select.mp3", false, 1.0f, 1.0f, 1.0f);
			break;
		}
		case ui::Widget::TouchEventType::ENDED:
		{
			//log("_startGameBtn ENDERD");
             //跳转场景
			auto chooseLevel = ChooseLevel::createScene();
			Director::getInstance()->replaceScene(chooseLevel);
			break;
		}
		default:
			break;
		}
		});

TIPS:注意需要#include “ChooseLevel.h”

源代码

  最后,附上ChooseLevel.h、ChooseLevel.cpp的源代码。

ChooseLevel.h

#pragma once
#include "cocos2d.h"
#include "ui/CocosGUI.h"
#include <string.h>

class ChooseLevel :public cocos2d::Scene
{
public:
	static cocos2d::Scene* createScene();

	virtual bool init();

	CREATE_FUNC(ChooseLevel);

private:
	void InitUI();

	void InitEvent();


private:
	cocos2d::ui::Button* _toolbarHome;
	cocos2d::ui::Button* _toolbarShop;
	cocos2d::ui::Button* _toolbarLeaderboard;

	cocos2d::ui::Button* _discountTagStone;
	cocos2d::Label* _discountText;

	cocos2d::ui::Button* _toolbarRightbg;

	static float discountText;
};

ChooseLevel.cpp

#include "ChooseLevel.h"
#include "MainScene.h"

USING_NS_CC;
using namespace cocos2d::ui;
using namespace std;


float ChooseLevel::discountText = 7.5;

cocos2d::Scene* ChooseLevel::createScene()
{
	return ChooseLevel::create();
}

bool ChooseLevel::init()
{
	if (!Scene::init())
		return false;


	InitUI();

	InitEvent();

	return true;
}

void ChooseLevel::InitUI()
{
	//背景滚动界面
	auto scrollView = ScrollView::create();
	scrollView->setDirection(ScrollView::Direction::HORIZONTAL);
	scrollView->setTouchEnabled(true);
	scrollView->setContentSize(Director::getInstance()->getVisibleSize());
	scrollView->setScrollBarEnabled(false);
	this->addChild(scrollView);

	Sprite* imageView = nullptr;
	string filePath;
	float nextPosX = 0.f;
	for (int i = 0; i < 14; i++)
	{
		filePath = "ChooseLevel/Map/stage_map_" + to_string(i) + ".png";
		imageView = Sprite::create(filePath);
		//更改锚点位置是因为第14张地图跟前面的13张地图宽度不一致
		imageView->setAnchorPoint(Vec2(0, 0.5));
		imageView->setPosition(nextPosX, Director::getInstance()->getVisibleSize().height / 2);
		nextPosX += imageView->getContentSize().width;
		scrollView->addChild(imageView);
	}
	scrollView->setInnerContainerSize(Size(nextPosX, Director::getInstance()->getVisibleSize().height));


	//UI按钮控件
	auto layerUI = Layer::create();
	this->addChild(layerUI);
	auto leftPanelPinfo = AutoPolygon::generatePolygon("ChooseLevel/stagemap_toolbar_leftbg.png");
	//该背景图始终在屏幕的左上角
	auto leftPanel = Sprite::create(leftPanelPinfo);
	leftPanel->setAnchorPoint(Vec2(0, 1));
	leftPanel->setPosition(0, Director::getInstance()->getVisibleSize().height);
	leftPanel->setScale(0.7);
	layerUI->addChild(leftPanel);
	//创建背景图精灵的子节点(三个按钮)
	string toolbarHomeFilePath = "ChooseLevel/stagemap_toolbar_home.png";
	_toolbarHome = Button::create(toolbarHomeFilePath, toolbarHomeFilePath, "");
	_toolbarHome->setAnchorPoint(Vec2(0, 0));
	_toolbarHome->setPosition(Vec2(10, 10));
	_toolbarHome->setPressedActionEnabled(true);
	leftPanel->addChild(_toolbarHome);

	string toolbarShopFilePath = "ChooseLevel/stagemap_toolbar_shop.png";
	_toolbarShop = Button::create(toolbarShopFilePath, toolbarShopFilePath, "");
	_toolbarShop->setAnchorPoint(Vec2(0, 0));
	_toolbarShop->setPosition(Vec2(125, 10));
	_toolbarShop->setPressedActionEnabled(true);
	leftPanel->addChild(_toolbarShop);

	string toolbarLeaderboardFilePath = "ChooseLevel/stagemap_toolbar_leaderboard.png";
	_toolbarLeaderboard = Button::create(toolbarLeaderboardFilePath, toolbarLeaderboardFilePath, "");
	_toolbarLeaderboard->setAnchorPoint(Vec2(0, 0));
	_toolbarLeaderboard->setPosition(Vec2(235, 10));
	_toolbarLeaderboard->setPressedActionEnabled(true);
	leftPanel->addChild(_toolbarLeaderboard);


	//创建中间的促销按钮
	string discountTagStoneFilePath = "ChooseLevel/zh/discount_tag_stone.png";
	_discountTagStone = Button::create(discountTagStoneFilePath, discountTagStoneFilePath, "");
	_discountTagStone->setAnchorPoint(Vec2(0.5, 1));
	_discountTagStone->setPosition(Vec2(Director::getInstance()->getVisibleSize().width / 2, Director::getInstance()->getVisibleSize().height));
	_discountTagStone->setScale(0.7);

	_discountText = Label::createWithBMFont("ChooseLevel/discount.fnt", "8");
	_discountTagStone->addChild(_discountText);
	_discountText->setAnchorPoint(Vec2(0, 0));
	_discountText->setPosition(160, 65);
	layerUI->addChild(_discountTagStone);


	//创建右上角 生命星按钮
	string toolbarRightbgFilePath = "ChooseLevel/stagemap_toolbar_rightbg.png";
	_toolbarRightbg = Button::create(toolbarRightbgFilePath, toolbarRightbgFilePath, "");
	_toolbarRightbg->setAnchorPoint(Vec2(1, 1));
	_toolbarRightbg->setPosition(Director::getInstance()->getVisibleSize());
	_toolbarRightbg->setScale(0.7);
	layerUI->addChild(_toolbarRightbg);

	//创建生命星星的图片背景
	auto starImage = Sprite::create("ChooseLevel/zh/stagemap_toolbar_overten.png");
	starImage->setAnchorPoint(Vec2(1, 1));
	starImage->setPosition(Director::getInstance()->getVisibleSize());
	starImage->setScale(0.7);
	layerUI->addChild(starImage);
	
	auto text = Label::createWithSystemFont("010", "Arial", 24);
	text->setAnchorPoint(Vec2(0, 0));
	text->setPosition(Vec2(220, 73));
	starImage->addChild(text);
}

void ChooseLevel::InitEvent()
{

	//初始化首页按钮、商店按钮、排行榜按钮的三个事件
	_toolbarHome->addTouchEventListener([](Ref* sender, Widget::TouchEventType type) {
		if (type == ui::Widget::TouchEventType::ENDED)
		{
			auto mainScene = MainScene::createScene();
			Director::getInstance()->replaceScene(mainScene);
		}
		});

	_toolbarShop->addTouchEventListener([](Ref* sender, Widget::TouchEventType type) {
		if (type == ui::Widget::TouchEventType::ENDED)
		{
			log("open the shop");
		}
		});


	_toolbarLeaderboard->addTouchEventListener([](Ref* sender, Widget::TouchEventType type) {
		if (type == ui::Widget::TouchEventType::ENDED)
		{
			log("open the leaderboard");
		}
		});

	//初始化中间的促销按钮
	_discountTagStone->addTouchEventListener([](Ref* sender, Widget::TouchEventType type) {
		if (type == ui::Widget::TouchEventType::ENDED)
		{
			log("open the discountTagStone");
		}
		});


	//初始化右上角生命星星事件
	_toolbarRightbg->addTouchEventListener([](Ref* sender, Widget::TouchEventType type) {
		if (type == ui::Widget::TouchEventType::ENDED)
		{
			log("click the toolbarRightbg");
		}
		});

}


static void problemLoading(const char* filename)
{
	printf("Error while loading:%s\n", filename);
	printf("Depending on how you compiled you might have to add 'Resources/' in front of filenames in ChooseLevel.cpp\n");
}

效果展示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ufgnix0802

总结不易,谢谢大家的支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值