Welp, Debug drawing works, but for some reason I can't get OpenGL to apply a rotation...
authordsc <david.schoonover@gmail.com>
Sun, 29 May 2011 20:06:05 +0000 (13:06 -0700)
committerdsc <david.schoonover@gmail.com>
Sun, 29 May 2011 20:06:05 +0000 (13:06 -0700)
35 files changed:
libs/sparrow/src/Classes/SPDisplayObject.h
libs/sparrow/src/Classes/SPDisplayObject.m
libs/sparrow/src/Classes/SPRenderSupport.m
src/game/QQDisplayable.h
src/game/QQGame.h
src/game/QQGame.mm
src/game/QQPhysical.h
src/game/actor/QQActor.h
src/game/actor/QQActor.mm
src/game/actor/QQUnit.h
src/game/actor/QQUnit.mm
src/game/map/QQLevel.h [new file with mode: 0644]
src/game/map/QQLevel.mm [new file with mode: 0644]
src/game/map/QQMap.h [new file with mode: 0644]
src/game/map/QQMap.mm [new file with mode: 0644]
src/game/map/QQRoom.h [new file with mode: 0644]
src/game/map/QQRoom.mm [new file with mode: 0644]
src/physics/QQWorld.h
src/physics/QQWorld.mm
src/physics/debug/QQGLESDebugDraw.h
src/physics/debug/QQGLESDebugDraw.mm
src/physics/debug/QQPhysicsDebugView.h
src/physics/debug/QQPhysicsDebugView.mm
src/physics/debug/QQPhysicsDebugView2.h [new file with mode: 0644]
src/physics/debug/QQPhysicsDebugView2.mm [new file with mode: 0644]
src/prefix.pch
src/render/QQShape.h [new file with mode: 0644]
src/render/QQShape.mm [new file with mode: 0644]
src/render/QQSparrowExtensions.h
src/render/QQSparrowExtensions.mm
src/ui/QQAppDelegate.h
src/ui/QQAppDelegate.mm
src/ui/iPad/en.lproj/MainWindow_iPad.xib
src/ui/iPhone/en.lproj/MainWindow_iPhone.xib
tanks.xcodeproj/project.pbxproj

index 2e85055..e6b931c 100644 (file)
@@ -82,6 +82,8 @@
     float mY;
     float mScaleX;
     float mScaleY;
+    float mRegX;
+    float mRegY;
     float mRotationZ;
     float mAlpha;
     BOOL mVisible;
 /// @name Properties
 /// ----------------
 
-/// The x coordinates of the object relative to the local coordinates of the parent.
+/// The x coordinate of the object relative to the local coordinates of the parent.
 @property (nonatomic, assign) float x;
 
-/// The y coordinates of the object relative to the local coordinates of the parent.
+/// The y coordinate of the object relative to the local coordinates of the parent.
 @property (nonatomic, assign) float y;
 
 /// The horizontal scale factor. "1" means no scale, negative values flip the object.
 /// The height of the object in points.
 @property (nonatomic, assign) float height;
 
+/// The x coordinate of the object's rotational origin in local coordinates.
+@property (nonatomic, assign) float registrationX;
+
+/// The y coordinate of the object's rotational origin in local coordinates.
+@property (nonatomic, assign) float registrationY;
+
 /// The rotation of the object in radians. (In Sparrow, all angles are measured in radians.)
 @property (nonatomic, assign) float rotation;
 
index 6ef3c6c..d7c0378 100644 (file)
@@ -24,6 +24,8 @@
 @synthesize y = mY;
 @synthesize scaleX = mScaleX;
 @synthesize scaleY = mScaleY;
+@synthesize registrationX = mRegX;
+@synthesize registrationY = mRegY;
 @synthesize rotation = mRotationZ;
 @synthesize parent = mParent;
 @synthesize alpha = mAlpha;
@@ -48,6 +50,9 @@
         mAlpha = 1.0f;
         mScaleX = 1.0f;
         mScaleY = 1.0f;
+        mRegX = 0;
+        mRegY = 0;
+        mRotationZ = 0;
         mVisible = YES;
         mTouchable = YES;
     }
 {
     SPMatrix *matrix = [[SPMatrix alloc] init];
     
-    if (mScaleX != 1.0f || mScaleY != 1.0f) [matrix scaleXBy:mScaleX yBy:mScaleY];
-    if (mRotationZ != 0.0f)                 [matrix rotateBy:mRotationZ];
     if (mX != 0.0f || mY != 0.0f)           [matrix translateXBy:mX yBy:mY];
+    if (mRotationZ != 0.0f) {
+        bool regMatters = (mRegX != 0.0f || mRegY != 0.0f);
+        if (regMatters) [matrix translateXBy:mRegX yBy:mRegY];
+        [matrix rotateBy:mRotationZ];
+        if (regMatters) [matrix translateXBy:-mRegX yBy:-mRegY];
+    }
+    if (mScaleX != 1.0f || mScaleY != 1.0f) [matrix scaleXBy:mScaleX yBy:mScaleY];
     
     return [matrix autorelease];
 }
index 13103ec..e752e06 100644 (file)
@@ -24,7 +24,7 @@
 
 - (id)init
 {
-    if (self = [super init])
+    if ((self = [super init]))
     {
         mBoundTextureID = UINT_MAX;
         mPremultipliedAlpha = YES;
 {
     float x = object.x;
     float y = object.y;
+    float regX = object.registrationX;
+    float regY = object.registrationY;
     float rotation = object.rotation;
     float scaleX = object.scaleX;
     float scaleY = object.scaleY;
     
     if (x != 0.0f || y != 0.0f)           glTranslatef(x, y, 0);
-    if (rotation != 0.0f)                 glRotatef(SP_R2D(rotation), 0.0f, 0.0f, 1.0f);
-    if (scaleX != 0.0f || scaleY != 0.0f) glScalef(scaleX, scaleY, 1.0f); 
+    if (rotation != 0.0f) {
+        bool regMatters = (regX != 0.0f || regY != 0.0f);
+        if (regMatters) glTranslatef(regX, regY, 0);
+        glRotatef(SP_R2D(rotation), 0.0f, 0.0f, 1.0f);
+        if (regMatters) glTranslatef(-regX, -regY, 0);
+    }
+    if (scaleX != 0.0f || scaleY != 0.0f) glScalef(scaleX, scaleY, 1.0f);
 }
 
 + (void)setupOrthographicRenderingWithLeft:(float)left right:(float)right 
index ab60dbf..4d0852e 100644 (file)
@@ -9,6 +9,10 @@
 @property (nonatomic, readwrite, assign, getter=isDirty) BOOL dirty; // TODO: implement this and fix various [shape setPosition] calls
 @property (nonatomic, readwrite, retain) SPDisplayObject* shape;
 
+/** Intended center of the shape in points. */
+@property (nonatomic, readwrite, assign) float shapeCenterX;
+@property (nonatomic, readwrite, assign) float shapeCenterY;
+
 /**
  * Called to setup the Sparrow shape.
  */
index e0a6ff1..fd5d95b 100644 (file)
@@ -1,25 +1,41 @@
 #import "Sparrow.h"
 
 #import "physics/QQWorld.h"
+#import "physics/debug/QQPhysicsDebugView.h"
 #import "game/actor/QQActor.h"
+#import "game/map/QQLevel.h"
 
 
 @interface QQGame : SPStage {
     
-    long _ticks;
-    
 @private
     QQWorld* _world;
+    QQLevel* _level;
+    SPSprite* _root;
+    
     NSMutableSet* _actors;
     NSMutableSet* _awake;
     NSMutableSet* _units;
     NSMutableSet* _bullets;
+    
+    QQPhysicsDebugView* _debugView;
+    BOOL _debugDrawingEnabled;
+    
+    long _ticks;
+    BOOL _running;
 }
 
-@property (nonatomic, assign, readonly) long ticks;
+@property (nonatomic, readonly) QQWorld* world;
+@property (nonatomic, readonly) QQLevel* level;
+@property (nonatomic, readonly) NSSet* actors;
+
+@property (nonatomic, readonly, assign) long ticks;
+@property (nonatomic, readonly, getter=isPaused) BOOL paused;
+@property (nonatomic, readwrite, assign) BOOL debugDrawingEnabled;
+
+- (void) start;
+- (void) stop;
 
-@property (nonatomic, retain) QQWorld* world;
-@property (nonatomic, retain) NSSet* actors;
 
 - (void) tick:(float)elapsed;
 
index 3dbfb59..a44f611 100644 (file)
@@ -16,10 +16,14 @@ static QQGame* _CurrentGame = NULL;
 
 @implementation QQGame
 
-@synthesize ticks  = _ticks;
 @synthesize world  = _world;
+@synthesize level  = _level;
 @synthesize actors = _actors;
 
+@synthesize ticks  = _ticks;
+@synthesize paused = _running;
+@synthesize debugDrawingEnabled = _debugDrawingEnabled;
+
 
 - (id) init {
     if (_CurrentGame) {
@@ -34,30 +38,68 @@ static QQGame* _CurrentGame = NULL;
     if ( (self = [super init]) ){
         _CurrentGame = self;
         _ticks = 0;
-        _actors = [[NSMutableArray alloc] initWithCapacity:10];
+        _running = NO;
+        
         _world = [[QQWorld alloc] init];
-        _world.debugDrawingEnabled = YES;
+        _root = [SPSprite sprite];
+        [self addChild:_root];
+        _level = [[QQLevel alloc] init];
+        [_root addChild:_level];
+        _debugView = [[QQPhysicsDebugView alloc] initWithWorld:_world];
+        [_root addChild:_debugView];
+        self.debugDrawingEnabled = YES;
+        
+        _actors = [[NSMutableArray alloc] initWithCapacity:10];
         
-        CGSize screen = [UIScreen mainScreen].bounds.size;
-        float wMax = screen.width  / _world.scale;
-        float hMax = screen.height / _world.scale;
+        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];
-        
-        [self addEventListener:@selector(onEnterFrame:) atObject:self forType:SP_EVENT_TYPE_ENTER_FRAME];
     }
     return self;
 }
 
 - (void) dealloc {
     [self removeEventListener:@selector(onEnterFrame:) atObject:self forType:SP_EVENT_TYPE_ENTER_FRAME];
+    [self removeAllChildren];
+    
     [_actors removeAllObjects];
     [_actors release];
+    
+    [_level release];
+    [_debugView release];
     [_world release];
+    
     _CurrentGame = NULL;
     [super dealloc];
 }
 
+
+/// properties
+
+- (void) setDebugDrawingEnabled:(BOOL)enable {
+    _debugDrawingEnabled = _debugView.visible = enable;
+}
+
+
+
+/// methods
+
+- (void) start {
+    if (!_running) {
+        _running = YES;
+        [self addEventListener:@selector(onEnterFrame:) atObject:self forType:SP_EVENT_TYPE_ENTER_FRAME];
+    }
+}
+
+- (void) stop {
+    if (_running) {
+        [self removeEventListener:@selector(onEnterFrame:) atObject:self forType:SP_EVENT_TYPE_ENTER_FRAME];
+        _running = NO;
+    }
+}
+
 - (QQGame*) addActor:(QQActor*)actor {
     [_actors addObject:actor];
     return self;
@@ -70,18 +112,21 @@ static QQGame* _CurrentGame = NULL;
 
 
 - (void) onEnterFrame:(SPEnterFrameEvent*)event {
-    [self tick:event.passedTime];
+    if (_running) [self tick:event.passedTime];
 }
 
 - (void) tick:(float)elapsed {
     _ticks++;
+    
+#ifdef DEBUG_LOG
     if ((_ticks % 100) == 0) {
         NSLog(@"[%ld] Time passed since last 100 frames: %f", _ticks, elapsed);
         for (QQActor* actor in self.actors) {
             b2Vec2 v = actor.body->GetLinearVelocity();
-            NSLog(@"[%@ pos:(%f,%f) impulse:(%f,%f)]", actor, actor.x,actor.y, v.x,v.y);
+            NSLog(@"[%@ impulse:(%f,%f)]", actor, v.x,v.y);
         }
     }
+#endif
     
     for (QQActor* actor in self.actors) [actor tick:elapsed]; // XXX: self.awakeAgents
     [self.world step];
index ec83ded..72203b3 100644 (file)
@@ -5,12 +5,24 @@
  */
 @protocol QQPhysical
 
+/// The x coordinate in the simulation.
 @property (nonatomic, readwrite, assign) float x;
+
+/// The y coordinate in the simulation.
 @property (nonatomic, readwrite, assign) float y;
 @property (nonatomic, readwrite) CGPoint position;
-
 - (void) setPositionX:(float)x y:(float)y;
 
+@property (nonatomic, readwrite, assign) float rotation;
+
+/// The width of the object in simulation units.
+//@property (nonatomic, assign) float width;
+
+/// The height of the object in simulation units.
+//@property (nonatomic, assign) float height;
+
+
+
 
 // FIXME: don't expose these, instead aggregate properties from body & fixtures/shapes
 @property (nonatomic, readonly) b2Body* body;
index c638de6..383b243 100644 (file)
 - (id) initAtX:(float)x y:(float)y;
 - (id) initType:(b2BodyType)type atX:(float)x y:(float)y;
 
+/// internal methods
+
+/** Updates the Shape using values from Box2D. */
+- (void) updateShape;
+
+/** Updates the Shape's position, pulling rotation from Box2D. */
+- (void) updateShapeX:(float)x y:(float)y;
+
+/** Updates the Shape's position and rotation. */
+- (void) updateShapeX:(float)x y:(float)y rotation:(float)r;
+
 
 @end
index ee0876b..92a4642 100644 (file)
 @synthesize dirty    = _dirty;
 @synthesize delegate = _delegate;
 
+@dynamic shapeCenterX;
+@dynamic shapeCenterY;
+
+
 - (QQGame*)  game  { return QQGame.current; }
 - (QQWorld*) world { return self.game.world; }
 
@@ -20,6 +24,8 @@
 - (b2Body*) body { return _body; }
 - (b2Fixture*) fixture { return nil; }
 
+- (float) rotation { return self.body->GetAngle(); }
+- (void) setRotation:(float)r { self.body->SetTransform(self.body->GetPosition(), r); }
 
 - (CGPoint) position {
     b2Vec2 pos = self.body->GetPosition();
 }
 - (void) setPositionX:(float)x y:(float)y {
     self.body->SetTransform(b2Vec2(x,y), self.body->GetAngle());
+    // [self updateShapeX:x y:y];
+}
+
+- (void) updateShapeX:(float)x y:(float)y {
     float px = self.world.scale;
-    [self.shape setPositionX:x*px y:y*px];
+    [self.shape setCenterX:x*px y:y*px];
+}
+
+- (void) updateShapeX:(float)x y:(float)y rotation:(float)r {
+    [self updateShapeX:x y:y];
+    SPDisplayObject* shape = self.shape;
+    shape.registrationX = self.shapeCenterX;
+    shape.registrationY = self.shapeCenterY;
+    shape.rotation = r;
+}
+
+- (void) updateShape {
+    b2Transform trans = self.body->GetTransform();
+    [self updateShapeX:trans.position.x y:trans.position.y rotation:trans.GetAngle()];
 }
 
+
 - (float) x             { return self.body->GetPosition().x;    }
 - (void) setX:(float)x  { [self setPositionX:x y:self.y];       }
 
 }
 
 - (void) draw {
-    float px = self.world.scale;
-    b2Vec2 pos = self.body->GetPosition();
-    [self.shape setPositionX:pos.x*px y:pos.y*px];
+    [self updateShape];
 }
 
 - (void) setupPhysics {}
 
+- (NSString *)description {
+    b2Transform trans = self.body->GetTransform();
+    b2Vec2 pos = trans.position;
+    //b2Vec2 v = actor.body->GetLinearVelocity();
+    SPDisplayObject* s = self.shape;
+    return [NSString stringWithFormat:@"[%@ w=%f, h=%f, pos=(%f,%f), rotation=%f @ (%f,%f), scale=(%f,%f), shape=[%@ center=(%f,%f)]]",
+        [super description], s.width,s.height, pos.x,pos.y, trans.GetAngle(), s.registrationX,s.registrationY, 
+        s.scaleX,s.scaleY, s, self.shapeCenterX,self.shapeCenterY];
+}
+
+
+
 @end
index e963b45..a69d48d 100644 (file)
@@ -11,6 +11,8 @@
 
 @private
     SPDisplayObject* _shape;
+    float _shapeCenterX;
+    float _shapeCenterY;
 }
 
 /// properties
index 869930f..a9b0e5b 100644 (file)
@@ -1,7 +1,8 @@
 #include <Box2D/Box2D.h>
 #import "Sparrow.h"
 
-#import "QQUnit.h"
+#import "game/actor/QQUnit.h"
+#import "game/QQGame.h"
 #import "render/QQSparrowExtensions.h"
 
 
@@ -13,6 +14,9 @@
 @dynamic game;
 
 @synthesize shape = _shape;
+@synthesize shapeCenterX = _shapeCenterX;
+@synthesize shapeCenterY = _shapeCenterY;
+
 
 - (BOOL) canAttack { return NO; }
 
 
 - (void) setShape:(SPDisplayObject*)newShape {
     if (_shape != newShape) {
-        [self.game removeChild:_shape];
+        [self.game.level removeChild:_shape];
         [_shape release];
         
         _shape = [newShape retain];
-        float px = self.world.scale;
-        [_shape setPositionX:self.x*px y:self.y*px];
-        [self.game addChild:_shape];
+        _shapeCenterX = _shape.width  * 0.5f;
+        _shapeCenterY = _shape.height * 0.5f;
+        [self updateShape];
+        [self.game.level addChild:_shape];
     }
 }
 
     [self setShape:[[[SPImage alloc] autorelease] initWithContentsOfFile:filename]];
 }
 
+- (void) act {
+    if ((self.game.ticks % 50) == 0) {
+        self.rotation += b2_pi / 8;
+    }
+}
+
+- (void) draw {
+    [super draw];
+    if ((self.game.ticks % 50) == 0) NSLog(@"%@", self);
+}
 
 
 - (void) attack:(QQActor*)actor {
diff --git a/src/game/map/QQLevel.h b/src/game/map/QQLevel.h
new file mode 100644 (file)
index 0000000..b31fdd9
--- /dev/null
@@ -0,0 +1,10 @@
+#import "Sparrow.h"
+
+@interface QQLevel : SPDisplayObjectContainer {
+@private
+    
+}
+
+
+
+@end
diff --git a/src/game/map/QQLevel.mm b/src/game/map/QQLevel.mm
new file mode 100644 (file)
index 0000000..1c6ec88
--- /dev/null
@@ -0,0 +1,18 @@
+#import "QQLevel.h"
+
+
+@implementation QQLevel
+
+- (id) init {
+    if ((self = [super init])){
+        
+    }
+    return self;
+}
+
+- (void) render:(SPRenderSupport*)support {
+    // glTranslatef(100, 100, 0);
+    [super render:support];
+}
+
+@end
diff --git a/src/game/map/QQMap.h b/src/game/map/QQMap.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/game/map/QQMap.mm b/src/game/map/QQMap.mm
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/game/map/QQRoom.h b/src/game/map/QQRoom.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/game/map/QQRoom.mm b/src/game/map/QQRoom.mm
new file mode 100644 (file)
index 0000000..e69de29
index eeb4c96..1533c25 100644 (file)
@@ -12,7 +12,7 @@
     float   _timestep;
     int     _velocityIterations;
     int     _positionIterations;
-    BOOL    _debugDrawingEnabled;
+    
     float   _scale;
 }
 
 @property (nonatomic, assign) float timestep;
 @property (nonatomic, assign) int   velocityIterations;
 @property (nonatomic, assign) int   positionIterations;
-@property (nonatomic, assign) BOOL  debugDrawingEnabled;
-@property (nonatomic, assign) float scale; // pixels per meter
+
+@property (nonatomic, assign) float scale; // pixels per meter // TODO: move this somewhere else!
 
 
-- (QQWorld*) init;
+- (id) init;
 
 - (void) setGravityX:(float)x y:(float)y;
 
index d97bf1c..9bbdd84 100644 (file)
@@ -9,41 +9,41 @@
 @synthesize timestep            = _timestep;
 @synthesize velocityIterations  = _velocityIterations;
 @synthesize positionIterations  = _positionIterations;
-@synthesize debugDrawingEnabled = _debugDrawingEnabled;
 @synthesize scale               = _scale;
 
 @synthesize world               = _world;
 
 
-- (QQWorld*) init {
+- (id) init {
     if ((self = [super init])) {
         _timestep = 1.0f/60.0f;
         _velocityIterations = 10;
         _positionIterations = 10;
-        _debugDrawingEnabled = NO;
         _scale = 5.0f;
         
         _world = new b2World(b2Vec2(0.0f, 0.0f), true); // b2World(gravity, doSleep)
-        _debugDraw = new QQGLESDebugDraw();
+        _debugDraw = new QQGLESDebugDraw(0.75f);
+        _debugDraw->SetAllFlags();
         _world->SetDebugDraw(_debugDraw);
         
         _walls = [[NSMutableArray alloc] initWithCapacity:4];
         
-        CGSize screen = [UIScreen mainScreen].bounds.size;
-        float pad = 5;
-        float w = screen.width  / _scale;
-        float h = screen.height / _scale;
-        b2Vec2 origin = b2Vec2(pad, pad);
-        b2Vec2 horz   = b2Vec2(w-2*pad, pad);
-        b2Vec2 vert   = b2Vec2(pad, h-2*pad);
+        CGSize screen = [UIScreen mainScreen].applicationFrame.size;
+        float padv = 5;
+        float w = screen.width  / _scale - 2*padv;
+        float h = screen.height / _scale - 2*padv;
         
-        b2Vec2 positions[] = {
-            b2Vec2(w*0.5f, h*0.0f),
-            b2Vec2(w*0.5f, h*1.0f),
-            b2Vec2(w*0.0f, h*0.5f),
-            b2Vec2(w*1.0f, h*0.5f)
-        };
-        b2Vec2 bounds[] = {horz, horz, vert, vert};
+        b2Vec2 origin = b2Vec2(0, 0);
+        b2Vec2 pad    = b2Vec2(padv, padv);
+        b2Vec2 bound  = b2Vec2(w, h);
+        
+        b2Vec2 horz   = b2Vec2(w, 0);
+        b2Vec2 hpos   = horz + pad;
+        b2Vec2 vert   = b2Vec2(0, h);
+        b2Vec2 vpos   = vert + pad;
+        
+        b2Vec2 positions[] = {pad, vpos, pad, hpos};
+        b2Vec2 endpoints[] = {horz, horz, vert, vert};
         
         for (int i=0; i<4; ++i) {
             b2BodyDef bd;
@@ -51,8 +51,7 @@
             b2Body* wall = _world->CreateBody(&bd);
             
             b2PolygonShape shape;
-            shape.SetAsEdge(origin, bounds[i]);
-            
+            shape.SetAsEdge(origin, endpoints[i]);
             wall->CreateFixture(&shape, 0.0f);
             // [_walls addObject:wall]; // doh, b2Body so does not descend from NSObject, and so is not an (id)
         }
@@ -67,6 +66,7 @@
     // }
     [_walls removeAllObjects];
     [_walls release];
+    delete _debugDraw;
     delete _world; // b2World destructor destroys all physics entities and releases all heap memory.
     [super dealloc];
 }
@@ -76,7 +76,7 @@
 }
 
 - (void) drawDebug {
-    if (_debugDrawingEnabled) _world->DrawDebugData();
+    _world->DrawDebugData();
 }
 
 - (void) setGravityX:(float)x y:(float)y {
index eb08b8e..1124397 100644 (file)
@@ -37,24 +37,26 @@ class QQGLESDebugDraw : public b2DebugDraw
 public:
     float32 globalAlpha;
     
-    QQGLESDebugDraw();
+    QQGLESDebugDraw(float32 alpha=1);
+    
+    void SetAllFlags();
     
     void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color);
-
+    
     void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color);
-
+    
     void DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color);
-
+    
     void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color);
-
+    
     void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color);
-
+    
     void DrawTransform(const b2Transform& xf);
-
+    
     void DrawPoint(const b2Vec2& p, float32 size, const b2Color& color);
-
+    
     void DrawString(int x, int y, const char* string, ...); 
-
+    
     void DrawAABB(b2AABB* aabb, const b2Color& color);
 };
 
index 7aaea54..fb936d5 100644 (file)
 
 #include "QQGLESDebugDraw.h"
 
-
 #include <cstdio>
 #include <cstdarg>
-
 #include <cstring>
 
-QQGLESDebugDraw::QQGLESDebugDraw() {
-    globalAlpha = 1;
+
+
+QQGLESDebugDraw::QQGLESDebugDraw(float32 alpha) {
+    globalAlpha = alpha;
+    m_drawFlags = 0;
+}
+
+void QQGLESDebugDraw::SetAllFlags() {
+    // uint32 flags = 0;
+    // flags += b2DebugDraw::e_shapeBit;
+    // flags += b2DebugDraw::e_jointBit;
+    // flags += b2DebugDraw::e_aabbBit;
+    // flags += b2DebugDraw::e_pairBit;
+    // flags += b2DebugDraw::e_centerOfMassBit;
+    
+    SetFlags((1 << 6) - 1); // should be all flag bits
 }
 
 void QQGLESDebugDraw::DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color)
index 261b7b5..fbeecda 100644 (file)
@@ -1,96 +1,32 @@
-#import <UIKit/UIKit.h>
-#import <OpenGLES/EAGL.h>
-#import <OpenGLES/ES1/gl.h>
-#import <OpenGLES/ES1/glext.h>
-
 #include <Box2D/Box2D.h>
+#import "Sparrow.h"
+#import "SPRenderSupport.h"
 
 #import "physics/QQWorld.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 QQPhysicsDebugView : UIView {
+
+@interface QQPhysicsDebugView : SPDisplayObjectContainer {
 @private
     QQWorld* _world;
     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;
+    BOOL _zooming;
     
-    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;
+    CGPoint _lastWorldTouch;
+    CGPoint _lastScreenTouch;
     
+    b2MouseJoint* _mouseJoint;
+    b2Vec2 _mouseWorld;
 }
 
 @property (nonatomic, readwrite, retain) QQWorld* world;
-@property (nonatomic, readonly, assign, getter=isPanning) BOOL panning;
 
-- (void) drawView;
+@property (nonatomic, readonly, getter=isPanning) BOOL panning;
+@property (nonatomic, readonly, getter=isZooming) BOOL zooming;
 
-@end
 
+- (id) initWithWorld:(QQWorld*)world;
 
-// 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;
-};
+- (void) render:(SPRenderSupport*)support;
+
+@end
index 24e9ae5..7b106eb 100644 (file)
-#import <QuartzCore/QuartzCore.h>
-#import <OpenGLES/EAGLDrawable.h>
-
 #import "QQPhysicsDebugView.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 QQPhysicsDebugView ()
-
-@property (nonatomic, retain) EAGLContext *context;
-
-- (void) setup;
-
-- (BOOL) createFramebuffer;
-- (void) destroyFramebuffer;
-
-- (void) prepContext;
-- (void) flushContext;
-
-@end
-
-
-
 
 @implementation QQPhysicsDebugView
 
 @synthesize world = _world;
-@synthesize panning = _panning;
-
-@synthesize context;
 
+@synthesize panning = _panning;
+@synthesize zooming = _zooming;
 
-// You must implement this method
-+ (Class)layerClass {
-    return [CAEAGLLayer class];
-}
 
-- (id) initWithFrame:(CGRect)aRect {
-    if ((self = [super initWithFrame:aRect])) {
-        [self setup];
-    }
-    return self;
+- (id) init {
+    return [self initWithWorld:nil];
 }
 
-//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])) {
-        [self setup];
+- (id) initWithWorld:(QQWorld*)world {
+    if ((self = [super init])) {
+        self.world = world;
+        self.scaleX = self.scaleY = self.world.scale; // TODO: the view should hold the scale
+        
+        _panning = NO;
+        _zooming = NO;
+        
+        _lastWorldTouch = CGPointMake(0,0);
     }
     return self;
 }
 
-- (void) setup {
-    // Get the layer
-    CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
-    
-    eaglLayer.opaque = NO;
-    eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
-                                        [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking,
-                                        kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat,
-                                    nil];
-    
-    context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
-    
-    if (!context || ![EAGLContext setCurrentContext:context]) {
-        [self release];
-        return;
-    }
-    
-    sceneScale = 10.0f;
-    positionOffset = CGPointMake(0,0);
-    lastWorldTouch = CGPointMake(0,0);
-    
-//    [[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0 / kAccelerometerFrequency)];
-//    [[UIAccelerometer sharedAccelerometer] setDelegate:self];
-}
-
 - (void) dealloc {
-    if ([EAGLContext currentContext] == context)
-        [EAGLContext setCurrentContext:nil];
-    [context release];
     [_world release];
     [super dealloc];
 }
 
 
+/// Rendering
 
-/// Methods ///
-
-- (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) layoutSubviews {
-    [EAGLContext setCurrentContext:context];
-    [self destroyFramebuffer];
-    [self createFramebuffer];
-    [self drawView];
-}
-
-- (void) prepContext {
-    [EAGLContext setCurrentContext:context];
+- (void) render:(SPRenderSupport*)support {
+    [support bindTexture:nil];
     
-    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, 0.0f);
-    glClear(GL_COLOR_BUFFER_BIT);
-    
-    glEnable(GL_BLEND);
+    // XXX: i think this is unnecessary based on what i think bindTexture does, but i'm not clear what happens with nil
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
     
+    // set viewport pan and zoom
+    self.scaleX = self.scaleY = self.world.scale; // TODO: the view should hold the scale
+    
     glEnableClientState(GL_VERTEX_ARRAY);
-}
-
-- (void) drawView {
-    [self prepContext];
     [self.world drawDebug];
-    [self flushContext];
-}
-
-- (void) flushContext {
-    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
-    [context presentRenderbuffer:GL_RENDERBUFFER_OES];
-}
-
-
-- (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);
+    glDisableClientState(GL_VERTEX_ARRAY);
     
-    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;
-    }
+    [super render:support];
 }
 
 @end
diff --git a/src/physics/debug/QQPhysicsDebugView2.h b/src/physics/debug/QQPhysicsDebugView2.h
new file mode 100644 (file)
index 0000000..261b7b5
--- /dev/null
@@ -0,0 +1,96 @@
+#import <UIKit/UIKit.h>
+#import <OpenGLES/EAGL.h>
+#import <OpenGLES/ES1/gl.h>
+#import <OpenGLES/ES1/glext.h>
+
+#include <Box2D/Box2D.h>
+
+#import "physics/QQWorld.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 QQPhysicsDebugView : UIView {
+@private
+    QQWorld* _world;
+    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, readwrite, retain) QQWorld* world;
+@property (nonatomic, readonly, assign, getter=isPanning) BOOL panning;
+
+- (void) drawView;
+
+@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/debug/QQPhysicsDebugView2.mm b/src/physics/debug/QQPhysicsDebugView2.mm
new file mode 100644 (file)
index 0000000..24e9ae5
--- /dev/null
@@ -0,0 +1,250 @@
+#import <QuartzCore/QuartzCore.h>
+#import <OpenGLES/EAGLDrawable.h>
+
+#import "QQPhysicsDebugView.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 QQPhysicsDebugView ()
+
+@property (nonatomic, retain) EAGLContext *context;
+
+- (void) setup;
+
+- (BOOL) createFramebuffer;
+- (void) destroyFramebuffer;
+
+- (void) prepContext;
+- (void) flushContext;
+
+@end
+
+
+
+
+@implementation QQPhysicsDebugView
+
+@synthesize world = _world;
+@synthesize panning = _panning;
+
+@synthesize context;
+
+
+// You must implement this method
++ (Class)layerClass {
+    return [CAEAGLLayer class];
+}
+
+- (id) initWithFrame:(CGRect)aRect {
+    if ((self = [super initWithFrame:aRect])) {
+        [self setup];
+    }
+    return self;
+}
+
+//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])) {
+        [self setup];
+    }
+    return self;
+}
+
+- (void) setup {
+    // Get the layer
+    CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
+    
+    eaglLayer.opaque = NO;
+    eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
+                                        [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking,
+                                        kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat,
+                                    nil];
+    
+    context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
+    
+    if (!context || ![EAGLContext setCurrentContext:context]) {
+        [self release];
+        return;
+    }
+    
+    sceneScale = 10.0f;
+    positionOffset = CGPointMake(0,0);
+    lastWorldTouch = CGPointMake(0,0);
+    
+//    [[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0 / kAccelerometerFrequency)];
+//    [[UIAccelerometer sharedAccelerometer] setDelegate:self];
+}
+
+- (void) dealloc {
+    if ([EAGLContext currentContext] == context)
+        [EAGLContext setCurrentContext:nil];
+    [context release];
+    [_world release];
+    [super dealloc];
+}
+
+
+
+/// Methods ///
+
+- (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) layoutSubviews {
+    [EAGLContext setCurrentContext:context];
+    [self destroyFramebuffer];
+    [self createFramebuffer];
+    [self drawView];
+}
+
+- (void) prepContext {
+    [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, 0.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    
+    glEnableClientState(GL_VERTEX_ARRAY);
+}
+
+- (void) drawView {
+    [self prepContext];
+    [self.world drawDebug];
+    [self flushContext];
+}
+
+- (void) flushContext {
+    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
+    [context presentRenderbuffer:GL_RENDERBUFFER_OES];
+}
+
+
+- (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 c2c25fe..fd86988 100644 (file)
@@ -10,6 +10,7 @@
 
 #ifdef __OBJC__
     #import <Foundation/Foundation.h>
+    #import <QuartzCore/QuartzCore.h>
     #import <UIKit/UIKit.h>
 #endif
 
diff --git a/src/render/QQShape.h b/src/render/QQShape.h
new file mode 100644 (file)
index 0000000..d975afe
--- /dev/null
@@ -0,0 +1,6 @@
+#import "Sparrow.h"
+
+
+@interface QQShape : SPQuad 
+
+@end
diff --git a/src/render/QQShape.mm b/src/render/QQShape.mm
new file mode 100644 (file)
index 0000000..2cfb9ec
--- /dev/null
@@ -0,0 +1,10 @@
+#import "QQShape.h"
+
+
+@implementation QQShape
+
+- (void) render:(SPRenderSupport*)support {
+    [super render:support];
+}
+
+@end
index d38f677..a68d4a9 100644 (file)
@@ -11,6 +11,16 @@ struct b2Vec2;
 /** Sets coordinates of the object relative to the local coordinates of the parent. */
 - (id) setPositionX:(float)x y:(float)y;
 
+@property (nonatomic, readwrite, assign) float centerX;
+@property (nonatomic, readwrite, assign) float centerY;
+
+/** Sets coordinates of the object relative to the local coordinates of the parent. */
+- (id) setCenterX:(float)x y:(float)y;
+
+/** Coordinates of the center of the object relative to the local coordinates of the parent. */
+@property (nonatomic, readwrite, assign) SPPoint* center;
+
+
 @end
 
 
index 74ec9b1..b8106e6 100644 (file)
     return self;
 }
 
+- (float) centerX { return self.x + self.width*0.5f; }
+- (void) setCenterX:(float)x { self.x = x - self.width*0.5f; }
+
+- (float) centerY { return self.y + self.height*0.5f; }
+- (void) setCenterY:(float)y { self.y = y - self.height*0.5f; }
+
+/** Sets coordinates of the object relative to the local coordinates of the parent. */
+- (id) setCenterX:(float)x y:(float)y {
+    self.centerX = x;
+    self.centerY = y;
+    return self;
+}
+
+- (SPPoint*) center {
+    return [SPPoint pointWithX:self.centerX y:self.centerY];
+}
+
+- (void) setCenter:(SPPoint*)pt {
+    [self setCenterX:pt.x y:pt.y];
+}
+
+
 @end
 
 
index 29dbd78..10b0e32 100644 (file)
@@ -3,17 +3,19 @@
 #import "physics/debug/QQPhysicsDebugView.h"
 
 
-@interface QQAppDelegate : NSObject <UIApplicationDelegate>
-{
+@interface QQAppDelegate : NSObject <UIApplicationDelegate> {
+
+@private
+    UIApplication* _app;
     UIWindow* window;
     SPView* sparrowView;
-    QQPhysicsDebugView* _debugView;
+    // QQPhysicsDebugView* _debugView;
     QQGame* _game;
 }
 
 @property (nonatomic, retain) IBOutlet UIWindow* window;
 @property (nonatomic, retain) IBOutlet SPView* sparrowView;
-@property (nonatomic, retain) QQPhysicsDebugView* debugView;
+// @property (nonatomic, retain) QQPhysicsDebugView* debugView;
 @property (nonatomic, retain) QQGame* game;
 
 @end
\ No newline at end of file
index 3e161ef..9d65e17 100644 (file)
 
 @synthesize window;
 @synthesize sparrowView;
-@synthesize debugView = _debugView;
 @synthesize game = _game;
 
 
 - (void) applicationDidFinishLaunching:(UIApplication*)application {
+    _app = application;
+    _app.statusBarHidden = YES;
+    
     SP_CREATE_POOL(pool);
     
     [SPStage setSupportHighResolutions:YES];
     [SPAudioEngine start];
     if ( sparrowView.frameRate != 60.0f )
         sparrowView.frameRate = 60.0f;
-    // sparrowView.stage = [[[SPStage alloc] init] autorelease];
     
     self.game = [[[QQGame alloc] init] autorelease];
     sparrowView.stage = _game;
-    self.debugView = [[[QQPhysicsDebugView alloc] initWithFrame:sparrowView.frame] autorelease];
-    [window addSubview:self.debugView];
+    [_game start];
     
     [window makeKeyAndVisible];
     [sparrowView start];
@@ -46,7 +46,7 @@
 }
 
 - (void) dealloc {
-    // [self setGame:nil];
+    _app = nil;
     [_game release];
     [sparrowView release];
     [window release];
index 50d6ea2..0b6248b 100644 (file)
@@ -40,6 +40,7 @@
                                                <string key="NSFrame">{{284, 501}, {200, 22}}</string>
                                                <reference key="NSSuperview" ref="62075450"/>
                                                <reference key="NSWindow"/>
+                                               <reference key="NSNextKeyView"/>
                                                <bool key="IBUIOpaque">NO</bool>
                                                <bool key="IBUIClipsSubviews">YES</bool>
                                                <int key="IBUIContentMode">7</int>
@@ -57,7 +58,7 @@
                                        <object class="IBUIView" id="607297697">
                                                <reference key="NSNextResponder" ref="62075450"/>
                                                <int key="NSvFlags">292</int>
-                                               <string key="NSFrameSize">{768, 1003}</string>
+                                               <string key="NSFrameSize">{768, 1024}</string>
                                                <reference key="NSSuperview" ref="62075450"/>
                                                <reference key="NSWindow"/>
                                                <reference key="NSNextKeyView" ref="348798989"/>
@@ -69,6 +70,9 @@
                                                        </object>
                                                </object>
                                                <bool key="IBUIMultipleTouchEnabled">YES</bool>
+                                               <object class="IBUIAccessibilityConfiguration" key="IBUIAccessibilityConfiguration">
+                                                       <integer value="512" key="IBUIAccessibilityTraits"/>
+                                               </object>
                                                <string key="targetRuntimeIdentifier">IBIPadFramework</string>
                                        </object>
                                </array>
                        <nil key="activeLocalization"/>
                        <dictionary class="NSMutableDictionary" key="localizations"/>
                        <nil key="sourceID"/>
-                       <int key="maxID">15</int>
+                       <int key="maxID">17</int>
                </object>
                <object class="IBClassDescriber" key="IBDocument.Classes">
                        <array class="NSMutableArray" key="referencedPartialClassDescriptions">
index a5af9d2..b8223a5 100644 (file)
@@ -60,7 +60,7 @@
                                        <object class="IBUIView" id="851352140">
                                                <reference key="NSNextResponder" ref="380026005"/>
                                                <int key="NSvFlags">1316</int>
-                                               <string key="NSFrame">{{0, 21}, {320, 459}}</string>
+                                               <string key="NSFrameSize">{320, 480}</string>
                                                <reference key="NSSuperview" ref="380026005"/>
                                                <reference key="NSWindow"/>
                                                <reference key="NSNextKeyView" ref="723173800"/>
@@ -72,6 +72,9 @@
                                                        </object>
                                                </object>
                                                <bool key="IBUIMultipleTouchEnabled">YES</bool>
+                                               <object class="IBUIAccessibilityConfiguration" key="IBUIAccessibilityConfiguration">
+                                                       <integer value="512" key="IBUIAccessibilityTraits"/>
+                                               </object>
                                                <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
                                        </object>
                                </array>
index 9fb3a7f..72e59da 100644 (file)
@@ -7,6 +7,8 @@
        objects = {
 
 /* Begin PBXBuildFile section */
+               49193BF5139280180005B3DD /* QQLevel.h in Headers */ = {isa = PBXBuildFile; fileRef = 49193BEF139280180005B3DD /* QQLevel.h */; };
+               49193BF6139280180005B3DD /* QQLevel.mm in Sources */ = {isa = PBXBuildFile; fileRef = 49193BF0139280180005B3DD /* QQLevel.mm */; };
                492D80CC138B231B0042D918 /* QQPhysical.h in Headers */ = {isa = PBXBuildFile; fileRef = 492D80CB138B231B0042D918 /* QQPhysical.h */; };
                492D80E4138BA4910042D918 /* QQCooldown.h in Headers */ = {isa = PBXBuildFile; fileRef = 492D80DE138BA4910042D918 /* QQCooldown.h */; };
                492D80E5138BA4910042D918 /* QQCooldown.mm in Sources */ = {isa = PBXBuildFile; fileRef = 492D80DF138BA4910042D918 /* QQCooldown.mm */; };
@@ -42,6 +44,8 @@
                49966919136930E8006E8125 /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49966914136930E8006E8125 /* OpenAL.framework */; };
                4996691A136930E8006E8125 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49966915136930E8006E8125 /* OpenGLES.framework */; };
                4996691B136930E8006E8125 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49966916136930E8006E8125 /* QuartzCore.framework */; };
+               49D8645D1392DB2800BC341C /* QQShape.h in Headers */ = {isa = PBXBuildFile; fileRef = 49D8645B1392DB2800BC341C /* QQShape.h */; };
+               49D8645E1392DB2800BC341C /* QQShape.mm in Sources */ = {isa = PBXBuildFile; fileRef = 49D8645C1392DB2800BC341C /* QQShape.mm */; };
                49DA67D4137847A7004841E9 /* QQWorld.h in Headers */ = {isa = PBXBuildFile; fileRef = 49DA67D2137847A7004841E9 /* QQWorld.h */; };
                49DA67D5137847A7004841E9 /* QQWorld.mm in Sources */ = {isa = PBXBuildFile; fileRef = 49DA67D3137847A7004841E9 /* QQWorld.mm */; };
                49E834A713812427007A6598 /* QQActive.h in Headers */ = {isa = PBXBuildFile; fileRef = 49E8349E13812427007A6598 /* QQActive.h */; };
 /* End PBXContainerItemProxy section */
 
 /* Begin PBXFileReference section */
+               49193BEF139280180005B3DD /* QQLevel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQLevel.h; sourceTree = "<group>"; };
+               49193BF0139280180005B3DD /* QQLevel.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = QQLevel.mm; sourceTree = "<group>"; };
                492D80CB138B231B0042D918 /* QQPhysical.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = QQPhysical.h; path = src/game/QQPhysical.h; sourceTree = SOURCE_ROOT; };
                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>"; };
                49966914136930E8006E8125 /* OpenAL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenAL.framework; path = System/Library/Frameworks/OpenAL.framework; sourceTree = SDKROOT; };
                49966915136930E8006E8125 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
                49966916136930E8006E8125 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
+               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>"; };
                49DA67D3137847A7004841E9 /* QQWorld.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = QQWorld.mm; sourceTree = "<group>"; };
                49E8349E13812427007A6598 /* QQActive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQActive.h; sourceTree = "<group>"; };
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
+               49193BEE139280180005B3DD /* map */ = {
+                       isa = PBXGroup;
+                       children = (
+                               49193BEF139280180005B3DD /* QQLevel.h */,
+                               49193BF0139280180005B3DD /* QQLevel.mm */,
+                       );
+                       path = map;
+                       sourceTree = "<group>";
+               };
                492D80DB138BA4910042D918 /* ability */ = {
                        isa = PBXGroup;
                        children = (
                49E8349D13812427007A6598 /* game */ = {
                        isa = PBXGroup;
                        children = (
+                               49193BEE139280180005B3DD /* map */,
                                492D80ED138BA4BC0042D918 /* bullet */,
                                492D80E8138BA4B40042D918 /* unit */,
                                492D80DB138BA4910042D918 /* ability */,
                49F2D9AE13764666000B6B8C /* src */ = {
                        isa = PBXGroup;
                        children = (
-                               49E8349D13812427007A6598 /* game */,
-                               49F2D9B113764666000B6B8C /* physics */,
                                49F2D9B313764666000B6B8C /* render */,
                                49E834AF13812555007A6598 /* ui */,
+                               49F2D9B113764666000B6B8C /* physics */,
+                               49E8349D13812427007A6598 /* game */,
                                49F2D9B013764666000B6B8C /* main.mm */,
                                49F2D9B213764666000B6B8C /* prefix.pch */,
                        );
                49F2D9B313764666000B6B8C /* render */ = {
                        isa = PBXGroup;
                        children = (
+                               49D8645B1392DB2800BC341C /* QQShape.h */,
+                               49D8645C1392DB2800BC341C /* QQShape.mm */,
                                4B8B2A4D137D090D00CA4076 /* animation */,
                                49E834D1138166A6007A6598 /* QQSparrowExtensions.h */,
                                49E834D2138166A6007A6598 /* QQSparrowExtensions.mm */,
                                49F2DADB13764ED6000B6B8C /* SPPoolObject.h in Headers */,
                                49F2DADD13764ED6000B6B8C /* SPUtils.h in Headers */,
                                49F2DADF13764ED6000B6B8C /* Sparrow.h in Headers */,
+                               492D810C138C07540042D918 /* BEParallaxSprite.h in Headers */,
+                               492D810E138C07540042D918 /* SHCircle.h in Headers */,
+                               492D8110138C07540042D918 /* SHLine.h in Headers */,
+                               492D8112138C07540042D918 /* SHPolygon.h in Headers */,
+                               492D8115138C07540042D918 /* SXFPSMeter.h in Headers */,
+                               492D8114138C07540042D918 /* SparrowExtras.h in Headers */,
                                49DA67D4137847A7004841E9 /* QQWorld.h in Headers */,
                                4B8B2A50137D098500CA4076 /* QQAnimationContainer.h in Headers */,
                                49E834A713812427007A6598 /* QQActive.h in Headers */,
                                492D80F0138BA4BC0042D918 /* QQBullet.h in Headers */,
                                492D80F3138BA4CE0042D918 /* QQThing.h in Headers */,
                                492D80FF138BCC9F0042D918 /* QQActorDelegate.h in Headers */,
-                               492D810C138C07540042D918 /* BEParallaxSprite.h in Headers */,
-                               492D810E138C07540042D918 /* SHCircle.h in Headers */,
-                               492D8110138C07540042D918 /* SHLine.h in Headers */,
-                               492D8112138C07540042D918 /* SHPolygon.h in Headers */,
-                               492D8114138C07540042D918 /* SparrowExtras.h in Headers */,
-                               492D8115138C07540042D918 /* SXFPSMeter.h in Headers */,
+                               49193BF5139280180005B3DD /* QQLevel.h in Headers */,
+                               49D8645D1392DB2800BC341C /* QQShape.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                49F2DADA13764ED6000B6B8C /* SPNSExtensions.m in Sources */,
                                49F2DADC13764ED6000B6B8C /* SPPoolObject.m in Sources */,
                                49F2DADE13764ED6000B6B8C /* SPUtils.m in Sources */,
+                               492D810D138C07540042D918 /* BEParallaxSprite.m in Sources */,
+                               492D810F138C07540042D918 /* SHCircle.m in Sources */,
+                               492D8111138C07540042D918 /* SHLine.m in Sources */,
+                               492D8113138C07540042D918 /* SHPolygon.m in Sources */,
+                               492D8116138C07540042D918 /* SXFPSMeter.m in Sources */,
+                               49E834CE13814F7D007A6598 /* QQGLESDebugDraw.mm in Sources */,
+                               4B91A15A138F644000EF4D7C /* QQPhysicsDebugView.mm in Sources */,
                                49DA67D5137847A7004841E9 /* QQWorld.mm in Sources */,
                                4B8B2A51137D098500CA4076 /* QQAnimationContainer.mm in Sources */,
-                               49F2D9C413764666000B6B8C /* main.mm in Sources */,
                                49E834A913812427007A6598 /* QQActor.mm in Sources */,
                                49E834AE13812427007A6598 /* QQGame.mm in Sources */,
                                49E834BF13812555007A6598 /* QQAppDelegate.mm in Sources */,
                                49E834C113812555007A6598 /* QQAppDelegate_iPad.mm in Sources */,
                                49E834C413812555007A6598 /* QQAppDelegate_iPhone.mm in Sources */,
                                49E834C713812555007A6598 /* QQViewport.mm in Sources */,
-                               49E834CE13814F7D007A6598 /* QQGLESDebugDraw.mm in Sources */,
                                49E834D4138166A6007A6598 /* QQSparrowExtensions.mm in Sources */,
                                492D80E5138BA4910042D918 /* QQCooldown.mm in Sources */,
-                               4B91A15A138F644000EF4D7C /* QQPhysicsDebugView.mm in Sources */,
                                492D80EC138BA4B40042D918 /* QQTank.mm in Sources */,
                                492D80F1138BA4BC0042D918 /* QQBullet.mm in Sources */,
                                492D80FD138BCA840042D918 /* QQUnit.mm in Sources */,
-                               492D810D138C07540042D918 /* BEParallaxSprite.m in Sources */,
-                               492D810F138C07540042D918 /* SHCircle.m in Sources */,
-                               492D8111138C07540042D918 /* SHLine.m in Sources */,
-                               492D8113138C07540042D918 /* SHPolygon.m in Sources */,
-                               492D8116138C07540042D918 /* SXFPSMeter.m in Sources */,
+                               49193BF6139280180005B3DD /* QQLevel.mm in Sources */,
+                               49F2D9C413764666000B6B8C /* main.mm in Sources */,
+                               49D8645E1392DB2800BC341C /* QQShape.mm in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };