Skip to content

Instantly share code, notes, and snippets.

@efranford
Created February 26, 2012 02:46
Show Gist options
  • Save efranford/1912407 to your computer and use it in GitHub Desktop.
Save efranford/1912407 to your computer and use it in GitHub Desktop.
Enhanced Sprites for Sparrow Framework
//
// EMedia.h
// Extended Media
//
// Created by Elliot Franford on 1/16/12.
// Copyright (c) 2012 Abandon Hope Games, LLC. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "SPStage.h"
#import "SPSoundChannel.h"
#import "SPTextureAtlas.h"
#import "SPAudioEngine.h"
@interface EMedia : NSObject
@property (nonatomic,retain) SPStage* stage;
@property (nonatomic,retain) SPJuggler* juggler;
+ (void)initTextures:(NSString*)atlasFile;
+ (void)releaseTextures;
+ (SPTexture *)atlasTexture:(NSString *)name;
+ (NSArray *)texturesStartingWith:(NSString *)name;
+ (void)initAudio;
+ (void)releaseAudio;
+ (void)initStage;
+ (void)releaseStage;
+ (SPStage*)getStage;
+ (void)onAddToStage:(SPEvent*)evt;
+ (void)initJuggler;
+ (void)releaseJuggler;
+ (SPJuggler*)getJuggler;
+ (void)playSound:(NSString *)soundName;
+ (SPSoundChannel *)soundChannel:(NSString *)soundName;
extern int RETINA_WIDTH;
extern int RETINA_HEIGHT;
extern int NORMAL_WIDTH;
extern int NORMAL_HEIGHT;
@end
//
// EMedia.m
// Extended Media
//
// Created by Elliot Franford on 1/16/12.
// Copyright (c) 2012 Abandon Hope Games, LLC. All rights reserved.
//
#import "EMedia.h"
#import "ESprite.h"
@implementation EMedia
static SPTextureAtlas *atlas = NULL;
static NSMutableDictionary *sounds = NULL;
static SPStage* _stage = NULL;
static SPJuggler* _juggler = NULL;
@synthesize stage = _stage;
@synthesize juggler = _juggler;
#pragma mark Texture Atlas
+ (void)initTextures:(NSString *)atlasFile
{
[atlas release];
NSString *atlasLoc = atlasFile;
atlas = [[SPTextureAtlas alloc] initWithContentsOfFile:atlasLoc];
}
+ (void)releaseTextures
{
[atlas release];
atlas = nil;
}
+ (SPTexture *)atlasTexture:(NSString *)name
{
if (!atlas)
[NSException raise:NSGenericException format:@"call 'initTextures:' first"];
return [atlas textureByName:name];
}
+ (NSArray *)texturesStartingWith:(NSString *)name
{
if (!atlas)
[NSException raise:NSGenericException format:@"call 'initTextures:' first"];
return [atlas texturesStartingWith:name];
}
#pragma mark Stage
+ (void)initStage{
_stage = [[SPStage alloc]init];
[_stage addEventListener:@selector(onAddToStage:) atObject:self forType:SP_EVENT_TYPE_ADDED_TO_STAGE];
}
+ (void)onAddToStage:(SPEvent*)evt
{
id obj = [_stage childAtIndex:_stage.numChildren-1];
if([obj isKindOfClass:ESprite.class])
{
[_juggler addObject:((ESprite*)obj).currentAnimation];
NSLog(@"Added %@ to the juggler", ((ESprite*)obj).name);
}
}
+ (void)releaseStage{
[_stage release];
_stage = nil;
}
+ (SPStage*) getStage{
return _stage;
}
#pragma mark Juggler
+ (void)initJuggler{
_juggler = [[SPJuggler alloc]init];
}
+ (void)releaseJuggler{
[_juggler release];
_juggler = nil;
}
+ (SPJuggler*)getJuggler{
return _juggler;
}
#pragma mark Audio
+ (void)initAudio
{
if (sounds) return;
[SPAudioEngine start];
sounds = [[NSMutableDictionary alloc] init];
// enumerate all sounds
NSString *soundDir = [[NSBundle mainBundle] resourcePath];
NSDirectoryEnumerator *dirEnum = [[NSFileManager defaultManager]
enumeratorAtPath:soundDir];
NSString *filename;
while (filename = [dirEnum nextObject])
{
if ([[filename pathExtension] isEqualToString: @"caf"])
{
SPSound *sound = [[SPSound alloc] initWithContentsOfFile:filename];
SPSoundChannel *channel = [sound createChannel];
[sounds setObject:channel forKey:filename];
[sound release];
}
}
}
+ (void)releaseAudio
{
[sounds release];
sounds = nil;
[SPAudioEngine stop];
}
+ (void)playSound:(NSString *)soundName
{
[[sounds objectForKey:soundName] play];
}
+ (SPSoundChannel *)soundChannel:(NSString *)soundName
{
return [sounds objectForKey:soundName];
}
//960x640
int RETINA_WIDTH = 640;
int RETINA_HEIGHT = 960;
//320x480
int NORMAL_WIDTH = 320;
int NORMAL_HEIGHT = 480;
@end
//
// ESprite.h
// Extended Sprite
//
// Created by Elliot Franford on 1/16/12.
// Copyright (c) 2012 Abandon Hope Games, LLC. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "SPMovieClip.h"
#import "SPEvent.h"
#import "SPEnterFrameEvent.h"
#import "ESpriteState.h"
#import "SPMacros.h"
#import "EMedia.h"
@interface ESprite : SPSprite <NSXMLParserDelegate> {
#define EVENT_TYPE_SPRITE_ANIMATION_CHANGE @"spriteAnimationChanged"
@private
NSMutableDictionary* stateAnimationDictionary;
SPMovieClip* currentAnimation;
NSString* spriteAtlasFile;
ESpriteState* currentState;
SPJuggler* juggler;
}
- (id) initWithESpriteFile:(NSString*)file;
- (id) initWithESpriteFile:(NSString*)file AndInitialAnimation:(NSString*)initialAnimation;
- (id) getAnimation;
- (void)onMoveSprite:(SPEvent*)evt:(float)speed:(float)angle;
- (void)setSpritePositionX:(int)x Y:(int)y;
- (void)parseTMXXml:(NSString *)path;
- (ESpriteState*)getFirstAnimation;
- (void)setState:(ESpriteState*)state;
- (void)setStateUsingKey:(NSString*)key;
- (void)changeState:(ESpriteState*)state;
- (void)advanceTime:(double)time;
@property (nonatomic,assign) NSMutableDictionary* stateAnimationDictionary;
@property (nonatomic,assign) SPMovieClip* currentAnimation;
@property (nonatomic,assign) NSString* spriteAtlasFile;
@property (nonatomic,assign) ESpriteState* currentState;
@property (nonatomic,assign) SPJuggler* juggler;
@end
//
// ESprite.m
// Sparrow
//
// Created by Elliot Franford on 1/16/12.
// Copyright (c) 2012 Abandon Hope Games, LLC. All rights reserved.
//
#import "ESprite.h"
@implementation ESprite
@synthesize stateAnimationDictionary;
@synthesize currentAnimation;
@synthesize spriteAtlasFile;
@synthesize currentState;
@synthesize juggler;
NSString* currentElementName;
- (id)initWithESpriteFile:(NSString*)file {
self = [super init];
if(self){
return [self initWithESpriteFile:file AndInitialAnimation:[[NSString alloc]initWithString:@"NoDefault"]];
}
else
return self;
}
- (id)initWithESpriteFile:(NSString*)file AndInitialAnimation:(NSString*)initialAnimation{
self = [super init];
if (self) {
juggler = [[SPJuggler alloc]init];
stateAnimationDictionary = [[NSMutableDictionary alloc]init];
[self parseTMXXml:file];
if([spriteAtlasFile isEqualToString:@""])
return nil;
[EMedia initTextures:spriteAtlasFile];
if(stateAnimationDictionary.count == 0)
return nil;
ESpriteState* startState = [self getFirstAnimation];
if([initialAnimation isEqualToString:@"NoDefault"])
startState = [self getFirstAnimation];
else
startState = (ESpriteState*)[stateAnimationDictionary objectForKey:initialAnimation];
if([initialAnimation isEqualToString:@"NoAnimation"])
return nil;
[self changeState:startState];
}
return self;
}
- (ESpriteState*) getFirstAnimation
{
ESpriteState* state = [[ESpriteState alloc]initWithName:@"NoAnimation" prefix:@"" fps:0 loop:FALSE];
if(stateAnimationDictionary.count > 0)
{
NSString* key = [[stateAnimationDictionary allKeys]objectAtIndex:0];
state = (ESpriteState*)[stateAnimationDictionary valueForKey:key];
}
return state;
}
- (void)parseTMXXml:(NSString *)path
{
if (!path) return;
float scaleFactor = [SPStage contentScaleFactor];
NSString* mPath = [[SPUtils absolutePathToFile:path withScaleFactor:scaleFactor] retain];
if (!mPath) [NSException raise:SP_EXC_FILE_NOT_FOUND format:@"file not found: %@", path];
SP_CREATE_POOL(pool);
NSData *xmlData = [[NSData alloc] initWithContentsOfFile:mPath];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:xmlData];
[xmlData release];
xmlParser.delegate = self;
BOOL success = [xmlParser parse];
SP_RELEASE_POOL(pool);
if (!success)
[NSException raise:SP_EXC_FILE_INVALID
format:@"could not parse texture atlas %@. Error code: %d, domain: %@",
path, xmlParser.parserError.code, xmlParser.parserError.domain];
[xmlParser release];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict
{
currentElementName = [elementName copy];
if ([currentElementName isEqualToString:@"ESprite"])
{
[self setName:[attributeDict valueForKey:@"name"]];
spriteAtlasFile = [[NSString alloc] initWithString:[attributeDict valueForKey:@"spriteAtlas"]];
}
if ([currentElementName isEqualToString:@"State"]) {
//State name="idle" anmationPrefix="away_" animationFPS="10"
NSString* stateName = [attributeDict valueForKey:@"name"];
NSString* animPrefix = [attributeDict valueForKey:@"animationPrefix"];
int fps = [[attributeDict valueForKey:@"animationFPS"]intValue];
BOOL loop = [[attributeDict valueForKey:@"loop"]boolValue];
ESpriteState* state = [[ESpriteState alloc]initWithName:stateName prefix:animPrefix fps:fps loop:loop];
[stateAnimationDictionary setObject:state forKey:stateName];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
// intentinoaly not handled right now
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
// intentinoaly not handled right now
}
-(id)getAnimation{
return currentAnimation;
}
-(void)onMoveSprite:(SPEvent*)evt:(float)speed:(float)angle{
/*
0
-45 .---. 45
/ | \
-90 ---|--- 90
\ | /
-135 '---' 135
-180|180
*/
//NSLog(@"a:%f s:%f",angle,speed);
float scale_x;
float scale_y;
float fAngle = SP_D2R(angle);
scale_y = cos(fAngle);
scale_x = sin(fAngle);
//NSLog(@"sx: %f sy: %f s:%f",scale_x,scale_y,speed);
float v_x,v_y;
if(speed > 0){
v_x = (speed) * scale_x;
v_y = (speed) * scale_y;
}
else
{
v_x = (speed * scale_x);
v_y = (speed * scale_y);
}
//NSLog(@"vx: %f vy: %f",v_x,v_y);
//NSLog(@"x: %f y: %f",self.x,self.y);
//NSLog(@"X: %f Y: %f",self.x+v_x,self.y+v_y);
self.x += v_x;
self.y -= v_y;
}
-(void)setSpritePositionX:(int)x Y:(int)y{
self.x = x;
self.y = y;
}
- (void)setState:(ESpriteState*)state
{
currentState = state;
[self changeState:state];
}
- (void)setStateUsingKey:(NSString*)key
{
[self changeState:[stateAnimationDictionary objectForKey:key]];
}
- (void) changeState:(ESpriteState*)state
{
currentState = state;
// create movie clip
NSArray *animation = [EMedia texturesStartingWith:state.animationPrefix];
currentAnimation = [[SPMovieClip alloc] initWithFrames:animation fps:state.animationFPS];
[currentAnimation setLoop:state.loop];
[currentAnimation play];
[self removeAllChildren];
[self addChild:currentAnimation];
}
- (void)advanceTime:(double)time
{
[juggler removeAllObjects];
[juggler addObject:currentAnimation];
[juggler advanceTime:time];
}
@end
//
// ESpriteManager.h
// AppScaffold
//
// Created by Elliot Franford on 1/16/12.
// Copyright (c) 2012 Abandon Hope Games, LLC. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "ESprite.h"
@interface ESpriteManager
@property (nonatomic,assign) NSMutableDictionary* sprites;
+(id)initManager;
+(void) addSprite:(ESprite*)sprite withName:(NSString*)name;
+(void) removeSpriteWithName:(NSString*)name;
+(ESprite*) spriteByName:(NSString*)name;
+(void) setSpriteState:(NSString*)state forSpriteWithName:(NSString*)name;
+(void) advanceTime:(double)time;
@end
//
// ESpriteManager.m
// AppScaffold
//
// Created by Elliot Franford on 1/16/12.
// Copyright (c) 2012 Abandon Hope Games, LLC. All rights reserved.
//
#import "ESpriteManager.h"
@implementation ESpriteManager
static NSMutableDictionary* _sprites;
@synthesize sprites = _sprites;
+(id) initManager
{
_sprites = [[NSMutableDictionary alloc]init];
return self;
}
+(void) addSprite:(ESprite*)sprite withName:(NSString*)name
{
[_sprites setObject:sprite forKey:name];
}
+(void) removeSpriteWithName:(NSString*)name
{
ESprite* removeMe = [_sprites objectForKey:name];
if(removeMe)
{
[_sprites removeObjectForKey:name];
}
[removeMe dealloc];
}
+(ESprite*) spriteByName:(NSString*)name
{
return [_sprites objectForKey:name];
}
+(void) setSpriteState:(NSString*)state forSpriteWithName:(NSString*)name
{
ESprite* sprite = [self spriteByName:name];
[sprite setStateUsingKey:state];
}
+(void) advanceTime:(double)time
{
for(NSString* key in _sprites)
{
ESprite* sprite = [_sprites valueForKey:key];
[sprite advanceTime:time];
}
}
@end
//
// ESpriteState.h
// AppScaffold
//
// Created by Elliot Franford on 1/16/12.
// Copyright (c) 2012 Abandon Hope Games, LLC. All rights reserved.
//
#import <Foundation/Foundation.h>
//<State name="idle" anmationPrefix="away_" animationFPS="10"/>
@interface ESpriteState : NSObject{
@private
NSString* mStateName;
NSString* mAnimationPrefix;
int mAnimationFPS;
BOOL mLoop;
}
@property (nonatomic,assign) NSString* stateName;
@property (nonatomic,assign) NSString* animationPrefix;
@property (nonatomic,assign) int animationFPS;
@property (nonatomic,assign) BOOL loop;
- (id) init;
- (id) initWithName:(NSString*)name prefix:(NSString*)prefix fps:(int)fps loop:(BOOL)loop;
@end
//
// ESpriteState.m
// AppScaffold
//
// Created by Elliot Franford on 1/16/12.
// Copyright (c) 2012 Abandon Hope Games, LLC. All rights reserved.
//
#import "ESpriteState.h"
@implementation ESpriteState
@synthesize stateName = mStateName;
@synthesize animationFPS = mAnimationFPS;
@synthesize animationPrefix = mAnimationPrefix;
@synthesize loop = mLoop;
- (id) init{
if(self = [super init])
{
mStateName = [[NSString alloc]init];
mAnimationPrefix = [[NSString alloc]init];
mAnimationFPS = 0;
}
return self;
}
- (id) initWithName:(NSString*)name prefix:(NSString*)prefix fps:(int)fps loop:(BOOL)loop{
if(self = [super init])
{
mStateName = [[NSString alloc]initWithString:name];
mAnimationPrefix = [[NSString alloc]initWithString:prefix];
mAnimationFPS = fps;
mLoop = loop;
}
return self;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment