IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> 基于Cocos2d-x开发guardCarrot--7 《保卫萝卜2》关卡选择页面开发 -> 正文阅读

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

《保卫萝卜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");
}

效果展示

在这里插入图片描述

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-02-26 12:03:55  更:2022-02-26 12:05:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 16:26:31-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码