Interfaces for units; enter_frame works.
authordsc <david.schoonover@gmail.com>
Mon, 16 May 2011 08:32:00 +0000 (01:32 -0700)
committerdsc <david.schoonover@gmail.com>
Mon, 16 May 2011 08:32:00 +0000 (01:32 -0700)
27 files changed:
.gitignore
libs/sparrow/VERSION [new file with mode: 0644]
src/RootAppDelegate.h
src/RootAppDelegate.mm [moved from src/RootAppDelegate.m with 61% similarity]
src/main.mm [moved from src/main.m with 100% similarity]
src/physics/PhysicsDebugView.h [new file with mode: 0644]
src/physics/PhysicsDebugView.mm [new file with mode: 0644]
src/physics/World.h
src/physics/World.mm
src/tanks/Active.h [new file with mode: 0644]
src/tanks/Displayable.h [new file with mode: 0644]
src/tanks/Game.h
src/tanks/Game.m [deleted file]
src/tanks/Game.mm [new file with mode: 0644]
src/tanks/unit/Actor.h [new file with mode: 0644]
src/tanks/unit/Actor.mm [new file with mode: 0644]
src/tanks/unit/Unit.h
src/tanks/unit/Unit.m [deleted file]
src/tanks/unit/Unit.mm [new file with mode: 0644]
src/ui/GLES-Render.h [moved from src/render/GLES-Render.h with 100% similarity]
src/ui/GLES-Render.mm [moved from src/render/GLES-Render.mm with 100% similarity]
src/ui/Viewport.h [new file with mode: 0644]
src/ui/Viewport.mm [new file with mode: 0644]
src/ui/iPad/RootAppDelegate_iPad.mm [moved from src/ui/iPad/RootAppDelegate_iPad.m with 100% similarity]
src/ui/iPhone/RootAppDelegate_iPhone.mm [moved from src/ui/iPhone/RootAppDelegate_iPhone.m with 100% similarity]
tanks-ios.tmproj [deleted file]
tanks.xcodeproj/project.pbxproj

index 9408889..89a8a7b 100644 (file)
@@ -1,3 +1,6 @@
+tmp
+*.tmproj
+
 # Xcode
 build
 *.pbxuser
@@ -12,5 +15,4 @@ build
 !default.xcworkspace
 xcuserdata
 profile
-*.moved-aside
-tmp
+*.moved-aside
\ No newline at end of file
diff --git a/libs/sparrow/VERSION b/libs/sparrow/VERSION
new file mode 100644 (file)
index 0000000..9459d4b
--- /dev/null
@@ -0,0 +1 @@
+1.1
index b3d29e3..13411b4 100644 (file)
@@ -1,21 +1,16 @@
-//
-//  RootAppDelegate.h
-//  tanks
-//
-//  Created by dsc on 4/27/11.
-//  Copyright 2011 lttlst.com. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
 #import "Sparrow.h"
+#import "Game.h"
+
 
 @interface RootAppDelegate : NSObject <UIApplicationDelegate>
 {
-    UIWindow *window;
-    SPView *sparrowView;
+    UIWindow* window;
+    SPView* sparrowView;
+    Game* game;
 }
 
-@property (nonatomic, retain) IBOutlet UIWindow *window;
-@property (nonatomic, retain) IBOutlet SPView *sparrowView;
+@property (nonatomic, retain) IBOutlet UIWindow* window;
+@property (nonatomic, retain) IBOutlet SPView* sparrowView;
+@property (nonatomic, retain) Game* game;
 
 @end
\ No newline at end of file
similarity index 61%
rename from src/RootAppDelegate.m
rename to src/RootAppDelegate.mm
index fac7681..34b7cd9 100644 (file)
 
 @synthesize window;
 @synthesize sparrowView;
+@synthesize game;
 
-- (void)applicationDidFinishLaunching:(UIApplication *)application
-{
+
+- (void) applicationDidFinishLaunching:(UIApplication*)application {
     SP_CREATE_POOL(pool);
     
     [SPStage setSupportHighResolutions:YES];
     [SPAudioEngine start];
+    if ( sparrowView.frameRate != 60.0f )
+        sparrowView.frameRate = 60.0f;
     
-    Game *game = [[Game alloc] init];
+    game = [[[Game alloc] init] autorelease];
     sparrowView.stage = game;
-    [game release];
     
     [window makeKeyAndVisible];
     [sparrowView start];
     SP_RELEASE_POOL(pool);
 }
 
-- (void)applicationWillResignActive:(UIApplication *)application
-{
+- (void) applicationWillResignActive:(UIApplication*)application {
     [sparrowView stop];
 }
 
-- (void)applicationDidBecomeActive:(UIApplication *)application
-{
+- (void) applicationDidBecomeActive:(UIApplication*)application {
     [sparrowView start];
 }
 
-- (void)dealloc
-{
+- (void) dealloc {
+    [self setGame:nil];
     [sparrowView release];
     [window release];
     [super dealloc];
similarity index 100%
rename from src/main.m
rename to src/main.mm
diff --git a/src/physics/PhysicsDebugView.h b/src/physics/PhysicsDebugView.h
new file mode 100644 (file)
index 0000000..57209d7
--- /dev/null
@@ -0,0 +1,67 @@
+#import <UIKit/UIKit.h>
+#import <OpenGLES/EAGL.h>
+#import <OpenGLES/ES1/gl.h>
+#import <OpenGLES/ES1/glext.h>
+
+#include <Box2D/Box2D.h>
+
+#import "physics/PhysicsView.h"
+
+/*
+This class wraps the CAEAGLLayer from CoreAnimation into a convenient UIView subclass.
+The view content is basically an EAGL surface you render your OpenGL scene into.
+Note that setting the view non-opaque will only work if the EAGL surface has an alpha channel.
+*/
+@interface PhysicsDebugView : PhysicsView {}
+
+@property (nonatomic, readonly, getter=isRunning) BOOL running;
+@property (nonatomic, assign) NSTimeInterval animationInterval;
+
+
+- (void) startAnimation;
+- (void) stopAnimation;
+
+@end
+
+
+// Render Settings
+struct Settings {
+    
+    Settings() :
+        hz(60.0f),
+        velocityIterations(10),
+        positionIterations(4),
+        drawStats(0),
+        drawShapes(1),
+        drawJoints(1),
+        drawAABBs(0),
+        drawPairs(0),
+        drawContactPoints(0),
+        drawContactNormals(0),
+        drawContactForces(0),
+        drawFrictionForces(0),
+        drawCOMs(0),
+        enableWarmStarting(1),
+        enableContinuous(1),
+        pause(0),
+        singleStep(0)
+    {}
+    
+    float32 hz;
+    int32 velocityIterations;
+    int32 positionIterations;
+    int32 drawShapes;
+    int32 drawJoints;
+    int32 drawAABBs;
+    int32 drawPairs;
+    int32 drawContactPoints;
+    int32 drawContactNormals;
+    int32 drawContactForces;
+    int32 drawFrictionForces;
+    int32 drawCOMs;
+    int32 drawStats;
+    int32 enableWarmStarting;
+    int32 enableContinuous;
+    int32 pause;
+    int32 singleStep;
+};
diff --git a/src/physics/PhysicsDebugView.mm b/src/physics/PhysicsDebugView.mm
new file mode 100644 (file)
index 0000000..be4444b
--- /dev/null
@@ -0,0 +1,299 @@
+#import <QuartzCore/QuartzCore.h>
+#import <OpenGLES/EAGLDrawable.h>
+
+#import "PhysicsDebugView.h"
+
+
+#define USE_DEPTH_BUFFER 0
+#define kAccelerometerFrequency 30
+#define FRAMES_BETWEEN_PRESSES_FOR_DOUBLE_CLICK 10
+
+
+
+// A class extension to declare private methods
+@interface PhysicsDebugView () {
+
+@private
+    World* _world;
+    BOOL _running;
+    
+    NSTimer* animationTimer;
+    NSTimeInterval animationInterval;
+    BOOL panning;
+    
+    // Position offset and scale
+    float sceneScale;
+    CGPoint positionOffset;
+    
+    CGPoint lastWorldTouch;
+    CGPoint lastScreenTouch;
+    
+    b2MouseJoint* mouseJoint;
+    b2Vec2 mouseWorld;
+    int32 stepCount;
+
+    
+    /// OpenGL ///
+    
+    /* The pixel dimensions of the backbuffer */
+    GLint backingWidth;
+    GLint backingHeight;
+    
+    EAGLContext *context;
+    
+    /* OpenGL names for the renderbuffer and framebuffers used to render to this view */
+    GLuint viewRenderbuffer, viewFramebuffer;
+    
+    /* OpenGL name for the depth buffer that is attached to viewFramebuffer, if it exists (0 if it does not exist) */
+    GLuint depthRenderbuffer;
+    
+}
+
+@property (nonatomic, retain) EAGLContext *context;
+@property (nonatomic, assign) NSTimer *animationTimer;
+
+- (BOOL) createFramebuffer;
+- (void) destroyFramebuffer;
+
+@end
+
+
+
+
+@implementation PhysicsDebugView
+
+@synthesize world = _world;
+@synthesize running = _running;
+
+@synthesize context;
+@synthesize animationTimer;
+@synthesize animationInterval;
+
+
+// You must implement this method
++ (Class)layerClass {
+    return [CAEAGLLayer class];
+}
+
+
+//The GL view is stored in the nib file. When it's unarchived it's sent -initWithCoder:
+- (id)initWithCoder:(NSCoder*)coder {
+    
+    if ((self = [super initWithCoder:coder])) {
+        // Get the layer
+        CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
+        
+        eaglLayer.opaque = YES;
+        eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
+                                        [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
+        
+        context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
+        
+        if (!context || ![EAGLContext setCurrentContext:context]) {
+            [self release];
+            return nil;
+        }
+        
+        _running = NO;
+        animationInterval = 1.0 / 60.0;
+        sceneScale = 10.0f;
+        positionOffset = CGPointMake(0, 0);
+        lastWorldTouch = CGPointMake(0, 0);
+        
+        [[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0 / kAccelerometerFrequency)];
+        [[UIAccelerometer sharedAccelerometer] setDelegate:self];
+    }
+    
+    return self;
+}
+
+- (void) dealloc {
+    [self stopAnimation];
+    
+    if ([EAGLContext currentContext] == context) {
+        [EAGLContext setCurrentContext:nil];
+    }
+    
+    [context release];
+    [super dealloc];
+}
+
+
+/// Accessors ///
+
+- (void) setAnimationTimer:(NSTimer*)newTimer {
+    [animationTimer invalidate];
+    animationTimer = newTimer;
+}
+
+- (void) setAnimationInterval:(NSTimeInterval)interval {
+    animationInterval = interval;
+    if (animationTimer) {
+        [self stopAnimation];
+        [self startAnimation];
+    }
+}
+
+
+/// Methods ///
+
+- (void) startAnimation {
+    _running = YES;
+    self.animationTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval target:self selector:@selector(drawView) userInfo:nil repeats:YES];
+}
+
+- (void) stopAnimation {
+    _running = NO;
+    self.animationTimer = nil;
+}
+
+- (CGPoint) screenSpaceToWorldSpace:(CGPoint) screenLocation {
+    screenLocation.x -= 160;
+    screenLocation.y -= 240;
+    screenLocation.x /= 160;
+    screenLocation.y /= 160;
+    screenLocation.x *= sceneScale;
+    screenLocation.y *= -sceneScale;
+    
+    screenLocation.x -= positionOffset.x;
+    screenLocation.y -= positionOffset.y;
+    
+    return screenLocation;
+}
+
+
+/// Events ///
+
+- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
+    panning = false;
+    for (UITouch *touch in touches) {
+        CGPoint touchLocation = [touch locationInView:self];
+        CGPoint worldPosition = [self screenSpaceToWorldSpace:touchLocation];
+        //printf("Screen touched %f,%f -> %f,%f\n",touchLocation.x,touchLocation.y,worldPosition.x,worldPosition.y);
+        lastScreenTouch = touchLocation;
+        lastWorldTouch = worldPosition;
+        
+        // test->MouseDown(b2Vec2(lastWorldTouch.x,lastWorldTouch.y));
+        // if (!test->m_mouseJoint) panning=true;
+    }
+}
+
+- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
+    for (UITouch *touch in touches) {
+        CGPoint touchLocation = [touch locationInView:self];
+        CGPoint worldPosition = [self screenSpaceToWorldSpace:touchLocation];
+        //printf("Screen touched %f,%f -> %f,%f\n",touchLocation.x,touchLocation.y,worldPosition.x,worldPosition.y);
+        
+        
+        CGPoint screenDistanceMoved = CGPointMake(touchLocation.x-lastScreenTouch.x,touchLocation.y-lastScreenTouch.y);
+        if (panning) {
+            screenDistanceMoved.x /= 160;
+            screenDistanceMoved.y /= 160;
+            screenDistanceMoved.x *= sceneScale;
+            screenDistanceMoved.y *= -sceneScale;
+            positionOffset.x += screenDistanceMoved.x;
+            positionOffset.y += screenDistanceMoved.y;
+        }
+        
+        lastScreenTouch = touchLocation;
+        lastWorldTouch = worldPosition;
+        // test->MouseMove(b2Vec2(lastWorldTouch.x,lastWorldTouch.y));
+    }
+}
+
+- (void) touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
+    // test->MouseUp(b2Vec2(lastWorldTouch.x, lastWorldTouch.y));
+}
+
+- (void) accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)acceleration {
+    // Only run for valid values
+    if (acceleration.y != 0 && acceleration.x != 0) {
+        if (self.world) [self.world setGravityX:acceleration.x Y:acceleration.y];
+    }
+}
+
+
+
+
+/// OpenGL ///
+
+- (void) drawView {
+    [EAGLContext setCurrentContext:context];
+    
+    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
+    glViewport(0, 0, backingWidth, backingHeight);
+    
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    
+    glOrthof(-sceneScale, sceneScale, -sceneScale*1.5f, sceneScale*1.5f, -1.0f, 1.0f);
+    
+    glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity();
+    glTranslatef(positionOffset.x, positionOffset.y,0);
+    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    
+    glEnableClientState(GL_VERTEX_ARRAY);
+    
+    [self.world step];
+    
+    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
+    [context presentRenderbuffer:GL_RENDERBUFFER_OES];
+}
+
+
+- (void) layoutSubviews {
+    [EAGLContext setCurrentContext:context];
+    [self destroyFramebuffer];
+    [self createFramebuffer];
+    [self drawView];
+}
+
+
+- (BOOL) createFramebuffer {
+    
+    glGenFramebuffersOES(1, &viewFramebuffer);
+    glGenRenderbuffersOES(1, &viewRenderbuffer);
+    
+    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
+    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
+    [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
+    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
+    
+    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
+    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
+    
+    if (USE_DEPTH_BUFFER) {
+        glGenRenderbuffersOES(1, &depthRenderbuffer);
+        glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
+        glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight);
+        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
+    }
+    
+    if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
+        NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
+        return NO;
+    }
+    
+    return YES;
+}
+
+
+- (void) destroyFramebuffer {
+    
+    glDeleteFramebuffersOES(1, &viewFramebuffer);
+    viewFramebuffer = 0;
+    glDeleteRenderbuffersOES(1, &viewRenderbuffer);
+    viewRenderbuffer = 0;
+    
+    if(depthRenderbuffer) {
+        glDeleteRenderbuffersOES(1, &depthRenderbuffer);
+        depthRenderbuffer = 0;
+    }
+}
+
+@end
index 6927a66..d9d2b56 100644 (file)
@@ -1,14 +1,16 @@
-#import <Foundation/Foundation.h>
 #include <Box2D/Box2D.h>
+#import "ui/GLES-Render.h"
 
 
 @interface World : NSObject {
-    
+
 @private
-    b2World* _world;
     float _timestep;
     int _velocityIterations;
     int _positionIterations;
+    
+    b2World* _world;
+    GLESDebugDraw debugDraw;
 }
 
 @property (nonatomic, readonly) b2World* world;
@@ -19,7 +21,9 @@
 
 - (World*) init;
 - (World*) initWithTimestep:(float)hz;
-- (World*) initWithTimestep:(float)hz gravityX:(float)x Y:(float)y;
+- (World*) initWithTimestep:(float)hz gravityX:(float)x y:(float)y;
+
+- (void) setGravityX:(float)x y:(float)y;
 
 - (void) step;
 
index 0b4a104..0beb32b 100644 (file)
@@ -1,6 +1,7 @@
 #import "World.h"
 
 
+
 @implementation World
 
 @synthesize world = _world;
 }
 
 - (World*) initWithTimestep:(float)hz {
-    return [self initWithTimestep:hz gravityX:0.0f Y:0.0f];
+    return [self initWithTimestep:hz gravityX:0.0f y:0.0f];
 }
 
-- (World*) initWithTimestep:(float)hz gravityX:(float)x Y:(float)y {
+- (World*) initWithTimestep:(float)hz gravityX:(float)x y:(float)y {
     if ((self = [super init])) {
-        b2Vec2 gravity = b2Vec2(x,y);
-        bool doSleep = true;
-        _world = new b2World(gravity, doSleep);
-        
         _timestep = 1.0f/hz;
         _velocityIterations = 10;
         _positionIterations = 10;
+        
+        b2Vec2 gravity = b2Vec2(x,y);
+        bool doSleep = true;
+        _world = new b2World(gravity, doSleep);
+        // _world->SetDebugDraw(&debugDraw);
     }
     return self;
 }
 }
 
 - (void) step {
-    self.world->Step(self.timestep, self.velocityIterations, self.positionIterations);
+    _world->Step(self.timestep, self.velocityIterations, self.positionIterations);
+    // _world->DrawDebugData();
+}
+
+- (void) setGravityX:(float)x y:(float)y {
+    _world->SetGravity(b2Vec2(x,y));
 }
 
+
+
+
+
 @end
diff --git a/src/tanks/Active.h b/src/tanks/Active.h
new file mode 100644 (file)
index 0000000..b9514a1
--- /dev/null
@@ -0,0 +1,11 @@
+
+/**
+ * Anything that takes a turn is Active.
+ */
+@protocol Active
+
+@property (nonatomic, getter=isActive) BOOL active;
+
+- (void) act;
+
+@end
\ No newline at end of file
diff --git a/src/tanks/Displayable.h b/src/tanks/Displayable.h
new file mode 100644 (file)
index 0000000..c99f41c
--- /dev/null
@@ -0,0 +1,8 @@
+#import "Sparrow.h"
+
+
+@protocol Displayable
+
+@property (nonatomic, readonly) SPDisplayObject* shape;
+
+@end
\ No newline at end of file
index 50950df..8b55c7a 100644 (file)
@@ -1,18 +1,13 @@
-//
-//  Game.h
-//  tanks
-//
-//  Created by dsc on 4/27/11.
-//  Copyright 2011 lttlst.com. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
 #import "Sparrow.h"
-#import "tanks/unit/Unit.h"
+
+#import "physics/World.h"
+
 
 
 @interface Game : SPStage
 
-@property(retain) Unit* unit;
+@property (nonatomic, retain) World* world;
+
+- (void) onEnterFrame:(SPEnterFrameEvent*)event;
 
 @end
diff --git a/src/tanks/Game.m b/src/tanks/Game.m
deleted file mode 100644 (file)
index 377fb6d..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-//
-//  Game.m
-//  tanks
-//
-//  Created by dsc on 4/27/11.
-//  Copyright 2011 lttlst.com. All rights reserved.
-//
-
-#import "Game.h"
-
-
-@implementation Game
-
-@synthesize unit;
-
-- (id)initWithWidth:(float)width height:(float)height {
-    if ( (self = [super initWithWidth:width height:height]) ){
-        unit = [[Unit alloc] initWithWidth:100 height:100 X:50 Y:50];
-        [self addEventListener:@selector(onTouch:) atObject:unit forType:SP_EVENT_TYPE_TOUCH];
-        [self addChild:unit.quad];
-    }
-    return self;
-}
-
-- (void)dealloc {
-    [self setUnit:nil];
-    [super dealloc];
-}
-
-@end
\ No newline at end of file
diff --git a/src/tanks/Game.mm b/src/tanks/Game.mm
new file mode 100644 (file)
index 0000000..aa9a8db
--- /dev/null
@@ -0,0 +1,44 @@
+#import "Game.h"
+#import "tanks/unit/Unit.h"
+
+
+@interface Game ()
+
+@property (nonatomic, retain) Unit* unit;
+
+@end
+
+
+@implementation Game
+
+@synthesize unit;
+@synthesize world;
+
+
+- (id) init {
+    if ( (self = [super init]) ){
+        world = [[[World alloc] init] autorelease];
+        [self addEventListener:@selector(onEnterFrame:) atObject:self forType:SP_EVENT_TYPE_ENTER_FRAME];
+        
+        unit = [[[Unit alloc] init:world] autorelease];
+        [self addEventListener:@selector(onTouch:) atObject:unit forType:SP_EVENT_TYPE_TOUCH];
+        [self addChild:unit.quad];
+    }
+    return self;
+}
+
+- (void) dealloc {
+    [self setUnit:nil];
+    [self setWorld:nil];
+    [super dealloc];
+}
+
+- (void) onEnterFrame:(SPEnterFrameEvent*)event {
+    NSLog(@"Time passed since last frame: %f", event.passedTime);
+    // [world step];
+}
+
+
+
+
+@end
\ No newline at end of file
diff --git a/src/tanks/unit/Actor.h b/src/tanks/unit/Actor.h
new file mode 100644 (file)
index 0000000..335e918
--- /dev/null
@@ -0,0 +1,19 @@
+#import "tanks/Active.h"
+#import "tanks/Displayable.h"
+
+#import "physics/World.h"
+
+
+@interface Actor : NSObject <Active, Displayable> {
+    
+@private
+    BOOL _active;
+    World* _world;
+}
+
+@property (nonatomic, readonly) World* world;
+
+- (id) init:(World*)theWorld;
+
+
+@end
diff --git a/src/tanks/unit/Actor.mm b/src/tanks/unit/Actor.mm
new file mode 100644 (file)
index 0000000..ddb6457
--- /dev/null
@@ -0,0 +1,24 @@
+#import "Actor.h"
+
+
+@implementation Actor
+
+@synthesize active;
+@synthesize world = _world;
+
+
+- (id) init:(World*)theWorld {
+    if ((self = [super init])) {
+        _world = theWorld; // weakref: does not inc refcount
+    }
+    return self;
+}
+
+- (SPDisplayObject*) shape {
+    return nil;
+}
+
+
+- (void) act {}
+
+@end
index 1c8fea5..4e877b6 100644 (file)
@@ -1,20 +1,14 @@
-//
-//  Unit.h
-//  tanks
-//
-//  Created by Doris Chen on 5/7/11.
-//  Copyright 2011 __MyCompanyName__. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
 #import "Sparrow.h"
+#import "tanks/unit/Actor.h"
+#import "physics/World.h"
 
 
-@interface Unit : NSObject {
+@interface Unit : Actor {
 }
 
-@property(nonatomic, retain) SPQuad* quad;
+@property (nonatomic, retain) SPQuad* quad;
+
+- (void) onTouch:(SPTouchEvent*)event;
+
 
--(Unit*)initWithWidth:(int)width height:(int)height X:(int)x Y:(int)y;
--(void)onTouch:(SPTouchEvent*)event;
 @end
diff --git a/src/tanks/unit/Unit.m b/src/tanks/unit/Unit.m
deleted file mode 100644 (file)
index 66da593..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-//
-//  Unit.m
-//  tanks
-//
-//  Created by Doris Chen on 5/7/11.
-//  Copyright 2011 __MyCompanyName__. All rights reserved.
-//
-
-#import "Unit.h"
-
-
-@implementation Unit
-
-@synthesize quad;
-
--(Unit*)initWithWidth:(int)width height:(int)height X:(int)x Y:(int)y {
-  quad = [SPQuad quadWithWidth:width height:height];
-  quad.color = 0xff0000;
-  quad.x = x;
-  quad.y = y;
-  
-  return self;
-}
-
--(void)onTouch:(SPTouchEvent*)event {
-  SPTouch* touch = [[event touchesWithTarget:quad.parent] anyObject];
-  if (touch) {
-    SPPoint* touchPosition = [touch locationInSpace:quad.parent];
-    quad.x = touchPosition.x - quad.width / 2.0f;
-    quad.y = touchPosition.y - quad.height / 2.0f;
-  }
-}
-
-@end
diff --git a/src/tanks/unit/Unit.mm b/src/tanks/unit/Unit.mm
new file mode 100644 (file)
index 0000000..469e6b7
--- /dev/null
@@ -0,0 +1,33 @@
+#import "Unit.h"
+#import "Sparrow.h"
+
+
+@implementation Unit
+
+@synthesize quad;
+
+- (SPDisplayObject*) shape { return quad; }
+
+
+
+- (Unit*) init:(World*)theWorld {
+    if ((self = [super init:theWorld])) {
+        quad = [SPQuad quadWithWidth:32 height:32];
+        quad.color = 0xff0000;
+        quad.x = 0;
+        quad.y = 0;
+    }
+    return self;
+}
+
+- (void) onTouch:(SPTouchEvent*)event {
+    SPTouch* touch = [[event touchesWithTarget:quad.parent] anyObject];
+    if (touch) {
+        SPPoint* touchPosition = [touch locationInSpace:quad.parent];
+        quad.x = touchPosition.x - quad.width / 2.0f;
+        quad.y = touchPosition.y - quad.height / 2.0f;
+    }
+}
+
+
+@end
diff --git a/src/ui/Viewport.h b/src/ui/Viewport.h
new file mode 100644 (file)
index 0000000..1cd86b8
--- /dev/null
@@ -0,0 +1,27 @@
+#include <Box2D/Box2D.h>
+#import "Sparrow.h"
+
+#import "physics/World.h"
+
+
+/**
+ * View subclass which optionally tracks user input gestures that would zoom
+ * or pan the viewport.
+ */
+@interface Viewport : SPView <UIAccelerometerDelegate>
+
+@property (nonatomic, retain) World* world;
+
+@property (nonatomic, assign, getter=isZoomable) BOOL zoomable;
+@property (nonatomic, assign) float viewportZoom;
+
+@property (nonatomic, assign, getter=isPanable) BOOL panable;
+@property (nonatomic, retain) SPPoint *viewportCenter;
+
+
+- (void) drawView;
+
+
+@end
+
+
diff --git a/src/ui/Viewport.mm b/src/ui/Viewport.mm
new file mode 100644 (file)
index 0000000..6bca710
--- /dev/null
@@ -0,0 +1,34 @@
+#import <OpenGLES/EAGL.h>
+#import <OpenGLES/ES1/gl.h>
+#import <OpenGLES/ES1/glext.h>
+#import "Sparrow.h"
+
+#import "Viewport.h"
+#import "World.h"
+
+@implementation Viewport
+
+@synthesize zoomable;
+@synthesize viewportZoom;
+
+@synthesize panable;
+@synthesize viewportCenter;
+
+@synthesize world;
+
+
+- (id) initWithFrame:(CGRect)frame {
+    if ((self = [super initWithFrame:frame])) {
+        zoomable = NO;
+        panable = NO;
+        viewportZoom = 1.0f;
+        viewportCenter = [[[SPPoint alloc] initWithX:0 y:0] autorelease];
+    }
+    return self;
+}
+
+- (void) drawView {
+    
+}
+
+@end
diff --git a/tanks-ios.tmproj b/tanks-ios.tmproj
deleted file mode 100644 (file)
index 12eae2b..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-       <key>currentDocument</key>
-       <string>libs/box2d/src/Box2D/Dynamics/b2World.h</string>
-       <key>documents</key>
-       <array>
-               <dict>
-                       <key>expanded</key>
-                       <true/>
-                       <key>name</key>
-                       <string>src</string>
-                       <key>regexFolderFilter</key>
-                       <string>!.*/(junk|target|html\-template|bin\-debug|\.[^/]*|CVS|_darcs|_MTN|\{arch\}|blib|.*~\.nib|.*\.(framework|app|pbproj|pbxproj|xcode(proj)?|bundle|egg-info))$</string>
-                       <key>sourceDirectory</key>
-                       <string>src</string>
-               </dict>
-               <dict>
-                       <key>name</key>
-                       <string>Tests</string>
-                       <key>regexFolderFilter</key>
-                       <string>!.*/(junk|target|html\-template|bin\-debug|\.[^/]*|CVS|_darcs|_MTN|\{arch\}|blib|.*~\.nib|.*\.(framework|app|pbproj|pbxproj|xcode(proj)?|bundle|egg-info))$</string>
-                       <key>sourceDirectory</key>
-                       <string>libs/box2d/src/Tests</string>
-               </dict>
-               <dict>
-                       <key>expanded</key>
-                       <true/>
-                       <key>name</key>
-                       <string>Box2D</string>
-                       <key>regexFolderFilter</key>
-                       <string>!.*/(junk|target|html\-template|bin\-debug|\.[^/]*|CVS|_darcs|_MTN|\{arch\}|blib|.*~\.nib|.*\.(framework|app|pbproj|pbxproj|xcode(proj)?|bundle|egg-info))$</string>
-                       <key>sourceDirectory</key>
-                       <string>libs/box2d/src/Box2D</string>
-               </dict>
-       </array>
-       <key>fileHierarchyDrawerWidth</key>
-       <integer>217</integer>
-       <key>metaData</key>
-       <dict>
-               <key>libs/box2d/src/Box2D/Dynamics/Joints/b2MouseJoint.h</key>
-               <dict>
-                       <key>caret</key>
-                       <dict>
-                               <key>column</key>
-                               <integer>0</integer>
-                               <key>line</key>
-                               <integer>0</integer>
-                       </dict>
-                       <key>firstVisibleColumn</key>
-                       <integer>0</integer>
-                       <key>firstVisibleLine</key>
-                       <integer>1</integer>
-               </dict>
-               <key>libs/box2d/src/Box2D/Dynamics/Joints/b2PrismaticJoint.h</key>
-               <dict>
-                       <key>caret</key>
-                       <dict>
-                               <key>column</key>
-                               <integer>0</integer>
-                               <key>line</key>
-                               <integer>0</integer>
-                       </dict>
-                       <key>firstVisibleColumn</key>
-                       <integer>0</integer>
-                       <key>firstVisibleLine</key>
-                       <integer>0</integer>
-               </dict>
-               <key>libs/box2d/src/Box2D/Dynamics/b2World.h</key>
-               <dict>
-                       <key>caret</key>
-                       <dict>
-                               <key>column</key>
-                               <integer>0</integer>
-                               <key>line</key>
-                               <integer>0</integer>
-                       </dict>
-                       <key>firstVisibleColumn</key>
-                       <integer>0</integer>
-                       <key>firstVisibleLine</key>
-                       <integer>189</integer>
-               </dict>
-               <key>libs/box2d/src/Tests/CompoundShapes.h</key>
-               <dict>
-                       <key>caret</key>
-                       <dict>
-                               <key>column</key>
-                               <integer>0</integer>
-                               <key>line</key>
-                               <integer>0</integer>
-                       </dict>
-                       <key>firstVisibleColumn</key>
-                       <integer>0</integer>
-                       <key>firstVisibleLine</key>
-                       <integer>45</integer>
-               </dict>
-               <key>libs/box2d/src/Tests/Gears.h</key>
-               <dict>
-                       <key>caret</key>
-                       <dict>
-                               <key>column</key>
-                               <integer>0</integer>
-                               <key>line</key>
-                               <integer>0</integer>
-                       </dict>
-                       <key>firstVisibleColumn</key>
-                       <integer>0</integer>
-                       <key>firstVisibleLine</key>
-                       <integer>0</integer>
-               </dict>
-               <key>src/physics/Physics.h</key>
-               <dict>
-                       <key>caret</key>
-                       <dict>
-                               <key>column</key>
-                               <integer>19</integer>
-                               <key>line</key>
-                               <integer>14</integer>
-                       </dict>
-                       <key>firstVisibleColumn</key>
-                       <integer>0</integer>
-                       <key>firstVisibleLine</key>
-                       <integer>0</integer>
-               </dict>
-               <key>src/physics/Physics.mm</key>
-               <dict>
-                       <key>caret</key>
-                       <dict>
-                               <key>column</key>
-                               <integer>0</integer>
-                               <key>line</key>
-                               <integer>0</integer>
-                       </dict>
-                       <key>firstVisibleColumn</key>
-                       <integer>0</integer>
-                       <key>firstVisibleLine</key>
-                       <integer>0</integer>
-               </dict>
-               <key>src/render/iPhoneTest.h</key>
-               <dict>
-                       <key>caret</key>
-                       <dict>
-                               <key>column</key>
-                               <integer>23</integer>
-                               <key>line</key>
-                               <integer>168</integer>
-                       </dict>
-                       <key>firstVisibleColumn</key>
-                       <integer>0</integer>
-                       <key>firstVisibleLine</key>
-                       <integer>93</integer>
-               </dict>
-               <key>src/render/iPhoneTest.mm</key>
-               <dict>
-                       <key>caret</key>
-                       <dict>
-                               <key>column</key>
-                               <integer>21</integer>
-                               <key>line</key>
-                               <integer>42</integer>
-                       </dict>
-                       <key>firstVisibleColumn</key>
-                       <integer>0</integer>
-                       <key>firstVisibleLine</key>
-                       <integer>11</integer>
-               </dict>
-       </dict>
-       <key>openDocuments</key>
-       <array>
-               <string>src/render/iPhoneTest.h</string>
-               <string>src/physics/Physics.h</string>
-               <string>src/physics/Physics.mm</string>
-               <string>src/render/iPhoneTest.mm</string>
-               <string>libs/box2d/src/Tests/Gears.h</string>
-               <string>libs/box2d/src/Tests/CompoundShapes.h</string>
-               <string>libs/box2d/src/Box2D/Dynamics/Joints/b2MouseJoint.h</string>
-               <string>libs/box2d/src/Box2D/Dynamics/Joints/b2PrismaticJoint.h</string>
-               <string>libs/box2d/src/Box2D/Dynamics/b2World.h</string>
-       </array>
-       <key>showFileHierarchyDrawer</key>
-       <false/>
-       <key>windowFrame</key>
-       <string>{{511, 0}, {1534, 1578}}</string>
-</dict>
-</plist>
index c022019..2191a3c 100644 (file)
                4996691B136930E8006E8125 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49966916136930E8006E8125 /* QuartzCore.framework */; };
                49DA67D4137847A7004841E9 /* World.h in Headers */ = {isa = PBXBuildFile; fileRef = 49DA67D2137847A7004841E9 /* World.h */; };
                49DA67D5137847A7004841E9 /* World.mm in Sources */ = {isa = PBXBuildFile; fileRef = 49DA67D3137847A7004841E9 /* World.mm */; };
-               49F2D9C413764666000B6B8C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 49F2D9B013764666000B6B8C /* main.m */; };
-               49F2D9C513764666000B6B8C /* RootAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 49F2D9B513764666000B6B8C /* RootAppDelegate.m */; };
-               49F2D9C613764666000B6B8C /* Game.m in Sources */ = {isa = PBXBuildFile; fileRef = 49F2D9B813764666000B6B8C /* Game.m */; };
+               49E834441380CB61007A6598 /* GLES-Render.h in Headers */ = {isa = PBXBuildFile; fileRef = 49E834421380CB61007A6598 /* GLES-Render.h */; };
+               49E834451380CB61007A6598 /* GLES-Render.mm in Sources */ = {isa = PBXBuildFile; fileRef = 49E834431380CB61007A6598 /* GLES-Render.mm */; };
+               49E834501380E234007A6598 /* Displayable.h in Headers */ = {isa = PBXBuildFile; fileRef = 49E8344F1380E234007A6598 /* Displayable.h */; };
+               49E834531380EBB2007A6598 /* Actor.h in Headers */ = {isa = PBXBuildFile; fileRef = 49E834511380EBB2007A6598 /* Actor.h */; };
+               49E834541380EBB2007A6598 /* Actor.mm in Sources */ = {isa = PBXBuildFile; fileRef = 49E834521380EBB2007A6598 /* Actor.mm */; };
+               49E8345613810618007A6598 /* Active.h in Headers */ = {isa = PBXBuildFile; fileRef = 49E8345513810618007A6598 /* Active.h */; };
+               49F2D9C413764666000B6B8C /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 49F2D9B013764666000B6B8C /* main.mm */; };
+               49F2D9C513764666000B6B8C /* RootAppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 49F2D9B513764666000B6B8C /* RootAppDelegate.mm */; };
+               49F2D9C613764666000B6B8C /* Game.mm in Sources */ = {isa = PBXBuildFile; fileRef = 49F2D9B813764666000B6B8C /* Game.mm */; };
                49F2D9C713764666000B6B8C /* MainWindow_iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 49F2D9BB13764666000B6B8C /* MainWindow_iPad.xib */; };
-               49F2D9C813764666000B6B8C /* RootAppDelegate_iPad.m in Sources */ = {isa = PBXBuildFile; fileRef = 49F2D9BE13764666000B6B8C /* RootAppDelegate_iPad.m */; };
+               49F2D9C813764666000B6B8C /* RootAppDelegate_iPad.mm in Sources */ = {isa = PBXBuildFile; fileRef = 49F2D9BE13764666000B6B8C /* RootAppDelegate_iPad.mm */; };
                49F2D9C913764666000B6B8C /* MainWindow_iPhone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 49F2D9C013764666000B6B8C /* MainWindow_iPhone.xib */; };
-               49F2D9CA13764666000B6B8C /* RootAppDelegate_iPhone.m in Sources */ = {isa = PBXBuildFile; fileRef = 49F2D9C313764666000B6B8C /* RootAppDelegate_iPhone.m */; };
+               49F2D9CA13764666000B6B8C /* RootAppDelegate_iPhone.mm in Sources */ = {isa = PBXBuildFile; fileRef = 49F2D9C313764666000B6B8C /* RootAppDelegate_iPhone.mm */; };
                49F2D9CD13764710000B6B8C /* RootAppDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 49F2D9B413764666000B6B8C /* RootAppDelegate.h */; };
                49F2D9CE13764710000B6B8C /* Game.h in Headers */ = {isa = PBXBuildFile; fileRef = 49F2D9B713764666000B6B8C /* Game.h */; };
                49F2D9CF13764710000B6B8C /* RootAppDelegate_iPad.h in Headers */ = {isa = PBXBuildFile; fileRef = 49F2D9BD13764666000B6B8C /* RootAppDelegate_iPad.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 */; };
-               49F2DAF213765004000B6B8C /* GLES-Render.h in Headers */ = {isa = PBXBuildFile; fileRef = 49F2DAE613765004000B6B8C /* GLES-Render.h */; };
-               49F2DAF313765004000B6B8C /* GLES-Render.mm in Sources */ = {isa = PBXBuildFile; fileRef = 49F2DAE713765004000B6B8C /* GLES-Render.mm */; };
                49F2DB341376632E000B6B8C /* Unit.h in Headers */ = {isa = PBXBuildFile; fileRef = 49F2DB321376632E000B6B8C /* Unit.h */; };
-               49F2DB351376632E000B6B8C /* Unit.m in Sources */ = {isa = PBXBuildFile; fileRef = 49F2DB331376632E000B6B8C /* Unit.m */; };
+               49F2DB351376632E000B6B8C /* Unit.mm in Sources */ = {isa = PBXBuildFile; fileRef = 49F2DB331376632E000B6B8C /* Unit.mm */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
 
 /* Begin PBXFileReference section */
                494DE9961376927C00FDB3D7 /* libBox2D.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libBox2D.a; sourceTree = SOURCE_ROOT; };
+               496D95E91379865A00C1D33E /* PhysicsDebugView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PhysicsDebugView.h; sourceTree = "<group>"; };
+               496D95EA1379865A00C1D33E /* PhysicsDebugView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PhysicsDebugView.mm; sourceTree = "<group>"; };
+               496D95F7137A358100C1D33E /* Viewport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Viewport.h; sourceTree = "<group>"; };
+               496D95F8137A358100C1D33E /* Viewport.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Viewport.mm; sourceTree = "<group>"; };
                499668C213692E2D006E8125 /* Tanks.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Tanks.app; sourceTree = BUILT_PRODUCTS_DIR; };
                499668C613692E2D006E8125 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
                499668C813692E2D006E8125 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
                49966916136930E8006E8125 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
                49DA67D2137847A7004841E9 /* World.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = World.h; sourceTree = "<group>"; };
                49DA67D3137847A7004841E9 /* World.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = World.mm; sourceTree = "<group>"; };
+               49E834421380CB61007A6598 /* GLES-Render.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GLES-Render.h"; sourceTree = "<group>"; };
+               49E834431380CB61007A6598 /* GLES-Render.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "GLES-Render.mm"; sourceTree = "<group>"; };
+               49E8344F1380E234007A6598 /* Displayable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Displayable.h; sourceTree = "<group>"; };
+               49E834511380EBB2007A6598 /* Actor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Actor.h; sourceTree = "<group>"; };
+               49E834521380EBB2007A6598 /* Actor.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Actor.mm; sourceTree = "<group>"; };
+               49E8345513810618007A6598 /* Active.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Active.h; sourceTree = "<group>"; };
                49F2D99B137645DF000B6B8C /* box2d-ios.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "box2d-ios.xcodeproj"; path = "libs/box2d/box2d-ios.xcodeproj"; sourceTree = "<group>"; };
-               49F2D9B013764666000B6B8C /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+               49F2D9B013764666000B6B8C /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = "<group>"; };
                49F2D9B213764666000B6B8C /* prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = prefix.pch; sourceTree = "<group>"; };
                49F2D9B413764666000B6B8C /* RootAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RootAppDelegate.h; sourceTree = "<group>"; };
-               49F2D9B513764666000B6B8C /* RootAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RootAppDelegate.m; sourceTree = "<group>"; };
+               49F2D9B513764666000B6B8C /* RootAppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RootAppDelegate.mm; sourceTree = "<group>"; };
                49F2D9B713764666000B6B8C /* Game.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Game.h; sourceTree = "<group>"; };
-               49F2D9B813764666000B6B8C /* Game.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Game.m; sourceTree = "<group>"; };
+               49F2D9B813764666000B6B8C /* Game.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Game.mm; sourceTree = "<group>"; };
                49F2D9BC13764666000B6B8C /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainWindow_iPad.xib; sourceTree = "<group>"; };
                49F2D9BD13764666000B6B8C /* RootAppDelegate_iPad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RootAppDelegate_iPad.h; sourceTree = "<group>"; };
-               49F2D9BE13764666000B6B8C /* RootAppDelegate_iPad.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RootAppDelegate_iPad.m; sourceTree = "<group>"; };
+               49F2D9BE13764666000B6B8C /* RootAppDelegate_iPad.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RootAppDelegate_iPad.mm; sourceTree = "<group>"; };
                49F2D9C113764666000B6B8C /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainWindow_iPhone.xib; sourceTree = "<group>"; };
                49F2D9C213764666000B6B8C /* RootAppDelegate_iPhone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RootAppDelegate_iPhone.h; sourceTree = "<group>"; };
-               49F2D9C313764666000B6B8C /* RootAppDelegate_iPhone.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RootAppDelegate_iPhone.m; sourceTree = "<group>"; };
+               49F2D9C313764666000B6B8C /* RootAppDelegate_iPhone.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RootAppDelegate_iPhone.mm; sourceTree = "<group>"; };
                49F2D9D513764A9B000B6B8C /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
                49F2D9D613764A9B000B6B8C /* tanks-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "tanks-Info.plist"; sourceTree = "<group>"; };
                49F2DA1D13764ED5000B6B8C /* Sparrow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Sparrow.h; sourceTree = "<group>"; };
                49F2DAE313765004000B6B8C /* Box2DView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Box2DView.h; sourceTree = "<group>"; };
                49F2DAE413765004000B6B8C /* Box2DView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Box2DView.mm; sourceTree = "<group>"; };
                49F2DAE513765004000B6B8C /* Delegates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Delegates.h; sourceTree = "<group>"; };
-               49F2DAE613765004000B6B8C /* GLES-Render.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GLES-Render.h"; sourceTree = "<group>"; };
-               49F2DAE713765004000B6B8C /* GLES-Render.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "GLES-Render.mm"; sourceTree = "<group>"; };
                49F2DAE813765004000B6B8C /* iPhoneTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iPhoneTest.h; sourceTree = "<group>"; };
                49F2DAE913765004000B6B8C /* iPhoneTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = iPhoneTest.mm; sourceTree = "<group>"; };
                49F2DAEA13765004000B6B8C /* iPhoneTestEntries.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = iPhoneTestEntries.mm; sourceTree = "<group>"; };
                49F2DAEB13765004000B6B8C /* TestEntriesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestEntriesViewController.h; sourceTree = "<group>"; };
                49F2DAEC13765004000B6B8C /* TestEntriesViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TestEntriesViewController.mm; sourceTree = "<group>"; };
                49F2DB321376632E000B6B8C /* Unit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Unit.h; sourceTree = "<group>"; };
-               49F2DB331376632E000B6B8C /* Unit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Unit.m; sourceTree = "<group>"; };
+               49F2DB331376632E000B6B8C /* Unit.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Unit.mm; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
                        isa = PBXGroup;
                        children = (
                                49F2D9AF13764666000B6B8C /* display */,
-                               49F2D9B013764666000B6B8C /* main.m */,
+                               49F2D9B013764666000B6B8C /* main.mm */,
                                49F2D9B113764666000B6B8C /* physics */,
                                49F2D9B213764666000B6B8C /* prefix.pch */,
                                49F2D9B313764666000B6B8C /* render */,
                                49F2D9B413764666000B6B8C /* RootAppDelegate.h */,
-                               49F2D9B513764666000B6B8C /* RootAppDelegate.m */,
+                               49F2D9B513764666000B6B8C /* RootAppDelegate.mm */,
                                49F2D9B613764666000B6B8C /* tanks */,
                                49F2D9B913764666000B6B8C /* ui */,
                        );
                        children = (
                                49DA67D2137847A7004841E9 /* World.h */,
                                49DA67D3137847A7004841E9 /* World.mm */,
+                               496D95E91379865A00C1D33E /* PhysicsDebugView.h */,
+                               496D95EA1379865A00C1D33E /* PhysicsDebugView.mm */,
                        );
                        path = physics;
                        sourceTree = "<group>";
                                49F2DAE313765004000B6B8C /* Box2DView.h */,
                                49F2DAE413765004000B6B8C /* Box2DView.mm */,
                                49F2DAE513765004000B6B8C /* Delegates.h */,
-                               49F2DAE613765004000B6B8C /* GLES-Render.h */,
-                               49F2DAE713765004000B6B8C /* GLES-Render.mm */,
                                49F2DAE813765004000B6B8C /* iPhoneTest.h */,
                                49F2DAE913765004000B6B8C /* iPhoneTest.mm */,
                                49F2DAEA13765004000B6B8C /* iPhoneTestEntries.mm */,
                49F2D9B613764666000B6B8C /* tanks */ = {
                        isa = PBXGroup;
                        children = (
+                               49E8345513810618007A6598 /* Active.h */,
+                               49E8344F1380E234007A6598 /* Displayable.h */,
                                49F2DB311376632E000B6B8C /* unit */,
                                49F2D9B713764666000B6B8C /* Game.h */,
-                               49F2D9B813764666000B6B8C /* Game.m */,
+                               49F2D9B813764666000B6B8C /* Game.mm */,
                        );
                        path = tanks;
                        sourceTree = "<group>";
                49F2D9B913764666000B6B8C /* ui */ = {
                        isa = PBXGroup;
                        children = (
+                               49E834421380CB61007A6598 /* GLES-Render.h */,
+                               49E834431380CB61007A6598 /* GLES-Render.mm */,
                                49F2D9BA13764666000B6B8C /* iPad */,
                                49F2D9BF13764666000B6B8C /* iPhone */,
+                               496D95F7137A358100C1D33E /* Viewport.h */,
+                               496D95F8137A358100C1D33E /* Viewport.mm */,
                        );
                        path = ui;
                        sourceTree = "<group>";
                        children = (
                                49F2D9BB13764666000B6B8C /* MainWindow_iPad.xib */,
                                49F2D9BD13764666000B6B8C /* RootAppDelegate_iPad.h */,
-                               49F2D9BE13764666000B6B8C /* RootAppDelegate_iPad.m */,
+                               49F2D9BE13764666000B6B8C /* RootAppDelegate_iPad.mm */,
                        );
                        path = iPad;
                        sourceTree = "<group>";
                        children = (
                                49F2D9C013764666000B6B8C /* MainWindow_iPhone.xib */,
                                49F2D9C213764666000B6B8C /* RootAppDelegate_iPhone.h */,
-                               49F2D9C313764666000B6B8C /* RootAppDelegate_iPhone.m */,
+                               49F2D9C313764666000B6B8C /* RootAppDelegate_iPhone.mm */,
                        );
                        path = iPhone;
                        sourceTree = "<group>";
                        isa = PBXGroup;
                        children = (
                                49F2DB321376632E000B6B8C /* Unit.h */,
-                               49F2DB331376632E000B6B8C /* Unit.m */,
+                               49F2DB331376632E000B6B8C /* Unit.mm */,
+                               49E834511380EBB2007A6598 /* Actor.h */,
+                               49E834521380EBB2007A6598 /* Actor.mm */,
                        );
                        path = unit;
                        sourceTree = "<group>";
                        isa = PBXHeadersBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
-                               49F2D9CD13764710000B6B8C /* RootAppDelegate.h in Headers */,
-                               49F2D9CE13764710000B6B8C /* Game.h in Headers */,
-                               49F2D9CF13764710000B6B8C /* RootAppDelegate_iPad.h in Headers */,
-                               49F2D9D013764710000B6B8C /* RootAppDelegate_iPhone.h in Headers */,
                                49F2DA8213764ED6000B6B8C /* SPAVSound.h in Headers */,
                                49F2DA8413764ED6000B6B8C /* SPAVSoundChannel.h in Headers */,
                                49F2DA8613764ED6000B6B8C /* SPALSound.h in Headers */,
                                49F2DADB13764ED6000B6B8C /* SPPoolObject.h in Headers */,
                                49F2DADD13764ED6000B6B8C /* SPUtils.h in Headers */,
                                49F2DADF13764ED6000B6B8C /* Sparrow.h in Headers */,
-                               49F2DAF213765004000B6B8C /* GLES-Render.h in Headers */,
+                               49F2D9CD13764710000B6B8C /* RootAppDelegate.h in Headers */,
+                               49F2D9CF13764710000B6B8C /* RootAppDelegate_iPad.h in Headers */,
+                               49F2D9D013764710000B6B8C /* RootAppDelegate_iPhone.h in Headers */,
+                               49F2D9CE13764710000B6B8C /* Game.h in Headers */,
                                49F2DB341376632E000B6B8C /* Unit.h in Headers */,
                                49DA67D4137847A7004841E9 /* World.h in Headers */,
+                               49E834441380CB61007A6598 /* GLES-Render.h in Headers */,
+                               49E834501380E234007A6598 /* Displayable.h in Headers */,
+                               49E834531380EBB2007A6598 /* Actor.h in Headers */,
+                               49E8345613810618007A6598 /* Active.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
 /* Begin PBXProject section */
                499668B913692E2D006E8125 /* Project object */ = {
                        isa = PBXProject;
+                       attributes = {
+                               ORGANIZATIONNAME = lttlst.com;
+                       };
                        buildConfigurationList = 499668BC13692E2D006E8125 /* Build configuration list for PBXProject "tanks" */;
                        compatibilityVersion = "Xcode 3.2";
                        developmentRegion = English;
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
-                               49F2D9C413764666000B6B8C /* main.m in Sources */,
-                               49F2D9C513764666000B6B8C /* RootAppDelegate.m in Sources */,
-                               49F2D9C613764666000B6B8C /* Game.m in Sources */,
-                               49F2D9C813764666000B6B8C /* RootAppDelegate_iPad.m in Sources */,
-                               49F2D9CA13764666000B6B8C /* RootAppDelegate_iPhone.m in Sources */,
                                49F2DA8313764ED6000B6B8C /* SPAVSound.m in Sources */,
                                49F2DA8513764ED6000B6B8C /* SPAVSoundChannel.m in Sources */,
                                49F2DA8713764ED6000B6B8C /* SPALSound.m in Sources */,
                                49F2DADA13764ED6000B6B8C /* SPNSExtensions.m in Sources */,
                                49F2DADC13764ED6000B6B8C /* SPPoolObject.m in Sources */,
                                49F2DADE13764ED6000B6B8C /* SPUtils.m in Sources */,
-                               49F2DAF313765004000B6B8C /* GLES-Render.mm in Sources */,
-                               49F2DB351376632E000B6B8C /* Unit.m in Sources */,
+                               49F2D9C413764666000B6B8C /* main.mm in Sources */,
+                               49F2D9C513764666000B6B8C /* RootAppDelegate.mm in Sources */,
+                               49F2D9C813764666000B6B8C /* RootAppDelegate_iPad.mm in Sources */,
+                               49F2D9CA13764666000B6B8C /* RootAppDelegate_iPhone.mm in Sources */,
                                49DA67D5137847A7004841E9 /* World.mm in Sources */,
+                               49F2D9C613764666000B6B8C /* Game.mm in Sources */,
+                               49F2DB351376632E000B6B8C /* Unit.mm in Sources */,
+                               49E834451380CB61007A6598 /* GLES-Render.mm in Sources */,
+                               49E834541380EBB2007A6598 /* Actor.mm in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                499668FF13692E2D006E8125 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               ALWAYS_SEARCH_USER_PATHS = YES;
                                COPY_PHASE_STRIP = NO;
                                GCC_DYNAMIC_NO_PIC = NO;
                                GCC_PRECOMPILE_PREFIX_HEADER = YES;
                                        "\"$(SRCROOT)/libs\"/**",
                                        "\"$(SRCROOT)\"",
                                );
-                               OTHER_LDFLAGS = "";
                                PRODUCT_NAME = "$(TARGET_NAME)";
-                               USER_HEADER_SEARCH_PATHS = "libs/** src/**";
-                               WRAPPER_EXTENSION = app;
+                               USER_HEADER_SEARCH_PATHS = "src libs libs/**";
                        };
                        name = Debug;
                };
                4996690013692E2D006E8125 /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               ALWAYS_SEARCH_USER_PATHS = YES;
                                COPY_PHASE_STRIP = YES;
                                GCC_PRECOMPILE_PREFIX_HEADER = YES;
                                GCC_PREFIX_HEADER = src/prefix.pch;
                                        "\"$(SRCROOT)/libs\"/**",
                                        "\"$(SRCROOT)\"",
                                );
-                               OTHER_LDFLAGS = "";
                                PRODUCT_NAME = "$(TARGET_NAME)";
-                               USER_HEADER_SEARCH_PATHS = "libs/** src/**";
+                               USER_HEADER_SEARCH_PATHS = "src libs libs/**";
                                VALIDATE_PRODUCT = YES;
-                               WRAPPER_EXTENSION = app;
                        };
                        name = Release;
                };