├── .gitignore ├── .jshintrc ├── LICENSE ├── README.md ├── index.js ├── package.json └── src ├── assets ├── assets │ └── platformer │ │ ├── animated_coin.gif │ │ ├── bitmap_font_sheet.png │ │ ├── blurry_hero.png │ │ ├── coin_scoreboard.png │ │ ├── coin_spritesheet.png │ │ ├── door_spawned.png │ │ ├── enemy_bounce.gif │ │ ├── enemy_dying.gif │ │ ├── game_loop.png │ │ ├── game_state.png │ │ ├── grass_1x1.png │ │ ├── grass_4x1.png │ │ ├── ground_falling.gif │ │ ├── hero_animation_glitch.gif │ │ ├── hero_animations.gif │ │ ├── hero_bad_position.png │ │ ├── hero_fall_bottom.png │ │ ├── hero_jump.gif │ │ ├── hero_spritesheet.png │ │ ├── hud_icon_only.png │ │ ├── invisible_walls.png │ │ ├── key_icon_empty.png │ │ ├── key_icon_filled.png │ │ ├── key_icon_spritesheet.png │ │ ├── key_spawned.png │ │ ├── key_tween.gif │ │ ├── level00_thumb.png │ │ ├── level_coin_scoreboard.png │ │ ├── platformer_screenshot.png │ │ ├── platforms_falling.gif │ │ ├── spider_disaster.gif │ │ ├── spider_spritesheet.png │ │ ├── spider_turning.gif │ │ ├── spider_vs_wall.png │ │ ├── start.zip │ │ ├── static_coins.png │ │ ├── step00_check.png │ │ ├── step01_check.png │ │ ├── step02_check.png │ │ ├── step03_check.png │ │ ├── step06_check.png │ │ ├── steps │ │ ├── step01.js │ │ ├── step02.js │ │ ├── step03.js │ │ ├── step04.js │ │ ├── step05.js │ │ ├── step06.js │ │ ├── step07.js │ │ ├── step08.js │ │ ├── step09.js │ │ ├── step10.js │ │ ├── step11.js │ │ ├── step12.js │ │ ├── step13.js │ │ ├── step14.js │ │ └── step15.js │ │ ├── walking_spider.gif │ │ └── win_condition.png ├── css │ └── styles.css ├── images │ ├── moz-favicon.svg │ └── moz-logo.svg ├── platformer │ ├── audio │ │ ├── bgm.mp3 │ │ ├── bgm.ogg │ │ ├── coin.wav │ │ ├── door.wav │ │ ├── jump.wav │ │ ├── key.wav │ │ └── stomp.wav │ ├── data │ │ ├── level00.json │ │ └── level01.json │ ├── images │ │ ├── background.png │ │ ├── coin_animated.png │ │ ├── coin_icon.png │ │ ├── decor.png │ │ ├── door.png │ │ ├── grass_1x1.png │ │ ├── grass_2x1.png │ │ ├── grass_4x1.png │ │ ├── grass_6x1.png │ │ ├── grass_8x1.png │ │ ├── ground.png │ │ ├── hero.png │ │ ├── hero_stopped.png │ │ ├── invisible_wall.png │ │ ├── key.png │ │ ├── key_icon.png │ │ ├── numbers.png │ │ └── spider.png │ ├── index.html │ └── js │ │ ├── main.js │ │ ├── phaser.map │ │ └── phaser.min.js └── vendor │ └── prism │ ├── prism.css │ └── prism.js ├── content ├── bonus │ └── resources_en.md ├── coach-guide │ └── index_en.md ├── index_en.md ├── platformer │ ├── index_en.md │ ├── step01_en.md │ ├── step02_en.md │ ├── step03_en.md │ ├── step04_en.md │ ├── step05_en.md │ ├── step06_en.md │ ├── step07_en.md │ ├── step08_en.md │ ├── step09_en.md │ ├── step10_en.md │ ├── step11_en.md │ ├── step12_en.md │ ├── step13_en.md │ ├── step14_en.md │ ├── step15_en.md │ └── step16_en.md └── setup │ ├── index_en.md │ └── step00_en.md └── layouts ├── default.pug ├── guide_index.pug └── guide_step.pug /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | 39 | # Project ignore 40 | .DS_Store 41 | publish.sh 42 | dist 43 | game-wip 44 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "esnext": true, 3 | "browser": true, 4 | "node": true 5 | } 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HTML5 games workshop 2 | 3 | A workshop that teaches how to develop HTML5 games with JavaScript and [Phaser](http://phaser.io). 4 | 5 | It is meant to last a full day, although it includes sufficient guiding for people to finish it at home if only a short session with a coach is possible. 6 | 7 | [**Access the workshop online here**](https://mozdevs.github.io/html5-games-workshop/). 8 | 9 |  10 | 11 | ## Sessions 12 | 13 | Upcoming sessions of this workshop: 14 | 15 | - Barcelona (Spain), 4 March 2017 at [AdaJS](http://ada.barcelonajs.org/). 16 | 17 | Would you like to host the workshop in your city? [Contact Belén](https://belenalbeza.com/speaking/#howtogetmeatyourevent). 18 | 19 | ## Development 20 | 21 | If you want to tinker around or have your own version… 22 | 23 | This project uses [Metalsmith](http://www.metalsmith.io/) to generate a static website out of Markdown files (among others). 24 | 25 | ### Build the project 26 | 27 | ```sh 28 | npm install 29 | node index.js 30 | ``` 31 | 32 | It will generate a `dist` folder with the website for the workshop generated. It's all static files. 33 | 34 | ### Watch 35 | 36 | There is a **watch** mode that will recompile the project whenever a markdown file has been changed: 37 | 38 | ```sh 39 | npm run watch 40 | ``` 41 | 42 | ### Publish to Github Pages 43 | 44 | ``` 45 | npm run deploy 46 | ``` 47 | 48 | This assumes that your repository is named `html5-games-workshop`. If not, you will need to update `package.json` and change: 49 | 50 | ```json 51 | "build:ghpages": "node index.js --base \"/html5-games-workshop\"", 52 | ``` 53 | 54 | …to use your repository name as `--base` parameter. 55 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | 5 | const metalsmith = require('metalsmith'); 6 | const markdown = require('metalsmith-markdown'); 7 | const assets = require('metalsmith-assets'); 8 | const layouts = require('metalsmith-layouts'); 9 | const multiLanguage = require('metalsmith-multi-language'); 10 | const permalinks = require('metalsmith-permalinks'); 11 | const collections = require('metalsmith-collections'); 12 | const rewrite = require('metalsmith-rewrite'); 13 | const slug = require('metalsmith-slug'); 14 | const relative = require('metalsmith-relative'); 15 | const prefixoid = require('metalsmith-prefixoid'); 16 | 17 | const argv = require('minimist')(process.argv.slice(2)); 18 | 19 | const DEFAULT_LOCALE = 'en'; 20 | const LOCALES = ['en', 'es']; 21 | 22 | metalsmith(__dirname) 23 | .source('src/content') 24 | .use(collections({ 25 | 'platformer_en': { 26 | pattern: 'platformer/*_en.md', 27 | sortBy: 'path' 28 | }, 29 | 'platformer_es': { 30 | pattern: 'platformer/*_es.md', 31 | sortBy: 'path' 32 | }, 33 | 'setup_en': { 34 | pattern: 'setup/*_en.md', 35 | sortBy: 'path' 36 | }, 37 | 'bonus': { 38 | pattern: 'bonus/*.md' 39 | }, 40 | 'coach_en' :{ 41 | pattern: 'coach-guide/*.md' 42 | } 43 | })) 44 | .use(multiLanguage({ 45 | locales: LOCALES, 46 | default: DEFAULT_LOCALE 47 | })) 48 | .use(slug()) 49 | .use(markdown()) 50 | .use(permalinks({ 51 | relative: false, 52 | pattern: ':locale/:slug/', 53 | linksets: [{ 54 | match: { collection: 'platformer_en' }, 55 | pattern: ':locale/guides/platformer/:slug' 56 | }, { 57 | match: { collection: 'platformer_es' }, 58 | pattern: ':locale/guias/plataformas/:slug' 59 | }, { 60 | match: { collection: 'setup_en' }, 61 | pattern: ':locale/guides/setup/:slug' 62 | }, { 63 | match: { collection: 'bonus' }, 64 | pattern: ':locale/bonus/:slug' 65 | }, { 66 | match: { collection: 'coach_en'}, 67 | pattern: ':locale/guides/coach' 68 | }] 69 | })) 70 | .use(relative()) 71 | .use(layouts({ 72 | engine: 'pug', 73 | default: 'default.pug', 74 | pattern: '**/*.html', 75 | directory: 'src/layouts', 76 | cache: false, 77 | pretty: true 78 | })) 79 | .use(assets({source: 'src/assets'})) 80 | .use(prefixoid({ 81 | prefix: argv.base || '', 82 | tag: 'a', 83 | attr: 'href' 84 | })) 85 | .use(prefixoid({ 86 | prefix: argv.base || '', 87 | tag: 'img', 88 | attr: 'src' 89 | })) 90 | .destination('dist') 91 | .build(function (err) { 92 | if (err) { console.error(err); } 93 | }); 94 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "html5-games-workshop", 3 | "version": "1.0.0", 4 | "description": "html5 game development workshop", 5 | "main": "index.js", 6 | "watch": { 7 | "build": { 8 | "patterns": [ 9 | "src" 10 | ], 11 | "extensions": "md,css,pug", 12 | "quiet": true 13 | } 14 | }, 15 | "scripts": { 16 | "test": "echo \"Error: no test specified\" && exit 1", 17 | "build": "node index.js", 18 | "build:ghpages": "node index.js --base \"/html5-games-workshop\"", 19 | "watch": "npm-watch", 20 | "ghpages": "gh-pages -d dist", 21 | "deploy": "npm run build:ghpages && npm run ghpages" 22 | }, 23 | "repository": { 24 | "type": "git", 25 | "url": "git+https://github.com/mozdevs/html5-games-workshop.git" 26 | }, 27 | "keywords": [ 28 | "workshop", 29 | "gamedev", 30 | "games" 31 | ], 32 | "author": "Belén \"Benko\" Albeza", 33 | "license": "CC-BY-SA-4.0", 34 | "bugs": { 35 | "url": "https://github.com/mozdevs/html5-games-workshop/issues" 36 | }, 37 | "homepage": "https://github.com/mozdevs/html5-games-workshop#readme", 38 | "dependencies": { 39 | "gh-pages": "^0.12.0", 40 | "ghpages": "0.0.8", 41 | "metalsmith": "^2.3.0", 42 | "metalsmith-assets": "^0.1.0", 43 | "metalsmith-collections": "^0.9.0", 44 | "metalsmith-layouts": "^1.7.0", 45 | "metalsmith-markdown": "^0.2.1", 46 | "metalsmith-multi-language": "^0.2.0", 47 | "metalsmith-permalinks": "^0.5.0", 48 | "metalsmith-prefixoid": "^1.0.3", 49 | "metalsmith-relative": "^1.0.3", 50 | "metalsmith-rewrite": "^0.1.2", 51 | "metalsmith-slug": "^0.2.0", 52 | "minimist": "^1.2.0", 53 | "pug": "^2.0.0-beta9" 54 | }, 55 | "devDependencies": { 56 | "gh-pages": "^0.12.0", 57 | "npm-watch": "^0.1.8" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/assets/assets/platformer/animated_coin.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/animated_coin.gif -------------------------------------------------------------------------------- /src/assets/assets/platformer/bitmap_font_sheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/bitmap_font_sheet.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/blurry_hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/blurry_hero.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/coin_scoreboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/coin_scoreboard.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/coin_spritesheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/coin_spritesheet.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/door_spawned.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/door_spawned.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/enemy_bounce.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/enemy_bounce.gif -------------------------------------------------------------------------------- /src/assets/assets/platformer/enemy_dying.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/enemy_dying.gif -------------------------------------------------------------------------------- /src/assets/assets/platformer/game_loop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/game_loop.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/game_state.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/game_state.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/grass_1x1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/grass_1x1.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/grass_4x1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/grass_4x1.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/ground_falling.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/ground_falling.gif -------------------------------------------------------------------------------- /src/assets/assets/platformer/hero_animation_glitch.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/hero_animation_glitch.gif -------------------------------------------------------------------------------- /src/assets/assets/platformer/hero_animations.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/hero_animations.gif -------------------------------------------------------------------------------- /src/assets/assets/platformer/hero_bad_position.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/hero_bad_position.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/hero_fall_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/hero_fall_bottom.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/hero_jump.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/hero_jump.gif -------------------------------------------------------------------------------- /src/assets/assets/platformer/hero_spritesheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/hero_spritesheet.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/hud_icon_only.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/hud_icon_only.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/invisible_walls.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/invisible_walls.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/key_icon_empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/key_icon_empty.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/key_icon_filled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/key_icon_filled.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/key_icon_spritesheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/key_icon_spritesheet.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/key_spawned.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/key_spawned.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/key_tween.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/key_tween.gif -------------------------------------------------------------------------------- /src/assets/assets/platformer/level00_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/level00_thumb.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/level_coin_scoreboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/level_coin_scoreboard.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/platformer_screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/platformer_screenshot.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/platforms_falling.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/platforms_falling.gif -------------------------------------------------------------------------------- /src/assets/assets/platformer/spider_disaster.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/spider_disaster.gif -------------------------------------------------------------------------------- /src/assets/assets/platformer/spider_spritesheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/spider_spritesheet.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/spider_turning.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/spider_turning.gif -------------------------------------------------------------------------------- /src/assets/assets/platformer/spider_vs_wall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/spider_vs_wall.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/start.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/start.zip -------------------------------------------------------------------------------- /src/assets/assets/platformer/static_coins.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/static_coins.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/step00_check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/step00_check.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/step01_check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/step01_check.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/step02_check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/step02_check.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/step03_check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/step03_check.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/step06_check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/step06_check.png -------------------------------------------------------------------------------- /src/assets/assets/platformer/steps/step01.js: -------------------------------------------------------------------------------- 1 | // ============================================================================= 2 | // entry point 3 | // ============================================================================= 4 | 5 | window.onload = function () { 6 | let game = new Phaser.Game(960, 600, Phaser.AUTO, 'game'); 7 | }; 8 | -------------------------------------------------------------------------------- /src/assets/assets/platformer/steps/step02.js: -------------------------------------------------------------------------------- 1 | // ============================================================================= 2 | // game states 3 | // ============================================================================= 4 | 5 | PlayState = {}; 6 | 7 | // load game assets here 8 | PlayState.preload = function () { 9 | this.game.load.image('background', 'images/background.png'); 10 | }; 11 | 12 | // create game entities and set up world here 13 | PlayState.create = function () { 14 | this.game.add.image(0, 0, 'background'); 15 | }; 16 | 17 | // ============================================================================= 18 | // entry point 19 | // ============================================================================= 20 | 21 | window.onload = function () { 22 | let game = new Phaser.Game(960, 600, Phaser.AUTO, 'game'); 23 | game.state.add('play', PlayState); 24 | game.state.start('play'); 25 | }; 26 | -------------------------------------------------------------------------------- /src/assets/assets/platformer/steps/step03.js: -------------------------------------------------------------------------------- 1 | // ============================================================================= 2 | // game states 3 | // ============================================================================= 4 | 5 | PlayState = {}; 6 | 7 | PlayState.preload = function () { 8 | this.game.load.json('level:1', 'data/level01.json'); 9 | 10 | this.game.load.image('background', 'images/background.png'); 11 | this.game.load.image('ground', 'images/ground.png'); 12 | this.game.load.image('grass:8x1', 'images/grass_8x1.png'); 13 | this.game.load.image('grass:6x1', 'images/grass_6x1.png'); 14 | this.game.load.image('grass:4x1', 'images/grass_4x1.png'); 15 | this.game.load.image('grass:2x1', 'images/grass_2x1.png'); 16 | this.game.load.image('grass:1x1', 'images/grass_1x1.png'); 17 | }; 18 | 19 | PlayState.create = function () { 20 | this.game.add.image(0, 0, 'background'); 21 | this._loadLevel(this.game.cache.getJSON('level:1')); 22 | }; 23 | 24 | PlayState._loadLevel = function (data) { 25 | // spawn all platforms 26 | data.platforms.forEach(this._spawnPlatform, this); 27 | }; 28 | 29 | PlayState._spawnPlatform = function (platform) { 30 | this.game.add.sprite(platform.x, platform.y, platform.image); 31 | }; 32 | 33 | // ============================================================================= 34 | // entry point 35 | // ============================================================================= 36 | 37 | window.onload = function () { 38 | let game = new Phaser.Game(960, 600, Phaser.AUTO, 'game'); 39 | game.state.add('play', PlayState); 40 | game.state.start('play'); 41 | }; 42 | -------------------------------------------------------------------------------- /src/assets/assets/platformer/steps/step04.js: -------------------------------------------------------------------------------- 1 | // ============================================================================= 2 | // sprites 3 | // ============================================================================= 4 | 5 | // 6 | // hero sprite 7 | // 8 | function Hero(game, x, y) { 9 | // call Phaser.Sprite constructor 10 | Phaser.Sprite.call(this, game, x, y, 'hero'); 11 | 12 | this.anchor.set(0.5, 0.5); 13 | } 14 | 15 | // inherit from Phaser.Sprite 16 | Hero.prototype = Object.create(Phaser.Sprite.prototype); 17 | Hero.prototype.constructor = Hero; 18 | 19 | // ============================================================================= 20 | // game states 21 | // ============================================================================= 22 | 23 | PlayState = {}; 24 | 25 | PlayState.preload = function () { 26 | this.game.load.json('level:1', 'data/level01.json'); 27 | 28 | this.game.load.image('background', 'images/background.png'); 29 | this.game.load.image('ground', 'images/ground.png'); 30 | this.game.load.image('grass:8x1', 'images/grass_8x1.png'); 31 | this.game.load.image('grass:6x1', 'images/grass_6x1.png'); 32 | this.game.load.image('grass:4x1', 'images/grass_4x1.png'); 33 | this.game.load.image('grass:2x1', 'images/grass_2x1.png'); 34 | this.game.load.image('grass:1x1', 'images/grass_1x1.png'); 35 | this.game.load.image('hero', 'images/hero_stopped.png'); 36 | }; 37 | 38 | PlayState.create = function () { 39 | this.game.add.image(0, 0, 'background'); 40 | this._loadLevel(this.game.cache.getJSON('level:1')); 41 | }; 42 | 43 | PlayState._loadLevel = function (data) { 44 | // spawn all platforms 45 | data.platforms.forEach(this._spawnPlatform, this); 46 | // spawn hero and enemies 47 | this._spawnCharacters({hero: data.hero, spiders: data.spiders}); 48 | }; 49 | 50 | PlayState._spawnPlatform = function (platform) { 51 | this.game.add.sprite(platform.x, platform.y, platform.image); 52 | }; 53 | 54 | PlayState._spawnCharacters = function (data) { 55 | // spawn hero 56 | this.hero = new Hero(this.game, data.hero.x, data.hero.y); 57 | this.game.add.existing(this.hero); 58 | }; 59 | 60 | // ============================================================================= 61 | // entry point 62 | // ============================================================================= 63 | 64 | window.onload = function () { 65 | let game = new Phaser.Game(960, 600, Phaser.AUTO, 'game'); 66 | game.state.add('play', PlayState); 67 | game.state.start('play'); 68 | }; 69 | -------------------------------------------------------------------------------- /src/assets/assets/platformer/steps/step05.js: -------------------------------------------------------------------------------- 1 | // ============================================================================= 2 | // sprites 3 | // ============================================================================= 4 | 5 | // 6 | // hero sprite 7 | // 8 | function Hero(game, x, y) { 9 | Phaser.Sprite.call(this, game, x, y, 'hero'); 10 | 11 | this.anchor.set(0.5, 0.5); 12 | } 13 | 14 | // inherit from Phaser.Sprite 15 | Hero.prototype = Object.create(Phaser.Sprite.prototype); 16 | Hero.prototype.constructor = Hero; 17 | 18 | Hero.prototype.move = function (direction) { 19 | this.x += direction * 2.5; // 2.5 pixels each frame 20 | }; 21 | 22 | // ============================================================================= 23 | // game states 24 | // ============================================================================= 25 | 26 | PlayState = {}; 27 | 28 | PlayState.init = function () { 29 | this.game.renderer.renderSession.roundPixels = true; 30 | 31 | this.keys = this.game.input.keyboard.addKeys({ 32 | left: Phaser.KeyCode.LEFT, 33 | right: Phaser.KeyCode.RIGHT 34 | }); 35 | }; 36 | 37 | PlayState.preload = function () { 38 | this.game.load.json('level:1', 'data/level01.json'); 39 | 40 | this.game.load.image('background', 'images/background.png'); 41 | this.game.load.image('ground', 'images/ground.png'); 42 | this.game.load.image('grass:8x1', 'images/grass_8x1.png'); 43 | this.game.load.image('grass:6x1', 'images/grass_6x1.png'); 44 | this.game.load.image('grass:4x1', 'images/grass_4x1.png'); 45 | this.game.load.image('grass:2x1', 'images/grass_2x1.png'); 46 | this.game.load.image('grass:1x1', 'images/grass_1x1.png'); 47 | this.game.load.image('hero', 'images/hero_stopped.png'); 48 | }; 49 | 50 | PlayState.create = function () { 51 | this.game.add.image(0, 0, 'background'); 52 | this._loadLevel(this.game.cache.getJSON('level:1')); 53 | }; 54 | 55 | PlayState.update = function () { 56 | this._handleInput(); 57 | }; 58 | 59 | PlayState._handleInput = function () { 60 | if (this.keys.left.isDown) { // move hero left 61 | this.hero.move(-1); 62 | } 63 | else if (this.keys.right.isDown) { // move hero right 64 | this.hero.move(1); 65 | } 66 | }; 67 | 68 | PlayState._loadLevel = function (data) { 69 | // spawn all platforms 70 | data.platforms.forEach(this._spawnPlatform, this); 71 | // spawn hero and enemies 72 | this._spawnCharacters({hero: data.hero, spiders: data.spiders}); 73 | }; 74 | 75 | PlayState._spawnPlatform = function (platform) { 76 | this.game.add.sprite(platform.x, platform.y, platform.image); 77 | }; 78 | 79 | PlayState._spawnCharacters = function (data) { 80 | // spawn hero 81 | this.hero = new Hero(this.game, data.hero.x, data.hero.y); 82 | this.game.add.existing(this.hero); 83 | }; 84 | 85 | // ============================================================================= 86 | // entry point 87 | // ============================================================================= 88 | 89 | window.onload = function () { 90 | let game = new Phaser.Game(960, 600, Phaser.AUTO, 'game'); 91 | game.state.add('play', PlayState); 92 | game.state.start('play'); 93 | }; 94 | -------------------------------------------------------------------------------- /src/assets/assets/platformer/steps/step06.js: -------------------------------------------------------------------------------- 1 | // ============================================================================= 2 | // sprites 3 | // ============================================================================= 4 | 5 | // 6 | // hero sprite 7 | // 8 | function Hero(game, x, y) { 9 | Phaser.Sprite.call(this, game, x, y, 'hero'); 10 | this.anchor.set(0.5, 0.5); 11 | 12 | // physic properties 13 | this.game.physics.enable(this); 14 | this.body.collideWorldBounds = true; 15 | } 16 | 17 | // inherit from Phaser.Sprite 18 | Hero.prototype = Object.create(Phaser.Sprite.prototype); 19 | Hero.prototype.constructor = Hero; 20 | 21 | Hero.prototype.move = function (direction) { 22 | const SPEED = 200; 23 | this.body.velocity.x = direction * SPEED; 24 | }; 25 | 26 | // ============================================================================= 27 | // game states 28 | // ============================================================================= 29 | 30 | PlayState = {}; 31 | 32 | PlayState.init = function () { 33 | this.game.renderer.renderSession.roundPixels = true; 34 | 35 | this.keys = this.game.input.keyboard.addKeys({ 36 | left: Phaser.KeyCode.LEFT, 37 | right: Phaser.KeyCode.RIGHT 38 | }); 39 | }; 40 | 41 | PlayState.preload = function () { 42 | this.game.load.json('level:1', 'data/level01.json'); 43 | 44 | this.game.load.image('background', 'images/background.png'); 45 | this.game.load.image('ground', 'images/ground.png'); 46 | this.game.load.image('grass:8x1', 'images/grass_8x1.png'); 47 | this.game.load.image('grass:6x1', 'images/grass_6x1.png'); 48 | this.game.load.image('grass:4x1', 'images/grass_4x1.png'); 49 | this.game.load.image('grass:2x1', 'images/grass_2x1.png'); 50 | this.game.load.image('grass:1x1', 'images/grass_1x1.png'); 51 | this.game.load.image('hero', 'images/hero_stopped.png'); 52 | }; 53 | 54 | PlayState.create = function () { 55 | this.game.add.image(0, 0, 'background'); 56 | this._loadLevel(this.game.cache.getJSON('level:1')); 57 | }; 58 | 59 | PlayState.update = function () { 60 | this._handleInput(); 61 | }; 62 | 63 | PlayState._handleInput = function () { 64 | if (this.keys.left.isDown) { // move hero left 65 | this.hero.move(-1); 66 | } 67 | else if (this.keys.right.isDown) { // move hero right 68 | this.hero.move(1); 69 | } 70 | else { // stop 71 | this.hero.move(0); 72 | } 73 | }; 74 | 75 | PlayState._loadLevel = function (data) { 76 | // spawn all platforms 77 | data.platforms.forEach(this._spawnPlatform, this); 78 | // spawn hero and enemies 79 | this._spawnCharacters({hero: data.hero, spiders: data.spiders}); 80 | }; 81 | 82 | PlayState._spawnPlatform = function (platform) { 83 | this.game.add.sprite(platform.x, platform.y, platform.image); 84 | }; 85 | 86 | PlayState._spawnCharacters = function (data) { 87 | // spawn hero 88 | this.hero = new Hero(this.game, data.hero.x, data.hero.y); 89 | this.game.add.existing(this.hero); 90 | }; 91 | 92 | // ============================================================================= 93 | // entry point 94 | // ============================================================================= 95 | 96 | window.onload = function () { 97 | let game = new Phaser.Game(960, 600, Phaser.AUTO, 'game'); 98 | game.state.add('play', PlayState); 99 | game.state.start('play'); 100 | }; 101 | -------------------------------------------------------------------------------- /src/assets/assets/platformer/steps/step07.js: -------------------------------------------------------------------------------- 1 | // ============================================================================= 2 | // sprites 3 | // ============================================================================= 4 | 5 | // 6 | // hero sprite 7 | // 8 | function Hero(game, x, y) { 9 | Phaser.Sprite.call(this, game, x, y, 'hero'); 10 | this.anchor.set(0.5, 0.5); 11 | 12 | // physic properties 13 | this.game.physics.enable(this); 14 | this.body.collideWorldBounds = true; 15 | } 16 | 17 | // inherit from Phaser.Sprite 18 | Hero.prototype = Object.create(Phaser.Sprite.prototype); 19 | Hero.prototype.constructor = Hero; 20 | 21 | Hero.prototype.move = function (direction) { 22 | const SPEED = 200; 23 | this.body.velocity.x = direction * SPEED; 24 | }; 25 | 26 | // ============================================================================= 27 | // game states 28 | // ============================================================================= 29 | 30 | PlayState = {}; 31 | 32 | PlayState.init = function () { 33 | this.game.renderer.renderSession.roundPixels = true; 34 | 35 | this.keys = this.game.input.keyboard.addKeys({ 36 | left: Phaser.KeyCode.LEFT, 37 | right: Phaser.KeyCode.RIGHT 38 | }); 39 | }; 40 | 41 | PlayState.preload = function () { 42 | this.game.load.json('level:1', 'data/level01.json'); 43 | 44 | this.game.load.image('background', 'images/background.png'); 45 | this.game.load.image('ground', 'images/ground.png'); 46 | this.game.load.image('grass:8x1', 'images/grass_8x1.png'); 47 | this.game.load.image('grass:6x1', 'images/grass_6x1.png'); 48 | this.game.load.image('grass:4x1', 'images/grass_4x1.png'); 49 | this.game.load.image('grass:2x1', 'images/grass_2x1.png'); 50 | this.game.load.image('grass:1x1', 'images/grass_1x1.png'); 51 | this.game.load.image('hero', 'images/hero_stopped.png'); 52 | }; 53 | 54 | PlayState.create = function () { 55 | this.game.add.image(0, 0, 'background'); 56 | this._loadLevel(this.game.cache.getJSON('level:1')); 57 | }; 58 | 59 | PlayState.update = function () { 60 | this._handleCollisions(); 61 | this._handleInput(); 62 | }; 63 | 64 | PlayState._handleCollisions = function () { 65 | this.game.physics.arcade.collide(this.hero, this.platforms); 66 | }; 67 | 68 | PlayState._handleInput = function () { 69 | if (this.keys.left.isDown) { // move hero left 70 | this.hero.move(-1); 71 | } 72 | else if (this.keys.right.isDown) { // move hero right 73 | this.hero.move(1); 74 | } 75 | else { // stop 76 | this.hero.move(0); 77 | } 78 | }; 79 | 80 | PlayState._loadLevel = function (data) { 81 | // create all the groups/layers that we need 82 | this.platforms = this.game.add.group(); 83 | 84 | // spawn all platforms 85 | data.platforms.forEach(this._spawnPlatform, this); 86 | // spawn hero and enemies 87 | this._spawnCharacters({hero: data.hero, spiders: data.spiders}); 88 | 89 | // enable gravity 90 | const GRAVITY = 1200; 91 | this.game.physics.arcade.gravity.y = GRAVITY; 92 | }; 93 | 94 | PlayState._spawnPlatform = function (platform) { 95 | let sprite = this.platforms.create( 96 | platform.x, platform.y, platform.image); 97 | 98 | this.game.physics.enable(sprite); 99 | sprite.body.allowGravity = false; 100 | sprite.body.immovable = true; 101 | }; 102 | 103 | PlayState._spawnCharacters = function (data) { 104 | // spawn hero 105 | this.hero = new Hero(this.game, data.hero.x, data.hero.y); 106 | this.game.add.existing(this.hero); 107 | }; 108 | 109 | // ============================================================================= 110 | // entry point 111 | // ============================================================================= 112 | 113 | window.onload = function () { 114 | let game = new Phaser.Game(960, 600, Phaser.AUTO, 'game'); 115 | game.state.add('play', PlayState); 116 | game.state.start('play'); 117 | }; 118 | -------------------------------------------------------------------------------- /src/assets/assets/platformer/steps/step08.js: -------------------------------------------------------------------------------- 1 | // ============================================================================= 2 | // sprites 3 | // ============================================================================= 4 | 5 | // 6 | // hero sprite 7 | // 8 | function Hero(game, x, y) { 9 | Phaser.Sprite.call(this, game, x, y, 'hero'); 10 | this.anchor.set(0.5, 0.5); 11 | 12 | // physic properties 13 | this.game.physics.enable(this); 14 | this.body.collideWorldBounds = true; 15 | } 16 | 17 | // inherit from Phaser.Sprite 18 | Hero.prototype = Object.create(Phaser.Sprite.prototype); 19 | Hero.prototype.constructor = Hero; 20 | 21 | Hero.prototype.move = function (direction) { 22 | const SPEED = 200; 23 | this.body.velocity.x = direction * SPEED; 24 | }; 25 | 26 | Hero.prototype.jump = function () { 27 | const JUMP_SPEED = 600; 28 | let canJump = this.body.touching.down; 29 | 30 | if (canJump) { 31 | this.body.velocity.y = -JUMP_SPEED; 32 | } 33 | 34 | return canJump; 35 | }; 36 | 37 | // ============================================================================= 38 | // game states 39 | // ============================================================================= 40 | 41 | PlayState = {}; 42 | 43 | PlayState.init = function () { 44 | this.game.renderer.renderSession.roundPixels = true; 45 | 46 | this.keys = this.game.input.keyboard.addKeys({ 47 | left: Phaser.KeyCode.LEFT, 48 | right: Phaser.KeyCode.RIGHT, 49 | up: Phaser.KeyCode.UP 50 | }); 51 | 52 | this.keys.up.onDown.add(function () { 53 | let didJump = this.hero.jump(); 54 | if (didJump) { 55 | this.sfx.jump.play(); 56 | } 57 | }, this); 58 | }; 59 | 60 | PlayState.preload = function () { 61 | this.game.load.json('level:1', 'data/level01.json'); 62 | 63 | this.game.load.image('background', 'images/background.png'); 64 | this.game.load.image('ground', 'images/ground.png'); 65 | this.game.load.image('grass:8x1', 'images/grass_8x1.png'); 66 | this.game.load.image('grass:6x1', 'images/grass_6x1.png'); 67 | this.game.load.image('grass:4x1', 'images/grass_4x1.png'); 68 | this.game.load.image('grass:2x1', 'images/grass_2x1.png'); 69 | this.game.load.image('grass:1x1', 'images/grass_1x1.png'); 70 | this.game.load.image('hero', 'images/hero_stopped.png'); 71 | 72 | this.game.load.audio('sfx:jump', 'audio/jump.wav'); 73 | }; 74 | 75 | PlayState.create = function () { 76 | // create sound entities 77 | this.sfx = { 78 | jump: this.game.add.audio('sfx:jump') 79 | }; 80 | 81 | this.game.add.image(0, 0, 'background'); 82 | this._loadLevel(this.game.cache.getJSON('level:1')); 83 | }; 84 | 85 | PlayState.update = function () { 86 | this._handleCollisions(); 87 | this._handleInput(); 88 | }; 89 | 90 | PlayState._handleCollisions = function () { 91 | this.game.physics.arcade.collide(this.hero, this.platforms); 92 | }; 93 | 94 | PlayState._handleInput = function () { 95 | if (this.keys.left.isDown) { // move hero left 96 | this.hero.move(-1); 97 | } 98 | else if (this.keys.right.isDown) { // move hero right 99 | this.hero.move(1); 100 | } 101 | else { // stop 102 | this.hero.move(0); 103 | } 104 | }; 105 | 106 | PlayState._loadLevel = function (data) { 107 | // create all the groups/layers that we need 108 | this.platforms = this.game.add.group(); 109 | 110 | // spawn all platforms 111 | data.platforms.forEach(this._spawnPlatform, this); 112 | // spawn hero and enemies 113 | this._spawnCharacters({hero: data.hero, spiders: data.spiders}); 114 | 115 | // enable gravity 116 | const GRAVITY = 1200; 117 | this.game.physics.arcade.gravity.y = GRAVITY; 118 | }; 119 | 120 | PlayState._spawnPlatform = function (platform) { 121 | let sprite = this.platforms.create( 122 | platform.x, platform.y, platform.image); 123 | 124 | this.game.physics.enable(sprite); 125 | sprite.body.allowGravity = false; 126 | sprite.body.immovable = true; 127 | }; 128 | 129 | PlayState._spawnCharacters = function (data) { 130 | // spawn hero 131 | this.hero = new Hero(this.game, data.hero.x, data.hero.y); 132 | this.game.add.existing(this.hero); 133 | }; 134 | 135 | // ============================================================================= 136 | // entry point 137 | // ============================================================================= 138 | 139 | window.onload = function () { 140 | let game = new Phaser.Game(960, 600, Phaser.AUTO, 'game'); 141 | game.state.add('play', PlayState); 142 | game.state.start('play'); 143 | }; 144 | -------------------------------------------------------------------------------- /src/assets/assets/platformer/steps/step09.js: -------------------------------------------------------------------------------- 1 | // ============================================================================= 2 | // sprites 3 | // ============================================================================= 4 | 5 | // 6 | // hero sprite 7 | // 8 | function Hero(game, x, y) { 9 | Phaser.Sprite.call(this, game, x, y, 'hero'); 10 | this.anchor.set(0.5, 0.5); 11 | 12 | // physic properties 13 | this.game.physics.enable(this); 14 | this.body.collideWorldBounds = true; 15 | } 16 | 17 | // inherit from Phaser.Sprite 18 | Hero.prototype = Object.create(Phaser.Sprite.prototype); 19 | Hero.prototype.constructor = Hero; 20 | 21 | Hero.prototype.move = function (direction) { 22 | const SPEED = 200; 23 | this.body.velocity.x = direction * SPEED; 24 | }; 25 | 26 | Hero.prototype.jump = function () { 27 | const JUMP_SPEED = 600; 28 | let canJump = this.body.touching.down; 29 | 30 | if (canJump) { 31 | this.body.velocity.y = -JUMP_SPEED; 32 | } 33 | 34 | return canJump; 35 | }; 36 | 37 | // ============================================================================= 38 | // game states 39 | // ============================================================================= 40 | 41 | PlayState = {}; 42 | 43 | PlayState.init = function () { 44 | this.game.renderer.renderSession.roundPixels = true; 45 | 46 | this.keys = this.game.input.keyboard.addKeys({ 47 | left: Phaser.KeyCode.LEFT, 48 | right: Phaser.KeyCode.RIGHT, 49 | up: Phaser.KeyCode.UP 50 | }); 51 | 52 | this.keys.up.onDown.add(function () { 53 | let didJump = this.hero.jump(); 54 | if (didJump) { 55 | this.sfx.jump.play(); 56 | } 57 | }, this); 58 | }; 59 | 60 | PlayState.preload = function () { 61 | this.game.load.json('level:1', 'data/level01.json'); 62 | 63 | this.game.load.image('background', 'images/background.png'); 64 | this.game.load.image('ground', 'images/ground.png'); 65 | this.game.load.image('grass:8x1', 'images/grass_8x1.png'); 66 | this.game.load.image('grass:6x1', 'images/grass_6x1.png'); 67 | this.game.load.image('grass:4x1', 'images/grass_4x1.png'); 68 | this.game.load.image('grass:2x1', 'images/grass_2x1.png'); 69 | this.game.load.image('grass:1x1', 'images/grass_1x1.png'); 70 | this.game.load.image('hero', 'images/hero_stopped.png'); 71 | 72 | this.game.load.spritesheet('coin', 'images/coin_animated.png', 22, 22); 73 | 74 | this.game.load.audio('sfx:jump', 'audio/jump.wav'); 75 | this.game.load.audio('sfx:coin', 'audio/coin.wav'); 76 | }; 77 | 78 | PlayState.create = function () { 79 | // create sound entities 80 | this.sfx = { 81 | jump: this.game.add.audio('sfx:jump'), 82 | coin: this.game.add.audio('sfx:coin'), 83 | }; 84 | 85 | this.game.add.image(0, 0, 'background'); 86 | this._loadLevel(this.game.cache.getJSON('level:1')); 87 | }; 88 | 89 | PlayState.update = function () { 90 | this._handleCollisions(); 91 | this._handleInput(); 92 | }; 93 | 94 | PlayState._handleCollisions = function () { 95 | this.game.physics.arcade.collide(this.hero, this.platforms); 96 | 97 | this.game.physics.arcade.overlap(this.hero, this.coins, this._onHeroVsCoin, 98 | null, this); 99 | }; 100 | 101 | PlayState._handleInput = function () { 102 | if (this.keys.left.isDown) { // move hero left 103 | this.hero.move(-1); 104 | } 105 | else if (this.keys.right.isDown) { // move hero right 106 | this.hero.move(1); 107 | } 108 | else { // stop 109 | this.hero.move(0); 110 | } 111 | }; 112 | 113 | PlayState._loadLevel = function (data) { 114 | // create all the groups/layers that we need 115 | this.platforms = this.game.add.group(); 116 | this.coins = this.game.add.group(); 117 | 118 | // spawn all platforms 119 | data.platforms.forEach(this._spawnPlatform, this); 120 | // spawn hero and enemies 121 | this._spawnCharacters({hero: data.hero, spiders: data.spiders}); 122 | // spawn important objects 123 | data.coins.forEach(this._spawnCoin, this); 124 | 125 | // enable gravity 126 | const GRAVITY = 1200; 127 | this.game.physics.arcade.gravity.y = GRAVITY; 128 | }; 129 | 130 | PlayState._spawnPlatform = function (platform) { 131 | let sprite = this.platforms.create( 132 | platform.x, platform.y, platform.image); 133 | 134 | this.game.physics.enable(sprite); 135 | sprite.body.allowGravity = false; 136 | sprite.body.immovable = true; 137 | }; 138 | 139 | PlayState._spawnCharacters = function (data) { 140 | // spawn hero 141 | this.hero = new Hero(this.game, data.hero.x, data.hero.y); 142 | this.game.add.existing(this.hero); 143 | }; 144 | 145 | PlayState._spawnCoin = function (coin) { 146 | let sprite = this.coins.create(coin.x, coin.y, 'coin'); 147 | sprite.anchor.set(0.5, 0.5); 148 | 149 | this.game.physics.enable(sprite); 150 | sprite.body.allowGravity = false; 151 | 152 | sprite.animations.add('rotate', [0, 1, 2, 1], 6, true); // 6fps, looped 153 | sprite.animations.play('rotate'); 154 | }; 155 | 156 | PlayState._onHeroVsCoin = function (hero, coin) { 157 | this.sfx.coin.play(); 158 | coin.kill(); 159 | }; 160 | 161 | // ============================================================================= 162 | // entry point 163 | // ============================================================================= 164 | 165 | window.onload = function () { 166 | let game = new Phaser.Game(960, 600, Phaser.AUTO, 'game'); 167 | game.state.add('play', PlayState); 168 | game.state.start('play'); 169 | }; 170 | -------------------------------------------------------------------------------- /src/assets/assets/platformer/steps/step10.js: -------------------------------------------------------------------------------- 1 | // ============================================================================= 2 | // sprites 3 | // ============================================================================= 4 | 5 | // 6 | // hero sprite 7 | // 8 | function Hero(game, x, y) { 9 | Phaser.Sprite.call(this, game, x, y, 'hero'); 10 | this.anchor.set(0.5, 0.5); 11 | 12 | // physic properties 13 | this.game.physics.enable(this); 14 | this.body.collideWorldBounds = true; 15 | } 16 | 17 | // inherit from Phaser.Sprite 18 | Hero.prototype = Object.create(Phaser.Sprite.prototype); 19 | Hero.prototype.constructor = Hero; 20 | 21 | Hero.prototype.move = function (direction) { 22 | const SPEED = 200; 23 | this.body.velocity.x = direction * SPEED; 24 | }; 25 | 26 | Hero.prototype.jump = function () { 27 | const JUMP_SPEED = 600; 28 | let canJump = this.body.touching.down; 29 | 30 | if (canJump) { 31 | this.body.velocity.y = -JUMP_SPEED; 32 | } 33 | 34 | return canJump; 35 | }; 36 | 37 | // 38 | // Spider (enemy) 39 | // 40 | function Spider(game, x, y) { 41 | Phaser.Sprite.call(this, game, x, y, 'spider'); 42 | 43 | // anchor 44 | this.anchor.set(0.5); 45 | // animation 46 | this.animations.add('crawl', [0, 1, 2], 8, true); // 8fps, looped 47 | this.animations.play('crawl'); 48 | 49 | // physic properties 50 | this.game.physics.enable(this); 51 | this.body.collideWorldBounds = true; 52 | this.body.velocity.x = Spider.SPEED; 53 | } 54 | 55 | Spider.SPEED = 100; 56 | 57 | // inherit from Phaser.Sprite 58 | Spider.prototype = Object.create(Phaser.Sprite.prototype); 59 | Spider.prototype.constructor = Spider; 60 | 61 | Spider.prototype.update = function () { 62 | // check against walls and reverse direction if necessary 63 | if (this.body.touching.right || this.body.blocked.right) { 64 | this.body.velocity.x = -Spider.SPEED; // turn left 65 | } 66 | else if (this.body.touching.left || this.body.blocked.left) { 67 | this.body.velocity.x = Spider.SPEED; // turn right 68 | } 69 | }; 70 | 71 | // ============================================================================= 72 | // game states 73 | // ============================================================================= 74 | 75 | PlayState = {}; 76 | 77 | PlayState.init = function () { 78 | this.game.renderer.renderSession.roundPixels = true; 79 | 80 | this.keys = this.game.input.keyboard.addKeys({ 81 | left: Phaser.KeyCode.LEFT, 82 | right: Phaser.KeyCode.RIGHT, 83 | up: Phaser.KeyCode.UP 84 | }); 85 | 86 | this.keys.up.onDown.add(function () { 87 | let didJump = this.hero.jump(); 88 | if (didJump) { 89 | this.sfx.jump.play(); 90 | } 91 | }, this); 92 | }; 93 | 94 | PlayState.preload = function () { 95 | this.game.load.json('level:1', 'data/level01.json'); 96 | 97 | this.game.load.image('background', 'images/background.png'); 98 | this.game.load.image('ground', 'images/ground.png'); 99 | this.game.load.image('grass:8x1', 'images/grass_8x1.png'); 100 | this.game.load.image('grass:6x1', 'images/grass_6x1.png'); 101 | this.game.load.image('grass:4x1', 'images/grass_4x1.png'); 102 | this.game.load.image('grass:2x1', 'images/grass_2x1.png'); 103 | this.game.load.image('grass:1x1', 'images/grass_1x1.png'); 104 | this.game.load.image('hero', 'images/hero_stopped.png'); 105 | this.game.load.image('invisible-wall', 'images/invisible_wall.png'); 106 | 107 | this.game.load.spritesheet('coin', 'images/coin_animated.png', 22, 22); 108 | this.game.load.spritesheet('spider', 'images/spider.png', 42, 32); 109 | 110 | this.game.load.audio('sfx:jump', 'audio/jump.wav'); 111 | this.game.load.audio('sfx:coin', 'audio/coin.wav'); 112 | }; 113 | 114 | PlayState.create = function () { 115 | // create sound entities 116 | this.sfx = { 117 | jump: this.game.add.audio('sfx:jump'), 118 | coin: this.game.add.audio('sfx:coin'), 119 | }; 120 | 121 | this.game.add.image(0, 0, 'background'); 122 | this._loadLevel(this.game.cache.getJSON('level:1')); 123 | }; 124 | 125 | PlayState.update = function () { 126 | this._handleCollisions(); 127 | this._handleInput(); 128 | }; 129 | 130 | PlayState._handleCollisions = function () { 131 | this.game.physics.arcade.collide(this.spiders, this.platforms); 132 | this.game.physics.arcade.collide(this.spiders, this.enemyWalls); 133 | this.game.physics.arcade.collide(this.hero, this.platforms); 134 | 135 | this.game.physics.arcade.overlap(this.hero, this.coins, this._onHeroVsCoin, 136 | null, this); 137 | }; 138 | 139 | PlayState._handleInput = function () { 140 | if (this.keys.left.isDown) { // move hero left 141 | this.hero.move(-1); 142 | } 143 | else if (this.keys.right.isDown) { // move hero right 144 | this.hero.move(1); 145 | } 146 | else { // stop 147 | this.hero.move(0); 148 | } 149 | }; 150 | 151 | PlayState._loadLevel = function (data) { 152 | // create all the groups/layers that we need 153 | this.platforms = this.game.add.group(); 154 | this.coins = this.game.add.group(); 155 | this.spiders = this.game.add.group(); 156 | this.enemyWalls = this.game.add.group(); 157 | this.enemyWalls.visible = false; 158 | 159 | // spawn all platforms 160 | data.platforms.forEach(this._spawnPlatform, this); 161 | // spawn hero and enemies 162 | this._spawnCharacters({hero: data.hero, spiders: data.spiders}); 163 | // spawn important objects 164 | data.coins.forEach(this._spawnCoin, this); 165 | 166 | // enable gravity 167 | const GRAVITY = 1200; 168 | this.game.physics.arcade.gravity.y = GRAVITY; 169 | }; 170 | 171 | PlayState._spawnPlatform = function (platform) { 172 | let sprite = this.platforms.create( 173 | platform.x, platform.y, platform.image); 174 | 175 | this.game.physics.enable(sprite); 176 | sprite.body.allowGravity = false; 177 | sprite.body.immovable = true; 178 | 179 | this._spawnEnemyWall(platform.x, platform.y, 'left'); 180 | this._spawnEnemyWall(platform.x + sprite.width, platform.y, 'right'); 181 | }; 182 | 183 | PlayState._spawnEnemyWall = function (x, y, side) { 184 | let sprite = this.enemyWalls.create(x, y, 'invisible-wall'); 185 | // anchor and y displacement 186 | sprite.anchor.set(side === 'left' ? 1 : 0, 1); 187 | // physic properties 188 | this.game.physics.enable(sprite); 189 | sprite.body.immovable = true; 190 | sprite.body.allowGravity = false; 191 | }; 192 | 193 | PlayState._spawnCharacters = function (data) { 194 | // spawn spiders 195 | data.spiders.forEach(function (spider) { 196 | let sprite = new Spider(this.game, spider.x, spider.y); 197 | this.spiders.add(sprite); 198 | }, this); 199 | 200 | // spawn hero 201 | this.hero = new Hero(this.game, data.hero.x, data.hero.y); 202 | this.game.add.existing(this.hero); 203 | }; 204 | 205 | PlayState._spawnCoin = function (coin) { 206 | let sprite = this.coins.create(coin.x, coin.y, 'coin'); 207 | sprite.anchor.set(0.5, 0.5); 208 | 209 | this.game.physics.enable(sprite); 210 | sprite.body.allowGravity = false; 211 | 212 | sprite.animations.add('rotate', [0, 1, 2, 1], 6, true); // 6fps, looped 213 | sprite.animations.play('rotate'); 214 | }; 215 | 216 | PlayState._onHeroVsCoin = function (hero, coin) { 217 | this.sfx.coin.play(); 218 | coin.kill(); 219 | }; 220 | 221 | // ============================================================================= 222 | // entry point 223 | // ============================================================================= 224 | 225 | window.onload = function () { 226 | let game = new Phaser.Game(960, 600, Phaser.AUTO, 'game'); 227 | game.state.add('play', PlayState); 228 | game.state.start('play'); 229 | }; 230 | -------------------------------------------------------------------------------- /src/assets/assets/platformer/steps/step11.js: -------------------------------------------------------------------------------- 1 | // ============================================================================= 2 | // sprites 3 | // ============================================================================= 4 | 5 | // 6 | // hero sprite 7 | // 8 | function Hero(game, x, y) { 9 | Phaser.Sprite.call(this, game, x, y, 'hero'); 10 | this.anchor.set(0.5, 0.5); 11 | 12 | // physic properties 13 | this.game.physics.enable(this); 14 | this.body.collideWorldBounds = true; 15 | } 16 | 17 | // inherit from Phaser.Sprite 18 | Hero.prototype = Object.create(Phaser.Sprite.prototype); 19 | Hero.prototype.constructor = Hero; 20 | 21 | Hero.prototype.move = function (direction) { 22 | const SPEED = 200; 23 | this.body.velocity.x = direction * SPEED; 24 | }; 25 | 26 | Hero.prototype.jump = function () { 27 | const JUMP_SPEED = 600; 28 | let canJump = this.body.touching.down; 29 | 30 | if (canJump) { 31 | this.body.velocity.y = -JUMP_SPEED; 32 | } 33 | 34 | return canJump; 35 | }; 36 | 37 | Hero.prototype.bounce = function () { 38 | const BOUNCE_SPEED = 200; 39 | this.body.velocity.y = -BOUNCE_SPEED; 40 | }; 41 | 42 | // 43 | // Spider (enemy) 44 | // 45 | function Spider(game, x, y) { 46 | Phaser.Sprite.call(this, game, x, y, 'spider'); 47 | 48 | // anchor 49 | this.anchor.set(0.5); 50 | // animation 51 | this.animations.add('crawl', [0, 1, 2], 8, true); // 8fps, looped 52 | this.animations.add('die', [0, 4, 0, 4, 0, 4, 3, 3, 3, 3, 3, 3], 12); 53 | this.animations.play('crawl'); 54 | 55 | // physic properties 56 | this.game.physics.enable(this); 57 | this.body.collideWorldBounds = true; 58 | this.body.velocity.x = Spider.SPEED; 59 | } 60 | 61 | Spider.SPEED = 100; 62 | 63 | // inherit from Phaser.Sprite 64 | Spider.prototype = Object.create(Phaser.Sprite.prototype); 65 | Spider.prototype.constructor = Spider; 66 | 67 | Spider.prototype.update = function () { 68 | // check against walls and reverse direction if necessary 69 | if (this.body.touching.right || this.body.blocked.right) { 70 | this.body.velocity.x = -Spider.SPEED; // turn left 71 | } 72 | else if (this.body.touching.left || this.body.blocked.left) { 73 | this.body.velocity.x = Spider.SPEED; // turn right 74 | } 75 | }; 76 | 77 | Spider.prototype.die = function () { 78 | this.body.enable = false; 79 | 80 | this.animations.play('die').onComplete.addOnce(function () { 81 | this.kill(); 82 | }, this); 83 | }; 84 | 85 | 86 | // ============================================================================= 87 | // game states 88 | // ============================================================================= 89 | 90 | PlayState = {}; 91 | 92 | PlayState.init = function () { 93 | this.game.renderer.renderSession.roundPixels = true; 94 | 95 | this.keys = this.game.input.keyboard.addKeys({ 96 | left: Phaser.KeyCode.LEFT, 97 | right: Phaser.KeyCode.RIGHT, 98 | up: Phaser.KeyCode.UP 99 | }); 100 | 101 | this.keys.up.onDown.add(function () { 102 | let didJump = this.hero.jump(); 103 | if (didJump) { 104 | this.sfx.jump.play(); 105 | } 106 | }, this); 107 | }; 108 | 109 | PlayState.preload = function () { 110 | this.game.load.json('level:1', 'data/level01.json'); 111 | 112 | this.game.load.image('background', 'images/background.png'); 113 | this.game.load.image('ground', 'images/ground.png'); 114 | this.game.load.image('grass:8x1', 'images/grass_8x1.png'); 115 | this.game.load.image('grass:6x1', 'images/grass_6x1.png'); 116 | this.game.load.image('grass:4x1', 'images/grass_4x1.png'); 117 | this.game.load.image('grass:2x1', 'images/grass_2x1.png'); 118 | this.game.load.image('grass:1x1', 'images/grass_1x1.png'); 119 | this.game.load.image('hero', 'images/hero_stopped.png'); 120 | this.game.load.image('invisible-wall', 'images/invisible_wall.png'); 121 | 122 | this.game.load.spritesheet('coin', 'images/coin_animated.png', 22, 22); 123 | this.game.load.spritesheet('spider', 'images/spider.png', 42, 32); 124 | 125 | this.game.load.audio('sfx:jump', 'audio/jump.wav'); 126 | this.game.load.audio('sfx:coin', 'audio/coin.wav'); 127 | this.game.load.audio('sfx:stomp', 'audio/stomp.wav'); 128 | }; 129 | 130 | PlayState.create = function () { 131 | // create sound entities 132 | this.sfx = { 133 | jump: this.game.add.audio('sfx:jump'), 134 | coin: this.game.add.audio('sfx:coin'), 135 | stomp: this.game.add.audio('sfx:stomp') 136 | }; 137 | 138 | this.game.add.image(0, 0, 'background'); 139 | this._loadLevel(this.game.cache.getJSON('level:1')); 140 | }; 141 | 142 | PlayState.update = function () { 143 | this._handleCollisions(); 144 | this._handleInput(); 145 | }; 146 | 147 | PlayState._handleCollisions = function () { 148 | this.game.physics.arcade.collide(this.spiders, this.platforms); 149 | this.game.physics.arcade.collide(this.spiders, this.enemyWalls); 150 | this.game.physics.arcade.collide(this.hero, this.platforms); 151 | 152 | this.game.physics.arcade.overlap(this.hero, this.coins, this._onHeroVsCoin, 153 | null, this); 154 | this.game.physics.arcade.overlap(this.hero, this.spiders, 155 | this._onHeroVsEnemy, null, this); 156 | }; 157 | 158 | PlayState._handleInput = function () { 159 | if (this.keys.left.isDown) { // move hero left 160 | this.hero.move(-1); 161 | } 162 | else if (this.keys.right.isDown) { // move hero right 163 | this.hero.move(1); 164 | } 165 | else { // stop 166 | this.hero.move(0); 167 | } 168 | }; 169 | 170 | PlayState._loadLevel = function (data) { 171 | // create all the groups/layers that we need 172 | this.platforms = this.game.add.group(); 173 | this.coins = this.game.add.group(); 174 | this.spiders = this.game.add.group(); 175 | this.enemyWalls = this.game.add.group(); 176 | this.enemyWalls.visible = false; 177 | 178 | // spawn all platforms 179 | data.platforms.forEach(this._spawnPlatform, this); 180 | // spawn hero and enemies 181 | this._spawnCharacters({hero: data.hero, spiders: data.spiders}); 182 | // spawn important objects 183 | data.coins.forEach(this._spawnCoin, this); 184 | 185 | // enable gravity 186 | const GRAVITY = 1200; 187 | this.game.physics.arcade.gravity.y = GRAVITY; 188 | }; 189 | 190 | PlayState._spawnPlatform = function (platform) { 191 | let sprite = this.platforms.create( 192 | platform.x, platform.y, platform.image); 193 | 194 | this.game.physics.enable(sprite); 195 | sprite.body.allowGravity = false; 196 | sprite.body.immovable = true; 197 | 198 | this._spawnEnemyWall(platform.x, platform.y, 'left'); 199 | this._spawnEnemyWall(platform.x + sprite.width, platform.y, 'right'); 200 | }; 201 | 202 | PlayState._spawnEnemyWall = function (x, y, side) { 203 | let sprite = this.enemyWalls.create(x, y, 'invisible-wall'); 204 | // anchor and y displacement 205 | sprite.anchor.set(side === 'left' ? 1 : 0, 1); 206 | // physic properties 207 | this.game.physics.enable(sprite); 208 | sprite.body.immovable = true; 209 | sprite.body.allowGravity = false; 210 | }; 211 | 212 | PlayState._spawnCharacters = function (data) { 213 | // spawn spiders 214 | data.spiders.forEach(function (spider) { 215 | let sprite = new Spider(this.game, spider.x, spider.y); 216 | this.spiders.add(sprite); 217 | }, this); 218 | 219 | // spawn hero 220 | this.hero = new Hero(this.game, data.hero.x, data.hero.y); 221 | this.game.add.existing(this.hero); 222 | }; 223 | 224 | PlayState._spawnCoin = function (coin) { 225 | let sprite = this.coins.create(coin.x, coin.y, 'coin'); 226 | sprite.anchor.set(0.5, 0.5); 227 | 228 | this.game.physics.enable(sprite); 229 | sprite.body.allowGravity = false; 230 | 231 | sprite.animations.add('rotate', [0, 1, 2, 1], 6, true); // 6fps, looped 232 | sprite.animations.play('rotate'); 233 | }; 234 | 235 | PlayState._onHeroVsCoin = function (hero, coin) { 236 | this.sfx.coin.play(); 237 | coin.kill(); 238 | }; 239 | 240 | PlayState._onHeroVsEnemy = function (hero, enemy) { 241 | if (hero.body.velocity.y > 0) { // kill enemies when hero is falling 242 | hero.bounce(); 243 | enemy.die(); 244 | this.sfx.stomp.play(); 245 | } 246 | else { // game over -> restart the game 247 | this.sfx.stomp.play(); 248 | this.game.state.restart(); 249 | } 250 | }; 251 | 252 | // ============================================================================= 253 | // entry point 254 | // ============================================================================= 255 | 256 | window.onload = function () { 257 | let game = new Phaser.Game(960, 600, Phaser.AUTO, 'game'); 258 | game.state.add('play', PlayState); 259 | game.state.start('play'); 260 | }; 261 | -------------------------------------------------------------------------------- /src/assets/assets/platformer/steps/step12.js: -------------------------------------------------------------------------------- 1 | // ============================================================================= 2 | // sprites 3 | // ============================================================================= 4 | 5 | // 6 | // hero sprite 7 | // 8 | function Hero(game, x, y) { 9 | Phaser.Sprite.call(this, game, x, y, 'hero'); 10 | this.anchor.set(0.5, 0.5); 11 | 12 | // physic properties 13 | this.game.physics.enable(this); 14 | this.body.collideWorldBounds = true; 15 | } 16 | 17 | // inherit from Phaser.Sprite 18 | Hero.prototype = Object.create(Phaser.Sprite.prototype); 19 | Hero.prototype.constructor = Hero; 20 | 21 | Hero.prototype.move = function (direction) { 22 | const SPEED = 200; 23 | this.body.velocity.x = direction * SPEED; 24 | }; 25 | 26 | Hero.prototype.jump = function () { 27 | const JUMP_SPEED = 600; 28 | let canJump = this.body.touching.down; 29 | 30 | if (canJump) { 31 | this.body.velocity.y = -JUMP_SPEED; 32 | } 33 | 34 | return canJump; 35 | }; 36 | 37 | Hero.prototype.bounce = function () { 38 | const BOUNCE_SPEED = 200; 39 | this.body.velocity.y = -BOUNCE_SPEED; 40 | }; 41 | 42 | // 43 | // Spider (enemy) 44 | // 45 | function Spider(game, x, y) { 46 | Phaser.Sprite.call(this, game, x, y, 'spider'); 47 | 48 | // anchor 49 | this.anchor.set(0.5); 50 | // animation 51 | this.animations.add('crawl', [0, 1, 2], 8, true); // 8fps, looped 52 | this.animations.add('die', [0, 4, 0, 4, 0, 4, 3, 3, 3, 3, 3, 3], 12); 53 | this.animations.play('crawl'); 54 | 55 | // physic properties 56 | this.game.physics.enable(this); 57 | this.body.collideWorldBounds = true; 58 | this.body.velocity.x = Spider.SPEED; 59 | } 60 | 61 | Spider.SPEED = 100; 62 | 63 | // inherit from Phaser.Sprite 64 | Spider.prototype = Object.create(Phaser.Sprite.prototype); 65 | Spider.prototype.constructor = Spider; 66 | 67 | Spider.prototype.update = function () { 68 | // check against walls and reverse direction if necessary 69 | if (this.body.touching.right || this.body.blocked.right) { 70 | this.body.velocity.x = -Spider.SPEED; // turn left 71 | } 72 | else if (this.body.touching.left || this.body.blocked.left) { 73 | this.body.velocity.x = Spider.SPEED; // turn right 74 | } 75 | }; 76 | 77 | Spider.prototype.die = function () { 78 | this.body.enable = false; 79 | 80 | this.animations.play('die').onComplete.addOnce(function () { 81 | this.kill(); 82 | }, this); 83 | }; 84 | 85 | 86 | // ============================================================================= 87 | // game states 88 | // ============================================================================= 89 | 90 | PlayState = {}; 91 | 92 | PlayState.init = function () { 93 | this.game.renderer.renderSession.roundPixels = true; 94 | 95 | this.keys = this.game.input.keyboard.addKeys({ 96 | left: Phaser.KeyCode.LEFT, 97 | right: Phaser.KeyCode.RIGHT, 98 | up: Phaser.KeyCode.UP 99 | }); 100 | 101 | this.keys.up.onDown.add(function () { 102 | let didJump = this.hero.jump(); 103 | if (didJump) { 104 | this.sfx.jump.play(); 105 | } 106 | }, this); 107 | 108 | this.coinPickupCount = 0; 109 | }; 110 | 111 | PlayState.preload = function () { 112 | this.game.load.json('level:1', 'data/level01.json'); 113 | 114 | this.game.load.image('font:numbers', 'images/numbers.png'); 115 | 116 | this.game.load.image('background', 'images/background.png'); 117 | this.game.load.image('ground', 'images/ground.png'); 118 | this.game.load.image('grass:8x1', 'images/grass_8x1.png'); 119 | this.game.load.image('grass:6x1', 'images/grass_6x1.png'); 120 | this.game.load.image('grass:4x1', 'images/grass_4x1.png'); 121 | this.game.load.image('grass:2x1', 'images/grass_2x1.png'); 122 | this.game.load.image('grass:1x1', 'images/grass_1x1.png'); 123 | this.game.load.image('hero', 'images/hero_stopped.png'); 124 | this.game.load.image('invisible-wall', 'images/invisible_wall.png'); 125 | this.game.load.image('icon:coin', 'images/coin_icon.png'); 126 | 127 | this.game.load.spritesheet('coin', 'images/coin_animated.png', 22, 22); 128 | this.game.load.spritesheet('spider', 'images/spider.png', 42, 32); 129 | 130 | this.game.load.audio('sfx:jump', 'audio/jump.wav'); 131 | this.game.load.audio('sfx:coin', 'audio/coin.wav'); 132 | this.game.load.audio('sfx:stomp', 'audio/stomp.wav'); 133 | }; 134 | 135 | PlayState.create = function () { 136 | // create sound entities 137 | this.sfx = { 138 | jump: this.game.add.audio('sfx:jump'), 139 | coin: this.game.add.audio('sfx:coin'), 140 | stomp: this.game.add.audio('sfx:stomp') 141 | }; 142 | 143 | // create level 144 | this.game.add.image(0, 0, 'background'); 145 | this._loadLevel(this.game.cache.getJSON('level:1')); 146 | 147 | // crete hud with scoreboards) 148 | this._createHud(); 149 | }; 150 | 151 | PlayState.update = function () { 152 | this._handleCollisions(); 153 | this._handleInput(); 154 | 155 | this.coinFont.text = `x${this.coinPickupCount}`; 156 | }; 157 | 158 | PlayState._handleCollisions = function () { 159 | this.game.physics.arcade.collide(this.spiders, this.platforms); 160 | this.game.physics.arcade.collide(this.spiders, this.enemyWalls); 161 | this.game.physics.arcade.collide(this.hero, this.platforms); 162 | 163 | this.game.physics.arcade.overlap(this.hero, this.coins, this._onHeroVsCoin, 164 | null, this); 165 | this.game.physics.arcade.overlap(this.hero, this.spiders, 166 | this._onHeroVsEnemy, null, this); 167 | }; 168 | 169 | PlayState._handleInput = function () { 170 | if (this.keys.left.isDown) { // move hero left 171 | this.hero.move(-1); 172 | } 173 | else if (this.keys.right.isDown) { // move hero right 174 | this.hero.move(1); 175 | } 176 | else { // stop 177 | this.hero.move(0); 178 | } 179 | }; 180 | 181 | PlayState._loadLevel = function (data) { 182 | // create all the groups/layers that we need 183 | this.platforms = this.game.add.group(); 184 | this.coins = this.game.add.group(); 185 | this.spiders = this.game.add.group(); 186 | this.enemyWalls = this.game.add.group(); 187 | this.enemyWalls.visible = false; 188 | 189 | // spawn all platforms 190 | data.platforms.forEach(this._spawnPlatform, this); 191 | // spawn hero and enemies 192 | this._spawnCharacters({hero: data.hero, spiders: data.spiders}); 193 | // spawn important objects 194 | data.coins.forEach(this._spawnCoin, this); 195 | 196 | // enable gravity 197 | const GRAVITY = 1200; 198 | this.game.physics.arcade.gravity.y = GRAVITY; 199 | }; 200 | 201 | PlayState._spawnPlatform = function (platform) { 202 | let sprite = this.platforms.create( 203 | platform.x, platform.y, platform.image); 204 | 205 | this.game.physics.enable(sprite); 206 | sprite.body.allowGravity = false; 207 | sprite.body.immovable = true; 208 | 209 | this._spawnEnemyWall(platform.x, platform.y, 'left'); 210 | this._spawnEnemyWall(platform.x + sprite.width, platform.y, 'right'); 211 | }; 212 | 213 | PlayState._spawnEnemyWall = function (x, y, side) { 214 | let sprite = this.enemyWalls.create(x, y, 'invisible-wall'); 215 | // anchor and y displacement 216 | sprite.anchor.set(side === 'left' ? 1 : 0, 1); 217 | // physic properties 218 | this.game.physics.enable(sprite); 219 | sprite.body.immovable = true; 220 | sprite.body.allowGravity = false; 221 | }; 222 | 223 | PlayState._spawnCharacters = function (data) { 224 | // spawn spiders 225 | data.spiders.forEach(function (spider) { 226 | let sprite = new Spider(this.game, spider.x, spider.y); 227 | this.spiders.add(sprite); 228 | }, this); 229 | 230 | // spawn hero 231 | this.hero = new Hero(this.game, data.hero.x, data.hero.y); 232 | this.game.add.existing(this.hero); 233 | }; 234 | 235 | PlayState._spawnCoin = function (coin) { 236 | let sprite = this.coins.create(coin.x, coin.y, 'coin'); 237 | sprite.anchor.set(0.5, 0.5); 238 | 239 | this.game.physics.enable(sprite); 240 | sprite.body.allowGravity = false; 241 | 242 | sprite.animations.add('rotate', [0, 1, 2, 1], 6, true); // 6fps, looped 243 | sprite.animations.play('rotate'); 244 | }; 245 | 246 | PlayState._onHeroVsCoin = function (hero, coin) { 247 | this.sfx.coin.play(); 248 | coin.kill(); 249 | this.coinPickupCount++; 250 | }; 251 | 252 | PlayState._onHeroVsEnemy = function (hero, enemy) { 253 | if (hero.body.velocity.y > 0) { // kill enemies when hero is falling 254 | hero.bounce(); 255 | enemy.die(); 256 | this.sfx.stomp.play(); 257 | } 258 | else { // game over -> restart the game 259 | this.sfx.stomp.play(); 260 | this.game.state.restart(); 261 | } 262 | }; 263 | 264 | PlayState._createHud = function () { 265 | const NUMBERS_STR = '0123456789X '; 266 | this.coinFont = this.game.add.retroFont('font:numbers', 20, 26, 267 | NUMBERS_STR); 268 | 269 | let coinIcon = this.game.make.image(0, 0, 'icon:coin'); 270 | let coinScoreImg = this.game.make.image(coinIcon.x + coinIcon.width, 271 | coinIcon.height / 2, this.coinFont); 272 | coinScoreImg.anchor.set(0, 0.5); 273 | 274 | this.hud = this.game.add.group(); 275 | this.hud.add(coinIcon); 276 | this.hud.add(coinScoreImg); 277 | this.hud.position.set(10, 10); 278 | }; 279 | 280 | // ============================================================================= 281 | // entry point 282 | // ============================================================================= 283 | 284 | window.onload = function () { 285 | let game = new Phaser.Game(960, 600, Phaser.AUTO, 'game'); 286 | game.state.add('play', PlayState); 287 | game.state.start('play'); 288 | }; 289 | -------------------------------------------------------------------------------- /src/assets/assets/platformer/steps/step13.js: -------------------------------------------------------------------------------- 1 | // ============================================================================= 2 | // sprites 3 | // ============================================================================= 4 | 5 | // 6 | // hero sprite 7 | // 8 | function Hero(game, x, y) { 9 | Phaser.Sprite.call(this, game, x, y, 'hero'); 10 | this.anchor.set(0.5, 0.5); 11 | 12 | // physic properties 13 | this.game.physics.enable(this); 14 | this.body.collideWorldBounds = true; 15 | 16 | this.animations.add('stop', [0]); 17 | this.animations.add('run', [1, 2], 8, true); // 8fps looped 18 | this.animations.add('jump', [3]); 19 | this.animations.add('fall', [4]); 20 | } 21 | 22 | // inherit from Phaser.Sprite 23 | Hero.prototype = Object.create(Phaser.Sprite.prototype); 24 | Hero.prototype.constructor = Hero; 25 | 26 | Hero.prototype.move = function (direction) { 27 | const SPEED = 200; 28 | this.body.velocity.x = direction * SPEED; 29 | 30 | // update image flipping & animations 31 | if (this.body.velocity.x < 0) { 32 | this.scale.x = -1; 33 | } 34 | else if (this.body.velocity.x > 0) { 35 | this.scale.x = 1; 36 | } 37 | }; 38 | 39 | Hero.prototype.jump = function () { 40 | const JUMP_SPEED = 600; 41 | let canJump = this.body.touching.down; 42 | 43 | if (canJump) { 44 | this.body.velocity.y = -JUMP_SPEED; 45 | } 46 | 47 | return canJump; 48 | }; 49 | 50 | Hero.prototype.bounce = function () { 51 | const BOUNCE_SPEED = 200; 52 | this.body.velocity.y = -BOUNCE_SPEED; 53 | }; 54 | 55 | Hero.prototype.update = function () { 56 | // update sprite animation, if it needs changing 57 | let animationName = this._getAnimationName(); 58 | if (this.animations.name !== animationName) { 59 | this.animations.play(animationName); 60 | } 61 | }; 62 | 63 | Hero.prototype._getAnimationName = function () { 64 | let name = 'stop'; // default animation 65 | 66 | // jumping 67 | if (this.body.velocity.y < 0) { 68 | name = 'jump'; 69 | } 70 | // falling 71 | else if (this.body.velocity.y >= 0 && !this.body.touching.down) { 72 | name = 'fall'; 73 | } 74 | else if (this.body.velocity.x !== 0 && this.body.touching.down) { 75 | name = 'run'; 76 | } 77 | 78 | return name; 79 | }; 80 | 81 | // 82 | // Spider (enemy) 83 | // 84 | function Spider(game, x, y) { 85 | Phaser.Sprite.call(this, game, x, y, 'spider'); 86 | 87 | // anchor 88 | this.anchor.set(0.5); 89 | // animation 90 | this.animations.add('crawl', [0, 1, 2], 8, true); // 8fps, looped 91 | this.animations.add('die', [0, 4, 0, 4, 0, 4, 3, 3, 3, 3, 3, 3], 12); 92 | this.animations.play('crawl'); 93 | 94 | // physic properties 95 | this.game.physics.enable(this); 96 | this.body.collideWorldBounds = true; 97 | this.body.velocity.x = Spider.SPEED; 98 | } 99 | 100 | Spider.SPEED = 100; 101 | 102 | // inherit from Phaser.Sprite 103 | Spider.prototype = Object.create(Phaser.Sprite.prototype); 104 | Spider.prototype.constructor = Spider; 105 | 106 | Spider.prototype.update = function () { 107 | // check against walls and reverse direction if necessary 108 | if (this.body.touching.right || this.body.blocked.right) { 109 | this.body.velocity.x = -Spider.SPEED; // turn left 110 | } 111 | else if (this.body.touching.left || this.body.blocked.left) { 112 | this.body.velocity.x = Spider.SPEED; // turn right 113 | } 114 | }; 115 | 116 | Spider.prototype.die = function () { 117 | this.body.enable = false; 118 | 119 | this.animations.play('die').onComplete.addOnce(function () { 120 | this.kill(); 121 | }, this); 122 | }; 123 | 124 | 125 | // ============================================================================= 126 | // game states 127 | // ============================================================================= 128 | 129 | PlayState = {}; 130 | 131 | PlayState.init = function () { 132 | this.game.renderer.renderSession.roundPixels = true; 133 | 134 | this.keys = this.game.input.keyboard.addKeys({ 135 | left: Phaser.KeyCode.LEFT, 136 | right: Phaser.KeyCode.RIGHT, 137 | up: Phaser.KeyCode.UP 138 | }); 139 | 140 | this.keys.up.onDown.add(function () { 141 | let didJump = this.hero.jump(); 142 | if (didJump) { 143 | this.sfx.jump.play(); 144 | } 145 | }, this); 146 | 147 | this.coinPickupCount = 0; 148 | }; 149 | 150 | PlayState.preload = function () { 151 | this.game.load.json('level:1', 'data/level01.json'); 152 | 153 | this.game.load.image('font:numbers', 'images/numbers.png'); 154 | 155 | this.game.load.image('background', 'images/background.png'); 156 | this.game.load.image('ground', 'images/ground.png'); 157 | this.game.load.image('grass:8x1', 'images/grass_8x1.png'); 158 | this.game.load.image('grass:6x1', 'images/grass_6x1.png'); 159 | this.game.load.image('grass:4x1', 'images/grass_4x1.png'); 160 | this.game.load.image('grass:2x1', 'images/grass_2x1.png'); 161 | this.game.load.image('grass:1x1', 'images/grass_1x1.png'); 162 | this.game.load.image('invisible-wall', 'images/invisible_wall.png'); 163 | this.game.load.image('icon:coin', 'images/coin_icon.png'); 164 | 165 | this.game.load.spritesheet('coin', 'images/coin_animated.png', 22, 22); 166 | this.game.load.spritesheet('spider', 'images/spider.png', 42, 32); 167 | this.game.load.spritesheet('hero', 'images/hero.png', 36, 42); 168 | 169 | this.game.load.audio('sfx:jump', 'audio/jump.wav'); 170 | this.game.load.audio('sfx:coin', 'audio/coin.wav'); 171 | this.game.load.audio('sfx:stomp', 'audio/stomp.wav'); 172 | }; 173 | 174 | PlayState.create = function () { 175 | // create sound entities 176 | this.sfx = { 177 | jump: this.game.add.audio('sfx:jump'), 178 | coin: this.game.add.audio('sfx:coin'), 179 | stomp: this.game.add.audio('sfx:stomp') 180 | }; 181 | 182 | // create level 183 | this.game.add.image(0, 0, 'background'); 184 | this._loadLevel(this.game.cache.getJSON('level:1')); 185 | 186 | // crete hud with scoreboards) 187 | this._createHud(); 188 | }; 189 | 190 | PlayState.update = function () { 191 | this._handleCollisions(); 192 | this._handleInput(); 193 | 194 | this.coinFont.text = `x${this.coinPickupCount}`; 195 | }; 196 | 197 | PlayState._handleCollisions = function () { 198 | this.game.physics.arcade.collide(this.spiders, this.platforms); 199 | this.game.physics.arcade.collide(this.spiders, this.enemyWalls); 200 | this.game.physics.arcade.collide(this.hero, this.platforms); 201 | 202 | this.game.physics.arcade.overlap(this.hero, this.coins, this._onHeroVsCoin, 203 | null, this); 204 | this.game.physics.arcade.overlap(this.hero, this.spiders, 205 | this._onHeroVsEnemy, null, this); 206 | }; 207 | 208 | PlayState._handleInput = function () { 209 | if (this.keys.left.isDown) { // move hero left 210 | this.hero.move(-1); 211 | } 212 | else if (this.keys.right.isDown) { // move hero right 213 | this.hero.move(1); 214 | } 215 | else { // stop 216 | this.hero.move(0); 217 | } 218 | }; 219 | 220 | PlayState._loadLevel = function (data) { 221 | // create all the groups/layers that we need 222 | this.platforms = this.game.add.group(); 223 | this.coins = this.game.add.group(); 224 | this.spiders = this.game.add.group(); 225 | this.enemyWalls = this.game.add.group(); 226 | this.enemyWalls.visible = false; 227 | 228 | // spawn all platforms 229 | data.platforms.forEach(this._spawnPlatform, this); 230 | // spawn hero and enemies 231 | this._spawnCharacters({hero: data.hero, spiders: data.spiders}); 232 | // spawn important objects 233 | data.coins.forEach(this._spawnCoin, this); 234 | 235 | // enable gravity 236 | const GRAVITY = 1200; 237 | this.game.physics.arcade.gravity.y = GRAVITY; 238 | }; 239 | 240 | PlayState._spawnPlatform = function (platform) { 241 | let sprite = this.platforms.create( 242 | platform.x, platform.y, platform.image); 243 | 244 | this.game.physics.enable(sprite); 245 | sprite.body.allowGravity = false; 246 | sprite.body.immovable = true; 247 | 248 | this._spawnEnemyWall(platform.x, platform.y, 'left'); 249 | this._spawnEnemyWall(platform.x + sprite.width, platform.y, 'right'); 250 | }; 251 | 252 | PlayState._spawnEnemyWall = function (x, y, side) { 253 | let sprite = this.enemyWalls.create(x, y, 'invisible-wall'); 254 | // anchor and y displacement 255 | sprite.anchor.set(side === 'left' ? 1 : 0, 1); 256 | // physic properties 257 | this.game.physics.enable(sprite); 258 | sprite.body.immovable = true; 259 | sprite.body.allowGravity = false; 260 | }; 261 | 262 | PlayState._spawnCharacters = function (data) { 263 | // spawn spiders 264 | data.spiders.forEach(function (spider) { 265 | let sprite = new Spider(this.game, spider.x, spider.y); 266 | this.spiders.add(sprite); 267 | }, this); 268 | 269 | // spawn hero 270 | this.hero = new Hero(this.game, data.hero.x, data.hero.y); 271 | this.game.add.existing(this.hero); 272 | }; 273 | 274 | PlayState._spawnCoin = function (coin) { 275 | let sprite = this.coins.create(coin.x, coin.y, 'coin'); 276 | sprite.anchor.set(0.5, 0.5); 277 | 278 | this.game.physics.enable(sprite); 279 | sprite.body.allowGravity = false; 280 | 281 | sprite.animations.add('rotate', [0, 1, 2, 1], 6, true); // 6fps, looped 282 | sprite.animations.play('rotate'); 283 | }; 284 | 285 | PlayState._onHeroVsCoin = function (hero, coin) { 286 | this.sfx.coin.play(); 287 | coin.kill(); 288 | this.coinPickupCount++; 289 | }; 290 | 291 | PlayState._onHeroVsEnemy = function (hero, enemy) { 292 | if (hero.body.velocity.y > 0) { // kill enemies when hero is falling 293 | hero.bounce(); 294 | enemy.die(); 295 | this.sfx.stomp.play(); 296 | } 297 | else { // game over -> restart the game 298 | this.sfx.stomp.play(); 299 | this.game.state.restart(); 300 | } 301 | }; 302 | 303 | PlayState._createHud = function () { 304 | const NUMBERS_STR = '0123456789X '; 305 | this.coinFont = this.game.add.retroFont('font:numbers', 20, 26, 306 | NUMBERS_STR); 307 | 308 | let coinIcon = this.game.make.image(0, 0, 'icon:coin'); 309 | let coinScoreImg = this.game.make.image(coinIcon.x + coinIcon.width, 310 | coinIcon.height / 2, this.coinFont); 311 | coinScoreImg.anchor.set(0, 0.5); 312 | 313 | this.hud = this.game.add.group(); 314 | this.hud.add(coinIcon); 315 | this.hud.add(coinScoreImg); 316 | this.hud.position.set(10, 10); 317 | }; 318 | 319 | // ============================================================================= 320 | // entry point 321 | // ============================================================================= 322 | 323 | window.onload = function () { 324 | let game = new Phaser.Game(960, 600, Phaser.AUTO, 'game'); 325 | game.state.add('play', PlayState); 326 | game.state.start('play'); 327 | }; 328 | -------------------------------------------------------------------------------- /src/assets/assets/platformer/steps/step14.js: -------------------------------------------------------------------------------- 1 | // ============================================================================= 2 | // sprites 3 | // ============================================================================= 4 | 5 | // 6 | // hero sprite 7 | // 8 | function Hero(game, x, y) { 9 | Phaser.Sprite.call(this, game, x, y, 'hero'); 10 | this.anchor.set(0.5, 0.5); 11 | 12 | // physic properties 13 | this.game.physics.enable(this); 14 | this.body.collideWorldBounds = true; 15 | 16 | this.animations.add('stop', [0]); 17 | this.animations.add('run', [1, 2], 8, true); // 8fps looped 18 | this.animations.add('jump', [3]); 19 | this.animations.add('fall', [4]); 20 | } 21 | 22 | // inherit from Phaser.Sprite 23 | Hero.prototype = Object.create(Phaser.Sprite.prototype); 24 | Hero.prototype.constructor = Hero; 25 | 26 | Hero.prototype.move = function (direction) { 27 | const SPEED = 200; 28 | this.body.velocity.x = direction * SPEED; 29 | 30 | // update image flipping & animations 31 | if (this.body.velocity.x < 0) { 32 | this.scale.x = -1; 33 | } 34 | else if (this.body.velocity.x > 0) { 35 | this.scale.x = 1; 36 | } 37 | }; 38 | 39 | Hero.prototype.jump = function () { 40 | const JUMP_SPEED = 600; 41 | let canJump = this.body.touching.down; 42 | 43 | if (canJump) { 44 | this.body.velocity.y = -JUMP_SPEED; 45 | } 46 | 47 | return canJump; 48 | }; 49 | 50 | Hero.prototype.bounce = function () { 51 | const BOUNCE_SPEED = 200; 52 | this.body.velocity.y = -BOUNCE_SPEED; 53 | }; 54 | 55 | Hero.prototype.update = function () { 56 | // update sprite animation, if it needs changing 57 | let animationName = this._getAnimationName(); 58 | if (this.animations.name !== animationName) { 59 | this.animations.play(animationName); 60 | } 61 | }; 62 | 63 | Hero.prototype._getAnimationName = function () { 64 | let name = 'stop'; // default animation 65 | 66 | // jumping 67 | if (this.body.velocity.y < 0) { 68 | name = 'jump'; 69 | } 70 | // falling 71 | else if (this.body.velocity.y >= 0 && !this.body.touching.down) { 72 | name = 'fall'; 73 | } 74 | else if (this.body.velocity.x !== 0 && this.body.touching.down) { 75 | name = 'run'; 76 | } 77 | 78 | return name; 79 | }; 80 | 81 | // 82 | // Spider (enemy) 83 | // 84 | function Spider(game, x, y) { 85 | Phaser.Sprite.call(this, game, x, y, 'spider'); 86 | 87 | // anchor 88 | this.anchor.set(0.5); 89 | // animation 90 | this.animations.add('crawl', [0, 1, 2], 8, true); // 8fps, looped 91 | this.animations.add('die', [0, 4, 0, 4, 0, 4, 3, 3, 3, 3, 3, 3], 12); 92 | this.animations.play('crawl'); 93 | 94 | // physic properties 95 | this.game.physics.enable(this); 96 | this.body.collideWorldBounds = true; 97 | this.body.velocity.x = Spider.SPEED; 98 | } 99 | 100 | Spider.SPEED = 100; 101 | 102 | // inherit from Phaser.Sprite 103 | Spider.prototype = Object.create(Phaser.Sprite.prototype); 104 | Spider.prototype.constructor = Spider; 105 | 106 | Spider.prototype.update = function () { 107 | // check against walls and reverse direction if necessary 108 | if (this.body.touching.right || this.body.blocked.right) { 109 | this.body.velocity.x = -Spider.SPEED; // turn left 110 | } 111 | else if (this.body.touching.left || this.body.blocked.left) { 112 | this.body.velocity.x = Spider.SPEED; // turn right 113 | } 114 | }; 115 | 116 | Spider.prototype.die = function () { 117 | this.body.enable = false; 118 | 119 | this.animations.play('die').onComplete.addOnce(function () { 120 | this.kill(); 121 | }, this); 122 | }; 123 | 124 | 125 | // ============================================================================= 126 | // game states 127 | // ============================================================================= 128 | 129 | PlayState = {}; 130 | 131 | PlayState.init = function () { 132 | this.game.renderer.renderSession.roundPixels = true; 133 | 134 | this.keys = this.game.input.keyboard.addKeys({ 135 | left: Phaser.KeyCode.LEFT, 136 | right: Phaser.KeyCode.RIGHT, 137 | up: Phaser.KeyCode.UP 138 | }); 139 | 140 | this.keys.up.onDown.add(function () { 141 | let didJump = this.hero.jump(); 142 | if (didJump) { 143 | this.sfx.jump.play(); 144 | } 145 | }, this); 146 | 147 | this.coinPickupCount = 0; 148 | this.hasKey = false; 149 | }; 150 | 151 | PlayState.preload = function () { 152 | this.game.load.json('level:1', 'data/level01.json'); 153 | 154 | this.game.load.image('font:numbers', 'images/numbers.png'); 155 | 156 | this.game.load.image('background', 'images/background.png'); 157 | this.game.load.image('ground', 'images/ground.png'); 158 | this.game.load.image('grass:8x1', 'images/grass_8x1.png'); 159 | this.game.load.image('grass:6x1', 'images/grass_6x1.png'); 160 | this.game.load.image('grass:4x1', 'images/grass_4x1.png'); 161 | this.game.load.image('grass:2x1', 'images/grass_2x1.png'); 162 | this.game.load.image('grass:1x1', 'images/grass_1x1.png'); 163 | this.game.load.image('invisible-wall', 'images/invisible_wall.png'); 164 | this.game.load.image('icon:coin', 'images/coin_icon.png'); 165 | this.game.load.image('key', 'images/key.png'); 166 | 167 | this.game.load.spritesheet('coin', 'images/coin_animated.png', 22, 22); 168 | this.game.load.spritesheet('spider', 'images/spider.png', 42, 32); 169 | this.game.load.spritesheet('hero', 'images/hero.png', 36, 42); 170 | this.game.load.spritesheet('door', 'images/door.png', 42, 66); 171 | this.game.load.spritesheet('icon:key', 'images/key_icon.png', 34, 30); 172 | 173 | this.game.load.audio('sfx:jump', 'audio/jump.wav'); 174 | this.game.load.audio('sfx:coin', 'audio/coin.wav'); 175 | this.game.load.audio('sfx:stomp', 'audio/stomp.wav'); 176 | this.game.load.audio('sfx:key', 'audio/key.wav'); 177 | this.game.load.audio('sfx:door', 'audio/door.wav'); 178 | }; 179 | 180 | PlayState.create = function () { 181 | // create sound entities 182 | this.sfx = { 183 | jump: this.game.add.audio('sfx:jump'), 184 | coin: this.game.add.audio('sfx:coin'), 185 | stomp: this.game.add.audio('sfx:stomp'), 186 | key: this.game.add.audio('sfx:key'), 187 | door: this.game.add.audio('sfx:door') 188 | }; 189 | 190 | // create level 191 | this.game.add.image(0, 0, 'background'); 192 | this._loadLevel(this.game.cache.getJSON('level:1')); 193 | 194 | // crete hud with scoreboards) 195 | this._createHud(); 196 | }; 197 | 198 | PlayState.update = function () { 199 | this._handleCollisions(); 200 | this._handleInput(); 201 | 202 | this.coinFont.text = `x${this.coinPickupCount}`; 203 | this.keyIcon.frame = this.hasKey ? 1 : 0; 204 | }; 205 | 206 | PlayState._handleCollisions = function () { 207 | this.game.physics.arcade.collide(this.spiders, this.platforms); 208 | this.game.physics.arcade.collide(this.spiders, this.enemyWalls); 209 | this.game.physics.arcade.collide(this.hero, this.platforms); 210 | 211 | this.game.physics.arcade.overlap(this.hero, this.coins, this._onHeroVsCoin, 212 | null, this); 213 | this.game.physics.arcade.overlap(this.hero, this.spiders, 214 | this._onHeroVsEnemy, null, this); 215 | this.game.physics.arcade.overlap(this.hero, this.key, this._onHeroVsKey, 216 | null, this) 217 | this.game.physics.arcade.overlap(this.hero, this.door, this._onHeroVsDoor, 218 | // ignore if there is no key or the player is on air 219 | function (hero, door) { 220 | return this.hasKey && hero.body.touching.down; 221 | }, this); 222 | }; 223 | 224 | PlayState._handleInput = function () { 225 | if (this.keys.left.isDown) { // move hero left 226 | this.hero.move(-1); 227 | } 228 | else if (this.keys.right.isDown) { // move hero right 229 | this.hero.move(1); 230 | } 231 | else { // stop 232 | this.hero.move(0); 233 | } 234 | }; 235 | 236 | PlayState._loadLevel = function (data) { 237 | // create all the groups/layers that we need 238 | this.bgDecoration = this.game.add.group(); 239 | this.platforms = this.game.add.group(); 240 | this.coins = this.game.add.group(); 241 | this.spiders = this.game.add.group(); 242 | this.enemyWalls = this.game.add.group(); 243 | this.enemyWalls.visible = false; 244 | 245 | // spawn all platforms 246 | data.platforms.forEach(this._spawnPlatform, this); 247 | // spawn hero and enemies 248 | this._spawnCharacters({hero: data.hero, spiders: data.spiders}); 249 | // spawn important objects 250 | data.coins.forEach(this._spawnCoin, this); 251 | this._spawnDoor(data.door.x, data.door.y); 252 | this._spawnKey(data.key.x, data.key.y); 253 | 254 | // enable gravity 255 | const GRAVITY = 1200; 256 | this.game.physics.arcade.gravity.y = GRAVITY; 257 | }; 258 | 259 | PlayState._spawnPlatform = function (platform) { 260 | let sprite = this.platforms.create( 261 | platform.x, platform.y, platform.image); 262 | 263 | this.game.physics.enable(sprite); 264 | sprite.body.allowGravity = false; 265 | sprite.body.immovable = true; 266 | 267 | this._spawnEnemyWall(platform.x, platform.y, 'left'); 268 | this._spawnEnemyWall(platform.x + sprite.width, platform.y, 'right'); 269 | }; 270 | 271 | PlayState._spawnEnemyWall = function (x, y, side) { 272 | let sprite = this.enemyWalls.create(x, y, 'invisible-wall'); 273 | // anchor and y displacement 274 | sprite.anchor.set(side === 'left' ? 1 : 0, 1); 275 | // physic properties 276 | this.game.physics.enable(sprite); 277 | sprite.body.immovable = true; 278 | sprite.body.allowGravity = false; 279 | }; 280 | 281 | PlayState._spawnCharacters = function (data) { 282 | // spawn spiders 283 | data.spiders.forEach(function (spider) { 284 | let sprite = new Spider(this.game, spider.x, spider.y); 285 | this.spiders.add(sprite); 286 | }, this); 287 | 288 | // spawn hero 289 | this.hero = new Hero(this.game, data.hero.x, data.hero.y); 290 | this.game.add.existing(this.hero); 291 | }; 292 | 293 | PlayState._spawnCoin = function (coin) { 294 | let sprite = this.coins.create(coin.x, coin.y, 'coin'); 295 | sprite.anchor.set(0.5, 0.5); 296 | 297 | this.game.physics.enable(sprite); 298 | sprite.body.allowGravity = false; 299 | 300 | sprite.animations.add('rotate', [0, 1, 2, 1], 6, true); // 6fps, looped 301 | sprite.animations.play('rotate'); 302 | }; 303 | 304 | PlayState._spawnDoor = function (x, y) { 305 | this.door = this.bgDecoration.create(x, y, 'door'); 306 | this.door.anchor.setTo(0.5, 1); 307 | this.game.physics.enable(this.door); 308 | this.door.body.allowGravity = false; 309 | }; 310 | 311 | PlayState._spawnKey = function (x, y) { 312 | this.key = this.bgDecoration.create(x, y, 'key'); 313 | this.key.anchor.set(0.5, 0.5); 314 | // enable physics to detect collisions, so the hero can pick the key up 315 | this.game.physics.enable(this.key); 316 | this.key.body.allowGravity = false; 317 | // add a small 'up & down' animation via a tween 318 | this.key.y -= 3; 319 | this.game.add.tween(this.key) 320 | .to({y: this.key.y + 6}, 800, Phaser.Easing.Sinusoidal.InOut) 321 | .yoyo(true) 322 | .loop() 323 | .start(); 324 | }; 325 | 326 | 327 | PlayState._onHeroVsCoin = function (hero, coin) { 328 | this.sfx.coin.play(); 329 | coin.kill(); 330 | this.coinPickupCount++; 331 | }; 332 | 333 | PlayState._onHeroVsEnemy = function (hero, enemy) { 334 | if (hero.body.velocity.y > 0) { // kill enemies when hero is falling 335 | hero.bounce(); 336 | enemy.die(); 337 | this.sfx.stomp.play(); 338 | } 339 | else { // game over -> restart the game 340 | this.sfx.stomp.play(); 341 | this.game.state.restart(); 342 | } 343 | }; 344 | 345 | PlayState._onHeroVsKey = function (hero, key) { 346 | this.sfx.key.play(); 347 | key.kill(); 348 | this.hasKey = true; 349 | }; 350 | 351 | PlayState._onHeroVsDoor = function (hero, door) { 352 | this.sfx.door.play(); 353 | this.game.state.restart(); 354 | // TODO: go to the next level instead 355 | }; 356 | 357 | PlayState._createHud = function () { 358 | const NUMBERS_STR = '0123456789X '; 359 | this.coinFont = this.game.add.retroFont('font:numbers', 20, 26, 360 | NUMBERS_STR); 361 | 362 | this.keyIcon = this.game.make.image(0, 19, 'icon:key'); 363 | this.keyIcon.anchor.set(0, 0.5); 364 | 365 | let coinIcon = this.game.make.image(this.keyIcon.width + 7, 0, 'icon:coin'); 366 | let coinScoreImg = this.game.make.image(coinIcon.x + coinIcon.width, 367 | coinIcon.height / 2, this.coinFont); 368 | coinScoreImg.anchor.set(0, 0.5); 369 | 370 | this.hud = this.game.add.group(); 371 | this.hud.add(coinIcon); 372 | this.hud.add(coinScoreImg); 373 | this.hud.add(this.keyIcon); 374 | this.hud.position.set(10, 10); 375 | }; 376 | 377 | // ============================================================================= 378 | // entry point 379 | // ============================================================================= 380 | 381 | window.onload = function () { 382 | let game = new Phaser.Game(960, 600, Phaser.AUTO, 'game'); 383 | game.state.add('play', PlayState); 384 | game.state.start('play'); 385 | }; 386 | -------------------------------------------------------------------------------- /src/assets/assets/platformer/walking_spider.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/walking_spider.gif -------------------------------------------------------------------------------- /src/assets/assets/platformer/win_condition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/assets/platformer/win_condition.png -------------------------------------------------------------------------------- /src/assets/css/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Georgia, serif; 3 | padding: 0; 4 | margin: 0; 5 | line-height: 1.5; 6 | font-size: 1.2em; 7 | } 8 | 9 | main { 10 | max-width: 960px; 11 | margin: 0 auto; 12 | } 13 | 14 | img { 15 | max-width: 100%; 16 | background: #efefef; 17 | } 18 | 19 | a { 20 | color: #00a; 21 | } 22 | 23 | li { 24 | margin: 0.25em 0; 25 | } 26 | 27 | code:not([class*="language-"]) { 28 | background-color: #f5f2f0; 29 | font-family: Courier, monospace; 30 | font-size: 1em; 31 | } 32 | 33 | pre code[class*="language-"] { 34 | font-size: 0.9em; 35 | } 36 | 37 | .main-header { 38 | padding: 1em 0em; 39 | border-bottom: 1px solid #ccc; 40 | } 41 | 42 | @media(min-width:1250px) { 43 | .main-header { 44 | background: url(../images/moz-logo.svg) 1vw center no-repeat; 45 | background-size: 10vw; 46 | } 47 | 48 | } 49 | 50 | @media(max-width:1249px) { 51 | main, .main-header { 52 | padding-left: 1em; 53 | padding-right: 1em; 54 | } 55 | } 56 | 57 | article h1 { 58 | font-size: 1.8em; 59 | } 60 | 61 | .main-header h1 { 62 | max-width: 960px; 63 | margin: 0 auto; 64 | } 65 | 66 | .main-header a { 67 | text-decoration: none; 68 | } 69 | 70 | .main-footer { 71 | margin-top: 4em; 72 | padding: 1em; 73 | border-top: 1px solid #ccc; 74 | } 75 | 76 | .main-footer p { 77 | max-width: 960px; 78 | margin-left: auto; 79 | margin-right: auto; 80 | } 81 | 82 | .paginated-nav { 83 | margin-top: 2em; 84 | font-size: 1.2em; 85 | } 86 | 87 | .paginated-nav ul { 88 | list-style-type: none; 89 | padding-left: 0; 90 | margin-left: 0; 91 | display: flex; 92 | } 93 | 94 | .paginated-nav li { 95 | flex: 1 1 auto; 96 | } 97 | 98 | .paginated-nav .next { 99 | text-align: right; 100 | font-weight: bold; 101 | } 102 | 103 | .toc { 104 | column-count: 2; 105 | } 106 | 107 | .author { 108 | font-size: 0.9em; 109 | font-style: italic; 110 | } 111 | -------------------------------------------------------------------------------- /src/assets/images/moz-favicon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/images/moz-logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/platformer/audio/bgm.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/platformer/audio/bgm.mp3 -------------------------------------------------------------------------------- /src/assets/platformer/audio/bgm.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/platformer/audio/bgm.ogg -------------------------------------------------------------------------------- /src/assets/platformer/audio/coin.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/platformer/audio/coin.wav -------------------------------------------------------------------------------- /src/assets/platformer/audio/door.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/platformer/audio/door.wav -------------------------------------------------------------------------------- /src/assets/platformer/audio/jump.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/platformer/audio/jump.wav -------------------------------------------------------------------------------- /src/assets/platformer/audio/key.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/platformer/audio/key.wav -------------------------------------------------------------------------------- /src/assets/platformer/audio/stomp.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/platformer/audio/stomp.wav -------------------------------------------------------------------------------- /src/assets/platformer/data/level00.json: -------------------------------------------------------------------------------- 1 | { 2 | "platforms": [ 3 | {"image": "ground", "x": 0, "y": 546}, 4 | {"image": "grass:4x1", "x": 420, "y": 420} 5 | ], 6 | "decoration": [ 7 | {"frame": 2, "x": 630, "y": 504}, 8 | {"frame": 2, "x": 663, "y": 504}, 9 | {"frame": 2, "x": 697, "y": 504}, 10 | {"frame": 3, "x": 756, "y": 504}, 11 | {"frame": 1, "x": 84, "y": 504}, 12 | {"frame": 0, "x": 252, "y": 504}, 13 | {"frame": 4, "x": 462, "y": 378} 14 | ], 15 | "coins": [ 16 | {"x": 147, "y": 525}, {"x": 189, "y": 525}, 17 | {"x": 399, "y": 399}, {"x": 357, "y": 420}, {"x": 336, "y": 462}, 18 | {"x": 819, "y": 525}, {"x": 861, "y": 525}, {"x": 903, "y": 525} 19 | ], 20 | "hero": {"x": 21, "y": 525}, 21 | "spiders": [ 22 | ], 23 | "door": {"x": 231, "y": 546}, 24 | "key": {"x": 525, "y": 336} 25 | } 26 | -------------------------------------------------------------------------------- /src/assets/platformer/data/level01.json: -------------------------------------------------------------------------------- 1 | { 2 | "platforms": [ 3 | {"image": "ground", "x": 0, "y": 546}, 4 | {"image": "grass:8x1", "x": 0, "y": 420}, 5 | {"image": "grass:2x1", "x": 420, "y": 336}, 6 | {"image": "grass:1x1", "x": 588, "y": 504}, 7 | {"image": "grass:8x1", "x": 672, "y": 378}, 8 | {"image": "grass:4x1", "x": 126, "y": 252}, 9 | {"image": "grass:6x1", "x": 462, "y": 168}, 10 | {"image": "grass:2x1", "x": 798, "y": 84} 11 | ], 12 | "decoration": [ 13 | {"frame": 0, "x": 84, "y": 504}, {"frame": 1, "x": 420, "y": 504}, 14 | {"frame": 3, "x": 672, "y": 504}, {"frame": 4, "x": 595, "y": 462}, 15 | {"frame": 2, "x": 142, "y": 378}, {"frame": 1, "x": 168, "y": 378}, 16 | {"frame": 0, "x": 714, "y": 336}, 17 | {"frame": 4, "x": 420, "y": 294}, 18 | {"frame": 1, "x": 515, "y": 126}, {"frame": 3, "x": 525, "y": 126} 19 | ], 20 | "coins": [ 21 | {"x": 231, "y": 524}, {"x": 273, "y": 524}, {"x": 315, "y": 524}, {"x": 357, "y": 524}, 22 | {"x": 819, "y": 524}, {"x": 861, "y": 524}, {"x": 903, "y": 524}, {"x": 945, "y": 524}, 23 | {"x": 399, "y": 294}, {"x": 357, "y": 315}, {"x": 336, "y": 357}, 24 | {"x": 777, "y": 357}, {"x": 819, "y": 357}, {"x": 861, "y": 357}, {"x": 903, "y": 357}, {"x": 945, "y": 357}, 25 | {"x": 189, "y": 231}, {"x": 231, "y": 231}, 26 | {"x": 525, "y": 147}, {"x": 567, "y": 147}, {"x": 609, "y": 147}, {"x": 651, "y": 147}, 27 | {"x": 819, "y": 63}, {"x": 861, "y": 63} 28 | ], 29 | "hero": {"x": 21, "y": 525}, 30 | "spiders": [{"x": 121, "y": 399}, {"x": 800, "y": 362}, {"x": 500, "y": 147}], 31 | "door": {"x": 169, "y": 546}, 32 | "key": {"x": 903, "y": 105} 33 | } 34 | -------------------------------------------------------------------------------- /src/assets/platformer/images/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/platformer/images/background.png -------------------------------------------------------------------------------- /src/assets/platformer/images/coin_animated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/platformer/images/coin_animated.png -------------------------------------------------------------------------------- /src/assets/platformer/images/coin_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/platformer/images/coin_icon.png -------------------------------------------------------------------------------- /src/assets/platformer/images/decor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/platformer/images/decor.png -------------------------------------------------------------------------------- /src/assets/platformer/images/door.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/platformer/images/door.png -------------------------------------------------------------------------------- /src/assets/platformer/images/grass_1x1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/platformer/images/grass_1x1.png -------------------------------------------------------------------------------- /src/assets/platformer/images/grass_2x1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/platformer/images/grass_2x1.png -------------------------------------------------------------------------------- /src/assets/platformer/images/grass_4x1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/platformer/images/grass_4x1.png -------------------------------------------------------------------------------- /src/assets/platformer/images/grass_6x1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/platformer/images/grass_6x1.png -------------------------------------------------------------------------------- /src/assets/platformer/images/grass_8x1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/platformer/images/grass_8x1.png -------------------------------------------------------------------------------- /src/assets/platformer/images/ground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/platformer/images/ground.png -------------------------------------------------------------------------------- /src/assets/platformer/images/hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/platformer/images/hero.png -------------------------------------------------------------------------------- /src/assets/platformer/images/hero_stopped.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/platformer/images/hero_stopped.png -------------------------------------------------------------------------------- /src/assets/platformer/images/invisible_wall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/platformer/images/invisible_wall.png -------------------------------------------------------------------------------- /src/assets/platformer/images/key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/platformer/images/key.png -------------------------------------------------------------------------------- /src/assets/platformer/images/key_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/platformer/images/key_icon.png -------------------------------------------------------------------------------- /src/assets/platformer/images/numbers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/platformer/images/numbers.png -------------------------------------------------------------------------------- /src/assets/platformer/images/spider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozdevs/html5-games-workshop/9e1ae36d195903be59d852448e374343a0938e71/src/assets/platformer/images/spider.png -------------------------------------------------------------------------------- /src/assets/platformer/index.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |