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.
Piotr Kowalski
"My 10 days with Phaser.js"
2015-09-16
@piecioshka
Who am I?
Kierownik Działu Aplikacji Webowych
Cyfrowy Polsat, Warsaw
JavaScript Ninja. Mac lover. Pebble evangelist.
Organ...
piecioshka.pl/blog github.com/piecioshka
twitter.com/piecioshka soundcloud.com/piecioshka
Where am I?
I made a game
dragonballplay.com
Advantages of Phaser.js
• Big community
• A lot of lines of code (a lot of JSDocs)
• Good quality of code (components)
• S...
Disadvantages of Phaser.js
• I didn't notice...
"State idea"
• The gameplay is based on state switching , e.g.
choose language, select character from menu,
fight, defeat o...
init method
• It runs as the first method
preload method
• Method which downloads the assets
• images
• sounds
• json files
create method
• Runs ones while generating the state
• In that method I create all objects that are
occurring in a game st...
update method
• Phaser.Game#raf via
requestAnimationFrame or setTimeout
• 38881: Phaser.Game#update
• The core game loop
render method
• Method runs after update process
• Inside it we can enable displaying debug
details
Day I: Here we go!
31↑
Use ECMAScript 6.
webpack and Babel.js take care of compiling
to ECMAScript 5 (for browser).
“
webpack.config.js
module.exports = {
resolve: { extensions: ['.es6.js', '.js', ''] },
entry: './app/scripts/main',
output: ...
Advantages of ECMAScript 6
• Modules - no global variables
• Importing - require only dependency
• Smooth syntax of class ...
HTML (index.html)
No more HTML files, because everything is in the Canvas.
1. Create container for game: <div id="game"></d...
Phaser.js v2.4.3
Type Files
Normal 2.8M phaser.js
726K phaser.min.js
Only need to 2,2M phaser-arcade-physics.js
754K phase...
Why not in modules?
• Throw an error: "PIXI is not defined"
• webpack will have big file to manage
• Do I really need it?
Write first lines of code
• Create a game object
// Create game object
this.game = new Phaser.Game(800, 400, Phaser.Canvas,...
Day II: Design (vol. 1)
157 LOC (126↑)
• Add states: MenuState - select character
// Add state to set
this.game.state.add(...
Day II: Design (vol. 2)
• assets - directory contains everything except code,
e.g. graphics , sound
• Display first in game...
Day II: Design (vol. 3)
• scripts/models/ directory with characters definition, e.g. Son Goku
• Add states: FightState , Se...
The first big problem
• Sharing objects between states?
Ideas?
• Global variables?
• Never!
• Create custom game properties!
Day III: We are moving!
258 LOC (101↑)
• Create map with Tiled - cool tool for create game maps
this.load.tilemap(key, pat...
Balls positions
• Definition of positions dragon balls in separate files, for why?
• backend can generate that files
• separa...
Create the first sprite - character
// Add sprite to game
this.add.sprite(x, y, key)
Add dragon balls
• Create group object...
Simple message
• Create message
// Add label
message = this.add.text(x, y, text)
• Animation: fadeIn
message.alpha = 0
thi...
Navigation vol. 1
if (keyboard.isDown(Phaser.Keyboard.LEFT) {
player.x -= 5
}
Warning!
If we would like to use collision d...
Navigation vol. 2
// Update velocity of player
player.velocity.x -= 5
Remember to clear velocity before that process!
// R...
Collision - a very broad subject
• Player
// Enable arcade mode for our player
this.physics.arcade.enable(player)
• Map
ma...
Collected items - dragon balls
• Group of balls should have a body
balls = this.add.group()
balls.enableBody = true
• Grou...
Day IV: Time from clock
384 LOC (126↑)
• Create states: ShenronState , GameOverState ,
TrainingState
• Handle keyboard on ...
Day V: Music!
710 LOC (326↑)
• Create fake spritesheets for characters
• Add logo and sound
this.load.audio(key, path)
sou...
Day VI: Display bars
858 LOC (148↑)
• Display player labels (HP and EXP),
and player avatars on FightState
• Disable sound...
Day VII: Player collision
1028 LOC (170↑)
• Support mouse events on MenuState
// Support mouse over
button.events.onInputO...
Day VIII: Create Artificial
Intelligence
1270 LOC (242↑)
• Create screen which create only message
• Display game control b...
Day IX: Easter egg
1533 LOC (263↑)
• Fixed AI - choose random move from predefined list
• Create Utilities module with stat...
Day X: Last day
1732 LOC (199↑)
• Rename SearchingState to CollectingState
• Choose randomly 1 map from 3 on CollectingSta...
Future plans
• Block players moves when someone dies on VersusState
• Add countdown on TrainingState
• Display app version...
The worst part
of code
scripts/states/VersusState.es6.js
The best part
of code
scripts/main.es6.js
What I learned?
• Draw something when you are finish implementation
• Keyboard handler doesn't have to be in update method
...
My mistakes
• Duplicate code
Phaser.State#rnd.integerInRange(min, max)
instead of:
Utilities.random(min, max)
• I missed t...
Donation
patreon.com/photonstorm
(Richard Davey @photonstorm)
Thanks!
Links
• Slides: http://piecioshka.github.io/warsawjs-presentation-my-10-days-with-phaser-js
• My games:
• https://github.c...
See you next
month at
WarsawJS
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
My 10 days with Phaser.js - WarsawJS Meetup #13
Upcoming SlideShare
Loading in …5
×

My 10 days with Phaser.js - WarsawJS Meetup #13

941 views

Published on

Video: https://www.youtube.com/watch?v=klDeljOKDjU

O tym jak przez kolejne 10 dni pisałem grę z użyciem Phaser.js. Fabuła gry opiera się na anime Dragon Ball. Grafikę do gry robiłem własnoręcznie, o czym możecie się przekonać wchodząc na www.dragonballplay.com, gdzie znajduje się wersja v1.0 tego projektu. Codziennie poświęcałem 5-6 godzin po pracy, aby od 1 do 10 września stworzyć pełnoprawną grę internetową.

Published in: Software
  • Be the first to comment

My 10 days with Phaser.js - WarsawJS Meetup #13

  1. 1. Piotr Kowalski "My 10 days with Phaser.js" 2015-09-16 @piecioshka
  2. 2. Who am I? Kierownik Działu Aplikacji Webowych Cyfrowy Polsat, Warsaw JavaScript Ninja. Mac lover. Pebble evangelist. Organizer WarsawJS "Kto chce szuka sposobu, kto nie chce szuka powodu."
  3. 3. piecioshka.pl/blog github.com/piecioshka twitter.com/piecioshka soundcloud.com/piecioshka Where am I?
  4. 4. I made a game
  5. 5. dragonballplay.com
  6. 6. Advantages of Phaser.js • Big community • A lot of lines of code (a lot of JSDocs) • Good quality of code (components) • Separation of layers in API, e.g. states and keyboards • Cool phaser.io/docs
  7. 7. Disadvantages of Phaser.js • I didn't notice...
  8. 8. "State idea" • The gameplay is based on state switching , e.g. choose language, select character from menu, fight, defeat or win • State definition - class with 4 methods: preload , create , update , render and optionally init • Only one state is active !
  9. 9. init method • It runs as the first method
  10. 10. preload method • Method which downloads the assets • images • sounds • json files
  11. 11. create method • Runs ones while generating the state • In that method I create all objects that are occurring in a game state
  12. 12. update method • Phaser.Game#raf via requestAnimationFrame or setTimeout • 38881: Phaser.Game#update • The core game loop
  13. 13. render method • Method runs after update process • Inside it we can enable displaying debug details
  14. 14. Day I: Here we go! 31↑ Use ECMAScript 6. webpack and Babel.js take care of compiling to ECMAScript 5 (for browser). “
  15. 15. webpack.config.js module.exports = { resolve: { extensions: ['.es6.js', '.js', ''] }, entry: './app/scripts/main', output: { filename: 'bundle.js', path: './app/dist' }, module: { loaders: [{ test: /.es6.js/, exclude: /node_modules/, loader: 'babel?stage=0' }] } } 01. 02. 03. 04. 05. 06. 07. 08. 09. 10. 11. 12. 13.
  16. 16. Advantages of ECMAScript 6 • Modules - no global variables • Importing - require only dependency • Smooth syntax of class definition with cool inheritance • Default parameters and Arrow function // Destructuring assignment let [x, y] = ['abc', 100] // x = 'abc', y = 100 01. 02. 03.
  17. 17. HTML (index.html) No more HTML files, because everything is in the Canvas. 1. Create container for game: <div id="game"></div> 2. Add library file: scripts/vendor/phaser.js 3. Add our game file: dist/bundle.js
  18. 18. Phaser.js v2.4.3 Type Files Normal 2.8M phaser.js 726K phaser.min.js Only need to 2,2M phaser-arcade-physics.js 754K phaser-arcade-physics.map 567K phaser-arcade-physics.min.js
  19. 19. Why not in modules? • Throw an error: "PIXI is not defined" • webpack will have big file to manage • Do I really need it?
  20. 20. Write first lines of code • Create a game object // Create game object this.game = new Phaser.Game(800, 400, Phaser.Canvas, 'game`) • One for all game • Available from the each of game state 01. 02.
  21. 21. Day II: Design (vol. 1) 157 LOC (126↑) • Add states: MenuState - select character // Add state to set this.game.state.add(name, handler) // Activate passed state this.game.state.start(name) 01. 02. 03. 04.
  22. 22. Day II: Design (vol. 2) • assets - directory contains everything except code, e.g. graphics , sound • Display first in game background - simple image with game dimension and position in point 0,0 // Load image file and put it to cache this.load.image(key, path) // Fetch from cache image and put to Canvas this.add.image(x, y, key) 01. 02. 03. 04.
  23. 23. Day II: Design (vol. 3) • scripts/models/ directory with characters definition, e.g. Son Goku • Add states: FightState , SearchingState (screen with collected balls) • scripts/configuration.js - file in isolated game configuration • Create instance of player class • Add some buttons // Add button to Canvas this.add.button(x, y, key, handler) 01. 02.
  24. 24. The first big problem • Sharing objects between states? Ideas? • Global variables? • Never! • Create custom game properties!
  25. 25. Day III: We are moving! 258 LOC (101↑) • Create map with Tiled - cool tool for create game maps this.load.tilemap(key, path, data, format) // data: if `path` was passed, equals null // format: Phaser.Tilemap.TILED_JSON • Add tileset to map (our spritesheet) this.load.spritesheet(key, path, width, height) // width: tile width // height: tile height • Create layer on map and extend it to the whole game area 01. 02. 03. 01. 02. 03.
  26. 26. Balls positions • Definition of positions dragon balls in separate files, for why? • backend can generate that files • separate configuration from business logic • Loading JSON file // Fetch file and put response into cache this.load.json(key, path) // Return parsed object object = this.cache.getJSON(key) 01. 02. 03. 04.
  27. 27. Create the first sprite - character // Add sprite to game this.add.sprite(x, y, key) Add dragon balls • Create group object for them, for better collision management 01. 02.
  28. 28. Simple message • Create message // Add label message = this.add.text(x, y, text) • Animation: fadeIn message.alpha = 0 this.add.tween(message).to(config, time, type, true) // config: { alpha: 1 } // time: Phaser.Timer.SECOND // type: Phaser.Easing.Linear.None 01. 02. 01. 02. 03. 04. 05.
  29. 29. Navigation vol. 1 if (keyboard.isDown(Phaser.Keyboard.LEFT) { player.x -= 5 } Warning! If we would like to use collision detection, we should update player.velocity.x not only player.x . 01. 02. 03.
  30. 30. Navigation vol. 2 // Update velocity of player player.velocity.x -= 5 Remember to clear velocity before that process! // Reset velocity player.velocity.x = 0 01. 02. “01. 02.
  31. 31. Collision - a very broad subject • Player // Enable arcade mode for our player this.physics.arcade.enable(player) • Map map.setCollisionByIndex(1) // Start counting from 1 layer = map.createLayer(name) this.physics.arcade.collide(player, layer) Player will be collide with tile with index = 0 from now! 01. 02. 01. 02. 03.
  32. 32. Collected items - dragon balls • Group of balls should have a body balls = this.add.group() balls.enableBody = true • Group should have defined a physics // Add body to group of balls this.physics.arcade.enable(balls) // Start collide between player and group of balls this.physics.arcade.collide(player, balls, handler) 01. 02. 01. 02. 03. 04.
  33. 33. Day IV: Time from clock 384 LOC (126↑) • Create states: ShenronState , GameOverState , TrainingState • Handle keyboard on MenuState • Create countdown - measure time to GameOver // Clock with reference to state this.time.events.add(time, handler, context) 01. 02.
  34. 34. Day V: Music! 710 LOC (326↑) • Create fake spritesheets for characters • Add logo and sound this.load.audio(key, path) sound = this.add.audio(key) sound.play() • Create enemies on FightState • Resize hitbox during fight • Create state MealState - regeneration state, HP will be reset 01. 02. 03.
  35. 35. Day VI: Display bars 858 LOC (148↑) • Display player labels (HP and EXP), and player avatars on FightState • Disable sound globally (saved state in localStorage ) • Add everywhere we can DragonBallPlay logo
  36. 36. Day VII: Player collision 1028 LOC (170↑) • Support mouse events on MenuState // Support mouse over button.events.onInputOver.add(handler, context) • Check players collision isOverlap() => { return this.physics.arcade.overlap(player, enemy) } • Decrease HP of enemy when player hits him 01. 02. 01. 02. 03.
  37. 37. Day VIII: Create Artificial Intelligence 1270 LOC (242↑) • Create screen which create only message • Display game control before main part of game • Rename FightState to VersusState - better name • FightState is base class with children VersusState and TrainingState • First idea for AI - create list of enemy moves
  38. 38. Day IX: Easter egg 1533 LOC (263↑) • Fixed AI - choose random move from predefined list • Create Utilities module with static methods • Create state: LanguageState • Detach all text to isolated JSON files • Create DefinitionTyped.js • Revert default player parameters on GameOverState • Create Easter Egg : new character available on MenuState
  39. 39. Day X: Last day 1732 LOC (199↑) • Rename SearchingState to CollectingState • Choose randomly 1 map from 3 on CollectingState • Add collision with 2 tiles: 1 and 3 // Upgrade collision map.setCollision([1, 3]) • Converting all images to PNG - why is it a bad idea for backgrounds? • Create states: PlayerPresentationState , EnemyPresentationState , WinnerState 01. 02.
  40. 40. Future plans • Block players moves when someone dies on VersusState • Add countdown on TrainingState • Display app version somewhere with small font size • Extend display time for MessageState • Fixed players collision, that they can't enter on themselves • Support shortcuts • Fixed Konami code • Support Gamepad API • Support Notification API • Draw characters and create simple favicon
  41. 41. The worst part of code
  42. 42. scripts/states/VersusState.es6.js
  43. 43. The best part of code
  44. 44. scripts/main.es6.js
  45. 45. What I learned? • Draw something when you are finish implementation • Keyboard handler doesn't have to be in update method • Each of state has his own clock , which is destroyed when state is destroyed
  46. 46. My mistakes • Duplicate code Phaser.State#rnd.integerInRange(min, max) instead of: Utilities.random(min, max) • I missed the manager to keep the storyline, so I decided to... buy a couple of books about Phaser.js
  47. 47. Donation patreon.com/photonstorm (Richard Davey @photonstorm)
  48. 48. Thanks!
  49. 49. Links • Slides: http://piecioshka.github.io/warsawjs-presentation-my-10-days-with-phaser-js • My games: • https://github.com/piecioshka/www.dragonballplay.com [COMPLETE] • https://github.com/javascript-ninjas/game-fastest-joby [COMPLETE] • https://github.com/piecioshka/ss15-dumplings [COMPLETE] • https://github.com/piecioshka/game-electrode [WIP] • https://github.com/piecioshka/game-snooker [WIP] • ECMAScript 7: https://babeljs.io/docs/usage/experimental • Special editor: http://phasereditor.boniatillo.com • Font: http://www.dafont.com/saiyan-sans.font
  50. 50. See you next month at WarsawJS

×