Test driven game development silly, stupid or inspired?

1,372 views

Published on

Published in: Technology, Design
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,372
On SlideShare
0
From Embeds
0
Number of Embeds
669
Actions
Shares
0
Downloads
7
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Test driven game development silly, stupid or inspired?

  1. 1. Tuesday, August 13, 13
  2. 2. Tuesday, August 13, 13
  3. 3. ! movl! edi,[_ylookup+edi*4] ! movl! eax,[_ds_x1] ! addl edi,[_columnofs+eax*4] // // build composite step // ! movl! ebx,[_ds_xstep] ! shll! ebx,10 ! andl! ebx,0ffff0000h ! movl! eax,[_ds_ystep] ! shrl! eax,6 ! andl! eax,0ffffh ! orl!ebx,eax ! movl! ! eax,OFFSET hpatch1+2! ! // convice tasm to modify code... ! movl! ! [eax],ebx ! movl! ! eax,OFFSET hpatch2+2! ! // convice tasm to modify code... ! movl! ! [eax],ebx // eax!! aligned colormap // ebx!! aligned colormap // ecx,edx! scratch // esi!! virtual source // edi!! moving destination pointer // ebp!! frac ! shldl ecx,ebp,22! Tuesday, August 13, 13
  4. 4. Tuesday, August 13, 13
  5. 5. Tuesday, August 13, 13
  6. 6. TDD and Games Silly, Stupid or Inspired? Tuesday, August 13, 13
  7. 7. var spaceImage = $("<img src='images/ space_background.png'>"); spaceImage.load(function() { spaceBackground = spaceImage.get(0); }); var playerImage = $("<img src='images/ player.png'>"); playerImage.load(function() { player = playerImage.get(0); }); var bulletJQueryImage = $("<img src='images/ bullet.png'>"); bulletJQueryImage.load(function() { bulletImage = bulletJQueryImage.get(0); }); Tuesday, August 13, 13
  8. 8. var context, spaceBackground, player, bulletImage, spiderImage, bullets = [], spiders = [], startTicks, lastGeneration, laserBeam, gameOn = true, explosion, pop, backgroundMusicTuesday, August 13, 13
  9. 9. Tuesday, August 13, 13
  10. 10. Scheduler ◦ schedules method called for repeated calls: ✓ schedules method called for repeated calls ◦ clears the interval when stop is called: ✓ clears the interval when stop is called ◦ calls that method with the tick rate: ✓ calls that method with the tick rate (200ms) ◦ returns the time for tics: ✓ returns the time for tics ◦ returns its tick time: ✓ returns its tick time 99 tests complete (743 ms) Done. Build script exited with 0 Tuesday, August 13, 13
  11. 11. Eskimo! Tuesday, August 13, 13
  12. 12. Tuesday, August 13, 13
  13. 13. ?Tuesday, August 13, 13
  14. 14. it("uses an associated loader to create a level object, if one exists", function() { var gameDescription = { "newLevel": { "gameObject" : { "customObject" : {} } } }; var customObjectLoader = { load: function(levelSpec, objectName, level, callback) { callback(objectName, {levelSpec: levelSpec, objectName: objectName, level: level}); } }; var gameSpec = new GameSpec({ assetDefinition: gameDescription }); gameSpec.registerLoader('customObject', customObjectLoader); gameSpec.load("newLevel", function(level) { var loadedObject = level.gameObject('gameObject'); assert.strictEqual(loadedObject.level, level); }); }); Tuesday, August 13, 13
  15. 15. var Eskimo = require('../src/main'), canvas, should = require('should'), assert = require('assert'), emptyFunction = function() {}, emptyDocument = {documentElement: null}, jquery = require("jquery"), FixedGameLoop = require("../src/fixed-game-loop"), ObjectPipeline = require('../src/object_pipeline/ display_visible_objects.js'), sandbox = require('sinon').sandbox.create(), levels = {}; function dependencies(customConfig) { var dependencyConfig = { game: {create: sandbox.stub().returns({})}, }; if (customConfig !== null) { jquery.extend(dependencyConfig, customConfig); } return dependencyConfig; } function configuration(config) { var standardConfig = {Tuesday, August 13, 13
  16. 16. Tuesday, August 13, 13
  17. 17. KEEP IT SIMPLE STUPID Tuesday, August 13, 13
  18. 18. Tuesday, August 13, 13
  19. 19. Hunting Tuesday, August 13, 13
  20. 20. Console DLL Game Logic Tuesday, August 13, 13
  21. 21. [Test]  public void ItMovesAnArrowInTheCommandedDirection()  {      var presenter = Substitute.For<Presenter>();      var map = new Map();      var game = new Game(presenter, map);      game.SetPlayerQuiver(1);      map.PlaceItem(0, MapItems.Player);      map.AddPath(0, 1, Command.Directions.East);      game.Command(new Command {          Direction = Command.Directions.East,          Order = Command.Commands.Shoot});      Assert.AreEqual(MapItems.Arrow, map.ItemsInCavern(1)[0]);  } Tuesday, August 13, 13
  22. 22.  protected void Rest()  {      DisplayAvailableDirections();      DisplayArrowStatus();  } Tuesday, August 13, 13
  23. 23. Feeling Good Tuesday, August 13, 13
  24. 24. Cubicle Wars Tuesday, August 13, 13
  25. 25. Unity Makes your life easier when it’s not making it harder Tuesday, August 13, 13
  26. 26. Scripts Tuesday, August 13, 13
  27. 27. public class NewScript : MonoBehaviour { // Use this for initialization void Start () { } // Update is called once per frame void Update () { } } Tuesday, August 13, 13
  28. 28. Tuesday, August 13, 13
  29. 29. Tuesday, August 13, 13
  30. 30. void Awake() { stateMachine = new CubicleWarsStateMachine( new HumanPlayer("Player1"), new HumanPlayer("Player2")); Tuesday, August 13, 13
  31. 31. ! ! [Test] ! ! public void ItAllowsAddingAUnitToAPlayer() ! ! { ! ! ! var unit = Substitute.For<Unit>(); ! ! ! stateMachine.AddUnitToPlayer("PlayerOne", unit); ! ! ! stateMachine.AddUnitToPlayer("PlayerTwo", unit); ! ! ! playerOne.Received().AddUnit(unit); ! ! ! playerTwo.Received().AddUnit(unit); ! ! } Tuesday, August 13, 13
  32. 32. Updating theView Tuesday, August 13, 13
  33. 33. Update theView public void Attack(Unit unit) ! ! { ! ! ! if (CurrentState == State.Attacking) ! ! ! { ! ! ! ! unit.AttackWith(CurrentPlayer.Weapon()); Tuesday, August 13, 13
  34. 34. Shared Interfaces Tuesday, August 13, 13
  35. 35. C# Events public delegate void GameOverEvent(String winner); ... public event GameOverEvent GameOver = delegate { }; ... private void AnnouncePlayerWins() { GameOver(CurrentPlayer.Name); } Tuesday, August 13, 13
  36. 36. Wiring the Events machine.GameOver += delegate(string winner) { winMessage.SendMessage("ShowWinner", String.Format("{0} wins!", winner)); }; Tuesday, August 13, 13
  37. 37. Health Tuesday, August 13, 13
  38. 38. “MVC” Tuesday, August 13, 13
  39. 39. void Update() { // Each update checks if we are waiting, and if so // modulates the color based on the sin wave and the // current time. if (StartWaiting) { renderer.material.color = tint * wave.at(Time.time); } } Tuesday, August 13, 13
  40. 40. Effects public class SineWave { ! protected float Amplitude { get; set; } ! protected float Frequency { get; set; } ! protected float Offset { get; set; } ! public SineWave(float amplitude, float frequency, float offset) ! { ! ! Amplitude = amplitude; ! ! Frequency = frequency; ! ! Offset = offset; ! } ! public float at(float time) ! { ! ! return (Amplitude * (float)Math.Sin(Frequency * time)) + Offset; ! } } Tuesday, August 13, 13
  41. 41. Effects [Test] public void ItReturnsANormalSinWaveOnTime() { ! var sineWave = new SineWave(1, 1, 0); ! Assert.AreEqual(0, sineWave.at(0)); ! Assert.AreEqual(1, sineWave.at((float) Math.PI / 2.0f)); } Tuesday, August 13, 13
  42. 42. Tuesday, August 13, 13
  43. 43. Tuesday, August 13, 13
  44. 44. Hypothesis Tuesday, August 13, 13
  45. 45. Hypothesis Tuesday, August 13, 13
  46. 46. Tuesday, August 13, 13
  47. 47. -(void) notifyOfSuccessfulDay { [self.presenter gameOver:Successful]; } -(void) notifyOfFailedDay { [self.presenter gameOver:Failed]; } -(void) notifyOfKidDeath { [self.presenter kidsKilledYou]; } -(void) notifyOfWorkDeath { [self.presenter workKilledYou]; } Tuesday, August 13, 13
  48. 48. It(@"Will inform the employee of clock ticks when the turn ends", ^{ id daddy = [OCMockObject niceMockForProtocol:@protocol(Freelancer)]; WorkdayStateMachine *machine = [WorkdayStateMachine machineWithFreeLancer:dadd presenter:nil] [machine start]; [[daddy expect] clockTicked]; [machine endTurn]; [daddy verify]; }); Tuesday, August 13, 13
  49. 49. Tuesday, August 13, 13
  50. 50. Tuesday, August 13, 13
  51. 51. Tuesday, August 13, 13
  52. 52. It(@"is fun", ^{ [ExpectBool(game.fun) toBeTrue]; }) Tuesday, August 13, 13
  53. 53. Tuesday, August 13, 13
  54. 54. Tuesday, August 13, 13
  55. 55. Tuesday, August 13, 13
  56. 56. Tuesday, August 13, 13
  57. 57. Tuesday, August 13, 13
  58. 58. FTT • Forget • The • Tests Tuesday, August 13, 13
  59. 59. Sprite *sprite = Sprite::createWithTexture(batchNode->getTexture()); sprite->setPosition(ccp(0, 60)); batchNode->addChild(sprite, 0, kTopBucket); sprite = Sprite::createWithTexture(batchNode->getTexture()); sprite->setPosition(ccp(0, 0)); batchNode->addChild(sprite, 0, kMiddleBucket); sprite = Sprite::createWithTexture(batchNode->getTexture()); sprite->setPosition(ccp(0, -60)); batchNode->addChild(sprite, 0, kBottomBucket); Tuesday, August 13, 13
  60. 60. Tuesday, August 13, 13
  61. 61. Design Phase Tuesday, August 13, 13
  62. 62. Bugs Tuesday, August 13, 13
  63. 63. Tuesday, August 13, 13
  64. 64. Not the Hard Part Tuesday, August 13, 13
  65. 65. Tuesday, August 13, 13
  66. 66. Tuesday, August 13, 13
  67. 67. Tuesday, August 13, 13
  68. 68. Tuesday, August 13, 13
  69. 69. Tuesday, August 13, 13
  70. 70. Tuesday, August 13, 13
  71. 71. Throw It Out! Tuesday, August 13, 13
  72. 72. It(@"lets the lesson know about an incorrect guess if this is the wrong card", ^{ [[lesson expect] incorrectGuess]; [card tap]; [lesson verify]; }); -(void) tap { self.current ? [self.lesson correctGuess] : [self.lesson incorrectGuess]; } Tuesday, August 13, 13
  73. 73. -(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event { CGSize textureSize = [self.texture contentSizeInPixels]; if ([Card contains: [self convertTouchToNodeSpaceAR:touch] inTextureSize:textureSize]) { [self setScale:1.2f]; return true; } return false; } -(void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event { [self setScale:1.0f]; [self.card tap]; } Tuesday, August 13, 13
  74. 74. <p> <strong>Title:</strong> <%= @post.title %> </p> <p> <strong>Text:</strong> <%= @post.text %> </p> Tuesday, August 13, 13
  75. 75. <%= form_for :post, url: posts_path do |f| %> <% if @post.errors.any? %> <div id="errorExplanation"> <h2><%= pluralize(@post.errors.count, "error") %> prohibited this post from being saved:</h2> <ul> <% @post.errors.full_messages.each do |msg| %> <li><%= msg %></li> <% end Tuesday, August 13, 13
  76. 76. Expect(game) toBeFun Tuesday, August 13, 13
  77. 77. @paytonrules www.paytonrules.com www.8thlight.com www.github.com/paytonrules Tuesday, August 13, 13
  78. 78. Platinum Sponsors Gold Sponsors Tuesday, August 13, 13
  79. 79. August 11th – 13th 2014 Same Place, Same Time Tuesday, August 13, 13

×