- Creating the Radar Dish and Viking Classes
- Creating the Viking Class
- Final Steps
- Summary
- Challenges
Creating the Viking Class
In the previous chapter, Ole the Viking was nothing more than a CCSprite. In this chapter you pull him out into his own class complete with animations and a state machine to transition him through his various states. If the Viking class code starts to look daunting, refer back to the RadarDish class: the Viking is simply a game character like the RadarDish, albeit with more functionality. Create the new Viking class in Xcode by:
- In Xcode, right-click on the GameObjects group.
- Select Add > New File, choose the Cocoa Touch category under iOS and Objective-C class as the file type, and click Next.
- For the Subclass field, enter GameCharacter and click Next.
- Enter Viking for the filename and click Save.
Open the Viking.h header file and change the contents to match the code in Listing 4.5.
Listing 4.5. Viking.h header file
// Viking.h // SpaceViking#import <Foundation/Foundation.h>
#import "GameCharacter.h"
#import "SneakyButton.h"
#import "SneakyJoystick.h"
typedef enum
{ kLeftHook, kRightHook } LastPunchType;@interface
Viking :GameCharacter
{LastPunchType
myLastPunch;BOOL
isCarryingMallet;CCSpriteFrame
*standingFrame; // Standing, breathing, and walkingCCAnimation
*breathingAnim;CCAnimation
*breathingMalletAnim;CCAnimation
*walkingAnim;CCAnimation
*walkingMalletAnim; // Crouching, standing up, and JumpingCCAnimation
*crouchingAnim;CCAnimation
*crouchingMalletAnim;CCAnimation
*standingUpAnim;CCAnimation
*standingUpMalletAnim;CCAnimation
*jumpingAnim;CCAnimation
*jumpingMalletAnim;CCAnimation
*afterJumpingAnim;CCAnimation
*afterJumpingMalletAnim; // PunchingCCAnimation
*rightPunchAnim;CCAnimation
*leftPunchAnim;CCAnimation
*malletPunchAnim; // Taking Damage and DeathCCAnimation
*phaserShockAnim;CCAnimation
*deathAnim;SneakyJoystick
*joystick;SneakyButton
*jumpButton ;SneakyButton
*attackButton;float
millisecondsStayingIdle; } // Standing, Breathing, Walking@property
(nonatomic
,retain
)CCAnimation
*breathingAnim;@property
(nonatomic
,retain
)CCAnimation
*breathingMalletAnim;@property
(nonatomic
,retain
)CCAnimation
*walkingAnim;@property
(nonatomic
,retain
)CCAnimation
*walkingMalletAnim; // Crouching, Standing Up, Jumping@property
(nonatomic
,retain
)CCAnimation
*crouchingAnim;@property
(nonatomic
,retain
)CCAnimation
*crouchingMalletAnim;@property
(nonatomic
,retain
)CCAnimation
*standingUpAnim;@property
(nonatomic
,retain
)CCAnimation
*standingUpMalletAnim;@property
(nonatomic
,retain
)CCAnimation
*jumpingAnim;@property
(nonatomic
,retain
)CCAnimation
*jumpingMalletAnim;@property
(nonatomic
,retain
)CCAnimation
*afterJumpingAnim;@property
(nonatomic
,retain
)CCAnimation
*afterJumpingMalletAnim; // Punching@property
(nonatomic
,retain
)CCAnimation
*rightPunchAnim;@property
(nonatomic
,retain
)CCAnimation
*leftPunchAnim;@property
(nonatomic
,retain
)CCAnimation
*malletPunchAnim; // Taking Damage and Death@property
(nonatomic
,retain
)CCAnimation
*phaserShockAnim;@property
(nonatomic
,retain
)CCAnimation
*deathAnim;@property
(nonatomic
,assign
)SneakyJoystick
*joystick;@property
(nonatomic
,assign
)SneakyButton
*jumpButton;@property
(nonatomic
,assign
)SneakyButton
*attackButton;@end
Listing 4.5 shows the large number of animations that are possible with the Viking character as well as instance variables to point to the onscreen joystick and button controls.
The key items to note are the typedef enumerator for the left and right punches, an instance variable to store what the last punch thrown was, and a float to keep track of how long the player has been idle. The code for the Viking implementation file is a bit on the lengthy side, hence it is broken up into four Listings, 4.6 through 4.9. Open the Viking.m implementation file and replace the code so that it matches the contents in Listings 4.6, 4.7, 4.8, and 4.9.
Listing 4.6. Viking.m implementation file (part 1 of 4)
// Viking.m // SpaceViking#import "Viking.h"
@implementation
Viking@synthesize
joystick;@synthesize
jumpButton ;@synthesize
attackButton; // Standing, Breathing, Walking@synthesize
breathingAnim;@synthesize
breathingMalletAnim;@synthesize
walkingAnim;@synthesize
walkingMalletAnim; // Crouching, Standing Up, Jumping@synthesize
crouchingAnim;@synthesize
crouchingMalletAnim;@synthesize
standingUpAnim;@synthesize
standingUpMalletAnim;@synthesize
jumpingAnim;@synthesize
jumpingMalletAnim;@synthesize
afterJumpingAnim;@synthesize
afterJumpingMalletAnim; // Punching@synthesize
rightPunchAnim;@synthesize
leftPunchAnim;@synthesize
malletPunchAnim; // Taking Damage and Death@synthesize
phaserShockAnim;@synthesize
deathAnim; - (void
)dealloc
{joystick
=nil
;jumpButton
=nil
;attackButton
=nil
; [breathingAnim
release]; [breathingMalletAnim
release]; [walkingAnim release
]; [walkingMalletAnim release
]; [crouchingAnim release
]; [crouchingMalletAnim release
]; [standingUpAnim
release]; [standingUpMalletAnim
release]; [jumpingAnim release
]; [jumpingMalletAnim release
]; [afterJumpingAnim
release]; [afterJumpingMalletAnim
release]; [rightPunchAnim release
]; [leftPunchAnim release
]; [malletPunchAnim
release]; [phaserShockAnim release]; [deathAnim
release]; [super
dealloc]; } -(BOOL
)isCarryingWeapon
{return
isCarryingMallet; } -(int
)getWeaponDamage {if
(isCarryingMallet
) {return kVikingMalletDamage
; }return kVikingFistDamage
; } -(void
)applyJoystick:(SneakyJoystick
*)aJoystick
forTimeDelta:(float
) deltaTime { CGPointscaledVelocity
= ccpMult(aJoystick.velocity,128.0f
); CGPoint oldPosition = [self
position]; CGPointnewPosition
= ccp(oldPosition
.x + scaledVelocity.x * deltaTime, oldPosition.y
);// 1
[self setPosition
:newPosition];// 2
if
(oldPosition
.x > newPosition.x) {self
.flipX =YES
;// 3
}else
{self
.flipX =NO
; } } -(void
)checkAndClampSpritePosition {if
(self
.characterState
!=kStateJumping
) {if
([self position
].y
>110.0f
) [self setPosition
:ccp
([self position
].x
,110.0f
)]; } [super checkAndClampSpritePosition
]; }
At the beginning of the Viking.m implementation file is the dealloc method. Far wiser Objective-C developers than this author have commented on the benefits of having your dealloc method up top and near your synthesize statements. The idea behind this move is to make sure you are deallocating any and all instance variables, therefore avoiding one of the main causes of memory leaks in Objective-C code.
Following the dealloc method, you have the isCarryingWeapon method, but since it is self-explanatory, move on to the applyJoystick method. This method is similar to the one back in Chapter 2, "Hello, Space Viking," Listing 2.10, but it has been modified to deal only with Ole's movement and removes the handling for the jump or attack buttons. The first change to applyJoystick is the creation of the oldPosition variable to track the Viking's position before it is moved. Looking at the applyJoystick method in Listing 4.6, take a note of the following key lines:
- Sets the new position based on the velocity of the joystick, but only in the x-axis. The y position stays constant, making it so Ole only walks to the left or right, and not up or down.
- Moves the Viking to the new position.
- Compares the old position with the new position, flipping the Viking horizontally if needed. If you look closely at the Viking images, he is facing to the right by default. If this method determines that the old position is to the right of the new position, Ole is moving to the left, and his pixels have to be flipped horizontally. If you don't flip Ole horizontally, he will look like he is trying to do the moonwalk when you move him to the left. It is a cool effect but not useful for your Viking.
Cocos2D has two built-in functions you will make use of frequently: flipX and flipY. These functions flip the pixels of a texture along the x- or y-axis, allowing you to display a mirror image of your graphics without having to have left- and right-facing copies of each image for each character. Figure 4.1 shows the effect of flipX on the Viking texture. This is a really handy feature to have, since it helps reduce the size of your application, and it keeps you from having to create images for every possible state.
Figure 4.1 Effects of the flipX function on the Viking texture or graphic
The next section of the Viking.m implementation file covers the changeState method. As you learned with the RadarDish class, the changeState method is used to transition the character from one state to another and to start the appropriate animations for each state. Copy the contents of Listing 4.7 into your Viking.m class.
Listing 4.7. Viking.m implementation file (part 2 of 4)
#pragma mark - -(void
)changeState:(CharacterStates
)newState { [self stopAllActions
];id
action =nil
;id
movementAction =nil
;CGPoint
newPosition; [self setCharacterState
:newState];switch
(newState) {case kStateIdle
:if
(isCarryingMallet
) { [self setDisplayFrame
:[[CCSpriteFrameCache
sharedSpriteFrameCache
]spriteFrameByName
:@"sv_mallet_1.png"
]]; }else
{ [self setDisplayFrame
:[[CCSpriteFrameCache
sharedSpriteFrameCache
]spriteFrameByName
:@"sv_anim_1.png"
]]; }break
;case kStateWalking
:if
(isCarryingMallet
) { action = [CCAnimate actionWithAnimation
:walkingMalletAnim
restoreOriginalFrame
:NO
]; }else
{ action = [CCAnimate actionWithAnimation
:walkingAnim
restoreOriginalFrame
:NO
]; }break
;case kStateCrouching
:if
(isCarryingMallet
) { action = [CCAnimate actionWithAnimation
:crouchingMalletAnim
restoreOriginalFrame
:NO
]; }else
{ action = [CCAnimate actionWithAnimation
:crouchingAnim
restoreOriginalFrame
:NO
]; }break
;case kStateStandingUp
:if
(isCarryingMallet
) { action = [CCAnimate actionWithAnimation
:standingUpMalletAnim
restoreOriginalFrame
:NO
]; }else
{ action = [CCAnimate actionWithAnimation
:standingUpAnim
restoreOriginalFrame
:NO
]; }break
;case kStateBreathing
:if
(isCarryingMallet
) { action = [CCAnimate actionWithAnimation
:breathingMalletAnim
restoreOriginalFrame
:YES
]; }else
{ action = [CCAnimate actionWithAnimation
:breathingAnim
restoreOriginalFrame
:YES
]; }break
;case
kStateJumping:newPosition
= ccp(screenSize
.width *0.2f
,0.0f
);if
([self
flipX] ==YES
) { newPosition = ccp(newPosition.x * -1.0f
,0.0f
); } movementAction = [CCJumpByactionWithDuration
:0.5f
position
:newPosition height:160.0f
jumps:1
];if
(isCarryingMallet
) {// Viking Jumping animation with the Mallet
action = [CCSequence actions
: [CCAnimate
actionWithAnimation
:crouchingMalletAnim
restoreOriginalFrame
:NO
], [CCSpawn actions
: [CCAnimate
actionWithAnimation
:jumpingMalletAnim
restoreOriginalFrame
:YES
], movementAction,nil
], [CCAnimate
actionWithAnimation
:afterJumpingMalletAnim
restoreOriginalFrame
:NO
],nil
]; }else
{// Viking Jumping animation without the Mallet
action = [CCSequence actions
: [CCAnimate
actionWithAnimation
:crouchingAnim
restoreOriginalFrame
:NO
], [CCSpawn actions
: [CCAnimate
actionWithAnimation
:jumpingAnim
restoreOriginalFrame
:YES
], movementAction,nil
], [CCAnimate
actionWithAnimation
:afterJumpingAnim
restoreOriginalFrame
:NO
],nil
]; }break
;case kStateAttacking
:if
(isCarryingMallet
==YES
) { action = [CCAnimate
actionWithAnimation
:malletPunchAnim
restoreOriginalFrame
:YES
]; }else
{if
(kLeftHook
==myLastPunch
) {// Execute a right hook
myLastPunch
=kRightHook
; action = [CCAnimate
actionWithAnimation
:rightPunchAnim
restoreOriginalFrame
:NO
]; }else
{// Execute a left hook
myLastPunch
=kLeftHook
; action = [CCAnimate
actionWithAnimation
:leftPunchAnim
restoreOriginalFrame
:NO
]; } }break
;case kStateTakingDamage
:self
.characterHealth
=self
.characterHealth -10.0f
; action = [CCAnimate
actionWithAnimation
:phaserShockAnim
restoreOriginalFrame
:YES
];break
;case kStateDead
: action = [CCAnimate
actionWithAnimation
:deathAnim
restoreOriginalFrame
:NO
];break
;default
:break
; }if
(action !=nil
) { [self runAction
:action]; } }
The first part of the changeState method stops any running actions, including animations. Any running actions would be a part of a previous state of the Viking and would no longer be valid. Following the first line, the Viking state is set to the new state value, and a switch statement is used to carry out the animations for the new state. A few items are important to note:
- Method variables cannot be declared inside a switch statement, as they would be out of scope as soon as the code exited the switch statement. Your id action variable is declared above the switch statement but initialized inside the switch branches.
- Most of the states have two animations: one for the Viking with the Mallet and one without. The isCarryingMallet Boolean instance variable is key in determining which animation to play.
- An action in Cocos2D can be made up of other actions in that it can be a compound action. The switch branch taken when the Viking state is kStateJumping has a compound action made up of CCSequence, CCAnimate, CCSpawn, and CCJumpBy actions. The CCJumpBy action provides the parabolic movement for Ole the Viking, while the CCAnimate actions play the crouching, jumping, and landing animations. The CCSpawn action allows for more than one action to be started at the same time, in this case the CCJumpBy and CCAnimate animation action of Ole jumping. The CCSequence action ties it all together by making Ole crouch down, then jump, and finally land on his feet in sequence.
- Taking a closer look at the kStateTakingDamage switch branch, you can see that after the animation completes, Ole reverts back to the frame that was displaying before the animation started. In this state transition, the CCAnimate action has the restoreOriginalFrame set to YES. The end effect of restoreOriginalFrame is that Ole will animate receiving a hit, and then return to looking as he did before the hit took place.
The first line of Listing 4.7 might be rather odd-looking: #pragma mark. The pragma mark serves as a formatting guide to Xcode and is not seen by the compiler. After the words #pragma mark you can place any text you would like displayed in the Xcode pulldown for this file. If you have just a hyphen (-), Xcode will create a separate section for that portion of the file. Using pragma mark can make your code easier to navigate. Figure 4.2 shows the effects of the pragma mark statements in the completed Viking.m file.
Figure 4.2 The effect of the pragma mark statements in the Xcode pulldown menus
The next section of the Viking.m file covers the updateStateWithDeltaTime and the adjustedBoundingBox methods. Copy the contents of Listing 4.8 into your Viking.m file immediately following the changeState method.
Listing 4.8. Viking.m implementation file (part 3 of 4)
#pragma mark - -(void
)updateStateWithDeltaTime:(ccTime
)deltaTime andListOfGameObjects:(CCArray
*)listOfGameObjects {if
(self.characterState
==kStateDead
)return
;// Nothing to do if the Viking is dead
if
((self.characterState
==kStateTakingDamage
) && ([self numberOfRunningActions
] >0
))return
;// Currently playing the taking damage animation
// Check for collisions
// Change this to keep the object count from querying it each time
CGRect
myBoundingBox = [self adjustedBoundingBox
];for
(GameCharacter
*characterin
listOfGameObjects) {// This is Ole the Viking himself
// No need to check collision with one's self
if
([charactertag
] ==kVikingSpriteTagValue
)continue
;CGRect
characterBox = [characteradjustedBoundingBox
];if
(CGRectIntersectsRect
(myBoundingBox, characterBox)) {// Remove the PhaserBullet from the scene
if
([charactergameObjectType
] ==kEnemyTypePhaser
) { [self changeState
:kStateTakingDamage
]; [characterchangeState
:kStateDead
]; }else if
([charactergameObjectType
] ==kPowerUpTypeMallet
) {// Update the frame to indicate Viking is
// carrying the mallet
isCarryingMallet
=YES
; [self changeState
:kStateIdle
];// Remove the Mallet from the scene
[characterchangeState
:kStateDead
]; }else if
([charactergameObjectType
] ==kPowerUpTypeHealth
) { [self setCharacterHealth
:100.0f
];// Remove the health power-up from the scene
[characterchangeState
:kStateDead
]; } } } [self checkAndClampSpritePosition
];if
((self.characterState
==kStateIdle
) || (self.characterState
==kStateWalking
) || (self.characterState
==kStateCrouching
) || (self.characterState
==kStateStandingUp
) || (self.characterState
==kStateBreathing
)) {if
(jumpButton
.active
) { [self changeState
:kStateJumping
]; }else if
(attackButton
.active
) { [self changeState
:kStateAttacking
]; }else if
((joystick
.velocity
.x
==0.0f
) && (joystick
.velocity
.y
==0.0f
)) {if
(self.characterState
==kStateCrouching
) [self changeState
:kStateStandingUp
]; }else if
(joystick
.velocity
.y
< -0.45f
) {if
(self.characterState
!=kStateCrouching
) [self changeState
:kStateCrouching
]; }else if
(joystick
.velocity
.x
!=0.0f
) {// dpad moving
if
(self.characterState
!=kStateWalking
) [self changeState
:kStateWalking
]; [self applyJoystick
:joystick
forTimeDelta
:deltaTime]; } }if
([self numberOfRunningActions
] ==0
) {// Not playing an animation
if
(self.characterHealth
<=0.0f
) { [self changeState
:kStateDead
]; }else if
(self.characterState
==kStateIdle
) {millisecondsStayingIdle
=millisecondsStayingIdle
+ deltaTime;if
(millisecondsStayingIdle
>kVikingIdleTimer
) { [self changeState
:kStateBreathing
]; } }else if
((self.characterState
!=kStateCrouching
) && (self.characterState
!=kStateIdle
)){millisecondsStayingIdle
=0.0f
; [self changeState
:kStateIdle
]; } } } #pragma mark - -(CGRect
)adjustedBoundingBox {// Adjust the bouding box to the size of the sprite
// without the transparent space
CGRect
vikingBoundingBox = [self boundingBox
];float
xOffset;float
xCropAmount = vikingBoundingBox.size
.width
*0.5482f
;float
yCropAmount = vikingBoundingBox.size
.height
*0.095f
;if
([self flipX
] ==NO
) {// Viking is facing to the rigth, back is on the left
xOffset = vikingBoundingBox.size
.width
*0.1566f
; }else
{// Viking is facing to the left; back is facing right
xOffset = vikingBoundingBox.size
.width
*0.4217f
; } vikingBoundingBox =CGRectMake
(vikingBoundingBox.origin
.x
+ xOffset, vikingBoundingBox.origin
.y
, vikingBoundingBox.size
.width
- xCropAmount, vikingBoundingBox.size
.height
- yCropAmount);if
(characterState
==kStateCrouching
) {// Shrink the bounding box to 56% of height
// 88 pixels on top on iPad
vikingBoundingBox =CGRectMake
(vikingBoundingBox.origin
.x
, vikingBoundingBox.origin
.y
, vikingBoundingBox.size
.width
, vikingBoundingBox.size
.height
*0.56f
); }return
vikingBoundingBox; }
In the same manner as the RadarDish updateStateWithDeltaMethod worked, this method also returns immediately if the Viking is dead. There is no need to update a dead Viking because he won't be going anywhere.
If the Viking is in the middle of playing, the taking damage animation is played. This method again short-circuits and returns. The taking damage animation is blocking in that the player cannot do anything else while Ole the Viking is being shocked.
If the Viking is not taking damage or is dead, then the next step is to check what objects are coming in contact with the Viking. If there are objects in contact with the Viking, he checks to see if they are:
- Phaser: Changes the Viking state to taking damage.
- Mallet power-up: Gives Ole the Viking the mallet, a fearsome weapon.
- Health power-up: Ole's health is restored back to 100.
After checking for contacts, often called collisions, a quick call is made to the checkAndClampSpritePosition method to ensure that the Viking sprite stays within the boundaries of the screen.
The next if statement block checks the state of the joystick, jump, and attack buttons and changes the state of the Viking to reflect which controls are being pressed. The if statement executes only if the Viking is not currently carrying out a blocking animation, such as jumping.
Lastly the Viking class reaches a section of the updateStateWithDeltaTime method that handles what happens when there are no animations currently running. Cocos2D has a convenience method on CCNodes that reports back the number of actions running against a particular CCNode object. If you recall from the beginning of this chapter, all animations have to be run by a CCAnimate action. Once the animation for a state completes, the numberOfRunningActions will return zero for the Viking, and this block of code will reset the Viking's state.
If the health is zero or less, the Viking will move into the dead state. Otherwise, if Viking is idle, a counter is incremented indicating how many seconds the player has been idle. Once that counter reaches a set limit, the Viking will play a heavy breathing animation. Finally, if the Viking is not already idle or crouching, he will move back into the idle state.
After the updateStateWithDeltaTime method, there is the adjustedBoundingBox method you declared inside the GameObject class. In Chapter 3, "Introduction to Cocos2D Animations and Actions," Figure 3.6 illustrated the transparent space in the Viking texture between the actual Viking and the edges of the image/texture. This method compensates for the transparent pixels by returning an adjusted bounding box that does not include the transparent pixels. The flipX parameter is used to determine which side the Viking is facing, as fewer pixels are trimmed off the back of the Viking image than the front.
The last part of the Viking.m implementation file sets up the animations inside the initAnimations method and the instance variables inside the init method. Once more, copy the contents of Listing 4.9 into your Viking.m implementation file immediately following the end of the adjustedBoundingBox method.
Listing 4.9. Viking.m implementation file (part 4 of 4)
#pragma mark - -(void
)initAnimations { [self
setBreathingAnim:[self
loadPlistForAnimationWithName:@"breathingAnim"
andClassName:NSStringFromClass([self
class])]]; [self setBreathingMalletAnim
:[self
loadPlistForAnimationWithName:@"breathingMalletAnim"
andClassName:NSStringFromClass([self
class])]]; [self
setWalkingAnim:[self
loadPlistForAnimationWithName:@"walkingAnim"
andClassName:NSStringFromClass
([self
class])]]; [self
setWalkingMalletAnim:[self
loadPlistForAnimationWithName:@"walkingMalletAnim" andClassName
:NSStringFromClass
([self
class])]]; [self
setCrouchingAnim:[self
loadPlistForAnimationWithName:@"crouchingAnim"
andClassName:NSStringFromClass
([self
class])]]; [self
setCrouchingMalletAnim:[self
loadPlistForAnimationWithName:@"crouchingMalletAnim"
andClassName:NSStringFromClass([self
class])]]; [self
setStandingUpAnim:[self
loadPlistForAnimationWithName:@"standingUpAnim"
andClassName:NSStringFromClass([self
class])]]; [self
setStandingUpMalletAnim:[self
loadPlistForAnimationWithName:@"standingUpMalletAnim"
andClassName:NSStringFromClass([self
class])]]; [self
setJumpingAnim:[self
loadPlistForAnimationWithName:@"jumpingAnim"
andClassName:NSStringFromClass([self
class])]]; [self
setJumpingMalletAnim:[self
loadPlistForAnimationWithName:@"jumpingMalletAnim"
andClassName:NSStringFromClass([self
class])]]; [self
setAfterJumpingAnim:[self
loadPlistForAnimationWithName:@"afterJumpingAnim"
andClassName:NSStringFromClass([self
class])]]; [self
setAfterJumpingMalletAnim:[self
loadPlistForAnimationWithName:@"afterJumpingMalletAnim"
andClassName:NSStringFromClass
([self
class])]];// Punches
[self
setRightPunchAnim:[self
loadPlistForAnimationWithName:@"rightPunchAnim"
andClassName:NSStringFromClass
([self
class])]]; [self
setLeftPunchAnim:[self
loadPlistForAnimationWithName:@"leftPunchAnim"
andClassName:NSStringFromClass([self
class])]]; [self
setMalletPunchAnim:[self
loadPlistForAnimationWithName:@"malletPunchAnim"
andClassName:NSStringFromClass
([self class
])]];// Taking Damage and Death
[self
setPhaserShockAnim:[self
loadPlistForAnimationWithName:@"phaserShockAnim"
andClassName:NSStringFromClass([self
class])]]; [self
setDeathAnim:[self
loadPlistForAnimationWithName:@"vikingDeathAnim"
andClassName:NSStringFromClass([self
class])]]; }#pragma mark -
-(id
) init {if
( (self
=[super init
]) ) {joystick
=nil
;jumpButton
=nil
;attackButton
=nil
; self.gameObjectType
=kVikingType
;myLastPunch
=kRightHook
;millisecondsStayingIdle
=0.0f
;isCarryingMallet
=NO
; [self initAnimations
]; }return self
; }@end
The initAnimation method, while quite long, is very basic in that it only initializes all of the Viking animations based on the display frames already loaded from the scene1atlas.plist file in the GameplayLayer class. The init method sets up the instance variables to their starting values.