看CSAPP看的头大,做个小游戏娱乐娱乐。
1、一个cocos2dx项目的执行流程
由于cocos2dx和Python是一路货色,搞不到他们的版本更迭这么快并且还非常不兼容,不知道这些设计者是怎么想的,总之是会给大家造成一些个不必要的麻烦。我是用的是cocos2dx3.1的版本,创建好项目之后,在pro.win32里面打开VS的工程。因为任何C++程序,不管是多大的项目,这个程序运行起来和操作系统的接口都是由一个Main函数来完成的。
而且,要注意一点的就是我们要运行一个程序,他里面调用的 自定义的函数和你的main函数并不一定要放在一起。我可以写一个main.c里面存放main函数,然后写另一个文件里面有要在main函数里面调用的函数,在最后用编译器进行编译成一个可执行文件的时候可以通过连接器的作用去连接两个文件。形成最终的程序。
创建了项目之后,在main.c里面可以看见main函数,虽然这个main函数可能是有点和我们所看到的不一样 ,但是道理上是一样的。可以看到他执行了一个应用的初始化函数,getinstance这个函数返回的应该是一个Application对象,然后接着调用run函数来运行。
转到run函数看一下便可以知道,代码的注释上已经给了你提示,初始化一个应用实例,划红线出的那个函数,应该就是一个初始化的函数了,如果初始化失败的话,那么整个程序就会立即退出。
转到这个函数之后就可以看出,里面都是一些 初始化函数,划红线的代码是创建一个场景,我的理解就是创建了一个大的框架的东西。转到这个函数的定义一看,执行的便是bool HelloWorld::init()这个函数。这个函数内部包括了一些,插入图片,插入文字等等的一些代码也就是说,我们执行一个cocos2dx程序一开始看到的东西,都是由这个函数里面的代码来实现的。所以只要我们 重写这个方法,就能够按照我们的想法去初始化这个窗口。
2、如何使用sprite控件
这个控件是和2D图像有关的。创建一个 这样的对象是用以下函数
利用下面这个函数创建一个sprite精灵对象,就可以在场景中添加一个2d图像,但是之后要用addchild方法,添加进去。
|
static |
指定图像文件名创建Sprite
创建之后,Sprite的尺寸大小与图像相同,且偏移被置为(0,0)。
- 参数
-
filename 包含路径的图像文件名,比如"scene1/monster.png"
- 返回
- 自动释放的Sprite对象
之后运行程序,虽然可以看到图片显示了,但是明显位置不对。这就又提到了一个概念,叫做锚点。锚点就是一个类似于定位点的概念。每一个通过addchild方法添加进来的一个节点都会有一个锚点,这个锚点默认情况下(0.5,0.5)
可以通过一个叫做s->setAnchorPoint(Point(0,0));的方法去设置锚点,具体的用法可以去查一下官方的API
http://cn.cocos2d-x.org/doc/cocos2d-x-3.0/d8/de9/group__sprite__nodes.html#gac1be6ca229d92a1a145fda8a7eece771
2、
Cocos2d-x之Director、Scene、Layer
在上面的图片我们可以看出,我们一开始初始化了一些变量,第一行就是初始化一个director,这个director,也可以说是导演。在Cocos2d-x-3.0x引擎中,采用节点树形结构来管理游戏对象,一个游戏可以划分为不同的场景,一个场景又可以分为不同的层,一个层又可以拥有任意个可见的游戏节点。Director是整个引擎的核心,他管理着游戏场景的转换,游戏的暂停等等,某种意义上来说,真的就像是一个导演一样。整个一个项目只有一个director对象,用getinstance来进行初始化创建。
而Scene则是一个游戏 的 场景,也是通过一个初始化的函数来创建,但是在创建场景的函数里面,createScene,会包含创建一个层,也就是layer。上述三个对象是有着密切的逻辑关系的。
当你想做一个 游戏的时候,首先的话,你要创建一个导演对象,把我整个游戏的各种设置,之后,你要为你的游戏创建不同的场景,也就是一个大的背景,平台,在此基础上要创建层这个对象,然后把我们 所需要的游戏元素,也就是addchild方法添加的那些节点放在层上。
3、COCOS2dx是如何呈现图形的
就按照 刚才上面的 顺序,因为之前说过applicationDidFinishLaunching()是程序的入口,那么在这里,项目会 自动生成一些创建场景的代码。现在,为了能够真正的了解cocos2dx是如何呈现图形了,把它自动 生成的代码注释一下,自己写一个。
bool AppDelegate::applicationDidFinishLaunching() { // initialize director auto director = Director::getInstance(); auto glview = director->getOpenGLView(); if(!glview) { glview = GLView::create("My Game"); director->setOpenGLView(glview); } // turn on display FPS director->setDisplayStats(true); // set FPS. the default value is 1.0/60 if you don't call this director->setAnimationInterval(1.0 / 60); // create a scene. it's an autorelease object //auto scene = HelloWorld::createScene(); Scene *scene = Scene::create(); //创建一个场景 Layer *layer = Layer::create(); //创建一个层 scene->addChild(layer); //在层场景里面添加一个层 Sprite *s = Sprite::create("dota2.jpg"); //创建一个2d图像元素 s->setAnchorPoint(Point(0,0)); //设置锚点 layer->addChild(s); //将节点加入层中 // run director->runWithScene(scene); return true; }
具体的功能我都给了注释。
4、LOG控件
这个控件类似于printf函数,是一个输出信息的API。
5、MessageBox控件和MFC里面的功能基本一样,都是一个弹窗。显示一些信息,具体的可以去官网的文档看
PS:
Size size = Director::getInstance()->getVisibleSize(); //获取屏幕可见区域的大小
这句话还是比较有用的,是获取当前屏幕可见区域的大小尺寸
6、LabelTTF文本标签控件
和使用其他标签的步骤基本 是一样的,再次不多说了,贴上代码,应该很好理解
bool HelloWorld::init() { ////////////////////////////// // 1. super init first if ( !Layer::init() ) { return false; } Size size = Director::getInstance()->getVisibleSize(); //获取屏幕可见区域的大小 LabelTTF *label = LabelTTF::create(); label->setString("hello xuran"); //设置文本标签内容 label->setFontSize(36); //设置文字大小 label->setPosition(size.width/2, size.height/2); //设置位置 addChild(label); return true; }
7.TextFiledTTF控件的使用
这个控件是在场景中添加一个文本输入框,但是添加文本输入框之后,要想用键盘进行输入还要去启动输入法。
// on "init" you need to initialize your instance bool HelloWorld::init() { ////////////////////////////// // 1. super init first if ( !Layer::init() ) { return false; } Size size = Director::getInstance()->getVisibleSize(); //获取屏幕可见区域的大小 TextFieldTTF *tf = TextFieldTTF::textFieldWithPlaceHolder("Please input words","宋体",36); //根据各项参数创建一个文本编辑框 tf->setPosition(size.width/2, size.height/2); //设定其位置在屏幕 中间 addChild(tf); auto listener = EventListenerTouchOneByOne::create(); //设立一个事件监听器 listener->onTouchBegan = [tf](Touch *t, Event *event) { if(tf->getBoundingBox().containsPoint(t->getLocation())) //获取触摸点并且触摸点是否包含在在文本编辑框内 { tf->attachWithIME(); //为这个控件启用输入法 } else { tf->detachWithIME(); } return false; }; Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, tf); //利用导演添加一个对事件的监听器 return true; }
8、自定义一个类
如果我想添加一个2D图像在界面中,但是又不想用之前的方式在init函数里面进行添加,使用sprite,我想自己定义,然后 实现一些自定义的功能。这样就需要自定义一个类。由于我们相用自己创建的类来添加一个2d图像的节点在场景中,那么我们还是需要继承sprite因为这个类里面毕竟提供了太多的功能让我们使用。
新建一个ball的类然后创建一个init的虚函数,重新实现这个函数。并且用initwithfile方法根据图片创建一个小球的节点。
之后再自己重新 实现一个create的静态方法,以便于创建一个小球的元素。
之后再场景的类的init函数中,创建一个ball的对象。并且把它添加到场景中,就可以看到这样通过自己自定义的一个类完全可以实现之前用sprite的功能,并且还可以再次基础多做扩展。
#pragma once #include<iostream> #include"cocos2d.h" using namespace cocos2d; class ball:public Sprite { public: virtual bool init(); static ball* create() { ball* b = new ball(); b->init(); b->autorelease(); return b; } };
#include "ball.h" bool ball::init() { initWithFile("ball.png"); return true; }
auto b = ball::create(); b->setPosition(200,200); addChild(b);
9、Menu控件的使用
Menu是菜单控件,menuitem是菜单项,菜单就是很多菜单项的一个集合。可以创建文字版的菜单项或者图片的。但是Menu这个集合只接受menuitem做为孩子。
auto menu = Menu::create(MenuItemImage::create("5.png", "6.png",[](Object *obj) //创建一个菜单控件,并且利用MenuItemImage::create来创建一个图片的菜单项,指定选择菜单项前后的图片,并且指定选中菜单项之后的回调函数 { log("menu item touched"); }),NULL); addChild(menu);
cocos2dx学习之常用控件的使用