Cocos2d-x3.0游戏实例之《别救我》第六篇——从代码中获取UI控件

笨木头  2014-05-2 20:48   3.0游戏实例《别救我》,Cocos2d-x,Cocos2d-x3.0   阅读(21,119)   72条评论

 

 

这篇的内容很简单,获取UI控件,然后使用它。

 

还记得我们在UI编辑器中给三个按钮分别命名了吧?

现在要用上了。

 

笨木头花心贡献,啥?花心?不呢,是用心~

转载请注明,原文地址: http://www.benmutou.com/archives/918

文章来源:笨木头与游戏开发

 

根据名字查找控件

首先给TollgateScene再include一些头文件,不然等会编译又报错了:


1
2
3
4
5
6
7
8
9
#include "editor-support/cocostudio/CCSGUIReader.h"

#include "cocostudio/CocoStudio.h"

#include "ui/CocosGUI.h"

using namespace cocos2d::ui;

using namespace cocostudio;

 

上面就是比较完整的使用UI所需要用到的头文件了。

 

然后,获取UI控件的方法如下,继续修改createOprUI函数:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void TollgateScene::createOprUI()

{

    auto UI = cocostudio::GUIReader::getInstance()->widgetFromJsonFile("OprUI_1.ExportJson");

    this->addChild(UI);

 

    /* 获取按钮对象 */

    Button* rightBtn = (Button*)Helper::seekWidgetByName(UI, "rightBtn");

    Button* quickMoveBtn = (Button*)Helper::seekWidgetByName(UI, "quickMoveBtn");

    Button* leftBtn = (Button*)Helper::seekWidgetByName(UI, "leftBtn");

}

Helper::seekWidgetByName函数会从UI里面找控件,一层层的找,父控件找不到,就找子控件,如此递归,最后找的名字相符的控件,返回这个控件对象。

 

很简单,不多解释喇~

 

添加按钮回调事件

OK,最后一步了,现在按钮摆在那里什么都做不了,我们给按钮添加回调事件~

 

先给TollgateScene添加三个函数声明:


1
2
3
4
5
    void moveToLeft(Ref* sender, TouchEventType type);

    void moveToRight(Ref* sender, TouchEventType type);

    void quickMove(Ref* sender, TouchEventType type);

这是Button点击事件回调时所需要的函数格式。

 

然后,继续修改createOprUI函数:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void TollgateScene::createOprUI()

{

    auto UI = cocostudio::GUIReader::getInstance()->widgetFromJsonFile("OprUI_1.ExportJson");

    this->addChild(UI);

 

    /* 获取按钮对象 */

    Button* rightBtn = (Button*)Helper::seekWidgetByName(UI, "rightBtn");

    Button* quickMoveBtn = (Button*)Helper::seekWidgetByName(UI, "quickMoveBtn");

    Button* leftBtn = (Button*)Helper::seekWidgetByName(UI, "leftBtn");

 

    /* 添加按钮回调事件 */

    leftBtn->addTouchEventListener(this, toucheventselector(TollgateScene::moveToLeft));

    rightBtn->addTouchEventListener(this, toucheventselector(TollgateScene::moveToRight));

    quickMoveBtn->addTouchEventListener(this, toucheventselector(TollgateScene::quickMove));

}

 

利用addTouchEventListener函数就可以绑定按钮的回调事件了~

 

最后了,看看三个回调函数的实现:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
void TollgateScene::moveToLeft(Ref* sender, TouchEventType type)

{

    switch (type)

    {

    case TOUCH_EVENT_ENDED:

        m_player->moveToLeft();

        break;

 

    }

}

 

void TollgateScene::moveToRight(Ref* sender, TouchEventType type)

{

    switch (type)

    {

    case TOUCH_EVENT_ENDED:

        m_player->moveToRight();

        break;

 

    }

}

 

void TollgateScene::quickMove(Ref* sender, TouchEventType type)

{

    switch (type)

    {

    case TOUCH_EVENT_ENDED:

        m_player->quickMove();

        break;

 

    }

}

是不是感觉有点小复杂?

应该说,有点小麻烦,因为按钮事件绑定的时候,是没有区分“按下”、“移动”、“松开”的,所以我们要自己判断一下,TOUCH_EVENT_ENDED就是按钮点击,然后松开的时候的事件。

如果大家觉得麻烦,可以自己改源码,添加一些函数,在绑定按钮事件的时候,可以指定绑定哪种事件。以及可以使用std::function来作为参数,这样很方便,当然,跑题了。为了避免大家混乱,这里就不介绍了。

 

运行测试

OK,现在大家运行游戏,然后点击这三个操作按钮,看看主角是不是能左右移动以及放屁(向下冲)吧~

 

 

下一篇,添加碰撞检测,让主角碰到墙壁之后,进行加血。

没错,就是加血,不是扣血~因为《别救我》胜利的条件是血量为0,碰到墙是要惩罚的~

惩罚的方式就是加血~

 

 

72 评论

  1. 0x10871D44 (libcocos2d.dll) (do_not_save_me.exe 中)处的第一机会异常: 0xC0000005: 写入位置 0x0000035C 时发生访问冲突。
    0x10871D44 (libcocos2d.dll) (do_not_save_me.exe 中)处有未经处理的异常: 0xC0000005: 写入位置 0x0000035C 时发生访问冲突。
    为什么会这样…..

    1. 你用下木头老师的UI试试,我也遇到同样的问题,可能是cocosstdio导出文件没覆盖原文件(我是按钮名字改完没覆盖),并放到要使用项目的resourse下

  2. Pingback: javascript
  3. Pingback: Vanessa Smith
  4. 求救.我按第4章节把项目依赖,引用,附加包含目录都设好了,还是没用fatal error C1083: 无法打开包括文件:“cocostudio/DictionaryHelper.h”求教木头,这个问题怎么解决

  5. 你好 木头哥 我今天在xcode中 学习您的作品 但是ios更换了 解析JSON的类 于是我就只能这样写 auto UI=cocostudio::timeline::NodeReader::getInstance()->createNode(“OprUI_1.ExportJson”); this->addChild(UI);然后 需要查找控件也就是按钮图片 我这边按照文中所写 会报错 Button* quickMoveBtn = (Button*)Helper::seekWidgetByName(UI, “quickMoveBtn”); 这是报错代码 cannot initialize a parameter of”cocostudio::ui::widget*” with an lvalue of type “cocos2d::node ‘;在网上查了一下 Button* rightBtn=(Button*)UI->getChildByName(“rightBtn”);按照这种写法下面 这三行代码是有黄色的感叹号 leftBtn->addTouchEventListener(this,toucheventselector(TollgateScene::moveToleft)); rightBtn->addTouchEventListener(this,toucheventselector(TollgateScene::moveToRight)); quickMoveBtn->addTouchEventListener(this,toucheventselector(TollgateScene::quickMove));这个是第二个问题void TollgateScene::moveToleft(Ref* sender, TouchEventType type){ // 在TollgateScene::init()代码中已经初始化了m_player这个玩意但这里仍然提示变量未经定义使用// auto m_player=Player::create(); switch (type){ m_player->moveToLeft();//这里提示 use of undeclared identifier’m_player’; break; }}这是编译完成后 点击按钮会闪退 这是我今天遇到的问题 请有空帮忙看一下 谢谢

    1. IOS的我不懂呢,不过你可以看看官方的demo,关于新的cocostudio::timeline::NodeReader用法以及添加按钮监听是否有改变~第二个问题,我猜测,是你没有包含Player的头文件(#include)~

      1. 在”TollgateScene.h”已经包含了”Player.h”而且 在前5节中bool TollgateScene::init(){ if(!Layer::init()) { return false; } Size visibleSize=Director::getInstance()->getVisibleSize(); auto m_player=Player::create(); m_player->setPosition(Point(visibleSize.width*0.5f,visibleSize.height*0.85f)); this->addChild(m_player,5); TollgateScene::createOprUI(); this->schedule(schedule_selector(TollgateScene::logic)); return true;}这个地方 使用都正常

        1. 那就奇怪了,包含了头文件是不可能出现这个错误的,你仔细看看你的头文件有没有哪里写错的,导致m_player的声明被影响了。有时候其他地方错误也会导致莫名其妙的报错….

          1. 我也觉得奇怪 auto m_player=Player::create(); 这个声明 是不是全局变量 怎么下面的函数调用这个变量都都找不到呢 我使用的xcode编译器 晚上我回去用vs2013试试看

  6. 求教:在mac下的cocos Studio中解析auto UI = cocostudio::GUIReader::getInstance()->widgetFromJsonFile(“OprUI_1.ExportJson”); 报错Assertion failed: (IsObject()), function FindMember, file /Users/macmini3/Desktop/test/DontSavess/cocos2d/build/../external/json/document.h, line 620.

  7. 出现一个十分奇葩的情况 quickMove按钮按了可以用 有按键特效 角色也会下冲….但是另外两个按钮死活没用 我检查了好多遍按着检查就是没发现什么不对…….顺便支持木头~最近刚学cocos2dx 你那本书里用的版本好像太低了

    1. 是连按钮点击都没有放大的效果?你是不是不小心把按钮的交互属性的勾给去掉了?(在Cocostudio编辑器里)~那本书的3.x版本还有2个月左右就印出来了~

      1. 没有去掉 就是leftBtn 和 rightBtn点击没有效果角色不会动按钮也没有放大效果 quickMove按钮点击了有效果 角色会下冲 我想可能是代码有问题 但是检查了很多遍都没有发现

          1. …我终于找到问题,我没有在init里面createoprui,木头你要说明一下啊,让后面学的人不要再犯这样的错了。

  8. void moveToLeft(Ref *sender, TouchEventType type);VS提示错误 4 error C2061: 语法错误: 标识符“TouchEventType” (..ClassesAppDelegate.cpp) e:cocos2d-x-3.0projectsdontsavemeclassestollgatescene.h 23 1 DontSaveMe错误 7 error C2511: “void TollgateScene::moveToLeft(cocos2d::Ref *,cocos2d::ui::TouchEventType)”:“TollgateScene”中没有找到重载的成员函数 e:cocos2d-x-3.0projectsdontsavemeclassestollgatescene.cpp 106 1 DontSaveMe请问这是怎么回事? 开始我以为TouchEventType需要头文件声明其类型,就加入了#include “UIWidget.h” 不过还是不行

    1. #pragma once#include “cocos2d.h”#include “BackgroundLayer.h”#include “Player.h”#include “UIWidget.h”USING_NS_CC;class TollgateScene : public Layer{public: TollgateScene(); ~TollgateScene(); static Scene* Myscene(); CREATE_FUNC(TollgateScene); virtual bool init(); virtual void onExit() /*override*/; void createOprUI(); // 创建UI // button点击事件回调函数 void moveToLeft(Ref *sender, TouchEventType type);……TollgateScene.cppvoid TollgateScene::moveToLeft(Ref *sender, TouchEventType type){ switch (type) { case TOUCH_EVENT_ENDED: //m_player->moveToLeft(); default: break; }}我这里代码是这样的,应该没有问题才对啊

    2. 这篇文章不是已经给了头文件么?你用起来有问题?#include “editor-support/cocostudio/CCSGUIReader.h”#include “cocostudio/CocoStudio.h”#include “ui/CocosGUI.h”using namespace cocos2d::ui;using namespace cocostudio;

      1. 这几个头文件我放到了CPP里,也许是因为这原因吧,我回去转回到.H文件里试试。早上时间有点紧,搞得都有点不愿动脑的习惯了(-__-)b

      2. vc2012+coco2d-x-3.5环境使用:#include “cocostudio/CCSGUIReader.h”#include “cocostudio/CocoStudio.h”#include “CocosGUI.h”// using namespace cocos2d::ui;// using namespace cocostudio;using namespace cocos2d::ui;using namespace cocostudio;可以通过在c/c++-》常规-》附加包含目录添加“:$(Cocos2dx)cocoseditor-support$(Cocos2dx)cocosui其中(Cocos2dx)是我的coco2d-x-3.5目录

  9. void moveToLeft(Ref *sender, TouchEventType type); void moveToRight(Ref *sender, TouchEventType type); void quickMove(Ref *sender, TouchEventType type);我看完整版的TollgateScene.h里面没有这三个函数,是放到哪里了吗? 感觉教程跟原版的出入还是有一点大。⊙﹏⊙‖

    1. quickMoveBtn->addTouchEventListener(this, toucheventselector(TollgateScene::moveToRight));还有教程这里写错了

    2. 当然差别大了,教程是尽量精简,把代码都挤在一个类了~ 完整版是尽量保持好习惯,我把对象都分层处理了~其实你搜索一下moveToLeft,然后就能知道它在哪里被调用了~Ctrl + F,然后选择在当前项目范围搜索就可以了~

  10. 为啥quickMove这个方法,和moveToRight方法的功能没多少差别,都是往右边走。而且quickMove方法也没有如你教程所说的快速向下冲。 首先声明,是用的代码。

    1. 你再看看这三个函数:void Player::moveToRight(){ this->getPhysicsBody()->applyImpulse(Vect(50000, 0));}void Player::moveToLeft(){ this->getPhysicsBody()->applyImpulse(Vect(-50000, 0));}void Player::quickMove(){ this->getPhysicsBody()->applyImpulse(Vect(0, -200000));}applyImpuse是给物体添加一个推力,quickMove的推力是Y方向,向下推。明显quickMove的推力是很大的~然后,moveToRight和moveToLeft就像是我推了你一下,而quickMove就像是绿巨人推了你一下,你觉得你会不会直接冲出去

                    1. 单机版的有八篇简单的教程(没有完整介绍整个代码),其他的都没有~以我的风格,要把那游戏写成教程,估计得半本书了

发表评论

电子邮件地址不会被公开。 必填项已用*标注