我在业余时间从Ray Wenderlich的书中学习Cocos2D,但如果它没有解释如何做一些我认为自己将来需要的东西,也会对它进行修改。我目前因为知识非常有限而陷入困境。
我希望使用GamePlayLayer类随机更改TBT类的字符状态。
我已经检查了每个状态并且它们都工作(通过使它们成为spawn状态进行检查)所以问题最有可能发生在我试图制作自己的方法的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
答案 0 :(得分:0)
我的猜测是你没有将TBT对象作为孩子添加到任何东西(即CCScene / CCNode / CCSprite)。尝试将其添加到“sceneSpriteBatchNode”中,就像在createObjectOfType:方法中一样。
[sceneSpriteBatchNode addChild:tBT
z:ZValue
tag:k1BTTagValue];