Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Itty bittypresentation lrug

420 views

Published on

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Itty bittypresentation lrug

  1. 1. IttyBittyBoom.com Cramp + Websockets = Awesome
  2. 2. What ? Attempt to play film here...
  3. 3. Why ?
  4. 4. How ? Drawing - canvas Network Requests - websockets Server - cramp
  5. 5. HTML5 Canvas Very Cool, Can do lots of cool things with it, Browser support is good (safari3.2, chrome3, firefox 3.0)
  6. 6. <table id= &quot;map&quot; > <tr> <td> StoneBlock </td><td> StoneBlock </td><td> StoneBlock </td><td> StoneBlock </td><td> StoneBlock </td><td> StoneBlock </td><td> StoneBlock </td> </tr> <tr> <td> StoneBlock </td><td walk= 'false' > WallBlockTall </td><td> StoneBlock </td><td walk= 'false' > WallBlockTall </td><td> StoneBlock </td><td walk= 'false' > WallBlockTall </td><td> StoneBlock </td> </tr> <tr> <td> StoneBlock </td><td> StoneBlock </td><td> StoneBlock </td><td> StoneBlock </td><td> StoneBlock </td><td> StoneBlock </td><td> StoneBlock </td> </tr> <tr> <td> StoneBlock </td><td walk= 'false' > WallBlockTall </td><td> StoneBlock </td><td walk= 'false' > WallBlockTall </td><td> StoneBlock </td><td walk= 'false' > WallBlockTall </td><td> StoneBlock </td> </tr> <tr> <td> StoneBlock </td><td> StoneBlock </td><td> StoneBlock </td><td> StoneBlock </td><td> StoneBlock </td><td> StoneBlock </td><td> StoneBlock </td> </tr> <tr> <td> StoneBlock </td><td walk= 'false' > WallBlockTall </td><td> StoneBlock </td><td walk= 'false' > WallBlockTall </td><td> StoneBlock </td><td walk= 'false' > WallBlockTall </td><td> StoneBlock </td> </tr> <tr> <td> StoneBlock </td><td> StoneBlock </td><td> StoneBlock </td><td> StoneBlock </td><td> StoneBlock </td><td> StoneBlock </td><td> StoneBlock </td> </tr> </table>
  7. 8. Sprites canvas.getContext( '2d' ).drawImage( image, imgOffsetX, imgOffsetY, frameWidth, frameHeight, xPos, yPos, frameWidth, frameHeight)
  8. 9. Websockets Full Duplex communication channel over a single socket Javascript interface Cope with firewalls + proxies
  9. 10. //Create one: var socket = new WebSocket ( 'ws://ittybittyboom.com/game' ); //Use it: socket . onopen = function ( evt ) { alert ( &quot;Connection open ...&quot; ); }; socket . onmessage = function ( evt ) { alert ( &quot;Received Message: &quot; + evt. data ); }; socket . onclose = function ( evt ) { alert ( &quot;Connection closed.&quot; ); }; socket. send ( &quot;Any data you fancy&quot; );
  10. 11. Where does Itty use them? Everywhere!
  11. 12. “ Run Away!”
  12. 13. //Register Keypress switch ( event .which){ case 38 : MrJaba.Bomberman.me.setMovementDirection( 'up' ); break ; case 40 : MrJaba.Bomberman.me.setMovementDirection( 'down' ); break ; case 37 : MrJaba.Bomberman.me.setMovementDirection( 'left' ); break ; case 39 : MrJaba.Bomberman.me.setMovementDirection( 'right' ); break ; } //Run Every Clock Tick: update : function (){ if ( this .canMoveTo( newX, newY )){ MrJaba.Bomberman.GameClient.trigger( 'player_move' ); } } //Send data to the server {&quot;type&quot;:&quot;player_move&quot;,&quot;uuid&quot;:&quot;5a5c0a80-844f-012d-5d1f-001b63957646&quot;,&quot;data&quot;:{&quot;x&quot;:&quot;0&quot;,&quot;y&quot;:&quot;105&quot;}} socket. send (movement_data);
  13. 14. “ You can't give a bomb to a baby!”
  14. 15. //Trigger the bombdrop on the game client MrJaba.Bomberman.GameClient.trigger( 'send_bomb_drop' ); //Send the Bomb drop message socket. send ( { &quot;type&quot; : &quot;send_bomb_drop&quot; , &quot;uuid&quot; : &quot;5a5c0a80-844f-012d-5d1f-001b63957646&quot; , &quot;data&quot; :{ &quot;x&quot; : &quot;0&quot; , &quot;y&quot; : &quot;90&quot; }} ); //The server will update it's map of players to bombs and issue an update every 5msec {type: &quot;update_bombs&quot; , positions:{ &quot;7fd93b20-8465-012d-5d20-001b63957646&quot; :{ x: &quot;0&quot; y: &quot;0&quot; } }} //The socket receives all messages through this: socket . onmessage = function ( evt ){ var data = JSON. parse (evt. data ) handleEvent ( data[ 'type' ], data ); };
  15. 16. updateBombPositions : function ( positions ){ $ .each(positions, function (bombId, bomb){ if ( isNewBomb(bombId) ){ MrJaba.Bomberman.bombs[bombId] = new Bomb (bombId, bomb) } }) }, //Event Handling Code calls this
  16. 17. “ Kill! Kill! Kill! Filthy bastards, Commies!” “ Norman! Tea's Ready!” “ Coming Dear!”
  17. 18. //tick tick...boom MrJaba.Bomberman.detonate( this , this .getTileX(), this .getTileY()); detonate : function ( bomb, tileX, tileY ){ delete MrJaba.Bomberman.bombs[bomb.getId()]; MrJaba.Bomberman.GameClient.trigger( 'send_bomb_detonate' , bomb.getId()); bomb.toExplosion(); },
  18. 19. Apparently Explosions Are...Unpleasant sendHotBurningDeath : function (){ var alreadyKilled = this .killed; this .tilesAround( this .getTileX(), this .getTileY(), function (tileX, tileY, direction, radius){ MrJaba.Bomberman.killPlayersAt( tileX, tileY, alreadyKilled ); }); },
  19. 20. Cramp! Asynchronous EventMachine based web framework
  20. 21. Asynchronous Event Driven Code Event Loop Request Handler Request Handler
  21. 22. Cramp::Controller::Action
  22. 23. class RootController < Cramp::Controller::Action on_start :send_socket def send_socket render File .open( &quot;public/index.html&quot; , 'r' ){ | f | f.readlines } finish end end
  23. 24. Anatomy of a cramp request Request: Blow the bloody doors off! initialize Initialize Response Start request Finish Request
  24. 25. Cramp::Controller::Websocket
  25. 26. class GameController < Cramp::Controller::Websocket on_data :receive_message def receive_message ( data ) message = JSON .parse(data) type = message[ 'type' ] uuid = message[ 'uuid' ] if Game .player_in_game?(uuid) || type == &quot;register&quot; update_last_message_time(uuid) self .send( &quot;receive_ #{type} &quot; , message, uuid) end end end
  26. 27. Example! { &quot;type&quot; : &quot;send_bomb_drop&quot; , &quot;uuid&quot; : &quot;4bba07e0-846c-012d-5d29-001b63957646&quot; , &quot;data&quot; :{ &quot;x&quot; : &quot;0&quot; , &quot;y&quot; : &quot;0&quot; }} Client: def receive_message ( data ) message = JSON .parse(data) type = message[ 'type' ] uuid = message[ 'uuid' ] if Game .player_in_game?(uuid) || type == &quot;register&quot; update_last_message_time(uuid) self .send( &quot;receive_ #{type} &quot; , message, uuid) end end Server: def receive_send_bomb_drop ( message, uuid ) position = { :x => message[ 'data' ][ 'x' ], :y => message[ 'data' ][ 'y' ]} Game .bomb_positions[uuid] = position if ! uuid.nil? end
  27. 28. Again and Again and Again Recurring Actions are super easy in Cramp
  28. 29. periodic_timer :push_states , :every => 0.05 def push_states data = { :type => 'update_positions' , :positions => game_states_for_connection}.to_json render data end def push_bombs if Game .bomb_positions.size > 0 data = { :type => 'update_bombs' , :positions => Game .bomb_positions}.to_json render data end end periodic_timer :push_bombs , :every => 0.05
  29. 30. Alternatives?
  30. 31. Thank You's!
  31. 32. Game Over! Tom Crinson @MrJaba http://github.com/MrJaba/Websocket-Bomberman

×