Cocos2D-ObjC:在RPG游戏中混合Swift代码
我之前写过一个RPG游戏<<熊猫之魂 SoulOfPanda>>
编译器使用的是SpriteBuilder,很好很强大!全部代码都由Objc完成,现在想尝试一下在其中混入Swift代码.
我的目的很简单,用Swift写一个GCMan9类,派生自Objc中的GameCharacter类,最后在Objc中使用GCMan9这个类.
GameCharacter类是游戏人物的基类,我从中派生了十几个子类分别表示游戏主角,各种NPC,各种敌人等等.
下面是GCMan1类的头文件:
#import "GameCharacter.h"
@interface GCMan1 : GameCharacter
@end
接着是实现文件:
#import "GCMan1.h"
#import "CCAnimation+Helper.h"
@implementation GCMan1
-(id)initWithGameScene:(GameScene *)gameScene{
self = [super initWithGameScene:gameScene andImageNamed:@"man1_forward_2.png"];
if (self) {
_facingForwardAnimation = [CCAnimation animation:@"man1" middle:@"forward" frameCount:3];
_facingBackAnimation = [CCAnimation animation:@"man1" middle:@"back" frameCount:3];
_facingLeftAnimation = [CCAnimation animation:@"man1" middle:@"left" frameCount:3];
_facingRightAnimation = [CCAnimation animation:@"man1" middle:@"right" frameCount:3];
self.speedPerStep = 0.4;
self.isNPC = YES;
self.gcName = @"GCMan1";
}
return self;
}
@end
可以看到GCMan1里只是根据实际角色初始化对应的纹理和动画,值得注意的是_facingForwardAnimation之类的变量是在其父类GameCharacter中定义的,如下:
@interface GameCharacter : CCSprite{
@protected
GameScene *_gameScene;
//移动的4个方向动画
CCAnimation *_facingForwardAnimation;
CCAnimation *_facingBackAnimation;
CCAnimation *_facingLeftAnimation;
CCAnimation *_facingRightAnimation;
}
这些变量增加了保护修饰,这里提一下,因为之后的Swift代码要在这里折腾一下.
按道理,如果在一个纯Objc项目中创建一个Swift文件,Xcode会提示你是否创建一个桥接文件,但是我这里并没有提示,所以我们得手动创建一个,格式是
项目名-Bridging-Header.h
里面导入需要在Swift文件中需要使用的类的头文件,在这里其内容是这样的:
#ifndef SoulOfPanda_Bridging_Header_h
#define SoulOfPanda_Bridging_Header_h
#import "GameCharacter.h"
#import "GameScene.h"
#endif /* SoulOfPanda_Bridging_Header_h */
然后新建一个GCMan9.swift文件,内容与Objc中的类似:
class GCMan9:GameCharacter{
override init(gameScene: GameScene!, andImageNamed imageName: String!) {
super.init(gameScene: gameScene, andImageNamed: imageName)
}
override init(gameScene:GameScene?){
super.init(gameScene: gameScene, andImageNamed: "man1_forward_2.png", andTintColor: UIColor.orangeColor())
//怎么设置父类中的保护变量???
speedPerStep = 0.4
isNPC = true
gcName = "GCMan9"
}
}
现在问题来了,父类中的几个@protected定义的变量在Swift中不可见!查阅了一些资料没找到解决办法,只有采用迂回方法,回到GameCharacter.m中新建一个帮助方法:
//设置GameCharacter类中的保护变量,在Swift中调用
-(void)setFacingAnimation:(NSString *)name frameCount:(int)count{
_facingForwardAnimation = [CCAnimation animation:name middle:@"forward" frameCount:count];
_facingBackAnimation = [CCAnimation animation:name middle:@"back" frameCount:count];
_facingLeftAnimation = [CCAnimation animation:name middle:@"left" frameCount:count];
_facingRightAnimation = [CCAnimation animation:name middle:@"right" frameCount:count];
}
同时别忘了在GameCharacter.h接口中导出该方法,回到GCMan9.swift文件中,将注释那一行替换为如下代码:
setFacingAnimation("man1", frameCount: 3)
因为你要在Objc中使用Swift中的类,所以你需要在对应的m文件中包含如下h文件:
#import "SoulOfPanda-Swift.h"
文件名格式很简单就是”项目名-Swift.h”
在实际测试之前,我们还要找到游戏某个场景的plist文件,将其中的NPC类名换为GCMan9:
运行一下游戏,咦怎么崩溃挂掉了…检查一下栈回溯,发现在以下方法中有问题:
//返回一个"假的"的GC对象,只能用于显示和获取数据,不能实际在场景中存在
+(instancetype)gcFakeWithName:(NSString *)name{
Class class = NSClassFromString(name);
GameCharacter *gc = [[class alloc] initWithGameScene:nil];
return gc;
}
仔细一看,发现NSClassFromString方法返回的是nil,虽然name是正确的@”GCMan9”.
测试了一下发现使用如下代码是没有问题的:
GCMan9 *man9 = [[GCMan9 alloc]initWithGameScene:gameScene];
难道是Swift中的类名在Objc中看到的有所不同么?查看Apple开发文档发现,果然如此!在Swift定义的类在Objc代码中实际看到的名字需要加上前缀,即GCMan9在Objc中看到的名字是SoulOfPanda.GCMan9,所以要把代码修改如下:
Class class = NSClassFromString(@"SoulOfPanda.GCMan9");
但问题还是没有解决,我不想一个一个的添加判断语句,这样非常的繁琐.相反我要利用Swift中提供了一个很好的特性,就是@objc伪指令,该指令告诉Swift不要在类名前添加前缀.回到GCMan9.swift在开头添加如下一句:
@objc(GCMan9)
class GCMan9:GameCharacter{
现在运行代码,终于OK啦:
Cocos2D-ObjC:在RPG游戏中混合Swift代码的更多相关文章
- SpriteBuilder中使用GUI界面快速搭建RPG游戏中的地图名显示动画
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 在RPG游戏中我们在进入一个新的场景时,比如一个房间,一个村庄, ...
- 在 OC 中调用 Swift 代码
1.在 Objective-C 项目中使用 Swift 代码 1)在 OC 项目中创建 .Swift 文件,文件中的格式为其本有的格式. 2)Xcode 提示是否创建 Objective-C brid ...
- RPG游戏中如何判断敌人是否在玩家的攻击范围之内
// 方式1:通过主角和场景中的所有敌人比较 private void AtkCondition1(float _range,float _angle) { // 搜索所有敌人列表(在动态创建敌人时生 ...
- 概念:RPG游戏中两个兵种互相攻击的逻辑
直接上题目: 解析题目: 根据题目的解析,进行代码的实现: 输出结果: 心得: (1) 当我们面对‘公式结果不是我们想要的’时,应该在脑海里将一个完整的攻击流程进行想象,就会对流程有个更清晰的思路 ( ...
- 项目中 添加 swift代码 真机调试 错误
错误: dyld: Library not loaded: @rpath/libswiftCore.dylib Referenced from: /private/var/mobile/Contain ...
- 在Objc项目中调用Swift
之前的文字中记录了在Swift项目中调用OC的相关代码,比较简单直接 传送门 但是在OC中调用swift代码则不是那么的和谐,网络上很多文章业已经有点陈旧.记录步骤如下: 1.创建OC项目 (1)启动 ...
- Swift & Objc 在同一个项目中的使用
在WWDC大会中发布了Swift让人眼前一亮.终于加了很多的现代编程语言该有的东西.很早年以前玩C#3.0+的时候这些差不多类似的 已经用的烂熟的东西终于一点一点的在看Swift Programmin ...
- 在同个工程中使用 Swift 和 Objective-C(Swift 2.0更新)-b
本节包含内容: Mix and Match 概述(Mix and Match Overview) 在同个应用的 target 中导入(Importing Code from Within the Sa ...
- Using Swift with Cocoa and Objective-C--在同个project中使用Swift和在同个project中
http://www.cocoachina.com/newbie/basic/2014/0605/8688.html watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5u ...
随机推荐
- 一 Django模型层简介(一)
模型 django提供了一个强大的orm(关系映射模型)系统. 模型包含了你要在数据库中创建的字段信息及对数据表的一些操作 使用模型 定义好模型后,要告诉django使用这些模型,你要做的就是在配置文 ...
- C#之不安全代码
MSDN:"尽管实际上对 C 或 C++ 中的每种指针类型构造,C# 都设置了与之对应的引用类型,但仍然会有一些场合需要访问指针类型.例如,当需要与基础操作系统进行交互.访问内存映射设备,或 ...
- C#之winform实现文件拖拽功能
将一个文件拖拽到窗体的某个控件时,将该控件的路径显示在该控件上,只要拿到了路径自然可以读取文件中的内容了 将一个控件的属性AllowDrop设置为true,然后添加DragDrop.DragEnter ...
- 微信的自动回复&接入聊天机器人
今天偶尔发现了一个有趣的python库--itchat,可以实现微信的自动回复.防撤回,结合图灵机器人还能实现聊天机器人的作用 简单介绍一下配置与工具 win7旗舰版 pycharm python ...
- 关于wooyun-2015-096990的总结
漏洞url:http://wooyun.jozxing.cc/static/bugs/wooyun-2015-096990.html 摘要 if(!ini_get('register_globals' ...
- [BZOJ 5055]膜法师
Description 在经历过1e9次大型战争后的宇宙中现在还剩下n个完美维度, 现在来自多元宇宙的膜法师,想偷取其中的三个维度为伟大的长者续秒, 显然,他能为长者所续的时间,为这三个维度上能量的乘 ...
- [JSOI2008]球形空间产生器
Description 有一个球形空间产生器能够在n维空间中产生一个坚硬的球体.现在,你被困在了这个n维球体中,你只知道球 面上n+1个点的坐标,你需要以最快的速度确定这个n维球体的球心坐标,以便于摧 ...
- [HNOI2015]接水果
题目描述 风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果.由于她已经DT FC 了The big black, 她觉得这个游戏太简单了,于是发明了一个更加难的版本. 首先有 ...
- P3928 SAC E#1 - 一道简单题 Sequence2
题目背景 小强和阿米巴是好朋友. 题目描述 小强喜欢数列.有一天,他心血来潮,写下了三个长度均为n的数列. 阿米巴也很喜欢数列.但是他只喜欢其中一种,波动数列. 阿米巴把他的喜好告诉了小强.小强便打算 ...
- [HNOI2009]有趣的数列
题目描述 我们称一个长度为2n的数列是有趣的,当且仅当该数列满足以下三个条件: (1)它是从1到2n共2n个整数的一个排列{ai}: (2)所有的奇数项满足a1<a3<...<a2n ...