Download - Test Driven Cocos2d

Transcript
Page 1: Test Driven Cocos2d

Saturday, October 26, 13

Page 2: Test Driven Cocos2d

Saturday, October 26, 13

Page 3: Test Driven Cocos2d

A game is a system in which players engage in an artificial conflict, defined by rules, that results in a quantifiable outcome.

Rules of Play

Saturday, October 26, 13

Page 4: Test Driven Cocos2d

Saturday, October 26, 13

Page 5: Test Driven Cocos2d

[Expect(game) toBe:Fun]

TDD in Games with Cocos2D

Saturday, October 26, 13

Page 6: Test Driven Cocos2d

Sprites and Sprite SheetsScene ManagementActions and AnimationsEffectsMenusTile MapsAnd more....

Saturday, October 26, 13

Page 7: Test Driven Cocos2d

Saturday, October 26, 13

Page 8: Test Driven Cocos2d

Saturday, October 26, 13

Page 9: Test Driven Cocos2d

Saturday, October 26, 13

Page 10: Test Driven Cocos2d

Saturday, October 26, 13

Page 11: Test Driven Cocos2d

Saturday, October 26, 13

Page 12: Test Driven Cocos2d

Saturday, October 26, 13

Page 13: Test Driven Cocos2d

Saturday, October 26, 13

Page 14: Test Driven Cocos2d

Saturday, October 26, 13

Page 15: Test Driven Cocos2d

The player starts the game and has three buckets.  They can move the buckets right and left.

Saturday, October 26, 13

Page 16: Test Driven Cocos2d

Saturday, October 26, 13

Page 17: Test Driven Cocos2d

Saturday, October 26, 13

Page 18: Test Driven Cocos2d

+(CCScene *) scene{!// 'scene' is an autorelease object.!CCScene *scene = [CCScene node];!!// 'layer' is an autorelease object.!HelloWorldLayer *layer = [HelloWorldLayer node];!!// add layer as a child to scene![scene addChild: layer];!!// return the scene!return scene;}

Hello World Layer

Saturday, October 26, 13

Page 19: Test Driven Cocos2d

Hello World Layer// on "init" you need to initialize your instance-(id) init{!// always call "super" init!// Apple recommends to re-assign "self" with the "super's" return value!if( (self=[super init]) ) {!!!! // create and initialize a Label!! CCLabelTTF *label = [CCLabelTTF labelWithString:@"Hello World"

fontName:@"Marker Felt" fontSize:64];

!! // ask director for the window size!! CGSize size = [[CCDirector sharedDirector] winSize];!!! // position the label on the center of the screen!! label.position = ccp( size.width /2 , size.height/2 );!!!! // add the label as a child to this Layer!! [self addChild: label];

Saturday, October 26, 13

Page 20: Test Driven Cocos2d

OCDSpec2Context(BucketsSpec) { Describe(@"moving", ^{ It(@"moves to the right", ^{ Buckets *buckets = [[Buckets alloc] initWithPosition:CGPointMake(10.0, 10.0)];

[buckets move:1];

[ExpectFloat(buckets.position.x) toBe:11.0 withPrecision:0.00001]; });

It(@"moves to the left", ^{ Buckets *buckets = [[Buckets alloc] initWithPosition:CGPointMake(10.0, 10.0)];

[buckets move:-1.0];

[ExpectFloat(buckets.position.x) toBe:9.0 withPrecision:0.00001]; }); }); }

Buckets

Saturday, October 26, 13

Page 21: Test Driven Cocos2d

@implementation Buckets

-(id) initWithPosition:(CGPoint) position{ if (self = [super init]) { self.position = position; } return self;}

-(void) move:(float) movement{ self.position = CGPointMake(self.position.x + movement, self.position.y);}@end

Buckets

Saturday, October 26, 13

Page 22: Test Driven Cocos2d

Saturday, October 26, 13

Page 23: Test Driven Cocos2d

Saturday, October 26, 13

Page 24: Test Driven Cocos2d

Bombing Layer

-(id) init{ if( (self=[super init]) ) {!! // ask director for the window size!! CGSize size = [[CCDirector sharedDirector] winSize];

Buckets *buckets = [[Buckets alloc] initWithPosition:CGPointMake(size.width / 2, size.height / 2)]; BucketsSprite *sprite = [BucketsSprite spriteWithBuckets:buckets];

!! // add the sprite as a child to this Layer!! [self addChild: sprite];!}!return self;}

Saturday, October 26, 13

Page 25: Test Driven Cocos2d

Buckets Sprite@implementation BucketsSprite

+(id) spriteWithBuckets:(Buckets *)buckets{ BucketsSprite *sprite = [BucketsSprite spriteWithFile:@"buckets.png"]; sprite.buckets = buckets;

[sprite scheduleUpdate]; return sprite;}

-(void)update:(ccTime)delta { [self setPosition:self.buckets.position];}@end

Saturday, October 26, 13

Page 26: Test Driven Cocos2d

Saturday, October 26, 13

Page 27: Test Driven Cocos2d

Bombing Layer-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event{ CGPoint point = [touch locationInView:[touch view]]; CGSize size = [[CCDirector sharedDirector] winSize];

if (point.x > size.width / 2) { self.movement++; } else { self.movement--; } return YES;}

Saturday, October 26, 13

Page 28: Test Driven Cocos2d

Bombing Layer

-(void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event{ CGPoint point = [touch locationInView:[touch view]]; CGSize size = [[CCDirector sharedDirector] winSize];

if (point.x > size.width / 2) { self.movement--; } else { self.movement++; }}

Saturday, October 26, 13

Page 29: Test Driven Cocos2d

Bombing Layer

-(void)update:(ccTime)delta{ BucketsSprite *sprite = (BucketsSprite *)[self getChildByTag:kBucket]; [sprite move:self.movement];}

Saturday, October 26, 13

Page 30: Test Driven Cocos2d

Saturday, October 26, 13

Page 31: Test Driven Cocos2d

?Saturday, October 26, 13

Page 32: Test Driven Cocos2d

Saturday, October 26, 13

Page 33: Test Driven Cocos2d

OCDSpec2Context(BomberSpec) { Describe(@"moving back and forth", ^{ It(@"moves towards its next spot", ^{ RiggedLocations *locations = [RiggedLocations newWithValues:@[@0.0]]; Bomber *bomber = [[Bomber alloc] initWithPosition:CGPointMake(10, 40)

speed:1.0 locationChooser:locations];

[bomber start];

[bomber update:1.0];

[ExpectFloat(bomber.position.x) toBe:9.0 withPrecision:0.0001]; });

Bomber Spec

Saturday, October 26, 13

Page 34: Test Driven Cocos2d

@implementation RiggedLocations

-(float) next { float value = [(NSNumber *) [self.values firstObject] floatValue]; if (self.values.count > 1) { [self.values removeObjectAtIndex:0]; }

return value;}

+(RiggedLocations *) newWithValues:(NSArray *)array { RiggedLocations *locations = [RiggedLocations new]; locations.values = [NSMutableArray arrayWithArray:array]; return locations;}

@end

Rigged Locations

Saturday, October 26, 13

Page 35: Test Driven Cocos2d

Describe(@"using the random number generator", ^{

It(@"uses the random number generator for its next location", ^{ id rand = [OCMockObject mockForProtocol:@protocol(RandomNumberGenerator)]; NSRange range = NSMakeRange(0, 100);

RandomLocationChooser *chooser = [RandomLocationChooser newChooserWithRange:range generator:rand];

float retVal = 0.0; [[[rand stub] andReturnValue:OCMOCK_VALUE(retVal)] generate];

[ExpectFloat([chooser next]) toBe:0.0 withPrecision:0.0001]; });

Random Locations

Saturday, October 26, 13

Page 36: Test Driven Cocos2d

Saturday, October 26, 13

Page 37: Test Driven Cocos2d

It(@"stops at the location when coming from the left", ^{ RiggedLocations *locations = [RiggedLocations newWithValues:@[@19.0, @22.0]]; Bomber *bomber = [[Bomber alloc] initWithPosition:CGPointMake(17, 40) speed:2.0 locationChooser:locations];

[bomber start];

[bomber update:1.0]; [bomber update:1.0];

[ExpectFloat(bomber.position.x) toBe:21.0 withPrecision:0.0001]; });

It(@"doesn't move until it is started", ^{ RiggedLocations *locations = [RiggedLocations newWithValues:@[@19.0, @22.0]]; Bomber *bomber = [[Bomber alloc] initWithPosition:CGPointMake(17, 40) speed:2.0 locationChooser:locations];

[bomber update:1.0];

[ExpectFloat(bomber.position.x) toBe:17.0 withPrecision:0.0001]; });

Bomber Spec

Saturday, October 26, 13

Page 38: Test Driven Cocos2d

Bomber- (void)update:(float)deltaTime{ if (self.started) { float moveDistance = self.speed * deltaTime; float distanceRemaining = abs(self.location - self.position.x);

if (self.location > self.position.x) { self.position = CGPointMake(self.position.x + moveDistance, self.position.y); } else { self.position = CGPointMake(self.position.x - moveDistance, self.position.y); }

if (moveDistance >= distanceRemaining) { self.location = [self.locations next]; } }

Saturday, October 26, 13

Page 39: Test Driven Cocos2d

-(id) init{ if (self = [super init]) { srand48(time(0)); } return self;}

-(float) generate{ return drand48();}

“Random”

Saturday, October 26, 13

Page 40: Test Driven Cocos2d

Bomber *bomber = [[Bomber alloc] initWithPosition:CGPointMake(size.width / 2, speed:60.0 locationChooser:chooser];BomberSprite *bomberSprite = [BomberSprite newSpriteWithBomber:bomber];

[self addChild:bomberSprite z:0 tag:kBomber]; [bomber start];

Bombing Layer

Saturday, October 26, 13

Page 41: Test Driven Cocos2d

@implementation BomberSprite

+(id) newSpriteWithBomber:(Bomber *)bomber{ BomberSprite *sprite = [BomberSprite spriteWithFile:@"bomber.png"]; sprite.bomber = bomber; [sprite scheduleUpdate]; return sprite;}

-(void)update:(ccTime)delta{ [self.bomber update:delta]; [self setPosition:self.bomber.position];}

Bomber Sprite

Saturday, October 26, 13

Page 42: Test Driven Cocos2d

Saturday, October 26, 13

Page 43: Test Driven Cocos2d

It(@"drops a bomb when it changes direction", ^{ RiggedLocations *locations = [RiggedLocations newWithValues:@[@18.0]]; Bomber *bomber = [[Bomber alloc] initWithPosition:CGPointMake(17.0, speed:1.0 locationChooser:locations];

[bomber start]; [bomber update:1.0];

[ExpectInt(bomber.bombCount) toBe:1]; });

Bomber Spec

Saturday, October 26, 13

Page 44: Test Driven Cocos2d

It(@"moves the bomb on each update", ^{ RiggedLocations *locations = [RiggedLocations newWithValues:@[@18.0]];

Bomber *bomber = [[Bomber alloc] initWithPosition:CGPointMake(17.0 speed:1.0 locationChooser:locations height:10 bombHeight:20];

[bomber start]; [bomber update:1.0]; [bomber update:1.0];

CGPoint bombPosition; [(NSValue *) bomber.bombs[0] getValue:&bombPosition]; [ExpectInt(bombPosition.x) toBe:18]; [ExpectInt(bombPosition.y) toBe:55 - kGravity]; });

Bomber Spec

Saturday, October 26, 13

Page 45: Test Driven Cocos2d

[self.bomber.bombs enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { [self.parent removeChildByTag:kBomb + idx]; NSValue *bombValue = (NSValue *)obj; CGPoint location; [bombValue getValue:&location];

CCSprite *bombSprite = [CCSprite spriteWithFile:@"bomb.png"]; bombSprite.position = location; [self.parent addChild:bombSprite z:0 tag:kBomb + idx]; }];

Bomber Sprite

Saturday, October 26, 13

Page 46: Test Driven Cocos2d

SHOW ME

Saturday, October 26, 13

Page 47: Test Driven Cocos2d

TDD and Games

• Have a Plan

• You Use the Framework

• Keep Views dumbBullets Suck - Hi Eric

Saturday, October 26, 13

Page 48: Test Driven Cocos2d

Saturday, October 26, 13

Page 49: Test Driven Cocos2d

Saturday, October 26, 13

Page 50: Test Driven Cocos2d

Saturday, October 26, 13

Page 51: Test Driven Cocos2d

Saturday, October 26, 13

Page 52: Test Driven Cocos2d

Saturday, October 26, 13

Page 53: Test Driven Cocos2d

5!

Saturday, October 26, 13

Page 54: Test Driven Cocos2d

@paytonruleswww.paytonrules.comwww.8thlight.comwww.github.com/paytonrules

Saturday, October 26, 13