I read with interest this post to StackOverflow:
How to Make a Basic Finite State Machine in Objective-C
I used this as a basis to build my state-machine for a simple football game. I have states Defend, Attack, Stoppage, Neutral. I have created the state Machine and it will print out with NSLog “Now Entering State Defend” etc.
Now I would like to pass in a reference to my Football Team to the state Machine, such that I can make my team do something based on the state. Ie if its Defend, I can send my players to stand next to an opponent.
Ive tried many different ways but all end in syntax errors. Id appreciate a push in the right direction
TeamState.h Note the Errors Im getting in the comments
@class TeamState;
#import <Foundation/Foundation.h>
#import "FootballTeam.h"
@protocol TeamStateProt
-(void) enterTeamState:(TeamState*)team;
-(void) executeTeamState:(TeamState*)team;
-(void) exitTeamState:(TeamState*)team;
@end
@interface TeamState : NSObject{
id<TeamStateProt> currentTeamState;
id<TeamStateProt> Stoppage;
id<TeamStateProt> Neutral;
id<TeamStateProt> Defend;
id<TeamStateProt> Attack;
FootballTeam *footballTeam; //ERROR Unknown Type name FootballTeam
}
@property (nonatomic, retain) id<TeamStateProt> currentTeamState;
@property (nonatomic, retain) id<TeamStateProt> Stoppage;
@property (nonatomic, retain) id<TeamStateProt> Neutral;
@property (nonatomic, retain) id<TeamStateProt> Defend;
@property (nonatomic, retain) id<TeamStateProt> Attack;
- (id)initWithFootBallTeam:(FootballTeam*) team; //Error Expected a Type
-(void)update;
-(void)changeState:(id<TeamStateProt>) newState;
-(void)executeState:(id<TeamStateProt>) State;
@end
TeamState.m
#import "TeamState.h"
#import "FootballTeam.h"
#import "Stoppage_TS.h"
#import "Neutral_TS.h"
#import "Defend_TS.h"
#import "Attack_TS.h"
@implementation TeamState
@synthesize currentTeamState;
@synthesize Stoppage, Neutral, Defend, Attack;
- (id)init
{
self = [super init];
if (self) {
// Initialization code here.
id<TeamStateProt> s = [[Stoppage_TS alloc] init];
self.Stoppage = s;
id<TeamStateProt> n = [[Neutral_TS alloc] init];
self.Neutral = n;
id<TeamStateProt> d = [[Defend_TS alloc] init];
self.Defend = d;
id<TeamStateProt> a = [[Attack_TS alloc] init];
self.Attack = a;
self.currentTeamState = n;
[self.currentTeamState enterTeamState:self];
[self executeState:self.currentTeamState];
}
return self;
}
- (id)initWithFootBallTeam:(FootballTeam*) team
{
self = [super init];
if (self) {
// Initialization code here.
id<TeamStateProt> s = [[Stoppage_TS alloc] init];
self.Stoppage = s;
id<TeamStateProt> n = [[Neutral_TS alloc] init];
self.Neutral = n;
id<TeamStateProt> d = [[Defend_TS alloc] init];
self.Defend = d;
id<TeamStateProt> a = [[Attack_TS alloc] init];
self.Attack = a;
self.currentTeamState = n;
[self.currentTeamState enterTeamState:self];
[self executeState:self.currentTeamState];
footballTeam = team;
}
return self;
}
-(void)changeState:(id<TeamStateProt>) newState{
NSLog(@"Changing State");
if (newState != nil) {
NSLog(@"Changing a state which isn't nil");
[self.currentTeamState exitTeamState:self];
self.currentTeamState = newState;
[self.currentTeamState enterTeamState:self];
[self executeState:self.currentTeamState];
}
}
-(void)executeState:(id<TeamStateProt>) State{
[self.currentTeamState executeTeamState:self];
}
// Each update, execute the execute state on the current team state
-(void)update{
[self executeState:self.currentTeamState];
}
@end
FootballTeam.h
#import <Foundation/Foundation.h>
#import "Player.h"
#import "TeamState.h"
#import "Football.h"
typedef enum {
Home,
Away
} TeamType;
@interface FootballTeam : NSObject{
Player *ReceivingPlayer; //Player to receive the ball
Player *ClosestToBall; //Player closest to the ball
Player *ControllingPlayer; //Player who has the ball can be NULL
Player *SupportingPlayer; //Player in a position to receive the ball
NSMutableArray *players; //Array of all the Players on this team
TeamState *state; //Current state of the teams state machine
TeamType type; //Defines if Home team or Away team
}
@property (nonatomic) TeamType type;
@property(nonatomic, retain) TeamState *state;
-(void) sendPlayersToHome;
-(Player*) playerClosestToBall:(Football*) ball;
-(BOOL) areAllPlayersAtHome;
@end
You’ve got circular references. You’re importing TeamState.h in FootballTeam.h and vice versa.
To avoid this, import the .h files in the .m files only, and add forward declarations in the .h files.
So, in TeamState.h:
And move the import to TeamState.m
The same in FootballTeam.