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

index 9408889..89a8a7b 100644 (file)
@@ -1,3 +1,6 @@
+tmp
+*.tmproj
+
 # Xcode
 build
 *.pbxuser
@@ -12,5 +15,4 @@ build
 !default.xcworkspace
 xcuserdata
 profile
-*.moved-aside
-tmp
+*.moved-aside
\ No newline at end of file
diff --git a/libs/sparrow/VERSION b/libs/sparrow/VERSION
new file mode 100644 (file)
index 0000000..9459d4b
--- /dev/null
@@ -0,0 +1 @@
+1.1
index b3d29e3..13411b4 100644 (file)
@@ -1,21 +1,16 @@
-//
-//  RootAppDelegate.h
-//  tanks
-//
-//  Created by dsc on 4/27/11.
-//  Copyright 2011 lttlst.com. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
 #import "Sparrow.h"
+#import "Game.h"
+
 
 @interface RootAppDelegate : NSObject <UIApplicationDelegate>
 {
-    UIWindow *window;
-    SPView *sparrowView;
+    UIWindow* window;
+    SPView* sparrowView;
+    Game* game;
 }
 
-@property (nonatomic, retain) IBOutlet UIWindow *window;
-@property (nonatomic, retain) IBOutlet SPView *sparrowView;
+@property (nonatomic, retain) IBOutlet UIWindow* window;
+@property (nonatomic, retain) IBOutlet SPView* sparrowView;
+@property (nonatomic, retain) Game* game;
 
 @end
\ No newline at end of file
similarity index 61%
rename from src/RootAppDelegate.m
rename to src/RootAppDelegate.mm
index fac7681..34b7cd9 100644 (file)
 
 @synthesize window;
 @synthesize sparrowView;
+@synthesize game;
 
-- (void)applicationDidFinishLaunching:(UIApplication *)application
-{
+
+- (void) applicationDidFinishLaunching:(UIApplication*)application {
     SP_CREATE_POOL(pool);
     
     [SPStage setSupportHighResolutions:YES];
     [SPAudioEngine start];
+    if ( sparrowView.frameRate != 60.0f )
+        sparrowView.frameRate = 60.0f;
     
-    Game *game = [[Game alloc] init];
+    game = [[[Game alloc] init] autorelease];
     sparrowView.stage = game;
-    [game release];
     
     [window makeKeyAndVisible];
     [sparrowView start];
     SP_RELEASE_POOL(pool);
 }
 
-- (void)applicationWillResignActive:(UIApplication *)application
-{
+- (void) applicationWillResignActive:(UIApplication*)application {
     [sparrowView stop];
 }
 
-- (void)applicationDidBecomeActive:(UIApplication *)application
-{
+- (void) applicationDidBecomeActive:(UIApplication*)application {
     [sparrowView start];
 }
 
-- (void)dealloc
-{
+- (void) dealloc {
+    [self setGame:nil];
     [sparrowView release];
     [window release];
     [super dealloc];
similarity index 100%
rename from src/main.m
rename to src/main.mm
diff --git a/src/physics/PhysicsDebugView.h b/src/physics/PhysicsDebugView.h
new file mode 100644 (file)
index 0000000..57209d7
--- /dev/null
@@ -0,0 +1,67 @@
+#import <UIKit/UIKit.h>
+#import <OpenGLES/EAGL.h>
+#import <OpenGLES/ES1/gl.h>
+#import <OpenGLES/ES1/glext.h>
+
+#include <Box2D/Box2D.h>
+
+#import "physics/PhysicsView.h"
+
+/*
+This class wraps the CAEAGLLayer from CoreAnimation into a convenient UIView subclass.
+The view content is basically an EAGL surface you render your OpenGL scene into.
+Note that setting the view non-opaque will only work if the EAGL surface has an alpha channel.
+*/
+@interface PhysicsDebugView : PhysicsView {}
+
+@property (nonatomic, readonly, getter=isRunning) BOOL running;
+@property (nonatomic, assign) NSTimeInterval animationInterval;
+
+
+- (void) startAnimation;
+- (void) stopAnimation;
+
+@end
+
+
+// Render Settings
+struct Settings {
+    
+    Settings() :
+        hz(60.0f),
+        velocityIterations(10),
+        positionIterations(4),
+        drawStats(0),
+        drawShapes(1),
+        drawJoints(1),
+        drawAABBs(0),
+        drawPairs(0),
+        drawContactPoints(0),
+        drawContactNormals(0),
+        drawContactForces(0),
+        drawFrictionForces(0),
+        drawCOMs(0),
+        enableWarmStarting(1),
+        enableContinuous(1),
+        pause(0),
+        singleStep(0)
+    {}
+    
+    float32 hz;
+    int32 velocityIterations;
+    int32 positionIterations;
+    int32 drawShapes;
+    int32 drawJoints;
+    int32 drawAABBs;
+    int32 drawPairs;
+    int32 drawContactPoints;
+    int32 drawContactNormals;
+    int32 drawContactForces;
+    int32 drawFrictionForces;
+    int32 drawCOMs;
+    int32 drawStats;
+    int32 enableWarmStarting;
+    int32 enableContinuous;
+    int32 pause;
+    int32 singleStep;
+};
diff --git a/src/physics/PhysicsDebugView.mm b/src/physics/PhysicsDebugView.mm
new file mode 100644 (file)
index 0000000..be4444b
--- /dev/null
@@ -0,0 +1,299 @@
+#import <QuartzCore/QuartzCore.h>
+#import <OpenGLES/EAGLDrawable.h>
+
+#import "PhysicsDebugView.h"
+
+
+#define USE_DEPTH_BUFFER 0
+#define kAccelerometerFrequency 30
+#define FRAMES_BETWEEN_PRESSES_FOR_DOUBLE_CLICK 10
+
+
+
+// A class extension to declare private methods
+@interface PhysicsDebugView () {
+
+@private
+    World* _world;
+    BOOL _running;
+    
+    NSTimer* animationTimer;
+    NSTimeInterval animationInterval;
+    BOOL panning;
+    
+    // Position offset and scale
+    float sceneScale;
+    CGPoint positionOffset;
+    
+    CGPoint lastWorldTouch;
+    CGPoint lastScreenTouch;
+    
+    b2MouseJoint* mouseJoint;
+    b2Vec2 mouseWorld;
+    int32 stepCount;
+
+    
+    /// OpenGL ///
+    
+    /* The pixel dimensions of the backbuffer */
+    GLint backingWidth;
+    GLint backingHeight;
+    
+    EAGLContext *context;
+    
+    /* OpenGL names for the renderbuffer and framebuffers used to render to this view */
+    GLuint viewRenderbuffer, viewFramebuffer;
+    
+    /* OpenGL name for the depth buffer that is attached to viewFramebuffer, if it exists (0 if it does not exist) */
+    GLuint depthRenderbuffer;
+    
+}
+
+@property (nonatomic, retain) EAGLContext *context;
+@property (nonatomic, assign) NSTimer *animationTimer;
+
+- (BOOL) createFramebuffer;
+- (void) destroyFramebuffer;
+
+@end
+
+
+
+
+@implementation PhysicsDebugView
+
+@synthesize world = _world;
+@synthesize running = _running;
+
+@synthesize context;
+@synthesize animationTimer;
+@synthesize animationInterval;
+
+
+// You must implement this method
++ (Class)layerClass {
+    return [CAEAGLLayer class];
+}
+
+
+//The GL view is stored in the nib file. When it's unarchived it's sent -initWithCoder:
+- (id)initWithCoder:(NSCoder*)coder {
+    
+    if ((self = [super initWithCoder:coder])) {
+        // Get the layer
+        CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
+        
+        eaglLayer.opaque = YES;
+        eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
+                                        [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
+        
+        context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
+        
+        if (!context || ![EAGLContext setCurrentContext:context]) {
+            [self release];
+            return nil;
+        }
+        
+        _running = NO;
+        animationInterval = 1.0 / 60.0;
+        sceneScale = 10.0f;
+        positionOffset = CGPointMake(0, 0);
+        lastWorldTouch = CGPointMake(0, 0);
+        
+        [[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0 / kAccelerometerFrequency)];
+        [[UIAccelerometer sharedAccelerometer] setDelegate:self];
+    }
+    
+    return self;
+}
+
+- (void) dealloc {
+    [self stopAnimation];
+    
+    if ([EAGLContext currentContext] == context) {
+        [EAGLContext setCurrentContext:nil];
+    }
+    
+    [context release];
+    [super dealloc];
+}
+
+
+/// Accessors ///
+
+- (void) setAnimationTimer:(NSTimer*)newTimer {
+    [animationTimer invalidate];
+    animationTimer = newTimer;
+}
+
+- (void) setAnimationInterval:(NSTimeInterval)interval {
+    animationInterval = interval;
+    if (animationTimer) {
+        [self stopAnimation];
+        [self startAnimation];
+    }
+}
+
+
+/// Methods ///
+
+- (void) startAnimation {
+    _running = YES;
+    self.animationTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval target:self selector:@selector(drawView) userInfo:nil repeats:YES];
+}
+
+- (void) stopAnimation {
+    _running = NO;
+    self.animationTimer = nil;
+}
+
+- (CGPoint) screenSpaceToWorldSpace:(CGPoint) screenLocation {
+    screenLocation.x -= 160;
+    screenLocation.y -= 240;
+    screenLocation.x /= 160;
+    screenLocation.y /= 160;
+    screenLocation.x *= sceneScale;
+    screenLocation.y *= -sceneScale;
+    
+    screenLocation.x -= positionOffset.x;
+    screenLocation.y -= positionOffset.y;
+    
+    return screenLocation;
+}
+
+
+/// Events ///
+
+- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
+    panning = false;
+    for (UITouch *touch in touches) {
+        CGPoint touchLocation = [touch locationInView:self];
+        CGPoint worldPosition = [self screenSpaceToWorldSpace:touchLocation];
+        //printf("Screen touched %f,%f -> %f,%f\n",touchLocation.x,touchLocation.y,worldPosition.x,worldPosition.y);
+        lastScreenTouch = touchLocation;
+        lastWorldTouch = worldPosition;
+        
+        // test->MouseDown(b2Vec2(lastWorldTouch.x,lastWorldTouch.y));
+        // if (!test->m_mouseJoint) panning=true;
+    }
+}
+
+- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
+    for (UITouch *touch in touches) {
+        CGPoint touchLocation = [touch locationInView:self];
+        CGPoint worldPosition = [self screenSpaceToWorldSpace:touchLocation];
+        //printf("Screen touched %f,%f -> %f,%f\n",touchLocation.x,touchLocation.y,worldPosition.x,worldPosition.y);
+        
+        
+        CGPoint screenDistanceMoved = CGPointMake(touchLocation.x-lastScreenTouch.x,touchLocation.y-lastScreenTouch.y);
+        if (panning) {
+            screenDistanceMoved.x /= 160;
+            screenDistanceMoved.y /= 160;
+            screenDistanceMoved.x *= sceneScale;
+            screenDistanceMoved.y *= -sceneScale;
+            positionOffset.x += screenDistanceMoved.x;
+            positionOffset.y += screenDistanceMoved.y;
+        }
+        
+        lastScreenTouch = touchLocation;
+        lastWorldTouch = worldPosition;
+        // test->MouseMove(b2Vec2(lastWorldTouch.x,lastWorldTouch.y));
+    }
+}
+
+- (void) touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
+    // test->MouseUp(b2Vec2(lastWorldTouch.x, lastWorldTouch.y));
+}
+
+- (void) accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)acceleration {
+    // Only run for valid values
+    if (acceleration.y != 0 && acceleration.x != 0) {
+        if (self.world) [self.world setGravityX:acceleration.x Y:acceleration.y];
+    }
+}
+
+
+
+
+/// OpenGL ///
+
+- (void) drawView {
+    [EAGLContext setCurrentContext:context];
+    
+    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
+    glViewport(0, 0, backingWidth, backingHeight);
+    
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    
+    glOrthof(-sceneScale, sceneScale, -sceneScale*1.5f, sceneScale*1.5f, -1.0f, 1.0f);
+    
+    glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity();
+    glTranslatef(positionOffset.x, positionOffset.y,0);
+    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    
+    glEnableClientState(GL_VERTEX_ARRAY);
+    
+    [self.world step];
+    
+    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
+    [context presentRenderbuffer:GL_RENDERBUFFER_OES];
+}
+
+
+- (void) layoutSubviews {
+    [EAGLContext setCurrentContext:context];
+    [self destroyFramebuffer];
+    [self createFramebuffer];
+    [self drawView];
+}
+
+
+- (BOOL) createFramebuffer {
+    
+    glGenFramebuffersOES(1, &viewFramebuffer);
+    glGenRenderbuffersOES(1, &viewRenderbuffer);
+    
+    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
+    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
+    [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
+    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
+    
+    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
+    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
+    
+    if (USE_DEPTH_BUFFER) {
+        glGenRenderbuffersOES(1, &depthRenderbuffer);
+        glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
+        glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight);
+        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
+    }
+    
+    if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
+        NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
+        return NO;
+    }
+    
+    return YES;
+}
+
+
+- (void) destroyFramebuffer {
+    
+    glDeleteFramebuffersOES(1, &viewFramebuffer);
+    viewFramebuffer = 0;
+    glDeleteRenderbuffersOES(1, &viewRenderbuffer);
+    viewRenderbuffer = 0;
+    
+    if(depthRenderbuffer) {
+        glDeleteRenderbuffersOES(1, &depthRenderbuffer);
+        depthRenderbuffer = 0;
+    }
+}
+
+@end
index 6927a66..d9d2b56 100644 (file)
@@ -1,14 +1,16 @@
-#import <Foundation/Foundation.h>
 #include <Box2D/Box2D.h>
+#import "ui/GLES-Render.h"
 
 
 @interface World : NSObject {
-    
+
 @private
-    b2World* _world;
     float _timestep;
     int _velocityIterations;
     int _positionIterations;
+    
+    b2World* _world;
+    GLESDebugDraw debugDraw;
 }
 
 @property (nonatomic, readonly) b2World* world;
@@ -19,7 +21,9 @@
 
 - (World*) init;
 - (World*) initWithTimestep:(float)hz;
-- (World*) initWithTimestep:(float)hz gravityX:(float)x Y:(float)y;
+- (World*) initWithTimestep:(float)hz gravityX:(float)x y:(float)y;
+
+- (void) setGravityX:(float)x y:(float)y;
 
 - (void) step;
 
index 0b4a104..0beb32b 100644 (file)
@@ -1,6 +1,7 @@
 #import "World.h"
 
 
+
 @implementation World
 
 @synthesize world = _world;
 }
 
 - (World*) initWithTimestep:(float)hz {
-    return [self initWithTimestep:hz gravityX:0.0f Y:0.0f];
+    return [self initWithTimestep:hz gravityX:0.0f y:0.0f];
 }
 
-- (World*) initWithTimestep:(float)hz gravityX:(float)x Y:(float)y {
+- (World*) initWithTimestep:(float)hz gravityX:(float)x y:(float)y {
     if ((self = [super init])) {
-        b2Vec2 gravity = b2Vec2(x,y);
-        bool doSleep = true;
-        _world = new b2World(gravity, doSleep);
-        
         _timestep = 1.0f/hz;
         _velocityIterations = 10;
         _positionIterations = 10;
+        
+        b2Vec2 gravity = b2Vec2(x,y);
+        bool doSleep = true;
+        _world = new b2World(gravity, doSleep);
+        // _world->SetDebugDraw(&debugDraw);
     }
     return self;
 }
 }
 
 - (void) step {
-    self.world->Step(self.timestep, self.velocityIterations, self.positionIterations);
+    _world->Step(self.timestep, self.velocityIterations, self.positionIterations);
+    // _world->DrawDebugData();
+}
+
+- (void) setGravityX:(float)x y:(float)y {
+    _world->SetGravity(b2Vec2(x,y));
 }
 
+
+
+
+
 @end
diff --git a/src/tanks/Active.h b/src/tanks/Active.h
new file mode 100644 (file)
index 0000000..b9514a1
--- /dev/null
@@ -0,0 +1,11 @@
+
+/**
+ * Anything that takes a turn is Active.
+ */
+@protocol Active
+
+@property (nonatomic, getter=isActive) BOOL active;
+
+- (void) act;
+
+@end
\ No newline at end of file
diff --git a/src/tanks/Displayable.h b/src/tanks/Displayable.h
new file mode 100644 (file)
index 0000000..c99f41c
--- /dev/null
@@ -0,0 +1,8 @@
+#import "Sparrow.h"
+
+
+@protocol Displayable
+
+@property (nonatomic, readonly) SPDisplayObject* shape;
+
+@end
\ No newline at end of file
index 50950df..8b55c7a 100644 (file)
@@ -1,18 +1,13 @@
-//
-//  Game.h
-//  tanks
-//
-//  Created by dsc on 4/27/11.
-//  Copyright 2011 lttlst.com. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
 #import "Sparrow.h"
-#import "tanks/unit/Unit.h"
+
+#import "physics/World.h"
+
 
 
 @interface Game : SPStage
 
-@property(retain) Unit* unit;
+@property (nonatomic, retain) World* world;
+
+- (void) onEnterFrame:(SPEnterFrameEvent*)event;
 
 @end
diff --git a/src/tanks/Game.m b/src/tanks/Game.m
deleted file mode 100644 (file)
index 377fb6d..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-//
-//  Game.m
-//  tanks
-//
-//  Created by dsc on 4/27/11.
-//  Copyright 2011 lttlst.com. All rights reserved.
-//
-
-#import "Game.h"
-
-
-@implementation Game
-
-@synthesize unit;
-
-- (id)initWithWidth:(float)width height:(float)height {
-    if ( (self = [super initWithWidth:width height:height]) ){
-        unit = [[Unit alloc] initWithWidth:100 height:100 X:50 Y:50];
-        [self addEventListener:@selector(onTouch:) atObject:unit forType:SP_EVENT_TYPE_TOUCH];
-        [self addChild:unit.quad];
-    }
-    return self;
-}
-
-- (void)dealloc {
-    [self setUnit:nil];
-    [super dealloc];
-}
-
-@end
\ No newline at end of file
diff --git a/src/tanks/Game.mm