终于抽时间把这个游戏写完了。由于没有自拍神器,所以把它移植到了Android上,用我的戴妃跑的很欢啊。自此,我算是完成了一个功能比较完善的游戏了。
麻雀虽小,五脏俱全,该有的都有,不该有的估计也有,嘿嘿。这几天把写这个游戏的经历和学习过程整理一下,多写几篇博客,就当做记笔记了。
首先还是就我个人的理解,讲讲游戏引擎的处理流程。
其实游戏逻辑简单化就是一个死循环,如下:
- bool game_is_running = true;
- while( game_is_running ) {
- update_game();
- display_game();
- }
我们所看到的游戏画面,游戏音乐,以及一些触控,输入等。在逻辑上就是这么一个死循环。这个循环一直在跑,期间会处理一些列的事件,简化之就是上面的两个函数。
cocos2d-x引擎也是如此,所有的逻辑都是在这个主循环下实现的。下面看看cocos2dx在各平台上的主循环实现。
1.Win
看它的main.cpp
- #include "main.h"
- #include "../Classes/AppDelegate.h"
- #include "CCEGLView.h"
- USING_NS_CC;
- int APIENTRY _tWinMain(HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- LPTSTR lpCmdLine,
- int nCmdShow)
- {
- UNREFERENCED_PARAMETER(hPrevInstance);
- UNREFERENCED_PARAMETER(lpCmdLine);
- // create the application instance
- AppDelegate app;
- CCEGLView* eglView = CCEGLView::sharedOpenGLView();
- eglView->setFrameSize(2048, 1536);
- // The resolution of ipad3 is very large. In general, PC's resolution is smaller than it.
- // So we need to invoke 'setFrameZoomFactor'(only valid on desktop(win32, mac, linux)) to make the window smaller.
- eglView->setFrameZoomFactor(0.4f);
- return CCApplication::sharedApplication()->run();// 注意这里
- }
前面都不要关心,只是用来传递OpenGL窗口的,关键是最后一句,CCApplication::sharedApplication()->run()。看这个run函数:
- int CCApplication::run()
- {
- PVRFrameEnableControlWindow(false);
- // Main message loop:
- MSG msg;
- LARGE_INTEGER nFreq;
- LARGE_INTEGER nLast;
- LARGE_INTEGER nNow;
- QueryPerformanceFrequency(&nFreq);
- QueryPerformanceCounter(&nLast);
- // Initialize instance and cocos2d.
- if (!applicationDidFinishLaunching())
- {
- return 0;
- }
- CCEGLView* pMainWnd = CCEGLView::sharedOpenGLView();
- pMainWnd->centerWindow();
- ShowWindow(pMainWnd->getHWnd(), SW_SHOW);
- while (1)// 注意这里,主循环来了
- {
- if (! PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
- {
- // Get current time tick.
- QueryPerformanceCounter(&nNow);
- // If it's the time to draw next frame, draw it, else sleep a while.
- if (nNow.QuadPart - nLast.QuadPart > m_nAnimationInterval.QuadPart)
- {
- nLast.QuadPart = nNow.QuadPart;
- CCDirector::sharedDirector()->mainLoop(); //看看这是神马
- }
- else
- {
- Sleep(0);
- }
- continue;
- }
- if (WM_QUIT == msg.message)
- {
- // Quit message loop.
- break;
- }
- // Deal with windows message.
- if (! m_hAccelTable || ! TranslateAccelerator(msg.hwnd, m_hAccelTable, &msg))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
- return (int) msg.wParam;
- }
不熟悉windows的童鞋估计都知道windows是消息驱动的。这个死循环就是用来处理windows的消息循环的,在其中处理了FPS逻辑,消息分发等。注意看其中红色标标注的
- CCDirector::sharedDirector()->mainLoop();
这是神马东西啊!这个就是cocos2d-x的主循环了,由导演负责维护。从此就进入了cocos2d-x的世界,跟windows没有一毛钱关系了。
2.Android
Android平台的游戏是从一个Activity开始的。(话说好像Android的所有应用都是从Activity开始的吧)。
在引擎源码下有个目录是android的java代码,是模板代码,几乎所有的游戏都用这个,不怎么变。不信可以你可以看
YourCocos2dxDir/cocos2dx/platform/android/java这个目录,就是创建android工程的时候会去这个目录拷贝java代码作为模板。
来看看HelloCpp的代码
- package org.cocos2dx.hellocpp;
- import org.cocos2dx.lib.Cocos2dxActivity;
- import android.os.Bundle;
- public class HelloCpp extends Cocos2dxActivity{
- protected void onCreate(Bundle savedInstanceState){
- super.onCreate(savedInstanceState);
- }
- static {
- System.loadLibrary("hellocpp");
- }
- }
很简单,对吧。几行代码而已,这里说明了两个问题
1. Cocos2dxActivity才是核心的Activity。
2. 游戏的C++部分包括引擎部分,被编译成了动态链接库hellocpp。这里就是加载了hellocpp动态链接库。
这个动态链接库是在用NDK编译的时候生成的,就是libs/armeabi/libhellocpp.so。(扯远了)
还是来看看Cocos2dxActivity这个Activity。
- public abstract class Cocos2dxActivity extends Activity implements Cocos2dxHelperListener {
- // ===========================================================
- // Constants
- // ===========================================================
- private static final String TAG = Cocos2dxActivity.class.getSimpleName();
- // ===========================================================
- // Fields
- // ===========================================================
- private Cocos2dxGLSurfaceView mGLSurfaceView;//注意这个SurfaceView
- private Cocos2dxHandler mHandler;
- // ===========================================================
- // Constructors
- // ===========================================================
- @Override
- protected void onCreate(final Bundle savedInstanceState) {
- super