Cocos2d-x学习笔记之Hello World源码分析

首先我们来说一下游戏的原理,游戏类似于一场电影,早期的电影不就是靠一张张的图片放出来的吗?把场景人物什么的画在一幅幅图片上,然后从第一张图片开始播放就可以了。游戏更是如此,其实我们玩的游戏看到的画面都是美工做出来的,我们程序员要做的事情是组织这些图片,比如先弄个背景图片,然后在某一个坐标上放置一个人物的图片,我们写好程序,控制这个图片的移动路径,等机器运行的时候每秒都要刷新画面,我们就看到人物动了起来。而刷新页面的快慢就是我们所说的帧率,这个在程序中我们可以控制。整体的意思就是游戏不过是一些图片罢了,而我们就是控制这些图片,让这些图片运动,当用户单击图片的时候我们做一些事件响应的处理等等,当然还有一些其他的工作。然后cocos2d-x中有一些基本的类,比如导演类,这个是用来控制整个游戏的,正如正真的导演一样,每个游戏中只有一个导演,是一种单例设计模式。还有场景类,图层类,使用最广的就是精灵类,场景里边可以包含图层,图层上包含精灵。下面我们就通过这个helloworld场景来进入cocos2d-x的编程世界吧。

我们先把结果运行出来,看着图来说明代码的含义。大多数代码的含义都有注释,大家可以看代码了。

首先是main.cpp

#include "main.h"
#include "AppDelegate.h"
#include "CCEGLView.h"

USING_NS_CC;

// uncomment below line, open debug console
// #define USE_WIN32_CONSOLE

int APIENTRY _tWinMain(HINSTANCE hInstance,
            HINSTANCE hPrevInstance,
            LPTSTR  lpCmdLine,
            int    nCmdShow)
{
  UNREFERENCED_PARAMETER(hPrevInstance);
  UNREFERENCED_PARAMETER(lpCmdLine);

#ifdef USE_WIN32_CONSOLE
  AllocConsole();
  freopen("CONIN$", "r", stdin);
  freopen("CONOUT$", "w", stdout);
  freopen("CONOUT$", "w", stderr);
#endif

  // create the application instance
  AppDelegate app;
	//CCEGLView是单例设计模式,通过调用sharedOpenGLView()(以后只要是看到shared...就代表是一种单例设计模式)函数,获得全局唯一的opengl图像引擎的实例
  CCEGLView* eglView = CCEGLView::sharedOpenGLView();
	//以下这句比较重要,setFrameSize(x,y)是设置游戏窗口的大小,通过改变传入的值,可以改变游戏窗口的大小,看到窗口顶部的那行字了吗,就是写的窗口的大小
  eglView->setFrameSize(480, 320);

  int ret = CCApplication::sharedApplication()->run();

#ifdef USE_WIN32_CONSOLE
  FreeConsole();
#endif

  return ret;
}

Appdelegate.cpp如下

#include "cocos2d.h"	//想要使用cocos2d-x引擎,就要包含这个头文件
#include "CCEGLView.h"	//这个是opengl图形引擎的头文件
#include "AppDelegate.h"	//这个是生命周期类的头文件
#include "HelloWorldScene.h"	//这个是HelloWorld场景的头文件
#include "SimpleAudioEngine.h"	//这个是声音引擎的头文件

//要使用声音引擎,必须使用命名空间CocosDenshion
using namespace CocosDenshion;

//要使用cocos2d-x引擎,必须使用命名空间cocos2d,这个宏定义相当于using namespace cocos2d,大家可以选中它,按下f12,转到它的定义
USING_NS_CC;

//以下这俩个分别是生命周期类的构造函数和析构函数
AppDelegate::AppDelegate()
{
}

AppDelegate::~AppDelegate()
{
	//游戏生命周期结束的时候停止播放声音,知道c++基础的人一定知道end()函数是静态函数吧
  SimpleAudioEngine::end();
}

//当游戏启动的时候,就会调用这个函数,所以以后我们应该从这个函数看起
bool AppDelegate::applicationDidFinishLaunching()
{
  //导演类的初始化,又是shared...所以又是单例设计模式啊
  CCDirector *pDirector = CCDirector::sharedDirector();
  pDirector->setOpenGLView(CCEGLView::sharedOpenGLView());

  //大家看到了游戏左下角的那个数字60了吗,这个就是帧率(就是每秒钟游戏屏幕刷新的次数),这里可以设置它是否显示在左下角
  pDirector->setDisplayStats(true);

  //当然这里就是设置这个帧率了,在手机上的时候帧率不能小于30,否则游戏玩起来就会卡,帧率越高当然越耗CPU了,也就越费电了,所以帧率应该合理的设置
  pDirector->setAnimationInterval(1.0 / 60);

  //创建一个helloworld场景,从这里就能看出scene是一个静态函数吧
  CCScene *pScene = HelloWorld::scene();

  //然后导演调用runWithScene()函数来运行helloworld场景
  pDirector->runWithScene(pScene);
  return true;
}

//当我们玩游戏的时候突然被其他事情打断的时候,比如接电话,就会调用这个函数
void AppDelegate::applicationDidEnterBackground()
{
	//导演调用stopAnimation()来停止播放画面
  CCDirector::sharedDirector()->stopAnimation();
	//声音引擎停止播放声音
  SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic();
}

//当事件处理完成之后就会调用这个函数,比如电话接听完毕
void AppDelegate::applicationWillEnterForeground()
{
  CCDirector::sharedDirector()->startAnimation();

  SimpleAudioEngine::sharedEngine()->resumeBackgroundMusic();
}

以上俩个文件中的代码我们使用模板生成成功以后基本不用更改,我们需要做的就是写自己的场景类,写之前,让我们看看HelloWorld这个场景的实现吧。

先来看HelloWorld.h

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"

#include "SimpleAudioEngine.h"

//HelloWorld继承自CCLayer图层
class HelloWorld : public cocos2d::CCLayer
{
public:
  //这是HelloWorld场景类的初始化函数,是一个虚函数
  virtual bool init();

  //这是一个静态函数,可以通过指向类名的指针->scene()直接调用,返回一个CCScene场景的指针
  static cocos2d::CCScene* scene();

  //这是一个回调函数,是对单击结束按钮事件的响应函数
  void menuCloseCallback(CCObject* pSender);

  //这个宏可以通过f12看看他的具体实现,其实就是new一个对象,然后调用它的init函数(现在知道init函数什么时候调用了吧),然后返回该对象的指针
  CREATE_FUNC(HelloWorld);
};

#endif // __HELLOWORLD_SCENE_H__

然后是HelloWorld.cpp

#include "HelloWorldScene.h"

using namespace cocos2d;

CCScene* HelloWorld::scene()
{
  CCScene * scene = NULL;
	//这个do,while循环只会执行一次,为什么这样写,先不用管
  do
  {
    //首先创建一个CCScene的场景,调用的是create函数,其实对象的创建大多数都是调用create函数
		//这个create函数内部就是new一个对象,然后调用对象的init()函数,还有关于内存管理的一些工作,先不用管,你只需要记住c++中我们创建指向对象的指针是通过new,现在都封装在了create函数中了
    //可能有时候我们需要往create()中传入一些东西,但是它的内部实现函数我上边说的,就是带了几个参数而已
		scene = CCScene::create();
		//CC_BREAK_IF宏的含义是如果没有创建成功对象scene,就跳出do,while语句
    CC_BREAK_IF(! scene);

    //大家可以对create()f12一下,看是不是到了CREATE_FUNC(HelloWorld)这了,说明我上边说的就是对的。这里产生了一个指向helloworld层的指针。
    HelloWorld *layer = HelloWorld::create();
    CC_BREAK_IF(! layer);

    //将helloworld层添加到scene场景中,往一个场景中添加层,往层中添加精灵等都是用的这个函数addChild()
    scene->addChild(layer);
  } while (0);

  //返回包含helloworld这个层的场景
  return scene;
}

//有些人可能还会问init函数是什么时候调用的,我建议你好好看看上边的注释
bool HelloWorld::init()
{
  bool bRet = false;
  do
  {
		//首先初始化父类的init()函数
    CC_BREAK_IF(! CCLayer::init());

    //这是一个菜单项,对应图中的那个关闭按钮,传入俩张图片,对应正常状态时候的按钮盒按下状态的按钮图片
		//第四个参数中menu_selector是菜单选择器,cocos2d-x中还有不少的选择器,先记住,menuCloseCallback对应那个回调函数,第三个参数this就代表是哪个类的回调函数
    CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
      "CloseNormal.png",
      "CloseSelected.png",
      this,
      menu_selector(HelloWorld::menuCloseCallback));
    CC_BREAK_IF(! pCloseItem);

    //设置这个按钮的坐标,ccp也是一个宏,用来设置坐标的,getWinSize()获得了屏幕的尺寸,返回CCSize,width、height是它的属性
    pCloseItem->setPosition(ccp(CCDirector::sharedDirector()->getWinSize().width - 20, 20));

    //创建一个菜单,在cocos2d-x中需要将菜单项添加到菜单中也就是CCMenu中才可以,NULL表示菜单项的结束。
    CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);
		//设置这个菜单的坐标CCPointZero对应(0,0)
    pMenu->setPosition(CCPointZero);
    CC_BREAK_IF(! pMenu);

    //将菜单添加到HelloWorld的图层中,1表示的是深度,数字越小深度越深,只有添加到图层中才可以显示
    this->addChild(pMenu, 1);

    //创建一个文字,传入要显示的字,字体,大小,对应图片上的那个helloworld
    CCLabelTTF* pLabel = CCLabelTTF::create("Hello World", "Arial", 24);
    CC_BREAK_IF(! pLabel);

    //获得屏幕的尺寸
    CCSize size = CCDirector::sharedDirector()->getWinSize();
		//为pLabel设置坐标
    pLabel->setPosition(ccp(size.width / 2, size.height - 50));

    //将这个文字天剑到图层中才能显示
    this->addChild(pLabel, 1);

    //往图层中添加一个精灵是最常用的,精灵初始化的时候传入了一张图片,这个资源就在resource下
    CCSprite* pSprite = CCSprite::create("HelloWorld.png");
    CC_BREAK_IF(! pSprite);

    //设置这个精灵的坐标
    pSprite->setPosition(ccp(size.width/2, size.height/2));

    //将精灵添加到图层中,深度是0
    this->addChild(pSprite, 0);

    bRet = true;
  } while (0);

  return bRet;
}

//当用户按下关闭按钮的时候调用该回调函数,CCObject代表的是和这个函数绑定的按钮,用的时候强制转化为CCMenuItemImg*
void HelloWorld::menuCloseCallback(CCObject* pSender)
{
  //导演调用end方法结束游戏
  CCDirector::sharedDirector()->end();
}

显示的图片中还有几点要说,那个左下角的3代表3个元素,在这个图层中,我们添加了一个精灵,一个文字,一个菜单项,所以是3,0.000代表每一帧的间隔。整体的含义就是在scene中添加了helloworld层,层中添加了三个精灵,然后导演调用runWithScene()函数运行scene场景。

(0)

相关推荐

  • Cocos2d-x学习笔记之Hello World!

    首先我们要为vs2010安装一个cocos2d-x的插件,有了这个插件,当我们打开vs2010,单击文件->新建->项目的时候,在已安装的模板一栏就能看到cocos2d-x了,方便了我们的编写.那么这个插件在什么地方呢,由于cocos2d-x的版本不同,在有的版本中是不包含这个插件的,我已经为大家准备好了,大家单击下载就可以了(下载cocos2d-x模板插件).下载好这个插件以后,双击InstallWizardForVS2010.js就可以了,如果你是vs2012,找对应的文件,双击.然后打开

  • Cocos2d-x学习笔记之开发环境搭建

    要问如今什么比较火,当然是手机app了,随之智能机的普及,不断推出了越来越多的手机app,而游戏其实也是一种app.cocos2d-x一款免费游戏开发引擎,本着开源.跨平台的特色,成为了越来越多的手机游戏的开发引擎,所以让我们也来学习cocos2d-x这款游戏引擎吧.通过学习cocos2d-x,我们将了解更多关于游戏开发的知识,比如lua脚本.Box2d物理引擎.代码设计思想等等.总之,我们并不局限于学习cocos2d-x本身,而是通过学习cocos2d-x,掌握更多的游戏开发经验和技巧.现在就

  • Cocos2d-x学习笔记之Hello World源码分析

    首先我们来说一下游戏的原理,游戏类似于一场电影,早期的电影不就是靠一张张的图片放出来的吗?把场景人物什么的画在一幅幅图片上,然后从第一张图片开始播放就可以了.游戏更是如此,其实我们玩的游戏看到的画面都是美工做出来的,我们程序员要做的事情是组织这些图片,比如先弄个背景图片,然后在某一个坐标上放置一个人物的图片,我们写好程序,控制这个图片的移动路径,等机器运行的时候每秒都要刷新画面,我们就看到人物动了起来.而刷新页面的快慢就是我们所说的帧率,这个在程序中我们可以控制.整体的意思就是游戏不过是一些图片

  • PHP getID3类的使用方法学习笔记【附getID3源码下载】

    本文实例讲述了PHP getID3类的使用方法.分享给大家供大家参考,具体如下: 网上描述: getID3()这个PHP脚本能够从MP3或其它媒体文件中提取有用的信息如:ID3标签,bitrate,播放时间等. (格式包括:Ogg,WMA,WMV,ASF,WAV,AVI,AAC,VQF,FLAC,MusePack,Real,QuickTime,Monkey's Audio,MIDI等). 官方网址:https://www.getid3.org/. 功能: 使用这个方法,可以获得音频.视频.图片等

  • jQuery插件-jRating评分插件源码分析及使用方法

    该插件被广泛应用于各种需要评分的页面当中,今天作为学习,把源码拿出来分析一下,顺便学习其使用方法. 一.插件使用一览. 复制代码 代码如下: <div> <div>第一个例子</div> <div id="16_1" class="myRating"></div> </div> 复制代码 代码如下: <link href="Script/jRating/jRating.jquer

  • ObjectAnimator属性动画源码分析篇

    又和大家见面了,这几天一直在忙大创项目,所以没有更新博客,而且我发现看源码这个东西必须写个博客或者笔记啊,这之前一段时机笔者已经看了ValueAnimator和ObjectAnimator的源码了,但是这才过了几天,搞了会别的事情就忘得几乎一干二净了.现在又要重头看一遍很痛苦额-.+. 另外,笔者已经在简书写了关于属性动画的比较系统的详细的文章,之后会陆续在CSDN上重新写的(是重新写,不是复制过去哦,因为第一次写的实在是太烂了-.=) 好了不继续扯皮了,我们看来一下今天想要讲的东西--Obje

  • Redis源码分析之set 和 sorted set 使用

    目录 set 和 sorted set 前言 set 常见命令 set 的使用场景 看下源码实现 sorted set 常见的命令 使用场景 分析下源码实现 总结 参考 set 和 sorted set 前言 前面在几个文章聊到了 list,string,hash 等结构的实现,这次来聊一下 set 和 sorted set 的细节. set Redis 的 Set 是 String 类型的无序集合,集合成员是唯一的. 底层实现主要用到了两种数据结构 hashtable 和 inset(整数集合

  • Golang通道channel的源码分析

    目录 前言 channel基础结构 channel初始化 channel发送 channel接收 小结 前言 channel是golang中标志性的概念之一,很好很强大! channel(通道),顾名思义,是一种通道,一种用于并发环境中数据传递的通道.通常结合golang中另一重要概念goroutine(go协程)使用,使得在golang中的并发编程变得清晰简洁同时又高效强大. 今天尝试着读读golang对channel的实现源码,本文主要是自己个人对于Channel源码的学习笔记,需要的朋友可

  • java使用websocket,并且获取HttpSession 源码分析(推荐)

    一:本文使用范围 此文不仅仅局限于spring boot,普通的spring工程,甚至是servlet工程,都是一样的,只不过配置一些监听器的方法不同而已. 本文经过作者实践,确认完美运行. 二:Spring boot使用websocket 2.1:依赖包 websocket本身是servlet容器所提供的服务,所以需要在web容器中运行,像我们所使用的tomcat,当然,spring boot中已经内嵌了tomcat. websocket遵循了javaee规范,所以需要引入javaee的包 <

  • Mybatis源码分析之存储过程调用和运行流程

    这一篇我们学习一下Mybatis调用存储过程的使用和运行流程.首先我们先创建一个简单的存储过程 DELIMITER $ CREATE PROCEDURE mybatis.ges_user_count(IN age INT, OUT user_count INT) BEGIN SELECT COUNT(*) FROM users WHERE users.age=age INTO user_count; END $ 这个存储过程的含义其实比较简单的,就是输入age,然后执行select count(

  • jQuery源码分析-03构造jQuery对象-工具函数

    作者:nuysoft/高云 QQ:47214707 EMail:nuysoft@gmail.com 声明:本文为原创文章,如需转载,请注明来源并保留原文链接. 读读写写,不对的地方请告诉我,多多交流共同进步,本章的的PDF等本章写完了发布. jQuery源码分析系列的目录请查看 http://nuysoft.iteye.com/blog/1177451,想系统的好好写写,目前还是从我感兴趣的部分开始,如果大家有对哪个模块感兴趣的,建议优先分析的,可以告诉我,一起学习. 3.4 其他静态工具函数

  • Android透明化和沉浸式状态栏实践及源码分析

    本文所提到的透明状态栏其实指的是将顶部的导航栏延伸到状态栏,使之浑然一体(Google官方建议状态栏颜色比导航栏的颜色略深一点),并不代表一定不设置背景色,比如导航栏是白色,则可设置状态栏为白色,视情况而定. 相比于iOS系统,Android系统对于状态栏的设置就显得稍微复杂了一点.Android系统提供了API 19以上对状态栏的设置接口,而直到API 23以上才提供对于icon颜色的设置,还有就是各家厂商(如魅族,小米等)对于状态栏的有自己的定制,对于需要使用浅色背景状态栏的应用,没处理好的

随机推荐