From f1e4dba539226f02c980d9e41a51187a185eca76 Mon Sep 17 00:00:00 2001 From: dsc Date: Sun, 29 May 2011 13:06:05 -0700 Subject: [PATCH] Welp, Debug drawing works, but for some reason I can't get OpenGL to apply a rotation matrix like I expect it to. --- libs/sparrow/src/Classes/SPDisplayObject.h | 12 +- libs/sparrow/src/Classes/SPDisplayObject.m | 14 ++- libs/sparrow/src/Classes/SPRenderSupport.m | 13 +- src/game/QQDisplayable.h | 4 + src/game/QQGame.h | 26 +++- src/game/QQGame.mm | 65 ++++++- src/game/QQPhysical.h | 14 ++- src/game/actor/QQActor.h | 11 ++ src/game/actor/QQActor.mm | 42 ++++- src/game/actor/QQUnit.h | 2 + src/game/actor/QQUnit.mm | 25 ++- src/game/map/QQLevel.h | 10 + src/game/map/QQLevel.mm | 18 ++ src/physics/QQWorld.h | 8 +- src/physics/QQWorld.mm | 42 +++--- src/physics/debug/QQGLESDebugDraw.h | 20 ++- src/physics/debug/QQGLESDebugDraw.mm | 20 ++- src/physics/debug/QQPhysicsDebugView.h | 94 ++-------- src/physics/debug/QQPhysicsDebugView.mm | 240 +++---------------------- src/physics/debug/QQPhysicsDebugView2.h | 96 ++++++++++ src/physics/debug/QQPhysicsDebugView2.mm | 250 ++++++++++++++++++++++++++ src/prefix.pch | 1 + src/render/QQShape.h | 6 + src/render/QQShape.mm | 10 + src/render/QQSparrowExtensions.h | 10 + src/render/QQSparrowExtensions.mm | 22 +++ src/ui/QQAppDelegate.h | 10 +- src/ui/QQAppDelegate.mm | 10 +- src/ui/iPad/en.lproj/MainWindow_iPad.xib | 8 +- src/ui/iPhone/en.lproj/MainWindow_iPhone.xib | 5 +- tanks.xcodeproj/project.pbxproj | 56 ++++-- 31 files changed, 769 insertions(+), 395 deletions(-) create mode 100644 src/game/map/QQLevel.h create mode 100644 src/game/map/QQLevel.mm create mode 100644 src/game/map/QQMap.h create mode 100644 src/game/map/QQMap.mm create mode 100644 src/game/map/QQRoom.h create mode 100644 src/game/map/QQRoom.mm create mode 100644 src/physics/debug/QQPhysicsDebugView2.h create mode 100644 src/physics/debug/QQPhysicsDebugView2.mm create mode 100644 src/render/QQShape.h create mode 100644 src/render/QQShape.mm diff --git a/libs/sparrow/src/Classes/SPDisplayObject.h b/libs/sparrow/src/Classes/SPDisplayObject.h index 2e85055..e6b931c 100644 --- a/libs/sparrow/src/Classes/SPDisplayObject.h +++ b/libs/sparrow/src/Classes/SPDisplayObject.h @@ -82,6 +82,8 @@ float mY; float mScaleX; float mScaleY; + float mRegX; + float mRegY; float mRotationZ; float mAlpha; BOOL mVisible; @@ -121,10 +123,10 @@ /// @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. @@ -139,6 +141,12 @@ /// 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; diff --git a/libs/sparrow/src/Classes/SPDisplayObject.m b/libs/sparrow/src/Classes/SPDisplayObject.m index 6ef3c6c..d7c0378 100644 --- a/libs/sparrow/src/Classes/SPDisplayObject.m +++ b/libs/sparrow/src/Classes/SPDisplayObject.m @@ -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; } @@ -290,9 +295,14 @@ { 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]; } diff --git a/libs/sparrow/src/Classes/SPRenderSupport.m b/libs/sparrow/src/Classes/SPRenderSupport.m index 13103ec..e752e06 100644 --- a/libs/sparrow/src/Classes/SPRenderSupport.m +++ b/libs/sparrow/src/Classes/SPRenderSupport.m @@ -24,7 +24,7 @@ - (id)init { - if (self = [super init]) + if ((self = [super init])) { mBoundTextureID = UINT_MAX; mPremultipliedAlpha = YES; @@ -88,13 +88,20 @@ { 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 diff --git a/src/game/QQDisplayable.h b/src/game/QQDisplayable.h index ab60dbf..4d0852e 100644 --- a/src/game/QQDisplayable.h +++ b/src/game/QQDisplayable.h @@ -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. */ diff --git a/src/game/QQGame.h b/src/game/QQGame.h index e0a6ff1..fd5d95b 100644 --- a/src/game/QQGame.h +++ b/src/game/QQGame.h @@ -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; diff --git a/src/game/QQGame.mm b/src/game/QQGame.mm index 3dbfb59..a44f611 100644 --- a/src/game/QQGame.mm +++ b/src/game/QQGame.mm @@ -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]; diff --git a/src/game/QQPhysical.h b/src/game/QQPhysical.h index ec83ded..72203b3 100644 --- a/src/game/QQPhysical.h +++ b/src/game/QQPhysical.h @@ -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; diff --git a/src/game/actor/QQActor.h b/src/game/actor/QQActor.h index c638de6..383b243 100644 --- a/src/game/actor/QQActor.h +++ b/src/game/actor/QQActor.h @@ -27,5 +27,16 @@ - (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 diff --git a/src/game/actor/QQActor.mm b/src/game/actor/QQActor.mm index ee0876b..92a4642 100644 --- a/src/game/actor/QQActor.mm +++ b/src/game/actor/QQActor.mm @@ -11,6 +11,10 @@ @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(); @@ -30,10 +36,28 @@ } - (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]; } @@ -74,11 +98,21 @@ } - (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 diff --git a/src/game/actor/QQUnit.h b/src/game/actor/QQUnit.h index e963b45..a69d48d 100644 --- a/src/game/actor/QQUnit.h +++ b/src/game/actor/QQUnit.h @@ -11,6 +11,8 @@ @private SPDisplayObject* _shape; + float _shapeCenterX; + float _shapeCenterY; } /// properties diff --git a/src/game/actor/QQUnit.mm b/src/game/actor/QQUnit.mm index 869930f..a9b0e5b 100644 --- a/src/game/actor/QQUnit.mm +++ b/src/game/actor/QQUnit.mm @@ -1,7 +1,8 @@ #include #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; } @@ -49,13 +53,14 @@ - (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]; } } @@ -63,6 +68,16 @@ [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 index 0000000..b31fdd9 --- /dev/null +++ b/src/game/map/QQLevel.h @@ -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 index 0000000..1c6ec88 --- /dev/null +++ b/src/game/map/QQLevel.mm @@ -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 index 0000000..e69de29 diff --git a/src/game/map/QQMap.mm b/src/game/map/QQMap.mm new file mode 100644 index 0000000..e69de29 diff --git a/src/game/map/QQRoom.h b/src/game/map/QQRoom.h new file mode 100644 index 0000000..e69de29 diff --git a/src/game/map/QQRoom.mm b/src/game/map/QQRoom.mm new file mode 100644 index 0000000..e69de29 diff --git a/src/physics/QQWorld.h b/src/physics/QQWorld.h index eeb4c96..1533c25 100644 --- a/src/physics/QQWorld.h +++ b/src/physics/QQWorld.h @@ -12,7 +12,7 @@ float _timestep; int _velocityIterations; int _positionIterations; - BOOL _debugDrawingEnabled; + float _scale; } @@ -21,11 +21,11 @@ @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; diff --git a/src/physics/QQWorld.mm b/src/physics/QQWorld.mm index d97bf1c..9bbdd84 100644 --- a/src/physics/QQWorld.mm +++ b/src/physics/QQWorld.mm @@ -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 { diff --git a/src/physics/debug/QQGLESDebugDraw.h b/src/physics/debug/QQGLESDebugDraw.h index eb08b8e..1124397 100644 --- a/src/physics/debug/QQGLESDebugDraw.h +++ b/src/physics/debug/QQGLESDebugDraw.h @@ -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); }; diff --git a/src/physics/debug/QQGLESDebugDraw.mm b/src/physics/debug/QQGLESDebugDraw.mm index 7aaea54..fb936d5 100644 --- a/src/physics/debug/QQGLESDebugDraw.mm +++ b/src/physics/debug/QQGLESDebugDraw.mm @@ -20,14 +20,26 @@ #include "QQGLESDebugDraw.h" - #include #include - #include -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) diff --git a/src/physics/debug/QQPhysicsDebugView.h b/src/physics/debug/QQPhysicsDebugView.h index 261b7b5..fbeecda 100644 --- a/src/physics/debug/QQPhysicsDebugView.h +++ b/src/physics/debug/QQPhysicsDebugView.h @@ -1,96 +1,32 @@ -#import -#import -#import -#import - #include +#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 diff --git a/src/physics/debug/QQPhysicsDebugView.mm b/src/physics/debug/QQPhysicsDebugView.mm index 24e9ae5..7b106eb 100644 --- a/src/physics/debug/QQPhysicsDebugView.mm +++ b/src/physics/debug/QQPhysicsDebugView.mm @@ -1,250 +1,54 @@ -#import -#import - #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 index 0000000..261b7b5 --- /dev/null +++ b/src/physics/debug/QQPhysicsDebugView2.h @@ -0,0 +1,96 @@ +#import +#import +#import +#import + +#include + +#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 index 0000000..24e9ae5 --- /dev/null +++ b/src/physics/debug/QQPhysicsDebugView2.mm @@ -0,0 +1,250 @@ +#import +#import + +#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 diff --git a/src/prefix.pch b/src/prefix.pch index c2c25fe..fd86988 100644 --- a/src/prefix.pch +++ b/src/prefix.pch @@ -10,6 +10,7 @@ #ifdef __OBJC__ #import + #import #import #endif diff --git a/src/render/QQShape.h b/src/render/QQShape.h new file mode 100644 index 0000000..d975afe --- /dev/null +++ b/src/render/QQShape.h @@ -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 index 0000000..2cfb9ec --- /dev/null +++ b/src/render/QQShape.mm @@ -0,0 +1,10 @@ +#import "QQShape.h" + + +@implementation QQShape + +- (void) render:(SPRenderSupport*)support { + [super render:support]; +} + +@end diff --git a/src/render/QQSparrowExtensions.h b/src/render/QQSparrowExtensions.h index d38f677..a68d4a9 100644 --- a/src/render/QQSparrowExtensions.h +++ b/src/render/QQSparrowExtensions.h @@ -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 diff --git a/src/render/QQSparrowExtensions.mm b/src/render/QQSparrowExtensions.mm index 74ec9b1..b8106e6 100644 --- a/src/render/QQSparrowExtensions.mm +++ b/src/render/QQSparrowExtensions.mm @@ -17,6 +17,28 @@ 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 diff --git a/src/ui/QQAppDelegate.h b/src/ui/QQAppDelegate.h index 29dbd78..10b0e32 100644 --- a/src/ui/QQAppDelegate.h +++ b/src/ui/QQAppDelegate.h @@ -3,17 +3,19 @@ #import "physics/debug/QQPhysicsDebugView.h" -@interface QQAppDelegate : NSObject -{ +@interface QQAppDelegate : NSObject { + +@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 diff --git a/src/ui/QQAppDelegate.mm b/src/ui/QQAppDelegate.mm index 3e161ef..9d65e17 100644 --- a/src/ui/QQAppDelegate.mm +++ b/src/ui/QQAppDelegate.mm @@ -13,23 +13,23 @@ @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]; diff --git a/src/ui/iPad/en.lproj/MainWindow_iPad.xib b/src/ui/iPad/en.lproj/MainWindow_iPad.xib index 50d6ea2..0b6248b 100644 --- a/src/ui/iPad/en.lproj/MainWindow_iPad.xib +++ b/src/ui/iPad/en.lproj/MainWindow_iPad.xib @@ -40,6 +40,7 @@ {{284, 501}, {200, 22}} + NO YES 7 @@ -57,7 +58,7 @@ 292 - {768, 1003} + {768, 1024} @@ -69,6 +70,9 @@ YES + + + IBIPadFramework @@ -177,7 +181,7 @@ - 15 + 17 diff --git a/src/ui/iPhone/en.lproj/MainWindow_iPhone.xib b/src/ui/iPhone/en.lproj/MainWindow_iPhone.xib index a5af9d2..b8223a5 100644 --- a/src/ui/iPhone/en.lproj/MainWindow_iPhone.xib +++ b/src/ui/iPhone/en.lproj/MainWindow_iPhone.xib @@ -60,7 +60,7 @@ 1316 - {{0, 21}, {320, 459}} + {320, 480} @@ -72,6 +72,9 @@ YES + + + IBCocoaTouchFramework diff --git a/tanks.xcodeproj/project.pbxproj b/tanks.xcodeproj/project.pbxproj index 9fb3a7f..72e59da 100644 --- a/tanks.xcodeproj/project.pbxproj +++ b/tanks.xcodeproj/project.pbxproj @@ -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 */; }; @@ -182,6 +186,8 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 49193BEF139280180005B3DD /* QQLevel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQLevel.h; sourceTree = ""; }; + 49193BF0139280180005B3DD /* QQLevel.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = QQLevel.mm; sourceTree = ""; }; 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 = ""; }; 492D80DF138BA4910042D918 /* QQCooldown.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = QQCooldown.mm; sourceTree = ""; }; @@ -239,6 +245,8 @@ 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 = ""; }; + 49D8645C1392DB2800BC341C /* QQShape.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = QQShape.mm; sourceTree = ""; }; 49DA67D2137847A7004841E9 /* QQWorld.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQWorld.h; sourceTree = ""; }; 49DA67D3137847A7004841E9 /* QQWorld.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = QQWorld.mm; sourceTree = ""; }; 49E8349E13812427007A6598 /* QQActive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QQActive.h; sourceTree = ""; }; @@ -387,6 +395,15 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 49193BEE139280180005B3DD /* map */ = { + isa = PBXGroup; + children = ( + 49193BEF139280180005B3DD /* QQLevel.h */, + 49193BF0139280180005B3DD /* QQLevel.mm */, + ); + path = map; + sourceTree = ""; + }; 492D80DB138BA4910042D918 /* ability */ = { isa = PBXGroup; children = ( @@ -547,6 +564,7 @@ 49E8349D13812427007A6598 /* game */ = { isa = PBXGroup; children = ( + 49193BEE139280180005B3DD /* map */, 492D80ED138BA4BC0042D918 /* bullet */, 492D80E8138BA4B40042D918 /* unit */, 492D80DB138BA4910042D918 /* ability */, @@ -628,10 +646,10 @@ 49F2D9AE13764666000B6B8C /* src */ = { isa = PBXGroup; children = ( - 49E8349D13812427007A6598 /* game */, - 49F2D9B113764666000B6B8C /* physics */, 49F2D9B313764666000B6B8C /* render */, 49E834AF13812555007A6598 /* ui */, + 49F2D9B113764666000B6B8C /* physics */, + 49E8349D13812427007A6598 /* game */, 49F2D9B013764666000B6B8C /* main.mm */, 49F2D9B213764666000B6B8C /* prefix.pch */, ); @@ -651,6 +669,8 @@ 49F2D9B313764666000B6B8C /* render */ = { isa = PBXGroup; children = ( + 49D8645B1392DB2800BC341C /* QQShape.h */, + 49D8645C1392DB2800BC341C /* QQShape.mm */, 4B8B2A4D137D090D00CA4076 /* animation */, 49E834D1138166A6007A6598 /* QQSparrowExtensions.h */, 49E834D2138166A6007A6598 /* QQSparrowExtensions.mm */, @@ -957,6 +977,12 @@ 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 */, @@ -976,12 +1002,8 @@ 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; }; @@ -1113,27 +1135,29 @@ 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; }; -- 1.7.0.4