├── README.md ├── demo ├── 00-canvas.html ├── 01-physics.html ├── 02-keys.html ├── 03-bitmap.html ├── 04-bullets.html ├── 05-enemies.html ├── 06-spritesheets.html ├── 07-collisions.html ├── 08-text.html ├── 09-background.html ├── 10-sound.html ├── 11-states.html ├── 12-polish.html ├── img │ ├── bg-fade.png │ ├── bg.png │ ├── bullet.png │ ├── enemyRun.png │ ├── sparkle.png │ ├── title.png │ └── whitemage.png ├── index.html ├── keymaster.js └── sound │ ├── hit.wav │ ├── hurt.wav │ └── missile.wav └── jsGameDemo.pdf /README.md: -------------------------------------------------------------------------------- 1 | Here's a step-by-step guide to building a game from scratch in JavaScript. 2 | 3 | [Play it!](http://mimswright.com/games/huge-gamedemo/) 4 | 5 | Be sure to *View Source*! 6 | -------------------------------------------------------------------------------- /demo/00-canvas.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Game! 6 | 7 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /demo/01-physics.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Game! 6 | 7 | 144 | 145 | 146 | 147 |

click to add more

148 | 149 | -------------------------------------------------------------------------------- /demo/02-keys.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Game! 6 | 7 | 8 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /demo/03-bitmap.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Game! 6 | 7 | 8 | 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /demo/04-bullets.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Game! 6 | 7 | 8 | 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /demo/05-enemies.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Game! 6 | 7 | 8 | 228 | 229 | 230 | 231 | 232 | -------------------------------------------------------------------------------- /demo/06-spritesheets.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Game! 6 | 7 | 8 | 252 | 253 | 254 | 255 | 256 | -------------------------------------------------------------------------------- /demo/07-collisions.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Game! 6 | 7 | 8 | 286 | 287 | 288 | 289 | 290 | -------------------------------------------------------------------------------- /demo/08-text.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Game! 6 | 7 | 8 | 314 | 315 | 316 | 317 | 318 | -------------------------------------------------------------------------------- /demo/09-background.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Game! 6 | 7 | 8 | 341 | 342 | 343 | 344 | 345 | -------------------------------------------------------------------------------- /demo/10-sound.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Game! 6 | 7 | 8 | 350 | 351 | 352 | 353 | 354 | -------------------------------------------------------------------------------- /demo/11-states.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Game! 6 | 7 | 8 | 415 | 416 | 417 | 418 | 419 | -------------------------------------------------------------------------------- /demo/12-polish.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Game! 6 | 7 | 8 | 493 | 494 | 495 | 496 | 497 | -------------------------------------------------------------------------------- /demo/img/bg-fade.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mimshwright/jsGameDemo/a10349555632ac2bd3ba8fad00ab536d685424d5/demo/img/bg-fade.png -------------------------------------------------------------------------------- /demo/img/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mimshwright/jsGameDemo/a10349555632ac2bd3ba8fad00ab536d685424d5/demo/img/bg.png -------------------------------------------------------------------------------- /demo/img/bullet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mimshwright/jsGameDemo/a10349555632ac2bd3ba8fad00ab536d685424d5/demo/img/bullet.png -------------------------------------------------------------------------------- /demo/img/enemyRun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mimshwright/jsGameDemo/a10349555632ac2bd3ba8fad00ab536d685424d5/demo/img/enemyRun.png -------------------------------------------------------------------------------- /demo/img/sparkle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mimshwright/jsGameDemo/a10349555632ac2bd3ba8fad00ab536d685424d5/demo/img/sparkle.png -------------------------------------------------------------------------------- /demo/img/title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mimshwright/jsGameDemo/a10349555632ac2bd3ba8fad00ab536d685424d5/demo/img/title.png -------------------------------------------------------------------------------- /demo/img/whitemage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mimshwright/jsGameDemo/a10349555632ac2bd3ba8fad00ab536d685424d5/demo/img/whitemage.png -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Game! 6 | 11 | 12 | 13 |

jsGameDemo

14 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /demo/keymaster.js: -------------------------------------------------------------------------------- 1 | // keymaster.js 2 | // (c) 2011 Thomas Fuchs 3 | // keymaster.js may be freely distributed under the MIT license. 4 | 5 | ;(function(global){ 6 | var k, 7 | _handlers = {}, 8 | _mods = { 16: false, 18: false, 17: false, 91: false }, 9 | _scope = 'all', 10 | // modifier keys 11 | _MODIFIERS = { 12 | '⇧': 16, shift: 16, 13 | '⌥': 18, alt: 18, option: 18, 14 | '⌃': 17, ctrl: 17, control: 17, 15 | '⌘': 91, command: 91 16 | }, 17 | // special keys 18 | _MAP = { 19 | backspace: 8, tab: 9, clear: 12, 20 | enter: 13, 'return': 13, 21 | esc: 27, escape: 27, space: 32, 22 | left: 37, up: 38, 23 | right: 39, down: 40, 24 | del: 46, 'delete': 46, 25 | home: 36, end: 35, 26 | pageup: 33, pagedown: 34, 27 | ',': 188, '.': 190, '/': 191, 28 | '`': 192, '-': 189, '=': 187, 29 | ';': 186, '\'': 222, 30 | '[': 219, ']': 221, '\\': 220 31 | }, 32 | _downKeys = []; 33 | 34 | for(k=1;k<20;k++) _MODIFIERS['f'+k] = 111+k; 35 | 36 | // IE doesn't support Array#indexOf, so have a simple replacement 37 | function index(array, item){ 38 | var i = array.length; 39 | while(i--) if(array[i]===item) return i; 40 | return -1; 41 | } 42 | 43 | // handle keydown event 44 | function dispatch(event, scope){ 45 | var key, handler, k, i, modifiersMatch; 46 | key = event.keyCode; 47 | 48 | if (index(_downKeys, key) == -1) { 49 | _downKeys.push(key); 50 | } 51 | 52 | // if a modifier key, set the key. property to true and return 53 | if(key == 93 || key == 224) key = 91; // right command on webkit, command on Gecko 54 | if(key in _mods) { 55 | _mods[key] = true; 56 | // 'assignKey' from inside this closure is exported to window.key 57 | for(k in _MODIFIERS) if(_MODIFIERS[k] == key) assignKey[k] = true; 58 | return; 59 | } 60 | 61 | // see if we need to ignore the keypress (ftiler() can can be overridden) 62 | // by default ignore key presses if a select, textarea, or input is focused 63 | if(!assignKey.filter.call(this, event)) return; 64 | 65 | // abort if no potentially matching shortcuts found 66 | if (!(key in _handlers)) return; 67 | 68 | // for each potential shortcut 69 | for (i = 0; i < _handlers[key].length; i++) { 70 | handler = _handlers[key][i]; 71 | 72 | // see if it's in the current scope 73 | if(handler.scope == scope || handler.scope == 'all'){ 74 | // check if modifiers match if any 75 | modifiersMatch = handler.mods.length > 0; 76 | for(k in _mods) 77 | if((!_mods[k] && index(handler.mods, +k) > -1) || 78 | (_mods[k] && index(handler.mods, +k) == -1)) modifiersMatch = false; 79 | // call the handler and stop the event if neccessary 80 | if((handler.mods.length == 0 && !_mods[16] && !_mods[18] && !_mods[17] && !_mods[91]) || modifiersMatch){ 81 | if(handler.method(event, handler)===false){ 82 | if(event.preventDefault) event.preventDefault(); 83 | else event.returnValue = false; 84 | if(event.stopPropagation) event.stopPropagation(); 85 | if(event.cancelBubble) event.cancelBubble = true; 86 | } 87 | } 88 | } 89 | } 90 | }; 91 | 92 | // unset modifier keys on keyup 93 | function clearModifier(event){ 94 | var key = event.keyCode, k, 95 | i = index(_downKeys, key); 96 | 97 | // remove key from _downKeys 98 | if (i >= 0) { 99 | _downKeys.splice(i, 1); 100 | } 101 | 102 | if(key == 93 || key == 224) key = 91; 103 | if(key in _mods) { 104 | _mods[key] = false; 105 | for(k in _MODIFIERS) if(_MODIFIERS[k] == key) assignKey[k] = false; 106 | } 107 | }; 108 | 109 | function resetModifiers() { 110 | for(k in _mods) _mods[k] = false; 111 | for(k in _MODIFIERS) assignKey[k] = false; 112 | } 113 | 114 | // parse and assign shortcut 115 | function assignKey(key, scope, method){ 116 | var keys, mods, i, mi; 117 | if (method === undefined) { 118 | method = scope; 119 | scope = 'all'; 120 | } 121 | key = key.replace(/\s/g,''); 122 | keys = key.split(','); 123 | 124 | if((keys[keys.length-1])=='') 125 | keys[keys.length-2] += ','; 126 | // for each shortcut 127 | for (i = 0; i < keys.length; i++) { 128 | // set modifier keys if any 129 | mods = []; 130 | key = keys[i].split('+'); 131 | if(key.length > 1){ 132 | mods = key.slice(0,key.length-1); 133 | for (mi = 0; mi < mods.length; mi++) 134 | mods[mi] = _MODIFIERS[mods[mi]]; 135 | key = [key[key.length-1]]; 136 | } 137 | // convert to keycode and... 138 | key = key[0] 139 | key = _MAP[key] || key.toUpperCase().charCodeAt(0); 140 | // ...store handler 141 | if (!(key in _handlers)) _handlers[key] = []; 142 | _handlers[key].push({ shortcut: keys[i], scope: scope, method: method, key: keys[i], mods: mods }); 143 | } 144 | }; 145 | 146 | // Returns true if the key with code 'keyCode' is currently down 147 | // Converts strings into key codes. 148 | function isPressed(keyCode) { 149 | if (typeof(keyCode)=='string') { 150 | if (keyCode.length == 1) { 151 | keyCode = (keyCode.toUpperCase()).charCodeAt(0); 152 | } else { 153 | return false; 154 | } 155 | } 156 | return index(_downKeys, keyCode) != -1; 157 | } 158 | 159 | function getPressedKeyCodes() { 160 | return _downKeys; 161 | } 162 | 163 | function filter(event){ 164 | var tagName = (event.target || event.srcElement).tagName; 165 | // ignore keypressed in any elements that support keyboard data input 166 | return !(tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'TEXTAREA'); 167 | } 168 | 169 | // initialize key. to false 170 | for(k in _MODIFIERS) assignKey[k] = false; 171 | 172 | // set current scope (default 'all') 173 | function setScope(scope){ _scope = scope || 'all' }; 174 | function getScope(){ return _scope || 'all' }; 175 | 176 | // delete all handlers for a given scope 177 | function deleteScope(scope){ 178 | var key, handlers, i; 179 | 180 | for (key in _handlers) { 181 | handlers = _handlers[key]; 182 | for (i = 0; i < handlers.length; ) { 183 | if (handlers[i].scope === scope) handlers.splice(i, 1); 184 | else i++; 185 | } 186 | } 187 | }; 188 | 189 | // cross-browser events 190 | function addEvent(object, event, method) { 191 | if (object.addEventListener) 192 | object.addEventListener(event, method, false); 193 | else if(object.attachEvent) 194 | object.attachEvent('on'+event, function(){ method(window.event) }); 195 | }; 196 | 197 | // set the handlers globally on document 198 | addEvent(document, 'keydown', function(event) { dispatch(event, _scope) }); // Passing _scope to a callback to ensure it remains the same by execution. Fixes #48 199 | addEvent(document, 'keyup', clearModifier); 200 | 201 | // reset modifiers to false whenever the window is (re)focused. 202 | addEvent(window, 'focus', resetModifiers); 203 | 204 | // set window.key and window.key.set/get/deleteScope, and the default filter 205 | global.key = assignKey; 206 | global.key.setScope = setScope; 207 | global.key.getScope = getScope; 208 | global.key.deleteScope = deleteScope; 209 | global.key.filter = filter; 210 | global.key.isPressed = isPressed; 211 | global.key.getPressedKeyCodes = getPressedKeyCodes; 212 | 213 | if(typeof module !== 'undefined') module.exports = key; 214 | 215 | })(this); 216 | -------------------------------------------------------------------------------- /demo/sound/hit.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mimshwright/jsGameDemo/a10349555632ac2bd3ba8fad00ab536d685424d5/demo/sound/hit.wav -------------------------------------------------------------------------------- /demo/sound/hurt.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mimshwright/jsGameDemo/a10349555632ac2bd3ba8fad00ab536d685424d5/demo/sound/hurt.wav -------------------------------------------------------------------------------- /demo/sound/missile.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mimshwright/jsGameDemo/a10349555632ac2bd3ba8fad00ab536d685424d5/demo/sound/missile.wav -------------------------------------------------------------------------------- /jsGameDemo.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mimshwright/jsGameDemo/a10349555632ac2bd3ba8fad00ab536d685424d5/jsGameDemo.pdf --------------------------------------------------------------------------------