Adds Cooldown class.
authordsc <david.schoonover@gmail.com>
Tue, 24 May 2011 08:30:53 +0000 (01:30 -0700)
committerdsc <david.schoonover@gmail.com>
Tue, 24 May 2011 08:30:53 +0000 (01:30 -0700)
src/game/QQActive.h
src/game/QQDisplayable.h
src/game/QQGame.mm
src/game/QQPhysical.h
src/game/ability/QQCooldown.h [new file with mode: 0644]
src/game/ability/QQCooldown.mm [new file with mode: 0644]
src/game/actor/QQActor.h
src/game/actor/QQUnit.h
src/game/actor/QQUnit.mm [deleted file]
src/prefix.pch

index 62a0681..ec6fe08 100644 (file)
@@ -1,8 +1,9 @@
+#import "game/QQThing.h"
 
 /**
  * Anything that takes a turn is QQActive.
  */
-@protocol QQActive
+@protocol QQActive <QQThing>
 
 @property (nonatomic, getter=isActive) BOOL active;
 
index 3d69432..a559892 100644 (file)
@@ -1,6 +1,9 @@
 #import "Sparrow.h"
 
 
+/**
+ * Anything that has a Sparrow represenation in the display tree.
+ */
 @protocol QQDisplayable
 
 @property (nonatomic, retain, readonly) SPDisplayObject* shape;
index aa54899..14ea57f 100644 (file)
@@ -1,9 +1,9 @@
 #import "QQGame.h"
-#import "game/actor/QQUnit.h"
+#import "game/actor/QQTank.h"
 
 
 
-static QQGame* _currentGame = NULL;
+static QQGame* _CurrentGame = NULL;
 
 
 
@@ -13,24 +13,24 @@ static QQGame* _currentGame = NULL;
 
 @implementation QQGame
 
-@synthesize ticks = _ticks;
-@synthesize world = _world;
+@synthesize ticks  = _ticks;
+@synthesize world  = _world;
 @synthesize actors = _actors;
 
 
 - (id) init {
-    if (_currentGame) {
+    if (_CurrentGame) {
         [self release];
         [NSException raise:@"TooManyGames" format:@"cannot instantiate more than one QQGame at a time!"];
     }
     
     if ( (self = [super init]) ){
-        _currentGame = self;
+        _CurrentGame = self;
         _ticks = 0l;
         _actors = [[NSMutableArray alloc] initWithCapacity:10];
         _world = [[QQWorld alloc] init];
         
-        [self addActor:[[[QQUnit alloc] init] autorelease]];
+        [self addActor:[[[QQTank alloc] init] autorelease]];
         
         [self addEventListener:@selector(onEnterFrame:) atObject:self forType:SP_EVENT_TYPE_ENTER_FRAME];
     }
@@ -41,7 +41,7 @@ static QQGame* _currentGame = NULL;
     [_actors removeAllObjects];
     [_actors release];
     [_world release];
-    _currentGame = NULL;
+    _CurrentGame = NULL;
     [super dealloc];
 }
 
@@ -69,10 +69,10 @@ static QQGame* _currentGame = NULL;
 
 
 + (QQGame*) current {
-    if (!_currentGame)
-        [[[QQGame alloc] init]    // init assigns to singleton, but singleton is a weakref,
+    if (!_CurrentGame)
+        [[[QQGame alloc] init]  // init assigns to singleton, but singleton is a weakref,
             autorelease];       // XXX: so game will still be released if not retained...
-    return _currentGame;
+    return _CurrentGame;
 }
 
 
index bb664cc..0dd0ce3 100644 (file)
@@ -5,8 +5,13 @@
  */
 @protocol QQPhysical
 
+// @property (nonatomic, readwrite, assign) float x;
+// @property (nonatomic, readwrite, assign) float y;
+
+
 // FIXME: don't expose these, instead aggregate properties from body & fixtures/shapes
 @property (nonatomic, readonly) b2Body* body;
 @property (nonatomic, readonly) b2Fixture* fixture;
 
+
 @end
\ No newline at end of file
diff --git a/src/game/ability/QQCooldown.h b/src/game/ability/QQCooldown.h
new file mode 100644 (file)
index 0000000..596b58e
--- /dev/null
@@ -0,0 +1,47 @@
+
+
+/**
+ * Cooldown timer.
+ */
+@interface QQCooldown : NSObject {
+@private
+    float _duration;
+    float _elapsed;
+}
+
+/** Duration of this cooldown timer (ms). */
+@property (nonatomic, readwrite, assign) float duration;
+
+/** Elapsed time (ms) since last activated if not ready; otherwise {duration}. */
+@property (nonatomic, readwrite, assign) float elapsed;
+
+/** Whether Cooldown timer is ready to be activated. */
+@property (nonatomic, readwrite, getter=isReady) BOOL ready;
+
+/** Percent completed (elapsed / duration), clamped [0, 1.0]. */
+@property (nonatomic, readwrite) float ratio;
+
+/**
+ * Implies ready=NO.
+ */
+- (id) initWithDuration:(float)duration;
+- (id) initWithDuration:(float)duration andReady:(BOOL)ready;
+
+/**
+ * Attempts to activate this cooldown, clearing the ready flag and setting elapsed to 0.
+ * If not ready, has no effect.
+ * @return Ready state.
+ */
+- (BOOL) activate;
+
+/**
+ * Advances the timer by {elapsed} milliseconds, updating ready state if necessary.
+ * @return Ready state.
+ */
+- (BOOL) tick:(float)elapsed;
+
+
++ (QQCooldown) cooldownWithDuration:(float)duration;
++ (QQCooldown) cooldownWithDuration:(float)duration andReady:(BOOL)ready;
+
+@end
diff --git a/src/game/ability/QQCooldown.mm b/src/game/ability/QQCooldown.mm
new file mode 100644 (file)
index 0000000..873bd54
--- /dev/null
@@ -0,0 +1,84 @@
+#import "QQCooldown.h"
+
+
+@implementation QQCooldown
+
+/// properties
+
+@synthesize duration = _duration;
+@synthesize elapsed = _elapsed;
+
+- (BOOL) ready { return (self.elapsed >= self.duration); }
+- (void) setReady:(BOOL)newReady {
+    if (newReady == self.ready)
+        return;
+    if (newReady)
+        self.elapsed = self.duration;
+    else
+        self.elapsed = 0f;
+}
+
+- (float) ratio { return fminf(1.0f, self.elapsed / self.duration); }
+- (void) setRatio:(float)newRatio {
+    if (newRatio >= 1.0f)
+        self.elapsed = self.duration;
+    else if (newRatio <= 0.0f)
+        self.elapsed = 0f;
+    else
+        self.elapsed = newRatio * self.duration;
+}
+
+
+/// initializers
+
+- (id) initWithDuration:(float)duration {
+    return [self initWithDuration:duration andReady:NO];
+}
+
+- (id) initWithDuration:(float)duration andReady:(BOOL)ready {
+    if ((self = [super init])){
+        _duration = duration;
+        _elapsed  = (ready ? _duration : 0f);
+    }
+    return self;
+}
+
+
+/// methods
+
+/**
+ * Attempts to activate this cooldown, clearing the ready flag and setting elapsed to 0. Otherwise has no effect.
+ * @return Whether activation succeeded.
+ */
+- (BOOL) activate {
+    if (self.ready) {
+        self.ready = NO;
+        return YES;
+    }
+    return NO;
+}
+
+/**
+ * Advances the timer by {elapsed} milliseconds, updating ready state if necessary.
+ * @return Ready state.
+ */
+- (BOOL) tick:(float)elapsed {
+    if (self.ready)
+        return YES;
+    self.elapsed += elapsed;
+    return self.ready;
+}
+
+
+/// convenience constructors
+
++ (QQCooldown) cooldownWithDuration:(float)duration {
+    return [[[QQCooldown alloc] initWithDuration:duration] autorelease];
+}
+
++ (QQCooldown) cooldownWithDuration:(float)duration andReady:(BOOL)ready {
+    return [[[QQCooldown alloc] initWithDuration:duration andReady:ready] autorelease];
+}
+
+
+@end
index b7fc953..3aefbe4 100644 (file)
@@ -1,4 +1,5 @@
 #include <Box2D/Box2D.h>
+#import "game/QQThing.h"
 #import "game/QQActive.h"
 #import "game/QQPhysical.h"
 #import "game/QQDisplayable.h"
@@ -7,7 +8,7 @@
 @class QQGame;
 
 
-@interface QQActor : NSObject <QQActive, QQPhysical, QQDisplayable> {
+@interface QQActor : NSObject <QQThing, QQActive, QQPhysical, QQDisplayable> {
     
 @protected
     b2Body* _body;
index 77517c9..6f05b9a 100644 (file)
@@ -1,30 +1,14 @@
-#include <Box2D/Box2D.h>
-#import "Sparrow.h"
-
-#import "render/QQSparrowExtensions.h"
-
 #import "game/actor/QQActor.h"
-#import "game/actor/QQUnitDelegate.h"
-
-#import "physics/QQWorld.h"
-
+#import "game/QQThing.h"
 
-////////////////////////////////////////////////////////////////////////////////////
-@interface QQUnit : QQActor {
 
-@private
-    SPDisplayObject* _shape;
-    id<QQUnitDelegate> _delegate;
-}
+@protocol QQUnit <QQThing>
 
-////////////////////////////////////////////////////////////////////////////////////
-@property (nonatomic, retain, readwrite) SPDisplayObject* shape;
-@property (nonatomic, retain, readwrite) id<QQUnitDelegate> delegate;
+@property (nonatomic, readonly) BOOL canAttack;
 
-////////////////////////////////////////////////////////////////////////////////////
-- (id) initWithFile:(NSString*)fileName atX:(float)x y:(float)y;
-- (id) initWithShape:(SPDisplayObject*)shape atX:(float)x y:(float)y;
+- (void) attackTarget:(QQActor)actor;
+- (void) attackToward:(NSPoint)point;
+- (void) attackTowardX:(float)x y:(float)y;
 
-- (void) onTouch:(SPTouchEvent*)event;
 
 @end
diff --git a/src/game/actor/QQUnit.mm b/src/game/actor/QQUnit.mm
deleted file mode 100644 (file)
index e6c0cac..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-#include <Box2D/Box2D.h>
-#import "Sparrow.h"
-#import "QQUnit.h"
-
-
-////////////////////////////////////////////////////////////////////////////////////
-@implementation QQUnit
-
-////////////////////////////////////////////////////////////////////////////////////
-@synthesize shape = _shape;
-@synthesize delegate = _delegate;
-
-////////////////////////////////////////////////////////////////////////////////////
-- (id) init {
-    return [self initWithShape:[SPQuad quadWithWidth:50 height:50 color:0xff0000] atX:15 y:15];
-}
-
-////////////////////////////////////////////////////////////////////////////////////
-- (id) initWithFile:(NSString*)fileName atX:(float)x y:(float)y {
-    return [self initWithShape:
-        [[[SPImage alloc] autorelease] initWithContentsOfFile:fileName]
-        atX:x y:y];
-}
-
-////////////////////////////////////////////////////////////////////////////////////
-- (id) initWithShape:(SPDisplayObject*)shape atX:(float)x y:(float)y {
-    if ((self = [super initAtX:x y:y])) {
-        float px = self.world.scale;
-        self.shape = [shape setPositionX:x*px y:y*px];
-        
-        b2PolygonShape box;
-        box.SetAsBox(shape.width/px, shape.height/px);
-        self.body->CreateFixture(&box, 5.0f);
-        
-        [self.game addEventListener:@selector(onTouch:) atObject:self forType:SP_EVENT_TYPE_TOUCH];
-    }
-    return self;
-}
-
-////////////////////////////////////////////////////////////////////////////////////
-- (void) dealloc {
-    [self.game removeEventListener:@selector(onTouch:) atObject:self forType:SP_EVENT_TYPE_TOUCH];
-    [self.game removeChild:_shape];
-    [_shape release];
-    [super dealloc];
-}
-
-////////////////////////////////////////////////////////////////////////////////////
-- (void) setShape:(SPDisplayObject*)newShape {
-    if (_shape != newShape) {
-        [self.game removeChild:_shape];
-        [_shape release];
-        _shape = [newShape retain];
-        [self.game addChild:_shape];
-    }
-}
-
-////////////////////////////////////////////////////////////////////////////////////
-- (void) onTouch:(SPTouchEvent*)event {
-    SPTouch* touch = [[event touchesWithTarget:self.shape.parent] anyObject];
-    if (touch) {
-        SPPoint* touchPosition = [touch locationInSpace:self.shape.parent];
-        float x = self.shape.x = touchPosition.x - self.shape.width / 2.0f;
-        float y = self.shape.y = touchPosition.y - self.shape.height / 2.0f;
-        
-        float px = self.world.scale;
-        self.body->SetTransform(b2Vec2(x/px, y/px), self.body->GetAngle());
-    }
-}
-
-
-@end
index 45a03fd..f3e2b5c 100644 (file)
@@ -12,3 +12,5 @@
     #import <UIKit/UIKit.h>
     #import <Foundation/Foundation.h>
 #endif
+
+#import "TanksMacros.h"