IttyBittyBoom.com Cramp + Websockets = Awesome
What ? Attempt to play film here...
Why ?
How ? Drawing - canvas Network Requests - websockets Server - cramp
HTML5 Canvas Very Cool, Can do lots of cool things with it, Browser support is good (safari3.2, chrome3, firefox 3.0)
<table id= &quot;map&quot; > <tr> <td> StoneBlock </td><td> StoneBlock </td><td> StoneBlock </td><td> StoneBlock </td><td>...
 
Sprites canvas.getContext( '2d' ).drawImage( image, imgOffsetX, imgOffsetY,  frameWidth,  frameHeight, xPos, yPos,  frameW...
Websockets Full Duplex communication channel over a single socket Javascript interface Cope with firewalls + proxies
//Create one: var  socket  =   new   WebSocket ( 'ws://ittybittyboom.com/game' ); //Use it: socket . onopen   =   function...
Where does Itty  use them? Everywhere!
“ Run Away!”
//Register Keypress switch ( event .which){ case   38 : MrJaba.Bomberman.me.setMovementDirection( 'up' );  break ; case   ...
“ You can't give  a bomb to a baby!”
//Trigger the bombdrop on the game client MrJaba.Bomberman.GameClient.trigger( 'send_bomb_drop' ); //Send the Bomb drop me...
updateBombPositions :  function ( positions ){ $ .each(positions,  function (bombId, bomb){ if ( isNewBomb(bombId) ){  MrJ...
“ Kill! Kill! Kill!  Filthy bastards,  Commies!” “ Norman! Tea's Ready!” “ Coming Dear!”
//tick tick...boom MrJaba.Bomberman.detonate( this ,  this .getTileX(),  this .getTileY()); detonate : function ( bomb, ti...
Apparently Explosions Are...Unpleasant sendHotBurningDeath : function (){ var  alreadyKilled  =   this .killed; this .tile...
Cramp! Asynchronous EventMachine based web framework
Asynchronous Event Driven Code Event Loop Request Handler Request Handler
Cramp::Controller::Action
class   RootController  < Cramp::Controller::Action on_start  :send_socket def   send_socket render   File .open( &quot;pu...
Anatomy of a cramp request Request: Blow the bloody doors off! initialize Initialize Response  Start request Finish Request
Cramp::Controller::Websocket
class   GameController  < Cramp::Controller::Websocket on_data  :receive_message def   receive_message ( data ) message  =...
Example! { &quot;type&quot; : &quot;send_bomb_drop&quot; , &quot;uuid&quot; : &quot;4bba07e0-846c-012d-5d29-001b63957646&q...
Again and Again and Again Recurring Actions are super easy in Cramp
periodic_timer  :push_states ,  :every  =>  0.05 def   push_states data  =  { :type  =>  'update_positions' ,  :positions ...
Alternatives?
Thank You's!
Game Over! Tom Crinson @MrJaba http://github.com/MrJaba/Websocket-Bomberman
Upcoming SlideShare
Loading in...5
×

Itty bittypresentation lrug

842

Published on

Presentation given to the London Ruby User Group (LRUG) and the Ipswich Ruby User Group (IPRUG) on a simple project I made called IttyBittyBoom.com which is an HTML5 based bomberman clone.

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

  • Be the first to like this

No Downloads
Views
Total Views
842
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
1
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

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
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×