我在業餘時間從Ray Wenderlich書中學習Cocos2D,但如果它沒有解釋如何做某件事,我可以看到自己需要未來。由於我的知識非常有限,我目前陷入困境。Cocos 2D - 從另一個班級更改遊戲角色狀態
我希望使用GamePlayLayer類隨意改變TBT類的字符狀態。
我已經檢查每一個國家,他們所有的工作(通過使它們產卵狀態檢查),所以這個問題是最有可能在我試圖使自己的方法gamePlayLayer.m文件。
我似乎能夠得到它的狀態改變爲kStateThrowing而是筆直向後(在第二!0.3),以kStateIdle它改變了動畫播放之前,並具有以下輸出...
2013-11-21 13:45:07.938 Spaceviking[981:12c03] CHANGING STATE TBT!!!!!!
2013-11-21 13:45:07.939 Spaceviking[981:12c03] TBT->Changing State to throwing
2013-11-21 13:45:07.967 Spaceviking[981:12c03] TBT Going to Idle
2013-11-21 13:45:07.970 Spaceviking[981:12c03] TBT->changing state to idle
任何幫助,這將不勝感激。
代碼如下...
// CommonProtocols.h
#ifndef SpaceViking_CommonProtocols_h
#define SpaceViking_CommonProtocols_h
typedef enum {
kDirectionLeft,
kDirectionRight
}
PhaserDirection;
typedef enum {
kStatespawning,
kStateIdle,
kStateWalking,
kStateIdleTilt,
kStatebackTilting,
kStateforwardTilting,
kStateAttacking,
kStateTakingDamage,
kStateThrowing,
kStateLosingALife,
kStateDead,
kStateTravelling,
kStateRotating,
kStatetest
}
CharacterStates; //1
typedef enum {
kObjectTypeNone,
kPowerUpTypeHealth,
kPowerTypeMallet,
kEnemyType1BT,
kEnemyType2BT,
kEnemyType3BT,
kEnemyTypePhaser,
kVikingType,
} GameObjectType;
@protocol GamePlayLayerDelegate
-(void)createObjectOfType:(GameObjectType)objectType
withHealth:(int)initialHealth
atLocation:(CGPoint)spawnLocation
withZValue:(int)ZValue;
-(void)createPhaserWithDirection: (PhaserDirection)phaserDirection
andPosition:(CGPoint)spawnPosition;
#endif
// GamePlayLayer.h
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#import "CCLayer.h"
#import "SneakyJoystick.h"
#import "SneakyButton.h"
#import "SneakyButtonSkinnedBase.h"
#import "SneakyJoystickSkinnedBase.h"
#import "Constants.h"
#import "CommonProtocols.h"
#import "TBT.h"
@interface GamePlayLayer : CCLayer <GamePlayLayerDelegate> {
CCSprite *vikingSprite;
SneakyJoystick *leftJoystick;
SneakyButton *jumpButton;
SneakyButton *attackButton;
CCSpriteBatchNode *sceneSpriteBatchNode;
}
@end
------------------------------------------------
// GamePlayLayer.m
#import "GamePlayLayer.h"
@implementation GamePlayLayer
-(void) dealloc {
[leftJoystick release];
[jumpButton release];
[attackButton release];
[super dealloc];
}
--DELETED BELOW 2 METHODS AS NOT NEEDED FOR THIS QUESTION--
-(void)initJoystickAndButtons {
}
-(void)applyJoystick:(SneakyJoystick *)aJoystick toNode: (CCNode *)tempNode forTimeDelta:(float)deltaTime
{
}
-(void) update:(ccTime)deltaTime {
CCArray *listOfGameObjects =
[sceneSpriteBatchNode children];
for (GameCharacter *tempChar in listOfGameObjects) {
[tempChar updateStateWithDeltaTime:deltaTime andListOfGameObjects:listOfGameObjects];
}
}
-(void) createObjectOfType: (GameObjectType)objectType
withHealth:(int)initialHealth atLocation:(CGPoint)spawnLocation withZValue:(int)ZValue {
if (objectType == kEnemyType1BT) {
CCLOG(@"creating 1BT");
TBT *tBT = [[TBT alloc] initWithSpriteFrameName:@"BT_anim_1.png"];
[tBT setCharacterHealth:initialHealth];
[tBT setPosition:spawnLocation];
[sceneSpriteBatchNode addChild:tBT
z:ZValue
tag:k1BTTagValue];
[tBT release];
}
}
--BELOW IS THE METHOD I HAVE CREATED TO CHANGE THE STATE--
-(void)changeState:(CharacterStates)newState {
[self stopAllActions];
int x = (arc4random() % 3);
TBT *tBT = [[TBT alloc]
initWithSpriteFrame:[[CCSpriteFrameCache
sharedSpriteFrameCache]
spriteFrameByName:@"BT_anim_1.png"]];
if (x>0) {
CCLOG(@"CHANGING STATE TBT!!!!!!");
[tBT changeState:kStateThrowing];
[tBT setDelegate:self];
[tBT release];
}
}
-(id)init {
self = [super init];
if (self !=nil) {
CGSize screenSize = [CCDirector sharedDirector]. winSize;
self.TouchEnabled = YES;
srandom(time(NULL));
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[[CCSpriteFrameCache sharedSpriteFrameCache]
addSpriteFramesWithFile:@"scene1atlas.plist"]; // 1
sceneSpriteBatchNode =
[CCSpriteBatchNode batchNodeWithFile:@"scene1atlas.png"]; // 2
} else {
[[CCSpriteFrameCache sharedSpriteFrameCache]
addSpriteFramesWithFile:@"scene1atlasiPhone.plist"]; // 1
sceneSpriteBatchNode =
[CCSpriteBatchNode batchNodeWithFile:@"scene1atlasiPhone.png"];
}
[self addChild:sceneSpriteBatchNode z:0];
[self initJoystickAndButtons];
BC *viking = [[BC alloc]
initWithSpriteFrame:[[CCSpriteFrameCache
sharedSpriteFrameCache]
spriteFrameByName:@"BCmoving_anim_1.png"]];
[viking setJumpButton:jumpButton];
[viking setAttackButton:attackButton];
[viking setPosition:ccp(screenSize.width * 0.19f,
screenSize.height * 0.19f)];
[viking setCharacterHealth:3];
[sceneSpriteBatchNode
addChild:viking
z:kVikingSpriteZValue
tag:kVikingSpriteTagValue];
[self createObjectOfType:kEnemyType1BT withHealth:3 atLocation:ccp(screenSize.width * 0.0439f, screenSize.height * 0.822f) withZValue:10];
---THE BELOW SELECTOR IS WHAT I HAVE USED TO DO A TIMED STATE CHANGE (METHOD ABOVE)--
[self schedule:@selector(changeState:) interval:1.0f];
[self scheduleUpdate];
}
return self;
}
@end
// TBT.h
#import <Foundation/Foundation.h>
#import "GameCharacter.h"
@interface TBT : GameCharacter {
//This is for the required animations
CCAnimation *tiltingAnim;
CCAnimation *transmittingAnim;
CCAnimation *loseLifeAnim;
CCAnimation *throwingAnim;
CCAnimation *afterThrowingAnim;
CCAnimation *shootPhaserAnim;
GameCharacter *vikingCharacter;
id <GamePlayLayerDelegate> delegate;
}
@property (nonatomic,assign) id <GamePlayLayerDelegate> delegate;
@property (nonatomic, retain) CCAnimation *tiltingAnim;
@property (nonatomic, retain) CCAnimation *transmittingAnim;
@property (nonatomic, retain) CCAnimation *loseLifeAnim;
@property (nonatomic, retain) CCAnimation *throwingAnim;
@property (nonatomic,retain) CCAnimation *afterThrowingAnim;
@property (nonatomic,retain) CCAnimation *shootPhaserAnim;
-(void)initAnimations;
-(void)changeState:(CharacterStates)newState;
@end
// TBT.m
#import "TBT.h"
@implementation TBT
@synthesize delegate;
@synthesize tiltingAnim;
@synthesize transmittingAnim;
@synthesize loseLifeAnim;
@synthesize throwingAnim;
@synthesize afterThrowingAnim;
@synthesize shootPhaserAnim;
-(void) dealloc {
delegate = nil;
[tiltingAnim release];
[transmittingAnim release];
[loseLifeAnim release];
[throwingAnim release];
[afterThrowingAnim release];
[shootPhaserAnim release];
[super dealloc];
}
--BELOW METHOD NOT NEEDED FOR THIS QUESTION
-(void)shootPhaser {}
-(CGRect)TBTboundingBox {
CGRect tbtBoundingBox = [self boundingBox];
float xOffset;
float xCropAmount = tbtBoundingBox.size.width * 0.5482f;
float yCropAmount = tbtBoundingBox.size.height * 0.1f;
tbtBoundingBox =
CGRectMake(tbtBoundingBox.origin.x + xOffset,
tbtBoundingBox.origin.y,
tbtBoundingBox.size.width - xCropAmount,
tbtBoundingBox.size.height - yCropAmount);
return tbtBoundingBox;
}
-(void)changeState:(CharacterStates)newState {
[self stopAllActions];
id action = nil;
[self setCharacterState:newState];
switch (newState) {
case kStatespawning:
CCLOG(@"TBT->Changing State to Spwaning");
[self setDisplayFrame:
[[CCSpriteFrameCache sharedSpriteFrameCache]
spriteFrameByName:@"BT_anim_1.png"]];
break;
case kStateIdle:
CCLOG(@"TBT->schaning state to idle");
[self setDisplayFrame:
[[CCSpriteFrameCache sharedSpriteFrameCache]
spriteFrameByName:@"BT_anim_1.png"]];
break;
case kStateThrowing:
CCLOG(@"TBT->Changing State to throwing");
action = [CCSequence actions:
[CCAnimate actionWithAnimation:throwingAnim
restoreOriginalFrame:NO],
[CCDelayTime actionWithDuration:1.0f],
//[CCAnimate actionWithAnimation:shootPhaserAnim
// restoreOriginalFrame:NO],
[CCCallFunc actionWithTarget:self
selector:@selector(shootPhaser)],
[CCAnimate actionWithAnimation:afterThrowingAnim
restoreOriginalFrame:NO],
[CCDelayTime actionWithDuration:0.1f],
nil];
break;
case kStateLosingALife:
CCLOG(@"TBT->Losing a life");
break;
case kStateDead:
CCLOG(@"TBT->changing state to dead");
action = [CCAnimate actionWithAnimation:loseLifeAnim];
break;
default:
CCLOG(@"unhandled state %d in TBT", newState);
break;
}
if (action !=nil) {
[self runAction:action];
}
}
-(void)updateStateWithDeltaTime: (ccTime)deltaTime andListOfGameObjects:(CCArray*)listOfGameObjects {
if (characterState == kStateDead)
return;
vikingCharacter =
(GameCharacter*)[[self parent]
getChildByTag:kVikingSpriteTagValue];
CGRect vikingBoudingBox =
[vikingCharacter adjustedBoundingBox];
CharacterStates vikingState = [vikingCharacter characterState];
if ((vikingState == kStateAttacking) && (CGRectIntersectsRect ([self adjustedBoundingBox], vikingBoudingBox))) {
if (characterState != kStateTakingDamage) {
[self changeState:kStateTakingDamage];
return;
}
}
if ((([self numberOfRunningActions] == 0) && (characterState != kStateDead))) {
CCLOG(@"TBT Going to Idle");
[self changeState:kStateIdle];
return;
}
}
-(void)initAnimations {
[self setTransmittingAnim:[self loadPlistForAnimationWithName:@"transmittingAnim" andClassName:NSStringFromClass([self class])]];
[self setThrowingAnim:[self loadPlistForAnimationWithName:@"throwingAnim" andClassName:NSStringFromClass([self class])]];
[self setAfterThrowingAnim:[self loadPlistForAnimationWithName:@"afterThrowingAnim" andClassName:NSStringFromClass([self class])]];
}
-(id) initWithSpriteFrameName:(NSString*)frameName{
if ((self=[super init])) {
if ((self = [super initWithSpriteFrameName:frameName])) {
CCLOG(@"### TBT initialized");
[self initAnimations];
characterHealth = 3.0f;
gameObjectType = kEnemyType1BT;
[self changeState:kStatespawning];
}
}
return self;
}
@end
嗨Skullz,非常感謝您給予回覆。我以爲我已經在createObjectOf類型中將TBT添加爲圖層中的一個子元素。我添加了TBT * tBT =(TBT *) [sceneSpriteBatchNode getChildByTag:kEnemyType1BT];進入changeState:(CharacterStates)newState方法,但是它什麼都不做,並且當它被添加時,它將不再將狀態改變爲拋出,並且它僅停留在空閒狀態。如果你能給我任何其他的想法,那就太好了,再次感謝 –