五毛的cocos2d-x学习笔记03-控件
VS2013快捷键:注释,Ctrl+K+C;取消注释Ctrl+K+U。都是单行。要实现多行注释与取消注释,就选中多行。
run方法调用了AppDelegate的applicationDidFinishLaunching方法
要调整窗体的大小的话,在AppDelegate.cpp的
auto director = Director::getInstance(); auto glview = director->getOpenGLView(); if(!glview) { glview = GLViewImpl::create("My Game"); director->setOpenGLView(glview); }
下面添加一行:
glview->setFrameSize(320,480);
效果如图:
director->setDisplayStats(true);//显示帧频 director->setAnimationInterval(1.0/60);//设置动画间隔。设置帧频大小,设置每一帧时间的间隔。1.0/60表示现在的帧频是60帧。
在讲今天的内容之前,需要了解几个概念:Director, Scene, Layer, Sprite, 本地坐标VS世界坐标,锚点,Z轴顺序。
游戏中基本上所有的类都派生自节点类(Node),如图
- Director是整个cocos2dx引擎的核心,是整个游戏的导航仪,游戏中的一些常用操作就是由Director来控制的,比如OpenGL ES的初始化,场景的转换,游戏暂停继续的控制,世界坐标和GL坐标之间的切换,对节点(游戏元素)的控制等,还有一些游戏数据的保存调用,屏幕尺寸的获取等都要由Director类来管理控制的。
1、获取Director实例:auto director = Director::getInstance();
2、Director控制场景的常用方法:用的栈的思想
-
- runWithScene(Scene *scene)
- replaceScene(Scene *scene)
-
- 场景(Scene)是层的容器。一般创建Scene的子类,在子类的初始化中载入游戏资源,为场景添加层,启动音乐播放等等。
- 层(Layer)通常包含的是直接在屏幕上呈现的内容,并且可以接受用户的输入事件,包括触摸,加速度计和键盘输入等。
- 精灵(Sprite)和其他游戏引擎中的精灵相似,它可以移动,旋转,缩放,执行动画,并接受其他转换。
笛卡尔坐标系、笛卡尔右手系、屏幕坐标系、cocos2d坐标系:
- 笛卡尔坐标系中定义右手系原点在左下角,x向右,y向上,z向外,OpenGL坐标系为笛卡尔右手系。
- Cocos2d坐标系和OpenGL坐标系一样,原点为屏幕左下角,x向右,y向上。
- iOS, Android, Windows Phone等在开发应用时使用的是标准屏幕坐标系,原点为屏幕左上角,x向右,y向下。
- 世界坐标系也叫绝对坐标系,“世界”指的是游戏世界。本地坐标系也叫相对坐标系,和节点关联,随节点移动。
锚点(Anchor Point):
- 两个参数在(0,1)之间。
- Layer的Anchor Point默认值为(0,0),其他Node的默认值为(0.5,0.5)。
- 将一个节点添加到父节点里面时,需要设置其在父节点上的位置,本质上是设置节点的锚点在父节点坐标上的位置。
- Layer添加子节点默认在(0,0),除非子节点用setPosition方法修改。setPosition默认参数为(0, 0)(相对坐标系)。
- 个人认为,锚点就是中心变化点。
VertexZ, PositionZ, Zorder:
- positionZ = VertexZ。
- positionZ:全局渲染顺序,即在根节点上的渲染顺序。
- zOrder: 局部渲染顺序,即在其父节点上的渲染顺序,与Node的层级有关。
- 当同时设置了positionZ和zOrder, 则positionZ生效。
- 个人理解:positionZ比zOrder优先级更大。
Sprite:
(Sprite)精灵只是很简单的表现,可以理解为图片对象,仅用于图像表现。所以包含攻击力、血量、速度等一系列属性的飞机不是Sprite。飞机包含了精灵对象,是组合。
Sprite的create方法有4个重载。
我们要把图片img.jpg放在项目的Resources目录下。然后在VS2013中,展开我们的项目,右键resource——>添加——>添加现有项(快捷键Alt+Shift+A)。找到Resources目录下的img.jpg,添加进来。
注释掉HelloWorldScene.cpp的init()方法中其他语句,只保留
bool HelloWorld::init() if ( !Layer::init() ) { return false; } //我们的代码从这里开始 return true; }
从我标注的地方添加代码:
auto s = Sprite::create("img.jpg"); this->addChild(s);
Shift+F5,运行项目,结果如图。
咦?和我们想象的不一样。图片只显示了右上角1/4。因为Sprite对象默认的锚点是(0.5, 0.5)。我们调整锚点为(0, 0)。
s->setAnchorPoint(Vec2(0, 0));//方法的参数是一个二维向量
这样,图片整个都出来了。
Director、Layer、Scene:
Director: 功能是切换Scene。只有在第一次呈现场景时用runWithScene,有场景存在的情况下,用replaceScene。
为了演示Scene是怎么操作的,我们注释掉AppDelegate.cpp的applicationDidFinishLaunching方法中的这条语句:auto scene = HelloWorld::createScene();
并在下面添加如下代码:
Scene *scene = Scene::create(); Layer *layer = Layer::create(); scene->addChild(layer); Sprite *s = Sprite::create("img.jpg"); s->setAnchorPoint(Vec2(0, 0)); layer->addChild(s);
运行效果和原来一样。
注:以下代码无特殊说明,都写在HelloWorldScene.cpp的init方法中。
Log:
Log只能在调试(快捷键F5)时才能看到。
log("Hello cocos2d-x log"); log("Hello int %d",5);
MessageBox(对话框):
创建方法:MessageBox("消息内容", "消息标题");
效果如图:
LabelTTF(文本标签):
//获得屏幕可见区域的大小 Size visibleSize = Director::getInstance()->getVisibleSize(); LabelTTF *label = LabelTTF::create(); label->setString("Hello cocos2d-x"); label->setFontSize(36); //setPosition放置的是label的锚点,而label的锚点默认是(0.5, 0.5),在label的正中间 //下面这条语句将label放在屏幕的正中间 label->setPosition(visibleSize.width/2, visibleSize.height/2); this->addChild(label);
运行结果:
TextFieldTTF(输入文本):
Size visibleSize = Director::getInstance()->getVisibleSize(); TextFieldTTF *tf = TextFieldTTF::textFieldWithPlaceHolder("input here","宋体",20); tf->setPosition(visibleSize.width/2, visibleSize.height/2); this->addChild(tf); auto listener = EventListenerTouchOneByOne::create(); listener->onTouchBegan = [](Touch *t, Event *e){ log(">>>>>>>>"); return false; }; Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener,tf);
以上代码,单击input here输入文本,有log输出,但是,单击屏幕其他地方,也有log输出,这就不是我们希望的结果了。
修改代码如下:
[](Touch *t, Event *e){ if (tf->getBoundingBox().containsPoint(t->getLocation())){ log(">>>>>>>>"); } return false; };
这段其实是函数闭包,我们在函数闭包里面是访问不到外面的变量的。要解决这个问题,在中括号里面写tf,即[tf]。
最终代码如下:
Size visibleSize = Director::getInstance()->getVisibleSize(); TextFieldTTF *tf = TextFieldTTF::textFieldWithPlaceHolder("input here","宋体",20); tf->setPosition(visibleSize.width/2, visibleSize.height/2); this->addChild(tf); auto listener = EventListenerTouchOneByOne::create(); listener->onTouchBegan = [tf](Touch *t, Event *e){ if (tf->getBoundingBox().containsPoint(t->getLocation())){ //log(">>>>>>>>"); tf->attachWithIME();//连接到IME,就可以输入了 } else{ tf->detachWithIME();//断开连接 } return false; }; Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener,tf);
效果如图:
创建自定义类:
cocos2d-x发展自cocos2d,cocos2d最开始是用OC开发的,所以cocos2d-x也保留了OC的语言习惯。
VS2013,如果你直接在:解决方案资源管理器——>HelloCocos——>src——>添加——>新建项,创建自定义类,那么你在include进其他.cpp或.h文件的时候,会报“无法打开源文件”的错。因为项目的层级显示是虚拟文件夹,你的新建项在proj.win32目录下,不在Classes目录下,当然找不到。所以为了统一管理,在Classes目录下新建.cpp和.h文件,然后解决方案资源管理器——>HelloCocos——>src——>添加——>现有项。资源文件也是如此。
自定义一个类,中间显示一个小球。ball.png放在HelloCocos\Resources目录下;Ball.h和Ball.cpp放在HelloCocos\Classes目录下。
Ball.h如下:
#ifndef _HELLOCOCOS_BALL_ #define _HELLOCOCOS_BALL_ #include<iostream> #include "cocos2d.h" using namespace cocos2d;//因为Sprite在cocos2d的命名空间里 class Ball : public Sprite{ public: virtual bool init(); /*static Ball* create(){ Ball* b = new Ball(); b->init(); b->autorelease(); return b; }*/ CREATE_FUNC(Ball); }; #endif
Ball.cpp如下:
#include "Ball.h" bool Ball::init(){ initWithFile("ball.png"); return true; }
在HelloWorldScene.cpp的init方法中添加如下代码:
Size visibleSize = Director::getInstance()->getVisibleSize(); auto ball = Ball::create(); ball->setPosition(visibleSize.width/2,visibleSize.height/2); this->addChild(ball);
具体添加位置如图:
运行结果:
今天就这么多内容。明天加油!