已有native app,ios、android都是分别开发,很多常用功能已经开发完善,测试稳定,现需要往里面添加游戏模块。
选择:
1、使用引擎完全重写app。 ———— 工作量太大,体力活,坑也多,暂不考虑。
2、纯原生进行开发。————需要集成各种图形库,第三方库,开发者需要有图形开发基础。成本太高,舍弃。
3、hybrid方案增量开发。————使用h5开发游戏模块,通过webview方式集成进app中,成本较低,第一版就使用这个方案,用户体验太差。
4、插件(模块)方式集成游戏引擎进行开发。————使用引擎开发游戏模块部分,原生控件部分不动,用户体验最佳。开发成本相对折中。
综合调研,最终决定选择集成cocos2dx-js(3.11)的方案,其技术关键点在于如何解决内存问题。
关键步骤记录:
1、原项目中添加引擎工程
2、添加库依赖
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切换时的预处理体验,以及完善游戏本身,删除没有使用到的引擎模块,增加热更新功能等等