在一个Cocos2d-x的应用入口中,当应用环境加载完成会回调以下方法
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool AppDelegate::applicationDidFinishLaunching()
{
// initialize director 初始化导演对象
CCDirector *pDirector = CCDirector::sharedDirector();
pDirector->setOpenGLView(CCEGLView::sharedOpenGLView()); //设定窗口绑定
// enable High Resource Mode(2x, such as iphone4) and maintains low resource on other devices.
// pDirector->enableRetinaDisplay(true); //是否处理大图
// turn on display FPS
pDirector->setDisplayStats(true); //是否显示fps 3个CCLabelTTF
// set FPS. the default value is 1.0/60 if you don't call this
pDirector->setAnimationInterval(1.0 / 60); //设定每秒绘制次数
// create a scene. it's an autorelease object
CCScene *pScene = HelloWorld::scene();//获取Node ,实际上Scene是要绘制所有 Node集合的第一个,在他里面AddChild了其他node,我们可以理解为一个tree
// run
pDirector->runWithScene(pScene); ///实际上是把这个node tree 放入渲染车间,由opengl来加工,每秒绘制60次到窗口。
return true;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CCDirector导演类
1。访问和改变场景
2。应用核心loop
3. 绑定和访问窗口
4。处理自动回收对象
5。处理事件消息转发
6。初始化各种管理器
7。处理在各Node的计划任务执行
8.在平台窗口绘图和opengl之间转换坐标
以下是CCDirector::init方法
bool CCDirector::init(void)
{
CCLOG("cocos2d: %s", cocos2dVersion());
// scenes 场景相关
m_pRunningScene = NULL;
m_pNextScene = NULL;
m_pNotificationNode = NULL;
m_dOldAnimationInterval = m_dAnimationInterval = 1.0 / kDefaultFPS;
m_pobScenesStack = new CCArray();
m_pobScenesStack->init();
// Set default projection (3D)
m_eProjection = kCCDirectorProjectionDefault;
// projection delegate if "Custom" projection is used
m_pProjectionDelegate = NULL;
// FPS 相关
m_fAccumDt = 0.0f;
m_fFrameRate = 0.0f;
m_pFPSLabel = NULL;
m_pSPFLabel = NULL;
m_pDrawsLabel = NULL;
m_bDisplayStats = false;
m_uTotalFrames = m_uFrames = 0;
m_pszFPS = new char[10];
m_pLastUpdate = new struct cc_timeval();
// paused ? 暂停
m_bPaused = false;
// purge ?
m_bPurgeDirecotorInNextLoop = false;
m_obWinSizeInPixels = m_obWinSizeInPoints = CCSizeZero;
m_pobOpenGLView = NULL;
m_fContentScaleFactor = 1.0f;
m_bIsContentScaleSupported = false;
// scheduler 计划任务
m_pScheduler = new CCScheduler();
// action manager 动作管理器
m_pActionManager = new CCActionManager();
m_pScheduler->scheduleUpdateForTarget(m_pActionManager, kCCPrioritySystem, false);
// touchDispatcher 触摸消息分发器
m_pTouchDispatcher = new CCTouchDispatcher();
m_pTouchDispatcher->init();
// KeypadDispatcher 按键消息分发器
m_pKeypadDispatcher = new CCKeypadDispatcher();
// Accelerometer 重力加速器
m_pAccelerometer = new CCAccelerometer();
// create autorelease pool 对象自动释放池管理器
CCPoolManager::sharedPoolManager()->push();
return true;
}
/////////////////////////////////////////////////////////////
在Windows ,ios,android等各种平台都会有对应的入口程序,在windows平台为main.cpp
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* eglView = CCEGLView::sharedOpenGLView();
eglView->setFrameSize(480, 320);
int ret = CCApplication::sharedApplication()->run();
#ifdef USE_WIN32_CONSOLE
FreeConsole();
#endif
return ret;
}
CCApplication::sharedApplication()->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 消息循环,在消息循环中实现了FPS逻辑,以及消息分发,分发后会由windows窗口类定义的消息处理函数来完成,消息处理函数在哪里呢?
CCEGLView* pMainWnd = CCEGLView::sharedOpenGLView();
pMainWnd->centerWindow();
可见在CCEGLView定义了窗口和窗口处理,看下源代码:
bool CCEGLView::Create(LPCTSTR pTitle, int w, int h)
{
bool bRet = false;
do
{
CC_BREAK_IF(m_hWnd);
HINSTANCE hInstance = GetModuleHandle( NULL );
WNDCLASS wc; // Windows Class Structure 定义窗口类
// Redraw On Size, And Own DC For Window.
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; //窗口样式,如果你想让windows 上的窗口没有标题栏,改这里呀。
wc.lpfnWndProc = _WindowProc; // WndProc Handles Messages 这个就是windows平台的消息处理函数,让我们下面看看_WindowProc源代码
wc.cbClsExtra = 0; // No Extra Window Data
wc.cbWndExtra = 0; // No Extra Window Data
wc.hInstance = hInstance; // Set The Instance
wc.hIcon = LoadIcon( NULL, IDI_WINLOGO ); // Load The Default Icon
wc.hCursor = LoadCursor( NULL, IDC_ARROW ); // Load The Arrow Pointer
wc.hbrBackground = NULL; // No Background Required For GL
wc.lpszMenuName = m_menu; //
wc.lpszClassName = kWindowClassName; // Set The Class Name
CC_BREAK_IF(! RegisterClass(&wc) && 1410 != GetLastError()); //注册窗口类
// center window position
RECT rcDesktop;
GetWindowRect(GetDesktopWindow(), &rcDesktop);
WCHAR wszBuf[50] = {0};
MultiByteToWideChar(CP_UTF8, 0, m_szViewName, -1, wszBuf, sizeof(wszBuf));
// create window 创建窗口
m_hWnd = CreateWindowEx(
WS_EX_APPWINDOW | WS_EX_WINDOWEDGE, // Extended Style For The Window
kWindowClassName, // Class Name
wszBuf, // Window Title
WS_CAPTION | WS_POPUPWINDOW | WS_MINIMIZEBOX, // Defined Window Style
0, 0, // Window Position
0, // Window Width
0, // Window Height
NULL, // No Parent Window
NULL, // No Menu
hInstance, // Instance
NULL );
CC_BREAK_IF(! m_hWnd);
resize(w, h);
bRet = initGL(); //在窗口初始化opengl
CC_BREAK_IF(!bRet);
s_pMainWindow = this;
bRet = true;
} while (0);
return bRet;
}
//////////////////////////////////////////////////////////////////////////////////////
static LRESULT CALLBACK _WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (s_pMainWindow && s_pMainWindow->getHWnd() == hWnd)
{
return s_pMainWindow->WindowProc(uMsg, wParam, lParam);
}
else
{
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
/////////////////////////////////////////////////////////////////////////////////////////
这个全局函数定义在cocos2dx/plantform/win32/CCGLView.cpp,我们看到,实际上 cocos2d-x窗口的处理函数为WindowProc
看下代码:
LRESULT CCEGLView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
BOOL bProcessed = FALSE;
switch (message)
{
case WM_LBUTTONDOWN:
if (m_pDelegate && MK_LBUTTON == wParam)
{
POINT point = {(short)LOWORD(lParam), (short)HIWORD(lParam)};
CCPoint pt(point.x/CC_CONTENT_SCALE_FACTOR(), point.y/CC_CONTENT_SCALE_FACTOR());
CCPoint tmp = ccp(pt.x, m_obScreenSize.height - pt.y);
if (m_obViewPortRect.equals(CCRectZero) || m_obViewPortRect.containsPoint(tmp))
{
m_bCaptured = true;
SetCapture(m_hWnd);
int id = 0;
pt.x *= m_windowTouchScaleX;
pt.y *= m_windowTouchScaleY;
handleTouchesBegin(1, &id, &pt.x, &pt.y);
}
}
break;
case WM_MOUSEMOVE:
if (MK_LBUTTON == wParam && m_bCaptured)
{
POINT point = {(short)LOWORD(lParam), (short)HIWORD(lParam)};
CCPoint pt(point.x/CC_CONTENT_SCALE_FACTOR(), point.y/CC_CONTENT_SCALE_FACTOR());
int id = 0;
pt.x *= m_windowTouchScaleX;
pt.y *= m_windowTouchScaleY;
handleTouchesMove(1, &id, &pt.x, &pt.y);
}
break;
case WM_LBUTTONUP:
if (m_bCaptured)
{
POINT point = {(short)LOWORD(lParam), (short)HIWORD(lParam)};
CCPoint pt(point.x/CC_CONTENT_SCALE_FACTOR(), point.y/CC_CONTENT_SCALE_FACTOR());
int id = 0;
pt.x *= m_windowTouchScaleX;
pt.y *= m_windowTouchScaleY;
handleTouchesEnd(1, &id, &pt.x, &pt.y);
ReleaseCapture();
m_bCaptured = false;
}
break;
case WM_SIZE:
switch (wParam)
{
case SIZE_RESTORED:
CCApplication::sharedApplication()->applicationWillEnterForeground();
break;
case SIZE_MINIMIZED:
CCApplication::sharedApplication()->applicationDidEnterBackground();
break;
}
break;
case WM_KEYDOWN:
if (wParam == VK_F1 || wParam == VK_F2)
{
CCDirector* pDirector = CCDirector::sharedDirector();
if (GetKeyState(VK_LSHIFT) < 0 || GetKeyState(VK_RSHIFT) < 0 || GetKeyState(VK_SHIFT) < 0)
pDirector->getKeypadDispatcher()->dispatchKeypadMSG(wParam == VK_F1 ? kTypeBackClicked : kTypeMenuClicked);
}
if ( m_lpfnAccelerometerKeyHook!=NULL )
{
(*m_lpfnAccelerometerKeyHook)( message,wParam,lParam );
}
break;
case WM_KEYUP:
if ( m_lpfnAccelerometerKeyHook!=NULL )
{
(*m_lpfnAccelerometerKeyHook)( message,wParam,lParam );
}
break;
case WM_CHAR:
{
if (wParam < 0x20)
{
if (VK_BACK == wParam)
{
CCIMEDispatcher::sharedDispatcher()->dispatchDeleteBackward();
}
else if (VK_RETURN == wParam)
{
CCIMEDispatcher::sharedDispatcher()->dispatchInsertText("\n", 1);
}
else if (VK_TAB == wParam)
{
// tab input
}
else if (VK_ESCAPE == wParam)
{
// ESC input
//CCDirector::sharedDirector()->end();
}
}
else if (wParam < 128)
{
// ascii char
CCIMEDispatcher::sharedDispatcher()->dispatchInsertText((const char *)&wParam, 1);
}
else
{
char szUtf8[8] = {0};
int nLen = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)&wParam, 1, szUtf8, sizeof(szUtf8), NULL, NULL);
CCIMEDispatcher::sharedDispatcher()->dispatchInsertText(szUtf8, nLen);
}
if ( m_lpfnAccelerometerKeyHook!=NULL )
{
(*m_lpfnAccelerometerKeyHook)( message,wParam,lParam );
}
}
break;
case WM_PAINT:
PAINTSTRUCT ps;
BeginPaint(m_hWnd, &ps);
EndPaint(m_hWnd, &ps);
break;
case WM_CLOSE: ///把WM_CLOSE,WM_DESTROY这2个消息注释,看看效果,是不是不能关闭了
//CCDirector::sharedDirector()->end();
break;
case WM_DESTROY:///把WM_CLOSE,WM_DESTROY这2个消息注释,看看效果,是不是不能关闭了,这里
//destroyGL();
//PostQuitMessage(0);
break;
default:
if (m_wndproc)
{
m_wndproc(message, wParam, lParam, &bProcessed);
if (bProcessed) break;
}
return DefWindowProc(m_hWnd, message, wParam, lParam);
}
if (m_wndproc && !bProcessed)
{
m_wndproc(message, wParam, lParam, &bProcessed);
}
return 0;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////不知道你懂了没
关注blog.csdn.net/sdhjob @weibo.com/shunfengche
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
下面看Android平台
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");
}
}
入口类貌似很简单,说明了2件事情,
1,Cocos2dxActivity必定是核心
2,Coco2d-x的引擎就是在hellocpp.so中集成的,并且这里一定跟Cocos2dxActivity有者千丝万屡的联系,元方,你认为呢?
看代码
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/****************************************************************************
package org.cocos2dx.lib;
import org.cocos2dx.lib.Cocos2dxHelper.Cocos2dxHelperListener; //处理从java到C以及从C到Java的调用
import android.app.Activity;
import android.app.AlertDialog;
import android.os.Bundle;
import android.os.Message;
import android.view.ViewGroup;
import android.widget.FrameLayout;
public abstract class Cocos2dxActivity extends Activity implements Cocos2dxHelperListener {
private static final String TAG = Cocos2dxActivity.class.getSimpleName();
private Cocos2dxGLSurfaceView mGLSurefaceView; //窗口GLSurfaceView
private Cocos2dxHandler mHandler; //窗口View的handler用来接收android系统的回调
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.init();
Cocos2dxHelper.init(this, this);
}
protected void onResume() {
super.onResume();
Cocos2dxHelper.onResume();
this.mGLSurefaceView.onResume();
}
protected void onPause() {
super.onPause();
Cocos2dxHelper.onPause();
this.mGLSurefaceView.onPause();
}
public void showDialog(final String pTitle, final String pMessage) {
Message msg = new Message();
msg.what = Cocos2dxHandler.HANDLER_SHOW_DIALOG;
msg.obj = new Cocos2dxHandler.DialogMessage(pTitle, pMessage);
this.mHandler.sendMessage(msg);
}
public void showEditTextDialog(final String pTitle, final String pContent, final int pInputMode, final int pInputFlag, final int pReturnType, final int pMaxLength) {
Message msg = new Message();
msg.what = Cocos2dxHandler.HANDLER_SHOW_EDITBOX_DIALOG;
msg.obj = new Cocos2dxHandler.EditBoxMessage(pTitle, pContent, pInputMode, pInputFlag, pReturnType, pMaxLength);
this.mHandler.sendMessage(msg);
}
public void runOnGLThread(final Runnable pRunnable) { //这里可以让java的线程运行在cocos2d-x的loop中
this.mGLSurefaceView.queueEvent(pRunnable);
}
public void init() {
// Init handler
this.mHandler = new Cocos2dxHandler(this); //处理从C++发送过来消息调用Adnroid FrameWork显示Dialg
ViewGroup.LayoutParams framelayout_params =
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT);
FrameLayout framelayout = new FrameLayout(this); //FrameLayout可以实现绝对定位绘图,还可以实现多层覆盖
framelayout.setLayoutParams(framelayout_params);
// Cocos2dxEditText layout
ViewGroup.LayoutParams edittext_layout_params =
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
Cocos2dxEditText edittext = new Cocos2dxEditText(this);
edittext.setLayoutParams(edittext_layout_params);
// ...add to FrameLayout
framelayout.addView(edittext); //添加一层编辑框
// Cocos2dxGLSurfaceView
this.mGLSurefaceView = this.onCreateGLSurfaceView();
// ...add to FrameLayout
framelayout.addView(mGLSurefaceView); //添加一层GLSurfaceView
mGLSurefaceView.setCocos2dxRenderer(new Cocos2dxRenderer());
mGLSurefaceView.setCocos2dxEditText(edittext);
// Set framelayout as the content view
setContentView(framelayout);
}
public Cocos2dxGLSurfaceView onCreateGLSurfaceView() {
return new Cocos2dxGLSurfaceView(this);
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}
//////////////////////////////////////////////////////////////////////
protected void onResume() {
super.onResume();
Cocos2dxHelper.onResume();
this.mGLSurefaceView.onResume();
}
protected void onPause() {
super.onPause();
Cocos2dxHelper.onPause();
this.mGLSurefaceView.onPause();
}
可见mGLSurefaceView一定会把应用窗口状态的变化传递给CCDirector,看看如何传递的:
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package org.cocos2dx.lib;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.inputmethod.InputMethodManager;
public class Cocos2dxGLSurfaceView extends GLSurfaceView {
// ===========================================================
// Constants
// ===========================================================
private static final String TAG = Cocos2dxGLSurfaceView.class.getSimpleName();
private final static int HANDLER_OPEN_IME_KEYBOARD = 2;
private final static int HANDLER_CLOSE_IME_KEYBOARD = 3;
// ===========================================================
// Fields
// ===========================================================
// TODO Static handler -> Potential leak!
private static Handler sHandler;
private static Cocos2dxGLSurfaceView mCocos2dxGLSurfaceView;
private static Cocos2dxTextInputWraper sCocos2dxTextInputWraper;
private Cocos2dxRenderer mCocos2dxRenderer;
private Cocos2dxEditText mCocos2dxEditText;
// ===========================================================
// Constructors
// ===========================================================
public Cocos2dxGLSurfaceView(final Context context) {
super(context);
this.setEGLContextClientVersion(2);
this.initView();
}
public Cocos2dxGLSurfaceView(final Context context, final AttributeSet attrs) {
super(context, attrs);
this.setEGLContextClientVersion(2);
this.initView();
}
protected void initView() {
this.setFocusableInTouchMode(true);
Cocos2dxGLSurfaceView.mCocos2dxGLSurfaceView = this;
Cocos2dxGLSurfaceView.sCocos2dxTextInputWraper = new Cocos2dxTextInputWraper(this);
Cocos2dxGLSurfaceView.sHandler = new Handler() {
@Override
public void handleMessage(final Message msg) {
switch (msg.what) {
case HANDLER_OPEN_IME_KEYBOARD:
if (null != Cocos2dxGLSurfaceView.this.mCocos2dxEditText && Cocos2dxGLSurfaceView.this.mCocos2dxEditText.requestFocus()) {
Cocos2dxGLSurfaceView.this.mCocos2dxEditText.removeTextChangedListener(Cocos2dxGLSurfaceView.sCocos2dxTextInputWraper);
Cocos2dxGLSurfaceView.this.mCocos2dxEditText.setText("");
final String text = (String) msg.obj;
Cocos2dxGLSurfaceView.this.mCocos2dxEditText.append(text);
Cocos2dxGLSurfaceView.sCocos2dxTextInputWraper.setOriginText(text);
Cocos2dxGLSurfaceView.this.mCocos2dxEditText.addTextChangedListener(Cocos2dxGLSurfaceView.sCocos2dxTextInputWraper);
final InputMethodManager imm = (InputMethodManager) Cocos2dxGLSurfaceView.mCocos2dxGLSurfaceView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(Cocos2dxGLSurfaceView.this.mCocos2dxEditText, 0);
Log.d("GLSurfaceView", "showSoftInput");
}
break;
case HANDLER_CLOSE_IME_KEYBOARD:
if (null != Cocos2dxGLSurfaceView.this.mCocos2dxEditText) {
Cocos2dxGLSurfaceView.this.mCocos2dxEditText.removeTextChangedListener(Cocos2dxGLSurfaceView.sCocos2dxTextInputWraper);
final InputMethodManager imm = (InputMethodManager) Cocos2dxGLSurfaceView.mCocos2dxGLSurfaceView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(Cocos2dxGLSurfaceView.this.mCocos2dxEditText.getWindowToken(), 0);
Log.d("GLSurfaceView", "HideSoftInput");
}
break;
}
}
};
}
// ===========================================================
// Getter & Setter
// ===========================================================
public void setCocos2dxRenderer(final Cocos2dxRenderer renderer) {
this.mCocos2dxRenderer = renderer;
this.setRenderer(this.mCocos2dxRenderer);
}
private String getContentText() {
return this.mCocos2dxRenderer.getContentText();
}
public Cocos2dxEditText getCocos2dxEditText() {
return this.mCocos2dxEditText;
}
public void setCocos2dxEditText(final Cocos2dxEditText pCocos2dxEditText) {
this.mCocos2dxEditText = pCocos2dxEditText;
if (null != this.mCocos2dxEditText && null != Cocos2dxGLSurfaceView.sCocos2dxTextInputWraper) {
this.mCocos2dxEditText.setOnEditorActionListener(Cocos2dxGLSurfaceView.sCocos2dxTextInputWraper);
this.mCocos2dxEditText.setCocos2dxGLSurfaceView(this);
this.requestFocus();
}
}
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
@Override
public void onResume() {
super.onResume();
this.queueEvent(new Runnable() {
@Override
public void run() {
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleOnResume();
}
});
}
@Override
public void onPause() {
this.queueEvent(new Runnable() {
@Override
public void run() {
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleOnPause();
}
});
super.onPause();
}
@Override
public boolean onTouchEvent(final MotionEvent pMotionEvent) {
// these data are used in ACTION_MOVE and ACTION_CANCEL
final int pointerNumber = pMotionEvent.getPointerCount();
final int[] ids = new int[pointerNumber];
final float[] xs = new float[pointerNumber];
final float[] ys = new float[pointerNumber];
for (int i = 0; i < pointerNumber; i++) {
ids[i] = pMotionEvent.getPointerId(i);
xs[i] = pMotionEvent.getX(i);
ys[i] = pMotionEvent.getY(i);
}
switch (pMotionEvent.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_POINTER_DOWN:
final int indexPointerDown = pMotionEvent.getAction() >> MotionEvent.ACTION_POINTER_ID_SHIFT;
final int idPointerDown = pMotionEvent.getPointerId(indexPointerDown);
final float xPointerDown = pMotionEvent.getX(indexPointerDown);
final float yPointerDown = pMotionEvent.getY(indexPointerDown);
this.queueEvent(new Runnable() {
@Override
public void run() {
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionDown(idPointerDown, xPointerDown, yPointerDown);
}
});
break;
case MotionEvent.ACTION_DOWN:
// there are only one finger on the screen
final int idDown = pMotionEvent.getPointerId(0);
final float xDown = xs[0];
final float yDown = ys[0];
this.queueEvent(new Runnable() {
@Override
public void run() {
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionDown(idDown, xDown, yDown);
}
});
break;
case MotionEvent.ACTION_MOVE:
this.queueEvent(new Runnable() {
@Override
public void run() {
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionMove(ids, xs, ys);
}
});
break;
case MotionEvent.ACTION_POINTER_UP:
final int indexPointUp = pMotionEvent.getAction() >> MotionEvent.ACTION_POINTER_ID_SHIFT;
final int idPointerUp = pMotionEvent.getPointerId(indexPointUp);
final float xPointerUp = pMotionEvent.getX(indexPointUp);
final float yPointerUp = pMotionEvent.getY(indexPointUp);
this.queueEvent(new Runnable() {
@Override
public void run() {
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionUp(idPointerUp, xPointerUp, yPointerUp);
}
});
break;
case MotionEvent.ACTION_UP:
// there are only one finger on the screen
final int idUp = pMotionEvent.getPointerId(0);
final float xUp = xs[0];
final float yUp = ys[0];
this.queueEvent(new Runnable() {
@Override
public void run() {
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionUp(idUp, xUp, yUp);
}
});
break;
case MotionEvent.ACTION_CANCEL:
this.queueEvent(new Runnable() {
@Override
public void run() {
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleActionCancel(ids, xs, ys);
}
});
break;
}
/*
if (BuildConfig.DEBUG) {
Cocos2dxGLSurfaceView.dumpMotionEvent(pMotionEvent);
}
*/
return true;
}
/*
* This function is called before Cocos2dxRenderer.nativeInit(), so the
* width and height is correct.
*/
@Override
protected void onSizeChanged(final int pNewSurfaceWidth, final int pNewSurfaceHeight, final int pOldSurfaceWidth, final int pOldSurfaceHeight) {
if(!this.isInEditMode()) {
this.mCocos2dxRenderer.setScreenWidthAndHeight(pNewSurfaceWidth, pNewSurfaceHeight);
}
}
@Override
public boolean onKeyDown(final int pKeyCode, final KeyEvent pKeyEvent) {
switch (pKeyCode) {
case KeyEvent.KEYCODE_BACK:
case KeyEvent.KEYCODE_MENU:
this.queueEvent(new Runnable() {
@Override
public void run() {
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleKeyDown(pKeyCode);
}
});
return true;
default:
return super.onKeyDown(pKeyCode, pKeyEvent);
}
}
// ===========================================================
// Methods
// ===========================================================
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
public static void openIMEKeyboard() {
final Message msg = new Message();
msg.what = Cocos2dxGLSurfaceView.HANDLER_OPEN_IME_KEYBOARD;
msg.obj = Cocos2dxGLSurfaceView.mCocos2dxGLSurfaceView.getContentText();
Cocos2dxGLSurfaceView.sHandler.sendMessage(msg);
}
public static void closeIMEKeyboard() {
final Message msg = new Message();
msg.what = Cocos2dxGLSurfaceView.HANDLER_CLOSE_IME_KEYBOARD;
Cocos2dxGLSurfaceView.sHandler.sendMessage(msg);
}
public void insertText(final String pText) {
this.queueEvent(new Runnable() {
@Override
public void run() {
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleInsertText(pText);
}
});
}
public void deleteBackward() {
this.queueEvent(new Runnable() {
@Override
public void run() {
Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleDeleteBackward();
}
});
}
private static void dumpMotionEvent(final MotionEvent event) {
final String names[] = { "DOWN", "UP", "MOVE", "CANCEL", "OUTSIDE", "POINTER_DOWN", "POINTER_UP", "7?", "8?", "9?" };
final StringBuilder sb = new StringBuilder();
final int action = event.getAction();
final int actionCode = action & MotionEvent.ACTION_MASK;
sb.append("event ACTION_").append(names[actionCode]);
if (actionCode == MotionEvent.ACTION_POINTER_DOWN || actionCode == MotionEvent.ACTION_POINTER_UP) {
sb.append("(pid ").append(action >> MotionEvent.ACTION_POINTER_ID_SHIFT);
sb.append(")");
}
sb.append("[");
for (int i = 0; i < event.getPointerCount(); i++) {
sb.append("#").append(i);
sb.append("(pid ").append(event.getPointerId(i));
sb.append(")=").append((int) event.getX(i));
sb.append(",").append((int) event.getY(i));
if (i + 1 < event.getPointerCount()) {
sb.append(";");
}
}
sb.append("]");
Log.d(Cocos2dxGLSurfaceView.TAG, sb.toString());
}
}
//////////////////////////////////////////////////////////////////////////////////////////////可见
无论是Activity的生命周期回调还是View的生命周期回调都给了Cocos2dxRenderer
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package org.cocos2dx.lib;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLSurfaceView;
public class Cocos2dxRenderer implements GLSurfaceView.Renderer {
// ===========================================================
// Constants
// ===========================================================
private final static long NANOSECONDSPERSECOND = 1000000000L;
private final static long NANOSECONDSPERMICROSECOND = 1000000;
private static long sAnimationInterval = (long) (1.0 / 60 * Cocos2dxRenderer.NANOSECONDSPERSECOND);
// ===========================================================
// Fields
// ===========================================================
private long mLastTickInNanoSeconds;
private int mScreenWidth;
private int mScreenHeight;
// ===========================================================
// Constructors
// ===========================================================
// ===========================================================
// Getter & Setter
// ===========================================================
public static void setAnimationInterval(final double pAnimationInterval) {
Cocos2dxRenderer.sAnimationInterval = (long) (pAnimationInterval * Cocos2dxRenderer.NANOSECONDSPERSECOND);
}
public void setScreenWidthAndHeight(final int pSurfaceWidth, final int pSurfaceHeight) {
this.mScreenWidth = pSurfaceWidth;
this.mScreenHeight = pSurfaceHeight;
}
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
@Override
public void onSurfaceCreated(final GL10 pGL10, final EGLConfig pEGLConfig) {
Cocos2dxRenderer.nativeInit(this.mScreenWidth, this.mScreenHeight);
this.mLastTickInNanoSeconds = System.nanoTime();
}
@Override
public void onSurfaceChanged(final GL10 pGL10, final int pWidth, final int pHeight) {
}
@Override
public void onDrawFrame(final GL10 gl) {
final long nowInNanoSeconds = System.nanoTime();
final long interval = nowInNanoSeconds - this.mLastTickInNanoSeconds;
// should render a frame when onDrawFrame() is called or there is a
// "ghost"
Cocos2dxRenderer.nativeRender();
// fps controlling
if (interval < Cocos2dxRenderer.sAnimationInterval) {
try {
// because we render it before, so we should sleep twice time interval
Thread.sleep((Cocos2dxRenderer.sAnimationInterval - interval) * 2 / Cocos2dxRenderer.NANOSECONDSPERMICROSECOND);
} catch (final Exception e) {
}
}
this.mLastTickInNanoSeconds = nowInNanoSeconds;
}
// ===========================================================
// Methods
// ===========================================================
private static native void nativeTouchesBegin(final int pID, final float pX, final float pY);
private static native void nativeTouchesEnd(final int pID, final float pX, final float pY);
private static native void nativeTouchesMove(final int[] pIDs, final float[] pXs, final float[] pYs);
private static native void nativeTouchesCancel(final int[] pIDs, final float[] pXs, final float[] pYs);
private static native boolean nativeKeyDown(final int pKeyCode);
private static native void nativeRender();
private static native void nativeInit(final int pWidth, final int pHeight);
private static native void nativeOnPause();
private static native void nativeOnResume();
public void handleActionDown(final int pID, final float pX, final float pY) {
Cocos2dxRenderer.nativeTouchesBegin(pID, pX, pY);
}
public void handleActionUp(final int pID, final float pX, final float pY) {
Cocos2dxRenderer.nativeTouchesEnd(pID, pX, pY);
}
public void handleActionCancel(final int[] pIDs, final float[] pXs, final float[] pYs) {
Cocos2dxRenderer.nativeTouchesCancel(pIDs, pXs, pYs);
}
public void handleActionMove(final int[] pIDs, final float[] pXs, final float[] pYs) {
Cocos2dxRenderer.nativeTouchesMove(pIDs, pXs, pYs);
}
public void handleKeyDown(final int pKeyCode) {
Cocos2dxRenderer.nativeKeyDown(pKeyCode);
}
public void handleOnPause() {
Cocos2dxRenderer.nativeOnPause();
}
public void handleOnResume() {
Cocos2dxRenderer.nativeOnResume();
}
private static native void nativeInsertText(final String pText);
private static native void nativeDeleteBackward();
private static native String nativeGetContentText();
public void handleInsertText(final String pText) {
Cocos2dxRenderer.nativeInsertText(pText);
}
public void handleDeleteBackward() {
Cocos2dxRenderer.nativeDeleteBackward();
}
public String getContentText() {
return Cocos2dxRenderer.nativeGetContentText();
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}
看到没----------------------------------------一堆native关键字----------------------------------------------------------
///////////JNI目录下的main.cpp
#include "AppDelegate.h"
#include "platform/android/jni/JniHelper.h"
#include <jni.h>
#include <android/log.h>
#include "HelloWorldScene.h"
#define LOG_TAG "main"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
using namespace cocos2d;
extern "C"
{
jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
JniHelper::setJavaVM(vm);
return JNI_VERSION_1_4;
}
void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit(JNIEnv* env, jobject thiz, jint w, jint h)
{
if (!CCDirector::sharedDirector()->getOpenGLView())
{
CCEGLView *view = CCEGLView::sharedOpenGLView();
view->setFrameSize(w, h);
AppDelegate *pAppDelegate = new AppDelegate();
CCApplication::sharedApplication()->run();
}
else
{
ccDrawInit();
ccGLInvalidateStateCache();
CCShaderCache::sharedShaderCache()->reloadDefaultShaders();
CCTextureCache::reloadAllTextures();
CCNotificationCenter::sharedNotificationCenter()->postNotification(EVNET_COME_TO_FOREGROUND, NULL);
CCDirector::sharedDirector()->setGLDefaultValues();
}
}
}
/////////////////////////////////////////////////////////////////////////////////////
所以在 Android平台窗口和 View是在java中Android FrameWork定义的,窗口和View的事件回掉基于Android FrameWork,只不过通过JNI传递到CCDirector,再由CCDirector分发到各个Node.
IOS平台也相差不多看代码:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#import <UIKit/UIKit.h>
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; //定义自动释放池
int retVal = UIApplicationMain(argc, argv, nil, @"AppController"); //定义消息循环和入口控制器AppController
[pool release];
return retVal;
}
/////////////////////////////////////看看这个入口控制器AppController
AppController.h
@class RootViewController;
@interface AppController : NSObject <UIAccelerometerDelegate, UIAlertViewDelegate, UITextFieldDelegate,UIApplicationDelegate> {
UIWindow *window; //window处理事件
RootViewController *viewController;//跟控制器,作为窗口View的容器
}
@end
/////////////////////////////////////////////////////////////////////////////AppController.mm
#import <UIKit/UIKit.h>
#import "AppController.h"
#import "cocos2d.h"
#import "EAGLView.h"
#import "AppDelegate.h"
#import "RootViewController.h"
@implementation AppController
#pragma mark -
#pragma mark Application lifecycle
// cocos2d application instance
static AppDelegate s_sharedApplication;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// Add the view controller's view to the window and display.
window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]];
EAGLView *__glView = [EAGLView viewWithFrame: [window bounds]
pixelFormat: kEAGLColorFormatRGBA8
depthFormat: GL_DEPTH_COMPONENT16
preserveBackbuffer: NO
sharegroup:nil
multiSampling:NO
numberOfSamples:0];
// Use RootViewController manage EAGLView 创建了一个EAGLView 添加到viewController
viewController = [[RootViewController alloc] initWithNibName:nil bundle:nil];
viewController.wantsFullScreenLayout = YES;
viewController.view = __glView;
// Set RootViewController to window
if ( [[UIDevice currentDevice].systemVersion floatValue] < 6.0)
{
// warning: addSubView doesn't work on iOS6
[window addSubview: viewController.view];
}
else
{
// use this method on ios6
[window setRootViewController:viewController];
}
[window makeKeyAndVisible]; //处理用户事件
[[UIApplication sharedApplication] setStatusBarHidden: YES];
cocos2d::CCApplication::sharedApplication()->run(); ///看到没,都要执行CCApplication::sharedApplication()->run();
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
cocos2d::CCDirector::sharedDirector()->pause();
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
cocos2d::CCDirector::sharedDirector()->resume();
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
cocos2d::CCApplication::sharedApplication()->applicationDidEnterBackground();
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
cocos2d::CCApplication::sharedApplication()->applicationWillEnterForeground();
}
- (void)applicationWillTerminate:(UIApplication *)application {
}
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
}
- (void)dealloc {
[super dealloc];
}
@end
//////////////////////////////////////////////////RootViewController.h可以看到,其实什么都没有
#import <UIKit/UIKit.h>
@interface RootViewController : UIViewController {
}
@end
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
cocos2d::CCApplication::sharedApplication()->run(); 究竟执行了什么呢?
。。。。。。。。。。。。。。。。。。。
CCDirector::sharedDirector()->mainLoop();
。。。。。。。。。。。。。。。。。
是导演的主循环,导演很忙,下次再聊。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。