I've previously written a RPG game << panda Soul Soulofpanda>>
The compiler is using Spritebuilder, very good and powerful! All the code is done by OBJC, and now you want to try to mix the swift code in it.
My purpose is simple, write a GCMan9 class with Swift, derive from the Gamecharacter class in OBJC, and finally use the GCMan9 class in OBJC.
The Gamecharacter class is the base class of the game characters, and I derive more than 10 sub-classes which represent the main characters of the game, various NPCs, various enemies and so on.
The following is the header file for the GCMan1 class:
#import "GameCharacter.h"@interface GCMan1 : GameCharacter@end
Then the implementation file:
#import "GCMan1.h" #import "Ccanimation+helper.h" @implementation GCMan1 -(ID) Initwithgamescene: (Gamescene *) gamescene{ Self= [SuperInitwithgamescene: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
You can see that the GCMan1 only initializes the corresponding textures and animations based on the actual role, and it's worth noting that variables such as _facingforwardanimation are defined in their parent class Gamecharacter, as follows:
@interface GameCharacter : CCSprite{@protected *_gameScene; //移动的4个方向动画 *_facingForwardAnimation; *_facingBackAnimation; *_facingLeftAnimation; *_facingRightAnimation;}
These variables add protection modifiers, which are mentioned here, because the swift code after that is a bit of a toss here.
As a matter of principle, if you create a swift file in a pure OBJC project, Xcode will prompt you to create a bridging file, but I do not have a hint here, so we have to create one manually, the format is
项目名-Bridging-Header.h
It imports the header file of the class that needs to be used in the swift file, where its contents are:
#ifndef SoulOfPanda_Bridging_Header_h#define SoulOfPanda_Bridging_Header_h#import "GameCharacter.h"#import "GameScene.h"#endif /* SoulOfPanda_Bridging_Header_h */
Then create a new Gcman9.swift file with the content similar to that in 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: "man 1_forward_2.png ", AndTintColor:UIColor.orangeColor ()) //how to set the protection variable in the parent class??? Speedperstep = 0.4 ISNPC = true GC Name = "GCMan9" }}
Now the problem is, a couple of @protected defined variables in the parent class are not visible in swift! Check some of the data did not find a solution, only the use of circuitous method, back to gamecharacter.m a new Help method:
//set the protection variables in the Gamecharacter class, Call -(void ) in Swift 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:< Span class= "Hljs-keyword" >count ];}
Also, don't forget to export the method in the GameCharacter.h interface, go back to the Gcman9.swift file, and replace the comment line with the following code:
setFacingAnimation("man1"3)
Because you want to use the classes in Swift in OBJC, you need to include the following H file in the corresponding m file:
#import "SoulOfPanda-Swift.h"
File name format is very simple is "project name-swift.h"
Before actually testing, we also need to find the plist file of a scene of the game, and change the NPC class name to GCMan9:
Run the game, how to collapse hung up ... Check the stack backtracking and find that there are problems in the following methods:
//返回一个"假的"的GC对象,只能用于显示和获取数据,不能实际在场景中存在+(instancetype)gcFakeWithName:(NSString *)name{ class = NSClassFromString(name); GameCharacter *gc = [[class alloc] initWithGameScene:nil]; return gc;}
Looking closely, we found that the Nsclassfromstring method returned nil, although name is the correct @ "GCMan9".
Test the discovery using the following code is not a problem:
GCMan9 *man9 = [[GCMan9 alloc]initWithGameScene:gameScene];
is the class name in Swift seen differently in OBJC? View the Apple Development documentation discovery, that's how it is! The names that are actually seen in the OBJC code in the classes defined by Swift need to be prefixed, The name that GCMan9 sees in OBJC is soulofpanda.gcman9, so modify the code as follows:
class = NSClassFromString(@"SoulOfPanda.GCMan9");
But the problem is still not resolved, I do not want to add a judgment statement, this is very cumbersome. Instead I'm going to use Swift to provide a good feature, which is @objc pseudo-instructions, This directive tells Swift not to prefix the class name. Return to Gcman9.swift at the beginning add the following sentence:
@objc(GCMan9)class GCMan9:GameCharacter{
Now run the code, finally OK:
COCOS2D-OBJC: Mixing Swift code in RPG games