From 2a6200bf8b56abbf3eeecea44f06861ed10857c2 Mon Sep 17 00:00:00 2001 From: dsc Date: Sat, 4 Jun 2011 20:55:47 -0700 Subject: [PATCH] Bullets now arbitrarily destroy shit. --- src/Tanks.h | 5 +- src/TanksMacros.h | 2 +- src/game/QQActive.h | 4 +- src/game/QQGame.h | 55 ++++++++----- src/game/QQGame.mm | 128 ++++++++++++++++++---------- src/game/QQGameTime.h | 7 ++ src/game/QQPhysical.h | 10 ++ src/game/QQThing.h | 4 +- src/game/ability/QQCooldown.h | 3 +- src/game/ability/QQCooldown.mm | 4 +- src/game/actor/QQActor.h | 10 ++- src/game/actor/QQActor.mm | 71 ++++++++++++--- src/game/actor/QQActors.h | 10 +- src/game/actor/QQUnit.mm | 8 +- src/game/actor/bullet/QQBullet.h | 1 - src/game/actor/bullet/QQBullet.mm | 15 +++- src/game/actor/unit/QQTank.mm | 15 ++-- src/physics/QQWorld.h | 22 +++-- src/physics/QQWorld.mm | 86 ++++++++----------- src/physics/event/QQContactNotification.mm | 5 +- src/qq/NSSet+QQExtensions.h | 8 ++ src/qq/NSSet+QQExtensions.mm | 15 +++ src/qq/QQNotificationCenter.h | 16 ++++ src/qq/QQNotificationCenter.mm | 69 +++++++++++++++ src/qq/QQNotificationProxy.h | 16 ++++ src/qq/QQNotificationProxy.mm | 70 +++++++++++++++ src/qq/QQNotifier.h | 18 ++++- src/qq/QQNotifiers.h | 42 +++++++++ src/qq/QQObject.h | 10 -- src/qq/QQObject.mm | 12 --- src/qq/QQObservable.h | 3 + src/ui/QQAppDelegate.h | 9 +-- src/ui/QQAppDelegate.mm | 17 ++-- tanks.xcodeproj/project.pbxproj | 30 ++++++- 34 files changed, 591 insertions(+), 209 deletions(-) create mode 100644 src/game/QQGameTime.h create mode 100644 src/qq/NSSet+QQExtensions.h create mode 100644 src/qq/NSSet+QQExtensions.mm create mode 100644 src/qq/QQNotificationCenter.h create mode 100644 src/qq/QQNotificationCenter.mm create mode 100644 src/qq/QQNotificationProxy.h create mode 100644 src/qq/QQNotificationProxy.mm create mode 100644 src/qq/QQNotifiers.h delete mode 100644 src/qq/QQObject.h delete mode 100644 src/qq/QQObject.mm diff --git a/src/Tanks.h b/src/Tanks.h index c9e4885..6a4d3c0 100644 --- a/src/Tanks.h +++ b/src/Tanks.h @@ -1,6 +1,9 @@ #ifndef TANKS_H #define TANKS_H -#define TANKS_DEBUG_LOG 1 + +#define TANKS_DEBUG_LOG 0 + #endif +#import "TanksMacros.h" #import "render/QQSparrowExtensions.h" diff --git a/src/TanksMacros.h b/src/TanksMacros.h index 2a9ef11..e85b6b2 100644 --- a/src/TanksMacros.h +++ b/src/TanksMacros.h @@ -1,7 +1,7 @@ #ifndef TANKS_MACROS_H #define TANKS_MACROS_H - +#define qqBoolToString(__val) ((__val)?("YES"):("NO")) #endif \ No newline at end of file diff --git a/src/game/QQActive.h b/src/game/QQActive.h index be63ea8..4bc669b 100644 --- a/src/game/QQActive.h +++ b/src/game/QQActive.h @@ -1,3 +1,4 @@ +#import "game/QQGameTime.h" #import "game/QQThing.h" /** @@ -7,8 +8,9 @@ @property (nonatomic, readwrite, getter=isActive) BOOL active; // @property (nonatomic, readwrite, getter=isSleeping) BOOL sleeping; +@property (nonatomic, readwrite, retain) NSArray* cooldowns; -- (void) tick:(float)elapsed; +- (void) tick; - (void) act; @end \ No newline at end of file diff --git a/src/game/QQGame.h b/src/game/QQGame.h index 789be17..1c5e0a4 100644 --- a/src/game/QQGame.h +++ b/src/game/QQGame.h @@ -1,47 +1,62 @@ #import "Sparrow.h" +#import "qq/QQNotificationCenter.h" #import "physics/QQWorld.h" #import "physics/debug/QQPhysicsDebugView.h" +#import "game/QQGameTime.h" #import "game/actor/QQActor.h" #import "game/map/QQLevel.h" -@interface QQGame : SPStage { - +@interface QQGame : QQNotificationCenter { @private - QQWorld* _world; - - QQLevel* _level; - SPSprite* _root; + float _now; + float _elapsed; + long _ticks; + long _realtime; - NSMutableSet* _actors; - NSMutableSet* _awake; - NSMutableSet* _units; - NSMutableSet* _bullets; + BOOL _running; + BOOL _debugDrawingEnabled; + QQWorld* _world; QQPhysicsDebugView* _debugView; - BOOL _debugDrawingEnabled; - long _ticks; - BOOL _running; + SPStage* _stage; + SPSprite* _root; + QQLevel* _level; + + NSSet* _actors; + NSSet* _awake; + NSSet* _units; + NSSet* _bullets; } -@property (nonatomic, readonly) QQWorld* world; -@property (nonatomic, readonly) QQLevel* level; -@property (nonatomic, readonly) NSSet* actors; +@property (nonatomic, readonly) id time; +@property (nonatomic, readonly) float now; +@property (nonatomic, readonly) float elapsed; +@property (nonatomic, readonly) long ticks; -@property (nonatomic, readonly, assign) long ticks; @property (nonatomic, readonly, getter=isPaused) BOOL paused; @property (nonatomic, readwrite, assign) BOOL debugDrawingEnabled; -- (void) start; -- (void) stop; +@property (nonatomic, readonly) SPStage* stage; +@property (nonatomic, readonly) SPDisplayObjectContainer* root; +@property (nonatomic, readonly) QQLevel* level; + +@property (nonatomic, readonly) QQWorld* world; + +@property (nonatomic, readonly, retain) NSSet* actors; -- (void) tick:(float)elapsed; +- (void) tick; - (QQGame*) addActor:(QQActor*)actor; +// - (QQGame*) addActorAndShape:(QQActor*)actor; - (QQGame*) removeActor:(QQActor*)actor; +- (QQGame*) destroyActor:(QQActor*)actor; + +- (void) start; +- (void) stop; + (QQGame*) current; diff --git a/src/game/QQGame.mm b/src/game/QQGame.mm index 60bddbc..1a06899 100644 --- a/src/game/QQGame.mm +++ b/src/game/QQGame.mm @@ -1,16 +1,19 @@ #import +#import "Tanks.h" +#import "qq/NSSet+QQExtensions.h" #import "game/QQGame.h" #import "game/actor/QQActors.h" #import "physics/event/QQContactNotification.h" - static QQGame* _CurrentGame = NULL; @interface QQGame () +@property (nonatomic, readwrite, retain) NSSet* actors; + - (void) onEnterFrame:(SPEnterFrameEvent*)event; - (void) onCollide:(QQContactNotification*)msg; @end @@ -18,12 +21,11 @@ static QQGame* _CurrentGame = NULL; @implementation QQGame - - (id) init { if (_CurrentGame) { [self release]; #ifdef DEBUG - [NSException raise:@"TooManyGames" format:@"cannot instantiate more than one QQGame at a time!"]; + [NSException raise:@"WTFTooManyGames" format:@"cannot instantiate more than one QQGame at a time!"]; #else return _CurrentGame; #endif @@ -31,49 +33,56 @@ static QQGame* _CurrentGame = NULL; if ( (self = [super init]) ){ _CurrentGame = self; + _now = 0; _ticks = 0; + _elapsed = 0; _running = NO; + _stage = [[SPStage alloc] init]; + _root = [[SPSprite sprite] retain]; + [_stage addChild:_root]; + _world = [[QQWorld alloc] init]; - [_world addObserver:self selector:@selector(onCollide:) name:QQ_EVENT_CONTACT_BEGIN]; - [_world addObserver:self selector:@selector(onCollide:) name:QQ_EVENT_CONTACT_END]; + _world.proxiedNotifier = self; + [_world addObserver:self selector:@selector(onCollide:) name:QQ_EVENT_CONTACT_BEGIN object:nil]; + [_world addObserver:self selector:@selector(onCollide:) name:QQ_EVENT_CONTACT_END object:nil]; - _root = [SPSprite sprite]; - [self addChild:_root]; _level = [[QQLevel alloc] init]; [_root addChild:_level]; _debugView = [[QQPhysicsDebugView alloc] initWithWorld:_world]; [_root addChild:_debugView]; self.debugDrawingEnabled = YES; - _actors = [[NSMutableSet alloc] initWithCapacity:10]; - _awake = [[NSMutableSet alloc] initWithCapacity:10]; - _units = [[NSMutableSet alloc] initWithCapacity:10]; - _bullets = [[NSMutableSet alloc] initWithCapacity:10]; + _actors = [[NSSet alloc] init]; + _awake = [[NSSet alloc] init]; + _units = [[NSSet alloc] init]; + _bullets = [[NSSet alloc] init]; CGSize frame = [UIScreen mainScreen].applicationFrame.size; float wMax = frame.width / _world.scale; float hMax = frame.height / _world.scale; [[[QQTank alloc] initAtX:wMax/6 y:hMax/6 width:50 height:50 color:0xFF0071] autorelease]; [[[QQUnit alloc] initAtX:wMax/3 y:hMax/2 width:50 height:50 color:0x4596FF] autorelease]; + + [_stage addEventListener:@selector(logEvent:) atObject:self forType:SP_EVENT_TYPE_ANY]; } return self; } - (void) dealloc { - [self removeEventListener:@selector(onEnterFrame:) atObject:self forType:SP_EVENT_TYPE_ENTER_FRAME]; - [self removeAllChildren]; + [_stage removeEventListener:@selector(logEvent:) atObject:self forType:SP_EVENT_TYPE_ANY]; + [_stage removeEventListener:@selector(onEnterFrame:) atObject:self forType:SP_EVENT_TYPE_ENTER_FRAME]; - NSMutableSet* sets[] = {_actors, _awake, _units, _bullets}; - for (int i = 0; i < 4; i++) { - NSMutableSet* set = sets[i]; - [set removeAllObjects]; - [set release]; - } + [_actors release]; + [_awake release]; + [_units release]; + [_bullets release]; + [_stage release]; + [_root release]; [_level release]; + [_debugView release]; - [_root release]; [_world release]; _CurrentGame = NULL; @@ -83,14 +92,21 @@ static QQGame* _CurrentGame = NULL; /// properties -@synthesize world = _world; -@synthesize level = _level; +@synthesize now = _now; +@synthesize elapsed = _elapsed; +@synthesize ticks = _ticks; -@synthesize actors = _actors; +- (id) time { return self; } -@synthesize ticks = _ticks; @synthesize paused = _running; +@synthesize stage = _stage; +@synthesize root = _root; +@synthesize level = _level; + +@synthesize world = _world; +@synthesize actors = _actors; + @synthesize debugDrawingEnabled = _debugDrawingEnabled; - (void) setDebugDrawingEnabled:(BOOL)enable { @@ -102,30 +118,37 @@ static QQGame* _CurrentGame = NULL; /// methods - (QQGame*) addActor:(QQActor*)actor { - [_actors addObject:actor]; - [_awake addObject:actor]; - if ([actor isKindOfClass:[QQUnit class]]) - [_units addObject:actor]; - if ([actor isKindOfClass:[QQBullet class]]) - [_bullets addObject:actor]; + self.actors = [self.actors setByAddingObject:actor]; +// if (actor.isActive) +// _awake = [_awake setByAddingObject:actor]; +// if ([actor isKindOfClass:[QQUnit class]]) +// _units = [_units setByAddingObject:actor]; +// if ([actor isKindOfClass:[QQBullet class]]) +// _bullets = [_bullets setByAddingObject:actor]; return self; } - (QQGame*) removeActor:(QQActor*)actor { - [_actors removeObject:actor]; - [_awake removeObject:actor]; - [_units removeObject:actor]; - [_bullets removeObject:actor]; + self.actors = [self.actors setByRemovingObject:actor]; +// if (actor.isActive) +// _awake = [_awake setByRemovingObject:actor]; +// if ([actor isKindOfClass:[QQUnit class]]) +// _units = [_units setByRemovingObject:actor]; +// if ([actor isKindOfClass:[QQBullet class]]) +// _bullets = [_bullets setByRemovingObject:actor]; return self; } +- (QQGame*) destroyActor:(QQActor*)actor { + [_world destroy:actor]; + return [self removeActor:actor]; +} -- (void) tick:(float)elapsed { - _ticks++; - + +- (void) tick { #if TANKS_DEBUG_LOG if ((_ticks % 100) == 0) { - NSLog(@"[%ld] Time passed since last 100 frames: %f", _ticks, elapsed); + NSLog(@"[%ld] Time passed since last 100 frames: %f", _ticks, _elapsed); for (QQActor* actor in self.actors) { b2Vec2 v = actor.body->GetLinearVelocity(); NSLog(@"[%@ impulse:(%f,%f)]", actor, v.x,v.y); @@ -133,37 +156,54 @@ static QQGame* _CurrentGame = NULL; } #endif - for (QQActor* actor in _awake) [actor tick:elapsed]; + for (QQActor* actor in self.actors) + [actor tick]; [self.world step]; - for (QQActor* actor in self.actors) [actor draw]; + for (QQActor* actor in self.actors) + if (!actor.dead) [actor draw]; } - (void) start { if (!_running) { _running = YES; - [self addEventListener:@selector(onEnterFrame:) atObject:self forType:SP_EVENT_TYPE_ENTER_FRAME]; + [_stage addEventListener:@selector(onEnterFrame:) atObject:self forType:SP_EVENT_TYPE_ENTER_FRAME]; } } - (void) stop { if (_running) { - [self removeEventListener:@selector(onEnterFrame:) atObject:self forType:SP_EVENT_TYPE_ENTER_FRAME]; + [_stage removeEventListener:@selector(onEnterFrame:) atObject:self forType:SP_EVENT_TYPE_ENTER_FRAME]; _running = NO; } } -/// event handlers +/// event handlers - (void) onEnterFrame:(SPEnterFrameEvent*)event { - if (_running) [self tick:event.passedTime]; + if (_running) { + _ticks++; + _elapsed = event.passedTime; + _now += _elapsed; + [self tick]; + } } - (void) onCollide:(QQContactNotification*)msg { NSLog(@"%@", msg); } +- (void) logEvent:(SPEvent*)evt { + if ([evt.type isEqualToString:SP_EVENT_TYPE_ENTER_FRAME]) return; + NSLog(@"%@", evt); +} + +- (NSString*) description { + return [NSString stringWithFormat:@"<%@: %x> {running=%s, #actors=%i, time={now=%f, elapsed=%f, ticks=%l}}", + [self class], (long)self, qqBoolToString(self.isPaused), [self.actors count], + self.now, self.elapsed, self.ticks]; +} + (QQGame*) current { diff --git a/src/game/QQGameTime.h b/src/game/QQGameTime.h new file mode 100644 index 0000000..9f48c3d --- /dev/null +++ b/src/game/QQGameTime.h @@ -0,0 +1,7 @@ +@protocol QQGameTime + +@property (nonatomic, readonly) float now; +@property (nonatomic, readonly) float elapsed; +@property (nonatomic, readonly) long ticks; + +@end diff --git a/src/game/QQPhysical.h b/src/game/QQPhysical.h index efe27e0..951567e 100644 --- a/src/game/QQPhysical.h +++ b/src/game/QQPhysical.h @@ -1,5 +1,8 @@ #include +@class QQContactNotification; + + /** * Anything that has a physics representation. */ @@ -35,4 +38,11 @@ */ - (void) setupPhysics; +- (void) applyLinearImpulseX:(float)xNs y:(float)yNs; + + +@optional +- (void) onCollideBegin:(QQContactNotification*)msg; +- (void) onCollideEnd:(QQContactNotification*)msg; + @end \ No newline at end of file diff --git a/src/game/QQThing.h b/src/game/QQThing.h index a259237..e10aa65 100644 --- a/src/game/QQThing.h +++ b/src/game/QQThing.h @@ -1,10 +1,12 @@ +#import "qq/QQObservable.h" + @class QQGame; @class QQWorld; /** * Anything in the game-world. */ -@protocol QQThing +@protocol QQThing @property (nonatomic, readonly) QQGame* game; @property (nonatomic, readonly) QQWorld* world; diff --git a/src/game/ability/QQCooldown.h b/src/game/ability/QQCooldown.h index 490a473..63fd4cd 100644 --- a/src/game/ability/QQCooldown.h +++ b/src/game/ability/QQCooldown.h @@ -1,3 +1,4 @@ +#import "game/QQGameTime.h" /** @@ -38,7 +39,7 @@ * Advances the timer by {elapsed} milliseconds, updating ready state if necessary. * @return Ready state. */ -- (BOOL) tick:(float)elapsed; +- (BOOL) tick:(id)time; + (QQCooldown*) cooldownWithDuration:(float)duration; diff --git a/src/game/ability/QQCooldown.mm b/src/game/ability/QQCooldown.mm index 72d9934..0949e5d 100644 --- a/src/game/ability/QQCooldown.mm +++ b/src/game/ability/QQCooldown.mm @@ -62,10 +62,10 @@ * Advances the timer by {elapsed} milliseconds, updating ready state if necessary. * @return Ready state. */ -- (BOOL) tick:(float)elapsed { +- (BOOL) tick:(id)time { if (self.ready) return YES; - self.elapsed += elapsed; + self.elapsed += time.elapsed; return self.ready; } diff --git a/src/game/actor/QQActor.h b/src/game/actor/QQActor.h index 383b243..4eaaf09 100644 --- a/src/game/actor/QQActor.h +++ b/src/game/actor/QQActor.h @@ -1,4 +1,6 @@ #include + +#import "qq/QQNotificationProxy.h" #import "game/QQThing.h" #import "game/QQActive.h" #import "game/QQPhysical.h" @@ -9,7 +11,7 @@ @class QQGame; -@interface QQActor : NSObject { +@interface QQActor : QQNotificationProxy { @protected b2Body* _body; @@ -17,16 +19,22 @@ @private BOOL _active; BOOL _dirty; + BOOL _dead; id _delegate; + NSArray* _cooldowns; } @property (nonatomic, readonly) QQGame* game; @property (nonatomic, readonly) QQWorld* world; @property (nonatomic, readwrite, retain) id delegate; +@property (nonatomic, readonly) BOOL dead; - (id) initAtX:(float)x y:(float)y; - (id) initType:(b2BodyType)type atX:(float)x y:(float)y; +- (void) destroy; + + /// internal methods /** Updates the Shape using values from Box2D. */ diff --git a/src/game/actor/QQActor.mm b/src/game/actor/QQActor.mm index 3c6b7a0..241226b 100644 --- a/src/game/actor/QQActor.mm +++ b/src/game/actor/QQActor.mm @@ -7,12 +7,14 @@ /// properties -@synthesize active = _active; -@synthesize dirty = _dirty; -@synthesize delegate = _delegate; - @dynamic shape; +@synthesize active = _active; +@synthesize dirty = _dirty; +@synthesize dead = _dead; +@synthesize delegate = _delegate; +@synthesize cooldowns = _cooldowns; + - (QQGame*) game { return QQGame.current; } - (QQWorld*) world { return self.game.world; } @@ -20,8 +22,18 @@ - (b2Body*) body { return _body; } - (b2Fixture*) fixture { return nil; } -- (float) rotation { return self.body->GetAngle(); } -- (void) setRotation:(float)r { self.body->SetTransform(self.body->GetPosition(), r); } +- (id) implicitNotificationSender { return self; } +- (void) setImplicitNotificationSender:(id)sender {} + +- (id) proxiedNotifier { return self.game; } +- (void) setProxiedNotifier:(id)notifier {} + + +- (float) x { return self.body->GetPosition().x; } +- (void) setX:(float)x { [self setPositionX:x y:self.y]; } + +- (float) y { return self.body->GetPosition().y; } +- (void) setY:(float)y { [self setPositionX:self.x y:y]; } - (CGPoint) position { b2Vec2 pos = self.body->GetPosition(); @@ -34,6 +46,10 @@ self.body->SetTransform(b2Vec2(x,y), self.body->GetAngle()); } +- (float) rotation { return self.body->GetAngle(); } +- (void) setRotation:(float)r { self.body->SetTransform(self.body->GetPosition(), r); } + + - (void) updateShapeX:(float)x y:(float)y { float px = self.world.scale; [self.shape setCenterX:x*px y:y*px]; @@ -50,12 +66,6 @@ } -- (float) x { return self.body->GetPosition().x; } -- (void) setX:(float)x { [self setPositionX:x y:self.y]; } - -- (float) y { return self.body->GetPosition().y; } -- (void) setY:(float)y { [self setPositionX:self.x y:y]; } - /// initializers @@ -65,6 +75,10 @@ - (id) initType:(b2BodyType)type atX:(float)x y:(float)y { if ((self = [super init])) { + _active = YES; + _dead = NO; + self.proxiedNotifier = self.game; + self.cooldowns = [NSArray array]; [self.game addActor:self]; b2BodyDef bd; @@ -72,15 +86,38 @@ bd.position = b2Vec2(x, y); bd.userData = self; _body = self.world.world->CreateBody(&bd); + + if ([self respondsToSelector:@selector(onCollideBegin:)]) + [self addObserver:self selector:@selector(onCollideBegin:) name:QQ_EVENT_CONTACT_BEGIN]; } return self; } +- (void) dealloc { + self.delegate = nil; + [_cooldowns release]; + [super dealloc]; +} + + /// methods -- (void) tick:(float)elapsed { - [self act]; +- (void) destroy { + NSLog(@"retainCount=%i", [self retainCount]); + if (!self.dead) { + _dead = YES; + self.shape = nil; + [self.game destroyActor:self]; + NSLog(@"%@ \v\tretainCount=%i \v\tgame=%@", self, [self retainCount], self.game); + } +} + +- (void) tick { + if (!self.dead) { + [self.cooldowns makeObjectsPerformSelector:@selector(tick:)withObject:self.game.time]; + if (self.isActive) [self act]; + } } - (void) act {} @@ -95,6 +132,12 @@ - (void) setupPhysics {} + +- (void) applyLinearImpulseX:(float)xNs y:(float)yNs { + self.body->ApplyLinearImpulse(b2Vec2(xNs, yNs), self.body->GetPosition()); +} + + - (NSString*) description { b2Transform trans = self.body->GetTransform(); b2Vec2 pos = trans.position; diff --git a/src/game/actor/QQActors.h b/src/game/actor/QQActors.h index bd83bb5..f7bad80 100644 --- a/src/game/actor/QQActors.h +++ b/src/game/actor/QQActors.h @@ -1,5 +1,5 @@ -#import "QQActor.h" -#import "QQActorDelegate.h" -#import "QQUnit.h" -#import "bullet/QQBullet.h" -#import "unit/QQTank.h" +#import "game/actor/QQActor.h" +#import "game/actor/QQActorDelegate.h" +#import "game/actor/QQUnit.h" +#import "game/actor/bullet/QQBullet.h" +#import "game/actor/unit/QQTank.h" diff --git a/src/game/actor/QQUnit.mm b/src/game/actor/QQUnit.mm index b09e9f1..f68c5fc 100644 --- a/src/game/actor/QQUnit.mm +++ b/src/game/actor/QQUnit.mm @@ -51,7 +51,7 @@ } - (void) dealloc { - [self.game removeChild:_shape]; + [self.game.level removeChild:_shape]; [_shape release]; [super dealloc]; } @@ -64,8 +64,10 @@ [_shape release]; _shape = [newShape retain]; - [self updateShape]; - [self.game.level addChild:_shape]; + if (_shape) { + [self updateShape]; + [self.game.level addChild:_shape]; + } } } diff --git a/src/game/actor/bullet/QQBullet.h b/src/game/actor/bullet/QQBullet.h index 6d66f6b..4a61675 100644 --- a/src/game/actor/bullet/QQBullet.h +++ b/src/game/actor/bullet/QQBullet.h @@ -10,6 +10,5 @@ - (id) init:(QQUnit*)owner x:(float)x y:(float)y; -- (void) applyLinearImpulseX:(float)xNs y:(float)yNs; @end diff --git a/src/game/actor/bullet/QQBullet.mm b/src/game/actor/bullet/QQBullet.mm index 597e347..99b3f42 100644 --- a/src/game/actor/bullet/QQBullet.mm +++ b/src/game/actor/bullet/QQBullet.mm @@ -2,6 +2,7 @@ #import "SparrowExtras.h" #import "QQBullet.h" +#import "physics/event/QQContactNotification.h" @@ -29,8 +30,18 @@ return self; } -- (void) applyLinearImpulseX:(float)xNs y:(float)yNs { - self.body->ApplyLinearImpulse(b2Vec2(xNs, yNs), self.body->GetPosition()); +- (void) onCollideBegin:(QQContactNotification*)msg { + QQActor* other = (msg.actorA && (msg.actorA != self) ? msg.actorA : + (msg.actorB && (msg.actorB != self) ? msg.actorB : nil)); + if (other) { + NSLog(@"BOOM! %@", msg); + [other destroy]; + [self destroy]; + } +} + +- (void) dealloc { + [super dealloc]; } diff --git a/src/game/actor/unit/QQTank.mm b/src/game/actor/unit/QQTank.mm index fa94b81..4b2622b 100644 --- a/src/game/actor/unit/QQTank.mm +++ b/src/game/actor/unit/QQTank.mm @@ -1,5 +1,6 @@ #import "QQTank.h" #import "render/QQSparrowExtensions.h" +#import "game/QQGame.h" #import "game/actor/bullet/QQBullet.h" @@ -18,23 +19,21 @@ - (id) initAtX:(float)x y:(float)y withShape:(SPDisplayObject*)shape { if ((self = [super initAtX:x y:y withShape:shape])){ self.coolAtk = [QQCooldown cooldownWithDuration:0.5f]; - [self.game addEventListener:@selector(onTouch:) atObject:self forType:SP_EVENT_TYPE_TOUCH]; + self.cooldowns = [self.cooldowns arrayByAddingObject:self.coolAtk]; + [self.game.stage addEventListener:@selector(onTouch:) atObject:self forType:SP_EVENT_TYPE_TOUCH]; } return self; } - (void) dealloc { - [self.game removeEventListener:@selector(onTouch:) atObject:self forType:SP_EVENT_TYPE_TOUCH]; + [self.game.stage removeEventListener:@selector(onTouch:) atObject:self forType:SP_EVENT_TYPE_TOUCH]; + [_coolAtk release]; [super dealloc]; } -- (void) tick:(float)elapsed { - [self.coolAtk tick:elapsed]; - [super tick:elapsed]; -} - (void) onTouch:(SPTouchEvent*)event { - SPTouch* touch = [[event touchesWithTarget:(SPDisplayObject*)self.game] anyObject]; + SPTouch* touch = [[event touchesWithTarget:(SPDisplayObject*)self.game.stage] anyObject]; if (touch && [self.coolAtk activate]) { // Touch's normal vector in local coords (rel unit origin) SPPoint* normVec = [[[touch locationInSpace:self.shape.parent] subtractPoint:self.shape.position] normalize]; @@ -51,7 +50,7 @@ } } -- (void) moveOnTouch:(SPTouchEvent*)event { +- (void) _moveOnTouch:(SPTouchEvent*)event { SPTouch* touch = [[event touchesWithTarget:self.shape.parent] anyObject]; if (touch) { SPPoint* touchPosition = [touch locationInSpace:self.shape.parent]; diff --git a/src/physics/QQWorld.h b/src/physics/QQWorld.h index c5ae17d..3b47e73 100644 --- a/src/physics/QQWorld.h +++ b/src/physics/QQWorld.h @@ -1,26 +1,27 @@ #include -#import "qq/QQObservable.h" #import "qq/QQNotifier.h" +#import "qq/QQNotificationProxy.h" #import "physics/event/QQPhysicalEvents.h" #import "physics/debug/QQGLESDebugDraw.h" +#import "game/QQPhysical.h" -@interface QQWorld : NSObject { + +@interface QQWorld : QQNotificationProxy { @private - QQGLESDebugDraw* _debugDraw; - QQContactListener _contactListener; - b2World* _world; - - NSNotificationCenter* _center; - - NSMutableArray* _walls; // Array of NSValue - float _timestep; int _velocityIterations; int _positionIterations; float _scale; + + b2World* _world; + QQContactListener _contactListener; + QQGLESDebugDraw* _debugDraw; + + NSMutableArray* _walls; // Array of NSValue + NSMutableSet* _trash; } @property (nonatomic, readonly) b2World* world; @@ -39,5 +40,6 @@ - (void) step; - (void) drawDebug; +- (void) destroy:(id)actor; @end diff --git a/src/physics/QQWorld.mm b/src/physics/QQWorld.mm index 9e663ae..02cf916 100644 --- a/src/physics/QQWorld.mm +++ b/src/physics/QQWorld.mm @@ -5,8 +5,12 @@ #import "physics/event/QQContactNotification.h" + + // private interface @interface QQWorld () +@property (nonatomic, readonly, getter=isDeleteLocked) bool deleteLocked; + - (void) postContactNotification:(b2Contact*)contact event:(NSString*)evt; - (void) createWalls; @end @@ -28,7 +32,6 @@ _velocityIterations = 10; _positionIterations = 10; _scale = 5.0f; - _center = [[NSNotificationCenter alloc] init]; _world = new b2World(b2Vec2(0.0f, 0.0f), true); // b2World(gravity, doSleep) @@ -39,16 +42,17 @@ _debugDraw->SetAllFlags(); _world->SetDebugDraw(_debugDraw); + _trash = [[NSMutableSet alloc] initWithCapacity:4]; _walls = [[NSMutableArray alloc] initWithCapacity:4]; // Array of NSValue + [self createWalls]; } return self; } - (void) dealloc { - [_walls removeAllObjects]; - [_walls release]; - [_center release]; + [_walls removeAllObjects]; [_walls release]; + [_trash removeAllObjects]; [_trash release]; delete _debugDraw; delete _world; // b2World destructor destroys all physics entities and releases all heap memory. [super dealloc]; @@ -88,9 +92,22 @@ } } +- (bool) isDeleteLocked { + return _world->IsLocked(); +} - (void) step { _world->Step(self.timestep, self.velocityIterations, self.positionIterations); + if (self.isDeleteLocked) { + NSLog(@"wtf! still delete-locked after step completed!"); + #ifdef DEBUG + [NSException raise:@"WTFWorldStillDeleteLocked" format:@"World still delete-locked after step completed!"]; + #endif + } else if ([_trash count] > 0) { + for (id actor in _trash) + [self destroy:actor]; + [_trash removeAllObjects]; + } } - (void) drawDebug { @@ -101,6 +118,20 @@ _world->SetGravity(b2Vec2(x,y)); } +- (void) destroy:(id)actor { + if (self.isDeleteLocked) { + [_trash addObject:actor]; + } else { + if (actor.fixture) { + actor.fixture->GetBody()->DestroyFixture(actor.fixture); + } else if (actor.body) { + _world->DestroyBody(actor.body); + } else { + NSLog(@"wtf! Cannot destroy actor with no body or fixture! %@", actor); + } + } +} + /// QQContactNotifier @@ -124,51 +155,4 @@ } - -/// observable - -- (void) addObserver:(id)observer selector:(SEL)selector name:(NSString*)event { - [self addObserver:observer selector:selector name:event object:self]; -} - -// Remove a listener from this object -- (void) removeObserver:(id)observer { - [self removeObserver:observer name:nil object:self]; -} -- (void) removeObserver:(id)observer name:(NSString*)event { - [self removeObserver:observer name:event object:self]; -} - -// Send a notification from this object -- (void) postNotificationName:(NSString*)name { - [self postNotificationName:name object:self]; -} -- (void) postNotificationName:(NSString*)name userInfo:(NSDictionary*)info { - [self postNotificationName:name object:self userInfo:info]; -} - - -/// notifier - -- (void) addObserver:(id)observer selector:(SEL)selector name:(NSString*)event object:(id)sender { - [_center addObserver:observer selector:selector name:event object:sender]; -} - -- (void) removeObserver:(id)observer name:(NSString*)event object:(id)sender { - [_center removeObserver:observer name:event object:sender]; -} -- (void) removeObservers:(id)observer { - [_center removeObserver:observer]; -} - -- (void) postNotification:(NSNotification*)msg { - [_center postNotification:msg]; -} -- (void) postNotificationName:(NSString*)name object:(id)sender { - [_center postNotificationName:name object:sender]; -} -- (void) postNotificationName:(NSString*)name object:(id)sender userInfo:(NSDictionary*)info { - [_center postNotificationName:name object:sender userInfo:info]; -} - @end diff --git a/src/physics/event/QQContactNotification.mm b/src/physics/event/QQContactNotification.mm index 2f36a4b..76911ed 100644 --- a/src/physics/event/QQContactNotification.mm +++ b/src/physics/event/QQContactNotification.mm @@ -13,11 +13,12 @@ - (id) initWithName:(NSString*)name object:(id)obj userInfo:(NSDictionary*)info contact:(b2Contact*)contact { if ((self = [super initWithName:name object:obj userInfo:info])) { _contact = contact; + [[self.actorA retain] autorelease]; + [[self.actorB retain] autorelease]; } return self; } - @synthesize contact = _contact; - (QQActor*) actorA { @@ -42,7 +43,7 @@ - (NSString*) description { - return [NSString stringWithFormat:@"[%@ actorA=%@, actorB=%@]", + return [NSString stringWithFormat:@"[%@ \v\tactorA=%@, \v\tactorB=%@]", [super description], self.actorA, self.actorB]; } diff --git a/src/qq/NSSet+QQExtensions.h b/src/qq/NSSet+QQExtensions.h new file mode 100644 index 0000000..80780dd --- /dev/null +++ b/src/qq/NSSet+QQExtensions.h @@ -0,0 +1,8 @@ + +@interface NSSet (QQExtensions) + +- (NSSet*) setByRemovingObject:(id)object; +- (NSSet*) setByRemovingArray:(NSArray*)objects; + + +@end diff --git a/src/qq/NSSet+QQExtensions.mm b/src/qq/NSSet+QQExtensions.mm new file mode 100644 index 0000000..6b4d74c --- /dev/null +++ b/src/qq/NSSet+QQExtensions.mm @@ -0,0 +1,15 @@ +@implementation NSSet (QQExtensions) + +- (NSSet*) setByRemovingObject:(id)object { + // (BOOL (^)(id obj, BOOL *stop))predicate + return [self objectsPassingTest:^(id item, BOOL *stop){ + return (BOOL) (item != object); + }]; +} +- (NSSet*) setByRemovingArray:(NSArray*)objects { + return [self objectsPassingTest:^(id item, BOOL *stop){ + return (BOOL) ![objects containsObject:item]; + }]; +} + +@end diff --git a/src/qq/QQNotificationCenter.h b/src/qq/QQNotificationCenter.h new file mode 100644 index 0000000..65c60ec --- /dev/null +++ b/src/qq/QQNotificationCenter.h @@ -0,0 +1,16 @@ +#import "qq/QQNotifier.h" + +@interface QQNotificationCenter : NSNotificationCenter { +@private + id _implicitNotificationSender; +} +/** Object used for implicit sender when adding or removing observers. */ +@property (nonatomic, readwrite, retain) id implicitNotificationSender; + +/** Initialize with self as implicit sender. */ +- (id) init; + +/** Returns a center with given implicit target. A nil target will subscript observers to all objects. */ ++ (QQNotificationCenter*) notifierWithTarget:(id)target; + +@end diff --git a/src/qq/QQNotificationCenter.mm b/src/qq/QQNotificationCenter.mm new file mode 100644 index 0000000..232c794 --- /dev/null +++ b/src/qq/QQNotificationCenter.mm @@ -0,0 +1,69 @@ +#import "qq/QQNotificationCenter.h" + + +@implementation QQNotificationCenter + +- (id) init { + if ((self = [super init])){ + _implicitNotificationSender = self; + } + return self; +} + +- (void) dealloc { + [_implicitNotificationSender release]; + [super dealloc]; +} + +@synthesize implicitNotificationSender = _implicitNotificationSender; + + +/// observable + +- (void) addObserver:(id)observer selector:(SEL)selector name:(NSString*)event { + [self addObserver:observer selector:selector name:event object:self.implicitNotificationSender]; +} + +// Remove a listener from this object +- (void) removeObserver:(id)observer { + [self removeObserver:observer name:nil object:self.implicitNotificationSender]; +} +- (void) removeObserver:(id)observer name:(NSString*)event { + [self removeObserver:observer name:event object:self.implicitNotificationSender]; +} + +// Send a notification from this object +- (void) postNotificationName:(NSString*)name { + [self postNotificationName:name object:self.implicitNotificationSender]; +} +- (void) postNotificationName:(NSString*)name userInfo:(NSDictionary*)info { + [self postNotificationName:name object:self.implicitNotificationSender userInfo:info]; +} + + +/// notifier + +- (void) removeObservers:(id)observer { + [super removeObserver:observer]; +} + + +/// NSNotificationCenter (superclass) provides: + +// - (void) addObserver:(id)observer selector:(SEL)selector name:(NSString*)event object:(id)sender +// - (void) removeObserver:(id)observer name:(NSString*)event object:(id)sender +// - (void) postNotification:(NSNotification*)msg +// - (void) postNotificationName:(NSString*)name object:(id)sender +// - (void) postNotificationName:(NSString*)name object:(id)sender userInfo:(NSDictionary*)info + +// as well as... +// - (id)addObserverForName:(NSString *)name object:(id)obj queue:(NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *))block + + ++ (QQNotificationCenter*) notifierWithTarget:(id)target { + QQNotificationCenter* notifier = [[[QQNotificationCenter alloc] init] autorelease]; + notifier.implicitNotificationSender = target; + return notifier; +} + +@end diff --git a/src/qq/QQNotificationProxy.h b/src/qq/QQNotificationProxy.h new file mode 100644 index 0000000..4b99c54 --- /dev/null +++ b/src/qq/QQNotificationProxy.h @@ -0,0 +1,16 @@ +#import "qq/QQNotifier.h" + +/** + * Proxies all QQObservableNotifier calls to another QQObservableNotifier. + */ +@interface QQNotificationProxy : NSObject { +@private + id _proxiedNotifier; + id _implicitNotificationSender; +} + +@property (nonatomic, readwrite, retain) id proxiedNotifier; + +- (id) initWithNotifier:(id)notifier; + +@end diff --git a/src/qq/QQNotificationProxy.mm b/src/qq/QQNotificationProxy.mm new file mode 100644 index 0000000..39b4697 --- /dev/null +++ b/src/qq/QQNotificationProxy.mm @@ -0,0 +1,70 @@ +#import "qq/QQNotificationProxy.h" + + +@implementation QQNotificationProxy + +@synthesize proxiedNotifier = _proxiedNotifier; +@synthesize implicitNotificationSender = _implicitNotificationSender; + + +- (id) initWithNotifier:(id)notifier { + if ((self = [super init])){ + self.proxiedNotifier = notifier; + } + return self; +} + +- (void) dealloc { + self.proxiedNotifier = nil; + [super dealloc]; +} + +/// observable + +- (void) addObserver:(id)observer selector:(SEL)selector name:(NSString*)event { + [self addObserver:observer selector:selector name:event object:self.implicitNotificationSender]; +} + +// Remove a listener from this object +- (void) removeObserver:(id)observer { + [self removeObserver:observer name:nil object:self.implicitNotificationSender]; +} +- (void) removeObserver:(id)observer name:(NSString*)event { + [self removeObserver:observer name:event object:self.implicitNotificationSender]; +} + +// Send a notification from this object +- (void) postNotificationName:(NSString*)name { + [self postNotificationName:name object:self.implicitNotificationSender]; +} +- (void) postNotificationName:(NSString*)name userInfo:(NSDictionary*)info { + [self postNotificationName:name object:self.implicitNotificationSender userInfo:info]; +} + + +/// notifier + +- (void) addObserver:(id)observer selector:(SEL)selector name:(NSString*)event object:(id)sender { + [self.proxiedNotifier addObserver:observer selector:selector name:event object:sender]; +} + +- (void) removeObserver:(id)observer name:(NSString*)event object:(id)sender { + [self.proxiedNotifier removeObserver:observer name:event object:sender]; +} +- (void) removeObservers:(id)observer { + [self.proxiedNotifier removeObserver:observer]; +} + +- (void) postNotification:(NSNotification*)msg { + [self.proxiedNotifier postNotification:msg]; +} +- (void) postNotificationName:(NSString*)name object:(id)sender { + [self.proxiedNotifier postNotificationName:name object:sender]; +} +- (void) postNotificationName:(NSString*)name object:(id)sender userInfo:(NSDictionary*)info { + [self.proxiedNotifier postNotificationName:name object:sender userInfo:info]; +} + + + +@end diff --git a/src/qq/QQNotifier.h b/src/qq/QQNotifier.h index 839154f..1ca2a5d 100644 --- a/src/qq/QQNotifier.h +++ b/src/qq/QQNotifier.h @@ -1,11 +1,21 @@ #import "qq/QQObservable.h" -@protocol QQNotifier +@protocol QQNotifier + +/** + * Adds an observer of specified object. + * + * A nil name means observer will be notified of all events for specified object. + * A nil object means observer will be notified of all events for specified name. + * An observer specifying nil for both name and object will be notified of all events. + */ - (void) addObserver:(id)observer selector:(SEL)selector name:(NSString*)event object:(id)sender; - (void) removeObserver:(id)observer name:(NSString*)event object:(id)sender; -- (void) removeObservers:(id)observer; // remove all from all objects + +/** Removes observer from all subscribed notices. */ +- (void) removeObservers:(id)observer; - (void) postNotification:(NSNotification*)msg; - (void) postNotificationName:(NSString*)name object:(id)sender; @@ -13,3 +23,7 @@ @end + +@protocol QQObservableNotifier + +@end \ No newline at end of file diff --git a/src/qq/QQNotifiers.h b/src/qq/QQNotifiers.h new file mode 100644 index 0000000..f36c283 --- /dev/null +++ b/src/qq/QQNotifiers.h @@ -0,0 +1,42 @@ +/** + * Various macros relating to notification dispatch. + */ + +/** + * As a QQNotificationProxy, but via encapsulation. + */ +#define qqNotifierProxy(__target, __notifier) \ +- (void) addObserver:(id)observer selector:(SEL)selector name:(NSString*)event { \ + [self addObserver:observer selector:selector name:event object:__target]; \ +} \ +- (void) removeObserver:(id)observer { \ + [self removeObserver:observer name:nil object:__target]; \ +} \ +- (void) removeObserver:(id)observer name:(NSString*)event { \ + [self removeObserver:observer name:event object:__target]; \ +} \ +- (void) postNotificationName:(NSString*)name { \ + [self postNotificationName:name object:__target]; \ +} \ +- (void) postNotificationName:(NSString*)name userInfo:(NSDictionary*)info { \ + [self postNotificationName:name object:__target userInfo:info]; \ +} \ +- (void) addObserver:(id)observer selector:(SEL)selector name:(NSString*)event object:(id)sender { \ + [__notifier addObserver:observer selector:selector name:event object:sender]; \ +} \ +- (void) removeObserver:(id)observer name:(NSString*)event object:(id)sender { \ + [__notifier removeObserver:observer name:event object:sender]; \ +} \ +- (void) removeObservers:(id)observer { \ + [__notifier removeObserver:observer]; \ +} \ +- (void) postNotification:(NSNotification*)msg { \ + [__notifier postNotification:msg]; \ +} \ +- (void) postNotificationName:(NSString*)name object:(id)sender { \ + [__notifier postNotificationName:name object:sender]; \ +} \ +- (void) postNotificationName:(NSString*)name object:(id)sender userInfo:(NSDictionary*)info { \ + [__notifier postNotificationName:name object:sender userInfo:info]; \ +} + diff --git a/src/qq/QQObject.h b/src/qq/QQObject.h deleted file mode 100644 index e1a151f..0000000 --- a/src/qq/QQObject.h +++ /dev/null @@ -1,10 +0,0 @@ - - -@interface QQObject : NSObject { -@private - -} - - - -@end diff --git a/src/qq/QQObject.mm b/src/qq/QQObject.mm deleted file mode 100644 index 9bd7ea9..0000000 --- a/src/qq/QQObject.mm +++ /dev/null @@ -1,12 +0,0 @@ -#import "QQObject.h" - - -@implementation QQObject - -- (id) init { - if ((self = [super init])){ - - } - return self; -} -@end diff --git a/src/qq/QQObservable.h b/src/qq/QQObservable.h index ff4e25d..8814775 100644 --- a/src/qq/QQObservable.h +++ b/src/qq/QQObservable.h @@ -4,6 +4,9 @@ * that would normally take an object if the call was made to an NSNotificationCenter. */ @protocol QQObservable + +@property (nonatomic, readwrite, retain) id implicitNotificationSender; + //- (void) observe:(NSString*)event notify:(id)observer selector:(SEL)selector; /** Adds an observer of this object. */ diff --git a/src/ui/QQAppDelegate.h b/src/ui/QQAppDelegate.h index 10b0e32..2b2e6e4 100644 --- a/src/ui/QQAppDelegate.h +++ b/src/ui/QQAppDelegate.h @@ -6,16 +6,13 @@ @interface QQAppDelegate : NSObject { @private - UIApplication* _app; UIWindow* window; SPView* sparrowView; - // QQPhysicsDebugView* _debugView; QQGame* _game; } -@property (nonatomic, retain) IBOutlet UIWindow* window; -@property (nonatomic, retain) IBOutlet SPView* sparrowView; -// @property (nonatomic, retain) QQPhysicsDebugView* debugView; -@property (nonatomic, retain) QQGame* game; +@property (nonatomic, readwrite, retain) IBOutlet UIWindow* window; +@property (nonatomic, readwrite, retain) IBOutlet SPView* sparrowView; +@property (nonatomic, readwrite, retain) QQGame* game; @end \ No newline at end of file diff --git a/src/ui/QQAppDelegate.mm b/src/ui/QQAppDelegate.mm index 9d65e17..5cf6f75 100644 --- a/src/ui/QQAppDelegate.mm +++ b/src/ui/QQAppDelegate.mm @@ -16,37 +16,34 @@ @synthesize game = _game; -- (void) applicationDidFinishLaunching:(UIApplication*)application { - _app = application; - _app.statusBarHidden = YES; - +- (void) applicationDidFinishLaunching:(UIApplication*)app { SP_CREATE_POOL(pool); + [app setStatusBarHidden:YES]; [SPStage setSupportHighResolutions:YES]; - [SPAudioEngine start]; if ( sparrowView.frameRate != 60.0f ) sparrowView.frameRate = 60.0f; - self.game = [[[QQGame alloc] init] autorelease]; - sparrowView.stage = _game; + self.game = [QQGame current]; + sparrowView.stage = _game.stage; [_game start]; [window makeKeyAndVisible]; [sparrowView start]; + [SPAudioEngine start]; SP_RELEASE_POOL(pool); } -- (void) applicationWillResignActive:(UIApplication*)application { +- (void) applicationWillResignActive:(UIApplication*)app { [sparrowView stop]; } -- (void) applicationDidBecomeActive:(UIApplication*)application { +- (void) applicationDidBecomeActive:(UIApplication*)app { [sparrowView start]; } - (void) dealloc { - _app = nil; [_game release]; [sparrowView release]; [window release]; diff --git a/tanks.xcodeproj/project.pbxproj b/tanks.xcodeproj/project.pbxproj index 236f4b9..79377d3 100644 --- a/tanks.xcodeproj/project.pbxproj +++ b/tanks.xcodeproj/project.pbxproj @@ -54,10 +54,17 @@ 49966919136930E8006E8125 /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49966914136930E8006E8125 /* OpenAL.framework */; }; 4996691A136930E8006E8125 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49966915136930E8006E8125 /* OpenGLES.framework */; }; 4996691B136930E8006E8125 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49966916136930E8006E8125 /* QuartzCore.framework */; }; + 499D6A9C1399BFB8008E4C0D /* QQNotificationCenter.h in Headers */ = {isa = PBXBuildFile; fileRef = 499D6A981399BFB8008E4C0D /* QQNotificationCenter.h */; }; + 499D6A9D1399BFB8008E4C0D /* QQNotificationCenter.mm in Sources */ = {isa = PBXBuildFile; fileRef = 499D6A991399BFB8008E4C0D /* QQNotificationCenter.mm */; }; + 499D6A9E1399BFB8008E4C0D /* QQNotificationProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 499D6A9A1399BFB8008E4C0D /* QQNotificationProxy.h */; }; + 499D6A9F1399BFB8008E4C0D /* QQNotificationProxy.mm in Sources */ = {isa = PBXBuildFile; fileRef = 499D6A9B1399BFB8008E4C0D /* QQNotificationProxy.mm */; }; 49D8645D1392DB2800BC341C /* QQShape.h in Headers */ = {isa = PBXBuildFile; fileRef = 49D8645B1392DB2800BC341C /* QQShape.h */; }; 49D8645E1392DB2800BC341C /* QQShape.mm in Sources */ = {isa = PBXBuildFile; fileRef = 49D8645C1392DB2800BC341C /* QQShape.mm */; }; 49DA67D4137847A7004841E9 /* QQWorld.h in Headers */ = {isa = PBXBuildFile; fileRef = 49DA67D2137847A7004841E9 /* QQWorld.h */; }; 49DA67D5137847A7004841E9 /* QQWorld.mm in Sources */ = {isa = PBXBuildFile; fileRef = 49DA67D3137847A7004841E9 /* QQWorld.mm */; }; + 49E3C5D2139A73E700A3958A /* NSSet+QQExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 49E3C5D0139A73E700A3958A /* NSSet+QQExtensions.h */; }; + 49E3C5D3139A73E700A3958A /* NSSet+QQExtensions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 49E3C5D1139A73E700A3958A /* NSSet+QQExtensions.mm */; }; + 49E67E11139B341600DDFC07 /* TanksMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 49E67E10139B341600DDFC07 /* TanksMacros.h */; }; 49E834A713812427007A6598 /* QQActive.h in Headers */ = {isa = PBXBuildFile; fileRef = 49E8349E13812427007A6598 /* QQActive.h */; }; 49E834A813812427007A6598 /* QQActor.h in Headers */ = {isa = PBXBuildFile; fileRef = 49E834A013812427007A6598 /* QQActor.h */; }; 49E834A913812427007A6598 /* QQActor.mm in Sources */ = {isa = PBXBuildFile; fileRef = 49E834A113812427007A6598 /* QQActor.mm */; }; @@ -265,10 +272,17 @@ 49966914136930E8006E8125 /* OpenAL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenAL.framework; path = System/Library/Frameworks/OpenAL.framework; sourceTree = SDKROOT; }; 49966915136930E8006E8125 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; 49966916136930E8006E8125 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; + 499D6A981399BFB8008E4C0D /* QQNotificationCenter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQNotificationCenter.h; sourceTree = ""; }; + 499D6A991399BFB8008E4C0D /* QQNotificationCenter.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = QQNotificationCenter.mm; sourceTree = ""; }; + 499D6A9A1399BFB8008E4C0D /* QQNotificationProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQNotificationProxy.h; sourceTree = ""; }; + 499D6A9B1399BFB8008E4C0D /* QQNotificationProxy.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = QQNotificationProxy.mm; sourceTree = ""; }; 49D8645B1392DB2800BC341C /* QQShape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQShape.h; sourceTree = ""; }; 49D8645C1392DB2800BC341C /* QQShape.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = QQShape.mm; sourceTree = ""; }; 49DA67D2137847A7004841E9 /* QQWorld.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQWorld.h; sourceTree = ""; }; 49DA67D3137847A7004841E9 /* QQWorld.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = QQWorld.mm; sourceTree = ""; }; + 49E3C5D0139A73E700A3958A /* NSSet+QQExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSSet+QQExtensions.h"; sourceTree = ""; }; + 49E3C5D1139A73E700A3958A /* NSSet+QQExtensions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSSet+QQExtensions.mm"; sourceTree = ""; }; + 49E67E10139B341600DDFC07 /* TanksMacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TanksMacros.h; sourceTree = ""; }; 49E8349E13812427007A6598 /* QQActive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQActive.h; sourceTree = ""; }; 49E834A013812427007A6598 /* QQActor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQActor.h; sourceTree = ""; }; 49E834A113812427007A6598 /* QQActor.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = QQActor.mm; sourceTree = ""; }; @@ -483,6 +497,12 @@ 4978AD1E1396302E00930447 /* qq */ = { isa = PBXGroup; children = ( + 49E3C5D0139A73E700A3958A /* NSSet+QQExtensions.h */, + 49E3C5D1139A73E700A3958A /* NSSet+QQExtensions.mm */, + 499D6A981399BFB8008E4C0D /* QQNotificationCenter.h */, + 499D6A991399BFB8008E4C0D /* QQNotificationCenter.mm */, + 499D6A9A1399BFB8008E4C0D /* QQNotificationProxy.h */, + 499D6A9B1399BFB8008E4C0D /* QQNotificationProxy.mm */, 4978AD1F1396302F00930447 /* QQNotification.h */, 4978AD201396302F00930447 /* QQNotification.mm */, 4978AD211396302F00930447 /* QQNotifier.h */, @@ -623,9 +643,9 @@ 492D80ED138BA4BC0042D918 /* bullet */, 492D80E8138BA4B40042D918 /* unit */, 4978AD0D1395E5CE00930447 /* QQActors.h */, + 492D80FE138BCC9F0042D918 /* QQActorDelegate.h */, 49E834A013812427007A6598 /* QQActor.h */, 49E834A113812427007A6598 /* QQActor.mm */, - 492D80FE138BCC9F0042D918 /* QQActorDelegate.h */, 49E834A213812427007A6598 /* QQUnit.h */, 492D80FC138BCA840042D918 /* QQUnit.mm */, ); @@ -695,6 +715,7 @@ 49F2D9B013764666000B6B8C /* main.mm */, 49F2D9B213764666000B6B8C /* prefix.pch */, 4978AD131396139100930447 /* Tanks.h */, + 49E67E10139B341600DDFC07 /* TanksMacros.h */, ); path = src; sourceTree = ""; @@ -1055,6 +1076,10 @@ 4978AD251396302F00930447 /* QQNotification.h in Headers */, 4978AD271396302F00930447 /* QQNotifier.h in Headers */, 4978AD2A1396302F00930447 /* QQObservable.h in Headers */, + 499D6A9C1399BFB8008E4C0D /* QQNotificationCenter.h in Headers */, + 499D6A9E1399BFB8008E4C0D /* QQNotificationProxy.h in Headers */, + 49E3C5D2139A73E700A3958A /* NSSet+QQExtensions.h in Headers */, + 49E67E11139B341600DDFC07 /* TanksMacros.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1212,6 +1237,9 @@ 4978AD1B1396302300930447 /* QQContactNotification.mm in Sources */, 4978AD1D1396302300930447 /* QQPhysicalEvents.mm in Sources */, 4978AD261396302F00930447 /* QQNotification.mm in Sources */, + 499D6A9D1399BFB8008E4C0D /* QQNotificationCenter.mm in Sources */, + 499D6A9F1399BFB8008E4C0D /* QQNotificationProxy.mm in Sources */, + 49E3C5D3139A73E700A3958A /* NSSet+QQExtensions.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; -- 1.7.0.4