Adds skeletons for Bullet and Tank; adds protocols for abstract classes like Unit
authordsc <david.schoonover@gmail.com>
Tue, 24 May 2011 08:53:40 +0000 (01:53 -0700)
committerdsc <david.schoonover@gmail.com>
Tue, 24 May 2011 08:53:40 +0000 (01:53 -0700)
14 files changed:
libs/box2d/src/Box2D/.gitignore [new file with mode: 0644]
src/game/QQGame.mm
src/game/QQThing.h [new file with mode: 0644]
src/game/ability/QQCooldown.h
src/game/ability/QQCooldown.mm
src/game/actor/QQUnit.h
src/game/actor/QQUnitBase.h [new file with mode: 0644]
src/game/actor/QQUnitBase.mm [new file with mode: 0644]
src/game/actor/bullet/QQBullet.h [new file with mode: 0644]
src/game/actor/bullet/QQBullet.mm [new file with mode: 0644]
src/game/actor/unit/QQTank.h [new file with mode: 0644]
src/game/actor/unit/QQTank.mm [new file with mode: 0644]
src/prefix.pch
tanks.xcodeproj/project.pbxproj

diff --git a/libs/box2d/src/Box2D/.gitignore b/libs/box2d/src/Box2D/.gitignore
new file mode 100644 (file)
index 0000000..5f2ff0e
--- /dev/null
@@ -0,0 +1 @@
+*.pch
index 14ea57f..512e165 100644 (file)
@@ -1,5 +1,5 @@
 #import "QQGame.h"
-#import "game/actor/QQTank.h"
+#import "game/actor/unit/QQTank.h"
 
 
 
diff --git a/src/game/QQThing.h b/src/game/QQThing.h
new file mode 100644 (file)
index 0000000..a259237
--- /dev/null
@@ -0,0 +1,12 @@
+@class QQGame;
+@class QQWorld;
+
+/**
+ * Anything in the game-world.
+ */
+@protocol QQThing
+
+@property (nonatomic, readonly) QQGame*  game;
+@property (nonatomic, readonly) QQWorld* world;
+
+@end
index 596b58e..f58e0a8 100644 (file)
@@ -41,7 +41,7 @@
 - (BOOL) tick:(float)elapsed;
 
 
-+ (QQCooldown) cooldownWithDuration:(float)duration;
-+ (QQCooldown) cooldownWithDuration:(float)duration andReady:(BOOL)ready;
++ (QQCooldown*) cooldownWithDuration:(float)duration;
++ (QQCooldown*) cooldownWithDuration:(float)duration andReady:(BOOL)ready;
 
 @end
index 873bd54..9bf369a 100644 (file)
@@ -15,7 +15,7 @@
     if (newReady)
         self.elapsed = self.duration;
     else
-        self.elapsed = 0f;
+        self.elapsed = 0;
 }
 
 - (float) ratio { return fminf(1.0f, self.elapsed / self.duration); }
@@ -23,7 +23,7 @@
     if (newRatio >= 1.0f)
         self.elapsed = self.duration;
     else if (newRatio <= 0.0f)
-        self.elapsed = 0f;
+        self.elapsed = 0;
     else
         self.elapsed = newRatio * self.duration;
 }
@@ -38,7 +38,7 @@
 - (id) initWithDuration:(float)duration andReady:(BOOL)ready {
     if ((self = [super init])){
         _duration = duration;
-        _elapsed  = (ready ? _duration : 0f);
+        _elapsed  = (ready ? _duration : 0);
     }
     return self;
 }
 
 /// convenience constructors
 
-+ (QQCooldown) cooldownWithDuration:(float)duration {
++ (QQCooldown*) cooldownWithDuration:(float)duration {
     return [[[QQCooldown alloc] initWithDuration:duration] autorelease];
 }
 
-+ (QQCooldown) cooldownWithDuration:(float)duration andReady:(BOOL)ready {
++ (QQCooldown*) cooldownWithDuration:(float)duration andReady:(BOOL)ready {
     return [[[QQCooldown alloc] initWithDuration:duration andReady:ready] autorelease];
 }
 
index 6f05b9a..15878ea 100644 (file)
@@ -6,9 +6,11 @@
 
 @property (nonatomic, readonly) BOOL canAttack;
 
-- (void) attackTarget:(QQActor)actor;
-- (void) attackToward:(NSPoint)point;
+- (void) attackTarget:(QQActor*)actor;
+- (void) attackToward:(CGPoint)point;
 - (void) attackTowardX:(float)x y:(float)y;
 
 
 @end
+
+//typedef id<QQUnit> QQUnit;
diff --git a/src/game/actor/QQUnitBase.h b/src/game/actor/QQUnitBase.h
new file mode 100644 (file)
index 0000000..6af3e83
--- /dev/null
@@ -0,0 +1,30 @@
+#include <Box2D/Box2D.h>
+#import "Sparrow.h"
+
+#import "render/QQSparrowExtensions.h"
+
+#import "game/actor/QQActor.h"
+#import "game/actor/QQUnit.h"
+#import "game/actor/QQUnitDelegate.h"
+
+#import "physics/QQWorld.h"
+
+
+////////////////////////////////////////////////////////////////////////////////////
+@interface QQUnitBase : QQActor <QQUnit> {
+
+@private
+    SPDisplayObject* _shape;
+    id<QQUnitDelegate> _delegate;
+}
+
+////////////////////////////////////////////////////////////////////////////////////
+@property (nonatomic, retain, readwrite) SPDisplayObject* shape;
+@property (nonatomic, retain, readwrite) id<QQUnitDelegate> delegate;
+
+////////////////////////////////////////////////////////////////////////////////////
+- (id) initAtX:(float)x y:(float)y withShape:(SPDisplayObject*)shape;
+
+- (void) setShapeFromFile:(NSString*)filename;
+
+@end
diff --git a/src/game/actor/QQUnitBase.mm b/src/game/actor/QQUnitBase.mm
new file mode 100644 (file)
index 0000000..2c52e58
--- /dev/null
@@ -0,0 +1,86 @@
+#include <Box2D/Box2D.h>
+#import "Sparrow.h"
+#import "QQUnit.h"
+#import "QQUnitBase.h"
+
+// private interface
+@interface QQUnitBase ()
+
+
+@end
+
+
+////////////////////////////////////////////////////////////////////////////////////
+@implementation QQUnitBase
+
+@dynamic world; // Eliminates compiler warnings due to inheritance (!)
+@dynamic game;
+
+////////////////////////////////////////////////////////////////////////////////////
+@synthesize shape = _shape;
+@synthesize delegate = _delegate;
+
+- (BOOL) canAttack { return NO; }
+
+
+////////////////////////////////////////////////////////////////////////////////////
+- (id) init {
+    return [self initAtX:15 y:15 withShape:[SPQuad quadWithWidth:50 height:50 color:0xff0000]];
+}
+
+- (id) initAtX:(float)x y:(float)y withShape:(SPDisplayObject*)shape {
+    if ((self = [super initAtX:x y:y])) {
+        float px = self.world.scale;
+        self.shape = [shape setPositionX:x*px y:y*px];
+        
+        b2PolygonShape box;
+        box.SetAsBox(shape.width/px, shape.height/px);
+        self.body->CreateFixture(&box, 5.0f);
+        
+        [self.game 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 removeChild:_shape];
+    [_shape release];
+    [super dealloc];
+}
+
+////////////////////////////////////////////////////////////////////////////////////
+- (void) setShape:(SPDisplayObject*)newShape {
+    if (_shape != newShape) {
+        [self.game removeChild:_shape];
+        [_shape release];
+        
+        _shape = [newShape retain];
+        // float px = self.world.scale;
+        // [_shape setPositionX:x*px y:y*px]
+        [self.game addChild:_shape];
+    }
+}
+
+- (void) setShapeFromFile:(NSString*)filename {
+    [self setShape:[[[SPImage alloc] autorelease] initWithContentsOfFile:filename]];
+}
+
+
+
+- (void) attackTarget:(QQActor*)actor {
+    
+}
+
+- (void) attackToward:(CGPoint)pt {
+    [self attackTowardX:pt.x y:pt.y];
+}
+
+- (void) attackTowardX:(float)x y:(float)y {
+    
+}
+
+
+
+@end
diff --git a/src/game/actor/bullet/QQBullet.h b/src/game/actor/bullet/QQBullet.h
new file mode 100644 (file)
index 0000000..e3bcfa3
--- /dev/null
@@ -0,0 +1,15 @@
+#import "game/actor/QQUnitBase.h"
+#import "game/actor/QQUnit.h"
+
+
+@interface QQBullet : QQUnitBase {
+@private
+    id<QQUnit>* _owner;
+}
+
+@property (nonatomic, readonly) id<QQUnit>* owner;
+
+- (id) initAtX:(float)x y:(float)y withOwner:(id<QQUnit>*)owner;
+
+
+@end
diff --git a/src/game/actor/bullet/QQBullet.mm b/src/game/actor/bullet/QQBullet.mm
new file mode 100644 (file)
index 0000000..7c489bc
--- /dev/null
@@ -0,0 +1,22 @@
+#import "QQBullet.h"
+
+
+// private interface
+@interface QQBullet ()
+
+@end
+
+
+@implementation QQBullet
+
+@synthesize owner = _owner;
+
+- (id) initAtX:(float)x y:(float)y withOwner:(id<QQUnit>*)owner {
+    if ((self = [super init])){
+        
+    }
+    return self;
+}
+
+
+@end
diff --git a/src/game/actor/unit/QQTank.h b/src/game/actor/unit/QQTank.h
new file mode 100644 (file)
index 0000000..9d58ed2
--- /dev/null
@@ -0,0 +1,7 @@
+#import "game/actor/QQUnitBase.h"
+
+@interface QQTank : QQUnitBase {
+    
+}
+
+@end
diff --git a/src/game/actor/unit/QQTank.mm b/src/game/actor/unit/QQTank.mm
new file mode 100644 (file)
index 0000000..f80056d
--- /dev/null
@@ -0,0 +1,41 @@
+#import "QQTank.h"
+
+
+// private interface
+@interface QQTank ()
+
+- (void) onTouch:(SPTouchEvent*)event;
+
+@end
+
+
+@implementation QQTank
+
+- (id) init {
+    if ((self = [super init])){
+        
+    }
+    return self;
+}
+
+- (void) onTouch:(SPTouchEvent*)event {
+    SPTouch* touch = [[event touchesWithTarget:self.shape.parent] anyObject];
+    if (touch) {
+        SPPoint* touchPosition = [touch locationInSpace:self.shape.parent];
+        
+    }
+}
+
+- (void) moveOnTouch:(SPTouchEvent*)event {
+    SPTouch* touch = [[event touchesWithTarget:self.shape.parent] anyObject];
+    if (touch) {
+        SPPoint* touchPosition = [touch locationInSpace:self.shape.parent];
+        float x = self.shape.x = touchPosition.x - self.shape.width / 2.0f;
+        float y = self.shape.y = touchPosition.y - self.shape.height / 2.0f;
+        
+        float px = self.world.scale;
+        self.body->SetTransform(b2Vec2(x/px, y/px), self.body->GetAngle());
+    }
+}
+
+@end
\ No newline at end of file
index f3e2b5c..c2c25fe 100644 (file)
@@ -9,8 +9,8 @@
 #endif
 
 #ifdef __OBJC__
-    #import <UIKit/UIKit.h>
     #import <Foundation/Foundation.h>
+    #import <UIKit/UIKit.h>
 #endif
 
-#import "TanksMacros.h"
+
index 94a5de6..bd5f63c 100644 (file)
@@ -7,6 +7,17 @@
        objects = {
 
 /* Begin PBXBuildFile section */
+               492D80CC138B231B0042D918 /* QQPhysical.h in Headers */ = {isa = PBXBuildFile; fileRef = 492D80CB138B231B0042D918 /* QQPhysical.h */; };
+               492D80D5138B233E0042D918 /* QQUnitBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 492D80CF138B233E0042D918 /* QQUnitBase.h */; };
+               492D80D6138B233E0042D918 /* QQUnitBase.mm in Sources */ = {isa = PBXBuildFile; fileRef = 492D80D0138B233E0042D918 /* QQUnitBase.mm */; };
+               492D80DA138B4B110042D918 /* QQUnitDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 492D80D9138B4B110042D918 /* QQUnitDelegate.h */; };
+               492D80E4138BA4910042D918 /* QQCooldown.h in Headers */ = {isa = PBXBuildFile; fileRef = 492D80DE138BA4910042D918 /* QQCooldown.h */; };
+               492D80E5138BA4910042D918 /* QQCooldown.mm in Sources */ = {isa = PBXBuildFile; fileRef = 492D80DF138BA4910042D918 /* QQCooldown.mm */; };
+               492D80EB138BA4B40042D918 /* QQTank.h in Headers */ = {isa = PBXBuildFile; fileRef = 492D80E9138BA4B40042D918 /* QQTank.h */; };
+               492D80EC138BA4B40042D918 /* QQTank.mm in Sources */ = {isa = PBXBuildFile; fileRef = 492D80EA138BA4B40042D918 /* QQTank.mm */; };
+               492D80F0138BA4BC0042D918 /* QQBullet.h in Headers */ = {isa = PBXBuildFile; fileRef = 492D80EE138BA4BC0042D918 /* QQBullet.h */; };
+               492D80F1138BA4BC0042D918 /* QQBullet.mm in Sources */ = {isa = PBXBuildFile; fileRef = 492D80EF138BA4BC0042D918 /* QQBullet.mm */; };
+               492D80F3138BA4CE0042D918 /* QQThing.h in Headers */ = {isa = PBXBuildFile; fileRef = 492D80F2138BA4CE0042D918 /* QQThing.h */; };
                494DE9971376927C00FDB3D7 /* libBox2D.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 494DE9961376927C00FDB3D7 /* libBox2D.a */; };
                4995ABB213816CCE00334646 /* QQGame.h in Headers */ = {isa = PBXBuildFile; fileRef = 49E834A513812427007A6598 /* QQGame.h */; };
                4995ABB313816CD400334646 /* QQUnit.h in Headers */ = {isa = PBXBuildFile; fileRef = 49E834A213812427007A6598 /* QQUnit.h */; };
@@ -26,7 +37,6 @@
                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 */; };
-               49E834AB13812427007A6598 /* QQUnit.mm in Sources */ = {isa = PBXBuildFile; fileRef = 49E834A313812427007A6598 /* QQUnit.mm */; };
                49E834AC13812427007A6598 /* QQDisplayable.h in Headers */ = {isa = PBXBuildFile; fileRef = 49E834A413812427007A6598 /* QQDisplayable.h */; };
                49E834AE13812427007A6598 /* QQGame.mm in Sources */ = {isa = PBXBuildFile; fileRef = 49E834A613812427007A6598 /* QQGame.mm */; };
                49E834BE13812555007A6598 /* QQAppDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 49E834B013812555007A6598 /* QQAppDelegate.h */; };
                49F2DADD13764ED6000B6B8C /* SPUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 49F2DA8013764ED6000B6B8C /* SPUtils.h */; };
                49F2DADE13764ED6000B6B8C /* SPUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 49F2DA8113764ED6000B6B8C /* SPUtils.m */; };
                49F2DADF13764ED6000B6B8C /* Sparrow.h in Headers */ = {isa = PBXBuildFile; fileRef = 49F2DA1D13764ED5000B6B8C /* Sparrow.h */; };
-               4B65630C138239F1001AEF76 /* QQUnitDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B65630B138239F1001AEF76 /* QQUnitDelegate.h */; };
                4B8B2A50137D098500CA4076 /* QQAnimationContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B8B2A4E137D098500CA4076 /* QQAnimationContainer.h */; };
                4B8B2A51137D098500CA4076 /* QQAnimationContainer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B8B2A4F137D098500CA4076 /* QQAnimationContainer.mm */; };
 /* End PBXBuildFile section */
 /* End PBXContainerItemProxy section */
 
 /* Begin PBXFileReference section */
+               492D80CB138B231B0042D918 /* QQPhysical.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = QQPhysical.h; path = src/game/QQPhysical.h; sourceTree = SOURCE_ROOT; };
+               492D80CF138B233E0042D918 /* QQUnitBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQUnitBase.h; sourceTree = "<group>"; };
+               492D80D0138B233E0042D918 /* QQUnitBase.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = QQUnitBase.mm; sourceTree = "<group>"; };
+               492D80D9138B4B110042D918 /* QQUnitDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQUnitDelegate.h; sourceTree = "<group>"; };
+               492D80DE138BA4910042D918 /* QQCooldown.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQCooldown.h; sourceTree = "<group>"; };
+               492D80DF138BA4910042D918 /* QQCooldown.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = QQCooldown.mm; sourceTree = "<group>"; };
+               492D80E9138BA4B40042D918 /* QQTank.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQTank.h; sourceTree = "<group>"; };
+               492D80EA138BA4B40042D918 /* QQTank.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = QQTank.mm; sourceTree = "<group>"; };
+               492D80EE138BA4BC0042D918 /* QQBullet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQBullet.h; sourceTree = "<group>"; };
+               492D80EF138BA4BC0042D918 /* QQBullet.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = QQBullet.mm; sourceTree = "<group>"; };
+               492D80F2138BA4CE0042D918 /* QQThing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQThing.h; sourceTree = "<group>"; };
                494DE9961376927C00FDB3D7 /* libBox2D.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libBox2D.a; sourceTree = SOURCE_ROOT; };
                4995ABCA1381C46B00334646 /* Icon-iPad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-iPad.png"; sourceTree = "<group>"; };
                4995ABCB1381C46B00334646 /* Icon-iPhone.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-iPhone.png"; sourceTree = "<group>"; };
                49E834A013812427007A6598 /* QQActor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQActor.h; sourceTree = "<group>"; };
                49E834A113812427007A6598 /* QQActor.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = QQActor.mm; sourceTree = "<group>"; };
                49E834A213812427007A6598 /* QQUnit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQUnit.h; sourceTree = "<group>"; };
-               49E834A313812427007A6598 /* QQUnit.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = QQUnit.mm; sourceTree = "<group>"; };
                49E834A413812427007A6598 /* QQDisplayable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQDisplayable.h; sourceTree = "<group>"; };
                49E834A513812427007A6598 /* QQGame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQGame.h; sourceTree = "<group>"; };
                49E834A613812427007A6598 /* QQGame.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = QQGame.mm; sourceTree = "<group>"; };
                49F2DA7F13764ED6000B6B8C /* SPPoolObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPPoolObject.m; sourceTree = "<group>"; };
                49F2DA8013764ED6000B6B8C /* SPUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPUtils.h; sourceTree = "<group>"; };
                49F2DA8113764ED6000B6B8C /* SPUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPUtils.m; sourceTree = "<group>"; };
-               4B65630B138239F1001AEF76 /* QQUnitDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQUnitDelegate.h; sourceTree = "<group>"; };
                4B8B2A4E137D098500CA4076 /* QQAnimationContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = QQAnimationContainer.h; path = animation/QQAnimationContainer.h; sourceTree = "<group>"; };
                4B8B2A4F137D098500CA4076 /* QQAnimationContainer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = QQAnimationContainer.mm; path = animation/QQAnimationContainer.mm; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
+               492D80DB138BA4910042D918 /* ability */ = {
+                       isa = PBXGroup;
+                       children = (
+                               492D80DE138BA4910042D918 /* QQCooldown.h */,
+                               492D80DF138BA4910042D918 /* QQCooldown.mm */,
+                       );
+                       path = ability;
+                       sourceTree = "<group>";
+               };
+               492D80E8138BA4B40042D918 /* unit */ = {
+                       isa = PBXGroup;
+                       children = (
+                               492D80E9138BA4B40042D918 /* QQTank.h */,
+                               492D80EA138BA4B40042D918 /* QQTank.mm */,
+                       );
+                       name = unit;
+                       path = actor/unit;
+                       sourceTree = "<group>";
+               };
+               492D80ED138BA4BC0042D918 /* bullet */ = {
+                       isa = PBXGroup;
+                       children = (
+                               492D80EE138BA4BC0042D918 /* QQBullet.h */,
+                               492D80EF138BA4BC0042D918 /* QQBullet.mm */,
+                       );
+                       name = bullet;
+                       path = actor/bullet;
+                       sourceTree = "<group>";
+               };
                4995ABC61381C46B00334646 /* assets */ = {
                        isa = PBXGroup;
                        children = (
                49E8349D13812427007A6598 /* game */ = {
                        isa = PBXGroup;
                        children = (
+                               492D80ED138BA4BC0042D918 /* bullet */,
+                               492D80E8138BA4B40042D918 /* unit */,
+                               492D80DB138BA4910042D918 /* ability */,
                                49E8349F13812427007A6598 /* actor */,
                                49E8349E13812427007A6598 /* QQActive.h */,
                                49E834A413812427007A6598 /* QQDisplayable.h */,
+                               492D80CB138B231B0042D918 /* QQPhysical.h */,
+                               492D80F2138BA4CE0042D918 /* QQThing.h */,
                                49E834A513812427007A6598 /* QQGame.h */,
                                49E834A613812427007A6598 /* QQGame.mm */,
                        );
                49E8349F13812427007A6598 /* actor */ = {
                        isa = PBXGroup;
                        children = (
-                               4B65630B138239F1001AEF76 /* QQUnitDelegate.h */,
+                               492D80D9138B4B110042D918 /* QQUnitDelegate.h */,
+                               492D80CF138B233E0042D918 /* QQUnitBase.h */,
+                               492D80D0138B233E0042D918 /* QQUnitBase.mm */,
                                49E834A013812427007A6598 /* QQActor.h */,
                                49E834A113812427007A6598 /* QQActor.mm */,
                                49E834A213812427007A6598 /* QQUnit.h */,
-                               49E834A313812427007A6598 /* QQUnit.mm */,
                        );
                        path = actor;
                        sourceTree = "<group>";
                                49E834C613812555007A6598 /* QQViewport.h in Headers */,
                                49E834CD13814F7D007A6598 /* QQGLESDebugDraw.h in Headers */,
                                49E834D3138166A6007A6598 /* QQSparrowExtensions.h in Headers */,
-                               4B65630C138239F1001AEF76 /* QQUnitDelegate.h in Headers */,
+                               492D80CC138B231B0042D918 /* QQPhysical.h in Headers */,
+                               492D80D5138B233E0042D918 /* QQUnitBase.h in Headers */,
+                               492D80DA138B4B110042D918 /* QQUnitDelegate.h in Headers */,
+                               492D80E4138BA4910042D918 /* QQCooldown.h in Headers */,
+                               492D80EB138BA4B40042D918 /* QQTank.h in Headers */,
+                               492D80F0138BA4BC0042D918 /* QQBullet.h in Headers */,
+                               492D80F3138BA4CE0042D918 /* QQThing.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                4B8B2A51137D098500CA4076 /* QQAnimationContainer.mm in Sources */,
                                49F2D9C413764666000B6B8C /* main.mm in Sources */,
                                49E834A913812427007A6598 /* QQActor.mm in Sources */,
-                               49E834AB13812427007A6598 /* QQUnit.mm in Sources */,
                                49E834AE13812427007A6598 /* QQGame.mm in Sources */,
                                49E834BF13812555007A6598 /* QQAppDelegate.mm in Sources */,
                                49E834C113812555007A6598 /* QQAppDelegate_iPad.mm in Sources */,
                                49E834C713812555007A6598 /* QQViewport.mm in Sources */,
                                49E834CE13814F7D007A6598 /* QQGLESDebugDraw.mm in Sources */,
                                49E834D4138166A6007A6598 /* QQSparrowExtensions.mm in Sources */,
+                               492D80D6138B233E0042D918 /* QQUnitBase.mm in Sources */,
+                               492D80E5138BA4910042D918 /* QQCooldown.mm in Sources */,
+                               492D80EC138BA4B40042D918 /* QQTank.mm in Sources */,
+                               492D80F1138BA4BC0042D918 /* QQBullet.mm in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        buildSettings = {
                                ARCHS = "$(ARCHS_STANDARD_32_BIT)";
                                "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
-                               GCC_C_LANGUAGE_STANDARD = gnu99;
                                GCC_OPTIMIZATION_LEVEL = 0;
                                GCC_PREPROCESSOR_DEFINITIONS = DEBUG;
                                GCC_SYMBOLS_PRIVATE_EXTERN = NO;
                        buildSettings = {
                                ARCHS = "$(ARCHS_STANDARD_32_BIT)";
                                "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
-                               GCC_C_LANGUAGE_STANDARD = gnu99;
                                GCC_VERSION = com.apple.compilers.llvmgcc42;
                                GCC_WARN_ABOUT_RETURN_TYPE = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                COPY_PHASE_STRIP = NO;
+                               GCC_C_LANGUAGE_STANDARD = gnu99;
                                GCC_DYNAMIC_NO_PIC = NO;
+                               GCC_PRECOMPILE_PREFIX_HEADER = YES;
                                GCC_PREFIX_HEADER = src/prefix.pch;
                                INFOPLIST_FILE = "etc/tanks-Info.plist";
                                LIBRARY_SEARCH_PATHS = (
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                COPY_PHASE_STRIP = YES;
+                               GCC_C_LANGUAGE_STANDARD = gnu99;
+                               GCC_PRECOMPILE_PREFIX_HEADER = YES;
                                GCC_PREFIX_HEADER = src/prefix.pch;
                                INFOPLIST_FILE = "etc/tanks-Info.plist";
                                LIBRARY_SEARCH_PATHS = (