Sparrow's coordinates are totally bogus if registration is changed. Argh.
authordsc <david.schoonover@gmail.com>
Mon, 6 Jun 2011 18:45:39 +0000 (11:45 -0700)
committerdsc <david.schoonover@gmail.com>
Mon, 6 Jun 2011 18:45:39 +0000 (11:45 -0700)
18 files changed:
src/game/QQGame.mm
src/game/QQPhysical.h
src/game/unit/QQActor.mm
src/game/unit/QQActors.h
src/game/unit/QQBullet.h
src/game/unit/QQBullet.mm
src/game/unit/QQPlayer.h [moved from src/game/unit/QQTank.h with 58% similarity]
src/game/unit/QQPlayer.mm [new file with mode: 0644]
src/game/unit/QQTank.mm [deleted file]
src/game/unit/QQUnit.h
src/game/unit/QQUnit.mm
src/main.mm
src/physics/event/QQContactNotification.mm
src/render/QQQuad.h [new file with mode: 0644]
src/render/QQQuad.mm [new file with mode: 0644]
src/render/QQSparrowExtensions.h
src/render/QQSparrowExtensions.mm
tanks.xcodeproj/project.pbxproj

index 6ec2b28..e08918a 100644 (file)
@@ -1,4 +1,4 @@
-#import <Box2D/Box2D.h>
+ #import <Box2D/Box2D.h>
 
 #import "game/QQGame.h"
 #import "game/unit/QQActors.h"
@@ -68,8 +68,8 @@ static QQGame* _CurrentGame = NULL;
         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];
+        [[[QQPlayer alloc] initNamed:@"Pink" atX:wMax/6 y:hMax/6 width:50 height:50 color:0xFF0071] autorelease];
+        [[[QQUnit alloc]   initNamed:@"Blue" atX:wMax/3 y:hMax/2 width:50 height:50 color:0x4596FF] autorelease];
         
         #if TANKS_DEBUG_LOG
             [_stage addEventListener:@selector(logEvent:) atObject:self forType:SP_EVENT_TYPE_ANY];
@@ -134,6 +134,9 @@ static QQGame* _CurrentGame = NULL;
     _elapsed = elapsed;
     _now += elapsed;
     
+    if (_ticks == 1)
+        NSLog(@"%@", self);
+    
     for (QQActor* actor in self.actors)
         [actor tick];
     [self.world step];
@@ -194,15 +197,16 @@ static QQGame* _CurrentGame = NULL;
 - (void) logEvent:(SPEvent*)evt {
     // ignore enter-frame events, as they happen constantly
     if ([evt.type isEqualToString:SP_EVENT_TYPE_ENTER_FRAME]) return;
-    NSLog(@"\v\t%@", evt);
+    // NSLog(@"\v\t%@", evt);
 }
 
 
 - (NSString*) description {
-    return [NSString stringWithFormat:@"<%@: %p> {running=%s, #actors=%i, time={now=%f, ticks=%l, elapsed=%f}}",
-            [self class], (long)self,
-            b2s(self.isRunning), [self.actors count],
-            self.now, self.ticks, self.elapsed
+    return [NSString stringWithFormat:@"<%@: %p> {running=%s, #actors=%i, time={now=%f, ticks=%i, elapsed=%f}, %@}",
+            [self class], self,
+            b2s(self.isRunning), (self.actors ? [self.actors count] : 0),
+            self.now, self.ticks, self.elapsed,
+            self.stage
         ];
 }
 
index 5714c23..ec57aa9 100644 (file)
@@ -2,6 +2,7 @@
 
 @class QQContactNotification;
 
+typedef b2Vec2 Vec;
 
 /**
  * Anything that has a physics representation.
@@ -15,7 +16,7 @@
 @property (nonatomic, readwrite, assign) float y;
 
 /// Simulation coordinates
-@property (nonatomic, readwrite) CGPoint position;
+@property (nonatomic, readwrite) Vec position;
 - (void) setPositionX:(float)x y:(float)y;
 
 @property (nonatomic, readwrite, assign) float rotation;
@@ -40,7 +41,7 @@
  */
 - (void) setupPhysics:(b2BodyDef*)bd;
 
-- (void) applyLinearImpulse:(CGPoint)vec;
+- (void) applyLinearImpulse:(Vec)vec;
 - (void) applyLinearImpulseX:(float)xNs y:(float)yNs;
 
 
index 0237ef0..dfb3d32 100644 (file)
 - (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();
-    return CGPointMake(pos.x, pos.y);
+- (Vec) position {
+    return self.body->GetPosition();
+    // return CGPointMake(pos.x, pos.y);
 }
-- (void) setPosition:(CGPoint)pos {
-    [self setPositionX:pos.x y:pos.y];
+- (void) setPosition:(Vec)pos {
+    self.body->SetTransform(pos, self.body->GetAngle());
 }
 - (void) setPositionX:(float)x y:(float)y {
-    self.body->SetTransform(b2Vec2(x,y), self.body->GetAngle());
+    [self setPosition:Vec(x,y)];
 }
 - (float) rotation { return self.body->GetAngle(); }
 - (void) setRotation:(float)r { self.body->SetTransform(self.body->GetPosition(), r); }
     [self updateShape];
 }
 
-- (void) applyLinearImpulse:(CGPoint)pt {
-    [self applyLinearImpulseX:pt.x y:pt.y];
+- (void) applyLinearImpulse:(Vec)pt {
+    self.body->ApplyLinearImpulse(pt, self.body->GetPosition());
 }
 - (void) applyLinearImpulseX:(float)xNs y:(float)yNs {
-    self.body->ApplyLinearImpulse(b2Vec2(xNs, yNs), self.body->GetPosition());
+    [self applyLinearImpulse:Vec(xNs, yNs)];
 }
 
 
index 1bb6ca8..21d12ed 100644 (file)
@@ -2,4 +2,4 @@
 #import "game/unit/QQActorDelegate.h"
 #import "game/unit/QQUnit.h"
 #import "game/unit/QQBullet.h"
-#import "game/unit/QQTank.h"
+#import "game/unit/QQPlayer.h"
index 2d11478..5e435d8 100644 (file)
@@ -5,11 +5,14 @@
 @interface QQBullet : QQUnit {
 @private
     QQUnit* _owner;
+    float _speed;
 }
 
 @property (nonatomic, readonly) QQUnit* owner;
+@property (nonatomic, readwrite, assign) float speed;
 
 - (id) init:(QQUnit*)owner x:(float)x y:(float)y;
+- (id) init:(QQUnit*)owner x:(float)x y:(float)y towardX:(float)tx y:(float)ty;
 
 
 @end
index ea998f7..c1109c5 100644 (file)
@@ -6,13 +6,16 @@
 
 
 
+
 @implementation QQBullet
 
 @synthesize owner = _owner;
+@synthesize speed = _speed;
 
 - (id) init:(QQUnit*)owner x:(float)x y:(float)y {
     if ((self = [super initAtX:x y:y])){
         _owner = owner;
+        _speed = 50.0f;
         
         float px = self.world.scale;
         float radius = 1.5f;
     return self;
 }
 
+- (id) init:(QQUnit*)owner x:(float)x y:(float)y towardX:(float)tx y:(float)ty {
+    if ((self = [self init:owner x:x y:y])) {
+        Vec imp = Vec(tx,ty);
+        imp.Normalize();
+        imp *= self.speed;
+        [self applyLinearImpulse:imp];
+    }
+    return self;
+}
+
 - (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);
+        NSLog(@"BOOM!");
         [other destroy];
         [self destroy];
     }
similarity index 58%
rename from src/game/unit/QQTank.h
rename to src/game/unit/QQPlayer.h
index 5850a26..0316255 100644 (file)
@@ -1,6 +1,6 @@
 #import "game/unit/QQUnit.h"
 
-@interface QQTank : QQUnit {
+@interface QQPlayer : QQUnit {
     
 }
 
diff --git a/src/game/unit/QQPlayer.mm b/src/game/unit/QQPlayer.mm
new file mode 100644 (file)
index 0000000..e636acc
--- /dev/null
@@ -0,0 +1,87 @@
+#import "QQPlayer.h"
+#import "render/QQSparrowExtensions.h"
+#import "game/QQGame.h"
+#import "game/unit/QQBullet.h"
+
+
+// private interface
+@interface QQPlayer ()
+- (void) onTouch:(SPTouchEvent*)event;
+@end
+
+
+
+@implementation QQPlayer
+
+
+- (id) initAtX:(float)x y:(float)y withShape:(SPDisplayObject*)shape {
+    if ((self = [super initAtX:x y:y withShape:shape])){
+        [self.shape addEventListener:@selector(onSelfTouch:) atObject:self forType:SP_EVENT_TYPE_TOUCH];
+        [self.game.stage addEventListener:@selector(attackOnTouch:) atObject:self forType:SP_EVENT_TYPE_TOUCH];
+    }
+    return self;
+}
+
+- (void) dealloc {
+    [self.game.stage removeEventListener:@selector(onTouch:) atObject:self forType:SP_EVENT_TYPE_TOUCH];
+    [super dealloc];
+}
+
+- (void) onSelfTouch:(SPTouchEvent*)event {
+    SPTouch* touch = [[event touchesWithTarget:(SPDisplayObject*)self.shape] anyObject];
+    NSLog(@">>>>> onSelfTouch! <<<<< \v\ttouch=%@ \v\tevent=%@ \v\tshape=%@ \v\tstage=%@\v", touch, event, self.shape, self.game.stage);
+}
+
+- (void) onTouch:(SPTouchEvent*)event {
+    SPTouch* touch = [[event touchesWithTarget:(SPDisplayObject*)self.game.stage] anyObject];
+    NSString* msg = [NSString stringWithFormat:@"onTouch! \vtouch=%@\v", touch];
+    msg = [msg stringByAppendingFormat:@"\t- %@\v", self.shape];
+    msg = [msg stringByAppendingFormat:@"\t- %@\v", self.game.stage];
+//    SPDisplayObject* obj = self.shape;
+//    do {
+//        msg = [msg stringByAppendingFormat:@"\t- %@\v", obj];
+//    } while ((obj = obj.parent));
+    NSLog(msg);
+}
+
+- (void) attackOnTouch:(SPTouchEvent*)event {
+    NSLog(@"onTouch: \v\t%@ \v\t%@", self, event);
+    SPTouch* touch = [[event touchesWithTarget:(SPDisplayObject*)self.game.stage] anyObject];
+    if (touch && [[self.cooldowns objectForKey:ATTACK_COOLDOWN_NAME] activate]) {
+        // [self attackToward:[[touch locationInSpace:self.shape.parent] scaleBy:1.0f/self.world.scale]];
+        
+        // Touch's normal vector in local coords (rel unit origin)
+        SPPoint* normVec = [[[touch locationInSpace:self.shape.parent] subtractPoint:self.shape.position] normalize];
+        
+        // Bullet starting position
+        float offset = 7.5f + fmaxf(self.shape.width, self.shape.height) * 1.41421356237f; // bullet_radius + tank_diagonal_length
+        SPPoint* start = [[self.shape.position addPoint:[normVec scaleBy:offset]] scaleBy:1.0f/self.world.scale];
+        QQBullet* bullet = [[[QQBullet alloc] init:self x:start.x y:start.y] autorelease];
+        
+        // Bullet impulse vector
+        SPPoint* imp = [normVec scaleBy:50];
+        [bullet applyLinearImpulseX:imp.x y:imp.y];
+        // NSLog(@"[%@ pos:(%f,%f) impulse:(%f,%f)]", bullet, bullet.x,bullet.y, imp.x,imp.y);
+    }
+}
+
+- (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 setPositionX:x/px y:y/px];
+        // self.body->SetTransform(b2Vec2(x/px, y/px), self.body->GetAngle());
+    }
+}
+
+// - (NSString*) description {
+//     return [NSString stringWithFormat:@"%@ bounds=%@",
+//             [super description], self.bounds];
+// }
+
+
+@end
\ No newline at end of file
diff --git a/src/game/unit/QQTank.mm b/src/game/unit/QQTank.mm
deleted file mode 100644 (file)
index edacf1a..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#import "QQTank.h"
-#import "render/QQSparrowExtensions.h"
-#import "game/QQGame.h"
-#import "game/unit/QQBullet.h"
-
-
-// private interface
-@interface QQTank ()
-- (void) onTouch:(SPTouchEvent*)event;
-@end
-
-
-
-@implementation QQTank
-
-
-- (id) initAtX:(float)x y:(float)y withShape:(SPDisplayObject*)shape {
-    if ((self = [super initAtX:x y:y withShape:shape])){
-        [self.game.stage addEventListener:@selector(onTouch:) atObject:self forType:SP_EVENT_TYPE_TOUCH];
-    }
-    return self;
-}
-
-- (void) dealloc {
-    [self.game.stage removeEventListener:@selector(onTouch:) atObject:self forType:SP_EVENT_TYPE_TOUCH];
-    [super dealloc];
-}
-
-
-- (void) onTouch:(SPTouchEvent*)event {
-    SPTouch* touch = [[event touchesWithTarget:(SPDisplayObject*)self.game.stage] anyObject];
-    if (touch && [[self.cooldowns objectForKey:ATTACK_COOLDOWN_NAME] activate]) {
-        // Touch's normal vector in local coords (rel unit origin)
-        SPPoint* normVec = [[[touch locationInSpace:self.shape.parent] subtractPoint:self.shape.position] normalize];
-        
-        // Bullet starting position
-        float offset = 7.5f + fmaxf(self.shape.width, self.shape.height) * 1.41421356237f; // bullet_radius + tank_diagonal_length
-        SPPoint* start = [[self.shape.position addPoint:[normVec scaleBy:offset]] scaleBy:1.0f/self.world.scale];
-        QQBullet* bullet = [[[QQBullet alloc] init:self x:start.x y:start.y] autorelease];
-        
-        // Bullet impulse vector
-        SPPoint* imp = [normVec scaleBy:50];
-        [bullet applyLinearImpulseX:imp.x y:imp.y];
-        NSLog(@"[%@ pos:(%f,%f) impulse:(%f,%f)]", bullet, bullet.x,bullet.y, imp.x,imp.y);
-    }
-}
-
-
-@end
\ No newline at end of file
index ce5bf9e..8deceaf 100644 (file)
@@ -6,7 +6,7 @@
 #import "game/unit/QQActor.h"
 #import "game/unit/QQActorDelegate.h"
 
-
+@class QQBullet;
 
 @interface QQUnit : QQActor {
 
 
 
 /// initializers
-- (id) initAtX:(float)x y:(float)y width:(float)w height:(float)h color:(uint)color;
+- (id) initNamed:(NSString*)name atX:(float)x y:(float)y width:(float)w height:(float)h color:(uint)color;
 - (id) initAtX:(float)x y:(float)y withShape:(SPDisplayObject*)shape;
 
 
 /// methods
 
-- (void) attack:(QQActor*)actor;
-- (void) attackToward:(CGPoint)point;
-- (void) attackTowardX:(float)x y:(float)y;
+- (QQBullet*) attack:(QQActor*)actor;
+- (QQBullet*) attackToward:(SPPoint*)point;
+- (QQBullet*) attackTowardX:(float)x y:(float)y;
 
 
 @end
index 557125d..7ab1c13 100644 (file)
@@ -1,6 +1,7 @@
 #include <Box2D/Box2D.h>
 #import "Sparrow.h"
 #import "render/QQSparrowExtensions.h"
+#import "render/QQQuad.h"
 
 #import "game/unit/QQUnit.h"
 #import "game/QQGame.h"
 /// initializers
 
 - (id) init {
-    return [self initAtX:50 y:50 width:50 height:50 color:0xff0071];
+    return [self initNamed:nil atX:50 y:50 width:50 height:50 color:0xff0071];
 }
 
-- (id) initAtX:(float)x y:(float)y width:(float)w height:(float)h color:(uint)color {
+- (id) initNamed:(NSString*)name atX:(float)x y:(float)y width:(float)w height:(float)h color:(uint)color {
     SPQuad* shape = [SPQuad quadWithWidth:w height:h color:color];
+    shape.name = name;
     return [self initAtX:x y:y withShape:shape];
 }
 
@@ -80,8 +82,8 @@
 }
 
 - (void) act {
-    if ((self.game.ticks % 50) == 0) {
-        self.rotation += b2_pi / 8;
+    if ((self.game.ticks % 100) == 0) {
+        self.rotation += b2_pi / 4;
     }
 }
 
 }
 
 
-- (void) attack:(QQActor*)actor {
-    [self attackTowardX:actor.x y:actor.y];
+- (QQBullet*) attack:(QQActor*)actor {
+    return [self attackTowardX:actor.x y:actor.y];
 }
-- (void) attackToward:(CGPoint)pt {
-    [self attackTowardX:pt.x y:pt.y];
+- (QQBullet*) attackTowardX:(float)x y:(float)y {
+    return [self attackToward:[SPPoint pointWithX:x y:y]];
 }
-- (void) attackTowardX:(float)x y:(float)y {
-    SPPoint* pos = [SPPoint pointFromCGPoint:self.position];
-    SPPoint* target = [SPPoint pointWithX:x y:y];
+- (QQBullet*) attackToward:(SPPoint*)target {
+    SPPoint* pos = [SPPoint pointFromVec:self.position];
     
     // Touch's normal vector in local coords (rel unit origin)
-    SPPoint* normVec = [[target subtractPoint:pos] normalize];
+    SPPoint* norm = [[target subtractPoint:pos] normalize];
     
     // Bullet starting position
+    // FIXME: GAH, unit size is wrong
     float offset = 1.5f + MAX(self.shape.width, self.shape.height) * 1.41421356237f; // bullet_radius + tank_diagonal_length
-    SPPoint* start = [pos addPoint:[normVec scaleBy:offset]];
-    QQBullet* bullet = [[[QQBullet alloc] init:self x:start.x y:start.y] autorelease];
+    SPPoint* start = [pos addPoint:[norm scaleBy:offset]];
+    QQBullet* bullet = [[[QQBullet alloc] init:self x:start.x y:start.y towardX:norm.x y:norm.y] autorelease];
     
     // Bullet impulse vector
-    SPPoint* imp = [normVec scaleBy:50];
-    [bullet applyLinearImpulseX:imp.x y:imp.y];
-    NSLog(@"[%@ pos:(%f,%f) impulse:(%f,%f)]", bullet, bullet.x,bullet.y, imp.x,imp.y);
+    NSLog(@"[%@ pos:(%f,%f) impulse:(%f,%f)]", bullet, bullet.x,bullet.y, norm.x*50,norm.y*50);
+    return bullet;
 }
 
 
index 9e6716c..fb586b0 100644 (file)
@@ -2,9 +2,9 @@
 #import "Tanks.h"
 
 
-int main(int argc, char *argv[])
-{
+int main(int argc, char *argv[]) {
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    // int retVal = 0;
     int retVal = UIApplicationMain(argc, argv, nil, nil);
     [pool release];
     return retVal;
index 76911ed..11b4840 100644 (file)
@@ -43,7 +43,7 @@
 
 
 - (NSString*) description {
-    return [NSString stringWithFormat:@"[%@ \v\tactorA=%@, \v\tactorB=%@]",
+    return [NSString stringWithFormat:@"\v\t[%@ \v\tactorA=%@, \v\tactorB=%@]",
             [super description], self.actorA, self.actorB];
 }
 
diff --git a/src/render/QQQuad.h b/src/render/QQQuad.h
new file mode 100644 (file)
index 0000000..efca9c1
--- /dev/null
@@ -0,0 +1,11 @@
+#import "Sparrow.h"
+
+
+@interface QQQuad : SPQuad
+
+- (id)initWithWidth:(float)width height:(float)height color:(uint)color;
+
++ (QQQuad*)quadWithWidth:(float)width height:(float)height;
++ (QQQuad*)quadWithWidth:(float)width height:(float)height color:(uint)color;
+
+@end
diff --git a/src/render/QQQuad.mm b/src/render/QQQuad.mm
new file mode 100644 (file)
index 0000000..8d46c8b
--- /dev/null
@@ -0,0 +1,40 @@
+#import "QQQuad.h"
+
+
+@implementation QQQuad
+
+- (id)initWithWidth:(float)width height:(float)height color:(uint)color {
+    if ((self = [super init])) {
+        self.autoUpdateReg = YES;
+        
+        float halfW = width  *0.5f;
+        float halfH = height *0.5f;
+        
+        mVertexCoords[0] = -halfW;
+        mVertexCoords[1] = -halfH;
+        
+        mVertexCoords[2] =  halfW;
+        mVertexCoords[3] = -halfH;
+        
+        mVertexCoords[4] = -halfW;
+        mVertexCoords[5] =  halfH;
+        
+        mVertexCoords[6] =  halfW;
+        mVertexCoords[7] =  halfH;
+        
+        self.color = color;
+        self.registrationX = 0;
+        self.registrationY = 0;
+    }
+    return self;
+}
+
++ (QQQuad*)quadWithWidth:(float)width height:(float)height {
+    return [[[QQQuad alloc] initWithWidth:width height:height] autorelease];
+}
+
++ (QQQuad*)quadWithWidth:(float)width height:(float)height color:(uint)color {
+    return [[[QQQuad alloc] initWithWidth:width height:height color:color] autorelease];
+}
+
+@end
index a68d4a9..2801d33 100644 (file)
@@ -27,7 +27,8 @@ struct b2Vec2;
 
 @interface SPPoint (QQSparrowExtensions)
 - (CGPoint)  toCGPoint;
+- (b2Vec2)   toVec;
 + (SPPoint*) pointFromCGPoint:(CGPoint)pt;
-+ (SPPoint*) pointFromB2Vec2:(b2Vec2)vec;
++ (SPPoint*) pointFromVec:(b2Vec2)vec;
 @end
 
index 479c88f..1c14400 100644 (file)
 
 @implementation SPPoint (QQSparrowExtensions)
 - (CGPoint) toCGPoint {
-    return CGPointMake(mX, mY);
+    return CGPointMake(mX,mY);
+}
+- (b2Vec2) toVec {
+    return b2Vec2(mX,mY);
 }
 
 + (SPPoint*) pointFromCGPoint:(CGPoint)pt {
     return [SPPoint pointWithX:pt.x y:pt.y];
 }
 
-+ (SPPoint*) pointFromB2Vec2:(b2Vec2)vec {
++ (SPPoint*) pointFromVec:(b2Vec2)vec {
     return [SPPoint pointWithX:vec.x y:vec.y];
 }
 
index 78525df..da58cdd 100644 (file)
@@ -57,8 +57,6 @@
                499F65E4139CBCBA00309DE4 /* QQActors.h in Headers */ = {isa = PBXBuildFile; fileRef = 499F65DA139CBCBA00309DE4 /* QQActors.h */; };
                499F65E5139CBCBA00309DE4 /* QQBullet.h in Headers */ = {isa = PBXBuildFile; fileRef = 499F65DB139CBCBA00309DE4 /* QQBullet.h */; };
                499F65E6139CBCBA00309DE4 /* QQBullet.mm in Sources */ = {isa = PBXBuildFile; fileRef = 499F65DC139CBCBA00309DE4 /* QQBullet.mm */; };
-               499F65E7139CBCBA00309DE4 /* QQTank.h in Headers */ = {isa = PBXBuildFile; fileRef = 499F65DD139CBCBA00309DE4 /* QQTank.h */; };
-               499F65E8139CBCBA00309DE4 /* QQTank.mm in Sources */ = {isa = PBXBuildFile; fileRef = 499F65DE139CBCBA00309DE4 /* QQTank.mm */; };
                499F65E9139CBCBA00309DE4 /* QQUnit.h in Headers */ = {isa = PBXBuildFile; fileRef = 499F65DF139CBCBA00309DE4 /* QQUnit.h */; };
                499F65EA139CBCBA00309DE4 /* QQUnit.mm in Sources */ = {isa = PBXBuildFile; fileRef = 499F65E0139CBCBA00309DE4 /* QQUnit.mm */; };
                499F65EC139CBCC000309DE4 /* QQGameTime.h in Headers */ = {isa = PBXBuildFile; fileRef = 499F65EB139CBCC000309DE4 /* QQGameTime.h */; };
                499F65FE139CFD3800309DE4 /* NSArray+QQExtensions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 499F65FA139CFD3700309DE4 /* NSArray+QQExtensions.mm */; };
                499F65FF139CFD3800309DE4 /* NSDictionary+QQExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 499F65FB139CFD3700309DE4 /* NSDictionary+QQExtensions.h */; };
                499F6600139CFD3800309DE4 /* NSDictionary+QQExtensions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 499F65FC139CFD3800309DE4 /* NSDictionary+QQExtensions.mm */; };
+               499F6603139D181400309DE4 /* QQPlayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 499F6601139D181400309DE4 /* QQPlayer.h */; };
+               499F6604139D181400309DE4 /* QQPlayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 499F6602139D181400309DE4 /* QQPlayer.mm */; };
+               499F6607139D31FC00309DE4 /* QQQuad.h in Headers */ = {isa = PBXBuildFile; fileRef = 499F6605139D31FC00309DE4 /* QQQuad.h */; };
+               499F6608139D31FC00309DE4 /* QQQuad.mm in Sources */ = {isa = PBXBuildFile; fileRef = 499F6606139D31FC00309DE4 /* QQQuad.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 */; };
                499F65DA139CBCBA00309DE4 /* QQActors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQActors.h; sourceTree = "<group>"; };
                499F65DB139CBCBA00309DE4 /* QQBullet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQBullet.h; sourceTree = "<group>"; };
                499F65DC139CBCBA00309DE4 /* QQBullet.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = QQBullet.mm; sourceTree = "<group>"; };
-               499F65DD139CBCBA00309DE4 /* QQTank.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQTank.h; sourceTree = "<group>"; };
-               499F65DE139CBCBA00309DE4 /* QQTank.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = QQTank.mm; sourceTree = "<group>"; };
                499F65DF139CBCBA00309DE4 /* QQUnit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQUnit.h; sourceTree = "<group>"; };
                499F65E0139CBCBA00309DE4 /* QQUnit.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = QQUnit.mm; sourceTree = "<group>"; };
                499F65EB139CBCC000309DE4 /* QQGameTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQGameTime.h; sourceTree = "<group>"; };
                499F65FA139CFD3700309DE4 /* NSArray+QQExtensions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSArray+QQExtensions.mm"; sourceTree = "<group>"; };
                499F65FB139CFD3700309DE4 /* NSDictionary+QQExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+QQExtensions.h"; sourceTree = "<group>"; };
                499F65FC139CFD3800309DE4 /* NSDictionary+QQExtensions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSDictionary+QQExtensions.mm"; sourceTree = "<group>"; };
+               499F6601139D181400309DE4 /* QQPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQPlayer.h; sourceTree = "<group>"; };
+               499F6602139D181400309DE4 /* QQPlayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = QQPlayer.mm; sourceTree = "<group>"; };
+               499F6605139D31FC00309DE4 /* QQQuad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQQuad.h; sourceTree = "<group>"; };
+               499F6606139D31FC00309DE4 /* QQQuad.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = QQQuad.mm; sourceTree = "<group>"; };
                49D8645B1392DB2800BC341C /* QQShape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQShape.h; sourceTree = "<group>"; };
                49D8645C1392DB2800BC341C /* QQShape.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = QQShape.mm; sourceTree = "<group>"; };
                49DA67D2137847A7004841E9 /* QQWorld.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQWorld.h; sourceTree = "<group>"; };
                                499F65D8139CBCBA00309DE4 /* QQActor.mm */,
                                499F65DB139CBCBA00309DE4 /* QQBullet.h */,
                                499F65DC139CBCBA00309DE4 /* QQBullet.mm */,
-                               499F65DD139CBCBA00309DE4 /* QQTank.h */,
-                               499F65DE139CBCBA00309DE4 /* QQTank.mm */,
                                499F65DF139CBCBA00309DE4 /* QQUnit.h */,
                                499F65E0139CBCBA00309DE4 /* QQUnit.mm */,
+                               499F6601139D181400309DE4 /* QQPlayer.h */,
+                               499F6602139D181400309DE4 /* QQPlayer.mm */,
                        );
                        path = unit;
                        sourceTree = "<group>";
                                4978AD1E1396302E00930447 /* qq */,
                                49F2D9B113764666000B6B8C /* physics */,
                                49E8349D13812427007A6598 /* game */,
-                               49F2D9B013764666000B6B8C /* main.mm */,
                                49F2D9B213764666000B6B8C /* prefix.pch */,
                                49E67E10139B341600DDFC07 /* TanksMacros.h */,
                                4978AD131396139100930447 /* Tanks.h */,
+                               49F2D9B013764666000B6B8C /* main.mm */,
                        );
                        path = src;
                        sourceTree = "<group>";
                        isa = PBXGroup;
                        children = (
                                4B8B2A4D137D090D00CA4076 /* animation */,
+                               499F6605139D31FC00309DE4 /* QQQuad.h */,
+                               499F6606139D31FC00309DE4 /* QQQuad.mm */,
                                49D8645B1392DB2800BC341C /* QQShape.h */,
                                49D8645C1392DB2800BC341C /* QQShape.mm */,
                                49E834D1138166A6007A6598 /* QQSparrowExtensions.h */,
                                499F65E3139CBCBA00309DE4 /* QQActorDelegate.h in Headers */,
                                499F65E4139CBCBA00309DE4 /* QQActors.h in Headers */,
                                499F65E5139CBCBA00309DE4 /* QQBullet.h in Headers */,
-                               499F65E7139CBCBA00309DE4 /* QQTank.h in Headers */,
                                499F65E9139CBCBA00309DE4 /* QQUnit.h in Headers */,
                                499F65EC139CBCC000309DE4 /* QQGameTime.h in Headers */,
                                499F65FD139CFD3800309DE4 /* NSArray+QQExtensions.h in Headers */,
                                499F65FF139CFD3800309DE4 /* NSDictionary+QQExtensions.h in Headers */,
+                               499F6603139D181400309DE4 /* QQPlayer.h in Headers */,
+                               499F6607139D31FC00309DE4 /* QQQuad.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                499F65CE139CBC0C00309DE4 /* QQNotificationProxy.mm in Sources */,
                                499F65E2139CBCBA00309DE4 /* QQActor.mm in Sources */,
                                499F65E6139CBCBA00309DE4 /* QQBullet.mm in Sources */,
-                               499F65E8139CBCBA00309DE4 /* QQTank.mm in Sources */,
                                499F65EA139CBCBA00309DE4 /* QQUnit.mm in Sources */,
                                499F65FE139CFD3800309DE4 /* NSArray+QQExtensions.mm in Sources */,
                                499F6600139CFD3800309DE4 /* NSDictionary+QQExtensions.mm in Sources */,
+                               499F6604139D181400309DE4 /* QQPlayer.mm in Sources */,
+                               499F6608139D31FC00309DE4 /* QQQuad.mm in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };