cocos2d-x 游戏引擎的处理流程 MainLoop主循环(上)

首先还是就我个人的理解,讲讲游戏引擎的处理流程。

其实游戏逻辑简单化就是一个死循环,如下:

[cpp]  view plain copy
  1.      
  2. bool game_is_running = true;  
  3.   
  4.     while( game_is_running ) {   
  5.         update_game();   
  6.         display_game();   
  7.     }  


我们所看到的游戏画面,游戏音乐,以及一些触控,输入等。在逻辑上就是这么一个死循环。这个循环一直在跑,期间会处理一些列的事件,简化之就是上面的两个函数。

cocos2d-x引擎也是如此,所有的逻辑都是在这个主循环下实现的。下面看看cocos2dx在各平台上的主循环实现。

1.Win

看它的main.cpp

[cpp]  view plain copy
  1. #include "main.h"  
  2. #include "../Classes/AppDelegate.h"  
  3. #include "CCEGLView.h"  
  4.   
  5. USING_NS_CC;  
  6.   
  7. int APIENTRY _tWinMain(HINSTANCE hInstance,  
  8.                        HINSTANCE hPrevInstance,  
  9.                        LPTSTR    lpCmdLine,  
  10.                        int       nCmdShow)  
  11. {  
  12.     UNREFERENCED_PARAMETER(hPrevInstance);  
  13.     UNREFERENCED_PARAMETER(lpCmdLine);  
  14.   
  15.     // create the application instance  
  16.     AppDelegate app;  
  17.     CCEGLView* eglView = CCEGLView::sharedOpenGLView();  
  18.     eglView->setFrameSize(2048, 1536);  
  19.     // The resolution of ipad3 is very large. In general, PC's resolution is smaller than it.  
  20.     // So we need to invoke 'setFrameZoomFactor'(only valid on desktop(win32, mac, linux)) to make the window smaller.  
  21.     eglView->setFrameZoomFactor(0.4f);  
  22.     return CCApplication::sharedApplication()->run();// 注意这里  
  23. }  

前面都不要关心,只是用来传递OpenGL窗口的,关键是最后一句,CCApplication::sharedApplication()->run()。看这个run函数:

[cpp]  view plain copy
  1. int CCApplication::run()  
  2. {  
  3.     PVRFrameEnableControlWindow(false);  
  4.   
  5.     // Main message loop:  
  6.     MSG msg;  
  7.     LARGE_INTEGER nFreq;  
  8.     LARGE_INTEGER nLast;  
  9.     LARGE_INTEGER nNow;  
  10.   
  11.     QueryPerformanceFrequency(&nFreq);  
  12.     QueryPerformanceCounter(&nLast);  
  13.   
  14.     // Initialize instance and cocos2d.  
  15.     if (!applicationDidFinishLaunching())  
  16.     {  
  17.         return 0;  
  18.     }  
  19.   
  20.     CCEGLView* pMainWnd = CCEGLView::sharedOpenGLView();  
  21.     pMainWnd->centerWindow();  
  22.     ShowWindow(pMainWnd->getHWnd(), SW_SHOW);  
  23.   
  24.     while (1)// 注意这里,主循环来了  
  25.     {  
  26.         if (! PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))  
  27.         {  
  28.             // Get current time tick.  
  29.             QueryPerformanceCounter(&nNow);  
  30.   
  31.             // If it's the time to draw next frame, draw it, else sleep a while.  
  32.             if (nNow.QuadPart - nLast.QuadPart > m_nAnimationInterval.QuadPart)  
  33.             {  
  34.                 nLast.QuadPart = nNow.QuadPart;  
  35.                 CCDirector::sharedDirector()->mainLoop(); //看看这是神马  
  36.             }  
  37.             else  
  38.             {  
  39.                 Sleep(0);  
  40.             }  
  41.             continue;  
  42.         }  
  43.   
  44.         if (WM_QUIT == msg.message)  
  45.         {  
  46.             // Quit message loop.  
  47.             break;  
  48.         }  
  49.   
  50.         // Deal with windows message.  
  51.         if (! m_hAccelTable || ! TranslateAccelerator(msg.hwnd, m_hAccelTable, &msg))  
  52.         {  
  53.             TranslateMessage(&msg);  
  54.             DispatchMessage(&msg);  
  55.         }  
  56.     }  
  57.   
  58.     return (int) msg.wParam;  
  59. }  


不熟悉windows的童鞋估计都知道windows是消息驱动的。这个死循环就是用来处理windows的消息循环的,在其中处理了FPS逻辑,消息分发等。注意看其中红色标标注的

[cpp]  view plain copy
  1. CCDirector::sharedDirector()->mainLoop();  

这是神马东西啊!这个就是cocos2d-x的主循环了,由导演负责维护。从此就进入了cocos2d-x的世界,跟windows没有一毛钱关系了。

2.iOs

ios上面和Android上类似。看AppController.mm

[cpp]  view plain copy
  1. #import <UIKit/UIKit.h>  
  2. #import "AppController.h"  
  3. #import "cocos2d.h"  
  4. #import "EAGLView.h"  
  5. #import "AppDelegate.h"  
  6.   
  7. #import "RootViewController.h"  
  8.   
  9. @implementation AppController  
  10.   
  11. @synthesize window;  
  12. @synthesize viewController;  
  13.   
  14. #pragma mark -  
  15. #pragma mark Application lifecycle  
  16.   
  17. // cocos2d application instance  
  18. static AppDelegate s_sharedApplication;  
  19.   
  20. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {  
  21.   
  22.     // Override point for customization after application launch.  
  23.   
  24.     // Add the view controller's view to the window and display.  
  25.     window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]];  
  26.     EAGLView *__glView = [EAGLView viewWithFrame: [window bounds]  
  27.                                      pixelFormat: kEAGLColorFormatRGBA8  
  28.                                      depthFormat: GL_DEPTH_COMPONENT16  
  29.                               preserveBackbuffer: NO  
  30.                                       sharegroup: nil  
  31.                                    multiSampling: NO  
  32.                                  numberOfSamples:0 ];  
  33.   
  34.     // Use RootViewController manage EAGLView  
  35.     viewController = [[RootViewController alloc] initWithNibName:nil bundle:nil];  
  36.     viewController.wantsFullScreenLayout = YES;  
  37.     viewController.view = __glView;  
  38.   
  39.     // Set RootViewController to window  
  40.     if ( [[UIDevice currentDevice].systemVersion floatValue] < 6.0)  
  41.     {  
  42.         // warning: addSubView doesn't work on iOS6  
  43.         [window addSubview: viewController.view];  
  44.     }  
  45.     else  
  46.     {  
  47.         // use this method on ios6  
  48.         [window setRootViewController:viewController];  
  49.     }  
  50.       
  51.     [window makeKeyAndVisible];  
  52.   
  53.     [[UIApplication sharedApplication] setStatusBarHidden: YES];  
  54.   
  55.       
  56.     <span style="color:#ff0000;">cocos2d::CCApplication::sharedApplication()->run();</span>//<span style="color:#ff0000;">看这里</span>  
  57.     return YES;  
  58. }  
  59.   
  60.   
  61. - (void)applicationWillResignActive:(UIApplication *)application {  
  62.     /* 
  63.      Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 
  64.      Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 
  65.      */  
  66.     cocos2d::CCDirector::sharedDirector()->pause();  
  67. }  
  68.   
  69. - (void)applicationDidBecomeActive:(UIApplication *)application {  
  70.     /* 
  71.      Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 
  72.      */  
  73.     cocos2d::CCDirector::sharedDirector()->resume();  
  74. }  
  75.   
  76. - (void)applicationDidEnterBackground:(UIApplication *)application {  
  77.     /* 
  78.      Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
  79.      If your application supports background execution, called instead of applicationWillTerminate: when the user quits. 
  80.      */  
  81.     cocos2d::CCApplication::sharedApplication()->applicationDidEnterBackground();  
  82. }  
  83.   
  84. - (void)applicationWillEnterForeground:(UIApplication *)application {  
  85.     /* 
  86.      Called as part of  transition from the background to the inactive state: here you can undo many of the changes made on entering the background. 
  87.      */  
  88.     cocos2d::CCApplication::sharedApplication()->applicationWillEnterForeground();  
  89. }  
  90.   
  91. - (void)applicationWillTerminate:(UIApplication *)application {  
  92.     /* 
  93.      Called when the application is about to terminate. 
  94.      See also applicationDidEnterBackground:. 
  95.      */  
  96. }  
  97.   
  98.   
  99. #pragma mark -  
  100. #pragma mark Memory management  
  101.   
  102. - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {  
  103.     /* 
  104.      Free up as much memory as possible by purging cached data objects that can be recreated (or reloaded from disk) later. 
  105.      */  
  106.      cocos2d::CCDirector::sharedDirector()->purgeCachedData();  
  107. }  
  108.   
  109.   
  110. - (void)dealloc {  
  111.     [super dealloc];  
  112. }  
  113.   
  114.   
  115. @end  


直接看标注,跟进run()

[cpp]  view plain copy
  1. <span style="font-size:18px;">int CCApplication::run()  
  2. {  
  3.     if (applicationDidFinishLaunching())   
  4.     {  
  5.         <span style="color:#ff0000;">[[CCDirectorCaller sharedDirectorCaller] startMainLoop]</span>;  
  6.     }  
  7.     return 0;  
  8. }</span>  

再跟标注的startMainLoop()

[cpp]  view plain copy
  1. -(void) startMainLoop  
  2. {  
  3.         // CCDirector::setAnimationInterval() is called, we should invalidate it first  
  4.         [displayLink invalidate];  
  5.         displayLink = nil;  
  6.         NSLog(@"run loop !");  
  7.         displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(doCaller:)];//看这里  
  8.         [displayLink setFrameInterval: self.interval];  
  9.         [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];  
  10. }  

好了,看红色标注。这个貌似循环不起来啊,呵呵。

仔细看他加载的这个类CADisplayLink,就是这个东西循环起来的。这其实就是个定时器,默认每秒运行60次,其有个属性可以设置FPS。看后面有个回调函数doCaller,跟进

[cpp]  view plain copy
  1. -(void) doCaller: (id) sender  
  2. {  
  3.     cocos2d::CCDirector::sharedDirector()->mainLoop();//看这里  
  4. }  

好了,终于又看到导演了。导演很忙,又开始主循环了。

一旦进入主循环,游戏就开始我们自己设计的游戏逻辑。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值