├── .bowerrc ├── .editorconfig ├── .gitignore ├── .jshintrc ├── Gruntfile.js ├── Procfile ├── README.md ├── app.js ├── assets ├── empty.wav ├── gun-cocking-01.wav ├── gunshot.wav ├── preloader.gif └── yeoman-logo.png ├── bower.json ├── bower_components └── phaser-official │ ├── .bower.json │ ├── CONTRIBUTING.md │ ├── Gruntfile.js │ ├── README.md │ ├── bower.json │ ├── build │ ├── config.php │ ├── custom │ │ ├── ninja.js │ │ ├── ninja.min.js │ │ ├── p2.js │ │ ├── p2.min.js │ │ ├── phaser-no-libs.js │ │ ├── phaser-no-libs.min.js │ │ ├── phaser-no-physics.js │ │ ├── phaser-no-physics.min.js │ │ ├── pixi.js │ │ └── pixi.min.js │ ├── phaser.d.ts │ ├── phaser.js │ ├── phaser.map │ └── phaser.min.js │ ├── changelog.md │ ├── license.txt │ ├── package.json │ ├── phaser-logo-small.png │ └── plugins │ ├── AStar.js │ ├── CSS3Filters.js │ ├── ColorHarmony.js │ ├── ProTracker.js │ ├── QuadTree.js │ ├── SamplePlugin.js │ └── Webcam.js ├── config.json ├── css └── styles.css ├── dist ├── assets │ ├── empty.wav │ ├── gun-cocking-01.wav │ ├── gunshot.wav │ ├── preloader.gif │ └── yeoman-logo.png ├── css │ └── styles.css ├── index.html └── js │ ├── game.js │ ├── phaser.js │ ├── phaser.min.js │ └── plugins │ └── HUDManager.js ├── game ├── hud-manager │ ├── hud-manager.js │ └── scope.js ├── main.js ├── plugins │ └── HudManager.js ├── prefabs │ ├── enemy.js │ └── player.js ├── registries │ └── game-registry.js └── states │ ├── boot.js │ ├── gameover.js │ ├── menu.js │ ├── play.js │ └── preload.js ├── index.html ├── package.json └── templates └── _main.js.tpl /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "bower_components" 3 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | bower_components/phaser-official/docs/ 3 | bower_components/phaser-official/examples/ 4 | bower_components/phaser-official/filters/ 5 | bower_components/phaser-official/labs/ 6 | bower_components/phaser-official/resources/ 7 | bower_components/phaser-official/src/ 8 | bower_components/phaser-official/tasks/ 9 | bower_components/phaser-official/tutorials/ 10 | *.log -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "esnext": true, 4 | "bitwise": true, 5 | "camelcase": true, 6 | "curly": true, 7 | "eqeqeq": true, 8 | "immed": true, 9 | "indent": 2, 10 | "latedef": true, 11 | "newcap": true, 12 | "noarg": true, 13 | "quotmark": "single", 14 | "regexp": true, 15 | "undef": true, 16 | "unused": true, 17 | "strict": true, 18 | "trailing": true, 19 | "smarttabs": true, 20 | "white": true 21 | } 22 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | // Generated on 2014-03-28 using generator-phaser-official 0.0.8-rc-2 2 | 'use strict'; 3 | var config = require('./config.json'); 4 | var _ = require('underscore'); 5 | _.str = require('underscore.string'); 6 | 7 | // Mix in non-conflict functions to Underscore namespace if you want 8 | _.mixin(_.str.exports()); 9 | 10 | var LIVERELOAD_PORT = 35729; 11 | var lrSnippet = require('connect-livereload')({port: LIVERELOAD_PORT}); 12 | var mountFolder = function (connect, dir) { 13 | return connect.static(require('path').resolve(dir)); 14 | }; 15 | 16 | module.exports = function (grunt) { 17 | // load all grunt tasks 18 | require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks); 19 | 20 | grunt.initConfig({ 21 | watch: { 22 | scripts: { 23 | files: [ 24 | 'game/**/*.js', 25 | '!game/main.js' 26 | ], 27 | options: { 28 | spawn: false, 29 | livereload: LIVERELOAD_PORT 30 | }, 31 | tasks: ['build'] 32 | } 33 | }, 34 | connect: { 35 | options: { 36 | port: 9000, 37 | // change this to '0.0.0.0' to access the server from outside 38 | hostname: 'localhost' 39 | }, 40 | livereload: { 41 | options: { 42 | middleware: function (connect) { 43 | return [ 44 | lrSnippet, 45 | mountFolder(connect, 'dist') 46 | ]; 47 | } 48 | } 49 | } 50 | }, 51 | open: { 52 | server: { 53 | path: 'http://localhost:9000' 54 | } 55 | }, 56 | copy: { 57 | dist: { 58 | files: [ 59 | // includes files within path and its sub-directories 60 | { expand: true, src: ['assets/**'], dest: 'dist/' }, 61 | { expand: true, flatten: true, src: ['game/plugins/*.js'], dest: 'dist/js/plugins/' }, 62 | { expand: true, flatten: true, src: ['bower_components/**/build/*.js'], dest: 'dist/js/' }, 63 | { expand: true, src: ['css/**'], dest: 'dist/' }, 64 | { expand: true, src: ['index.html'], dest: 'dist/' } 65 | ] 66 | } 67 | }, 68 | browserify: { 69 | build: { 70 | src: ['game/main.js'], 71 | dest: 'dist/js/game.js' 72 | } 73 | } 74 | }); 75 | 76 | grunt.registerTask('build', ['buildBootstrapper', 'browserify','copy']); 77 | grunt.registerTask('serve', ['build', 'connect:livereload', 'open', 'watch']); 78 | grunt.registerTask('default', ['serve']); 79 | grunt.registerTask('prod', ['build', 'copy']); 80 | 81 | grunt.registerTask('buildBootstrapper', 'builds the bootstrapper file correctly', function() { 82 | var stateFiles = grunt.file.expand('game/states/*.js'); 83 | var gameStates = []; 84 | var statePattern = new RegExp(/(\w+).js$/); 85 | stateFiles.forEach(function(file) { 86 | var state = file.match(statePattern)[1]; 87 | if (!!state) { 88 | gameStates.push({shortName: state, stateName: _.capitalize(state) + 'State'}); 89 | } 90 | }); 91 | config.gameStates = gameStates; 92 | console.log(config); 93 | var bootstrapper = grunt.file.read('templates/_main.js.tpl'); 94 | bootstrapper = grunt.template.process(bootstrapper,{data: config}); 95 | grunt.file.write('game/main.js', bootstrapper); 96 | }); 97 | }; -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: node app.js 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | phaser-HudManager 2 | ================= 3 | Introducing AnguarJS Style data bindings for your game's hud. 4 | 5 | Demo: http://phaser-hudmanager.herokuapp.com 6 | 7 | Usage is simple: 8 | 9 | ```language-javascript 10 | create: function() { 11 | this.score = 0; 12 | 13 | var style = { font: '18px Arial', fill: '#ffffff', align: 'center'}; 14 | 15 | this.hud = Phaser.Plugins.HUDManager.createHud(this.game, this, 'gamehud'); 16 | this.scoreHUD = this.hud.addText(x, y, 'Score: ', style, 'score', this); 17 | this.game.add.existing(this.scoreHUD.text); 18 | }, 19 | 20 | update: function() { 21 | this.score++; 22 | } 23 | ``` 24 | 25 | The hud manager will watch for changes on the `this.score` variable and update your text object so that it will output: 26 | 27 | #### Score: 0 28 | 29 | There's also progress/health bars, and general watchers. 30 | 31 | ## API 32 | ### Static Methods 33 | #### HUDManager.create(game, parent, name, pollrate): 34 | ##### returns: a new hud instance. if the name given already exists, it will return the current instance of the hud with that name 35 | Don't create a bunch of hud instances around the game. Instead, create one for your game's hud, and one to encompass all of your sprites, if you're using the health bar component. 36 | 37 | By default, the poll rate is once every 100ms. This means the hud dirty checks the watched variables 10 times a second. 38 | 39 | 40 | 41 | #### HUDManager.get(name): 42 | ##### returns the hud instance with the given name, or throws an exception if the named hud isn't found 43 | 44 | ### Instance Methods 45 | #### HUDManager.destroy() 46 | ##### Destorys the current instance of HUDManager. 47 | 48 | 49 | #### HUDManager.addText(x, y, label, style, watched, context) 50 | ##### arguments: 51 | * `x`: (number) the x position of the created Phaser.Text object 52 | * `y`: (number) the y position of the created Phaser.Text object 53 | * `label`: (string) the string to prepend to the Phaser.Text object 54 | * `watched`: (string) the name of the variable to watch in the given context 55 | * `context`: (object) the context of the watched variabled 56 | 57 | ##### returns: 58 | { text: Phaser.Text, deregister: Function } 59 | Calling the deregistration function will cause the HUDManager instance to stop updating on changes 60 | 61 | #### HUDManager.addBar(x, y, width, height, max, watched, context, color, backgroundColor, shouldCountUp ) 62 | Adds a progress/health bar. 63 | ##### arguments 64 | * `x`: (number) the x position of the created Phaser.Sprite object 65 | * `y`: (number) the y position of the created Phaser.Sprite object 66 | * `width`: (number) the width of the created Phaser.Sprite object 67 | * `height`: (number) the height of the created Phaser.Sprite object 68 | # `max`: (number) the maximum value of the watched value 69 | * `watched`: (string) the name of the variable to watch in the given context 70 | * `context`: (object) the context of the watched variabled 71 | * `color`: (string | function) the color of the created bar. You can provide a function that accepts (percent) as an argument. Percent will be a value between 0 and 1 indicating how much of the bar is filled. The function must return a string that represents a color. DEFAULT: 'white' 72 | * 'backgroundColor': (string) A string representing a color. DEFAULT: '#999' 73 | 74 | ##### returns: 75 | { bar: Phaser.Sprite, deregister: Function } 76 | Calling the deregistration function will cause the HUDManager instance to stop updating on changes 77 | 78 | #### HUDManager.HEALTHBAR 79 | This is a predefined function that you can pass as the `color` argument in `HUDManager.addBar`. This will automatically return a green, yellow, or red color to signify the health amount. 80 | 81 | 82 | #### HUDManager.addWatch(watched, watchedContext, callback, callbackContext) 83 | ##### arguments 84 | * `watched`: (string) the name of the variable to watch in the given context 85 | * `watchedContext`: (object) the context of the watched variabled 86 | * `callback`: (Function(newValue, oldValue)) callback to call when a change has been detected 87 | * `callbackContext`: (object) the context of the callback function 88 | 89 | ##### returns: Function 90 | The returned function is the deregistration function. Calling this function will stop the HUDManager instance from watching for changes on this watched item. 91 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var port = process.env.PORT || 5000; 3 | var app = express(); 4 | 5 | app.use(express.static(__dirname + "/dist")); 6 | 7 | app.listen(port); -------------------------------------------------------------------------------- /assets/empty.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ada-lovecraft/phaser-HudManager/4ef6970598217c098e5b2c9c91832fd30f23307a/assets/empty.wav -------------------------------------------------------------------------------- /assets/gun-cocking-01.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ada-lovecraft/phaser-HudManager/4ef6970598217c098e5b2c9c91832fd30f23307a/assets/gun-cocking-01.wav -------------------------------------------------------------------------------- /assets/gunshot.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ada-lovecraft/phaser-HudManager/4ef6970598217c098e5b2c9c91832fd30f23307a/assets/gunshot.wav -------------------------------------------------------------------------------- /assets/preloader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ada-lovecraft/phaser-HudManager/4ef6970598217c098e5b2c9c91832fd30f23307a/assets/preloader.gif -------------------------------------------------------------------------------- /assets/yeoman-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ada-lovecraft/phaser-HudManager/4ef6970598217c098e5b2c9c91832fd30f23307a/assets/yeoman-logo.png -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hud-manager", 3 | "version": "0.0.0", 4 | "dependencies": { 5 | "phaser-official": "2.0.2" 6 | } 7 | } -------------------------------------------------------------------------------- /bower_components/phaser-official/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phaser", 3 | "version": "2.0.2", 4 | "homepage": "http://phaser.io", 5 | "authors": [ 6 | "photonstorm " 7 | ], 8 | "description": "A fun, free and fast 2D game framework for making HTML5 games for desktop and mobile, supporting Canvas and WebGL.", 9 | "main": "build/phaser.js", 10 | "keywords": [ 11 | "html5", 12 | "game", 13 | "games", 14 | "framework", 15 | "canvas", 16 | "WebGL", 17 | "tilemaps", 18 | "physics", 19 | "sprites", 20 | "fonts", 21 | "images", 22 | "audio", 23 | "Web", 24 | "Audio", 25 | "touch", 26 | "input", 27 | "mobile" 28 | ], 29 | "license": "MIT", 30 | "ignore": [ 31 | "**/.*", 32 | "node_modules", 33 | "bower_components", 34 | "test", 35 | "tests" 36 | ], 37 | "_release": "2.0.2", 38 | "_resolution": { 39 | "type": "version", 40 | "tag": "v2.0.2", 41 | "commit": "5b73bb21bb74c2b3d4b9dd7a4518cec40e019d58" 42 | }, 43 | "_source": "git://github.com/photonstorm/phaser.git", 44 | "_target": "2.0.2", 45 | "_originalSource": "phaser-official" 46 | } -------------------------------------------------------------------------------- /bower_components/phaser-official/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | #How to contribute 2 | 3 | It's important to us that you feel you can contribute towards the evolution of Phaser. This can take many forms: from helping to fix bugs or improve the docs, to adding in new features to the source. This guide should help you in making that process as smooth as possible. 4 | 5 | 6 | ##Reporting issues 7 | 8 | [GitHub Issues][0] is the place to report bugs you may have found in either the core library or any of the examples that are part of the repository. When submitting a bug please do the following: 9 | 10 | 1. **Search for existing issues.** Your bug may have already been fixed or addressed in a development branch version of Phaser, so be sure to search the issues first before putting in a duplicate issue. 11 | 12 | 2. **Not sure if it's a bug?.** Then please ask on the forum. If something is blatantly wrong then post it to github. But if you feel it might just be because you're not sure of expected behaviour, then it might save us time, and get you a response faster, if you post it to the Phaser forum instead. 13 | 14 | 3. **Create an isolated and reproducible test case.** If you are reporting a bug, make sure you also have a minimal, runnable, code example that reproduces the problem you have. 15 | 16 | 4. **Include a live example.** After narrowing your code down to only the problem areas, make use of [jsFiddle][1], [jsBin][2], or a link to your live site so that we can view a live example of the problem. 17 | 18 | 5. **Share as much information as possible.** Include browser version affected, your OS, version of the library, steps to reproduce, etc. "X isn't working!!!1!" will probably just be closed. 19 | 20 | 21 | ##Pixi and Phaser 22 | 23 | It's important to understand that internally Phaser uses [Pixi.js](https://github.com/GoodBoyDigital/pixi.js/) for all rendering. It's possible you may find a bug that is generated on the Pixi level rather than Phaser. You're welcome to still report the issue of course, but if you get a reply saying we think it might be a Pixi issue this is what we're talking about :) 24 | 25 | 26 | ##Support Forum 27 | 28 | We have a very active [Phaser Support Forum](http://www.html5gamedevs.com/forum/14-phaser/). If you need general support, or are struggling to understand how to do something or need your code checked over, then we would urge you to post it to our forum. There are a lot of friendly devs in there who can help, as well as the core Phaser and Pixi teams, so it's a great place to get support from. You're welcome to report bugs directly on GitHub, but for general support we'd always recommend using the forum first. 29 | 30 | 31 | ##Dev vs. Master 32 | 33 | The dev branch of Phaser is our 'current working' version. It is always ahead of the master branch in terms of features and fixes. However it's also bleeding-edge and experimental and we cannot and do not guarantee it will compile or work for you. Very often we have to break things for a few days while we rebuild and patch. So by all means please export the dev branch and contribute towards it, indeed that is where all Pull Requests should be sent, but do so understanding the API may change beneath you. 34 | 35 | 36 | ##Making Changes 37 | 38 | To take advantage of our grunt build script and jshint config it will be easiest for you if you have node.js and grunt installed locally. 39 | 40 | You can download node.js from [nodejs.org][3]. After it has been installed open a console and run `npm i -g grunt -cli` to install the global `grunt` executable. 41 | 42 | After that you can clone the repository and run `npm i` inside the cloned folder. This will install dependencies necessary for building the project. Once that is ready, 43 | make your changes and submit a Pull Request: 44 | 45 | - **Send Pull Requests to the `dev` branch.** All Pull Requests must be sent to the `dev` branch, `master` is the latest release and PRs to that branch will be closed. 46 | 47 | - **Ensure changes are jshint validated.** Our JSHint configuration file is provided in the repository and you should check against it before submitting. 48 | 49 | - **Never commit new builds.** When making a code change you should always run `grunt` which will rebuild the project so you can test, *however* please do not commit these new builds or your PR will be closed. Builds by default are placed in the `dist` folder, to keep them separate from the `build` folder releases. 50 | 51 | - **Only commit relevant changes.** Don't include changes that are not directly relevant to the fix you are making. The more focused a PR is, the faster it will get attention and be merged. Extra files changing only whitespace or trash files will likely get your PR closed. 52 | 53 | 54 | ##I don't really like git / node.js, but I can fix this bug 55 | 56 | That is fine too. While Pull Requests are the best thing in the world for us, they are not the only way to help. You're welcome to post fixes to our forum or even just email them to us. All we ask is that you still adhere to the guidelines presented here re: JSHint, etc. 57 | 58 | 59 | ##Code Style Guide 60 | 61 | - Use 4 spaces for tabs, never tab characters. 62 | 63 | - No trailing whitespace, blank lines should have no whitespace. 64 | 65 | - Always favor strict equals `===` unless you *need* to use type coercion. 66 | 67 | - Follow conventions already in the code, and listen to jshint. Our config is set-up for a reason. 68 | 69 | Thanks to Chad for creating the original Pixi.js Contributing file which we adapted for Phaser. 70 | 71 | [0]: https://github.com/photonstorm/phaser/issues 72 | [1]: http://jsfiddle.net 73 | [2]: http://jsbin.com/ 74 | [3]: http://nodejs.org 75 | -------------------------------------------------------------------------------- /bower_components/phaser-official/Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | 3 | grunt.loadNpmTasks('grunt-contrib-clean'); 4 | grunt.loadNpmTasks('grunt-contrib-concat'); 5 | grunt.loadNpmTasks('grunt-contrib-connect'); 6 | grunt.loadNpmTasks('grunt-contrib-copy'); 7 | grunt.loadNpmTasks('grunt-contrib-jshint'); 8 | grunt.loadNpmTasks('grunt-contrib-uglify'); 9 | grunt.loadNpmTasks('grunt-text-replace'); 10 | grunt.loadTasks('./tasks'); 11 | 12 | grunt.initConfig({ 13 | 14 | pkg: grunt.file.readJSON('package.json'), 15 | 16 | banner: '/**\n' + 17 | '* @author Richard Davey \n' + 18 | '* @copyright 2014 Photon Storm Ltd.\n' + 19 | '* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}\n' + 20 | '*\n' + 21 | '* @overview\n' + 22 | '*\n' + 23 | '* Phaser - http://www.phaser.io\n' + 24 | '*\n' + 25 | '* v<%= pkg.version %> "<%= pkg.release %>" - Built: <%= grunt.template.today() %>\n' + 26 | '*\n' + 27 | '* By Richard Davey http://www.photonstorm.com @photonstorm\n' + 28 | '*\n' + 29 | '* Phaser is a fun, free and fast 2D game framework for making HTML5 games \n' + 30 | '* for desktop and mobile web browsers, supporting Canvas and WebGL.\n' + 31 | '*\n' + 32 | '* Phaser uses Pixi.js for rendering, created by Mat Groves http://matgroves.com @Doormat23\n' + 33 | '* Phaser uses p2.js for full-body physics, created by Stefan Hedman https://github.com/schteppe/p2.js @schteppe\n' + 34 | '* Phaser contains a port of N+ Physics, converted by Richard Davey, original by http://www.metanetsoftware.com\n' + 35 | '*\n' + 36 | '* Many thanks to Adam Saltsman (@ADAMATOMIC) for releasing Flixel, from which both Phaser\n' + 37 | '* and my love of framework development can be traced.\n' + 38 | '*\n' + 39 | '* Follow development at http://phaser.io and on our forum\n' + 40 | '*\n' + 41 | '* "If you want your children to be intelligent, read them fairy tales."\n' + 42 | '* "If you want them to be more intelligent, read them more fairy tales."\n' + 43 | '* -- Albert Einstein\n' + 44 | '*/\n', 45 | 46 | release_dir: 'build', 47 | compile_dir: 'dist', 48 | 49 | pixi: [ 50 | 'src/pixi/Intro.js', 51 | 'src/pixi/Pixi.js', 52 | 'src/pixi/core/Point.js', 53 | 'src/pixi/core/Rectangle.js', 54 | 'src/pixi/core/Polygon.js', 55 | 'src/pixi/core/Circle.js', 56 | 'src/pixi/core/Ellipse.js', 57 | 'src/pixi/core/Matrix.js', 58 | 'src/pixi/display/DisplayObject.js', 59 | 'src/pixi/display/DisplayObjectContainer.js', 60 | 'src/pixi/display/Sprite.js', 61 | 'src/pixi/display/SpriteBatch.js', 62 | 'src/pixi/filters/FilterBlock.js', 63 | 'src/pixi/text/Text.js', 64 | 'src/pixi/text/BitmapText.js', 65 | 'src/pixi/display/Stage.js', 66 | 'src/pixi/utils/Utils.js', 67 | 'src/pixi/utils/EventTarget.js', 68 | 'src/pixi/utils/Polyk.js', 69 | 'src/pixi/renderers/webgl/utils/WebGLShaderUtils.js', 70 | 'src/pixi/renderers/webgl/shaders/PixiShader.js', 71 | 'src/pixi/renderers/webgl/shaders/PixiFastShader.js', 72 | 'src/pixi/renderers/webgl/shaders/StripShader.js', 73 | 'src/pixi/renderers/webgl/shaders/PrimitiveShader.js', 74 | 'src/pixi/renderers/webgl/utils/WebGLGraphics.js', 75 | 'src/pixi/renderers/webgl/WebGLRenderer.js', 76 | 'src/pixi/renderers/webgl/utils/WebGLMaskManager.js', 77 | 'src/pixi/renderers/webgl/utils/WebGLShaderManager.js', 78 | 'src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js', 79 | 'src/pixi/renderers/webgl/utils/WebGLFastSpriteBatch.js', 80 | 'src/pixi/renderers/webgl/utils/WebGLFilterManager.js', 81 | 'src/pixi/renderers/webgl/utils/FilterTexture.js', 82 | 'src/pixi/renderers/canvas/utils/CanvasMaskManager.js', 83 | 'src/pixi/renderers/canvas/utils/CanvasTinter.js', 84 | 'src/pixi/renderers/canvas/CanvasRenderer.js', 85 | 'src/pixi/renderers/canvas/CanvasGraphics.js', 86 | 'src/pixi/primitives/Graphics.js', 87 | 'src/pixi/extras/TilingSprite.js', 88 | 'src/pixi/textures/BaseTexture.js', 89 | 'src/pixi/textures/Texture.js', 90 | 'src/pixi/textures/RenderTexture.js', 91 | 'src/pixi/Outro.js', 92 | ], 93 | 94 | phaser: [ 95 | 'src/Intro.js', 96 | 'src/Phaser.js', 97 | 'src/utils/Utils.js', 98 | 99 | 'src/geom/Circle.js', 100 | 'src/geom/Point.js', 101 | 'src/geom/Rectangle.js', 102 | 'src/geom/Line.js', 103 | 'src/geom/Ellipse.js', 104 | 'src/geom/Polygon.js', 105 | 106 | 'src/core/Camera.js', 107 | 'src/core/State.js', 108 | 'src/core/StateManager.js', 109 | 'src/core/LinkedList.js', 110 | 'src/core/Signal.js', 111 | 'src/core/SignalBinding.js', 112 | 'src/core/Filter.js', 113 | 'src/core/Plugin.js', 114 | 'src/core/PluginManager.js', 115 | 'src/core/Stage.js', 116 | 'src/core/Group.js', 117 | 'src/core/World.js', 118 | 'src/core/ScaleManager.js', 119 | 'src/core/Game.js', 120 | 121 | 'src/input/Input.js', 122 | 'src/input/Key.js', 123 | 'src/input/Keyboard.js', 124 | 'src/input/Mouse.js', 125 | 'src/input/MSPointer.js', 126 | 'src/input/Pointer.js', 127 | 'src/input/Touch.js', 128 | 'src/input/Gamepad.js', 129 | 'src/input/SinglePad.js', 130 | 'src/input/GamepadButton.js', 131 | 'src/input/InputHandler.js', 132 | 133 | 'src/gameobjects/Events.js', 134 | 'src/gameobjects/GameObjectFactory.js', 135 | 'src/gameobjects/GameObjectCreator.js', 136 | 'src/gameobjects/BitmapData.js', 137 | 'src/gameobjects/Sprite.js', 138 | 'src/gameobjects/Image.js', 139 | 'src/gameobjects/TileSprite.js', 140 | 'src/gameobjects/Text.js', 141 | 'src/gameobjects/BitmapText.js', 142 | 'src/gameobjects/Button.js', 143 | 'src/gameobjects/Graphics.js', 144 | 'src/gameobjects/RenderTexture.js', 145 | 'src/gameobjects/SpriteBatch.js', 146 | 'src/gameobjects/RetroFont.js', 147 | 148 | 'src/system/Canvas.js', 149 | 'src/system/Device.js', 150 | 'src/system/RequestAnimationFrame.js', 151 | 152 | 'src/math/Math.js', 153 | 'src/math/RandomDataGenerator.js', 154 | 'src/math/QuadTree.js', 155 | 156 | 'src/net/Net.js', 157 | 158 | 'src/tween/TweenManager.js', 159 | 'src/tween/Tween.js', 160 | 'src/tween/Easing.js', 161 | 162 | 'src/time/Time.js', 163 | 'src/time/Timer.js', 164 | 'src/time/TimerEvent.js', 165 | 166 | 'src/animation/AnimationManager.js', 167 | 'src/animation/Animation.js', 168 | 'src/animation/Frame.js', 169 | 'src/animation/FrameData.js', 170 | 'src/animation/AnimationParser.js', 171 | 172 | 'src/loader/Cache.js', 173 | 'src/loader/Loader.js', 174 | 'src/loader/LoaderParser.js', 175 | 176 | 'src/sound/Sound.js', 177 | 'src/sound/SoundManager.js', 178 | 179 | 'src/utils/Debug.js', 180 | 'src/utils/Color.js', 181 | 182 | 'src/physics/Physics.js', 183 | 184 | 'src/physics/arcade/World.js', 185 | 'src/physics/arcade/Body.js', 186 | 187 | 'src/particles/Particles.js', 188 | 'src/particles/arcade/ArcadeParticles.js', 189 | 'src/particles/arcade/Emitter.js', 190 | 191 | 'src/tilemap/Tile.js', 192 | 'src/tilemap/Tilemap.js', 193 | 'src/tilemap/TilemapLayer.js', 194 | 'src/tilemap/TilemapParser.js', 195 | 'src/tilemap/Tileset.js', 196 | 197 | 'src/Outro.js' 198 | ], 199 | 200 | p2: [ 201 | 'src/physics/p2/p2.js', 202 | 'src/physics/p2/World.js', 203 | 'src/physics/p2/PointProxy.js', 204 | 'src/physics/p2/InversePointProxy.js', 205 | 'src/physics/p2/Body.js', 206 | 'src/physics/p2/BodyDebug.js', 207 | 'src/physics/p2/Spring.js', 208 | 'src/physics/p2/Material.js', 209 | 'src/physics/p2/ContactMaterial.js', 210 | 'src/physics/p2/CollisionGroup.js', 211 | 'src/physics/p2/DistanceConstraint.js', 212 | 'src/physics/p2/GearConstraint.js', 213 | 'src/physics/p2/LockConstraint.js', 214 | 'src/physics/p2/PrismaticConstraint.js', 215 | 'src/physics/p2/RevoluteConstraint.js' 216 | ], 217 | 218 | ninja: [ 219 | 'src/physics/ninja/World.js', 220 | 'src/physics/ninja/Body.js', 221 | 'src/physics/ninja/AABB.js', 222 | 'src/physics/ninja/Tile.js', 223 | 'src/physics/ninja/Circle.js' 224 | ], 225 | 226 | // If we've updated pixi or p2 then their UMD wrappers will be wrong, this will fix it: 227 | replace: { 228 | 229 | pixi: { 230 | src: ['src/pixi/Outro.js'], 231 | dest: 'src/pixi/Outro.js', 232 | replacements: [{ 233 | from: "define(PIXI);", 234 | to: "define('PIXI', (function() { return root.PIXI = PIXI; })() );" 235 | }] 236 | }, 237 | 238 | p2: { 239 | src: ['src/physics/p2/p2.js'], 240 | dest: 'src/physics/p2/p2.js', 241 | replacements: [{ 242 | from: '!function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.p2=e():"undefined"!=typeof global?self.p2=e():"undefined"!=typeof self&&(self.p2=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module \'"+o+"\'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o'], 250 | 251 | concat: { 252 | 253 | // Our custom version of p2 254 | p2: { 255 | src: ['<%= p2 %>'], 256 | dest: '<%= compile_dir %>/p2.js' 257 | }, 258 | 259 | // Our custom version of Pixi 260 | pixi: { 261 | src: ['<%= pixi %>'], 262 | dest: '<%= compile_dir %>/pixi.js' 263 | }, 264 | 265 | // Our custom version of Ninja Physics 266 | ninja: { 267 | src: ['<%= ninja %>'], 268 | dest: '<%= compile_dir %>/ninja.js' 269 | }, 270 | 271 | // Phaser with no bundled libs 272 | phaser: { 273 | options: { 274 | banner: '<%= banner %>' 275 | }, 276 | src: ['<%= phaser %>'], 277 | dest: '<%= compile_dir %>/phaser-no-libs.js' 278 | }, 279 | 280 | // Phaser with pixi but no physics libs 281 | phaserNoPhysics: { 282 | options: { 283 | banner: '<%= banner %>' 284 | }, 285 | src: ['<%= compile_dir %>/pixi.js', '<%= compile_dir %>/phaser-no-libs.js'], 286 | dest: '<%= compile_dir %>/phaser-no-physics.js' 287 | }, 288 | 289 | // One ring to rule them all 290 | standalone: { 291 | options: { 292 | banner: '<%= banner %>' 293 | }, 294 | src: ['<%= compile_dir %>/pixi.js', '<%= compile_dir %>/phaser-no-libs.js', '<%= compile_dir %>/ninja.js', '<%= compile_dir %>/p2.js'], 295 | dest: '<%= compile_dir %>/phaser.js' 296 | } 297 | 298 | }, 299 | 300 | uglify: { 301 | 302 | p2: { 303 | options: { 304 | banner: '/* p2.js custom build for Phaser v<%= pkg.version %> - http://phaser.io - @photonstorm - (c) 2014 Photon Storm Ltd. */\n' 305 | }, 306 | src: ['<%= concat.p2.dest %>'], 307 | dest: '<%= compile_dir %>/p2.min.js' 308 | }, 309 | 310 | pixi: { 311 | options: { 312 | banner: '/* Pixi.js custom build for Phaser v<%= pkg.version %> - http://phaser.io - @photonstorm - (c) 2014 Photon Storm Ltd. */\n' 313 | }, 314 | src: ['<%= concat.pixi.dest %>'], 315 | dest: '<%= compile_dir %>/pixi.min.js' 316 | }, 317 | 318 | ninja: { 319 | options: { 320 | banner: '/* Ninja Physics for Phaser v<%= pkg.version %> - http://phaser.io - @photonstorm - (c) 2014 Photon Storm Ltd. */\n' 321 | }, 322 | src: ['<%= concat.ninja.dest %>'], 323 | dest: '<%= compile_dir %>/ninja.min.js' 324 | }, 325 | 326 | phaser: { 327 | options: { 328 | banner: '/* Phaser (no libs) v<%= pkg.version %> - http://phaser.io - @photonstorm - (c) 2014 Photon Storm Ltd. */\n' 329 | }, 330 | src: ['<%= concat.phaser.dest %>'], 331 | dest: '<%= compile_dir %>/phaser-no-libs.min.js' 332 | }, 333 | 334 | phaserNoPhysics: { 335 | options: { 336 | banner: '/* Phaser (no physics) v<%= pkg.version %> - http://phaser.io - @photonstorm - (c) 2014 Photon Storm Ltd. */\n' 337 | }, 338 | src: ['<%= concat.phaserNoPhysics.dest %>'], 339 | dest: '<%= compile_dir %>/phaser-no-physics.min.js' 340 | }, 341 | 342 | standalone: { 343 | options: { 344 | sourceMap: true, 345 | sourceMapName: '<%= compile_dir %>/phaser.map', 346 | banner: '/* Phaser v<%= pkg.version %> - http://phaser.io - @photonstorm - (c) 2014 Photon Storm Ltd. */\n' 347 | }, 348 | src: ['<%= concat.standalone.dest %>'], 349 | dest: '<%= compile_dir %>/phaser.min.js' 350 | } 351 | 352 | }, 353 | 354 | copy: { 355 | main: { 356 | files: [ 357 | { src: ['dist/phaser.js'], dest: 'build/phaser.js' }, 358 | { src: ['dist/phaser.min.js'], dest: 'build/phaser.min.js' }, 359 | { src: ['dist/phaser.map'], dest: 'build/phaser.map' }, 360 | 361 | { src: ['dist/p2.js'], dest: 'build/custom/p2.js' }, 362 | { src: ['dist/p2.min.js'], dest: 'build/custom/p2.min.js' }, 363 | { src: ['dist/phaser-no-libs.js'], dest: 'build/custom/phaser-no-libs.js' }, 364 | { src: ['dist/phaser-no-libs.min.js'], dest: 'build/custom/phaser-no-libs.min.js' }, 365 | { src: ['dist/pixi.js'], dest: 'build/custom/pixi.js' }, 366 | { src: ['dist/pixi.min.js'], dest: 'build/custom/pixi.min.js' }, 367 | { src: ['dist/ninja.js'], dest: 'build/custom/ninja.js' }, 368 | { src: ['dist/ninja.min.js'], dest: 'build/custom/ninja.min.js' }, 369 | { src: ['dist/phaser-no-physics.js'], dest: 'build/custom/phaser-no-physics.js' }, 370 | { src: ['dist/phaser-no-physics.min.js'], dest: 'build/custom/phaser-no-physics.min.js' } 371 | 372 | ] 373 | } 374 | }, 375 | 376 | connect: { 377 | root: { 378 | options: { 379 | keepalive: true, 380 | hostname: '*' 381 | } 382 | } 383 | }, 384 | 385 | jshint: { 386 | src: { 387 | src: [ 388 | 'plugins/**/*.js', 389 | 'src/**/*.js', 390 | '!src/Intro.js', 391 | '!src/Outro.js', 392 | '!src/pixi/**/*', 393 | '!src/physics/p2/p2.js', 394 | '!plugins/AStar.js' 395 | ], 396 | options: { jshintrc: '.jshintrc' } 397 | }, 398 | 399 | filters: { 400 | src: ['filters/**/*.js'], 401 | options: { jshintrc: 'filters/.jshintrc', } 402 | }, 403 | 404 | tooling: { 405 | src: [ 406 | 'Gruntfile.js', 407 | 'tasks/**/*.js' 408 | ], 409 | options: { jshintrc: 'tasks/.jshintrc' } 410 | }, 411 | 412 | options: { 413 | force: true 414 | } 415 | } 416 | }); 417 | 418 | grunt.registerTask('default', ['build']); 419 | 420 | grunt.registerTask('build', ['clean', 'jshint', 'concat', 'uglify']); 421 | grunt.registerTask('dist', ['build', 'copy']); 422 | 423 | }; 424 | -------------------------------------------------------------------------------- /bower_components/phaser-official/README.md: -------------------------------------------------------------------------------- 1 | ![Phaser 2.0](http://www.phaser.io/images/phaser2-github.png) 2 | 3 | Phaser 2.0.2 4 | ============ 5 | 6 | Phaser is a fast, free and fun open source game framework for making desktop and mobile browser HTML5 games. It uses [Pixi.js](https://github.com/GoodBoyDigital/pixi.js/) internally for fast 2D Canvas and WebGL rendering. 7 | 8 | Version: 2.0.2 "Ghealdan" - Released: 28th March 2014 9 | 10 | By Richard Davey, [Photon Storm](http://www.photonstorm.com) 11 | 12 | * View the [Official Website](http://phaser.io) 13 | * Follow on [Twitter](https://twitter.com/photonstorm) 14 | * Join the [Forum](http://www.html5gamedevs.com/forum/14-phaser/) 15 | * Source code for 250+ [Phaser Examples](https://github.com/photonstorm/phaser-examples) 16 | * Read the [documentation online](http://docs.phaser.io) 17 | * Browse the [Examples online](http://examples.phaser.io) 18 | * Join our [#phaserio IRC channel](http://www.html5gamedevs.com/topic/4470-official-phaserio-irc-channel-phaserio-on-freenode/) on freenode 19 | 20 | [Subscribe to our new Phaser Newsletter](https://confirmsubscription.com/h/r/369DE48E3E86AF1E). We'll email you when new versions are released as well as send you our regular Phaser game making magazine. 21 | 22 | [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/photonstorm/phaser/trend.png)](https://bitdeli.com/free "Bitdeli Badge") 23 | 24 | 25 | What's new in 2.0.2? 26 | -------------------- 27 | 28 | The great thing about running an open source project are all the awesome contributions from the community, and this release reflects that. Aside from a raft of small but important ArcadePhysics fixes we've also had the entirely library jshinted and tidied up by xtian. We have had jshint configs in place for a while now, but he's forced us to make them part of the build process and helped tidy-up a number of things that had crept in. 29 | 30 | We've also updated the included tutorial (and the web version) so it's now fully compatible with Phaser 2 and re-published and updated all of the API documentation, which you'll find in the docs folder in this release. 31 | 32 | 33 | Welcome to Phaser 34 | ----------------- 35 | 36 | 6 months ago we released Phaser 1.0 into the world. Suffice to say that since then we've been overwhelmed at the huge surge of developers taking to it! Our github repository is consistently in the top JavaScript lists, we've over 3200 stars at the time of writing, and a wonderful, vibrant and friendly community. Phaser 2 is a natural evolution of what we started. We've focused specifically on performance and expansion with this release. Lots of developers have already reported to us considerably speed increases just by swapping to Phaser 2 (reports of 200% faster speeds on mobile aren't unheard of!). There's also a full-body physics system available now, in the form of the excellent p2.js. The upgrade to Pixi 1.5 under the hood bought lots of new visual effects in, including blend modes and tints. 37 | 38 | And we're also really pleased to have closed down over 550 issues reported on github. We literally went through every last bug reported to us, and fixed it. All kinds of little things that as a whole make the library that much more solid. With the 2.0 release we're now freezing the API. Before we have to admit that the API changed somewhat on a whim, and we moved things around and changed things without too much consideration for fellow developers. With 2.0 that stops - we've spent long enough on this release that we're now extremely happy with the organisation of classes and methods, and while we may still need to make small tweaks in the future, none of them will be API breaking without prior community approval first. This means if you're using Phaser to teach in classes, or writing a book / tutorials around it, this is the version to base off. 39 | 40 | If you want to port a Phaser 1.x game over to 2 then do read our [Migration Guide](https://github.com/photonstorm/phaser/blob/master/resources/Migration%20Guide.md) first. 41 | 42 | So what's next? We have a roadmap (which you can find at the bottom of this document), but we're going to sit back and take stock for a while, building up the tutorials and sample games. We will of course jump on bug fixes quickly, but this is definitely the best release of Phaser ever. The most features, the fastest, the most stable and just generally the most fun to use. 43 | 44 | Happy coding everyone! See you on the forums. 45 | 46 | ![boogie](http://www.phaser.io/images/spacedancer.gif) 47 | 48 | 49 | Getting Started Guides 50 | ---------------------- 51 | 52 | We have a new [Getting Started Guide](http://phaser.io/getting-started-js.php) which covers all you need to begin developing games with Phaser. From setting up a web server to picking an IDE. If you're new to HTML5 game development, or are coming from another language like AS3, then we recommend starting there. 53 | 54 | There is a comprehensive [How to Learn Phaser](http://gamedevelopment.tutsplus.com/articles/how-to-learn-the-phaser-html5-game-engine--gamedev-13643) guide on the GameDevTuts+ site which is a great place to learn where to find tutorials, examples and support. 55 | 56 | There is also an [un-official Getting Started Guide](http://www.antonoffplus.com/coding-an-html5-game-for-30-minutes-or-an-introduction-to-the-phaser-framework). 57 | 58 | 59 | ![Phaser Logo](http://www.photonstorm.com/wp-content/uploads/2013/09/phaser_10_release.jpg) 60 | 61 | Change Log 62 | ---------- 63 | 64 | Version 2.0.2 - "Ghealdan" - 28th March 2014 65 | 66 | Bug Fixes 67 | 68 | * Sprite would glitch if it had an ArcadePhysics Body that was re-positioned out of loop. 69 | * Sprite would "fly off" if it had an ArcadePhysics Body that was re-positioned during an input handler. 70 | * Tween.generateData would enter an eternal loop if the total resulted in a float. Now wrapped in Math.floor. 71 | * ArcadePhysics.Body preUpdate has been modified to stop Sprites with non-1 scaling from gaining delta and moving off the screen (fix #644). 72 | * ArcadePhysics.Body deltaMaxY wasn't being correctly applied. 73 | * P2.World - Removing tilemap layer retrieval for object layers in convertCollisionObjects() (thanks bmceldowney, fix #653) 74 | * Calling Keyboard.stop() wouldn't let you call Keyboard.start() later on in the same game 75 | 76 | 77 | Updated 78 | 79 | * The "Build your First Phaser Game" Tutorial has been updated for Phaser 2 80 | * Line.fromSprite now sets "fromCenter" to false by default as Sprite.center is deprecated in 2.x. Documentation and Examples updated to reflect this. 81 | * All the documentation has been re-published for 2.0.2. 82 | * Lots of ArcadePhysics.World methods have been marked as private where they shouldn't be called directly (separateX, etc) 83 | * xtian jshint fixed nearly every single file in the repository! 84 | 85 | 86 | New Features 87 | 88 | * Sprite.overlap lets you quickly check to see if the bounds of two display objects are intersecting or not, without having to use a physics system. 89 | * Keyboard.destroy will now clear all event listeners and any custom set callbacks or Keys. 90 | 91 | 92 | There is an extensive [Migration Guide](https://github.com/photonstorm/phaser/blob/master/resources/Migration%20Guide.md) available for those converting from Phaser 1.x to 2.x. In the guide we detail the API breaking changes and approach to our new physics system. 93 | 94 | The full Change Log is at https://github.com/photonstorm/phaser/blob/master/changelog.md 95 | 96 | 97 | How to Build 98 | ------------ 99 | 100 | We provide a fully compiled version of Phaser in the `build` directory, in both plain and minified formats. 101 | 102 | We also provide a Grunt script that will build Phaser from source along with all the examples. 103 | 104 | Run `grunt` to perform a default build to the `dist` folder and update the examples. 105 | 106 | If you replace Pixi or p2 then run `grunt replace` to patch their UMD strings so they work properly with Phaser and requireJS. 107 | 108 | 109 | Koding 110 | ------ 111 | 112 | You can [![clone the Phaser repo in Koding](http://learn.koding.com/btn/clone_d.png)][koding] and then start editing and previewing code right away using their web based VM development system. 113 | 114 | 115 | Bower 116 | ----- 117 | 118 | If you use bowser you can install phaser with: 119 | 120 | `bower install phaser` 121 | 122 | Nice and easy :) 123 | 124 | ![Tanks](http://www.photonstorm.com/wp-content/uploads/2013/10/phaser_tanks-640x480.png) 125 | 126 | 127 | CDNJS 128 | ----- 129 | 130 | Thanks to a community member Phaser is now available on [CDNJS](http://cdnjs.com). You can include the following in your html: 131 | 132 | `http://cdnjs.cloudflare.com/ajax/libs/phaser/2.0.2/phaser.min.js` 133 | 134 | Or if you prefer you can leave the protocol off, so it works via http and https: 135 | 136 | `//cdnjs.cloudflare.com/ajax/libs/phaser/2.0.2/phaser.min.js` 137 | 138 | 139 | Requirements 140 | ------------ 141 | 142 | Games created with Phaser require a modern web browser that supports the canvas tag. This includes Internet Explorer 9+, Firefox, Chrome, Safari and Opera. It also works on mobile web browsers including stock Android 2.x browser and above and iOS5 Mobile Safari and above. 143 | 144 | If you need to support IE9 or Android 2.x then you must use a build of Phaser that doesn't include P2 physics. You'll find these in the `build/custom` folder. 145 | 146 | For developing with Phaser you can use either a plain-vanilla JavaScript approach or [TypeScript](https://typescript.codeplex.com/) using the provided TypeScript definitions file. We made no assumptions about how you like to code your games, and were careful not to impose any form of class/inheritance/structure upon you. 147 | 148 | Phaser is 576 KB minified (including all 3 physics engines, 311 KB without) and 128 KB gzipped (67 KB without physics libs). 149 | 150 | 151 | Learn By Example 152 | ---------------- 153 | 154 | Ever since we started Phaser we've been growing and expanding our extensive set of Examples. Currently over 250 of them! 155 | 156 | They used to be bundled in the main Phaser repo, but because they got so large and in order to help with versioning we've moved them to their own repo. 157 | 158 | Please go and checkout https://github.com/photonstorm/phaser-examples 159 | 160 | Phaser comes with an ever growing suite of Examples. Personally I feel that we learn better by looking at small refined code examples, so we created over 250 of them and create new ones to test every new feature added. Inside the `examples` repo you'll find the current set. If you write a particularly good example then please send it to us. 161 | 162 | The examples need to be run through a local web server (in order to avoid file access permission errors from your browser). You can use your own web server, or start the included web server using grunt. 163 | 164 | Using a locally installed web server browse to the examples folder: 165 | 166 | examples/index.html 167 | 168 | Alternatively in order to start the included web server, after you've cloned the repo, run `npm install` to install all dependencies, then `grunt connect` to start a local server. After running this command you should be able to access your local webserver at `http://127.0.0.1:8000`. Then browse to the examples folder: `http://127.0.0.1:8000/examples/index.html` 169 | 170 | There is a new 'Side View' example viewer as well. This loads all the examples into a left-hand frame for faster navigation. 171 | 172 | You can also browse all [Phaser Examples](http://examples.phaser.io) online. 173 | 174 | 175 | Features 176 | -------- 177 | 178 | **WebGL & Canvas** 179 | 180 | Phaser uses both a Canvas and WebGL renderer internally and can automatically swap between them based on browser support. This allows for lightning fast rendering across Desktop and Mobile. When running under WebGL Phaser now supports shaders, allowing for some incredible in-game effects. Phaser uses and contributes towards the excellent Pixi.js library for rendering. 181 | 182 | **Preloader** 183 | 184 | We've made the loading of assets as simple as one line of code. Images, Sounds, Sprite Sheets, Tilemaps, JSON data, XML and JavaScript files - all parsed and handled automatically, ready for use in game and stored in a global Cache for Sprites to share. 185 | 186 | **Physics** 187 | 188 | Phaser ships with our Arcade Physics system, Ninja Physics and P2.JS - a full body physics system. Arcade Physics is for high-speed AABB collision only. Ninja Physics allows for complex tiles and slopes, perfect for level scenery, and P2.JS is a full-body physics system, with constraints, springs, polygon support and more. 189 | 190 | **Sprites** 191 | 192 | Sprites are the life-blood of your game. Position them, tween them, rotate them, scale them, animate them, collide them, paint them onto custom textures and so much more! 193 | Sprites also have full Input support: click them, touch them, drag them around, snap them - even pixel perfect click detection if needed. 194 | 195 | **Groups** 196 | 197 | Group bundles of Sprites together for easy pooling and recycling, avoiding constant object creation. Groups can also be collided: for example a "Bullets" group checking for collision against the "Aliens" group, with a custom collision callback to handle the outcome. 198 | 199 | **Animation** 200 | 201 | Phaser supports classic Sprite Sheets with a fixed frame size, Texture Packer and Flash CS6/CC JSON files (both Hash and Array formats) and Starling XML files. All of these can be used to easily create animation for Sprites. 202 | 203 | **Particles** 204 | 205 | An Arcade Particle system is built-in, which allows you to create fun particle effects easily. Create explosions or constant streams for effects like rain or fire. Or attach the Emitter to a Sprite for a jet trail. 206 | 207 | **Camera** 208 | 209 | Phaser has a built-in Game World. Objects can be placed anywhere within the world and you've got access to a powerful Camera to look into that world. Pan around and follow Sprites with ease. 210 | 211 | **Input** 212 | 213 | Talk to a Phaser.Pointer and it doesn't matter if the input came from a touch-screen or mouse, it can even change mid-game without dropping a beat. Multi-touch, Mouse, Keyboard and lots of useful functions allow you to code custom gesture recognition. 214 | 215 | **Sound** 216 | 217 | Phaser supports both Web Audio and legacy HTML Audio. It automatically handles mobile device locking, easy Audio Sprite creation, looping, streaming and volume. We know how much of a pain dealing with audio on mobile is, so we did our best to resolve that! 218 | 219 | **Tilemaps** 220 | 221 | Phaser can load, render and collide with a tilemap with just a couple of lines of code. We support CSV and Tiled map data formats with multiple tile layers. There are lots of powerful tile manipulation functions: swap tiles, replace them, delete them, add them and update the map in realtime. 222 | 223 | **Device Scaling** 224 | 225 | Phaser has a built-in Scale Manager which allows you to scale your game to fit any size screen. Control aspect ratios, minimum and maximum scales and full-screen support. 226 | 227 | **Plugin system** 228 | 229 | We are trying hard to keep the core of Phaser limited to only essential classes, so we built a smart Plugin system to handle everything else. Create your own plugins easily and share them with the community. 230 | 231 | **Mobile Browser** 232 | 233 | Phaser was built specifically for Mobile web browsers. Of course it works blazingly fast on Desktop too, but unlike lots of frameworks mobile was our main focus. If it doesn't perform well on mobile then we don't add it into the Core. 234 | 235 | **Developer Support** 236 | 237 | We use Phaser every day on our many client projects. As a result it's constantly evolving and improving and we jump on bugs and pull requests quickly. This is a living, breathing framework maintained by a commercial company with custom feature development and support packages available. We live and breathe HTML5 games. 238 | 239 | **Battle Tested** 240 | 241 | Phaser has been used to create hundreds of games, which receive millions of plays per month. We're not saying it is 100% bug free, but we use it for our client work every day, so issues get resolved fast and we stay on-top of the changing browser landscape. 242 | 243 | ![FruitParty](http://www.photonstorm.com/wp-content/uploads/2013/10/phaser_fruit_particles-640x480.png) 244 | 245 | 246 | Road Map 247 | -------- 248 | 249 | Beyond version 2.0 here are some of the features planned for the future: 250 | 251 | Version 2.1 ("Shienar") 252 | 253 | * Enhance the State Management, so you can perform non-destructive State swaps and persistence. 254 | * A more advanced Particle system, one that can render to a single canvas (rather than spawn hundreds of Sprites), more advanced effects, etc. 255 | * Ability to control DOM elements from the core game and layer them into the game. 256 | * Touch Gestures. 257 | * Support for parallel asset loading. 258 | 259 | Version 2.2 ("Tarabon") 260 | 261 | * Comprehensive testing across Firefox OS devices, CocoonJS and Ejecta. 262 | * Integration with third party services like Google Play Game Services and Amazon JS SDK. 263 | * Flash CC HTML5 export integration. 264 | * Massively enhance the audio side of Phaser. Take more advantage of Web Audio: echo effects, positional sound, etc. 265 | 266 | Beyond version 2.2 267 | 268 | * Test out packaging with Node-webkit. 269 | * Game parameters stored in Google Docs. 270 | * Look at HiDPI Canvas settings. 271 | * Multiple Camera support. 272 | * DragonBones support. 273 | * Cache to localStorage using If-Modified-Since. [See github request](https://github.com/photonstorm/phaser/issues/495) 274 | * Allow for complex assets like Bitmap Fonts to be stored within a texture atlas. 275 | * Look at XDomainRequest for IE9 CORs issues. 276 | 277 | 278 | Nadion 279 | ------ 280 | 281 | [Nadion](https://github.com/jcd-as/nadion) is a set of powerful enhancements for Phaser that makes level building even easier. It includes features such as Trigger, Area, Alarms and Emitters, debug panels, state machines, parallax layer scrolling, 'developer mode' short-cuts and more. 282 | 283 | 284 | Contributing 285 | ------------ 286 | 287 | We now have a full [Contributors Guide][contribute] which goes into the process in more detail, but here are the headlines: 288 | 289 | - If you find a bug then please report it on [GitHub Issues][issues] or our [Support Forum][forum]. 290 | 291 | - If you have a feature request, or have written a game or demo that shows Phaser in use, then please get in touch. We'd love to hear from you! Either post to our [forum][forum] or email: rich@photonstorm.com 292 | 293 | - If you issue a Pull Request for Phaser, please only do so againt the `dev` branch and *not* against the `master` branch. 294 | 295 | - Before submitting a Pull Request please run your code through [JSHint](http://www.jshint.com/) to check for stylistic or formatting errors. To use JSHint, run `grunt jshint`. This isn't a strict requirement and we are happy to receive Pull Requests that haven't been JSHinted, so don't let it put you off contributing, but do know that we'll reformat your source before going live with it. 296 | 297 | 298 | Bugs? 299 | ----- 300 | 301 | Please add them to the [Issue Tracker][issues] with as much info as possible, especially source code demonstrating the issue. 302 | 303 | ![Phaser Tilemap](http://www.photonstorm.com/wp-content/uploads/2013/04/phaser_tilemap_collision.png) 304 | 305 | "Being negative is not how we make progress" - Larry Page, Google 306 | 307 | 308 | License 309 | ------- 310 | 311 | Phaser is released under the [MIT License](http://opensource.org/licenses/MIT). 312 | 313 | [issues]: https://github.com/photonstorm/phaser/issues 314 | [contribute]: https://github.com/photonstorm/phaser/blob/master/CONTRIBUTING.md 315 | [phaser]: https://github.com/photonstorm/phaser 316 | [forum]: http://www.html5gamedevs.com/forum/14-phaser/ 317 | [koding]: https://koding.com/Teamwork?import=https://github.com/photonstorm/phaser/archive/master.zip&c=git1 318 | 319 | [![Analytics](https://ga-beacon.appspot.com/UA-44006568-2/phaser/index)](https://github.com/igrigorik/ga-beacon) 320 | -------------------------------------------------------------------------------- /bower_components/phaser-official/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phaser", 3 | "version": "2.0.2", 4 | "homepage": "http://phaser.io", 5 | "authors": [ 6 | "photonstorm " 7 | ], 8 | "description": "A fun, free and fast 2D game framework for making HTML5 games for desktop and mobile, supporting Canvas and WebGL.", 9 | "main": "build/phaser.js", 10 | "keywords": [ 11 | "html5", 12 | "game", 13 | "games", 14 | "framework", 15 | "canvas", 16 | "WebGL", 17 | "tilemaps", 18 | "physics", 19 | "sprites", 20 | "fonts", 21 | "images", 22 | "audio", 23 | "Web", 24 | "Audio", 25 | "touch", 26 | "input", 27 | "mobile" 28 | ], 29 | "license": "MIT", 30 | "ignore": [ 31 | "**/.*", 32 | "node_modules", 33 | "bower_components", 34 | "test", 35 | "tests" 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /bower_components/phaser-official/build/config.php: -------------------------------------------------------------------------------- 1 | "; 25 | } 26 | 27 | echo << 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | EOL; 168 | 169 | if ($arcade) 170 | { 171 | echo << 174 | 175 | EOL; 176 | } 177 | 178 | 179 | if ($p2) 180 | { 181 | echo << 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | EOL; 198 | } 199 | 200 | if ($ninja) 201 | { 202 | echo << 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | EOL; 213 | } 214 | 215 | ?> -------------------------------------------------------------------------------- /bower_components/phaser-official/license.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Richard Davey, Photon Storm Ltd. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /bower_components/phaser-official/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Phaser", 3 | "version": "2.0.2", 4 | "release": "Ghealdan", 5 | "description": "A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers.", 6 | "author": "Richard Davey", 7 | "logo": "https://raw.github.com/photonstorm/phaser/master/phaser-logo-small.png", 8 | "homepage": "http://phaser.io", 9 | "bugs": "https://github.com/photonstorm/phaser/issues", 10 | "license": "MIT", 11 | "licenseUrl": "http://www.opensource.org/licenses/mit-license.php", 12 | "repository": { 13 | "type": "git", 14 | "url": "https://photonstorm@github.com/photonstorm/phaser.git" 15 | }, 16 | "keywords": [ 17 | "HTML5", 18 | "game", 19 | "canvas", 20 | "2d", 21 | "WebGL", 22 | "web audio", 23 | "physics", 24 | "tweens", 25 | "javascript", 26 | "typescript" 27 | ], 28 | "devDependencies": { 29 | "grunt": "~0.4.1", 30 | "grunt-contrib-concat": "~0.3.0", 31 | "grunt-contrib-connect": "~0.5.0", 32 | "grunt-contrib-copy": "~0.5.0", 33 | "grunt-contrib-clean": "~0.5.0", 34 | "grunt-contrib-jshint": "~0.9.2", 35 | "grunt-contrib-uglify": "~0.3.3", 36 | "lodash": "~2.2.1", 37 | "grunt-text-replace": "~0.3.11", 38 | "jshint": "~2.4.4" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /bower_components/phaser-official/phaser-logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ada-lovecraft/phaser-HudManager/4ef6970598217c098e5b2c9c91832fd30f23307a/bower_components/phaser-official/phaser-logo-small.png -------------------------------------------------------------------------------- /bower_components/phaser-official/plugins/AStar.js: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | 4 | * Copyright (c) 2014 Raphaël Roux 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | * 25 | * 26 | */ 27 | 28 | /** 29 | * @author Raphaël Roux 30 | * @copyright 2014 Raphaël Roux 31 | * @license {@link http://opensource.org/licenses/MIT} 32 | */ 33 | 34 | /** 35 | * AStar is a phaser pathfinding plugin based on an A* kind of algorythm 36 | * It works with the Phaser.Tilemap 37 | * 38 | * @class Phaser.Plugin.AStar 39 | * @constructor 40 | * @param {Any} parent - The object that owns this plugin, usually Phaser.PluginManager. 41 | */ 42 | Phaser.Plugin.AStar = function (parent) 43 | { 44 | 45 | /** 46 | * @property {Any} parent - The parent of this plugin. If added to the PluginManager the parent will be set to that, otherwise it will be null. 47 | */ 48 | this.parent = parent; 49 | 50 | /** 51 | * @property {Phaser.Tilemap} _tilemap - A reference to the tilemap used to store astar nodes according to the Phaser.Tilemap structure. 52 | */ 53 | this._tilemap; 54 | 55 | /** 56 | * @property {number} _layerIndex - The layer index of the tilemap that is used to store astar nodes. 57 | */ 58 | this._layerIndex; 59 | 60 | /** 61 | * @property {number} _tilesetIndex - The tileset index of the tileset that handle tiles properties. 62 | */ 63 | this._tilesetIndex; 64 | 65 | /** 66 | * @property {array} _open - An array that references nodes to be considered by the search path algorythm. 67 | */ 68 | this._open; 69 | 70 | /** 71 | * @property {array} _closed - An array that references nodes not to consider anymore. 72 | */ 73 | this._closed; 74 | 75 | /** 76 | * @property {array} _visited - Internal array of visited tiles, use for debug pupose. 77 | */ 78 | this._visited; 79 | 80 | /** 81 | * @property {boolean} _useDiagonal - Does the astar algorythm can use tile diagonal? 82 | * @default true 83 | */ 84 | this._useDiagonal = true; 85 | 86 | /** 87 | * @property {boolean} _findClosest - Does the findPath algorythm must calculate the closest result if destination is unreachable. If not findPath will return an empty array 88 | * @default true 89 | */ 90 | this._findClosest = true; 91 | 92 | /** 93 | * @property {string} _walkablePropName - Wich name have the walkable propertiy in your tileset. 94 | * @default 'walkable' 95 | */ 96 | this._walkablePropName = 'walkable'; 97 | 98 | /** 99 | * @property {function} _distanceFunction - The function used to calculate distance. 100 | */ 101 | this._distanceFunction = Phaser.Plugin.AStar.DISTANCE_EUCLIDIAN; 102 | 103 | /** 104 | * @property {Phaser.Plugin.AStar.AStarPath} _lastPath - The last path calculated by astar. 105 | */ 106 | this._lastPath = null; 107 | 108 | /** 109 | * @property {boolean} _debug - Boolean to debug mode, stores visited nodes, and have a cost. Disable in production. 110 | * @default false 111 | */ 112 | this._debug = true; 113 | }; 114 | 115 | Phaser.Plugin.AStar.prototype = Object.create(Phaser.Plugin.prototype); 116 | Phaser.Plugin.AStar.prototype.constructor = Phaser.Plugin.AStar; 117 | 118 | 119 | Phaser.Plugin.AStar.VERSION = '0.0.101'; 120 | Phaser.Plugin.AStar.COST_ORTHOGONAL = 1; 121 | Phaser.Plugin.AStar.COST_DIAGONAL = Phaser.Plugin.AStar.COST_ORTHOGONAL*Math.sqrt(2); 122 | Phaser.Plugin.AStar.DISTANCE_MANHATTAN = 'distManhattan'; 123 | Phaser.Plugin.AStar.DISTANCE_EUCLIDIAN = 'distEuclidian'; 124 | 125 | /** 126 | * Sets the Phaser.Tilemap used to searchPath into. 127 | * @method Phaser.Plugin.AStar#setAStarMap 128 | * @public 129 | * @param {Phaser.Tilemap} map - the Phaser.Tilemap used to searchPath into. It must have a tileset with tile porperties to know if tiles are walkable or not. 130 | * @param {string} layerName - The name of the layer that handle tiles. 131 | * @param {string} tilesetName - The name of the tileset that have walkable properties. 132 | * @return {Phaser.Plugin.AStar} The Phaser.Plugin.AStar itself. 133 | */ 134 | Phaser.Plugin.AStar.prototype.setAStarMap = function(map, layerName, tilesetName) 135 | { 136 | this._tilemap = map; 137 | this._layerIndex = this._tilemap.getLayerIndex(layerName);; 138 | this._tilesetIndex = this._tilemap.getTilesetIndex(tilesetName); 139 | 140 | this.updateMap(); 141 | 142 | return this; 143 | }; 144 | 145 | 146 | /** 147 | * Sets the Phaser.Tilemap used to searchPath into. 148 | * @method Phaser.Plugin.AStar-setAStarMap 149 | * @private 150 | * @return {void} The Phaser.Plugin.AStar itself. 151 | */ 152 | Phaser.Plugin.AStar.prototype.updateMap = function() 153 | { 154 | var tile; 155 | var walkable; 156 | 157 | //for each tile, add a default AStarNode with x, y and walkable properties according to the tilemap/tileset datas 158 | for(var y=0; y < this._tilemap.height; y++) 159 | { 160 | for(var x=0; x < this._tilemap.width; x++) 161 | { 162 | tile = this._tilemap.layers[this._layerIndex].data[y][x]; 163 | walkable = this._tilemap.tilesets[this._tilesetIndex].tileProperties[tile.index - 1][this._walkablePropName] !== "false" ? true : false; 164 | tile.properties.astarNode = new Phaser.Plugin.AStar.AStarNode(x, y, walkable); 165 | } 166 | } 167 | 168 | }; 169 | 170 | 171 | /** 172 | * Find a path between to tiles coordinates 173 | * @method Phaser.Plugin.AStar#findPath 174 | * @public 175 | * @param {Phaser.Point} startPoint - The start point x, y in tiles coordinates to search a path. 176 | * @param {Phaser.Point} goalPoint - The goal point x, y in tiles coordinates that you trying to reach. 177 | * @return {Phaser.Plugin.AStar.AStarPath} The Phaser.Plugin.AStar.AStarPath that results 178 | */ 179 | Phaser.Plugin.AStar.prototype.findPath = function(startPoint, goalPoint) 180 | { 181 | var path = new Phaser.Plugin.AStar.AStarPath(); 182 | 183 | var start = this._tilemap.layers[this._layerIndex].data[startPoint.y][startPoint.x].properties.astarNode; //:AStarNode; 184 | var goal = this._tilemap.layers[this._layerIndex].data[goalPoint.y][goalPoint.x].properties.astarNode 185 | 186 | path.start = start; 187 | path.goal = goal; 188 | 189 | this._open = []; 190 | this._closed = []; 191 | this._visited = []; 192 | 193 | this._open.push(start); 194 | 195 | start.g = 0; 196 | start.h = this[this._distanceFunction](start, goal); 197 | start.f = start.h; 198 | start.parent = null; 199 | 200 | //Loop until there are no more nodes to search 201 | while(this._open.length > 0) 202 | { 203 | //Find lowest f in this._open 204 | var f = Infinity; 205 | var x; 206 | for (var i=0; i 0) { 348 | 349 | n = map[y][x-1].properties.astarNode; 350 | if (n.walkable) { 351 | n.travelCost = Phaser.Plugin.AStar.COST_ORTHOGONAL; 352 | neighbors.push(n); 353 | } 354 | } 355 | //East 356 | if (x < this._tilemap.width-1) { 357 | n = map[y][x+1].properties.astarNode; 358 | if (n.walkable) { 359 | n.travelCost = Phaser.Plugin.AStar.COST_ORTHOGONAL; 360 | neighbors.push(n); 361 | } 362 | } 363 | //North 364 | if (y > 0) { 365 | n = map[y-1][x].properties.astarNode; 366 | if (n.walkable) { 367 | n.travelCost = Phaser.Plugin.AStar.COST_ORTHOGONAL; 368 | neighbors.push(n); 369 | } 370 | } 371 | //South 372 | if (y < this._tilemap.height-1) { 373 | n = map[y+1][x].properties.astarNode; 374 | if (n.walkable) { 375 | n.travelCost = Phaser.Plugin.AStar.COST_ORTHOGONAL; 376 | neighbors.push(n); 377 | } 378 | } 379 | 380 | //If diagonals aren't used do not search for other neighbors and return orthogonal search result 381 | if(this._useDiagonal === false) 382 | return neighbors; 383 | 384 | //NorthWest 385 | if (x > 0 && y > 0) { 386 | n = map[y-1][x-1].properties.astarNode; 387 | if (n.walkable 388 | && map[y][x-1].properties.astarNode.walkable 389 | && map[y-1][x].properties.astarNode.walkable 390 | ) { 391 | n.travelCost = Phaser.Plugin.AStar.COST_DIAGONAL; 392 | neighbors.push(n); 393 | } 394 | } 395 | //NorthEast 396 | if (x < this._tilemap.width-1 && y > 0) { 397 | n = map[y-1][x+1].properties.astarNode; 398 | if (n.walkable 399 | && map[y][x+1].properties.astarNode.walkable 400 | && map[y-1][x].properties.astarNode.walkable 401 | ) { 402 | n.travelCost = Phaser.Plugin.AStar.COST_DIAGONAL; 403 | neighbors.push(n); 404 | } 405 | } 406 | //SouthWest 407 | if (x > 0 && y < this._tilemap.height-1) { 408 | n = map[y+1][x-1].properties.astarNode; 409 | if (n.walkable 410 | && map[y][x-1].properties.astarNode.walkable 411 | && map[y+1][x].properties.astarNode.walkable 412 | ) { 413 | n.travelCost = Phaser.Plugin.AStar.COST_DIAGONAL; 414 | neighbors.push(n); 415 | } 416 | } 417 | //SouthEast 418 | if (x < this._tilemap.width-1 && y < this._tilemap.height-1) { 419 | n = map[y+1][x+1].properties.astarNode; 420 | if (n.walkable 421 | && map[y][x+1].properties.astarNode.walkable 422 | && map[y+1][x].properties.astarNode.walkable 423 | ) { 424 | n.travelCost = Phaser.Plugin.AStar.COST_DIAGONAL; 425 | neighbors.push(n); 426 | } 427 | } 428 | 429 | return neighbors; 430 | }; 431 | 432 | 433 | /** 434 | * Calculate a distance between tow astar nodes coordinates according to the Manhattan method 435 | * @method Phaser.Plugin.AStar-distManhattan 436 | * @private 437 | * @param {Phaser.Plugin.AStar.AStarNode} nodeA - The A node. 438 | * @param {Phaser.Plugin.AStar.AStarNode} nodeB - The B node. 439 | * @return {number} The distance between nodeA and nodeB 440 | */ 441 | Phaser.Plugin.AStar.prototype.distManhattan = function (nodeA, nodeB) 442 | { 443 | return Math.abs(nodeA.x - nodeB.x) + Math.abs(nodeA.y - nodeB.y); 444 | }; 445 | 446 | /** 447 | * Calculate a distance between tow astar nodes coordinates according to the Euclidian method. More accurate 448 | * @method Phaser.Plugin.AStar-distEuclidian 449 | * @private 450 | * @param {Phaser.Plugin.AStar.AStarNode} nodeA - The A node. 451 | * @param {Phaser.Plugin.AStar.AStarNode} nodeB - The B node. 452 | * @return {number} The distance between nodeA and nodeB 453 | */ 454 | Phaser.Plugin.AStar.prototype.distEuclidian = function(nodeA, nodeB) 455 | { 456 | return Math.sqrt(Math.pow((nodeA.x - nodeB.x), 2) + Math.pow((nodeA.y -nodeB.y), 2)); 457 | }; 458 | 459 | 460 | /** 461 | * Tells if a tile is walkable from its tilemap coordinates 462 | * @method Phaser.Plugin.AStar-isWalkable 463 | * @public 464 | * @param {number} x - The x coordiante of the tile in tilemap's coordinate. 465 | * @param {number} y - The y coordinate of the tile in tilemap's coordinate. 466 | * @return {boolean} The distance between nodeA and nodeB 467 | */ 468 | Phaser.Plugin.AStar.prototype.isWalkable = function(x, y) 469 | { 470 | return this._tilemap.layers[this._layerIndex].data[y][x].properties.astarNode.walkable; 471 | }; 472 | 473 | 474 | /** 475 | * @properties {string} version - The version number of Phaser.Plugin.AStar read only 476 | */ 477 | Object.defineProperty(Phaser.Plugin.AStar.prototype, "version", { 478 | 479 | get: function () { 480 | return Phaser.Plugin.AStar.VERSION; 481 | } 482 | 483 | }); 484 | 485 | 486 | /** 487 | * AStarNode is an object that stores AStar value. Each tile have an AStarNode in their properties 488 | * @class Phaser.Plugin.AStar.AStarNode 489 | * @constructor 490 | * @param {number} x - The x coordinate of the tile. 491 | * @param {number} y - The y coordinate of the tile. 492 | * @param {boolean} isWalkable - Is this tile is walkable? 493 | */ 494 | Phaser.Plugin.AStar.AStarNode = function(x, y, isWalkable) 495 | { 496 | 497 | /** 498 | * @property {number} x - The x coordinate of the tile. 499 | */ 500 | this.x = x; 501 | 502 | /** 503 | * @property {number} y - The y coordinate of the tile. 504 | */ 505 | this.y = y; 506 | 507 | /** 508 | * @property {number} g - The total travel cost from the start point. Sum of COST_ORTHOGONAL and COST_DIAGONAL 509 | */ 510 | this.g = 0; 511 | 512 | /** 513 | * @property {number} h - The remaing distance as the crow flies between this node and the goal. 514 | */ 515 | this.h = 0; 516 | 517 | /** 518 | * @property {number} f - The weight. Sum of g + h. 519 | */ 520 | this.f = 0; 521 | 522 | /** 523 | * @property {Phaser.Plugin.AStar.AStarNode} parent - Where do we come from? It's an AStarNode reference needed to reconstruct a path backwards (from goal to start point) 524 | */ 525 | this.parent; 526 | 527 | /** 528 | * @property {boolean} walkable - Is this node is walkable? 529 | */ 530 | this.walkable = isWalkable; 531 | 532 | /** 533 | * @property {number} travelCost - The cost to travel to this node, COST_ORTHOGONAL or COST_DIAGONAL 534 | */ 535 | this.travelCost; 536 | }; 537 | 538 | 539 | /** 540 | * AStarPath is an object that stores a searchPath result. 541 | * @class Phaser.Plugin.AStar.AStarPath 542 | * @constructor 543 | * @param {array} nodes - An array of nodes coordinates sorted backward from goal to start point. 544 | * @param {Phaser.Plugin.AStarNode} start - The start AStarNode used for the searchPath. 545 | * @param {Phaser.Plugin.AStarNode} goal - The goal AStarNode used for the searchPath. 546 | */ 547 | Phaser.Plugin.AStar.AStarPath = function(nodes, start, goal) 548 | { 549 | /** 550 | * @property {array} nodes - Array of AstarNodes x, y coordiantes that are the path solution from goal to start point. 551 | */ 552 | this.nodes = nodes || []; 553 | 554 | /** 555 | * @property {Phaser.Plugin.Astar.AStarNode} start - Reference to the start point used by findPath. 556 | */ 557 | this.start = start || null; 558 | 559 | /** 560 | * @property {Phaser.Plugin.Astar.AStarNode} goal - Reference to the goal point used by findPath. 561 | */ 562 | this.goal = goal || null; 563 | 564 | /** 565 | * @property {array} visited - Array of AStarNodes that the findPath algorythm has visited. Used for debug only. 566 | */ 567 | this.visited = []; 568 | }; 569 | 570 | 571 | /** 572 | * Debug method to draw the last calculated path by AStar 573 | * @method Phaser.Utils.Debug.AStar 574 | * @param {Phaser.Plugin.AStar} astar- The AStar plugin that you want to debug. 575 | * @param {number} x - X position on camera for debug display. 576 | * @param {number} y - Y position on camera for debug display. 577 | * @param {string} color - Color to stroke the path line. 578 | * @return {void} 579 | */ 580 | Phaser.Utils.Debug.prototype.AStar = function(astar, x, y, color, showVisited) 581 | { 582 | if (this.context == null) 583 | { 584 | return; 585 | } 586 | 587 | var pathLength = 0; 588 | if(astar._lastPath !== null) 589 | { 590 | pathLength = astar._lastPath.nodes.length; 591 | } 592 | 593 | color = color || 'rgb(255,255,255)'; 594 | 595 | game.debug.start(x, y, color); 596 | 597 | 598 | if(pathLength > 0) 599 | { 600 | var node = astar._lastPath.nodes[0]; 601 | this.context.strokeStyle = color; 602 | this.context.beginPath(); 603 | this.context.moveTo((node.x * astar._tilemap.tileWidth) + (astar._tilemap.tileWidth/2) - game.camera.view.x, (node.y * astar._tilemap.tileHeight) + (astar._tilemap.tileHeight/2) - game.camera.view.y); 604 | 605 | for(var i=0; i 7 | * @copyright 2013 Photon Storm Ltd. 8 | * @license https://github.com/photonstorm/phaser/blob/master/license.txt MIT License 9 | * @module Phaser 10 | */ 11 | 12 | Phaser.Plugins.ColorHarmony.prototype = { 13 | 14 | /** 15 | * Returns a Complementary Color Harmony for the given color. 16 | *

A complementary hue is one directly opposite the color given on the color wheel

17 | *

Value returned in 0xAARRGGBB format with Alpha set to 255.

18 | * 19 | * @method getComplementHarmony 20 | * @param {Number} color The color to base the harmony on. 21 | * @return {Number} 0xAARRGGBB format color value. 22 | */ 23 | getComplementHarmony: function (color) { 24 | 25 | var hsv = Phaser.Color.RGBtoHSV(color); 26 | var opposite = Phaser.Color.game.math.wrapValue(hsv.hue, 180, 359); 27 | return Phaser.Color.HSVtoRGB(opposite, 1.0, 1.0); 28 | 29 | }, 30 | 31 | /** 32 | * Returns an Analogous Color Harmony for the given color. 33 | *

An Analogous harmony are hues adjacent to each other on the color wheel

34 | *

Values returned in 0xAARRGGBB format with Alpha set to 255.

35 | * 36 | * @method getAnalogousHarmony 37 | * @param {Number} color The color to base the harmony on. 38 | * @param {Number} threshold Control how adjacent the colors will be (default +- 30 degrees) 39 | * @return {Object} Object containing 3 properties: color1 (the original color), color2 (the warmer analogous color) and color3 (the colder analogous color) 40 | */ 41 | getAnalogousHarmony: function (color, threshold) { 42 | if (typeof threshold === "undefined") { threshold = 30; } 43 | var hsv = Phaser.Color.RGBtoHSV(color); 44 | if(threshold > 359 || threshold < 0) { 45 | throw new Error("Color Warning: Invalid threshold given to getAnalogousHarmony()"); 46 | } 47 | var warmer = Phaser.Color.game.math.wrapValue(hsv.hue, 359 - threshold, 359); 48 | var colder = Phaser.Color.game.math.wrapValue(hsv.hue, threshold, 359); 49 | return { 50 | color1: color, 51 | color2: Phaser.Color.HSVtoRGB(warmer, 1.0, 1.0), 52 | color3: Phaser.Color.HSVtoRGB(colder, 1.0, 1.0), 53 | hue1: hsv.hue, 54 | hue2: warmer, 55 | hue3: colder 56 | }; 57 | }, 58 | 59 | /** 60 | * Returns an Split Complement Color Harmony for the given color. 61 | *

A Split Complement harmony are the two hues on either side of the color's Complement

62 | *

Values returned in 0xAARRGGBB format with Alpha set to 255.

63 | * 64 | * @method getSplitComplementHarmony 65 | * @param {Number} color The color to base the harmony on 66 | * @param {Number} threshold Control how adjacent the colors will be to the Complement (default +- 30 degrees) 67 | * @return {Object} An object containing 3 properties: color1 (the original color), color2 (the warmer analogous color) and color3 (the colder analogous color) 68 | */ 69 | getSplitComplementHarmony: function (color, threshold) { 70 | if (typeof threshold === "undefined") { threshold = 30; } 71 | var hsv = Phaser.Color.RGBtoHSV(color); 72 | if(threshold >= 359 || threshold <= 0) { 73 | throw new Error("Phaser.Color Warning: Invalid threshold given to getSplitComplementHarmony()"); 74 | } 75 | var opposite = Phaser.Color.game.math.wrapValue(hsv.hue, 180, 359); 76 | var warmer = Phaser.Color.game.math.wrapValue(hsv.hue, opposite - threshold, 359); 77 | var colder = Phaser.Color.game.math.wrapValue(hsv.hue, opposite + threshold, 359); 78 | return { 79 | color1: color, 80 | color2: Phaser.Color.HSVtoRGB(warmer, hsv.saturation, hsv.value), 81 | color3: Phaser.Color.HSVtoRGB(colder, hsv.saturation, hsv.value), 82 | hue1: hsv.hue, 83 | hue2: warmer, 84 | hue3: colder 85 | }; 86 | }, 87 | 88 | /** 89 | * Returns a Triadic Color Harmony for the given color. 90 | *

A Triadic harmony are 3 hues equidistant from each other on the color wheel

91 | *

Values returned in 0xAARRGGBB format with Alpha set to 255.

92 | * 93 | * @method getTriadicHarmony 94 | * @param {Number} color The color to base the harmony on. 95 | * @return {Object} An Object containing 3 properties: color1 (the original color), color2 and color3 (the equidistant colors) 96 | */ 97 | getTriadicHarmony: function (color) { 98 | var hsv = Phaser.Color.RGBtoHSV(color); 99 | var triadic1 = Phaser.Color.game.math.wrapValue(hsv.hue, 120, 359); 100 | var triadic2 = Phaser.Color.game.math.wrapValue(triadic1, 120, 359); 101 | return { 102 | color1: color, 103 | color2: Phaser.Color.HSVtoRGB(triadic1, 1.0, 1.0), 104 | color3: Phaser.Color.HSVtoRGB(triadic2, 1.0, 1.0) 105 | }; 106 | }, 107 | 108 | /** 109 | * Get HSV color wheel values in an array which will be 360 elements in size. 110 | * 111 | * @method getHSVColorWheel 112 | * @param {Number} alpha Alpha value for each color of the color wheel, between 0 (transparent) and 255 (opaque) 113 | * @return {Array} An array containing 360 elements corresponding to the HSV color wheel. 114 | */ 115 | getHSVColorWheel: function (alpha) { 116 | 117 | alpha = alpha || 255; 118 | 119 | var colors = []; 120 | 121 | for (var c = 0; c <= 359; c++) 122 | { 123 | colors[c] = Phaser.Color.getWebRGB(Phaser.Color.HSVtoRGB(c, 1.0, 1.0, alpha)); 124 | } 125 | 126 | return colors; 127 | }, 128 | 129 | /** 130 | * Convert a HSV (hue, saturation, lightness) color space value to an RGB color 131 | * 132 | * @method HSVtoRGB 133 | * @param {Number} h Hue degree, between 0 and 359 134 | * @param {Number} s Saturation, between 0.0 (grey) and 1.0 135 | * @param {Number} v Value, between 0.0 (black) and 1.0 136 | * @param {Number} alpha Alpha value to set per color (between 0 and 255) 137 | * @return {Number} 32-bit ARGB color value (0xAARRGGBB) 138 | */ 139 | HSVtoRGB: function (h, s, v, alpha) { 140 | if (typeof alpha === "undefined") { alpha = 255; } 141 | var result; 142 | if(s === 0.0) { 143 | result = Phaser.Color.getColor32(alpha, v * 255, v * 255, v * 255); 144 | } else { 145 | h = h / 60.0; 146 | var f = h - Math.floor(h); 147 | var p = v * (1.0 - s); 148 | var q = v * (1.0 - s * f); 149 | var t = v * (1.0 - s * (1.0 - f)); 150 | switch(Math.floor(h)) { 151 | case 0: 152 | result = Phaser.Color.getColor32(alpha, v * 255, t * 255, p * 255); 153 | break; 154 | case 1: 155 | result = Phaser.Color.getColor32(alpha, q * 255, v * 255, p * 255); 156 | break; 157 | case 2: 158 | result = Phaser.Color.getColor32(alpha, p * 255, v * 255, t * 255); 159 | break; 160 | case 3: 161 | result = Phaser.Color.getColor32(alpha, p * 255, q * 255, v * 255); 162 | break; 163 | case 4: 164 | result = Phaser.Color.getColor32(alpha, t * 255, p * 255, v * 255); 165 | break; 166 | case 5: 167 | result = Phaser.Color.getColor32(alpha, v * 255, p * 255, q * 255); 168 | break; 169 | default: 170 | throw new Error("Phaser.Color.HSVtoRGB : Unknown color"); 171 | } 172 | } 173 | return result; 174 | }, 175 | 176 | /** 177 | * Convert an RGB color value to an object containing the HSV color space values: Hue, Saturation and Lightness 178 | * 179 | * @method RGBtoHSV 180 | * @param {Number} color In format 0xRRGGBB 181 | * @return {Object} An Object with the properties hue (from 0 to 360), saturation (from 0 to 1.0) and lightness (from 0 to 1.0, also available under .value) 182 | */ 183 | RGBtoHSV: function (color) { 184 | var rgb = Phaser.Color.getRGB(color); 185 | var red = rgb.red / 255; 186 | var green = rgb.green / 255; 187 | var blue = rgb.blue / 255; 188 | var min = Math.min(red, green, blue); 189 | var max = Math.max(red, green, blue); 190 | var delta = max - min; 191 | var lightness = (max + min) / 2; 192 | var hue; 193 | var saturation; 194 | // Grey color, no chroma 195 | if(delta === 0) { 196 | hue = 0; 197 | saturation = 0; 198 | } else { 199 | if(lightness < 0.5) { 200 | saturation = delta / (max + min); 201 | } else { 202 | saturation = delta / (2 - max - min); 203 | } 204 | var delta_r = (((max - red) / 6) + (delta / 2)) / delta; 205 | var delta_g = (((max - green) / 6) + (delta / 2)) / delta; 206 | var delta_b = (((max - blue) / 6) + (delta / 2)) / delta; 207 | if(red == max) { 208 | hue = delta_b - delta_g; 209 | } else if(green == max) { 210 | hue = (1 / 3) + delta_r - delta_b; 211 | } else if(blue == max) { 212 | hue = (2 / 3) + delta_g - delta_r; 213 | } 214 | if(hue < 0) { 215 | hue += 1; 216 | } 217 | if(hue > 1) { 218 | hue -= 1; 219 | } 220 | } 221 | // Keep the value with 0 to 359 222 | hue *= 360; 223 | hue = Math.round(hue); 224 | return { 225 | hue: hue, 226 | saturation: saturation, 227 | lightness: lightness, 228 | value: lightness 229 | }; 230 | } 231 | 232 | }; 233 | -------------------------------------------------------------------------------- /bower_components/phaser-official/plugins/ProTracker.js: -------------------------------------------------------------------------------- 1 | /* jshint asi:true,camelcase:false,curly:false,indent:2,unused:false */ 2 | /* 3 | amiga protracker module player for web audio api 4 | (c) 2012-2013 firehawk/tda (firehawk@haxor.fi) 5 | 6 | originally hacked together in a weekend, so please excuse 7 | me for the spaghetti code. :) 8 | 9 | AMIGAAAAAAAAH!! 10 | 11 | kinda sorta changelog: 12 | (apr 2013) 13 | - changed the logic for pattern break/jump. mod.pattern_skank now 14 | plays correctly. 15 | (feb 2013) 16 | - fixed NaN samples with mod.fractured and mod.multicolour (thanks Aegis!) 17 | (jan 2013) 18 | - fixed vibrato amplitude (was half of what it should be, apparently) 19 | - fixed to work on safari again (thanks Matt Diamond @ stackoverflow.com) 20 | (dec 2012) 21 | - replaced effect switch-statement with jumptables 22 | - fixed clicks (bad loops, empty samples) 23 | - fixed playback bug with sample-only rows 24 | - added amiga 500 lowpass filters (not 100% authentic, though) 25 | - added compressor to output 26 | - latest safari has broken web audio so chrome-only for now 27 | (aug 2012) 28 | - first version written from scratch 29 | 30 | todo: 31 | - safari on ipad is broken again, it seems 32 | - fix more playback bugs 33 | * mod.black_queen (pattern loop has glitches) 34 | - properly test EEx delay pattern 35 | - implement the rest of the effects 36 | - optimize for more speed!! SPEEEED!! 37 | * switch to fixed point sample pointers, Math.floor() is _slow_ on iOS 38 | */ 39 | 40 | // constructor for protracker player object 41 | function Protracker() 42 | { 43 | var i, t; 44 | 45 | this.initialize(); 46 | this.clearsong(); 47 | 48 | this.url=""; 49 | this.loading=false; 50 | this.ready=false; 51 | this.playing=false; 52 | this.buffer=0; 53 | this.mixerNode=0; 54 | this.paused=false; 55 | this.repeat=false; 56 | this.separation=true; 57 | 58 | this.palclock=true; 59 | 60 | this.autostart=false; 61 | 62 | this.onReady=function(){}; 63 | this.onPlay=function(){}; 64 | this.onStop=function(){}; 65 | 66 | // paula period values 67 | this.baseperiodtable=new Array( 68 | 856,808,762,720,678,640,604,570,538,508,480,453, 69 | 428,404,381,360,339,320,302,285,269,254,240,226, 70 | 214,202,190,180,170,160,151,143,135,127,120,113); 71 | 72 | // finetune multipliers 73 | this.finetunetable=[]; 74 | for(t=0;t<16;t++) this.finetunetable[t]=Math.pow(2, (t-8)/12/8); 75 | 76 | // calc tables for vibrato waveforms 77 | this.vibratotable=[]; 78 | for(t=0;t<4;t++) { 79 | this.vibratotable[t]=[]; 80 | for(var i=0;i<64;i++) { 81 | switch(t) { 82 | case 0: 83 | this.vibratotable[t][i]=127*Math.sin(Math.PI*2*(i/64)); 84 | break; 85 | case 1: 86 | this.vibratotable[t][i]=127-4*i; 87 | break; 88 | case 2: 89 | this.vibratotable[t][i]=(i<32)?127:-127; 90 | break; 91 | case 3: 92 | this.vibratotable[t][i]=(1-2*Math.random())*127; 93 | break; 94 | } 95 | } 96 | } 97 | 98 | // effect jumptables 99 | this.effects_t0 = new Array( 100 | this.effect_t0_0, this.effect_t0_1, this.effect_t0_2, this.effect_t0_3, this.effect_t0_4, this.effect_t0_5, this.effect_t0_6, this.effect_t0_7, 101 | this.effect_t0_8, this.effect_t0_9, this.effect_t0_a, this.effect_t0_b, this.effect_t0_c, this.effect_t0_d, this.effect_t0_e, this.effect_t0_f); 102 | this.effects_t0_e = new Array( 103 | this.effect_t0_e0, this.effect_t0_e1, this.effect_t0_e2, this.effect_t0_e3, this.effect_t0_e4, this.effect_t0_e5, this.effect_t0_e6, this.effect_t0_e7, 104 | this.effect_t0_e8, this.effect_t0_e9, this.effect_t0_ea, this.effect_t0_eb, this.effect_t0_ec, this.effect_t0_ed, this.effect_t0_ee, this.effect_t0_ef); 105 | this.effects_t1 = new Array( 106 | this.effect_t1_0, this.effect_t1_1, this.effect_t1_2, this.effect_t1_3, this.effect_t1_4, this.effect_t1_5, this.effect_t1_6, this.effect_t1_7, 107 | this.effect_t1_8, this.effect_t1_9, this.effect_t1_a, this.effect_t1_b, this.effect_t1_c, this.effect_t1_d, this.effect_t1_e, this.effect_t1_f); 108 | this.effects_t1_e = new Array( 109 | this.effect_t1_e0, this.effect_t1_e1, this.effect_t1_e2, this.effect_t1_e3, this.effect_t1_e4, this.effect_t1_e5, this.effect_t1_e6, this.effect_t1_e7, 110 | this.effect_t1_e8, this.effect_t1_e9, this.effect_t1_ea, this.effect_t1_eb, this.effect_t1_ec, this.effect_t1_ed, this.effect_t1_ee, this.effect_t1_ef); 111 | 112 | this.context = null; 113 | this.samplerate=44100; 114 | this.bufferlen=2048; 115 | } 116 | 117 | 118 | 119 | // create the web audio context 120 | Protracker.prototype.createContext = function() 121 | { 122 | /* global webkitAudioContext:false */ 123 | /* jshint newcap:false */ 124 | this.context = new webkitAudioContext(); 125 | this.samplerate=this.context.sampleRate; 126 | this.bufferlen=(this.samplerate > 44100) ? 4096 : 2048; 127 | 128 | // fixed filter at 6kHz 129 | this.filterNode=this.context.createBiquadFilter(); 130 | this.filterNode.frequency.value=6000 131 | 132 | // "LED filter" at 3.5kHz - off by default 133 | this.lowpassNode=this.context.createBiquadFilter(); 134 | this.lowpassNode.frequency.value=28867; 135 | 136 | // mixer 137 | this.mixerNode=this.context.createJavaScriptNode(this.bufferlen, 1, 2); 138 | this.mixerNode.module=this; 139 | this.mixerNode.onaudioprocess=Protracker.prototype.mix; 140 | 141 | // compressor for a bit of volume boost 142 | this.compressorNode=this.context.createDynamicsCompressor(); 143 | 144 | // patch up some cables :) 145 | this.mixerNode.connect(this.filterNode); 146 | this.filterNode.connect(this.lowpassNode); 147 | this.lowpassNode.connect(this.compressorNode); 148 | this.compressorNode.connect(this.context.destination); 149 | } 150 | 151 | 152 | 153 | // play loaded and parsed module with webaudio context 154 | Protracker.prototype.play = function() 155 | { 156 | if (this.context==null) this.createContext(); 157 | 158 | if (!this.ready) return false; 159 | if (this.paused) { 160 | this.paused=false; 161 | return true; 162 | } 163 | this.paused=false; 164 | this.initialize(); 165 | this.flags=1+2; 166 | this.playing=true; 167 | this.onPlay(); 168 | return true; 169 | } 170 | 171 | 172 | 173 | // pause playback 174 | Protracker.prototype.pause = function() 175 | { 176 | if (!this.paused) { 177 | this.paused=true; 178 | } else { 179 | this.paused=false; 180 | } 181 | } 182 | 183 | 184 | 185 | // stop playback and release webaudio node 186 | Protracker.prototype.stop = function() 187 | { 188 | this.playing=false; 189 | this.onStop(); 190 | } 191 | 192 | 193 | 194 | // jump positions forward/back 195 | Protracker.prototype.jump = function(step) 196 | { 197 | this.tick=0; 198 | this.row=0; 199 | this.position+=step; 200 | this.flags=1+2; 201 | if (this.position<0) this.position=0; 202 | if (this.position >= this.songlen) this.stop(); 203 | } 204 | 205 | 206 | 207 | // set whether module repeats after songlen 208 | Protracker.prototype.setrepeat = function(rep) 209 | { 210 | this.repeat=rep; 211 | } 212 | 213 | 214 | 215 | // set stereo separation mode (false=paula, true=betterpaula) 216 | Protracker.prototype.setseparation = function(sep) 217 | { 218 | this.separation=sep; 219 | } 220 | 221 | 222 | 223 | // set amiga video standard (false=NTSC, true=PAL) 224 | Protracker.prototype.setamigatype = function(clock) 225 | { 226 | this.palclock=clock; 227 | } 228 | 229 | 230 | 231 | // set autostart to play immediately after loading 232 | Protracker.prototype.setautostart = function(st) 233 | { 234 | this.autostart=st; 235 | } 236 | 237 | 238 | 239 | // clear song data 240 | Protracker.prototype.clearsong = function() 241 | { 242 | this.title=""; 243 | this.signature=""; 244 | this.songlen=1; 245 | this.repeatpos=0; 246 | this.patterntable=new ArrayBuffer(128); 247 | for(var i=0;i<128;i++) this.patterntable[i]=0; 248 | 249 | this.channels=4; 250 | 251 | this.sample=[]; 252 | this.samples=31; 253 | for(var i=0;i<31;i++) { 254 | this.sample[i]={}; 255 | this.sample[i].name=""; 256 | this.sample[i].length=0; 257 | this.sample[i].finetune=0; 258 | this.sample[i].volume=64; 259 | this.sample[i].loopstart=0; 260 | this.sample[i].looplength=0; 261 | this.sample[i].data=0; 262 | } 263 | 264 | this.patterns=0; 265 | this.pattern=[]; 266 | this.note=[]; 267 | 268 | this.looprow=0; 269 | this.loopstart=0; 270 | this.loopcount=0; 271 | 272 | this.patterndelay=0; 273 | this.patternwait=0; 274 | } 275 | 276 | 277 | // initialize all player variables 278 | Protracker.prototype.initialize = function() 279 | { 280 | this.tick=0; 281 | this.position=0; 282 | this.row=0; 283 | this.offset=0; 284 | this.flags=0; 285 | 286 | this.speed=6; 287 | this.bpm=125; 288 | this.breakrow=0; 289 | this.patternjump=0; 290 | this.patterndelay=0; 291 | this.patternwait=0; 292 | 293 | this.channel=[]; 294 | for(var i=0;i0x1f) && (this.buffer[st+j]<0x7f)) ? 389 | (String.fromCharCode(this.buffer[st+j])) : 390 | (" "); 391 | j++; 392 | } 393 | this.sample[i].length=2*(this.buffer[st+22]*256 + this.buffer[st+23]); 394 | this.sample[i].finetune=this.buffer[st+24]; 395 | if (this.sample[i].finetune > 7) this.sample[i].finetune=this.sample[i].finetune-16; 396 | this.sample[i].volume=this.buffer[st+25]; 397 | this.sample[i].loopstart=2*(this.buffer[st+26]*256 + this.buffer[st+27]); 398 | this.sample[i].looplength=2*(this.buffer[st+28]*256 + this.buffer[st+29]); 399 | if (this.sample[i].looplength==2) this.sample[i].looplength=0; 400 | if (this.sample[i].loopstart>this.sample[i].length) { 401 | this.sample[i].loopstart=0; 402 | this.sample[i].looplength=0; 403 | } 404 | } 405 | 406 | this.songlen=this.buffer[950]; 407 | if (this.buffer[951] != 127) this.repeatpos=this.buffer[951]; 408 | for(var i=0;i<128;i++) { 409 | this.patterntable[i]=this.buffer[952+i]; 410 | if (this.patterntable[i] > this.patterns) this.patterns=this.patterntable[i]; 411 | } 412 | this.patterns+=1; 413 | var patlen=4*64*this.channels; 414 | 415 | this.pattern=[]; 416 | this.note=[]; 417 | for(var i=0;ispd) { mod.tick++; mod.offset=0; mod.flags|=1; } 465 | if (mod.tick>=mod.speed) { 466 | 467 | if (mod.patterndelay) { // delay pattern 468 | if (mod.tick < ((mod.patternwait+1)*mod.speed)) { 469 | mod.patternwait++; 470 | } else { 471 | mod.row++; 472 | mod.tick=0; 473 | mod.flags|=2; 474 | mod.patterndelay=0; 475 | } 476 | } 477 | else { 478 | 479 | if (mod.flags&(16+32+64)) { 480 | if (mod.flags&64) { // loop pattern? 481 | mod.row=mod.looprow; 482 | mod.flags&=0xa1; 483 | mod.flags|=2; 484 | } 485 | else { 486 | if (mod.flags&16) { // pattern jump/break? 487 | //console.log("break to pattern " + mod.patternjump + " row "+mod.breakrow); 488 | mod.position=mod.patternjump; 489 | mod.row=mod.breakrow; 490 | mod.patternjump=0; 491 | mod.breakrow=0; 492 | mod.flags&=0xe1; 493 | mod.flags|=2; 494 | } 495 | } 496 | mod.tick=0; 497 | } else { 498 | mod.row++; 499 | mod.tick=0; 500 | mod.flags|=2; 501 | } 502 | } 503 | } 504 | 505 | if (mod.row>=64) { 506 | mod.position++; 507 | mod.row=0; 508 | mod.flags|=4; 509 | } 510 | if (mod.position>=mod.songlen) { 511 | if (mod.repeat) { 512 | mod.position=0; 513 | } else { 514 | mod.stop(); 515 | } 516 | return; 517 | } 518 | } 519 | 520 | 521 | 522 | // mix an audio buffer with data 523 | Protracker.prototype.mix = function(ape) { 524 | var f; 525 | var p, pp, n, nn; 526 | var mod=ape.srcElement.module; 527 | var outp=[]; 528 | 529 | var bufs=new Array(ape.outputBuffer.getChannelData(0), ape.outputBuffer.getChannelData(1)); 530 | var buflen=ape.outputBuffer.length; 531 | for(var s=0;s3) mod.channel[ch].vibratopos=0; 559 | mod.channel[ch].flags|=3; // recalc speed 560 | mod.channel[ch].noteon=1; 561 | } else { 562 | mod.channel[ch].slideto=n; 563 | 564 | } 565 | } 566 | nn=mod.pattern[p][pp+0]&0xf0 | mod.pattern[p][pp+2]>>4; 567 | if (nn) { 568 | mod.channel[ch].sample=nn-1; 569 | 570 | mod.channel[ch].volume=mod.sample[nn-1].volume; 571 | if (!n && (mod.channel[ch].samplepos > mod.sample[nn-1].length)) mod.channel[ch].samplepos=0; 572 | } 573 | } 574 | } 575 | mod.channel[ch].voiceperiod=mod.channel[ch].period; 576 | if (mod.channel[ch].samplepos===0) mod.sample[ch]=mod.channel[ch].sample; 577 | 578 | 579 | // kill empty samples 580 | if (!mod.sample[mod.channel[ch].sample].length) mod.channel[ch].noteon=0; 581 | 582 | // effects 583 | if (mod.flags&1) { 584 | if (!mod.tick) { 585 | // process only on tick 0 586 | mod.effects_t0[mod.channel[ch].command](mod, ch); 587 | } else { 588 | mod.effects_t1[mod.channel[ch].command](mod, ch); 589 | } 590 | } 591 | 592 | // recalc note number from period 593 | if (mod.channel[ch].flags&2) { 594 | for(var np=0; np=mod.channel[ch].period) mod.channel[ch].note=np; 596 | mod.channel[ch].semitone=7; 597 | if (mod.channel[ch].period>=120) 598 | mod.channel[ch].semitone=mod.baseperiodtable[mod.channel[ch].note]-mod.baseperiodtable[mod.channel[ch].note+1]; 599 | } 600 | 601 | // recalc sample speed and apply finetune 602 | if ((mod.channel[ch].flags&1 || mod.flags&2) && mod.channel[ch].voiceperiod) 603 | mod.channel[ch].samplespeed= 604 | (mod.palclock ? 7093789.2 : 7159090.5)/(mod.channel[ch].voiceperiod*2) * mod.finetunetable[mod.sample[mod.channel[ch].sample].finetune+8] / mod.samplerate; 605 | 606 | // advance vibrato on each new tick 607 | if (mod.flags&1) { 608 | mod.channel[ch].vibratopos+=mod.channel[ch].vibratospeed; 609 | mod.channel[ch].vibratopos&=0x3f; 610 | } 611 | 612 | // mix channel to output 613 | och=och^(ch&1); 614 | f=0.0; 615 | if (mod.channel[ch].noteon) { 616 | if (mod.sample[mod.channel[ch].sample].length > mod.channel[ch].samplepos) 617 | f=(1.0/mod.channels) * 618 | (mod.sample[mod.channel[ch].sample].data[Math.floor(mod.channel[ch].samplepos)]*mod.channel[ch].volume)/64.0; 619 | outp[och]+=f; 620 | mod.channel[ch].samplepos+=mod.channel[ch].samplespeed; 621 | } 622 | if (s===0) mod.vu[ch]=Math.abs(f); 623 | 624 | // loop or end samples 625 | if (mod.channel[ch].noteon) { 626 | if (mod.sample[mod.channel[ch].sample].loopstart || mod.sample[mod.channel[ch].sample].looplength) { 627 | if (mod.channel[ch].samplepos >= (mod.sample[mod.channel[ch].sample].loopstart+mod.sample[mod.channel[ch].sample].looplength)) { 628 | mod.channel[ch].samplepos=mod.sample[mod.channel[ch].sample].loopstart; 629 | } 630 | } else { 631 | if (mod.channel[ch].samplepos >= mod.sample[mod.channel[ch].sample].length) { 632 | mod.channel[ch].noteon=0; 633 | } 634 | } 635 | } 636 | 637 | // clear channel flags 638 | mod.channel[ch].flags=0; 639 | } 640 | mod.offset++; 641 | mod.flags&=0x70; 642 | } 643 | 644 | // a more headphone-friendly stereo separation (aka. betterpaula) 645 | if (mod.separation) { 646 | var t=outp[0]; 647 | outp[0]=outp[0]*0.6 + outp[1]*0.4; 648 | outp[1]=outp[1]*0.6 + t*0.4; 649 | } 650 | bufs[0][s]=outp[0]; 651 | bufs[1][s]=outp[1]; 652 | } 653 | } 654 | 655 | 656 | 657 | // 658 | // tick 0 effect functions 659 | // 660 | Protracker.prototype.effect_t0_0=function(mod, ch) { // 0 arpeggio 661 | mod.channel[ch].arpeggio=mod.channel[ch].data; 662 | } 663 | Protracker.prototype.effect_t0_1=function(mod, ch) { // 1 slide up 664 | if (mod.channel[ch].data) mod.channel[ch].slidespeed=mod.channel[ch].data; 665 | } 666 | Protracker.prototype.effect_t0_2=function(mod, ch) { // 2 slide down 667 | if (mod.channel[ch].data) mod.channel[ch].slidespeed=mod.channel[ch].data; 668 | } 669 | Protracker.prototype.effect_t0_3=function(mod, ch) { // 3 slide to note 670 | if (mod.channel[ch].data) mod.channel[ch].slidetospeed=mod.channel[ch].data; 671 | } 672 | Protracker.prototype.effect_t0_4=function(mod, ch) { // 4 vibrato 673 | if (mod.channel[ch].data&0x0f && mod.channel[ch].data&0xf0) { 674 | mod.channel[ch].vibratodepth=(mod.channel[ch].data&0x0f); 675 | mod.channel[ch].vibratospeed=(mod.channel[ch].data&0xf0)>>4; 676 | } 677 | mod.channel[ch].voiceperiod+= 678 | (mod.channel[ch].vibratodepth/32)*mod.channel[ch].semitone*(mod.vibratotable[mod.channel[ch].vibratowave&3][mod.channel[ch].vibratopos]/127); 679 | mod.channel[ch].flags|=1; 680 | } 681 | Protracker.prototype.effect_t0_5=function(mod, ch) { // 5 682 | } 683 | Protracker.prototype.effect_t0_6=function(mod, ch) { // 6 684 | } 685 | Protracker.prototype.effect_t0_7=function(mod, ch) { // 7 686 | } 687 | Protracker.prototype.effect_t0_8=function(mod, ch) { // 8 688 | } 689 | Protracker.prototype.effect_t0_9=function(mod, ch) { // 9 set sample offset 690 | mod.channel[ch].samplepos=mod.channel[ch].data*256; 691 | } 692 | Protracker.prototype.effect_t0_a=function(mod, ch) { // a 693 | } 694 | Protracker.prototype.effect_t0_b=function(mod, ch) { // b pattern jump 695 | mod.breakrow=0; 696 | mod.patternjump=mod.channel[ch].data; 697 | mod.flags|=16; 698 | } 699 | Protracker.prototype.effect_t0_c=function(mod, ch) { // c set volume 700 | mod.channel[ch].volume=mod.channel[ch].data; 701 | } 702 | Protracker.prototype.effect_t0_d=function(mod, ch) { // d pattern break 703 | mod.breakrow=((mod.channel[ch].data&0xf0)>>4)*10 + (mod.channel[ch].data&0x0f); 704 | if (!(mod.flags&16)) mod.patternjump=mod.position+1; 705 | mod.flags|=16; 706 | } 707 | Protracker.prototype.effect_t0_e=function(mod, ch) { // e 708 | var i=(mod.channel[ch].data&0xf0)>>4; 709 | mod.effects_t0_e[i](mod, ch); 710 | } 711 | Protracker.prototype.effect_t0_f=function(mod, ch) { // f set speed 712 | if (mod.channel[ch].data > 32) { 713 | mod.bpm=mod.channel[ch].data; 714 | } else { 715 | if (mod.channel[ch].data) mod.speed=mod.channel[ch].data; 716 | } 717 | } 718 | 719 | 720 | 721 | // 722 | // tick 0 effect e functions 723 | // 724 | Protracker.prototype.effect_t0_e0=function(mod, ch) { // e0 filter on/off 725 | if (mod.channel[ch].data&0x0f) { 726 | mod.lowpassNode.frequency.value=4280; //3500; 727 | } else { 728 | mod.lowpassNode.frequency.value=28867; 729 | } 730 | } 731 | Protracker.prototype.effect_t0_e1=function(mod, ch) { // e1 fine slide up 732 | mod.channel[ch].period-=mod.channel[ch].data&0x0f; 733 | if (mod.channel[ch].period < 113) mod.channel[ch].period=113; 734 | } 735 | Protracker.prototype.effect_t0_e2=function(mod, ch) { // e2 fine slide down 736 | mod.channel[ch].period+=mod.channel[ch].data&0x0f; 737 | if (mod.channel[ch].period > 856) mod.channel[ch].period=856; 738 | mod.channel[ch].flags|=1; 739 | } 740 | Protracker.prototype.effect_t0_e3=function(mod, ch) { // e3 set glissando 741 | } 742 | Protracker.prototype.effect_t0_e4=function(mod, ch) { // e4 set vibrato waveform 743 | mod.channel[ch].vibratowave=mod.channel[ch].data&0x07; 744 | } 745 | Protracker.prototype.effect_t0_e5=function(mod, ch) { // e5 set finetune 746 | } 747 | Protracker.prototype.effect_t0_e6=function(mod, ch) { // e6 loop pattern 748 | if (mod.channel[ch].data&0x0f) { 749 | if (mod.loopcount) { 750 | mod.loopcount--; 751 | } else { 752 | mod.loopcount=mod.channel[ch].data&0x0f; 753 | } 754 | if (mod.loopcount) mod.flags|=64; 755 | } else { 756 | mod.looprow=mod.row; 757 | } 758 | } 759 | Protracker.prototype.effect_t0_e7=function(mod, ch) { // e7 760 | } 761 | Protracker.prototype.effect_t0_e8=function(mod, ch) { // e8 762 | } 763 | Protracker.prototype.effect_t0_e9=function(mod, ch) { // e9 764 | } 765 | Protracker.prototype.effect_t0_ea=function(mod, ch) { // ea fine volslide up 766 | mod.channel[ch].volume+=mod.channel[ch].data&0x0f; 767 | if (mod.channel[ch].volume > 64) mod.channel[ch].volume=64; 768 | } 769 | Protracker.prototype.effect_t0_eb=function(mod, ch) { // eb fine volslide down 770 | mod.channel[ch].volume-=mod.channel[ch].data&0x0f; 771 | if (mod.channel[ch].volume < 0) mod.channel[ch].volume=0; 772 | } 773 | Protracker.prototype.effect_t0_ec=function(mod, ch) { // ec 774 | } 775 | Protracker.prototype.effect_t0_ed=function(mod, ch) { // ed delay sample 776 | if (mod.tick==(mod.channel[ch].data&0x0f)) { 777 | // start note 778 | var p=mod.patterntable[mod.position]; 779 | var pp=mod.row*4*mod.channels + ch*4; 780 | var n=(mod.pattern[p][pp]&0x0f)<<8 | mod.pattern[p][pp+1]; 781 | if (n) { 782 | mod.channel[ch].period=n; 783 | mod.channel[ch].voiceperiod=mod.channel[ch].period; 784 | mod.channel[ch].samplepos=0; 785 | if (mod.channel[ch].vibratowave>3) mod.channel[ch].vibratopos=0; 786 | mod.channel[ch].flags|=3; // recalc speed 787 | mod.channel[ch].noteon=1; 788 | } 789 | n=mod.pattern[p][pp+0]&0xf0 | mod.pattern[p][pp+2]>>4; 790 | if (n) { 791 | mod.channel[ch].sample=n-1; 792 | mod.channel[ch].volume=mod.sample[n-1].volume; 793 | } 794 | } 795 | } 796 | Protracker.prototype.effect_t0_ee=function(mod, ch) { // ee delay pattern 797 | mod.patterndelay=mod.channel[ch].data&0x0f; 798 | mod.patternwait=0; 799 | } 800 | Protracker.prototype.effect_t0_ef=function(mod, ch) { // ef 801 | } 802 | 803 | 804 | 805 | // 806 | // tick 1+ effect functions 807 | // 808 | Protracker.prototype.effect_t1_0=function(mod, ch) { // 0 arpeggio 809 | if (mod.channel[ch].data) { 810 | var apn=mod.channel[ch].note; 811 | if ((mod.tick%3)==1) apn+=mod.channel[ch].arpeggio>>4; 812 | if ((mod.tick%3)==2) apn+=mod.channel[ch].arpeggio&0x0f; 813 | if (apn>=0 && apn <= mod.baseperiodtable.length) 814 | mod.channel[ch].voiceperiod = mod.baseperiodtable[apn]; 815 | mod.channel[ch].flags|=1; 816 | } 817 | } 818 | Protracker.prototype.effect_t1_1=function(mod, ch) { // 1 slide up 819 | mod.channel[ch].period-=mod.channel[ch].slidespeed; 820 | if (mod.channel[ch].period<113) mod.channel[ch].period=113; 821 | mod.channel[ch].flags|=3; // recalc speed 822 | } 823 | Protracker.prototype.effect_t1_2=function(mod, ch) { // 2 slide down 824 | mod.channel[ch].period+=mod.channel[ch].slidespeed; 825 | if (mod.channel[ch].period>856) mod.channel[ch].period=856; 826 | mod.channel[ch].flags|=3; // recalc speed 827 | } 828 | Protracker.prototype.effect_t1_3=function(mod, ch) { // 3 slide to note 829 | if (mod.channel[ch].period < mod.channel[ch].slideto) { 830 | mod.channel[ch].period+=mod.channel[ch].slidetospeed; 831 | if (mod.channel[ch].period > mod.channel[ch].slideto) 832 | mod.channel[ch].period=mod.channel[ch].slideto; 833 | } 834 | if (mod.channel[ch].period > mod.channel[ch].slideto) { 835 | mod.channel[ch].period-=mod.channel[ch].slidetospeed; 836 | if (mod.channel[ch].period>4); 864 | if (mod.channel[ch].volume>64) mod.channel[ch].volume=64; 865 | } 866 | if (!(mod.channel[ch].data&0xf0)) { 867 | // x is zero, slide down 868 | mod.channel[ch].volume-=(mod.channel[ch].data&0x0f); 869 | if (mod.channel[ch].volume<0) mod.channel[ch].volume=0; 870 | } 871 | } 872 | Protracker.prototype.effect_t1_b=function(mod, ch) { // b pattern jump 873 | } 874 | Protracker.prototype.effect_t1_c=function(mod, ch) { // c set volume 875 | } 876 | Protracker.prototype.effect_t1_d=function(mod, ch) { // d pattern break 877 | } 878 | Protracker.prototype.effect_t1_e=function(mod, ch) { // e 879 | var i=(mod.channel[ch].data&0xf0)>>4; 880 | mod.effects_t1_e[i](mod, ch); 881 | } 882 | Protracker.prototype.effect_t1_f=function(mod, ch) { // f 883 | } 884 | 885 | 886 | 887 | // 888 | // tick 1+ effect e functions 889 | // 890 | Protracker.prototype.effect_t1_e0=function(mod, ch) { // e0 891 | } 892 | Protracker.prototype.effect_t1_e1=function(mod, ch) { // e1 893 | } 894 | Protracker.prototype.effect_t1_e2=function(mod, ch) { // e2 895 | } 896 | Protracker.prototype.effect_t1_e3=function(mod, ch) { // e3 897 | } 898 | Protracker.prototype.effect_t1_e4=function(mod, ch) { // e4 899 | } 900 | Protracker.prototype.effect_t1_e5=function(mod, ch) { // e5 901 | } 902 | Protracker.prototype.effect_t1_e6=function(mod, ch) { // e6 903 | } 904 | Protracker.prototype.effect_t1_e7=function(mod, ch) { // e7 905 | } 906 | Protracker.prototype.effect_t1_e8=function(mod, ch) { // e8 907 | } 908 | Protracker.prototype.effect_t1_e9=function(mod, ch) { // e9 retrig sample 909 | if (mod.tick%(mod.channel[ch].data&0x0f)===0) 910 | mod.channel[ch].samplepos=0; 911 | } 912 | Protracker.prototype.effect_t1_ea=function(mod, ch) { // ea 913 | } 914 | Protracker.prototype.effect_t1_eb=function(mod, ch) { // eb 915 | } 916 | Protracker.prototype.effect_t1_ec=function(mod, ch) { // ec cut sample 917 | if (mod.tick==(mod.channel[ch].data&0x0f)) 918 | mod.channel[ch].volume=0; 919 | } 920 | Protracker.prototype.effect_t1_ed=function(mod, ch) { // ed delay sample 921 | mod.effect_t0_ed(mod, ch); 922 | } 923 | Protracker.prototype.effect_t1_ee=function(mod, ch) { // ee 924 | } 925 | Protracker.prototype.effect_t1_ef=function(mod, ch) { // ef 926 | } 927 | -------------------------------------------------------------------------------- /bower_components/phaser-official/plugins/QuadTree.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Richard Davey 3 | * @copyright 2014 Photon Storm Ltd. 4 | * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} 5 | */ 6 | 7 | /** 8 | * Javascript QuadTree 9 | * @version 1.0 10 | * @author Timo Hausmann 11 | * 12 | * @version 1.2, September 4th 2013 13 | * @author Richard Davey 14 | * The original code was a conversion of the Java code posted to GameDevTuts. However I've tweaked 15 | * it massively to add node indexing, removed lots of temp. var creation and significantly 16 | * increased performance as a result. 17 | * 18 | * Original version at https://github.com/timohausmann/quadtree-js/ 19 | */ 20 | 21 | /** 22 | * @copyright © 2012 Timo Hausmann 23 | * 24 | * Permission is hereby granted, free of charge, to any person obtaining 25 | * a copy of this software and associated documentation files (the 26 | * "Software"), to deal in the Software without restriction, including 27 | * without limitation the rights to use, copy, modify, merge, publish, 28 | * distribute, sublicense, and/or sell copies of the Software, and to 29 | * permit persons to whom the Software is furnished to do so, subject to 30 | * the following conditions: 31 | * 32 | * The above copyright notice and this permission notice shall be 33 | * included in all copies or substantial portions of the Software. 34 | * 35 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 36 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 37 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 38 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 39 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 40 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 41 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 42 | */ 43 | 44 | /** 45 | * QuadTree Constructor 46 | * 47 | * @class Phaser.QuadTree 48 | * @classdesc A QuadTree implementation. The original code was a conversion of the Java code posted to GameDevTuts. 49 | * However I've tweaked it massively to add node indexing, removed lots of temp. var creation and significantly increased performance as a result. 50 | * Original version at https://github.com/timohausmann/quadtree-js/ 51 | * @constructor 52 | * @param {number} x - The top left coordinate of the quadtree. 53 | * @param {number} y - The top left coordinate of the quadtree. 54 | * @param {number} width - The width of the quadtree in pixels. 55 | * @param {number} height - The height of the quadtree in pixels. 56 | * @param {number} [maxObjects=10] - The maximum number of objects per node. 57 | * @param {number} [maxLevels=4] - The maximum number of levels to iterate to. 58 | * @param {number} [level=0] - Which level is this? 59 | */ 60 | Phaser.QuadTree = function (x, y, width, height, maxObjects, maxLevels, level) { 61 | 62 | this.maxObjects = maxObjects || 10; 63 | this.maxLevels = maxLevels || 4; 64 | this.level = level || 0; 65 | 66 | this.bounds = { 67 | x: Math.round(x), 68 | y: Math.round(y), 69 | width: width, 70 | height: height, 71 | subWidth: Math.floor(width / 2), 72 | subHeight: Math.floor(height / 2), 73 | right: Math.round(x) + Math.floor(width / 2), 74 | bottom: Math.round(y) + Math.floor(height / 2) 75 | }; 76 | 77 | this.objects = []; 78 | this.nodes = []; 79 | 80 | }; 81 | 82 | Phaser.QuadTree.prototype = { 83 | 84 | /* 85 | * Populates this quadtree with the members of the given Group. 86 | * 87 | * @method Phaser.QuadTree#populate 88 | * @param {Phaser.Group} group - The Group to add to the quadtree. 89 | */ 90 | populate: function (group) { 91 | 92 | group.forEach(this.populateHandler, this, true); 93 | 94 | }, 95 | 96 | /* 97 | * Handler for the populate method. 98 | * 99 | * @method Phaser.QuadTree#populateHandler 100 | * @param {Phaser.Sprite} sprite - The Sprite to check. 101 | */ 102 | populateHandler: function (sprite) { 103 | 104 | if (sprite.body && sprite.body.checkCollision.none === false && sprite.alive) 105 | { 106 | this.insert(sprite.body); 107 | } 108 | 109 | }, 110 | 111 | /* 112 | * Split the node into 4 subnodes 113 | * 114 | * @method Phaser.QuadTree#split 115 | */ 116 | split: function () { 117 | 118 | this.level++; 119 | 120 | // top right node 121 | this.nodes[0] = new Phaser.QuadTree(this.bounds.right, this.bounds.y, this.bounds.subWidth, this.bounds.subHeight, this.maxObjects, this.maxLevels, this.level); 122 | 123 | // top left node 124 | this.nodes[1] = new Phaser.QuadTree(this.bounds.x, this.bounds.y, this.bounds.subWidth, this.bounds.subHeight, this.maxObjects, this.maxLevels, this.level); 125 | 126 | // bottom left node 127 | this.nodes[2] = new Phaser.QuadTree(this.bounds.x, this.bounds.bottom, this.bounds.subWidth, this.bounds.subHeight, this.maxObjects, this.maxLevels, this.level); 128 | 129 | // bottom right node 130 | this.nodes[3] = new Phaser.QuadTree(this.bounds.right, this.bounds.bottom, this.bounds.subWidth, this.bounds.subHeight, this.maxObjects, this.maxLevels, this.level); 131 | 132 | }, 133 | 134 | /* 135 | * Insert the object into the node. If the node exceeds the capacity, it will split and add all objects to their corresponding subnodes. 136 | * 137 | * @method Phaser.QuadTree#insert 138 | * @param {Phaser.Physics.Arcade.Body|object} body - The Body object to insert into the quadtree. 139 | */ 140 | insert: function (body) { 141 | 142 | var i = 0; 143 | var index; 144 | 145 | // if we have subnodes ... 146 | if (this.nodes[0] != null) 147 | { 148 | index = this.getIndex(body); 149 | 150 | if (index !== -1) 151 | { 152 | this.nodes[index].insert(body); 153 | return; 154 | } 155 | } 156 | 157 | this.objects.push(body); 158 | 159 | if (this.objects.length > this.maxObjects && this.level < this.maxLevels) 160 | { 161 | // Split if we don't already have subnodes 162 | if (this.nodes[0] == null) 163 | { 164 | this.split(); 165 | } 166 | 167 | // Add objects to subnodes 168 | while (i < this.objects.length) 169 | { 170 | index = this.getIndex(this.objects[i]); 171 | 172 | if (index !== -1) 173 | { 174 | // this is expensive - see what we can do about it 175 | this.nodes[index].insert(this.objects.splice(i, 1)[0]); 176 | } 177 | else 178 | { 179 | i++; 180 | } 181 | } 182 | } 183 | 184 | }, 185 | 186 | /* 187 | * Determine which node the object belongs to. 188 | * 189 | * @method Phaser.QuadTree#getIndex 190 | * @param {Phaser.Rectangle|object} rect - The bounds in which to check. 191 | * @return {number} index - Index of the subnode (0-3), or -1 if rect cannot completely fit within a subnode and is part of the parent node. 192 | */ 193 | getIndex: function (rect) { 194 | 195 | // default is that rect doesn't fit, i.e. it straddles the internal quadrants 196 | var index = -1; 197 | 198 | if (rect.x < this.bounds.right && rect.right < this.bounds.right) 199 | { 200 | if ((rect.y < this.bounds.bottom && rect.bottom < this.bounds.bottom)) 201 | { 202 | // rect fits within the top-left quadrant of this quadtree 203 | index = 1; 204 | } 205 | else if ((rect.y > this.bounds.bottom)) 206 | { 207 | // rect fits within the bottom-left quadrant of this quadtree 208 | index = 2; 209 | } 210 | } 211 | else if (rect.x > this.bounds.right) 212 | { 213 | // rect can completely fit within the right quadrants 214 | if ((rect.y < this.bounds.bottom && rect.bottom < this.bounds.bottom)) 215 | { 216 | // rect fits within the top-right quadrant of this quadtree 217 | index = 0; 218 | } 219 | else if ((rect.y > this.bounds.bottom)) 220 | { 221 | // rect fits within the bottom-right quadrant of this quadtree 222 | index = 3; 223 | } 224 | } 225 | 226 | return index; 227 | 228 | }, 229 | 230 | /* 231 | * Return all objects that could collide with the given Sprite. 232 | * 233 | * @method Phaser.QuadTree#retrieve 234 | * @param {Phaser.Sprite} sprite - The sprite to check against. 235 | * @return {array} - Array with all detected objects. 236 | */ 237 | retrieve: function (sprite) { 238 | 239 | var returnObjects = this.objects; 240 | 241 | sprite.body.quadTreeIndex = this.getIndex(sprite.body); 242 | 243 | // Temp store for the node IDs this sprite is in, we can use this for fast elimination later 244 | // sprite.body.quadTreeIDs.push(this.ID); 245 | 246 | if (this.nodes[0]) 247 | { 248 | // if rect fits into a subnode .. 249 | if (sprite.body.quadTreeIndex !== -1) 250 | { 251 | returnObjects = returnObjects.concat(this.nodes[sprite.body.quadTreeIndex].retrieve(sprite)); 252 | } 253 | else 254 | { 255 | // if rect does not fit into a subnode, check it against all subnodes (unrolled for speed) 256 | returnObjects = returnObjects.concat(this.nodes[0].retrieve(sprite)); 257 | returnObjects = returnObjects.concat(this.nodes[1].retrieve(sprite)); 258 | returnObjects = returnObjects.concat(this.nodes[2].retrieve(sprite)); 259 | returnObjects = returnObjects.concat(this.nodes[3].retrieve(sprite)); 260 | } 261 | } 262 | 263 | return returnObjects; 264 | 265 | }, 266 | 267 | /* 268 | * Clear the quadtree. 269 | * @method Phaser.QuadTree#clear 270 | */ 271 | clear: function () { 272 | 273 | this.objects = []; 274 | 275 | for (var i = 0, len = this.nodes.length; i < len; i++) 276 | { 277 | if (this.nodes[i]) 278 | { 279 | this.nodes[i].clear(); 280 | delete this.nodes[i]; 281 | } 282 | } 283 | } 284 | 285 | }; 286 | 287 | Phaser.QuadTree.prototype.constructor = Phaser.QuadTree; 288 | -------------------------------------------------------------------------------- /bower_components/phaser-official/plugins/SamplePlugin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * A Sample Plugin demonstrating how to hook into the Phaser plugin system. 3 | */ 4 | Phaser.Plugin.SamplePlugin = function (game, parent) { 5 | 6 | Phaser.Plugin.call(this, game, parent); 7 | 8 | this.sprite = null; 9 | 10 | }; 11 | 12 | // Extends the Phaser.Plugin template, setting up values we need 13 | Phaser.Plugin.SamplePlugin.prototype = Object.create(Phaser.Plugin.prototype); 14 | Phaser.Plugin.SamplePlugin.prototype.constructor = Phaser.Plugin.SamplePlugin; 15 | 16 | /** 17 | * Add a Sprite reference to this Plugin. 18 | * All this plugin does is move the Sprite across the screen slowly. 19 | * @type {Phaser.Sprite} 20 | */ 21 | Phaser.Plugin.SamplePlugin.prototype.addSprite = function (sprite) { 22 | 23 | this.sprite = sprite; 24 | 25 | }; 26 | 27 | /** 28 | * This is run when the plugins update during the core game loop. 29 | */ 30 | Phaser.Plugin.SamplePlugin.prototype.update = function () { 31 | 32 | if (this.sprite) 33 | { 34 | this.sprite.x += 0.5; 35 | } 36 | 37 | }; 38 | -------------------------------------------------------------------------------- /bower_components/phaser-official/plugins/Webcam.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Provides access to the Webcam (if available) 3 | */ 4 | Phaser.Plugin.Webcam = function (game, parent) { 5 | 6 | Phaser.Plugin.call(this, game, parent); 7 | 8 | if (!game.device.getUserMedia) 9 | { 10 | return false; 11 | } 12 | 13 | navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; 14 | 15 | this.context = null; 16 | this.stream = null; 17 | 18 | this.video = document.createElement('video'); 19 | this.video.autoplay = true; 20 | 21 | }; 22 | 23 | Phaser.Plugin.Webcam.prototype = Object.create(Phaser.Plugin.prototype); 24 | Phaser.Plugin.Webcam.prototype.constructor = Phaser.Plugin.Webcam; 25 | 26 | Phaser.Plugin.Webcam.prototype.start = function (width, height, context) { 27 | 28 | console.log('Webcam start', width, height); 29 | 30 | this.context = context; 31 | 32 | if (!this.stream) 33 | { 34 | navigator.getUserMedia( { video: { mandatory: { minWidth: width, minHeight: height } } }, this.connectCallback.bind(this), this.errorCallback.bind(this)); 35 | } 36 | 37 | }; 38 | 39 | Phaser.Plugin.Webcam.prototype.stop = function () { 40 | 41 | if (this.stream) 42 | { 43 | this.stream.stop(); 44 | this.stream = null; 45 | } 46 | 47 | }; 48 | 49 | Phaser.Plugin.Webcam.prototype.connectCallback = function (stream) { 50 | 51 | this.stream = stream; 52 | 53 | this.video.src = window.URL.createObjectURL(this.stream); 54 | 55 | }; 56 | 57 | Phaser.Plugin.Webcam.prototype.errorCallback = function (e) { 58 | 59 | console.log('Video Stream rejected', e); 60 | 61 | }; 62 | 63 | Phaser.Plugin.Webcam.prototype.grab = function (context, x, y) { 64 | 65 | if (this.stream) 66 | { 67 | context.drawImage(this.video, x, y); 68 | } 69 | 70 | }; 71 | 72 | Phaser.Plugin.Webcam.prototype.update = function () { 73 | 74 | if (this.stream) 75 | { 76 | this.context.drawImage(this.video, 0, 0); 77 | } 78 | 79 | }; 80 | 81 | /** 82 | * @name Phaser.Plugin.Webcam#active 83 | * @property {boolean} active - Is this Webcam plugin capturing a video stream or not? 84 | * @readonly 85 | */ 86 | Object.defineProperty(Phaser.Plugin.Webcam.prototype, "active", { 87 | 88 | get: function() { 89 | return (this.stream); 90 | } 91 | 92 | }); 93 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "projectName": "hud manager", 3 | "gameWidth": "800", 4 | "gameHeight": "600" 5 | } -------------------------------------------------------------------------------- /css/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #333; 3 | } 4 | 5 | #hud-manager { 6 | border: 2px solid white; 7 | width: 800px; 8 | margin-left: auto; 9 | margin-right: auto; 10 | cursor: pointer; 11 | } -------------------------------------------------------------------------------- /dist/assets/empty.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ada-lovecraft/phaser-HudManager/4ef6970598217c098e5b2c9c91832fd30f23307a/dist/assets/empty.wav -------------------------------------------------------------------------------- /dist/assets/gun-cocking-01.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ada-lovecraft/phaser-HudManager/4ef6970598217c098e5b2c9c91832fd30f23307a/dist/assets/gun-cocking-01.wav -------------------------------------------------------------------------------- /dist/assets/gunshot.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ada-lovecraft/phaser-HudManager/4ef6970598217c098e5b2c9c91832fd30f23307a/dist/assets/gunshot.wav -------------------------------------------------------------------------------- /dist/assets/preloader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ada-lovecraft/phaser-HudManager/4ef6970598217c098e5b2c9c91832fd30f23307a/dist/assets/preloader.gif -------------------------------------------------------------------------------- /dist/assets/yeoman-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ada-lovecraft/phaser-HudManager/4ef6970598217c098e5b2c9c91832fd30f23307a/dist/assets/yeoman-logo.png -------------------------------------------------------------------------------- /dist/css/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #333; 3 | } 4 | 5 | #hud-manager { 6 | border: 2px solid white; 7 | width: 800px; 8 | margin-left: auto; 9 | margin-right: auto; 10 | cursor: pointer; 11 | } -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Hud manager 8 | 9 | 10 | 11 | Fork me on GitHub 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /dist/js/game.js: -------------------------------------------------------------------------------- 1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= 0) { 77 | self.$$watchers.splice(index, 1); 78 | } 79 | }; 80 | }; 81 | 82 | 83 | 84 | Phaser.Plugin.HUDManager.prototype.$digestOnce = function() { 85 | var newValue, oldValue, dirty; 86 | this.$$watchers.forEach(function(watcher) { 87 | newValue = watcher.watchFn(this); 88 | oldValue = watcher.last; 89 | if(newValue !== oldValue) { 90 | this.$$lastDirtyWatch = watcher; 91 | watcher.last = newValue; 92 | watcher.listenerFn(newValue, (oldValue == initWatchVal ? newValue: oldValue), this); 93 | dirty = true; 94 | } else if (this.$$lastDirtyWatch === watcher) { 95 | return false; 96 | } 97 | }, this); 98 | return dirty; 99 | }; 100 | 101 | Phaser.Plugin.HUDManager.prototype.$digest = function() { 102 | var ttl = 10; 103 | 104 | var self = this; 105 | 106 | this.$$lastDirtyWatch = null; 107 | function digest() { 108 | var dirty = self.$digestOnce(); 109 | if (dirty && !(ttl--)) { 110 | throw "10 Digest Iterations Reached"; 111 | } 112 | if(dirty) { 113 | setTimeout(digest, 0); 114 | } 115 | } 116 | setTimeout(digest, 0); 117 | 118 | }; 119 | 120 | Phaser.Plugin.HUDManager.prototype.addText = function(x, y, label, style, watched, context) { 121 | var text = this.game.add.text(x, y, label, style); 122 | context = context || window; 123 | var dereg = this.$watch(function() { 124 | return context[watched]; 125 | }, function() { 126 | text.setText(label + context[watched]); 127 | }); 128 | return {text: text, deregister: dereg}; 129 | }; 130 | 131 | Phaser.Plugin.HUDManager.prototype.addBar = function(x, y, width, height, max, watched, context, color, backgroundColor) { 132 | max = max || 100; 133 | 134 | color = color || 'white'; 135 | backgroundColor = backgroundColor || '#999'; 136 | 137 | var colorFunction = function() { return color; }; 138 | 139 | if(typeof color === 'function' ) { 140 | colorFunction = color; 141 | } 142 | 143 | 144 | var bmd = this.game.add.bitmapData(width, height); 145 | context = context || window; 146 | var bar = this.game.add.sprite(x, y, bmd); 147 | var dereg = this.$watch(function() { 148 | return context[watched]; 149 | }, function(newVal) { 150 | var percent = newVal / max; 151 | if((percent <= 1 && percent >= 0)) { 152 | bmd.clear(); 153 | bmd.ctx.beginPath(); 154 | bmd.ctx.moveTo(0,0); 155 | bmd.ctx.rect(0,0, width, height); 156 | bmd.ctx.closePath(); 157 | bmd.ctx.fillStyle = backgroundColor; 158 | bmd.ctx.fill(); 159 | bmd.ctx.beginPath(); 160 | bmd.ctx.rect(0,0,width*percent, height); 161 | bmd.ctx.fillStyle = colorFunction(percent); 162 | bmd.ctx.fill(); 163 | bmd.ctx.closePath(); 164 | bmd.render(); 165 | bmd.refreshBuffer(); 166 | } 167 | }); 168 | 169 | return {bar: bar, deregister: dereg}; 170 | }; 171 | 172 | 173 | Phaser.Plugin.HUDManager.prototype.addWatch = function(watched, watchedContext, callback, callbackContext) { 174 | watchedContext = watchedContext || window; 175 | callbackContext = callbackContext || window; 176 | var dereg = this.$watch(function() { 177 | return watchedContext[watched]; 178 | }, function(newVal, oldVal) { 179 | callback.call(callbackContext, newVal, oldVal); 180 | }); 181 | return dereg; 182 | }; 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /game/hud-manager/hud-manager.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function initWatchVal() {} 4 | 5 | 6 | var HudManager = function(game, name, pollRate) { 7 | this.game = game; 8 | this.pollRate = pollRate || 100; 9 | this.digestTimer = this.game.time.events.loop(this.pollRate, this.$digest, this); 10 | this.digestTimer.timer.start(); 11 | this.$$watchers = []; 12 | this.$$lastDirtyWatch = null; 13 | this.name = name || HudManager.hudCounter++; 14 | }; 15 | 16 | HudManager.huds = {}; 17 | HudManager.hudCounter = 0; 18 | 19 | HudManager.createHud = function(game, name, pollrate) { 20 | name = name || HudManager.hudCounter++; 21 | var hud = new HudManager(game, name, pollrate); 22 | HudManager.huds[name] = hud; 23 | return hud; 24 | }; 25 | 26 | HudManager.prototype.destroy = function() { 27 | delete HudManager.huds[this.name]; 28 | this.$$watchers = []; 29 | }; 30 | 31 | HudManager.prototype.$watch = function(watchFn, listenerFn) { 32 | var watcher = { 33 | watchFn: watchFn, 34 | listenerFn: listenerFn || function() {}, 35 | last: initWatchVal, 36 | }; 37 | this.$$watchers.push(watcher); 38 | this.$$lastDirtyWatch = null; 39 | var self = this; 40 | return function() { 41 | var index = self.$$watchers.indexOf(watcher); 42 | if (index >= 0) { 43 | self.$$watchers.splice(index, 1); 44 | } 45 | }; 46 | }; 47 | 48 | 49 | 50 | HudManager.prototype.$digestOnce = function() { 51 | var newValue, oldValue, dirty; 52 | this.$$watchers.forEach(function(watcher) { 53 | newValue = watcher.watchFn(this); 54 | oldValue = watcher.last; 55 | if(newValue !== oldValue) { 56 | this.$$lastDirtyWatch = watcher; 57 | watcher.last = newValue; 58 | watcher.listenerFn(newValue, (oldValue == initWatchVal ? newValue: oldValue), this); 59 | dirty = true; 60 | } else if (this.$$lastDirtyWatch === watcher) { 61 | return false; 62 | } 63 | }, this); 64 | return dirty; 65 | }; 66 | 67 | HudManager.prototype.$digest = function() { 68 | var ttl = 10; 69 | var dirty; 70 | this.$$lastDirtyWatch = null; 71 | do { 72 | dirty = this.$digestOnce(); 73 | if (dirty && !(ttl--)) { 74 | throw "10 Digest Iterations Reached"; 75 | } 76 | } while (dirty); 77 | }; 78 | 79 | HudManager.prototype.addText = function(x, y, label, style, watched, context) { 80 | var text = this.game.add.text(x, y, label, style); 81 | context = context || window; 82 | var dereg = this.$watch(function() { 83 | return context[watched]; 84 | }, function() { 85 | text.setText(label + context[watched]); 86 | }); 87 | return {text: text, deregister: dereg}; 88 | }; 89 | 90 | HudManager.prototype.addProgressBar = function(x, y, width, height, max, watched, context) { 91 | var bmd = this.game.add.bitmapData(width, height); 92 | context = context || window; 93 | var bar = this.game.add.sprite(x, y, bmd); 94 | var dereg = this.$watch(function() { 95 | return context[watched]; 96 | }, function(newVal) { 97 | var percent = newVal / max; 98 | if(percent <= 1) { 99 | bmd.clear(); 100 | bmd.ctx.beginPath(); 101 | bmd.ctx.moveTo(0,0); 102 | bmd.ctx.rect(0,0,width*percent, height); 103 | bmd.ctx.fillStyle = 'white'; 104 | bmd.ctx.fill(); 105 | bmd.ctx.closePath(); 106 | bmd.render(); 107 | bmd.refreshBuffer(); 108 | } else { 109 | dereg(); 110 | } 111 | }); 112 | 113 | return {bar: bar, deregister: dereg}; 114 | }; 115 | 116 | 117 | HudManager.prototype.addWatch = function(watched, watchedContext, callback, callbackContext) { 118 | watchedContext = watchedContext || window; 119 | callbackContext = callbackContext || window; 120 | var dereg = this.$watch(function() { 121 | return watchedContext[watched]; 122 | }, function(newVal, oldVal) { 123 | callback.call(callbackContext, newVal, oldVal); 124 | }); 125 | return dereg; 126 | }; 127 | 128 | module.exports = HudManager; 129 | -------------------------------------------------------------------------------- /game/hud-manager/scope.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | function initWatchVal() {} 3 | 4 | function Scope() { 5 | this.$$watchers = []; 6 | this.$$lastDirtyWatch = null; 7 | } 8 | 9 | Scope.prototype.$watch = function(watchFn, listenerFn) { 10 | var watcher = { 11 | watchFn: watchFn, 12 | listenerFn: listenerFn || function() {}, 13 | last: initWatchVal, 14 | }; 15 | this.$$watchers.push(watcher); 16 | this.$$lastDirtyWatch = null; 17 | }; 18 | 19 | 20 | 21 | Scope.prototype.$digestOnce = function() { 22 | var newValue, oldValue, dirty; 23 | this.$$watchers.forEach(function(watcher) { 24 | newValue = watcher.watchFn(this); 25 | oldValue = watcher.last; 26 | if(newValue !== oldValue) { 27 | this.$$lastDirtyWatch = watcher; 28 | watcher.last = newValue; 29 | watcher.listenerFn(newValue, (oldValue == initWatchVal ? newValue: oldValue), this); 30 | dirty = true; 31 | } else if (this.$$lastDirtyWatch === watcher) { 32 | return false; 33 | } 34 | }, this); 35 | return dirty; 36 | }; 37 | 38 | Scope.prototype.$digest = function() { 39 | var ttl = 10; 40 | var dirty; 41 | this.$$lastDirtyWatch = null; 42 | do { 43 | dirty = this.$digestOnce(); 44 | if (dirty && !(ttl--)) { 45 | throw "10 Digest Iterations Reached"; 46 | } 47 | } while (dirty); 48 | }; 49 | 50 | module.exports = Scope; -------------------------------------------------------------------------------- /game/main.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | //global variables 4 | window.onload = function () { 5 | var game = new Phaser.Game(800, 600, Phaser.AUTO, 'hud-manager'); 6 | 7 | // Game States 8 | game.state.add('boot', require('./states/boot')); 9 | game.state.add('gameover', require('./states/gameover')); 10 | game.state.add('menu', require('./states/menu')); 11 | game.state.add('play', require('./states/play')); 12 | game.state.add('preload', require('./states/preload')); 13 | 14 | 15 | game.state.start('boot'); 16 | }; -------------------------------------------------------------------------------- /game/plugins/HudManager.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * A Sample Plugin demonstrating how to hook into the Phaser plugin system. 4 | */ 5 | function initWatchVal() {} 6 | 7 | Phaser.Plugin.HUDManager = function (game, parent, name, pollRate) { 8 | 9 | Phaser.Plugin.call(this, game, parent); 10 | 11 | this.pollRate = pollRate || 100; 12 | this.digestTimer = this.game.time.events.loop(this.pollRate, this.$digest, this); 13 | this.digestTimer.timer.start(); 14 | this.$$watchers = []; 15 | this.$$lastDirtyWatch = null; 16 | this.name = name || Phaser.Plugin.HUDManager.hudCounter++; 17 | }; 18 | 19 | Phaser.Plugin.HUDManager.huds = {}; 20 | Phaser.Plugin.HUDManager.hudCounter = 0; 21 | 22 | Phaser.Plugin.HUDManager.HEALTHBAR = function(percent) { 23 | if (percent <= 0.25) { 24 | return '#ff7474'; //red 25 | } 26 | if (percent <= 0.75) { 27 | return '#eaff74'; //yellow 28 | } 29 | return '#74ff74'; //green 30 | }; 31 | 32 | 33 | Phaser.Plugin.HUDManager.prototype = Object.create(Phaser.Plugin.prototype); 34 | Phaser.Plugin.HUDManager.prototype.constructor = Phaser.Plugin.HUDManager; 35 | 36 | 37 | 38 | Phaser.Plugin.HUDManager.create = function(game, parent, name, pollrate) { 39 | 40 | var hud = Phaser.Plugin.HUDManager.huds[name]; 41 | if(!!hud) { 42 | return hud; 43 | } 44 | name = name || Phaser.Plugin.HUDManager.hudCounter++; 45 | hud = new Phaser.Plugin.HUDManager(game, parent, name, pollrate); 46 | Phaser.Plugin.HUDManager.huds[name] = hud; 47 | return hud; 48 | }; 49 | 50 | Phaser.Plugin.HUDManager.get = function(name) { 51 | var hud = Phaser.Plugin.HUDManager.huds[name]; 52 | if(hud) { 53 | return hud; 54 | } else { 55 | throw 'HUD "' + name + '" not found'; 56 | } 57 | }; 58 | 59 | 60 | Phaser.Plugin.HUDManager.prototype.destroy = function() { 61 | delete Phaser.Plugin.HUDManager.huds[this.name]; 62 | this.$$watchers = []; 63 | }; 64 | 65 | Phaser.Plugin.HUDManager.prototype.$watch = function(watchFn, listenerFn) { 66 | var watcher = { 67 | watchFn: watchFn, 68 | listenerFn: listenerFn || function() {}, 69 | last: initWatchVal, 70 | }; 71 | this.$$watchers.push(watcher); 72 | this.$$lastDirtyWatch = null; 73 | var self = this; 74 | return function() { 75 | var index = self.$$watchers.indexOf(watcher); 76 | if (index >= 0) { 77 | self.$$watchers.splice(index, 1); 78 | } 79 | }; 80 | }; 81 | 82 | 83 | 84 | Phaser.Plugin.HUDManager.prototype.$digestOnce = function() { 85 | var newValue, oldValue, dirty; 86 | this.$$watchers.forEach(function(watcher) { 87 | newValue = watcher.watchFn(this); 88 | oldValue = watcher.last; 89 | if(newValue !== oldValue) { 90 | this.$$lastDirtyWatch = watcher; 91 | watcher.last = newValue; 92 | watcher.listenerFn(newValue, (oldValue == initWatchVal ? newValue: oldValue), this); 93 | dirty = true; 94 | } else if (this.$$lastDirtyWatch === watcher) { 95 | return false; 96 | } 97 | }, this); 98 | return dirty; 99 | }; 100 | 101 | Phaser.Plugin.HUDManager.prototype.$digest = function() { 102 | var ttl = 10; 103 | 104 | var self = this; 105 | 106 | this.$$lastDirtyWatch = null; 107 | function digest() { 108 | var dirty = self.$digestOnce(); 109 | if (dirty && !(ttl--)) { 110 | throw "10 Digest Iterations Reached"; 111 | } 112 | if(dirty) { 113 | setTimeout(digest, 0); 114 | } 115 | } 116 | setTimeout(digest, 0); 117 | 118 | }; 119 | 120 | Phaser.Plugin.HUDManager.prototype.addText = function(x, y, label, style, watched, context) { 121 | var text = this.game.add.text(x, y, label, style); 122 | context = context || window; 123 | var dereg = this.$watch(function() { 124 | return context[watched]; 125 | }, function() { 126 | text.setText(label + context[watched]); 127 | }); 128 | return {text: text, deregister: dereg}; 129 | }; 130 | 131 | Phaser.Plugin.HUDManager.prototype.addBar = function(x, y, width, height, max, watched, context, color, backgroundColor) { 132 | max = max || 100; 133 | 134 | color = color || 'white'; 135 | backgroundColor = backgroundColor || '#999'; 136 | 137 | var colorFunction = function() { return color; }; 138 | 139 | if(typeof color === 'function' ) { 140 | colorFunction = color; 141 | } 142 | 143 | 144 | var bmd = this.game.add.bitmapData(width, height); 145 | context = context || window; 146 | var bar = this.game.add.sprite(x, y, bmd); 147 | var dereg = this.$watch(function() { 148 | return context[watched]; 149 | }, function(newVal) { 150 | var percent = newVal / max; 151 | if((percent <= 1 && percent >= 0)) { 152 | bmd.clear(); 153 | bmd.ctx.beginPath(); 154 | bmd.ctx.moveTo(0,0); 155 | bmd.ctx.rect(0,0, width, height); 156 | bmd.ctx.closePath(); 157 | bmd.ctx.fillStyle = backgroundColor; 158 | bmd.ctx.fill(); 159 | bmd.ctx.beginPath(); 160 | bmd.ctx.rect(0,0,width*percent, height); 161 | bmd.ctx.fillStyle = colorFunction(percent); 162 | bmd.ctx.fill(); 163 | bmd.ctx.closePath(); 164 | bmd.render(); 165 | bmd.refreshBuffer(); 166 | } 167 | }); 168 | 169 | return {bar: bar, deregister: dereg}; 170 | }; 171 | 172 | 173 | Phaser.Plugin.HUDManager.prototype.addWatch = function(watched, watchedContext, callback, callbackContext) { 174 | watchedContext = watchedContext || window; 175 | callbackContext = callbackContext || window; 176 | var dereg = this.$watch(function() { 177 | return watchedContext[watched]; 178 | }, function(newVal, oldVal) { 179 | callback.call(callbackContext, newVal, oldVal); 180 | }); 181 | return dereg; 182 | }; 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /game/prefabs/enemy.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var GameRegistry = require('../registries/game-registry'); 3 | 4 | var Enemy = function(game, x, y, frame) { 5 | var bmd = game.add.bitmapData(32,32); 6 | bmd.ctx.beginPath(); 7 | bmd.ctx.rect(0,0, 32,32); 8 | bmd.ctx.fillStyle = 'red'; 9 | bmd.ctx.fill(); 10 | bmd.render(); 11 | this.maxHealth = 5; 12 | Phaser.Sprite.call(this, game, x, y, bmd); 13 | this.anchor.setTo(0.5, 0.5); 14 | this.game.physics.arcade.enableBody(this); 15 | this.health = 5; 16 | this.alive = true; 17 | 18 | this.hud = Phaser.Plugin.HUDManager.create(this.game, this, 'enemyhud'); 19 | this.healthHUD = this.hud.addBar(0,-20, 32, 2, this.maxHealth, 'health', this, Phaser.Plugin.HUDManager.HEALTHBAR, false); 20 | this.healthHUD.bar.anchor.setTo(0.5, 0.5); 21 | this.addChild(this.healthHUD.bar); 22 | 23 | }; 24 | 25 | Enemy.prototype = Object.create(Phaser.Sprite.prototype); 26 | Enemy.prototype.constructor = Enemy; 27 | 28 | Enemy.prototype.update = function() { 29 | 30 | this.game.physics.arcade.moveToObject(this,GameRegistry.getPlayer()); 31 | 32 | }; 33 | 34 | module.exports = Enemy; 35 | -------------------------------------------------------------------------------- /game/prefabs/player.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Player = function(game, x, y, frame) { 4 | var bmd = game.add.bitmapData(16,16); 5 | bmd.ctx.beginPath(); 6 | bmd.ctx.rect(0,0, 16,16); 7 | bmd.ctx.fillStyle = 'white'; 8 | bmd.ctx.fill(); 9 | bmd.render(); 10 | 11 | Phaser.Sprite.call(this, game, x, y, bmd); 12 | 13 | 14 | 15 | this.ammoMax = 6; 16 | this.ammo = 6; 17 | this.reloadCounter = 50; 18 | this.moveSpeed = 200; 19 | this.canReload = false; 20 | this.fireRate = 300; 21 | this.fireTimer = 0; 22 | 23 | 24 | 25 | this.reloadTimer = this.game.time.create(false); 26 | 27 | 28 | this.anchor.setTo(0.5, 0.5); 29 | this.game.physics.arcade.enableBody(this); 30 | this.body.collideWorldBounds = true; 31 | 32 | this.hud = Phaser.Plugin.HUDManager.get('gamehud'); 33 | this.ammoHUD = this.hud.addBar(0,-12, 16, 2, this.ammoMax, 'ammo', this, '#ffbd55'); 34 | this.ammoHUD.bar.anchor.setTo(0.5, 0.5); 35 | 36 | this.addChild(this.ammoHUD.bar); 37 | 38 | this.leftKey = this.game.input.keyboard.addKey(Phaser.Keyboard.A); 39 | this.rightKey = this.game.input.keyboard.addKey(Phaser.Keyboard.D); 40 | this.upKey = this.game.input.keyboard.addKey(Phaser.Keyboard.W); 41 | this.downKey = this.game.input.keyboard.addKey(Phaser.Keyboard.S); 42 | this.fireSound = this.game.add.audio('gunshot'); 43 | this.reloadSound = this.game.add.audio('reloadSound'); 44 | this.emptySound = this.game.add.audio('empty'); 45 | 46 | }; 47 | 48 | Player.prototype = Object.create(Phaser.Sprite.prototype); 49 | Player.prototype.constructor = Player; 50 | 51 | 52 | Player.prototype.update = function() { 53 | this.body.velocity.x = 0; 54 | this.body.velocity.y = 0; 55 | // movement 56 | if(this.leftKey.isDown) { 57 | this.body.velocity.x = -this.moveSpeed; 58 | } 59 | if(this.rightKey.isDown) { 60 | this.body.velocity.x = this.moveSpeed; 61 | } 62 | if(this.downKey.isDown) { 63 | this.body.velocity.y = this.moveSpeed; 64 | } 65 | if(this.upKey.isDown) { 66 | this.body.velocity.y = -this.moveSpeed; 67 | } 68 | 69 | }; 70 | Player.prototype.canFire = function() { 71 | if(this.reloadTimer.running) { 72 | if(this.fireTimer <= this.game.time.now) { 73 | this.emptySound.play(); 74 | this.fireTimer = this.fireRate + this.game.time.now; 75 | } 76 | return false; 77 | } else { 78 | return this.fireTimer <= this.game.time.now; 79 | } 80 | }; 81 | 82 | 83 | Player.prototype.addAmmo = function() { 84 | this.ammo++; 85 | if (this.ammo === this.ammoMax - 1) { 86 | this.reloadSound.play(); 87 | } 88 | if (this.ammo === this.ammoMax) { 89 | this.ammoHUD.bar.alpha = 1; 90 | this.reloadTimer.stop(true); 91 | this.fireTimer = this.game.time.now; 92 | } 93 | }; 94 | Player.prototype.fire = function() { 95 | this.ammo--; 96 | if (this.ammo === 0) { 97 | this.ammoHUD.bar.alpha = 0.75; 98 | this.reloadTimer.repeat(Phaser.Timer.SECOND * 0.5, this.ammoMax, this.addAmmo, this); 99 | this.reloadTimer.start(); 100 | } 101 | this.fireSound.play(); 102 | this.fireTimer = this.fireRate + this.game.time.now; 103 | }; 104 | 105 | module.exports = Player; 106 | -------------------------------------------------------------------------------- /game/registries/game-registry.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var GameRegistry = function() { 4 | GameRegistry.player = null; 5 | }; 6 | 7 | GameRegistry.getPlayer = function() { 8 | return GameRegistry.player; 9 | }; 10 | 11 | GameRegistry.setPlayer = function(p) { 12 | GameRegistry.player = p; 13 | }; 14 | 15 | module.exports = GameRegistry; -------------------------------------------------------------------------------- /game/states/boot.js: -------------------------------------------------------------------------------- 1 | 2 | 'use strict'; 3 | 4 | function Boot() { 5 | } 6 | 7 | Boot.prototype = { 8 | preload: function() { 9 | this.load.image('preloader', 'assets/preloader.gif'); 10 | }, 11 | create: function() { 12 | this.game.input.maxPointers = 1; 13 | this.game.state.start('preload'); 14 | } 15 | }; 16 | 17 | module.exports = Boot; 18 | -------------------------------------------------------------------------------- /game/states/gameover.js: -------------------------------------------------------------------------------- 1 | 2 | 'use strict'; 3 | function GameOver() {} 4 | 5 | GameOver.prototype = { 6 | preload: function () { 7 | 8 | }, 9 | create: function () { 10 | var style = { font: '65px Arial', fill: '#ffffff', align: 'center'}; 11 | this.titleText = this.game.add.text(this.game.world.centerX,100, 'Game Over!', style); 12 | this.titleText.anchor.setTo(0.5, 0.5); 13 | 14 | this.congratsText = this.game.add.text(this.game.world.centerX, 200, 'You Win!', { font: '32px Arial', fill: '#ffffff', align: 'center'}); 15 | this.congratsText.anchor.setTo(0.5, 0.5); 16 | 17 | this.instructionText = this.game.add.text(this.game.world.centerX, 300, 'Click To Play Again', { font: '16px Arial', fill: '#ffffff', align: 'center'}); 18 | this.instructionText.anchor.setTo(0.5, 0.5); 19 | }, 20 | update: function () { 21 | if(this.game.input.activePointer.justPressed()) { 22 | this.game.state.start('play'); 23 | } 24 | } 25 | }; 26 | module.exports = GameOver; 27 | -------------------------------------------------------------------------------- /game/states/menu.js: -------------------------------------------------------------------------------- 1 | 2 | 'use strict'; 3 | 4 | var Player = require('../prefabs/player'); 5 | var Enemy = require('../prefabs/enemy'); 6 | var GameRegistry = require('../registries/game-registry'); 7 | 8 | 9 | function Menu() {} 10 | 11 | 12 | Menu.prototype = { 13 | preload: function() { 14 | 15 | }, 16 | create: function() { 17 | this.hud = Phaser.Plugin.HUDManager.create(this.game, this, 'gamehud'); 18 | 19 | this.player = new Player(this.game, this.game.width/2, this.game.height/2); 20 | this.game.add.existing(this.player); 21 | GameRegistry.setPlayer(this.player); 22 | 23 | this.bulletBMD = this.game.add.bitmapData(4,4); 24 | this.bulletBMD.ctx.beginPath(); 25 | this.bulletBMD.ctx.rect(0,0, 4,4); 26 | this.bulletBMD.ctx.fillStyle = '#008aff'; 27 | this.bulletBMD.ctx.fill(); 28 | this.bulletBMD.render(); 29 | 30 | this.bullets = this.game.add.group(); 31 | 32 | this.enemies = this.game.add.group(); 33 | this.enemies.add(new Enemy(this.game, this.game.world.randomX, this.game.world.randomY)); 34 | 35 | this.score = 0; 36 | this.shotsFired = 0; 37 | this.accuracy = null; 38 | this.hits = null; 39 | 40 | var style = { font: '18px Arial', fill: '#ffffff', align: 'center'}; 41 | this.scoreHUD = this.hud.addText(10, 10, 'Score: ', style, 'score', this); 42 | this.game.add.existing(this.scoreHUD.text); 43 | 44 | this.firedHUD = this.hud.addText(150, 10, 'Shots Fired: ', style, 'shotsFired', this); 45 | this.game.add.existing(this.scoreHUD.text); 46 | 47 | this.accuracyHUD = this.hud.addText(300, 10, 'Accuracy: ', style, 'accuracy', this); 48 | this.game.add.existing(this.accuracyHUD.text); 49 | 50 | 51 | /* 52 | var style = { font: '65px Arial', fill: '#ffffff', align: 'center'}; 53 | 54 | this.textWatcher = this.hud.addText(this.game.world.centerX, 300, 'Update Calls: ', style, 'score', this); 55 | this.textWatcher.text.anchor.setTo(0.5, 0.5); 56 | 57 | 58 | this.progressWatcher = this.hud.addProgressBar(5, 10, 790, 100, 300, 'score', this ); 59 | 60 | this.cooldownWatcher = this.hud.addWatch('cooldownCounter',this, this.cooldownHandler, this); 61 | 62 | this.bmd = this.game.add.bitmapData(790, 50); 63 | this.bmd.ctx.rect(0,0,790,50); 64 | this.bmd.ctx.fillStyle = 'white'; 65 | this.bmd.ctx.fill(); 66 | this.bmd.render(); 67 | this.cooldownSprite = this.game.add.sprite(5,400, this.bmd); 68 | this.cooldownSprite.alpha = 0; 69 | var cooldownText = this.game.add.text(this.cooldownSprite.width/2,this.cooldownSprite.height / 2,'cooldown'); 70 | cooldownText.anchor.setTo(0.5, 0.5); 71 | 72 | this.cooldownSprite.addChild(cooldownText); 73 | */ 74 | 75 | }, 76 | update: function() { 77 | if(this.game.input.activePointer.isDown) { 78 | this.fire(); 79 | } 80 | 81 | this.game.physics.arcade.collide(this.bullets, this.enemies, this.killEnemy, null, this); 82 | }, 83 | 84 | killEnemy: function(bullet, enemy) { 85 | this.hits++; 86 | this.accuracy = (this.hits / this.shotsFired * 100).toFixed(2); 87 | bullet.kill(); 88 | enemy.damage(1); 89 | 90 | if(this.enemies.countLiving() == 0) { 91 | this.score++; 92 | var enemy = this.enemies.getFirstExists(false); 93 | enemy.reset(this.game.world.randomX, this.game.world.randomY, enemy.maxHealth); 94 | } 95 | 96 | }, 97 | fire: function() { 98 | if(this.player.canFire()) { 99 | var bullet = this.bullets.getFirstExists(false); 100 | if(!bullet) { 101 | bullet = this.bullets.add(this.game.add.sprite(0,0, this.bulletBMD)); 102 | this.game.physics.arcade.enableBody(bullet); 103 | bullet.anchor.setTo(0.5, 0.5); 104 | } 105 | bullet.reset(this.player.x, this.player.y); 106 | this.game.physics.arcade.moveToPointer(bullet, 1000); 107 | this.player.fire(); 108 | this.shotsFired++; 109 | 110 | } 111 | }, 112 | cooldownHandler: function(cooldownValue, oldVal) { 113 | if(cooldownValue <= 0 ) { 114 | this.cooldownWatcher(); 115 | } else { 116 | var percent = cooldownValue / 300; 117 | this.cooldownSprite.alpha = percent; 118 | } 119 | 120 | }, 121 | }; 122 | 123 | module.exports = Menu; 124 | -------------------------------------------------------------------------------- /game/states/play.js: -------------------------------------------------------------------------------- 1 | 2 | 'use strict'; 3 | function Play() {} 4 | Play.prototype = { 5 | create: function() { 6 | this.game.physics.startSystem(Phaser.Physics.ARCADE); 7 | this.sprite = this.game.add.sprite(this.game.width/2, this.game.height/2, 'yeoman'); 8 | this.sprite.inputEnabled = true; 9 | 10 | this.game.physics.arcade.enable(this.sprite); 11 | this.sprite.body.collideWorldBounds = true; 12 | this.sprite.body.bounce.setTo(1,1); 13 | this.sprite.body.velocity.x = this.game.rnd.integerInRange(-500,500); 14 | this.sprite.body.velocity.y = this.game.rnd.integerInRange(-500,500); 15 | 16 | this.sprite.events.onInputDown.add(this.clickListener, this); 17 | }, 18 | update: function() { 19 | 20 | }, 21 | clickListener: function() { 22 | this.game.state.start('gameover'); 23 | } 24 | }; 25 | 26 | module.exports = Play; -------------------------------------------------------------------------------- /game/states/preload.js: -------------------------------------------------------------------------------- 1 | 2 | 'use strict'; 3 | function Preload() { 4 | this.asset = null; 5 | this.ready = false; 6 | } 7 | 8 | Preload.prototype = { 9 | preload: function() { 10 | this.asset = this.add.sprite(this.width/2,this.height/2, 'preloader'); 11 | this.asset.anchor.setTo(0.5, 0.5); 12 | 13 | this.load.onLoadComplete.addOnce(this.onLoadComplete, this); 14 | this.load.setPreloadSprite(this.asset); 15 | this.load.image('yeoman', 'assets/yeoman-logo.png'); 16 | this.load.script('HudManager', 'js/plugins/HUDManager.js'); 17 | this.load.audio('reloadSound', 'assets/gun-cocking-01.wav'); 18 | this.load.audio('gunshot', 'assets/gunshot.wav'); 19 | this.load.audio('empty', 'assets/empty.wav'); 20 | 21 | 22 | }, 23 | create: function() { 24 | this.asset.cropEnabled = false; 25 | }, 26 | update: function() { 27 | if(!!this.ready) { 28 | this.game.state.start('menu'); 29 | } 30 | }, 31 | onLoadComplete: function() { 32 | this.ready = true; 33 | } 34 | }; 35 | 36 | module.exports = Preload; 37 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Hud manager 8 | 9 | 10 | 11 | Fork me on GitHub 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hud-manager", 3 | "private": true, 4 | "devDependencies": { 5 | "grunt": "~0.4.1", 6 | "bower": "~0.9.2", 7 | "grunt-contrib-connect": "~0.2.0", 8 | "grunt-contrib-watch": "~0.4.3", 9 | "grunt-contrib-copy": "*", 10 | "grunt-open": "~0.2.0", 11 | "matchdep": "~0.1.2", 12 | "connect-livereload": "~0.1.3", 13 | "moment": "~2.0.0", 14 | "grunt-html-build": "~0.3.2", 15 | "underscore": "*", 16 | "underscore.string": "*", 17 | "browserify": "~3.38.0", 18 | "grunt-browserify": "~1.3.0" 19 | }, 20 | "engines": { 21 | "node": ">=0.8.0", 22 | "npm": "1.3.x" 23 | }, 24 | "dependencies": { 25 | "express": "~3.4.7" 26 | } 27 | } -------------------------------------------------------------------------------- /templates/_main.js.tpl: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | //global variables 4 | window.onload = function () { 5 | var game = new Phaser.Game(<%= gameWidth %>, <%= gameHeight %>, Phaser.AUTO, '<%= _.slugify(projectName) %>'); 6 | 7 | // Game States 8 | <% _.forEach(gameStates, function(gameState) { %>game.state.add('<%= gameState.shortName %>', require('./states/<%= gameState.shortName %>')); 9 | <% }); %> 10 | 11 | game.state.start('boot'); 12 | }; --------------------------------------------------------------------------------