首先我們來說一下游戲的原理,游戲類似于一場電影,早期的電影不就是靠一張張的圖片放出來的嗎?把場景人物什么的畫在一幅幅圖片上,然后從第一張圖片開始播放就可以了。游戲更是如此,其實我們玩的游戲看到的畫面都是美工做出來的,我們程序員要做的事情是組織這些圖片,比如先弄個背景圖片,然后在某一個坐標上放置一個人物的圖片,我們寫好程序,控制這個圖片的移動路徑,等機器運行的時候每秒都要刷新畫面,我們就看到人物動了起來。而刷新頁面的快慢就是我們所說的幀率,這個在程序中我們可以控制。整體的意思就是游戲不過是一些圖片罷了,而我們就是控制這些圖片,讓這些圖片運動,當用戶單擊圖片的時候我們做一些事件響應的處理等等,當然還有一些其他的工作。然后cocos2d-x中有一些基本的類,比如導演類,這個是用來控制整個游戲的,正如正真的導演一樣,每個游戲中只有一個導演,是一種單例設計模式。還有場景類,圖層類,使用最廣的就是精靈類,場景里邊可以包含圖層,圖層上包含精靈。下面我們就通過這個helloworld場景來進入cocos2d-x的編程世界吧。
我們先把結果運行出來,看著圖來說明代碼的含義。大多數代碼的含義都有注釋,大家可以看代碼了。
首先是main.cpp
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
|
#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如下
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
|
#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
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
|
#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
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
#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 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場景。