Cocos Creator集成到原生swift

一、集成流程

1. 下载Creator2.4.10版本

官网地址: https://www.cocos.com/creator-download

2. 新建cocos-HelloWorld项目

image.png

3. 顶部工具栏->项目->构建发布

按如下配置,构建、编译、运行iOS工程


image.png

构建时勾选default,不是link
jsb-default文件夹下的内容就是我们iOS开发需要的代码了

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

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


image.png

得到一个能够正常运行的工程非常重要!
后续集成Cocos Creator就是将此demo工程的相关代码、配置挪到自己的iOS工程。

5. 整理引擎代码

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


image.png

注:

  • 红框内容是Cocos游戏代码,迁移至/Resource文件夹,若替换游戏直接替换/Resource内所有内容
  • frameworks中,可以只导入frameworks-->runtime-src-->proj.ios_mac + Classes , proj.android-studio和proj.win32 可以不导入

6. 导入游戏引擎到自己的工程

image.png
  • Create groups方式** **添加 Classes、ios
  • Create groups whith folder方式 添加 Resources内部文件,注意 /Resource 一定不能是folder方式(灰色)
  • Create groups方式** **添加cocos2d_libs.xcodeproj,注意不需要将cocos2d-x文件夹拖入工程

7. 工程中移除ios文件夹下的main.m、Info.plist

否则与主工程文件冲突

8. 导入项目的依赖库

具体以第2步构建导出的Demo工程为准


image.png

9. 导入libcocos2d iOS(cocos2d_libs)

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


image.png

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

10. 配置工程头文件搜索路径

若编译时报错头文件找不到,则在此处添加路径


image.png
  • Library Search Paths 添加 $(SRCROOT)/cocos/frameworks/cocos2d-x/external/iOS/libs
  • User Header Search Paths 添加如下:(具体需参考第2步构建导出的Demo工程)
$(PROJECT_DIR)/cocos/frameworks/cocos2d-x
$(PROJECT_DIR)/cocos/frameworks/cocos2d-x/cocos
$(PROJECT_DIR)/cocos/frameworks/cocos2d-x/cocos/base
$(PROJECT_DIR)/cocos/frameworks/cocos2d-x/cocos/2d
$(PROJECT_DIR)/cocos/frameworks/cocos2d-x/cocos/ui
$(PROJECT_DIR)/cocos/frameworks/cocos2d-x/cocos/network
$(PROJECT_DIR)/cocos/frameworks/cocos2d-x/cocos/audio/include
$(PROJECT_DIR)/cocos/frameworks/cocos2d-x/cocos/editor-support
$(PROJECT_DIR)/cocos/frameworks/cocos2d-x/extensions
$(PROJECT_DIR)/cocos/frameworks/cocos2d-x/external
$(PROJECT_DIR)/cocos/frameworks/cocos2d-x/external/sources
$(PROJECT_DIR)/cocos/frameworks/cocos2d-x/external/chipmunk/include/chipmunk
$(PROJECT_DIR)/cocos/frameworks/cocos2d-x/cocos/scripting/js-bindings/auto
$(PROJECT_DIR)/cocos/frameworks/cocos2d-x/cocos/scripting/js-bindings/manual
$(PROJECT_DIR)/cocos/frameworks/cocos2d-x/external/mac/include/v8

11. 其他配置

  • 为TARGETS为other linker flags 添加 -Objc
  • 把PROJECT和TARGETS的Enable BitCode都设为NO
  • 在PROJECT和TARGETS为Preprocessor Macros添加预定义宏,具体需参考第2步构建导出的Demo工程
image.png

12. 工程代码的修改

  • 修改Classes文件夹下的AppDelegate.h 和 AppDelegate.cpp
    把名称改成CocosAppDelegate.h 和 CocosAppDelegate.cpp,把代码内的AppDelegate全部替换成CocosAppDelegate
  • 修改 目录: cocos2d_libs -> platform -> iOS下的 CCApplication-ios.mm 文件的end方法
void Application::end()
{
    //    delete this;
       //
       //    exit(0);
       
       // 上面是原来的样子
   #if USE_AUDIO
       AudioEngine::end();
   #endif
       // stop main loop
       [(MainLoop*)_delegate stopMainLoop];
 
}

修改它的目的是为了cocos引擎在启动后,退出游戏不自动关闭引擎,不杀死APP,再次进入游戏,可以直接开始游戏,切换另一个游戏。

13. 创建游戏引擎管理类

image.png
  • CocosManager:控制游戏开始结束等
//
//  CocosManager.h
//
//  cocos引擎管理器,负责iOS启动、退出以及管理cocos引擎
/*
 
 类名不要改变,对应cocos的JS调用OC的类名;
 所有的供JS调用的方法,使用类方法;
 所有的OC调用的JS方法,统一写在CocosManager下;
 
 */

#ifndef CocosManager_h
#define CocosManager_h

#import <UIKit/UIKit.h>
#import <CCEAGLView-ios.h>

@protocol CocosManagerDelegate <NSObject>

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


@end


@interface CocosManager : NSObject
{
}

@property(nonatomic, retain) UIViewController* viewController;

@property (nonatomic, weak) id <CocosManagerDelegate> 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 /* CocosManager_h */

#import "CocosManager.h"
#import "CocosAppDelegate.h"
#import "SDKWrapper.h"
#import <cocos/cocos2d.h>
#import <CCEAGLView-ios.h>
#import <cocos/scripting/js-bindings/jswrapper/SeApi.h>
#import <CCApplication.h>

using namespace cocos2d;

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

@interface CocosManager ()

@property (nonatomic, strong) NSDictionary *gameData;

@end

@implementation CocosManager


+(instancetype)getInstance {
//    static dispatch_once_t onceToken;
//    dispatch_once(&onceToken, ^{
//        _instance = [[self alloc] init];
//    });
    
    if (!_instance) {
        _instance = [[CocosManager 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 {
    [[CocosManager 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];
    [CocosManager 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
  • GameViewController: 游戏页面,作用是添加游戏画布
#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

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

NS_ASSUME_NONNULL_END

#import "GameViewController.h"
#import "CocosManager.h"
#import "CocosAppDelegate.h"
#import "SDKWrapper.h"
#import <CCEAGLView-ios.h>
#import <cocos/scripting/js-bindings/jswrapper/SeApi.h>
#import <cocos/cocos2d.h>

@interface GameViewController ()

@end

@implementation GameViewController

//- (void) loadView {
//    UIView *cocosViw = [CocosManager getCocosView];
//    if (cocosViw != nil) {
//        self.view = [CocosManager 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 = [CocosManager 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(@"游戏暂停-------->");
//        [[CocosManager getInstance] gamePauses];
//    });
//
//    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(20 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//        NSLog(@"游戏继续-------->");
//        [[CocosManager getInstance] gameContinue];
//    });
//
//    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(30 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//        NSLog(@"游戏结束-------->");
//        [[CocosManager 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

注:

  • 特别注意两个文件是OC、C++混编,.mm后缀
  • 在Compile Sources必须保证有这三个文件
image.png

14. 创建桥接文件

  • 新建 Swift-Bridge-Objective-C.h
//
//  Swift-Bridge-Objective-C.h
//  FlatGame
//
//

#ifndef Swift_Bridge_Objective_C_h
#define Swift_Bridge_Objective_C_h

#import "CocosManager.h"
#import "GameViewController.h"

#endif /* Swift_Bridge_Objective_C_h */

  • XCode配置桥接文件路径
image.png

二、问题汇总

1. python版本问题,必须使用python2.x版本

2. 子工程编译问题

image.png

严格参照第2步构建导出的Demo工程,打开里面的 cocos2d_libs.xcodeproj,保证内部文件个数、路径都一致(部分不需要的则删除,具体看Demo工程里是否引入了),保证子工程编译通过,再拖进自己工程。

  • 注意只需要拖入 cocos2d_libs.xcodeproj,不需要将 cocos2d-x文件夹拖入工程

3. Undefined symbol:头文件找不到错误总结

image.png
  • 红色:系统库头文件找不到,回到 【8. 导入项目的依赖库】检查缺失
  • 蓝色:cocos引擎头文件找不到,回到【10. 配置工程头文件搜索路径】检查添加路径

4. Undefined symbol: OBJC_CLASS$_CocosManager (类找不到)

回到【13. 创建游戏引擎管理类】检查 Compile Sources是否添加 CocosManager.mm
还不行回到【14. 创建桥接文件】检查桥接文件

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

推荐阅读更多精彩内容