操作系统:UOS1060专业版本。
cocos2dx:版本4.0
环境搭建教程:统信UOS下配置安装cocos2dx开发环境
本课主要内容:
文章地址:https://arv000.blog.csdn.net/article/details/132489182
点击关卡地图上的关卡跳转到对应的关卡难度选择。在这个游戏中每个关卡上三种难度。场景的切换我们使用pushScene方式进行,这样可以方便我们回到原来的关卡选择界面,我们只需要popScene就能回到原来的关卡选择场景。
在MapFlagSprite中,初始化touch监听
- void MapFlagSprite::initEvent()
- {
- auto listener = EventListenerTouchOneByOne::create();
- listener->onTouchBegan = CC_CALLBACK_2(MapFlagSprite::onTouchBeganFlag,this);
- listener->onTouchEnded = CC_CALLBACK_2(MapFlagSprite::onTouchEndedFlag,this);
- _eventDispatcher->addEventListenerWithSceneGraphPriority(listener,sprite_flag_);
- }
在MapFlagSprite中,处理监听进行场景切换,关键代码Director::getInstance()->pushScene(ChooseDifficultyScene::createSceneWithLevel(getLevel()));
- bool MapFlagSprite::onTouchEndedFlag(Touch *touch, Event *event)
- {
- auto target = static_cast
(event->getCurrentTarget()); -
- Point p = target->convertTouchToNodeSpace(touch);
- Rect rect= Rect(0,0,target->getContentSize().width,target->getContentSize().height);
- if(rect.containsPoint(p)){
- CCLOG(" MapFlagSprite::onTouchEndedFlag start level:%d",getLevel());
- Director::getInstance()->pushScene(ChooseDifficultyScene::createSceneWithLevel(getLevel()));
- }
- return false;
- }
效果如下:
首先我们需要加载新的资源,还是在LoadingScene.cpp中添加
SpriteFrameCache::getInstance()->addSpriteFramesWithFile("map_spritesheet_16_a_3-hd.plist");
第一层背景就是木板底层,然后因为他的宽度小于实际界面宽度,因此我们可以通过重复显示的方式铺满整个界面
- // 第一层背景,木板背景
- for (int i = 0; i< 4; i++) {
- for(int j = 0 ; j < 5 ;j ++){
- auto sprite = Sprite::createWithSpriteFrameName("encyclopedia_bgTile.png");
- sprite->setPosition(Point(i*320,j*160));
- sprite->setAnchorPoint(Point(0,0));
- addChild(sprite);
- }
- }
效果如下:
第二层背景就是纸张和地图
- // 第二层背景,纸张和地图
- auto sprite_bg2 = Sprite::createWithSpriteFrameName("LevelSelect_Bg.png");
- sprite_bg2->setPosition(Point(visible_size_.width/2,visible_size_.height/2));
- addChild(sprite_bg2,1);
- // 第三层背景放大镜
- auto sprite_loupe = Sprite::createWithSpriteFrameName("LevelSelect_loupe.png");
- sprite_loupe->setPosition(Point(visible_size_.width*0.21,390));
- addChild(sprite_loupe,2);
关闭按钮的操作就是popScene回退到上一次场景(关卡选择页面)
- // 关闭按钮
- auto sprite_close = MenuItemSprite::create(Sprite::createWithSpriteFrameName("LevelSelect_Back_0001.png"),
- Sprite::createWithSpriteFrameName("LevelSelect_Back_0002.png"),
- CC_CALLBACK_1(ChooseDifficultyScene::touchReturnMapSenec,this));
- Menu *menu_close = Menu::create(sprite_close,nullptr);
- sprite_close->setPosition(visible_size_.width*0.87,580);
- menu_close->setPosition(Vec2::ZERO);
- addChild(menu_close,2);
-
- // 进度战斗按钮
- auto sprite_start_mode = MenuItemSprite::create(Sprite::createWithSpriteFrameName("levelSelect_startMode_0001.png"),
- Sprite::createWithSpriteFrameName("levelSelect_startMode_0002.png"));
-
- Menu* menu_start_mode = Menu::create(sprite_start_mode,nullptr);
- sprite_start_mode->setPosition(Point(visible_size_.width*0.8,100));
- sprite_start_mode->setPosition(Vec2::ZERO);
- addChild(menu_start_mode,2);
小星星用于表示玩家游戏的得分情况,前三个是小星星后面两个一个是盾牌一个是拳头。
- // 第一颗 小星星
- sprite_star1 = Sprite::createWithSpriteFrameName("levelSelect_badges_0002.png");
- sprite_star1->setPosition(Point(170,580));
- sprite_star1->setRotation(-30.0f);
- addChild(sprite_star1,9);
-
- // 第一颗 小星星
- sprite_star2 = Sprite::createWithSpriteFrameName("levelSelect_badges_0002.png");
- sprite_star2->setPosition(Point(220,600));
- sprite_star2->setRotation(-15.0f);
- addChild(sprite_star2,9);
-
- // 第一颗 小星星
- sprite_star3 = Sprite::createWithSpriteFrameName("levelSelect_badges_0002.png");
- sprite_star3->setPosition(Point(270,605));
- addChild(sprite_star3,9);
-
- // 盾牌
- sprite_star4 = Sprite::createWithSpriteFrameName("levelSelect_badges_0004.png");
- sprite_star4->setPosition(Point(320,600));
- sprite_star3->setRotation(15.0f);
- addChild(sprite_star4,9);
-
- // 拳头
- sprite_star5 = Sprite::createWithSpriteFrameName("levelSelect_badges_0006.png");
- sprite_star5->setPosition(Point(370,580));
- sprite_star5->setRotation(30.0f);
- addChild(sprite_star5,9);
- ///=============================按钮1===============================
- auto menu_item_normal1 = MenuItemSprite::create(Sprite::createWithSpriteFrameName("levelSelect_butModes_0005.png"),
- Sprite::createWithSpriteFrameName("levelSelect_butModes_0001.png"));
- auto menu_ite_select1 = MenuItemSprite::create(Sprite::createWithSpriteFrameName("levelSelect_butModes_0001.png"),
- Sprite::createWithSpriteFrameName("levelSelect_butModes_0005.png"));
-
- toggle_item1_ = MenuItemToggle::createWithCallback(CC_CALLBACK_1(ChooseDifficultyScene::touchStarMenu1,this)
- ,menu_item_normal1
- ,menu_ite_select1
- ,nullptr);
- toggle_item1_->setTag(1);
- toggle_item1_->setPosition(Point(visible_size_.width*0.12,20));
- toggle_item1_->setSelectedIndex(0); // 初始化时设置0项为选中项
- toggle_item1_->setEnabled(true);
- ///=============================按钮2===============================
- auto menu_item_normal2 = MenuItemSprite::create(Sprite::createWithSpriteFrameName("levelSelect_butModes_0006.png"),
- Sprite::createWithSpriteFrameName("levelSelect_butModes_0006.png"));
- auto menu_ite_select2 = MenuItemSprite::create(Sprite::createWithSpriteFrameName("levelSelect_butModes_0002.png"),
- Sprite::createWithSpriteFrameName("levelSelect_butModes_0002.png"));
- auto menu_ite_disable2 = MenuItemSprite::create(Sprite::createWithSpriteFrameName("levelSelect_butModes_0004.png"),
- Sprite::createWithSpriteFrameName("levelSelect_butModes_0004.png"));
-
- toggle_item2_ = MenuItemToggle::createWithCallback(CC_CALLBACK_1(ChooseDifficultyScene::touchStarMenu2,this)
- ,menu_item_normal2
- ,menu_ite_select2
- ,menu_ite_disable2
- ,nullptr);
- toggle_item2_->setPosition(Point(visible_size_.width*0.24,20));
- toggle_item2_->setSelectedIndex(2); // 初始化时设置0项为选中项
- toggle_item2_->setEnabled(true);
- ///=============================按钮2===============================
- auto menu_item_normal3 = MenuItemSprite::create(Sprite::createWithSpriteFrameName("levelSelect_butModes_0007.png"),
- Sprite::createWithSpriteFrameName("levelSelect_butModes_0007.png"));
- auto menu_ite_select3 = MenuItemSprite::create(Sprite::createWithSpriteFrameName("levelSelect_butModes_0003.png"),
- Sprite::createWithSpriteFrameName("levelSelect_butModes_0003.png"));
- auto menu_ite_disable3 = MenuItemSprite::create(Sprite::createWithSpriteFrameName("levelSelect_butModes_0004.png"),
- Sprite::createWithSpriteFrameName("levelSelect_butModes_0004.png"));
- toggle_item3_ = MenuItemToggle::createWithCallback(CC_CALLBACK_1(ChooseDifficultyScene::touchStarMenu3,this)
- ,menu_item_normal3
- ,menu_ite_select3
- ,menu_ite_disable3
- ,nullptr);
- toggle_item3_->setPosition(Point(visible_size_.width*0.36,20));
- toggle_item3_->setSelectedIndex(2); // 初始化时设置0项为选中项
- toggle_item3_->setEnabled(true);
- auto toggle_menu = Menu::create(toggle_item1_,toggle_item2_,toggle_item3_,nullptr);
- toggle_menu->setPosition(Point(0,0));
- addChild(toggle_menu,2);
文字的内容保存在xml文件内,因此我们需要根据当前的关卡获取对应的xml文件内容。
- ValueVector txt_description = FileUtils::getInstance()->getValueVectorFromFile(StringUtils::format("xml/level%d_description.xml",level));
- int i = 0;
- for(auto& e:txt_description){
- auto txt_map = txt_description.at(i).asValueMap();
- int id_init = txt_map.at("id").asInt();
- if(i == id_init){
- str_blue_top_ = txt_map.at("blueStrTop").asString();
- str_black_[0] = txt_map.at("blackStr1").asString();
- str_black_[1] = txt_map.at("blackStr2").asString();
- str_black_[2] = txt_map.at("blackStr3").asString();
- str_blue_[0] = txt_map.at("blueStr1").asString();
- str_blue_[1] = txt_map.at("blueStr2").asString();
- str_blue_[2] = txt_map.at("blueStr3").asString();
- }
- i++;
- }
-
-
- auto label1 = Label::createWithTTF(str_blue_top_,"fonts/Marker Felt.ttf",40);
- label1->setPosition(Point(visible_size_.width * 0.5,620));
- label1->setColor(Color3B(0,0,0));
- label1->setRotation(3.0f);
- label1->setAnchorPoint(Point(0,1));
- addChild(label1,1);
-
- label_blue_ = Label::createWithTTF(str_blue_[0],"fonts/Marker Felt.ttf",30);
- label_blue_->setPosition(Point(visible_size_.width * 0.5,570));
- label_blue_->setColor(Color3B(65,94,241));
- label_blue_->setRotation(3.0f);
- label_blue_->setAnchorPoint(Point(0,1));
- addChild(label_blue_,1);
-
- label_black_ = Label::createWithTTF(str_black_[0],"fonts/Marker Felt.ttf",21);
- label_black_->setPosition(Point(visible_size_.width * 0.5,525));
- label_black_->setColor(Color3B(0,0,0));
- label_black_->setRotation(3.0f);
- label_black_->setAnchorPoint(Point(0,1));
- addChild(label_black_,1);
根据当前的关卡获取被放大的图片,让用户觉得当前的关卡被放大了。
- // 放大镜里面的东西。
- auto sprite_thumb = Sprite::createWithSpriteFrameName("thumb_stage2.png");
- sprite_thumb->setPosition(Point(260,400));
- addChild(sprite_thumb,1);
pushScene
方法用于将一个新的场景推送到场景堆栈(Scene Stack)中,使其成为当前场景。pushScene
时,当前场景将被暂停(不再更新和渲染),而新场景将变为活动场景。popScene
返回到前一个场景。replaceScene
方法用于替换当前的活动场景为一个新的场景,而不像 pushScene
,它不会将当前场景保留在堆栈中。replaceScene
时,当前场景将被销毁,而新场景将取代它成为活动场景。`pushScene` 和 `replaceScene` 在使用上各自有优点和缺点,取决于你的游戏需求和设计目标。以下是它们的一些优点和缺点:
1. 场景堆栈管理: 使用 `pushScene` 可以在场景堆栈中保留多个场景。这对于实现复杂的场景切换逻辑非常有用,例如从游戏中的任意位置返回到主菜单。
2. 后退功能:因为前一个场景仍然存在于堆栈中,所以你可以轻松地使用 `popScene` 返回到前一个场景,实现后退功能。
3. 场景切换流畅性:由于当前场景保留在堆栈中,切换回前一个场景通常比较流畅,因为前一个场景的状态仍然保留。
1. 内存消耗:保留多个场景可能会占用更多内存,特别是如果场景包含大量资源和对象。
2. 场景堆栈管理复杂性:多个场景堆栈可能会增加游戏的复杂性,需要谨慎管理场景的生命周期和资源。
1. 内存效率:使用 `replaceScene` 只保留一个场景,因此在内存使用方面更加高效。
2. 简单管理:场景堆栈始终保持简单,只有一个活动场景,这可能使代码和逻辑管理更加清晰。
1. 无法后退:由于前一个场景被销毁,所以无法直接返回到前一个场景。如果需要后退功能,你需要自行实现。
2. 场景切换可能有延迟:由于当前场景被销毁,加载新场景时可能会有短暂的延迟,这可能会在某些情况下影响用户体验。
综上所述,选择使用 `pushScene` 还是 `replaceScene` 取决于你的游戏需求和设计目标。如果你需要复杂的场景切换逻辑和后退功能,可能更适合使用 `pushScene`。如果你关注内存效率和简化场景管理,那么 `replaceScene` 可能更合适。通常,在实际游戏开发中,你可能会根据不同的情况和场景选择合适的方法来实现场景切换。
MenuItemToggle`是 Cocos2d-x 中的一个菜单项(`MenuItem`)控件,它允许你创建一个可以在多个选项之间切换的菜单项。当用户点击该菜单项时,它会循环切换到下一个选项。这个控件通常用于创建切换按钮或切换游戏中的不同选项或状态。
以下是关于 `MenuItemToggle` 的一些使用知识点:
1. 创建 `MenuItemToggle`: 要创建 `MenuItemToggle`,你需要为每个选项创建一个 `MenuItem`,然后将这些菜单项添加到 `MenuItemToggle` 中。你可以使用 `create` 方法来创建 `MenuItemToggle`。
2. 设置选项切换的回调函数:你可以为 `MenuItemToggle` 设置一个回调函数,当用户点击菜单项时,该回调函数会被调用。在回调函数中,你可以执行与选项切换相关的操作。
3. 添加到菜单:将 `MenuItemToggle` 添加到菜单中,以便它能够在菜单中显示并接收用户的点击操作。
4. 切换选项:当用户点击 `MenuItemToggle` 时,它会自动循环切换到下一个选项。你可以使用 `setSelectedIndex` 方法来手动设置当前选项的索引。
5. 设置选项的标签和文本: 每个选项都可以设置一个标签和文本,以便用户了解当前选中的选项是什么。
6. 自定义外观: 你可以自定义 `MenuItemToggle` 的外观,包括背景、文本颜色、字体等,以使其符合你的应用或游戏的风格。
以下是一个简单的示例,演示如何创建和使用 `MenuItemToggle`:
- #include "cocos2d.h"
-
- USING_NS_CC;
-
- void menuCallback(Ref* sender) {
- // 处理菜单项点击事件
- CCLOG("MenuItemToggle Clicked");
- }
-
- int main(int argc, char** argv) {
- // 创建应用程序实例
- Application app(argc, argv);
-
- // 创建场景
- auto scene = Scene::create();
- auto layer = Layer::create();
- scene->addChild(layer);
-
- // 创建菜单项
- auto item1 = MenuItemFont::create("Option 1", menuCallback);
- auto item2 = MenuItemFont::create("Option 2", menuCallback);
- auto item3 = MenuItemFont::create("Option 3", menuCallback);
-
- // 创建 MenuItemToggle,并将选项添加到其中
- auto toggleItem = MenuItemToggle::createWithCallback(menuCallback, item1, item2, item3);
-
- // 设置初始选中的选项
- toggleItem->setSelectedIndex(0);
-
- // 创建菜单并添加菜单项
- auto menu = Menu::create(toggleItem, nullptr);
- menu->setPosition(Vec2(240, 160));
- layer->addChild(menu);
-
- // 运行场景
- Director::getInstance()->runWithScene(scene);
-
- return app.run();
- }
在这个示例中,我们创建了一个 `MenuItemToggle`,其中包含三个选项。当用户点击菜单项时,会调用 `menuCallback` 函数。你可以根据需要在回调函数中执行不同的操作来处理不同的选项。
在coco2dx中我们可以使用xml文件存储和读取内容,xml文件的格式有一定的要求,每一个dict都是一个数组,里面使用key和string交替表示key->value的对应关系。通过FileUtils::getInstance()->getValueVectorFromFile
文件格式如下:
- "1.0" encoding="UTF-8"?>
- plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" ">
"> -
-
id -
0 -
info -
风一般的男纸 -
-
-
id -
1 -
info -
注定是寂寞的 -
-
-
读取
ValueVector txt_vec = FileUtils::getInstance()->getValueVectorFromFile("label.xml");
可以看到他是一个vector,typedef std::vector
Value是一个Map,因此我们可以通过一下方式提取数据,第一步:先取列表内容
auto txt_map = txt_vec.at(0).asValueMap();
第二步:通过关键词获取对应的数据内容
int id_int = txt_map.at("id").asInt();
完整代码如下:
- ValueVector txt_vec = FileUtils::getInstance()->getValueVectorFromFile("label.xml");//读取xml文档,放入ValueVector中
-
- for( auto& e : txt_vec)
- {
- auto txt_map = e.asValueMap();//将键值转化成Map格式,放入txt_map中
- int id_int = txt_map.at("id").asInt();//获取id
- if(10 == id_int)
- {
- auto label_str = txt_map.at("info").asString();//获取info的值
- auto label1 = LabelTTF::create(label_str,"Arial",25);
- label1->setPosition(Point(160,425));
- this->addChild(label1,2);
- }
- else if(20 == id_int)
- {
- auto label_str = txt_map.at("info").asString();
- auto label1 = LabelTTF::create(label_str,"Arial",25);
- label1->setPosition(Point(160,400));
- this->addChild(label1,2);
- }
- }
上一节:《入门级-Cocos2dx4.0 塔防游戏开发》---第八课:关卡地图开发
下一节:待定