Cocos Creator游戏集成到原生iOS及JS和OC交互

文章主要参考:https://blog.csdn.net/xjw532881071/article/details/108715666 ,在原来基础上,根据自己的集成经验进行了完善

1:获取到Cocos Creator构建的iOS工程

这一步主要是Cocos Creator开发工程师提供,最后给到我们的是构建好的


image.png

jsb-default文件夹下的内容就是我们iOS开发需要的代码了

2.运行jsb-default下的iOS工程

这一步的作用是为了验证构建的工程是没有问题的,同时获取到我们这个工程集成到iOS需要的配置是哪些.

image.png

通过以上路劲,运行iOS项目hello_world.xcodeproj,进行证书配置,然后采用真机运行,如果能够正常运行,说明构建的iOS工程是没有问题的.

得到一个能够正常运行的工程非常重要,非常重要,非常重要!!!因为我们在自己的iOS工程中集成Cocos Creator游戏用到的配置信息都是从这个工程中是查找的.

3.真正的集成开始

3.1 导入游戏代码到iOS原生工程

在工程目录下创建 cocos 文件夹, 然后找到之前游戏构建的代码,复制到cocos文件夹下,这里的jsb-default就是cocos项目构建成功后的代码:

image.png

注:frameworks中,可以只导入frameworks-->runtime-src-->proj.ios_mac + Classes , proj.android-studioproj.win32 可以不导入

3.2 导入游戏代码到iOS原生工程

打开iOS原生工程,导入cocos下的文件和文件夹.这里要注意文件夹的黄色(group)和蓝色(fold references)区别。
以蓝色fold references导入assets、cocos2d_libs.xcodeproj;

新建一个名为CocosResources的group,并以fold references模式导入main.js、project.json、src、jsb-adapter到其中;

以黄色group模式导入ios、Classes文件夹;

注:如果没有cocos2d_libs.xcodeproj,找cocos开发工程师构建(就是构建时勾选default,不是link)

结果如下:


Pasted Graphic 2.png

3.3 工程中移除ios文件夹下的main.m

image.png

3.4 导入项目的依赖库

这里我们就需要使用到之前运行起来的cocos下生产的工程了,去里面找依赖库,我的如下:


image.png

把库全部导入即可, .lib的文件,直接采用tbd代替;

3.5 导入libcocos2d iOS(cocos2d_libs)

为原生iOS工程的TARGETS添加Dependences(Build Phase/Dependencies):libcocos2d iOS(cocos2d_libs),有两处都要添加

image.png

注:如果删除了cocos下的文件夹,重新导入了,可能会导致 libcocos2d iOS丢失,需要再次按照上面的流程重新导入一次,不然报错: cocos的一些方法找不到了;

3.6 工程配置

  • 参考cocos导出的iOS工程为原生工程的PROJECT添加以下头文件搜索路径(Build Settings/Search Paths/User Header Search Paths), (SRCROOT)为相对.xcodeproj文件的路径, Always Search User Paths设为Yes
    Pasted Graphic 5.png

注:以上的User Header Search Paths中的配置要参考之前cocos导出的iOS工程,同时请验证路径是否正确,我的如下:

Pasted Graphic 6.png

这里需要100%确认正确,不然会出现一堆的问题;

  • 参考cocos导出的iOS工程为原生工程的TARGETS添加以下头文件(搜索路径:Build Settings/Search Paths/User Header Search Paths)

  • 同时把Always Search User Paths设为Yes;

  • TARGETS下,为Library Search Paths添加:
    $(SRCROOT)/cocos/frameworks/cocos2d-x/external/iOS/libs

cocos/frameworks/cocos2d-x/external/iOS/libs这个路径自己验证下,如果你创建的也是cocos文件夹,就是一样的,反正找到libs就行;

Pasted Graphic 8.png
  • 为TARGETS为other linker flags 添加 -Objc

  • 把PROJECT和TARGETS的Enable BitCode都设为NO

  • 分别修改PROJECT、TARGETS下C Language Dialectgnu11

注:这里的gnu11是我的工程的,根据自己的cocos的工程查找到对应的,去配置

  • 在PROJECT和TARGETS为Preprocessor Macros添加预定义宏 ,具体看工程,所有的宏也根据自己的cocos的工程查找到对应的
image.png

3.7 工程代码的修改

  • 修改Classes文件夹下的AppDelegate.hAppDelegate.cpp
    把名称改成CocosAppDelegate.hCocosAppDelegate.cpp,把代码内的AppDelegate全部替换成CocosAppDelegate

    image.png

  • 修改Classes文件夹下的 CocosAppDelegate.cppjsb_module_register.cpptype,改成Objective-C++ (这是一个巨坑,如果你的代码在不修改的情况下,能正常运行,就保持原C++,如果是报错就改成Objective-C++,个人感觉这个应该和我们后面配置的gnu11 或者 C99有关)

    Pasted Graphic 9.png

  • 把ios文件夹下的AppController.mm内的#import "AppDelegate.h"改成#import "CocosAppDelegate.h",把下面的app = new CocosAppDelegate(bounds.size.width * scale, bounds.size.height * scale); app->setMultitouch(true);改掉

    image.png

  • 很重要的一点,前面忘记提了,之前classes文件下的文件改名后,建议是删除掉,重新导入一次,不然会出现报错或者运行完界面黑屏 !!!! (PS:Target-->Build Phases-->Compile Sources)

  • 修改 目录: cocos2d_libs—>platform——>iOS下的 CCApplication-ios.mm 文件的end方法入下(322行)

void Application::end()
{
    //    delete this;
       //
       //    exit(0);
       
       // 上面是原来的样子
   #if USE_AUDIO
       AudioEngine::end();
   #endif
       // stop main loop
       [(MainLoop*)_delegate stopMainLoop];
 
}

修改它的目的是为了cocos引擎在启动后,退出游戏不自动关闭引擎,不杀死APP,再次进入游戏,可以直接开始游戏了,更加的快速;

3.8 搭建游戏引擎交互界面,游戏界面VC

搭建 CocosMng,这里面包括了所有的JS调用OC的方法,OC调用JS的方法,有参数,无参数,多个参数等的方法调用,这个CocosMng类名需要提供给cocos开发人员,里面注释的方法不是不能用,而是要看cocos给的方法的参数是如何的,是让我们传一个int,一个string,还是多个字符串还是json字符串:

//
//  CocosMng.h
//
//  cocos引擎管理器,负责iOS启动、退出以及管理cocos引擎
/*
 
 类名不要改变,对应cocos的JS调用OC的类名;
 所有的供JS调用的方法,使用类方法;
 所有的OC调用的JS方法,统一写在CocosMng下;
 
 */

#ifndef CocosMng_h
#define CocosMng_h

#import <UIKit/UIKit.h>

#include "platform/ios/CCEAGLView-ios.h"

@protocol CocosMngDelegate <NSObject>

//游戏开始
-(void)cocosGameStart;
//返回游戏分数
-(void)cocosgameEnd:(int)score;
//退出游戏
-(void)cocosGameClose;


@end


@interface CocosMng : NSObject
{
}

@property(nonatomic, retain) UIViewController* viewController;

@property (nonatomic, weak) id <CocosMngDelegate> delegate;

+(instancetype)getInstance;
+(void) destroyInstance;
-(instancetype)init;
-(void)startCocos; // 启动cocos游戏引擎
-(void)exitCocos;  // 退出cocos游戏引擎
+(void)exitCocosForJS;   // 给js调用,js只能调用静态方法

+(CCEAGLView *)getCocosView;

-(void)didEnterBackground;  // app进入后台时调用,通知游戏js层
-(void)willEnterForeground; // app返回前台时调用, 通知游戏js层
-(void)willTerminate;


//oc 调用 js  测试
-(void)testOCForJS;


-(void)gamePauses;//游戏暂停
-(void)gameContinue;//游戏继续
-(void)gameOver;//游戏结束


#pragma mark 初始化参数设置
-(void)gameInitDataSet:(NSDictionary *)data;

#pragma mark fish 给JS调用的方法
//初始化配置,此方法被调用后,需要调用recvDataFromNativeWithData把初始化参数传递给JS
+(void)initGameVC;

//游戏开始
+(void)game_GetStar_Start;
//返回游戏分数
+(void)game_GetStar_end:(int)score;
//退出游戏
+(void)closeGameVC;

#pragma mark fish OC调用JS的方法
//log输出:printlog
-(void)printlog:(NSString *)logString;
//初始化方法recvDataFromNative(historyMaxFraction, model, max, min)
-(void)recvDataFromNativeWithData:(NSDictionary *)dataDic;
//接收肌电值数据onRecvFly(s)
-(void)onRecvFly:(int)num;
//导联脱落onDaoLianRecv
-(void)onDaoLianRecv:(BOOL)recv;
//电极脱落onDianJiRecv
-(void)onDianJiRecv:(BOOL)recv;

@end


#endif /* CocosMng_h */

#import "CocosMng.h"

#import "cocos2d.h"
#import "CocosAppDelegate.h"
#import "SDKWrapper.h"
#import "platform/CCApplication.h"
#import "platform/ios/CCEAGLView-ios.h"
#import "cocos/scripting/js-bindings/jswrapper/SeApi.h"
#import "CRBeeGameController_new.h"

using namespace cocos2d;

static CocosMng * _instance = NULL;
static Application * _app = NULL;

@interface CocosMng ()

@property (nonatomic, strong) NSDictionary *gameData;

@end

@implementation CocosMng


+(instancetype)getInstance {
//    static dispatch_once_t onceToken;
//    dispatch_once(&onceToken, ^{
//        _instance = [[self alloc] init];
//    });
    
    if (!_instance) {
        _instance = [[CocosMng alloc]init];
    }
    
    return _instance;
}

+(void) destroyInstance {
    if (_instance != NULL) {
        _instance = NULL;
    }
}

+(CCEAGLView*)getCocosView {
    return (__bridge CCEAGLView *)cocos2d::Application::getInstance()->getView();
}

-(instancetype)init {
    self = [super init];
    if (self) {
        float scale = [[UIScreen mainScreen] scale];
        CGRect bounds = [[UIScreen mainScreen] bounds];
        // cocos2d application instance
        if (_app == NULL) {
            _app = new CocosAppDelegate(bounds.size.width * scale, bounds.size.height * scale);
            _app->setMultitouch(false);
        }
        
//        [self setupCocos];
    }
    
    return self;
}

//-(void)setupCocos {
//    self.viewController = [[CRBeeGameController_new alloc]init];
//    [self.viewController setModalPresentationStyle:UIModalPresentationFullScreen];
//}

-(void)startCocos {
    NSLog(@"start cocos.");
    
    _app->restart();
    return;
}

+ (void)exitCocosForJS {
    [[CocosMng getInstance]exitCocos];
}

- (void)exitCocos {
    if (_app == NULL) {
        return;
    }
    
    _app->end(); // mark: 这里修改了CCApplication-ios.mm,end不再直接退出游戏而是只停止主循环和音频播放
    [self.viewController dismissViewControllerAnimated:YES completion:NULL];
}

-(void)didEnterBackground {
    if (_app != NULL) {
        _app->onPause();
    }
}

-(void)willEnterForeground {
    if (_app != NULL) {
        _app->onResume();
    }
}

-(void)willTerminate {
    [self.viewController dismissViewControllerAnimated:YES completion:NULL];
    [CocosMng destroyInstance];
}

//oc 调用 js
-(void)testOCForJS{
//    NSLog(@"%s",__func__);
//    std::string strRet = "hahaha";
//    std::string jsCallStr = cocos2d::StringUtils::format("onGameStop();"); //Main.js
//    se::Value *ret = new se::Value();
//    se::ScriptEngine::getInstance()->evalString(jsCallStr.c_str() , -1 , ret);
//    NSLog(@"jsCallStr rtn = %s", ret->toString().c_str());
    
    
//    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(15 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        //测试  -->OC调用 JS 的方法 'window.testMethod'
        NSLog(@"OC调用 JS 的方法");
        std::string strRet = "hahaha";
        std::string jsCallStr = cocos2d::StringUtils::format("window.onGameStop();"); //gamectrl
        se::Value *ret = new se::Value();
        se::ScriptEngine::getInstance()->evalString(jsCallStr.c_str() , -1 , ret);
        NSLog(@"jsCallStr rtn");
//    });
    
    
    
}
/*
 1.std::string转NSString

 std::string _string("hello");
 NSString *str= [NSString stringWithCString:_string.c_str() encoding:[NSString defaultCStringEncoding]];

 2.NSString转std::string
 NSString  * nsfaceName=@"HELLO";
 const char  *  lpfaceName = [nsfaceName UTF8String];
 std::string   strFaceName=  [nsfaceName UTF8String];

 */

#pragma mark 游戏暂停
-(void)gamePauses{
    std::string strRet = "hahaha";
    std::string jsCallStr = cocos2d::StringUtils::format("window.onGameStop();"); //gamectrl
    se::Value *ret = new se::Value();
    se::ScriptEngine::getInstance()->evalString(jsCallStr.c_str() , -1 , ret);
    
    
}
#pragma mark 游戏继续
-(void)gameContinue{
    std::string strRet = "hahaha";
    std::string jsCallStr = cocos2d::StringUtils::format("window.onGameResume();"); //gamectrl
    se::Value *ret = new se::Value();
    se::ScriptEngine::getInstance()->evalString(jsCallStr.c_str() , -1 , ret);
}
#pragma mark 游戏结束
-(void)gameOver{
    std::string strRet = "hahaha";
    std::string jsCallStr = cocos2d::StringUtils::format("window.onGameOver();"); //gamectrl
    se::Value *ret = new se::Value();
    se::ScriptEngine::getInstance()->evalString(jsCallStr.c_str() , -1 , ret);
    
}

#pragma mark fish 给JS调用的方法
//初始化配置,此方法被调用后,需要调用recvDataFromNativeWithData把初始化参数传递给JS
+(void)initGameVC{
    NSLog(@"游戏初始化中~~~~~~~");
//    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [_instance recvDataFromNativeWithData:_instance.gameData];
//    });
    
}

//游戏开始
+(void)game_GetStar_Start{
    NSLog(@"游戏开始~~~~~~~");
    if (_instance.delegate && [_instance.delegate respondsToSelector:@selector(cocosGameStart)]) {
        [_instance.delegate cocosGameStart];
    }
}
//返回游戏分数
+(void)game_GetStar_end:(int)score{
    NSLog(@"游戏分数~~~~~~~%d",score);
    if (_instance.delegate && [_instance.delegate respondsToSelector:@selector(cocosgameEnd:)]) {
        [_instance.delegate cocosgameEnd:score];
    }
}
//退出游戏
+(void)closeGameVC{
    NSLog(@"游戏退出,关闭界面~~~~~~~");
    if (_instance.delegate && [_instance.delegate respondsToSelector:@selector(cocosGameClose)]) {
        [_instance.delegate cocosGameClose];
    }
}

#pragma mark 初始化参数设置
-(void)gameInitDataSet:(NSDictionary *)data{
    if (data) {
        _instance.gameData = [data copy];
    }else{
        //未赋值的情况下,给默认初值
        _instance.gameData =  @{
            @"historyMaxFraction":@(200),
            @"model":@(1),
            @"max":@(40),
            @"min":@(10)
        };
    }
}

#pragma mark fish OC调用JS的方法
//log输出:printlog
-(void)printlog:(NSString *)logString{
    std::string strRet = [logString UTF8String];//"haha";
    std::string jsCallStr = cocos2d::StringUtils::format("window.printlog(\"%s\");", strRet.c_str());
    se::Value *ret = new se::Value();
    se::ScriptEngine::getInstance()->evalString(jsCallStr.c_str() , -1 , ret);
}
//初始化方法recvDataFromNative(historyMaxFraction, model, max, min)
-(void)recvDataFromNativeWithData:(NSDictionary *)dataDic{
    NSString *hisScore = [NSString stringWithFormat:@"%@",dataDic[@"historyMaxFraction"]];
    NSString *model = [NSString stringWithFormat:@"%@",dataDic[@"model"]];
    NSString *max = [NSString stringWithFormat:@"%@",dataDic[@"max"]];
    NSString *min = [NSString stringWithFormat:@"%@",dataDic[@"min"]];
    std::string hisScoreRet = [hisScore UTF8String];
    std::string modelScoreRet = [model UTF8String];
    std::string maxScoreRet = [max UTF8String];
    std::string minScoreRet = [min UTF8String];
    std::string jsCallStrNew = cocos2d::StringUtils::format("window.recvDataFromNative2(\"%s\",\"%s\",\"%s\",\"%s\");", hisScoreRet.c_str(),modelScoreRet.c_str(),maxScoreRet.c_str(),minScoreRet.c_str());
    se::ScriptEngine::getInstance()->evalString(jsCallStrNew.c_str());
    
    
//    int historyMaxFraction = [dataDic[@"historyMaxFraction"] intValue];
//    int model = [dataDic[@"model"] intValue];
//    int max = [dataDic[@"max"] intValue];
//    int min = [dataDic[@"min"] intValue];
//    NSLog(@"初始参数:%d,%d,%d,%d",historyMaxFraction,model,max,min);
//
////    std::string jsCallStr = cocos2d::StringUtils::format("window.recvDataFromNative(\"%d,%d,%d,%d\");", historyMaxFraction,model,max,min);
//    std::string jsCallStr = cocos2d::StringUtils::format("window.recvDataFromNative(\"%d\",\"%d\",\"%d\",\"%d\");", historyMaxFraction,model,max,min);
//
//    se::ScriptEngine::getInstance()->evalString(jsCallStr.c_str());
   
    
}
//接收肌电值数据onRecvFly(s)
-(void)onRecvFly:(int)num{
    std::string jsCallStr = cocos2d::StringUtils::format("window.onRecvFly(\"%d\");", num);
    se::ScriptEngine::getInstance()->evalString(jsCallStr.c_str());
}
//导联脱落onDaoLianRecv
-(void)onDaoLianRecv:(BOOL)recv{
    std::string jsCallStr = cocos2d::StringUtils::format("window.onDaoLianRecv(\"%d\");", recv == 0?false:true);
    se::ScriptEngine::getInstance()->evalString(jsCallStr.c_str());
}
//电极脱落onDianJiRecv
-(void)onDianJiRecv:(BOOL)recv{
    std::string jsCallStr = cocos2d::StringUtils::format("window.onDianJiRecv(\"%d\");", recv == 0?false:true);
    se::ScriptEngine::getInstance()->evalString(jsCallStr.c_str());
}

//
//- (void)statusBarOrientationChanged:(NSNotification *)notification {
//    if (_app == NULL) {
//        return;
//    }
//
//    CGRect bounds = [UIScreen mainScreen].bounds;
//    float scale = [[UIScreen mainScreen] scale];
//    float width = bounds.size.width * scale;
//    float height = bounds.size.height * scale;
//    Application::getInstance()->updateViewSize(width, height);
//}
//
//- (void)applicationWillResignActive:(UIApplication *)application {
//    /*
//     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.
//     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.
//     */
//    if (_app == NULL) {
//        return;
//    }
//
//    _app->onPause();
//    [[SDKWrapper getInstance] applicationWillResignActive:application];
//}
//
//- (void)applicationDidBecomeActive:(UIApplication *)application {
//    /*
//     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.
//     */
//    if (!_app) {
//        return;
//    }
//
//    _app->onResume();
//    [[SDKWrapper getInstance] applicationDidBecomeActive:application];
//}
//
//- (void)applicationDidEnterBackground:(UIApplication *)application {
//    /*
//     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.
//     If your application supports background execution, called instead of applicationWillTerminate: when the user quits.
//     */
//    if (!_app) {
//        return;
//    }
//
//    [[SDKWrapper getInstance] applicationDidEnterBackground:application];
//}
//
//- (void)applicationWillEnterForeground:(UIApplication *)application {
//    /*
//     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.
//     */
//    if (!_app) {
//        return;
//    }
//
//    [[SDKWrapper getInstance] applicationWillEnterForeground:application];
//}
//
//- (void)applicationWillTerminate:(UIApplication *)application
//{
//    if (!_app) {
//        return;
//    }
//
//    [[SDKWrapper getInstance] applicationWillTerminate:application];
////    delete _app;
////    _app = nil;
//}
//
//#pragma mark -
//#pragma mark Memory management
//
//- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
//    /*
//     Free up as much memory as possible by purging cached data objects that can be recreated (or reloaded from disk) later.
//     */
//    NSLog(@"%s",__func__);
//}
//

@end



搭建游戏VC:

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface GameViewController : UIViewController
{
    
}
- (BOOL)prefersStatusBarHidden;
@end

NS_ASSUME_NONNULL_END
#import "GameViewController.h"
#import "CocosMng.h"
#import "AppDelegate.h"

#import "platform/ios/CCEAGLView-ios.h"
#import "SDKWrapper.h"
#include "cocos/scripting/js-bindings/jswrapper/SeApi.h"
#import "cocos2d.h"
//#import "AppDelegate.h"


@interface GameViewController ()

@end

@implementation GameViewController

//- (void) loadView {
//    UIView *cocosViw = [CocosMng getCocosView];
//    if (cocosViw != nil) {
//        self.view = [CocosMng getCocosView];
//    } else {
//        NSLog(@"初始化cocos view失败!");
//        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//            [self dismissViewControllerAnimated:YES completion:NULL];
//        });
//    }
//}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor redColor];
    NSLog(@"---%s", __func__);
    
    // Do any additional setup after loading the view.
    // 支持多个view
//    self.view.backgroundColor = [[UIColor alloc] initWithRed:160 / 255.0 green:140 / 255.0 blue:255 / 255.0 alpha:1];
//    self.view.layer.contents = (__bridge id _Nullable)([UIImage imageNamed:@"上课背景图"].CGImage);
//    //    ((GLKView *)self.view).delegate = self;
//    if ([[UIDevice currentDevice].model isEqualToString:@"iPhone"]) {
//        self.view.layer.contents = nil;
//        self.view.backgroundColor = [UIColor blackColor];
//    }
    
//    UIView *videoView = [[UIView alloc] initWithFrame:CGRectMake(50, 70, 150, 150)];
//    [self.view addSubview:videoView];
//    videoView.tag = kPTGameVideoPlayerViewTag;
    
    UIView *_cocosView = [CocosMng getCocosView];
    if (_cocosView == NULL) {
        NSLog(@"创建cocos view失败!");
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [self dismissViewControllerAnimated:true completion:NULL];
        });
        return;
    }
    _cocosView.frame = self.view.bounds;
    _cocosView.backgroundColor = UIColor.clearColor;
    [self.view addSubview:_cocosView];
    
    
//    UIView *courseVideoView = [[UIView alloc] initWithFrame:CGRectZero];
//    [self.view addSubview:courseVideoView];
//    courseVideoView.tag = kPTGameCourseVideoPlayerViewTag;
    
//
    
//    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//        [PTNativeFunc showNoRecordToast:@"为保证您的上课体验,建议您使用更高性能的设备上课!"];
//    });
    
//    [PTNativeFunc onNetBlock:^{
//        [PTCocos2D onNoNetShowDialog];
//    }];
    
    [[UIApplication sharedApplication] setStatusBarHidden:true];
    
    
//    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//        NSLog(@"游戏暂停-------->");
//        [[CocosMng getInstance] gamePauses];
//    });
//    
//    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(20 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//        NSLog(@"游戏继续-------->");
//        [[CocosMng getInstance] gameContinue];
//    });
//    
//    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(30 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//        NSLog(@"游戏结束-------->");
//        [[CocosMng getInstance] gameOver];
//    });
    
    
}

- (BOOL)prefersStatusBarHidden {
     return YES;
}

- (BOOL)prefersHomeIndicatorAutoHidden {
    return YES;
}

#pragma mark - 横屏设置
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self checkLandscapeRight];
}
- (void)checkLandscapeRight {
    [self switchNewOrientation:UIInterfaceOrientationLandscapeRight];
}

void switchNewOrientation(UIInterfaceOrientation interfaceOrientation)
{

    NSNumber *orientationTarget = [NSNumber numberWithInt:interfaceOrientation];

    [[UIDevice currentDevice] setValue:orientationTarget forKey:@"orientation"];
    
}

- (void)switchNewOrientation:(UIInterfaceOrientation)orientation
{
//    AppDelegate * appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
//    //允许转成横屏
//    appDelegate.allowRotation = orientation != UIInterfaceOrientationPortrait;
    //调用横屏代码
    switchNewOrientation(orientation);

}


- (void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];
    NSLog(@"---%s", __func__);
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    NSLog(@"---%s", __func__);
}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    NSLog(@"---%s", __func__);
}

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
    
    // Release any cached data, images, etc that aren't in use.
    NSLog(@"---%s", __func__);
}

- (void)becomeActive {
    NSLog(@"---%s", __func__);
}

- (void)willResginActive {
    NSLog(@"---%s", __func__);
}

- (void)willEnterForeground {
    NSLog(@"---%s", __func__);
}

- (void)didEnterBackground {
    NSLog(@"---%s", __func__);
}


/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end


进入游戏VC的界面VC

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController


@end

#import "ViewController.h"
#import "CocosMng.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"ViewController");
    self.view.backgroundColor = [UIColor whiteColor];
    // Do any additional setup after loading the view.
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self presentViewController:[CocosMng getInstance].viewController animated:YES completion:nil];
        NSLog(@"启动cocos引擎");
        [[CocosMng getInstance] startCocos];
    });
    
}
- (IBAction)startCocos:(id)sender {
    GameViewController * vc = [[GameViewController alloc] init];
    [CocosMng getInstance].viewController = vc;

    [self presentViewController:[CocosMng getInstance].viewController animated:YES completion:nil];
    NSLog(@"启动cocos引擎");
    [[CocosMng getInstance] startCocos];
    
    
    
}


@end


到此,整个配置流程完成


4 报错

很多报错没有总结进来忘记了,这里就几个

  • 出现setting.js 找不到—>直接clear后,卸载APP重新安装,缓存问题导致的;(有可能是)
  • 在导入Class后报错:Unknown type name 'NSString'
    1__#$!@%!#__Pasted Graphic.png

解决办法就是把Class下的两个cpp文件修改type(上面提到了)

  • Multiple commands produce LaunchScreen.storyboardc
    我的做法是删除Target--->Build Phases下的info文件,同时进行如下设置:
    image.png

如果不修改Projetc Setting(有⚠️),也可以删除掉自己工程中的Main 和 LaunchScreen(如果没有用到的话)


image.png
  • 在cocos 2.4.5的版本上,生成的iOS工程,集成时,出现 Undefined symbols for architecture x86_64 报错,如下:
    image.png

    我发现,采用上面的这些配置正确配置,还是有这个问题,不知道是新的版本需要添加什么配置,有找到的大佬请留言解惑; 我的解决办法是把cocos2.4.3生成的 cocos2d-x文件夹,替换掉新的 cocos2d-x文件夹,这样可以解决,但是不知道原因;

后期还有集成了游戏后的上架问题,也是需要处理的,这里还没上架,后期上架再补上了.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容