native app 集成 cocos-2dx-js 3.11 (IOS篇)

前提:

   已有native appiosandroid都是分别开发,很多常用功能已经开发完善,测试稳定,现需要往里面添加游戏模块。


选择:

1、使用引擎完全重写app ———— 工作量太大,体力活,坑也多,暂不考虑。

2、纯原生进行开发。————需要集成各种图形库,第三方库,开发者需要有图形开发基础。成本太高,舍弃。

3、hybrid方案增量开发。————使用h5开发游戏模块,通过webview方式集成进app中,成本较低,第一版就使用这个方案,用户体验太差。

4、插件(模块)方式集成游戏引擎进行开发。————使用引擎开发游戏模块部分,原生控件部分不动,用户体验最佳。开发成本相对折中。

  

综合调研,最终决定选择集成cocos2dx-js3.11)的方案,其技术关键点在于如何解决内存问题。


关键步骤记录:

1、原项目中添加引擎工程

native app 集成 cocos-2dx-js 3.11 (IOS篇)_第1张图片


2、添加库依赖

native app 集成 cocos-2dx-js 3.11 (IOS篇)_第2张图片

3、添加头文件引用

native app 集成 cocos-2dx-js 3.11 (IOS篇)_第3张图片


4、修改编译选项



5、修改原项目中引用报错、函数冲突、c++ oc混编等等问题

__weak __typeof(&*self) weakSelf=self;

EXTScope中宏定义 onExit cocos中函数冲突,修改重命名

将混编文件后缀名改为 .mm

原项目中OpenSSL库冲突,删除其中之一即可


6、封装跳转页面,新建 GameMainController.h

#import 

@interface GameMainController : UIViewController

+(BOOL)callNativeUIWithTitle:(NSString *) title andContent:(NSString *)content;

@end

static GameMainController* instace;

//———————

7、实现 GameMainController.m

#import "GameMainController.h"
#import "CCAppDelegate.h"
#import "platform/ios/CCEAGLView-ios.h"
#import "platform/ios/CCDirectorCaller-ios.h"
#import "cocos2d.h"

static cocos2d::Size designResolutionSize = cocos2d::Size(480, 320);
static cocos2d::Size smallResolutionSize = cocos2d::Size(480, 320);
static cocos2d::Size mediumResolutionSize = cocos2d::Size(1024, 768);
static cocos2d::Size largeResolutionSize = cocos2d::Size(2048, 1536);


@interface GameMainController ( ) {
    UIWindow *window;
}
@property (strong, nonatomic) CCEAGLView *eaglView;
@end
@implementation GameMainController

@synthesize eaglView = _eaglView;

+(BOOL)callNativeUIWithTitle:(NSString *) title andContent:(NSString *)content{
    [instace.navigationController popViewControllerAnimated:YES];
    return true;
}


- (id)init{
    self = [super init];
    return self;
}

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    cocos2d::Application *app = cocos2d::Application::getInstance();
    app->initGLContextAttrs();
    cocos2d::GLViewImpl::convertAttrs();
    
    CCEAGLView *eaglView = [CCEAGLView viewWithFrame: [[UIScreen mainScreen] bounds]
                                         pixelFormat: kEAGLColorFormatRGBA8
                                         depthFormat: GL_DEPTH24_STENCIL8_OES
                                  preserveBackbuffer: NO
                                          sharegroup: nil
                                       multiSampling: NO
                                     numberOfSamples: 0 ];
    
    self.eaglView = eaglView;
    
    [self.eaglView setMultipleTouchEnabled:NO];
    [self.view insertSubview:self.eaglView atIndex:0];

    cocos2d::GLView *glview = cocos2d::GLViewImpl::createWithEAGLView((__bridge void *)self.eaglView);
    cocos2d::Director::getInstance()->setOpenGLView(glview);
    
    CCAppDelegate *app_delegate = (CCAppDelegate*) app;
    app_delegate->enterCocos();
    instace = self;
    
    
}

- (void)viewDidUnload {
    [super viewDidUnload];
}

- (void)viewWillDisappear:(BOOL)animated{
   cocos2d::Director::getInstance()->end();
}

-(void)viewDidDisappear:(BOOL)animated {
    
    [super viewWillDisappear:animated];
    
    auto director = cocos2d::Director::getInstance();
    director->stopAnimation();
    director->purgeCachedData();
   
    if (self.eaglView) {
        [self.eaglView removeFromSuperview];
        self.eaglView = nil;
    }
    [self dismissViewControllerAnimated:YES completion:nil];
    
}

@end


8、添加 enterCocos

void CCAppDelegate::enterCocos()
{
    // initialize director
    auto director = Director::getInstance();
    
    auto glview = director->getOpenGLView();
    if(!glview) {
#if(CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
        glview = cocos2d::GLViewImpl::create("WebGame");
#else
        glview = cocos2d::GLViewImpl::createWithRect("WebGame", Rect(0,0,960,640));
#endif
        director->setOpenGLView(glview);
    }
    
    // set FPS. the default value is 1.0/60 if you don't call this
    director->setAnimationInterval(1.0 / 60);
    director->startAnimation();
    
    ScriptingCore* sc = ScriptingCore::getInstance();

    sc->cleanAllScript();
    sc->restartVM();
    
    sc->addRegisterCallback(register_all_cocos2dx);
    sc->addRegisterCallback(register_cocos2dx_js_core);
    sc->addRegisterCallback(jsb_register_system);
    
    // extension can be commented out to reduce the package
    sc->addRegisterCallback(register_all_cocos2dx_extension);
    sc->addRegisterCallback(register_all_cocos2dx_extension_manual);
    
    // chipmunk can be commented out to reduce the package
    sc->addRegisterCallback(jsb_register_chipmunk);
    // opengl can be commented out to reduce the package
    sc->addRegisterCallback(JSB_register_opengl);
    
    // builder can be commented out to reduce the package
    sc->addRegisterCallback(register_all_cocos2dx_builder);
    sc->addRegisterCallback(register_CCBuilderReader);
    
    // ui can be commented out to reduce the package, attension studio need ui module
    sc->addRegisterCallback(register_all_cocos2dx_ui);
    sc->addRegisterCallback(register_all_cocos2dx_ui_manual);
    
    // studio can be commented out to reduce the package,
    sc->addRegisterCallback(register_all_cocos2dx_studio);
    sc->addRegisterCallback(register_all_cocos2dx_studio_manual);
    
    // spine can be commented out to reduce the package
    sc->addRegisterCallback(register_all_cocos2dx_spine);
    sc->addRegisterCallback(register_all_cocos2dx_spine_manual);
    
    // XmlHttpRequest can be commented out to reduce the package
    sc->addRegisterCallback(MinXmlHttpRequest::_js_register);
    // websocket can be commented out to reduce the package
    sc->addRegisterCallback(register_jsb_websocket);
    // sokcet io can be commented out to reduce the package
    sc->addRegisterCallback(register_jsb_socketio);
    
    // 3d can be commented out to reduce the package
    sc->addRegisterCallback(register_all_cocos2dx_3d);
    sc->addRegisterCallback(register_all_cocos2dx_3d_manual);
    
    // 3d extension can be commented out to reduce the package
    sc->addRegisterCallback(register_all_cocos2dx_3d_extension);
    
#if CC_USE_3D_PHYSICS && CC_ENABLE_BULLET_INTEGRATION
    // Physics 3d can be commented out to reduce the package
    sc->addRegisterCallback(register_all_cocos2dx_physics3d);
    sc->addRegisterCallback(register_all_cocos2dx_physics3d_manual);
#endif
    
#if CC_USE_NAVMESH
    sc->addRegisterCallback(register_all_cocos2dx_navmesh);
    sc->addRegisterCallback(register_all_cocos2dx_navmesh_manual);
#endif
    
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    sc->addRegisterCallback(register_all_cocos2dx_experimental_video);
    sc->addRegisterCallback(register_all_cocos2dx_experimental_video_manual);
    sc->addRegisterCallback(register_all_cocos2dx_experimental_webView);
    sc->addRegisterCallback(register_all_cocos2dx_experimental_webView_manual);
#endif
    
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT || CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
    sc->addRegisterCallback(register_all_cocos2dx_audioengine);
#endif
    
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
    sc->addRegisterCallback(JavascriptJavaBridge::_js_register);
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC)
    sc->addRegisterCallback(JavaScriptObjCBridge::_js_register);
#endif
    sc->start();
    sc->runScript("script/jsb_boot.js");
#if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0)
    sc->enableDebugger();
#endif
    ScriptEngineProtocol *engine = ScriptingCore::getInstance();
    ScriptEngineManager::getInstance()->setScriptEngine(engine);
    
    ScriptingCore::getInstance()->runScript("main.js");

    JSContext *cx = ScriptingCore::getInstance()->getGlobalContext();
    jsval args[1];
    args[0] = std_string_to_jsval(cx, "gameId=10003");
    ScriptingCore::getInstance()->executeFunctionWithOwner(OBJECT_TO_JSVAL(sc->getGlobalObject()), "EnterCocos”, 1, args);
    
}


9、添加main.js 中添加入口方法

 EnterCocos=function(gameArgs){
    cc.director.runScene(new HelloWorldScene(gameArgs));
 };

总结:

       效果达到预期,内存释放基本正常,接下来的工作就是优化native切换时的预处理体验,以及完善游戏本身,删除没有使用到的引擎模块,增加热更新功能等等

你可能感兴趣的:(cocos,c++)