Created
July 18, 2013 04:42
-
-
Save chrisjacob/6026762 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Built with IMPACT - impactjs.org | |
(function (window) { | |
"use strict"; | |
Number.prototype.map = function (istart, istop, ostart, ostop) { | |
return ostart + (ostop - ostart) * ((this - istart) / (istop - istart)); | |
}; | |
Number.prototype.limit = function (min, max) { | |
return Math.min(max, Math.max(min, this)); | |
}; | |
Number.prototype.round = function (precision) { | |
precision = Math.pow(10, precision || 0); | |
return Math.round(this * precision) / precision; | |
}; | |
Number.prototype.floor = function () { | |
return Math.floor(this); | |
}; | |
Number.prototype.ceil = function () { | |
return Math.ceil(this); | |
}; | |
Number.prototype.toInt = function () { | |
return (this | 0); | |
}; | |
Number.prototype.toRad = function () { | |
return (this / 180) * Math.PI; | |
}; | |
Number.prototype.toDeg = function () { | |
return (this * 180) / Math.PI; | |
}; | |
Array.prototype.erase = function (item) { | |
for (var i = this.length; i--;) { | |
if (this[i] === item) { | |
this.splice(i, 1); | |
} | |
} | |
return this; | |
}; | |
Array.prototype.random = function () { | |
return this[Math.floor(Math.random() * this.length)]; | |
}; | |
Function.prototype.bind = Function.prototype.bind || function (oThis) { | |
if (typeof this !== "function") { | |
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); | |
} | |
var aArgs = Array.prototype.slice.call(arguments, 1), | |
fToBind = this, | |
fNOP = function () {}, fBound = function () { | |
return fToBind.apply((this instanceof fNOP && oThis ? this : oThis), aArgs.concat(Array.prototype.slice.call(arguments))); | |
}; | |
fNOP.prototype = this.prototype; | |
fBound.prototype = new fNOP(); | |
return fBound; | |
}; | |
window.ig = { | |
game: null, | |
debug: null, | |
version: '1.20', | |
global: window, | |
modules: {}, | |
resources: [], | |
ready: false, | |
baked: false, | |
nocache: '', | |
ua: {}, | |
prefix: (window.ImpactPrefix || ''), | |
lib: 'lib/', | |
_current: null, | |
_loadQueue: [], | |
_waitForOnload: 0, | |
$: function (selector) { | |
return selector.charAt(0) == '#' ? document.getElementById(selector.substr(1)) : document.getElementsByTagName(selector); | |
}, | |
$new: function (name) { | |
return document.createElement(name); | |
}, | |
copy: function (object) { | |
if (!object || typeof (object) != 'object' || object instanceof HTMLElement || object instanceof ig.Class) { | |
return object; | |
} else if (object instanceof Array) { | |
var c = []; | |
for (var i = 0, l = object.length; i < l; i++) { | |
c[i] = ig.copy(object[i]); | |
} | |
return c; | |
} else { | |
var c = {}; | |
for (var i in object) { | |
c[i] = ig.copy(object[i]); | |
} | |
return c; | |
} | |
}, | |
merge: function (original, extended) { | |
for (var key in extended) { | |
var ext = extended[key]; | |
if (typeof (ext) != 'object' || ext instanceof HTMLElement || ext instanceof ig.Class) { | |
original[key] = ext; | |
} else { | |
if (!original[key] || typeof (original[key]) != 'object') { | |
original[key] = (ext instanceof Array) ? [] : {}; | |
} | |
ig.merge(original[key], ext); | |
} | |
} | |
return original; | |
}, | |
ksort: function (obj) { | |
if (!obj || typeof (obj) != 'object') { | |
return []; | |
} | |
var keys = [], | |
values = []; | |
for (var i in obj) { | |
keys.push(i); | |
} | |
keys.sort(); | |
for (var i = 0; i < keys.length; i++) { | |
values.push(obj[keys[i]]); | |
} | |
return values; | |
}, | |
setVendorAttribute: function (el, attr, val) { | |
var uc = attr.charAt(0).toUpperCase() + attr.substr(1); | |
el[attr] = el['ms' + uc] = el['moz' + uc] = el['webkit' + uc] = el['o' + uc] = val; | |
}, | |
getVendorAttribute: function (el, attr) { | |
var uc = attr.charAt(0).toUpperCase() + attr.substr(1); | |
return el[attr] || el['ms' + uc] || el['moz' + uc] || el['webkit' + uc] || el['o' + uc]; | |
}, | |
normalizeVendorAttribute: function (el, attr) { | |
var prefixedVal = ig.getVendorAttribute(el, attr); | |
if (!el[attr] && prefixedVal) { | |
el[attr] = prefixedVal; | |
} | |
}, | |
getImagePixels: function (image, x, y, width, height) { | |
var canvas = ig.$new('canvas'); | |
canvas.width = image.width; | |
canvas.height = image.height; | |
var ctx = canvas.getContext('2d'); | |
var ratio = ig.getVendorAttribute(ctx, 'backingStorePixelRatio') || 1; | |
ig.normalizeVendorAttribute(ctx, 'getImageDataHD'); | |
var realWidth = image.width / ratio, | |
realHeight = image.height / ratio; | |
canvas.width = Math.ceil(realWidth); | |
canvas.height = Math.ceil(realHeight); | |
ctx.drawImage(image, 0, 0, realWidth, realHeight); | |
return (ratio === 1) ? ctx.getImageData(x, y, width, height) : ctx.getImageDataHD(x, y, width, height); | |
}, | |
module: function (name) { | |
if (ig._current) { | |
throw ("Module '" + ig._current.name + "' defines nothing"); | |
} | |
if (ig.modules[name] && ig.modules[name].body) { | |
throw ("Module '" + name + "' is already defined"); | |
} | |
ig._current = { | |
name: name, | |
requires: [], | |
loaded: false, | |
body: null | |
}; | |
ig.modules[name] = ig._current; | |
ig._loadQueue.push(ig._current); | |
return ig; | |
}, | |
requires: function () { | |
ig._current.requires = Array.prototype.slice.call(arguments); | |
return ig; | |
}, | |
defines: function (body) { | |
ig._current.body = body; | |
ig._current = null; | |
ig._initDOMReady(); | |
}, | |
addResource: function (resource) { | |
ig.resources.push(resource); | |
}, | |
setNocache: function (set) { | |
ig.nocache = set ? '?' + Date.now() : ''; | |
}, | |
log: function () {}, | |
assert: function (condition, msg) {}, | |
show: function (name, number) {}, | |
mark: function (msg, color) {}, | |
_loadScript: function (name, requiredFrom) { | |
ig.modules[name] = { | |
name: name, | |
requires: [], | |
loaded: false, | |
body: null | |
}; | |
ig._waitForOnload++; | |
var path = ig.prefix + ig.lib + name.replace(/\./g, '/') + '.js' + ig.nocache; | |
var script = ig.$new('script'); | |
script.type = 'text/javascript'; | |
script.src = path; | |
script.onload = function () { | |
ig._waitForOnload--; | |
ig._execModules(); | |
}; | |
script.onerror = function () { | |
throw ('Failed to load module ' + name + ' at ' + path + ' ' + 'required from ' + requiredFrom); | |
}; | |
ig.$('head')[0].appendChild(script); | |
}, | |
_execModules: function () { | |
var modulesLoaded = false; | |
for (var i = 0; i < ig._loadQueue.length; i++) { | |
var m = ig._loadQueue[i]; | |
var dependenciesLoaded = true; | |
for (var j = 0; j < m.requires.length; j++) { | |
var name = m.requires[j]; | |
if (!ig.modules[name]) { | |
dependenciesLoaded = false; | |
ig._loadScript(name, m.name); | |
} else if (!ig.modules[name].loaded) { | |
dependenciesLoaded = false; | |
} | |
} | |
if (dependenciesLoaded && m.body) { | |
ig._loadQueue.splice(i, 1); | |
m.loaded = true; | |
m.body(); | |
modulesLoaded = true; | |
i--; | |
} | |
} | |
if (modulesLoaded) { | |
ig._execModules(); | |
} else if (!ig.baked && ig._waitForOnload == 0 && ig._loadQueue.length != 0) { | |
var unresolved = []; | |
for (var i = 0; i < ig._loadQueue.length; i++) { | |
var unloaded = []; | |
var requires = ig._loadQueue[i].requires; | |
for (var j = 0; j < requires.length; j++) { | |
var m = ig.modules[requires[j]]; | |
if (!m || !m.loaded) { | |
unloaded.push(requires[j]); | |
} | |
} | |
unresolved.push(ig._loadQueue[i].name + ' (requires: ' + unloaded.join(', ') + ')'); | |
} | |
throw ('Unresolved (circular?) dependencies. ' + "Most likely there's a name/path mismatch for one of the listed modules:\n" + | |
unresolved.join('\n')); | |
} | |
}, | |
_DOMReady: function () { | |
if (!ig.modules['dom.ready'].loaded) { | |
if (!document.body) { | |
return setTimeout(ig._DOMReady, 13); | |
} | |
ig.modules['dom.ready'].loaded = true; | |
ig._waitForOnload--; | |
ig._execModules(); | |
} | |
return 0; | |
}, | |
_boot: function () { | |
if (document.location.href.match(/\?nocache/)) { | |
ig.setNocache(true); | |
} | |
ig.ua.pixelRatio = window.devicePixelRatio || 1; | |
ig.ua.viewport = { | |
width: window.innerWidth, | |
height: window.innerHeight | |
}; | |
ig.ua.screen = { | |
width: window.screen.availWidth * ig.ua.pixelRatio, | |
height: window.screen.availHeight * ig.ua.pixelRatio | |
}; | |
ig.ua.iPhone = /iPhone/i.test(navigator.userAgent); | |
ig.ua.iPhone4 = (ig.ua.iPhone && ig.ua.pixelRatio == 2); | |
ig.ua.iPad = /iPad/i.test(navigator.userAgent); | |
ig.ua.android = /android/i.test(navigator.userAgent); | |
ig.ua.iOS = ig.ua.iPhone || ig.ua.iPad; | |
ig.ua.mobile = ig.ua.iOS || ig.ua.android; | |
}, | |
_initDOMReady: function () { | |
if (ig.modules['dom.ready']) { | |
ig._execModules(); | |
return; | |
} | |
ig._boot(); | |
ig.modules['dom.ready'] = { | |
requires: [], | |
loaded: false, | |
body: null | |
}; | |
ig._waitForOnload++; | |
if (document.readyState === 'complete') { | |
ig._DOMReady(); | |
} else { | |
document.addEventListener('DOMContentLoaded', ig._DOMReady, false); | |
window.addEventListener('load', ig._DOMReady, false); | |
} | |
} | |
}; | |
ig.normalizeVendorAttribute(window, 'requestAnimationFrame'); | |
if (window.requestAnimationFrame) { | |
var next = 1, | |
anims = {}; | |
window.ig.setAnimation = function (callback, element) { | |
var current = next++; | |
anims[current] = true; | |
var animate = function () { | |
if (!anims[current]) { | |
return; | |
} | |
window.requestAnimationFrame(animate, element); | |
callback(); | |
}; | |
window.requestAnimationFrame(animate, element); | |
return current; | |
}; | |
window.ig.clearAnimation = function (id) { | |
delete anims[id]; | |
}; | |
} else { | |
window.ig.setAnimation = function (callback, element) { | |
return window.setInterval(callback, 1000 / 60); | |
}; | |
window.ig.clearAnimation = function (id) { | |
window.clearInterval(id); | |
}; | |
} | |
var initializing = false, | |
fnTest = /xyz/.test(function () { | |
xyz; | |
}) ? /\bparent\b/ : /.*/; | |
window.ig.Class = function () {}; | |
var inject = function (prop) { | |
var proto = this.prototype; | |
var parent = {}; | |
for (var name in prop) { | |
if (typeof (prop[name]) == "function" && typeof (proto[name]) == "function" && fnTest.test(prop[name])) { | |
parent[name] = proto[name]; | |
proto[name] = (function (name, fn) { | |
return function () { | |
var tmp = this.parent; | |
this.parent = parent[name]; | |
var ret = fn.apply(this, arguments); | |
this.parent = tmp; | |
return ret; | |
}; | |
})(name, prop[name]); | |
} else { | |
proto[name] = prop[name]; | |
} | |
} | |
}; | |
window.ig.Class.extend = function (prop) { | |
var parent = this.prototype; | |
initializing = true; | |
var prototype = new this(); | |
initializing = false; | |
for (var name in prop) { | |
if (typeof (prop[name]) == "function" && typeof (parent[name]) == "function" && fnTest.test(prop[name])) { | |
prototype[name] = (function (name, fn) { | |
return function () { | |
var tmp = this.parent; | |
this.parent = parent[name]; | |
var ret = fn.apply(this, arguments); | |
this.parent = tmp; | |
return ret; | |
}; | |
})(name, prop[name]); | |
} else { | |
prototype[name] = prop[name]; | |
} | |
} | |
function Class() { | |
if (!initializing) { | |
if (this.staticInstantiate) { | |
var obj = this.staticInstantiate.apply(this, arguments); | |
if (obj) { | |
return obj; | |
} | |
} | |
for (var p in this) { | |
if (typeof (this[p]) == 'object') { | |
this[p] = ig.copy(this[p]); | |
} | |
} | |
if (this.init) { | |
this.init.apply(this, arguments); | |
} | |
} | |
return this; | |
} | |
Class.prototype = prototype; | |
Class.prototype.constructor = Class; | |
Class.extend = window.ig.Class.extend; | |
Class.inject = inject; | |
return Class; | |
}; | |
})(window); | |
// lib/impact/image.js | |
ig.baked = true; | |
ig.module('impact.image').defines(function () { | |
"use strict"; | |
ig.Image = ig.Class.extend({ | |
data: null, | |
width: 0, | |
height: 0, | |
loaded: false, | |
failed: false, | |
loadCallback: null, | |
path: '', | |
staticInstantiate: function (path) { | |
return ig.Image.cache[path] || null; | |
}, | |
init: function (path) { | |
this.path = path; | |
this.load(); | |
}, | |
load: function (loadCallback) { | |
if (this.loaded) { | |
if (loadCallback) { | |
loadCallback(this.path, true); | |
} | |
return; | |
} else if (!this.loaded && ig.ready) { | |
this.loadCallback = loadCallback || null; | |
this.data = new Image(); | |
this.data.onload = this.onload.bind(this); | |
this.data.onerror = this.onerror.bind(this); | |
this.data.src = ig.prefix + this.path + ig.nocache; | |
} else { | |
ig.addResource(this); | |
} | |
ig.Image.cache[this.path] = this; | |
}, | |
reload: function () { | |
this.loaded = false; | |
this.data = new Image(); | |
this.data.onload = this.onload.bind(this); | |
this.data.src = this.path + '?' + Date.now(); | |
}, | |
onload: function (event) { | |
this.width = this.data.width; | |
this.height = this.data.height; | |
this.loaded = true; | |
if (ig.system.scale != 1) { | |
this.resize(ig.system.scale); | |
} | |
if (this.loadCallback) { | |
this.loadCallback(this.path, true); | |
} | |
}, | |
onerror: function (event) { | |
this.failed = true; | |
if (this.loadCallback) { | |
this.loadCallback(this.path, false); | |
} | |
}, | |
resize: function (scale) { | |
var origPixels = ig.getImagePixels(this.data, 0, 0, this.width, this.height); | |
var widthScaled = this.width * scale; | |
var heightScaled = this.height * scale; | |
var scaled = ig.$new('canvas'); | |
scaled.width = widthScaled; | |
scaled.height = heightScaled; | |
var scaledCtx = scaled.getContext('2d'); | |
var scaledPixels = scaledCtx.getImageData(0, 0, widthScaled, heightScaled); | |
for (var y = 0; y < heightScaled; y++) { | |
for (var x = 0; x < widthScaled; x++) { | |
var index = (Math.floor(y / scale) * this.width + Math.floor(x / scale)) * 4; | |
var indexScaled = (y * widthScaled + x) * 4; | |
scaledPixels.data[indexScaled] = origPixels.data[index]; | |
scaledPixels.data[indexScaled + 1] = origPixels.data[index + 1]; | |
scaledPixels.data[indexScaled + 2] = origPixels.data[index + 2]; | |
scaledPixels.data[indexScaled + 3] = origPixels.data[index + 3]; | |
} | |
} | |
scaledCtx.putImageData(scaledPixels, 0, 0); | |
this.data = scaled; | |
}, | |
draw: function (targetX, targetY, sourceX, sourceY, width, height) { | |
if (!this.loaded) { | |
return; | |
} | |
var scale = ig.system.scale; | |
sourceX = sourceX ? sourceX * scale : 0; | |
sourceY = sourceY ? sourceY * scale : 0; | |
width = (width ? width : this.width) * scale; | |
height = (height ? height : this.height) * scale; | |
ig.system.context.drawImage(this.data, sourceX, sourceY, width, height, ig.system.getDrawPos(targetX), ig.system.getDrawPos(targetY), width, height); | |
ig.Image.drawCount++; | |
}, | |
drawTile: function (targetX, targetY, tile, tileWidth, tileHeight, flipX, flipY) { | |
tileHeight = tileHeight ? tileHeight : tileWidth; | |
if (!this.loaded || tileWidth > this.width || tileHeight > this.height) { | |
return; | |
} | |
var scale = ig.system.scale; | |
var tileWidthScaled = Math.floor(tileWidth * scale); | |
var tileHeightScaled = Math.floor(tileHeight * scale); | |
var scaleX = flipX ? -1 : 1; | |
var scaleY = flipY ? -1 : 1; | |
if (flipX || flipY) { | |
ig.system.context.save(); | |
ig.system.context.scale(scaleX, scaleY); | |
} | |
ig.system.context.drawImage(this.data, (Math.floor(tile * tileWidth) % this.width) * scale, (Math.floor(tile * tileWidth / this.width) * tileHeight) * scale, tileWidthScaled, tileHeightScaled, ig.system.getDrawPos(targetX) * scaleX - (flipX ? tileWidthScaled : 0), ig.system.getDrawPos(targetY) * scaleY - (flipY ? tileHeightScaled : 0), tileWidthScaled, tileHeightScaled); | |
if (flipX || flipY) { | |
ig.system.context.restore(); | |
} | |
ig.Image.drawCount++; | |
} | |
}); | |
ig.Image.drawCount = 0; | |
ig.Image.cache = {}; | |
ig.Image.reloadCache = function () { | |
for (var path in ig.Image.cache) { | |
ig.Image.cache[path].reload(); | |
} | |
}; | |
}); | |
// lib/impact/font.js | |
ig.baked = true; | |
ig.module('impact.font').requires('impact.image').defines(function () { | |
"use strict"; | |
ig.Font = ig.Image.extend({ | |
widthMap: [], | |
indices: [], | |
firstChar: 32, | |
alpha: 1, | |
letterSpacing: 1, | |
lineSpacing: 0, | |
onload: function (ev) { | |
this._loadMetrics(this.data); | |
this.parent(ev); | |
}, | |
widthForString: function (text) { | |
if (text.indexOf('\n') !== -1) { | |
var lines = text.split('\n'); | |
var width = 0; | |
for (var i = 0; i < lines.length; i++) { | |
width = Math.max(width, this._widthForLine(lines[i])); | |
} | |
return width; | |
} else { | |
return this._widthForLine(text); | |
} | |
}, | |
_widthForLine: function (text) { | |
var width = 0; | |
for (var i = 0; i < text.length; i++) { | |
width += this.widthMap[text.charCodeAt(i) - this.firstChar] + this.letterSpacing; | |
} | |
return width; | |
}, | |
heightForString: function (text) { | |
return text.split('\n').length * (this.height + this.lineSpacing); | |
}, | |
draw: function (text, x, y, align) { | |
if (typeof (text) != 'string') { | |
text = text.toString(); | |
} | |
if (text.indexOf('\n') !== -1) { | |
var lines = text.split('\n'); | |
var lineHeight = this.height + this.lineSpacing; | |
for (var i = 0; i < lines.length; i++) { | |
this.draw(lines[i], x, y + i * lineHeight, align); | |
} | |
return; | |
} | |
if (align == ig.Font.ALIGN.RIGHT || align == ig.Font.ALIGN.CENTER) { | |
var width = this._widthForLine(text); | |
x -= align == ig.Font.ALIGN.CENTER ? width / 2 : width; | |
} | |
if (this.alpha !== 1) { | |
ig.system.context.globalAlpha = this.alpha; | |
} | |
for (var i = 0; i < text.length; i++) { | |
var c = text.charCodeAt(i); | |
x += this._drawChar(c - this.firstChar, x, y); | |
} | |
if (this.alpha !== 1) { | |
ig.system.context.globalAlpha = 1; | |
} | |
ig.Image.drawCount += text.length; | |
}, | |
_drawChar: function (c, targetX, targetY) { | |
if (!this.loaded || c < 0 || c >= this.indices.length) { | |
return 0; | |
} | |
var scale = ig.system.scale; | |
var charX = this.indices[c] * scale; | |
var charY = 0; | |
var charWidth = this.widthMap[c] * scale; | |
var charHeight = (this.height - 2) * scale; | |
ig.system.context.drawImage(this.data, charX, charY, charWidth, charHeight, ig.system.getDrawPos(targetX), ig.system.getDrawPos(targetY), charWidth, charHeight); | |
return this.widthMap[c] + this.letterSpacing; | |
}, | |
_loadMetrics: function (image) { | |
this.height = image.height - 1; | |
this.widthMap = []; | |
this.indices = []; | |
var px = ig.getImagePixels(image, 0, image.height - 1, image.width, 1); | |
var currentChar = 0; | |
var currentWidth = 0; | |
for (var x = 0; x < image.width; x++) { | |
var index = x * 4 + 3; | |
if (px.data[index] > 127) { | |
currentWidth++; | |
} else if (px.data[index] == 0 && currentWidth) { | |
this.widthMap.push(currentWidth); | |
this.indices.push(x - currentWidth); | |
currentChar++; | |
currentWidth = 0; | |
} | |
} | |
this.widthMap.push(currentWidth); | |
this.indices.push(x - currentWidth); | |
} | |
}); | |
ig.Font.ALIGN = { | |
LEFT: 0, | |
RIGHT: 1, | |
CENTER: 2 | |
}; | |
}); | |
// lib/impact/sound.js | |
ig.baked = true; | |
ig.module('impact.sound').defines(function () { | |
"use strict"; | |
ig.SoundManager = ig.Class.extend({ | |
clips: {}, | |
volume: 1, | |
format: null, | |
init: function () { | |
if (!ig.Sound.enabled || !window.Audio) { | |
ig.Sound.enabled = false; | |
return; | |
} | |
var probe = new Audio(); | |
for (var i = 0; i < ig.Sound.use.length; i++) { | |
var format = ig.Sound.use[i]; | |
if (probe.canPlayType(format.mime)) { | |
this.format = format; | |
break; | |
} | |
} | |
if (!this.format) { | |
ig.Sound.enabled = false; | |
} | |
}, | |
load: function (path, multiChannel, loadCallback) { | |
var realPath = ig.prefix + path.replace(/[^\.]+$/, this.format.ext) + ig.nocache; | |
if (this.clips[path]) { | |
if (multiChannel && this.clips[path].length < ig.Sound.channels) { | |
for (var i = this.clips[path].length; i < ig.Sound.channels; i++) { | |
var a = new Audio(realPath); | |
a.load(); | |
this.clips[path].push(a); | |
} | |
} | |
return this.clips[path][0]; | |
} | |
var clip = new Audio(realPath); | |
if (loadCallback) { | |
clip.addEventListener('canplaythrough', function cb(ev) { | |
clip.removeEventListener('canplaythrough', cb, false); | |
loadCallback(path, true, ev); | |
}, false); | |
clip.addEventListener('error', function (ev) { | |
loadCallback(path, false, ev); | |
}, false); | |
} | |
clip.preload = 'auto'; | |
clip.load(); | |
this.clips[path] = [clip]; | |
if (multiChannel) { | |
for (var i = 1; i < ig.Sound.channels; i++) { | |
var a = new Audio(realPath); | |
a.load(); | |
this.clips[path].push(a); | |
} | |
} | |
return clip; | |
}, | |
get: function (path) { | |
var channels = this.clips[path]; | |
for (var i = 0, clip; clip = channels[i++];) { | |
if (clip.paused || clip.ended) { | |
if (clip.ended) { | |
clip.currentTime = 0; | |
} | |
return clip; | |
} | |
} | |
channels[0].pause(); | |
channels[0].currentTime = 0; | |
return channels[0]; | |
} | |
}); | |
ig.Music = ig.Class.extend({ | |
tracks: [], | |
namedTracks: {}, | |
currentTrack: null, | |
currentIndex: 0, | |
random: false, | |
_volume: 1, | |
_loop: false, | |
_fadeInterval: 0, | |
_fadeTimer: null, | |
_endedCallbackBound: null, | |
init: function () { | |
this._endedCallbackBound = this._endedCallback.bind(this); | |
if (Object.defineProperty) { | |
Object.defineProperty(this, "volume", { | |
get: this.getVolume.bind(this), | |
set: this.setVolume.bind(this) | |
}); | |
Object.defineProperty(this, "loop", { | |
get: this.getLooping.bind(this), | |
set: this.setLooping.bind(this) | |
}); | |
} else if (this.__defineGetter__) { | |
this.__defineGetter__('volume', this.getVolume.bind(this)); | |
this.__defineSetter__('volume', this.setVolume.bind(this)); | |
this.__defineGetter__('loop', this.getLooping.bind(this)); | |
this.__defineSetter__('loop', this.setLooping.bind(this)); | |
} | |
}, | |
add: function (music, name) { | |
if (!ig.Sound.enabled) { | |
return; | |
} | |
var path = music instanceof ig.Sound ? music.path : music; | |
var track = ig.soundManager.load(path, false); | |
track.loop = this._loop; | |
track.volume = this._volume; | |
track.addEventListener('ended', this._endedCallbackBound, false); | |
this.tracks.push(track); | |
if (name) { | |
this.namedTracks[name] = track; | |
} | |
if (!this.currentTrack) { | |
this.currentTrack = track; | |
} | |
}, | |
next: function () { | |
if (!this.tracks.length) { | |
return; | |
} | |
this.stop(); | |
this.currentIndex = this.random ? Math.floor(Math.random() * this.tracks.length) : (this.currentIndex + 1) % this.tracks.length; | |
this.currentTrack = this.tracks[this.currentIndex]; | |
this.play(); | |
}, | |
pause: function () { | |
if (!this.currentTrack) { | |
return; | |
} | |
this.currentTrack.pause(); | |
}, | |
stop: function () { | |
if (!this.currentTrack) { | |
return; | |
} | |
this.currentTrack.pause(); | |
this.currentTrack.currentTime = 0; | |
}, | |
play: function (name) { | |
if (name && this.namedTracks[name]) { | |
var newTrack = this.namedTracks[name]; | |
if (newTrack != this.currentTrack) { | |
this.stop(); | |
this.currentTrack = newTrack; | |
} | |
} else if (!this.currentTrack) { | |
return; | |
} | |
this.currentTrack.play(); | |
}, | |
getLooping: function () { | |
return this._loop; | |
}, | |
setLooping: function (l) { | |
this._loop = l; | |
for (var i in this.tracks) { | |
this.tracks[i].loop = l; | |
} | |
}, | |
getVolume: function () { | |
return this._volume; | |
}, | |
setVolume: function (v) { | |
this._volume = v.limit(0, 1); | |
for (var i in this.tracks) { | |
this.tracks[i].volume = this._volume; | |
} | |
}, | |
fadeOut: function (time) { | |
if (!this.currentTrack) { | |
return; | |
} | |
clearInterval(this._fadeInterval); | |
this.fadeTimer = new ig.Timer(time); | |
this._fadeInterval = setInterval(this._fadeStep.bind(this), 50); | |
}, | |
_fadeStep: function () { | |
var v = this.fadeTimer.delta().map(-this.fadeTimer.target, 0, 1, 0).limit(0, 1) * this._volume; | |
if (v <= 0.01) { | |
this.stop(); | |
this.currentTrack.volume = this._volume; | |
clearInterval(this._fadeInterval); | |
} else { | |
this.currentTrack.volume = v; | |
} | |
}, | |
_endedCallback: function () { | |
if (this._loop) { | |
this.play(); | |
} else { | |
this.next(); | |
} | |
} | |
}); | |
ig.Sound = ig.Class.extend({ | |
path: '', | |
volume: 1, | |
currentClip: null, | |
multiChannel: true, | |
init: function (path, multiChannel) { | |
this.path = path; | |
this.multiChannel = (multiChannel !== false); | |
this.load(); | |
}, | |
load: function (loadCallback) { | |
if (!ig.Sound.enabled) { | |
if (loadCallback) { | |
loadCallback(this.path, true); | |
} | |
return; | |
} | |
if (ig.ready) { | |
ig.soundManager.load(this.path, this.multiChannel, loadCallback); | |
} else { | |
ig.addResource(this); | |
} | |
}, | |
play: function () { | |
if (!ig.Sound.enabled) { | |
return; | |
} | |
this.currentClip = ig.soundManager.get(this.path); | |
this.currentClip.volume = ig.soundManager.volume * this.volume; | |
this.currentClip.play(); | |
}, | |
stop: function () { | |
if (this.currentClip) { | |
this.currentClip.pause(); | |
this.currentClip.currentTime = 0; | |
} | |
} | |
}); | |
ig.Sound.FORMAT = { | |
MP3: { | |
ext: 'mp3', | |
mime: 'audio/mpeg' | |
}, | |
M4A: { | |
ext: 'm4a', | |
mime: 'audio/mp4; codecs=mp4a' | |
}, | |
OGG: { | |
ext: 'ogg', | |
mime: 'audio/ogg; codecs=vorbis' | |
}, | |
WEBM: { | |
ext: 'webm', | |
mime: 'audio/webm; codecs=vorbis' | |
}, | |
CAF: { | |
ext: 'caf', | |
mime: 'audio/x-caf' | |
} | |
}; | |
ig.Sound.use = [ig.Sound.FORMAT.OGG, ig.Sound.FORMAT.MP3]; | |
ig.Sound.channels = 4; | |
ig.Sound.enabled = true; | |
}); | |
// lib/impact/loader.js | |
ig.baked = true; | |
ig.module('impact.loader').requires('impact.image', 'impact.font', 'impact.sound').defines(function () { | |
"use strict"; | |
ig.Loader = ig.Class.extend({ | |
resources: [], | |
gameClass: null, | |
status: 0, | |
done: false, | |
_unloaded: [], | |
_drawStatus: 0, | |
_intervalId: 0, | |
_loadCallbackBound: null, | |
init: function (gameClass, resources) { | |
this.gameClass = gameClass; | |
this.resources = resources; | |
this._loadCallbackBound = this._loadCallback.bind(this); | |
for (var i = 0; i < this.resources.length; i++) { | |
this._unloaded.push(this.resources[i].path); | |
} | |
}, | |
load: function () { | |
ig.system.clear('#000'); | |
if (!this.resources.length) { | |
this.end(); | |
return; | |
} | |
for (var i = 0; i < this.resources.length; i++) { | |
this.loadResource(this.resources[i]); | |
} | |
this._intervalId = setInterval(this.draw.bind(this), 16); | |
}, | |
loadResource: function (res) { | |
res.load(this._loadCallbackBound); | |
}, | |
end: function () { | |
if (this.done) { | |
return; | |
} | |
this.done = true; | |
clearInterval(this._intervalId); | |
ig.system.setGame(this.gameClass); | |
}, | |
draw: function () { | |
this._drawStatus += (this.status - this._drawStatus) / 5; | |
var s = ig.system.scale; | |
var w = ig.system.width * 0.6; | |
var h = ig.system.height * 0.1; | |
var x = ig.system.width * 0.5 - w / 2; | |
var y = ig.system.height * 0.5 - h / 2; | |
ig.system.context.fillStyle = '#000'; | |
ig.system.context.fillRect(0, 0, 480, 320); | |
ig.system.context.fillStyle = '#fff'; | |
ig.system.context.fillRect(x * s, y * s, w * s, h * s); | |
ig.system.context.fillStyle = '#000'; | |
ig.system.context.fillRect(x * s + s, y * s + s, w * s - s - s, h * s - s - s); | |
ig.system.context.fillStyle = '#fff'; | |
ig.system.context.fillRect(x * s, y * s, w * s * this._drawStatus, h * s); | |
}, | |
_loadCallback: function (path, status) { | |
if (status) { | |
this._unloaded.erase(path); | |
} else { | |
throw ('Failed to load resource: ' + path); | |
} | |
this.status = 1 - (this._unloaded.length / this.resources.length); | |
if (this._unloaded.length == 0) { | |
setTimeout(this.end.bind(this), 250); | |
} | |
} | |
}); | |
}); | |
// lib/impact/timer.js | |
ig.baked = true; | |
ig.module('impact.timer').defines(function () { | |
"use strict"; | |
ig.Timer = ig.Class.extend({ | |
target: 0, | |
base: 0, | |
last: 0, | |
pausedAt: 0, | |
init: function (seconds) { | |
this.base = ig.Timer.time; | |
this.last = ig.Timer.time; | |
this.target = seconds || 0; | |
}, | |
set: function (seconds) { | |
this.target = seconds || 0; | |
this.base = ig.Timer.time; | |
this.pausedAt = 0; | |
}, | |
reset: function () { | |
this.base = ig.Timer.time; | |
this.pausedAt = 0; | |
}, | |
tick: function () { | |
var delta = ig.Timer.time - this.last; | |
this.last = ig.Timer.time; | |
return (this.pausedAt ? 0 : delta); | |
}, | |
delta: function () { | |
return (this.pausedAt || ig.Timer.time) - this.base - this.target; | |
}, | |
pause: function () { | |
if (!this.pausedAt) { | |
this.pausedAt = ig.Timer.time; | |
} | |
}, | |
unpause: function () { | |
if (this.pausedAt) { | |
this.base += ig.Timer.time - this.pausedAt; | |
this.pausedAt = 0; | |
} | |
} | |
}); | |
ig.Timer._last = 0; | |
ig.Timer.time = Number.MIN_VALUE; | |
ig.Timer.timeScale = 1; | |
ig.Timer.maxStep = 0.05; | |
ig.Timer.step = function () { | |
var current = Date.now(); | |
var delta = (current - ig.Timer._last) / 1000; | |
ig.Timer.time += Math.min(delta, ig.Timer.maxStep) * ig.Timer.timeScale; | |
ig.Timer._last = current; | |
}; | |
}); | |
// lib/impact/system.js | |
ig.baked = true; | |
ig.module('impact.system').requires('impact.timer', 'impact.image').defines(function () { | |
"use strict"; | |
ig.System = ig.Class.extend({ | |
fps: 30, | |
width: 320, | |
height: 240, | |
realWidth: 320, | |
realHeight: 240, | |
scale: 1, | |
tick: 0, | |
animationId: 0, | |
newGameClass: null, | |
running: false, | |
delegate: null, | |
clock: null, | |
canvas: null, | |
context: null, | |
init: function (canvasId, fps, width, height, scale) { | |
this.fps = fps; | |
this.clock = new ig.Timer(); | |
this.canvas = ig.$(canvasId); | |
this.resize(width, height, scale); | |
this.context = this.canvas.getContext('2d'); | |
this.getDrawPos = ig.System.drawMode; | |
if (this.scale != 1) { | |
ig.System.scaleMode = ig.System.SCALE.CRISP; | |
} | |
ig.System.scaleMode(this.canvas, this.context); | |
}, | |
resize: function (width, height, scale) { | |
this.width = width; | |
this.height = height; | |
this.scale = scale || this.scale; | |
this.realWidth = this.width * this.scale; | |
this.realHeight = this.height * this.scale; | |
this.canvas.width = this.realWidth; | |
this.canvas.height = this.realHeight; | |
}, | |
setGame: function (gameClass) { | |
if (this.running) { | |
this.newGameClass = gameClass; | |
} else { | |
this.setGameNow(gameClass); | |
} | |
}, | |
setGameNow: function (gameClass) { | |
ig.game = new(gameClass)(); | |
ig.system.setDelegate(ig.game); | |
}, | |
setDelegate: function (object) { | |
if (typeof (object.run) == 'function') { | |
this.delegate = object; | |
this.startRunLoop(); | |
} else { | |
throw ('System.setDelegate: No run() function in object'); | |
} | |
}, | |
stopRunLoop: function () { | |
ig.clearAnimation(this.animationId); | |
this.running = false; | |
}, | |
startRunLoop: function () { | |
this.stopRunLoop(); | |
this.animationId = ig.setAnimation(this.run.bind(this), this.canvas); | |
this.running = true; | |
}, | |
clear: function (color) { | |
this.context.fillStyle = color; | |
this.context.fillRect(0, 0, this.realWidth, this.realHeight); | |
}, | |
run: function () { | |
ig.Timer.step(); | |
this.tick = this.clock.tick(); | |
this.delegate.run(); | |
ig.input.clearPressed(); | |
if (this.newGameClass) { | |
this.setGameNow(this.newGameClass); | |
this.newGameClass = null; | |
} | |
}, | |
getDrawPos: null | |
}); | |
ig.System.DRAW = { | |
AUTHENTIC: function (p) { | |
return Math.round(p) * this.scale; | |
}, | |
SMOOTH: function (p) { | |
return Math.round(p * this.scale); | |
}, | |
SUBPIXEL: function (p) { | |
return p * this.scale; | |
} | |
}; | |
ig.System.drawMode = ig.System.DRAW.SMOOTH; | |
ig.System.SCALE = { | |
CRISP: function (canvas, context) { | |
ig.setVendorAttribute(context, 'imageSmoothingEnabled', false); | |
canvas.style.imageRendering = '-moz-crisp-edges'; | |
canvas.style.imageRendering = '-o-crisp-edges'; | |
canvas.style.imageRendering = '-webkit-optimize-contrast'; | |
canvas.style.imageRendering = 'crisp-edges'; | |
canvas.style.msInterpolationMode = 'nearest-neighbor'; | |
}, | |
SMOOTH: function (canvas, context) { | |
ig.setVendorAttribute(context, 'imageSmoothingEnabled', true); | |
canvas.style.imageRendering = ''; | |
canvas.style.msInterpolationMode = ''; | |
} | |
}; | |
ig.System.scaleMode = ig.System.SCALE.SMOOTH; | |
}); | |
// lib/impact/input.js | |
ig.baked = true; | |
ig.module('impact.input').defines(function () { | |
"use strict"; | |
ig.KEY = { | |
'MOUSE1': -1, | |
'MOUSE2': -3, | |
'MWHEEL_UP': -4, | |
'MWHEEL_DOWN': -5, | |
'BACKSPACE': 8, | |
'TAB': 9, | |
'ENTER': 13, | |
'PAUSE': 19, | |
'CAPS': 20, | |
'ESC': 27, | |
'SPACE': 32, | |
'PAGE_UP': 33, | |
'PAGE_DOWN': 34, | |
'END': 35, | |
'HOME': 36, | |
'LEFT_ARROW': 37, | |
'UP_ARROW': 38, | |
'RIGHT_ARROW': 39, | |
'DOWN_ARROW': 40, | |
'INSERT': 45, | |
'DELETE': 46, | |
'_0': 48, | |
'_1': 49, | |
'_2': 50, | |
'_3': 51, | |
'_4': 52, | |
'_5': 53, | |
'_6': 54, | |
'_7': 55, | |
'_8': 56, | |
'_9': 57, | |
'A': 65, | |
'B': 66, | |
'C': 67, | |
'D': 68, | |
'E': 69, | |
'F': 70, | |
'G': 71, | |
'H': 72, | |
'I': 73, | |
'J': 74, | |
'K': 75, | |
'L': 76, | |
'M': 77, | |
'N': 78, | |
'O': 79, | |
'P': 80, | |
'Q': 81, | |
'R': 82, | |
'S': 83, | |
'T': 84, | |
'U': 85, | |
'V': 86, | |
'W': 87, | |
'X': 88, | |
'Y': 89, | |
'Z': 90, | |
'NUMPAD_0': 96, | |
'NUMPAD_1': 97, | |
'NUMPAD_2': 98, | |
'NUMPAD_3': 99, | |
'NUMPAD_4': 100, | |
'NUMPAD_5': 101, | |
'NUMPAD_6': 102, | |
'NUMPAD_7': 103, | |
'NUMPAD_8': 104, | |
'NUMPAD_9': 105, | |
'MULTIPLY': 106, | |
'ADD': 107, | |
'SUBSTRACT': 109, | |
'DECIMAL': 110, | |
'DIVIDE': 111, | |
'F1': 112, | |
'F2': 113, | |
'F3': 114, | |
'F4': 115, | |
'F5': 116, | |
'F6': 117, | |
'F7': 118, | |
'F8': 119, | |
'F9': 120, | |
'F10': 121, | |
'F11': 122, | |
'F12': 123, | |
'SHIFT': 16, | |
'CTRL': 17, | |
'ALT': 18, | |
'PLUS': 187, | |
'COMMA': 188, | |
'MINUS': 189, | |
'PERIOD': 190 | |
}; | |
ig.Input = ig.Class.extend({ | |
bindings: {}, | |
actions: {}, | |
presses: {}, | |
locks: {}, | |
delayedKeyup: {}, | |
isUsingMouse: false, | |
isUsingKeyboard: false, | |
isUsingAccelerometer: false, | |
mouse: { | |
x: 0, | |
y: 0 | |
}, | |
accel: { | |
x: 0, | |
y: 0, | |
z: 0 | |
}, | |
initMouse: function () { | |
if (this.isUsingMouse) { | |
return; | |
} | |
this.isUsingMouse = true; | |
var mouseWheelBound = this.mousewheel.bind(this); | |
ig.system.canvas.addEventListener('mousewheel', mouseWheelBound, false); | |
ig.system.canvas.addEventListener('DOMMouseScroll', mouseWheelBound, false); | |
ig.system.canvas.addEventListener('contextmenu', this.contextmenu.bind(this), false); | |
ig.system.canvas.addEventListener('mousedown', this.keydown.bind(this), false); | |
ig.system.canvas.addEventListener('mouseup', this.keyup.bind(this), false); | |
ig.system.canvas.addEventListener('mousemove', this.mousemove.bind(this), false); | |
ig.system.canvas.addEventListener('touchstart', this.keydown.bind(this), false); | |
ig.system.canvas.addEventListener('touchend', this.keyup.bind(this), false); | |
ig.system.canvas.addEventListener('touchmove', this.mousemove.bind(this), false); | |
}, | |
initKeyboard: function () { | |
if (this.isUsingKeyboard) { | |
return; | |
} | |
this.isUsingKeyboard = true; | |
window.addEventListener('keydown', this.keydown.bind(this), false); | |
window.addEventListener('keyup', this.keyup.bind(this), false); | |
}, | |
initAccelerometer: function () { | |
if (this.isUsingAccelerometer) { | |
return; | |
} | |
window.addEventListener('devicemotion', this.devicemotion.bind(this), false); | |
}, | |
mousewheel: function (event) { | |
var delta = event.wheelDelta ? event.wheelDelta : (event.detail * -1); | |
var code = delta > 0 ? ig.KEY.MWHEEL_UP : ig.KEY.MWHEEL_DOWN; | |
var action = this.bindings[code]; | |
if (action) { | |
this.actions[action] = true; | |
this.presses[action] = true; | |
this.delayedKeyup[action] = true; | |
event.stopPropagation(); | |
event.preventDefault(); | |
} | |
}, | |
getEventPosition: function (event) { | |
var internalWidth = parseInt(ig.system.canvas.offsetWidth) || ig.system.realWidth; | |
var scale = ig.system.scale * (internalWidth / ig.system.realWidth); | |
var pos = { | |
left: 0, | |
top: 0 | |
}; | |
if (ig.system.canvas.getBoundingClientRect) { | |
pos = ig.system.canvas.getBoundingClientRect(); | |
} | |
return { | |
x: (event.clientX - pos.left) / scale, | |
y: (event.clientY - pos.top) / scale | |
}; | |
}, | |
mousemove: function (event) { | |
ig.input.mouse = this.getEventPosition(event.touches ? event.touches[0] : event); | |
}, | |
contextmenu: function (event) { | |
if (this.bindings[ig.KEY.MOUSE2]) { | |
event.stopPropagation(); | |
event.preventDefault(); | |
} | |
}, | |
keydown: function (event) { | |
var tag = event.target.tagName; | |
if (tag == 'INPUT' || tag == 'TEXTAREA') { | |
return; | |
} | |
var code = event.type == 'keydown' ? event.keyCode : (event.button == 2 ? ig.KEY.MOUSE2 : ig.KEY.MOUSE1); | |
if (event.type == 'touchstart' || event.type == 'mousedown') { | |
this.mousemove(event); | |
} | |
var action = this.bindings[code]; | |
if (action) { | |
this.actions[action] = true; | |
if (!this.locks[action]) { | |
this.presses[action] = true; | |
this.locks[action] = true; | |
} | |
event.stopPropagation(); | |
event.preventDefault(); | |
} | |
}, | |
keyup: function (event) { | |
var tag = event.target.tagName; | |
if (tag == 'INPUT' || tag == 'TEXTAREA') { | |
return; | |
} | |
var code = event.type == 'keyup' ? event.keyCode : (event.button == 2 ? ig.KEY.MOUSE2 : ig.KEY.MOUSE1); | |
var action = this.bindings[code]; | |
if (action) { | |
this.delayedKeyup[action] = true; | |
event.stopPropagation(); | |
event.preventDefault(); | |
} | |
}, | |
devicemotion: function (event) { | |
this.accel = event.accelerationIncludingGravity; | |
}, | |
bind: function (key, action) { | |
if (key < 0) { | |
this.initMouse(); | |
} else if (key > 0) { | |
this.initKeyboard(); | |
} | |
this.bindings[key] = action; | |
}, | |
bindTouch: function (selector, action) { | |
var element = ig.$(selector); | |
var that = this; | |
element.addEventListener('touchstart', function (ev) { | |
that.touchStart(ev, action); | |
}, false); | |
element.addEventListener('touchend', function (ev) { | |
that.touchEnd(ev, action); | |
}, false); | |
}, | |
unbind: function (key) { | |
var action = this.bindings[key]; | |
this.delayedKeyup[action] = true; | |
this.bindings[key] = null; | |
}, | |
unbindAll: function () { | |
this.bindings = {}; | |
this.actions = {}; | |
this.presses = {}; | |
this.locks = {}; | |
this.delayedKeyup = {}; | |
}, | |
state: function (action) { | |
return this.actions[action]; | |
}, | |
pressed: function (action) { | |
return this.presses[action]; | |
}, | |
released: function (action) { | |
return this.delayedKeyup[action]; | |
}, | |
clearPressed: function () { | |
for (var action in this.delayedKeyup) { | |
this.actions[action] = false; | |
this.locks[action] = false; | |
} | |
this.delayedKeyup = {}; | |
this.presses = {}; | |
}, | |
touchStart: function (event, action) { | |
this.actions[action] = true; | |
this.presses[action] = true; | |
event.stopPropagation(); | |
event.preventDefault(); | |
return false; | |
}, | |
touchEnd: function (event, action) { | |
this.delayedKeyup[action] = true; | |
event.stopPropagation(); | |
event.preventDefault(); | |
return false; | |
} | |
}); | |
}); | |
// lib/impact/impact.js | |
ig.baked = true; | |
ig.module('impact.impact').requires('dom.ready', 'impact.loader', 'impact.system', 'impact.input', 'impact.sound').defines(function () { | |
"use strict"; | |
ig.main = function (canvasId, gameClass, fps, width, height, scale, loaderClass) { | |
ig.system = new ig.System(canvasId, fps, width, height, scale || 1); | |
ig.input = new ig.Input(); | |
ig.soundManager = new ig.SoundManager(); | |
ig.music = new ig.Music(); | |
ig.ready = true; | |
var loader = new(loaderClass || ig.Loader)(gameClass, ig.resources); | |
loader.load(); | |
}; | |
}); | |
// lib/impact/animation.js | |
ig.baked = true; | |
ig.module('impact.animation').requires('impact.timer', 'impact.image').defines(function () { | |
"use strict"; | |
ig.AnimationSheet = ig.Class.extend({ | |
width: 8, | |
height: 8, | |
image: null, | |
init: function (path, width, height) { | |
this.width = width; | |
this.height = height; | |
this.image = new ig.Image(path); | |
} | |
}); | |
ig.Animation = ig.Class.extend({ | |
sheet: null, | |
timer: null, | |
sequence: [], | |
flip: { | |
x: false, | |
y: false | |
}, | |
pivot: { | |
x: 0, | |
y: 0 | |
}, | |
frame: 0, | |
tile: 0, | |
loopCount: 0, | |
alpha: 1, | |
angle: 0, | |
init: function (sheet, frameTime, sequence, stop) { | |
this.sheet = sheet; | |
this.pivot = { | |
x: sheet.width / 2, | |
y: sheet.height / 2 | |
}; | |
this.timer = new ig.Timer(); | |
this.frameTime = frameTime; | |
this.sequence = sequence; | |
this.stop = !! stop; | |
this.tile = this.sequence[0]; | |
}, | |
rewind: function () { | |
this.timer.set(); | |
this.loopCount = 0; | |
this.tile = this.sequence[0]; | |
return this; | |
}, | |
gotoFrame: function (f) { | |
this.timer.set(this.frameTime * -f); | |
this.update(); | |
}, | |
gotoRandomFrame: function () { | |
this.gotoFrame(Math.floor(Math.random() * this.sequence.length)) | |
}, | |
update: function () { | |
var frameTotal = Math.floor(this.timer.delta() / this.frameTime); | |
this.loopCount = Math.floor(frameTotal / this.sequence.length); | |
if (this.stop && this.loopCount > 0) { | |
this.frame = this.sequence.length - 1; | |
} else { | |
this.frame = frameTotal % this.sequence.length; | |
} | |
this.tile = this.sequence[this.frame]; | |
}, | |
draw: function (targetX, targetY) { | |
var bbsize = Math.max(this.sheet.width, this.sheet.height); | |
if (targetX > ig.system.width || targetY > ig.system.height || targetX + bbsize < 0 || targetY + bbsize < 0) { | |
return; | |
} | |
if (this.alpha != 1) { | |
ig.system.context.globalAlpha = this.alpha; | |
} | |
if (this.angle == 0) { | |
this.sheet.image.drawTile(targetX, targetY, this.tile, this.sheet.width, this.sheet.height, this.flip.x, this.flip.y); | |
} else { | |
ig.system.context.save(); | |
ig.system.context.translate(ig.system.getDrawPos(targetX + this.pivot.x), ig.system.getDrawPos(targetY + this.pivot.y)); | |
ig.system.context.rotate(this.angle); | |
this.sheet.image.drawTile(-this.pivot.x, -this.pivot.y, this.tile, this.sheet.width, this.sheet.height, this.flip.x, this.flip.y); | |
ig.system.context.restore(); | |
} | |
if (this.alpha != 1) { | |
ig.system.context.globalAlpha = 1; | |
} | |
} | |
}); | |
}); | |
// lib/impact/entity.js | |
ig.baked = true; | |
ig.module('impact.entity').requires('impact.animation', 'impact.impact').defines(function () { | |
"use strict"; | |
ig.Entity = ig.Class.extend({ | |
id: 0, | |
settings: {}, | |
size: { | |
x: 16, | |
y: 16 | |
}, | |
offset: { | |
x: 0, | |
y: 0 | |
}, | |
pos: { | |
x: 0, | |
y: 0 | |
}, | |
last: { | |
x: 0, | |
y: 0 | |
}, | |
vel: { | |
x: 0, | |
y: 0 | |
}, | |
accel: { | |
x: 0, | |
y: 0 | |
}, | |
friction: { | |
x: 0, | |
y: 0 | |
}, | |
maxVel: { | |
x: 100, | |
y: 100 | |
}, | |
zIndex: 0, | |
gravityFactor: 1, | |
standing: false, | |
bounciness: 0, | |
minBounceVelocity: 40, | |
anims: {}, | |
animSheet: null, | |
currentAnim: null, | |
health: 10, | |
type: 0, | |
checkAgainst: 0, | |
collides: 0, | |
_killed: false, | |
slopeStanding: { | |
min: (44).toRad(), | |
max: (136).toRad() | |
}, | |
init: function (x, y, settings) { | |
this.id = ++ig.Entity._lastId; | |
this.pos.x = x; | |
this.pos.y = y; | |
ig.merge(this, settings); | |
}, | |
addAnim: function (name, frameTime, sequence, stop) { | |
if (!this.animSheet) { | |
throw ('No animSheet to add the animation ' + name + ' to.'); | |
} | |
var a = new ig.Animation(this.animSheet, frameTime, sequence, stop); | |
this.anims[name] = a; | |
if (!this.currentAnim) { | |
this.currentAnim = a; | |
} | |
return a; | |
}, | |
update: function () { | |
this.last.x = this.pos.x; | |
this.last.y = this.pos.y; | |
this.vel.y += ig.game.gravity * ig.system.tick * this.gravityFactor; | |
this.vel.x = this.getNewVelocity(this.vel.x, this.accel.x, this.friction.x, this.maxVel.x); | |
this.vel.y = this.getNewVelocity(this.vel.y, this.accel.y, this.friction.y, this.maxVel.y); | |
var mx = this.vel.x * ig.system.tick; | |
var my = this.vel.y * ig.system.tick; | |
var res = ig.game.collisionMap.trace(this.pos.x, this.pos.y, mx, my, this.size.x, this.size.y); | |
this.handleMovementTrace(res); | |
if (this.currentAnim) { | |
this.currentAnim.update(); | |
} | |
}, | |
getNewVelocity: function (vel, accel, friction, max) { | |
if (accel) { | |
return (vel + accel * ig.system.tick).limit(-max, max); | |
} else if (friction) { | |
var delta = friction * ig.system.tick; | |
if (vel - delta > 0) { | |
return vel - delta; | |
} else if (vel + delta < 0) { | |
return vel + delta; | |
} else { | |
return 0; | |
} | |
} | |
return vel.limit(-max, max); | |
}, | |
handleMovementTrace: function (res) { | |
this.standing = false; | |
if (res.collision.y) { | |
if (this.bounciness > 0 && Math.abs(this.vel.y) > this.minBounceVelocity) { | |
this.vel.y *= -this.bounciness; | |
} else { | |
if (this.vel.y > 0) { | |
this.standing = true; | |
} | |
this.vel.y = 0; | |
} | |
} | |
if (res.collision.x) { | |
if (this.bounciness > 0 && Math.abs(this.vel.x) > this.minBounceVelocity) { | |
this.vel.x *= -this.bounciness; | |
} else { | |
this.vel.x = 0; | |
} | |
} | |
if (res.collision.slope) { | |
var s = res.collision.slope; | |
if (this.bounciness > 0) { | |
var proj = this.vel.x * s.nx + this.vel.y * s.ny; | |
this.vel.x = (this.vel.x - s.nx * proj * 2) * this.bounciness; | |
this.vel.y = (this.vel.y - s.ny * proj * 2) * this.bounciness; | |
} else { | |
var lengthSquared = s.x * s.x + s.y * s.y; | |
var dot = (this.vel.x * s.x + this.vel.y * s.y) / lengthSquared; | |
this.vel.x = s.x * dot; | |
this.vel.y = s.y * dot; | |
var angle = Math.atan2(s.x, s.y); | |
if (angle > this.slopeStanding.min && angle < this.slopeStanding.max) { | |
this.standing = true; | |
} | |
} | |
} | |
this.pos = res.pos; | |
}, | |
draw: function () { | |
if (this.currentAnim) { | |
this.currentAnim.draw(this.pos.x - this.offset.x - ig.game._rscreen.x, this.pos.y - this.offset.y - ig.game._rscreen.y); | |
} | |
}, | |
kill: function () { | |
ig.game.removeEntity(this); | |
}, | |
receiveDamage: function (amount, from) { | |
this.health -= amount; | |
if (this.health <= 0) { | |
this.kill(); | |
} | |
}, | |
touches: function (other) { | |
return !(this.pos.x >= other.pos.x + other.size.x || this.pos.x + this.size.x <= other.pos.x || this.pos.y >= other.pos.y + other.size.y || this.pos.y + this.size.y <= other.pos.y); | |
}, | |
distanceTo: function (other) { | |
var xd = (this.pos.x + this.size.x / 2) - (other.pos.x + other.size.x / 2); | |
var yd = (this.pos.y + this.size.y / 2) - (other.pos.y + other.size.y / 2); | |
return Math.sqrt(xd * xd + yd * yd); | |
}, | |
angleTo: function (other) { | |
return Math.atan2((other.pos.y + other.size.y / 2) - (this.pos.y + this.size.y / 2), (other.pos.x + other.size.x / 2) - (this.pos.x + this.size.x / 2)); | |
}, | |
check: function (other) {}, | |
collideWith: function (other, axis) {}, | |
ready: function () {} | |
}); | |
ig.Entity._lastId = 0; | |
ig.Entity.COLLIDES = { | |
NEVER: 0, | |
LITE: 1, | |
PASSIVE: 2, | |
ACTIVE: 4, | |
FIXED: 8 | |
}; | |
ig.Entity.TYPE = { | |
NONE: 0, | |
A: 1, | |
B: 2, | |
BOTH: 3 | |
}; | |
ig.Entity.checkPair = function (a, b) { | |
if (a.checkAgainst & b.type) { | |
a.check(b); | |
} | |
if (b.checkAgainst & a.type) { | |
b.check(a); | |
} | |
if (a.collides && b.collides && a.collides + b.collides > ig.Entity.COLLIDES.ACTIVE) { | |
ig.Entity.solveCollision(a, b); | |
} | |
}; | |
ig.Entity.solveCollision = function (a, b) { | |
var weak = null; | |
if (a.collides == ig.Entity.COLLIDES.LITE || b.collides == ig.Entity.COLLIDES.FIXED) { | |
weak = a; | |
} else if (b.collides == ig.Entity.COLLIDES.LITE || a.collides == ig.Entity.COLLIDES.FIXED) { | |
weak = b; | |
} | |
if (a.last.x + a.size.x > b.last.x && a.last.x < b.last.x + b.size.x) { | |
if (a.last.y < b.last.y) { | |
ig.Entity.seperateOnYAxis(a, b, weak); | |
} else { | |
ig.Entity.seperateOnYAxis(b, a, weak); | |
} | |
a.collideWith(b, 'y'); | |
b.collideWith(a, 'y'); | |
} else if (a.last.y + a.size.y > b.last.y && a.last.y < b.last.y + b.size.y) { | |
if (a.last.x < b.last.x) { | |
ig.Entity.seperateOnXAxis(a, b, weak); | |
} else { | |
ig.Entity.seperateOnXAxis(b, a, weak); | |
} | |
a.collideWith(b, 'x'); | |
b.collideWith(a, 'x'); | |
} | |
}; | |
ig.Entity.seperateOnXAxis = function (left, right, weak) { | |
var nudge = (left.pos.x + left.size.x - right.pos.x); | |
if (weak) { | |
var strong = left === weak ? right : left; | |
weak.vel.x = -weak.vel.x * weak.bounciness + strong.vel.x; | |
var resWeak = ig.game.collisionMap.trace(weak.pos.x, weak.pos.y, weak == left ? -nudge : nudge, 0, weak.size.x, weak.size.y); | |
weak.pos.x = resWeak.pos.x; | |
} else { | |
var v2 = (left.vel.x - right.vel.x) / 2; | |
left.vel.x = -v2; | |
right.vel.x = v2; | |
var resLeft = ig.game.collisionMap.trace(left.pos.x, left.pos.y, -nudge / 2, 0, left.size.x, left.size.y); | |
left.pos.x = Math.floor(resLeft.pos.x); | |
var resRight = ig.game.collisionMap.trace(right.pos.x, right.pos.y, nudge / 2, 0, right.size.x, right.size.y); | |
right.pos.x = Math.ceil(resRight.pos.x); | |
} | |
}; | |
ig.Entity.seperateOnYAxis = function (top, bottom, weak) { | |
var nudge = (top.pos.y + top.size.y - bottom.pos.y); | |
if (weak) { | |
var strong = top === weak ? bottom : top; | |
weak.vel.y = -weak.vel.y * weak.bounciness + strong.vel.y; | |
var nudgeX = 0; | |
if (weak == top && Math.abs(weak.vel.y - strong.vel.y) < weak.minBounceVelocity) { | |
weak.standing = true; | |
nudgeX = strong.vel.x * ig.system.tick; | |
} | |
var resWeak = ig.game.collisionMap.trace(weak.pos.x, weak.pos.y, nudgeX, weak == top ? -nudge : nudge, weak.size.x, weak.size.y); | |
weak.pos.y = resWeak.pos.y; | |
weak.pos.x = resWeak.pos.x; | |
} else if (ig.game.gravity && (bottom.standing || top.vel.y > 0)) { | |
var resTop = ig.game.collisionMap.trace(top.pos.x, top.pos.y, 0, -(top.pos.y + top.size.y - bottom.pos.y), top.size.x, top.size.y); | |
top.pos.y = resTop.pos.y; | |
if (top.bounciness > 0 && top.vel.y > top.minBounceVelocity) { | |
top.vel.y *= -top.bounciness; | |
} else { | |
top.standing = true; | |
top.vel.y = 0; | |
} | |
} else { | |
var v2 = (top.vel.y - bottom.vel.y) / 2; | |
top.vel.y = -v2; | |
bottom.vel.y = v2; | |
var nudgeX = bottom.vel.x * ig.system.tick; | |
var resTop = ig.game.collisionMap.trace(top.pos.x, top.pos.y, nudgeX, -nudge / 2, top.size.x, top.size.y); | |
top.pos.y = resTop.pos.y; | |
var resBottom = ig.game.collisionMap.trace(bottom.pos.x, bottom.pos.y, 0, nudge / 2, bottom.size.x, bottom.size.y); | |
bottom.pos.y = resBottom.pos.y; | |
} | |
}; | |
}); | |
// lib/impact/map.js | |
ig.baked = true; | |
ig.module('impact.map').defines(function () { | |
"use strict"; | |
ig.Map = ig.Class.extend({ | |
tilesize: 8, | |
width: 1, | |
height: 1, | |
data: [ | |
[] | |
], | |
name: null, | |
init: function (tilesize, data) { | |
this.tilesize = tilesize; | |
this.data = data; | |
this.height = data.length; | |
this.width = data[0].length; | |
}, | |
getTile: function (x, y) { | |
var tx = Math.floor(x / this.tilesize); | |
var ty = Math.floor(y / this.tilesize); | |
if ((tx >= 0 && tx < this.width) && (ty >= 0 && ty < this.height)) { | |
return this.data[ty][tx]; | |
} else { | |
return 0; | |
} | |
}, | |
setTile: function (x, y, tile) { | |
var tx = Math.floor(x / this.tilesize); | |
var ty = Math.floor(y / this.tilesize); | |
if ((tx >= 0 && tx < this.width) && (ty >= 0 && ty < this.height)) { | |
this.data[ty][tx] = tile; | |
} | |
} | |
}); | |
}); | |
// lib/impact/collision-map.js | |
ig.baked = true; | |
ig.module('impact.collision-map').requires('impact.map').defines(function () { | |
"use strict"; | |
ig.CollisionMap = ig.Map.extend({ | |
lastSlope: 1, | |
tiledef: null, | |
init: function (tilesize, data, tiledef) { | |
this.parent(tilesize, data); | |
this.tiledef = tiledef || ig.CollisionMap.defaultTileDef; | |
for (var t in this.tiledef) { | |
if (t | 0 > this.lastSlope) { | |
this.lastSlope = t | 0; | |
} | |
} | |
}, | |
trace: function (x, y, vx, vy, objectWidth, objectHeight) { | |
var res = { | |
collision: { | |
x: false, | |
y: false, | |
slope: false | |
}, | |
pos: { | |
x: x, | |
y: y | |
}, | |
tile: { | |
x: 0, | |
y: 0 | |
} | |
}; | |
var steps = Math.ceil(Math.max(Math.abs(vx), Math.abs(vy)) / this.tilesize); | |
if (steps > 1) { | |
var sx = vx / steps; | |
var sy = vy / steps; | |
for (var i = 0; i < steps && (sx || sy); i++) { | |
this._traceStep(res, x, y, sx, sy, objectWidth, objectHeight, vx, vy, i); | |
x = res.pos.x; | |
y = res.pos.y; | |
if (res.collision.x) { | |
sx = 0; | |
vx = 0; | |
} | |
if (res.collision.y) { | |
sy = 0; | |
vy = 0; | |
} | |
if (res.collision.slope) { | |
break; | |
} | |
} | |
} else { | |
this._traceStep(res, x, y, vx, vy, objectWidth, objectHeight, vx, vy, 0); | |
} | |
return res; | |
}, | |
_traceStep: function (res, x, y, vx, vy, width, height, rvx, rvy, step) { | |
res.pos.x += vx; | |
res.pos.y += vy; | |
var t = 0; | |
if (vx) { | |
var pxOffsetX = (vx > 0 ? width : 0); | |
var tileOffsetX = (vx < 0 ? this.tilesize : 0); | |
var firstTileY = Math.max(Math.floor(y / this.tilesize), 0); | |
var lastTileY = Math.min(Math.ceil((y + height) / this.tilesize), this.height); | |
var tileX = Math.floor((res.pos.x + pxOffsetX) / this.tilesize); | |
var prevTileX = Math.floor((x + pxOffsetX) / this.tilesize); | |
if (step > 0 || tileX == prevTileX || prevTileX < 0 || prevTileX >= this.width) { | |
prevTileX = -1; | |
} | |
if (tileX >= 0 && tileX < this.width) { | |
for (var tileY = firstTileY; tileY < lastTileY; tileY++) { | |
if (prevTileX != -1) { | |
t = this.data[tileY][prevTileX]; | |
if (t > 1 && t <= this.lastSlope && this._checkTileDef(res, t, x, y, rvx, rvy, width, height, prevTileX, tileY)) { | |
break; | |
} | |
} | |
t = this.data[tileY][tileX]; | |
if (t == 1 || t > this.lastSlope || (t > 1 && this._checkTileDef(res, t, x, y, rvx, rvy, width, height, tileX, tileY))) { | |
if (t > 1 && t <= this.lastSlope && res.collision.slope) { | |
break; | |
} | |
res.collision.x = true; | |
res.tile.x = t; | |
x = res.pos.x = tileX * this.tilesize - pxOffsetX + tileOffsetX; | |
rvx = 0; | |
break; | |
} | |
} | |
} | |
} | |
if (vy) { | |
var pxOffsetY = (vy > 0 ? height : 0); | |
var tileOffsetY = (vy < 0 ? this.tilesize : 0); | |
var firstTileX = Math.max(Math.floor(res.pos.x / this.tilesize), 0); | |
var lastTileX = Math.min(Math.ceil((res.pos.x + width) / this.tilesize), this.width); | |
var tileY = Math.floor((res.pos.y + pxOffsetY) / this.tilesize); | |
var prevTileY = Math.floor((y + pxOffsetY) / this.tilesize); | |
if (step > 0 || tileY == prevTileY || prevTileY < 0 || prevTileY >= this.height) { | |
prevTileY = -1; | |
} | |
if (tileY >= 0 && tileY < this.height) { | |
for (var tileX = firstTileX; tileX < lastTileX; tileX++) { | |
if (prevTileY != -1) { | |
t = this.data[prevTileY][tileX]; | |
if (t > 1 && t <= this.lastSlope && this._checkTileDef(res, t, x, y, rvx, rvy, width, height, tileX, prevTileY)) { | |
break; | |
} | |
} | |
t = this.data[tileY][tileX]; | |
if (t == 1 || t > this.lastSlope || (t > 1 && this._checkTileDef(res, t, x, y, rvx, rvy, width, height, tileX, tileY))) { | |
if (t > 1 && t <= this.lastSlope && res.collision.slope) { | |
break; | |
} | |
res.collision.y = true; | |
res.tile.y = t; | |
res.pos.y = tileY * this.tilesize - pxOffsetY + tileOffsetY; | |
break; | |
} | |
} | |
} | |
} | |
}, | |
_checkTileDef: function (res, t, x, y, vx, vy, width, height, tileX, tileY) { | |
var def = this.tiledef[t]; | |
if (!def) { | |
return false; | |
} | |
var lx = (tileX + def[0]) * this.tilesize, | |
ly = (tileY + def[1]) * this.tilesize, | |
lvx = (def[2] - def[0]) * this.tilesize, | |
lvy = (def[3] - def[1]) * this.tilesize, | |
solid = def[4]; | |
var tx = x + vx + (lvy < 0 ? width : 0) - lx, | |
ty = y + vy + (lvx > 0 ? height : 0) - ly; | |
if (lvx * ty - lvy * tx > 0) { | |
if (vx * -lvy + vy * lvx < 0) { | |
return solid; | |
} | |
var length = Math.sqrt(lvx * lvx + lvy * lvy); | |
var nx = lvy / length, | |
ny = -lvx / length; | |
var proj = tx * nx + ty * ny; | |
var px = nx * proj, | |
py = ny * proj; | |
if (px * px + py * py >= vx * vx + vy * vy) { | |
return solid || (lvx * (ty - vy) - lvy * (tx - vx) < 0.5); | |
} | |
res.pos.x = x + vx - px; | |
res.pos.y = y + vy - py; | |
res.collision.slope = { | |
x: lvx, | |
y: lvy, | |
nx: nx, | |
ny: ny | |
}; | |
return true; | |
} | |
return false; | |
} | |
}); | |
var H = 1 / 2, | |
N = 1 / 3, | |
M = 2 / 3, | |
SOLID = true, | |
NON_SOLID = false; | |
ig.CollisionMap.defaultTileDef = { | |
5: [0, 1, 1, M, SOLID], | |
6: [0, M, 1, N, SOLID], | |
7: [0, N, 1, 0, SOLID], | |
3: [0, 1, 1, H, SOLID], | |
4: [0, H, 1, 0, SOLID], | |
2: [0, 1, 1, 0, SOLID], | |
10: [H, 1, 1, 0, SOLID], | |
21: [0, 1, H, 0, SOLID], | |
32: [M, 1, 1, 0, SOLID], | |
43: [N, 1, M, 0, SOLID], | |
54: [0, 1, N, 0, SOLID], | |
27: [0, 0, 1, N, SOLID], | |
28: [0, N, 1, M, SOLID], | |
29: [0, M, 1, 1, SOLID], | |
25: [0, 0, 1, H, SOLID], | |
26: [0, H, 1, 1, SOLID], | |
24: [0, 0, 1, 1, SOLID], | |
11: [0, 0, H, 1, SOLID], | |
22: [H, 0, 1, 1, SOLID], | |
33: [0, 0, N, 1, SOLID], | |
44: [N, 0, M, 1, SOLID], | |
55: [M, 0, 1, 1, SOLID], | |
16: [1, N, 0, 0, SOLID], | |
17: [1, M, 0, N, SOLID], | |
18: [1, 1, 0, M, SOLID], | |
14: [1, H, 0, 0, SOLID], | |
15: [1, 1, 0, H, SOLID], | |
13: [1, 1, 0, 0, SOLID], | |
8: [H, 1, 0, 0, SOLID], | |
19: [1, 1, H, 0, SOLID], | |
30: [N, 1, 0, 0, SOLID], | |
41: [M, 1, N, 0, SOLID], | |
52: [1, 1, M, 0, SOLID], | |
38: [1, M, 0, 1, SOLID], | |
39: [1, N, 0, M, SOLID], | |
40: [1, 0, 0, N, SOLID], | |
36: [1, H, 0, 1, SOLID], | |
37: [1, 0, 0, H, SOLID], | |
35: [1, 0, 0, 1, SOLID], | |
9: [1, 0, H, 1, SOLID], | |
20: [H, 0, 0, 1, SOLID], | |
31: [1, 0, M, 1, SOLID], | |
42: [M, 0, N, 1, SOLID], | |
53: [N, 0, 0, 1, SOLID], | |
12: [0, 0, 1, 0, NON_SOLID], | |
23: [1, 1, 0, 1, NON_SOLID], | |
34: [1, 0, 1, 1, NON_SOLID], | |
45: [0, 1, 0, 0, NON_SOLID] | |
}; | |
ig.CollisionMap.staticNoCollision = { | |
trace: function (x, y, vx, vy) { | |
return { | |
collision: { | |
x: false, | |
y: false, | |
slope: false | |
}, | |
pos: { | |
x: x + vx, | |
y: y + vy | |
}, | |
tile: { | |
x: 0, | |
y: 0 | |
} | |
}; | |
} | |
}; | |
}); | |
// lib/impact/background-map.js | |
ig.baked = true; | |
ig.module('impact.background-map').requires('impact.map', 'impact.image').defines(function () { | |
"use strict"; | |
ig.BackgroundMap = ig.Map.extend({ | |
tiles: null, | |
scroll: { | |
x: 0, | |
y: 0 | |
}, | |
distance: 1, | |
repeat: false, | |
tilesetName: '', | |
foreground: false, | |
enabled: true, | |
preRender: false, | |
preRenderedChunks: null, | |
chunkSize: 512, | |
debugChunks: false, | |
anims: {}, | |
init: function (tilesize, data, tileset) { | |
this.parent(tilesize, data); | |
this.setTileset(tileset); | |
}, | |
setTileset: function (tileset) { | |
this.tilesetName = tileset instanceof ig.Image ? tileset.path : tileset; | |
this.tiles = new ig.Image(this.tilesetName); | |
this.preRenderedChunks = null; | |
}, | |
setScreenPos: function (x, y) { | |
this.scroll.x = x / this.distance; | |
this.scroll.y = y / this.distance; | |
}, | |
preRenderMapToChunks: function () { | |
var totalWidth = this.width * this.tilesize * ig.system.scale, | |
totalHeight = this.height * this.tilesize * ig.system.scale; | |
var chunkCols = Math.ceil(totalWidth / this.chunkSize), | |
chunkRows = Math.ceil(totalHeight / this.chunkSize); | |
this.preRenderedChunks = []; | |
for (var y = 0; y < chunkRows; y++) { | |
this.preRenderedChunks[y] = []; | |
for (var x = 0; x < chunkCols; x++) { | |
var chunkWidth = (x == chunkCols - 1) ? totalWidth - x * this.chunkSize : this.chunkSize; | |
var chunkHeight = (y == chunkRows - 1) ? totalHeight - y * this.chunkSize : this.chunkSize; | |
this.preRenderedChunks[y][x] = this.preRenderChunk(x, y, chunkWidth, chunkHeight); | |
} | |
} | |
}, | |
preRenderChunk: function (cx, cy, w, h) { | |
var tw = w / this.tilesize / ig.system.scale + 1, | |
th = h / this.tilesize / ig.system.scale + 1; | |
var nx = (cx * this.chunkSize / ig.system.scale) % this.tilesize, | |
ny = (cy * this.chunkSize / ig.system.scale) % this.tilesize; | |
var tx = Math.floor(cx * this.chunkSize / this.tilesize / ig.system.scale), | |
ty = Math.floor(cy * this.chunkSize / this.tilesize / ig.system.scale); | |
var chunk = ig.$new('canvas'); | |
chunk.width = w; | |
chunk.height = h; | |
var oldContext = ig.system.context; | |
ig.system.context = chunk.getContext("2d"); | |
for (var x = 0; x < tw; x++) { | |
for (var y = 0; y < th; y++) { | |
if (x + tx < this.width && y + ty < this.height) { | |
var tile = this.data[y + ty][x + tx]; | |
if (tile) { | |
this.tiles.drawTile(x * this.tilesize - nx, y * this.tilesize - ny, tile - 1, this.tilesize); | |
} | |
} | |
} | |
} | |
ig.system.context = oldContext; | |
return chunk; | |
}, | |
draw: function () { | |
if (!this.tiles.loaded || !this.enabled) { | |
return; | |
} | |
if (this.preRender) { | |
this.drawPreRendered(); | |
} else { | |
this.drawTiled(); | |
} | |
}, | |
drawPreRendered: function () { | |
if (!this.preRenderedChunks) { | |
this.preRenderMapToChunks(); | |
} | |
var dx = ig.system.getDrawPos(this.scroll.x), | |
dy = ig.system.getDrawPos(this.scroll.y); | |
if (this.repeat) { | |
var w = this.width * this.tilesize * ig.system.scale; | |
dx = (dx % w + w) % w; | |
var h = this.height * this.tilesize * ig.system.scale; | |
dy = (dy % h + h) % h; | |
} | |
var minChunkX = Math.max(Math.floor(dx / this.chunkSize), 0), | |
minChunkY = Math.max(Math.floor(dy / this.chunkSize), 0), | |
maxChunkX = Math.ceil((dx + ig.system.realWidth) / this.chunkSize), | |
maxChunkY = Math.ceil((dy + ig.system.realHeight) / this.chunkSize), | |
maxRealChunkX = this.preRenderedChunks[0].length, | |
maxRealChunkY = this.preRenderedChunks.length; | |
if (!this.repeat) { | |
maxChunkX = Math.min(maxChunkX, maxRealChunkX); | |
maxChunkY = Math.min(maxChunkY, maxRealChunkY); | |
} | |
var nudgeY = 0; | |
for (var cy = minChunkY; cy < maxChunkY; cy++) { | |
var nudgeX = 0; | |
for (var cx = minChunkX; cx < maxChunkX; cx++) { | |
var chunk = this.preRenderedChunks[cy % maxRealChunkY][cx % maxRealChunkX]; | |
var x = -dx + cx * this.chunkSize - nudgeX; | |
var y = -dy + cy * this.chunkSize - nudgeY; | |
ig.system.context.drawImage(chunk, x, y); | |
ig.Image.drawCount++; | |
if (this.debugChunks) { | |
ig.system.context.strokeStyle = '#f0f'; | |
ig.system.context.strokeRect(x, y, this.chunkSize, this.chunkSize); | |
} | |
if (this.repeat && chunk.width < this.chunkSize && x + chunk.width < ig.system.realWidth) { | |
nudgeX = this.chunkSize - chunk.width; | |
maxChunkX++; | |
} | |
} | |
if (this.repeat && chunk.height < this.chunkSize && y + chunk.height < ig.system.realHeight) { | |
nudgeY = this.chunkSize - chunk.height; | |
maxChunkY++; | |
} | |
} | |
}, | |
drawTiled: function () { | |
var tile = 0, | |
anim = null, | |
tileOffsetX = (this.scroll.x / this.tilesize).toInt(), | |
tileOffsetY = (this.scroll.y / this.tilesize).toInt(), | |
pxOffsetX = this.scroll.x % this.tilesize, | |
pxOffsetY = this.scroll.y % this.tilesize, | |
pxMinX = -pxOffsetX - this.tilesize, | |
pxMinY = -pxOffsetY - this.tilesize, | |
pxMaxX = ig.system.width + this.tilesize - pxOffsetX, | |
pxMaxY = ig.system.height + this.tilesize - pxOffsetY; | |
for (var mapY = -1, pxY = pxMinY; pxY < pxMaxY; mapY++, pxY += this.tilesize) { | |
var tileY = mapY + tileOffsetY; | |
if (tileY >= this.height || tileY < 0) { | |
if (!this.repeat) { | |
continue; | |
} | |
tileY = (tileY % this.height + this.height) % this.height; | |
} | |
for (var mapX = -1, pxX = pxMinX; pxX < pxMaxX; mapX++, pxX += this.tilesize) { | |
var tileX = mapX + tileOffsetX; | |
if (tileX >= this.width || tileX < 0) { | |
if (!this.repeat) { | |
continue; | |
} | |
tileX = (tileX % this.width + this.width) % this.width; | |
} | |
if ((tile = this.data[tileY][tileX])) { | |
if ((anim = this.anims[tile - 1])) { | |
anim.draw(pxX, pxY); | |
} else { | |
this.tiles.drawTile(pxX, pxY, tile - 1, this.tilesize); | |
} | |
} | |
} | |
} | |
} | |
}); | |
}); | |
// lib/impact/game.js | |
ig.baked = true; | |
ig.module('impact.game').requires('impact.impact', 'impact.entity', 'impact.collision-map', 'impact.background-map').defines(function () { | |
"use strict"; | |
ig.Game = ig.Class.extend({ | |
clearColor: '#000000', | |
gravity: 0, | |
screen: { | |
x: 0, | |
y: 0 | |
}, | |
_rscreen: { | |
x: 0, | |
y: 0 | |
}, | |
entities: [], | |
namedEntities: {}, | |
collisionMap: ig.CollisionMap.staticNoCollision, | |
backgroundMaps: [], | |
backgroundAnims: {}, | |
autoSort: false, | |
sortBy: null, | |
cellSize: 64, | |
_deferredKill: [], | |
_levelToLoad: null, | |
_doSortEntities: false, | |
staticInstantiate: function () { | |
this.sortBy = this.sortBy || ig.Game.SORT.Z_INDEX; | |
ig.game = this; | |
return null; | |
}, | |
loadLevel: function (data) { | |
this.screen = { | |
x: 0, | |
y: 0 | |
}; | |
this.entities = []; | |
this.namedEntities = {}; | |
for (var i = 0; i < data.entities.length; i++) { | |
var ent = data.entities[i]; | |
this.spawnEntity(ent.type, ent.x, ent.y, ent.settings); | |
} | |
this.sortEntities(); | |
this.collisionMap = ig.CollisionMap.staticNoCollision; | |
this.backgroundMaps = []; | |
for (var i = 0; i < data.layer.length; i++) { | |
var ld = data.layer[i]; | |
if (ld.name == 'collision') { | |
this.collisionMap = new ig.CollisionMap(ld.tilesize, ld.data); | |
} else { | |
var newMap = new ig.BackgroundMap(ld.tilesize, ld.data, ld.tilesetName); | |
newMap.anims = this.backgroundAnims[ld.tilesetName] || {}; | |
newMap.repeat = ld.repeat; | |
newMap.distance = ld.distance; | |
newMap.foreground = !! ld.foreground; | |
newMap.preRender = !! ld.preRender; | |
newMap.name = ld.name; | |
this.backgroundMaps.push(newMap); | |
} | |
} | |
for (var i = 0; i < this.entities.length; i++) { | |
this.entities[i].ready(); | |
} | |
}, | |
loadLevelDeferred: function (data) { | |
this._levelToLoad = data; | |
}, | |
getMapByName: function (name) { | |
if (name == 'collision') { | |
return this.collisionMap; | |
} | |
for (var i = 0; i < this.backgroundMaps.length; i++) { | |
if (this.backgroundMaps[i].name == name) { | |
return this.backgroundMaps[i]; | |
} | |
} | |
return null; | |
}, | |
getEntityByName: function (name) { | |
return this.namedEntities[name]; | |
}, | |
getEntitiesByType: function (type) { | |
var entityClass = typeof (type) === 'string' ? ig.global[type] : type; | |
var a = []; | |
for (var i = 0; i < this.entities.length; i++) { | |
var ent = this.entities[i]; | |
if (ent instanceof entityClass && !ent._killed) { | |
a.push(ent); | |
} | |
} | |
return a; | |
}, | |
spawnEntity: function (type, x, y, settings) { | |
var entityClass = typeof (type) === 'string' ? ig.global[type] : type; | |
if (!entityClass) { | |
throw ("Can't spawn entity of type " + type); | |
} | |
var ent = new(entityClass)(x, y, settings || {}); | |
this.entities.push(ent); | |
if (ent.name) { | |
this.namedEntities[ent.name] = ent; | |
} | |
return ent; | |
}, | |
sortEntities: function () { | |
this.entities.sort(this.sortBy); | |
}, | |
sortEntitiesDeferred: function () { | |
this._doSortEntities = true; | |
}, | |
removeEntity: function (ent) { | |
if (ent.name) { | |
delete this.namedEntities[ent.name]; | |
} | |
ent._killed = true; | |
ent.type = ig.Entity.TYPE.NONE; | |
ent.checkAgainst = ig.Entity.TYPE.NONE; | |
ent.collides = ig.Entity.COLLIDES.NEVER; | |
this._deferredKill.push(ent); | |
}, | |
run: function () { | |
this.update(); | |
this.draw(); | |
}, | |
update: function () { | |
if (this._levelToLoad) { | |
this.loadLevel(this._levelToLoad); | |
this._levelToLoad = null; | |
} | |
if (this._doSortEntities || this.autoSort) { | |
this.sortEntities(); | |
this._doSortEntities = false; | |
} | |
this.updateEntities(); | |
this.checkEntities(); | |
for (var i = 0; i < this._deferredKill.length; i++) { | |
this.entities.erase(this._deferredKill[i]); | |
} | |
this._deferredKill = []; | |
for (var tileset in this.backgroundAnims) { | |
var anims = this.backgroundAnims[tileset]; | |
for (var a in anims) { | |
anims[a].update(); | |
} | |
} | |
}, | |
updateEntities: function () { | |
for (var i = 0; i < this.entities.length; i++) { | |
var ent = this.entities[i]; | |
if (!ent._killed) { | |
ent.update(); | |
} | |
} | |
}, | |
draw: function () { | |
if (this.clearColor) { | |
ig.system.clear(this.clearColor); | |
} | |
this._rscreen.x = ig.system.getDrawPos(this.screen.x) / ig.system.scale; | |
this._rscreen.y = ig.system.getDrawPos(this.screen.y) / ig.system.scale; | |
var mapIndex; | |
for (mapIndex = 0; mapIndex < this.backgroundMaps.length; mapIndex++) { | |
var map = this.backgroundMaps[mapIndex]; | |
if (map.foreground) { | |
break; | |
} | |
map.setScreenPos(this.screen.x, this.screen.y); | |
map.draw(); | |
} | |
this.drawEntities(); | |
for (mapIndex; mapIndex < this.backgroundMaps.length; mapIndex++) { | |
var map = this.backgroundMaps[mapIndex]; | |
map.setScreenPos(this.screen.x, this.screen.y); | |
map.draw(); | |
} | |
}, | |
drawEntities: function () { | |
for (var i = 0; i < this.entities.length; i++) { | |
this.entities[i].draw(); | |
} | |
}, | |
checkEntities: function () { | |
var hash = {}; | |
for (var e = 0; e < this.entities.length; e++) { | |
var entity = this.entities[e]; | |
if (entity.type == ig.Entity.TYPE.NONE && entity.checkAgainst == ig.Entity.TYPE.NONE && entity.collides == ig.Entity.COLLIDES.NEVER) { | |
continue; | |
} | |
var checked = {}, xmin = Math.floor(entity.pos.x / this.cellSize), | |
ymin = Math.floor(entity.pos.y / this.cellSize), | |
xmax = Math.floor((entity.pos.x + entity.size.x) / this.cellSize) + 1, | |
ymax = Math.floor((entity.pos.y + entity.size.y) / this.cellSize) + 1; | |
for (var x = xmin; x < xmax; x++) { | |
for (var y = ymin; y < ymax; y++) { | |
if (!hash[x]) { | |
hash[x] = {}; | |
hash[x][y] = [entity]; | |
} else if (!hash[x][y]) { | |
hash[x][y] = [entity]; | |
} else { | |
var cell = hash[x][y]; | |
for (var c = 0; c < cell.length; c++) { | |
if (entity.touches(cell[c]) && !checked[cell[c].id]) { | |
checked[cell[c].id] = true; | |
ig.Entity.checkPair(entity, cell[c]); | |
} | |
} | |
cell.push(entity); | |
} | |
} | |
} | |
} | |
} | |
}); | |
ig.Game.SORT = { | |
Z_INDEX: function (a, b) { | |
return a.zIndex - b.zIndex; | |
}, | |
POS_X: function (a, b) { | |
return (a.pos.x + a.size.x) - (b.pos.x + b.size.x); | |
}, | |
POS_Y: function (a, b) { | |
return (a.pos.y + a.size.y) - (b.pos.y + b.size.y); | |
} | |
}; | |
}); | |
// lib/game/menus.js | |
ig.baked = true; | |
ig.module('game.menus').requires('impact.font').defines(function () { | |
MenuItem = ig.Class.extend({ | |
getText: function () { | |
return 'none' | |
}, | |
left: function () {}, | |
right: function () {}, | |
ok: function () {}, | |
click: function () { | |
this.ok(); | |
ig.system.canvas.style.cursor = 'auto'; | |
} | |
}); | |
Menu = ig.Class.extend({ | |
clearColor: null, | |
name: null, | |
font: new ig.Font('media/fonts/tungsten-18.png'), | |
fontSelected: new ig.Font('media/fonts/tungsten-18-orange.png'), | |
fontTitle: new ig.Font('media/fonts/tungsten-48.png'), | |
current: 0, | |
itemClasses: [], | |
items: [], | |
init: function () { | |
this.y = ig.system.height / 4 + 160; | |
for (var i = 0; i < this.itemClasses.length; i++) { | |
this.items.push(new this.itemClasses[i]()); | |
} | |
}, | |
update: function () { | |
if (ig.input.pressed('up')) { | |
this.current--; | |
} | |
if (ig.input.pressed('down')) { | |
this.current++; | |
} | |
this.current = this.current.limit(0, this.items.length - 1); | |
if (ig.input.pressed('left')) { | |
this.items[this.current].left(); | |
} | |
if (ig.input.pressed('right')) { | |
this.items[this.current].right(); | |
} | |
if (ig.input.pressed('ok')) { | |
this.items[this.current].ok(); | |
} | |
var ys = this.y; | |
var xs = ig.system.width / 2; | |
var hoverItem = null; | |
for (var i = 0; i < this.items.length; i++) { | |
var item = this.items[i]; | |
var w = this.font.widthForString(item.getText()) / 2; | |
if (ig.input.mouse.x > xs - w && ig.input.mouse.x < xs + w && ig.input.mouse.y > ys && ig.input.mouse.y < ys + 24) { | |
hoverItem = item; | |
this.current = i; | |
} | |
ys += 30; | |
} | |
if (hoverItem) { | |
ig.system.canvas.style.cursor = 'pointer'; | |
if (ig.input.pressed('click')) { | |
hoverItem.click(); | |
} | |
} else { | |
ig.system.canvas.style.cursor = 'auto'; | |
} | |
}, | |
draw: function () { | |
if (this.clearColor) { | |
ig.system.context.fillStyle = this.clearColor; | |
ig.system.context.fillRect(0, 0, ig.system.width, ig.system.height); | |
} | |
var xs = ig.system.width / 2; | |
var ys = this.y; | |
if (this.name) { | |
this.fontTitle.draw(this.name, xs, ys - 160, ig.Font.ALIGN.CENTER); | |
} | |
for (var i = 0; i < this.items.length; i++) { | |
var t = this.items[i].getText(); | |
if (i == this.current) { | |
this.fontSelected.draw(t, xs, ys, ig.Font.ALIGN.CENTER); | |
} else { | |
this.font.draw(t, xs, ys, ig.Font.ALIGN.CENTER); | |
} | |
ys += 30; | |
} | |
} | |
}); | |
MenuItemSoundVolume = MenuItem.extend({ | |
getText: function () { | |
return 'Sound Volume: < ' + (ig.soundManager.volume * 100).round() + '% >'; | |
}, | |
left: function () { | |
ig.soundManager.volume = (ig.soundManager.volume - 0.1).limit(0, 1); | |
}, | |
right: function () { | |
ig.soundManager.volume = (ig.soundManager.volume + 0.1).limit(0, 1); | |
}, | |
click: function () { | |
if (ig.input.mouse.x > 220) { | |
this.right(); | |
} else { | |
this.left(); | |
} | |
} | |
}); | |
MenuItemMusicVolume = MenuItem.extend({ | |
getText: function () { | |
return 'Music Volume: < ' + (ig.music.volume * 100).round() + '% >'; | |
}, | |
left: function () { | |
ig.music.volume = (ig.music.volume - 0.1).limit(0, 1); | |
}, | |
right: function () { | |
ig.music.volume = (ig.music.volume + 0.1).limit(0, 1); | |
}, | |
click: function () { | |
if (ig.input.mouse.x > 220) { | |
this.right(); | |
} else { | |
this.left(); | |
} | |
} | |
}); | |
MenuItemResume = MenuItem.extend({ | |
getText: function () { | |
return 'Resume'; | |
}, | |
ok: function () { | |
ig.game.toggleMenu(); | |
} | |
}); | |
PauseMenu = Menu.extend({ | |
name: 'Menu', | |
clearColor: 'rgba(0,0,0,0.9)', | |
itemClasses: [MenuItemSoundVolume, MenuItemMusicVolume, MenuItemResume] | |
}); | |
MenuItemNormalMode = MenuItem.extend({ | |
getText: function () { | |
return 'Play Normal Mode'; | |
}, | |
ok: function () { | |
ig.game.difficulty = 'NORMAL'; | |
ig.game.setGame(); | |
} | |
}); | |
MenuItemExpertMode = MenuItem.extend({ | |
getText: function () { | |
return 'Play Expert Mode'; | |
}, | |
ok: function () { | |
ig.game.difficulty = 'EXPERT'; | |
ig.game.setGame(); | |
} | |
}); | |
MenuItemSoundMenu = MenuItem.extend({ | |
getText: function () { | |
return 'Sound Menu/Pause (ESC Key)'; | |
}, | |
ok: function () { | |
ig.game.toggleMenu(); | |
} | |
}); | |
TitleMenu = Menu.extend({ | |
itemClasses: [MenuItemNormalMode, MenuItemExpertMode, MenuItemSoundMenu] | |
}); | |
MenuItemBack = MenuItem.extend({ | |
getText: function () { | |
return 'Back to Title'; | |
}, | |
ok: function () { | |
ig.game.setTitle(); | |
} | |
}); | |
GameOverMenu = Menu.extend({ | |
init: function () { | |
this.parent(); | |
this.y = ig.system.height / 4 + 240; | |
}, | |
itemClasses: [MenuItemBack] | |
}); | |
}); | |
// lib/game/words.js | |
ig.baked = true; | |
ig.module('game.words').defines(function () { | |
WORDS = { | |
2: ['am', 'an', 'as', 'at', 'be', 'by', 'cs', 'do', 'go', 'he', 'if', 'in', 'is', 'it', 'me', 'my', 'no', 'of', 'oh', 'on', 'or', 'pi', 're', 'so', 'to', 'up', 'us', 'we'], | |
3: ['act', 'add', 'age', 'ago', 'aid', 'aim', 'air', 'all', 'and', 'any', 'are', 'arm', 'art', 'ask', 'ate', 'bad', 'ban', 'bar', 'bed', 'bet', 'bid', 'big', 'bit', 'box', 'boy', 'bug', 'bus', 'but', 'buy', 'can', 'car', 'cat', 'cry', 'cup', 'cut', 'day', 'did', 'die', 'doe', 'dog', 'dry', 'due', 'eat', 'end', 'err', 'eye', 'fan', 'far', 'fed', 'few', 'fit', 'fix', 'fly', 'for', 'fry', 'fun', 'gap', 'gas', 'get', 'got', 'gun', 'guy', 'had', 'has', 'hat', 'her', 'hid', 'him', 'his', 'hit', 'hot', 'how', 'ice', 'ill', 'its', 'job', 'joy', 'key', 'kid', 'law', 'lay', 'led', 'leg', 'let', 'lie', 'log', 'lot', 'low', 'mad', 'man', 'map', 'may', 'men', 'met', 'mix', 'mod', 'net', 'new', 'nor', 'not', 'now', 'odd', 'off', 'oil', 'old', 'one', 'our', 'out', 'owe', 'own', 'pay', 'pen', 'per', 'pop', 'put', 'ran', 'raw', 'red', 'rid', 'row', 'run', 'sad', 'sat', 'saw', 'say', 'see', 'set', 'sex', 'she', 'sit', 'six', 'son', 'sum', 'sun', 'tax', 'tea', 'ten', 'the', 'tie', 'tin', 'too', 'top', 'try', 'two', 'use', 'van', 'via', 'war', 'was', 'way', 'who', 'why', 'win', 'won', 'yes', 'yet', 'you'], | |
4: ['able', 'acts', 'adds', 'ages', 'aims', 'also', 'area', 'army', 'asks', 'away', 'back', 'ball', 'band', 'bank', 'bars', 'base', 'bear', 'been', 'best', 'bets', 'bids', 'bill', 'bind', 'bite', 'bits', 'blow', 'blue', 'boat', 'body', 'book', 'boot', 'bore', 'both', 'bugs', 'bulk', 'bury', 'busy', 'buys', 'byte', 'call', 'came', 'card', 'care', 'case', 'cell', 'cent', 'char', 'chip', 'city', 'club', 'clue', 'code', 'cold', 'come', 'cope', 'copy', 'core', 'cost', 'cure', 'cuts', 'dare', 'dark', 'data', 'date', 'days', 'dead', 'deal', 'dear', 'deem', 'deep', 'desk', 'died', 'dies', 'disc', 'disk', 'does', 'done', 'door', 'down', 'draw', 'drew', 'drop', 'dumb', 'dump', 'duty', 'each', 'ease', 'east', 'easy', 'eats', 'edge', 'edit', 'else', 'ends', 'even', 'ever', 'eyes', 'face', 'fact', 'fail', 'fair', 'fall', 'farm', 'fast', 'fate', 'fear', 'feed', 'feel', 'feet', 'fell', 'felt', 'file', 'fill', 'film', 'find', 'fine', 'fire', 'firm', 'fish', 'fits', 'five', 'flag', 'flat', 'flew', 'flow', 'folk', 'food', 'foot', 'form', 'four', 'free', 'from', 'full', 'fund', 'gain', 'game', 'gave', 'gets', 'girl', 'give', 'glad', 'goes', 'gone', 'good', 'grew', 'grow', 'hack', 'hair', 'half', 'hall', 'hand', 'hang', 'hard', 'harm', 'hate', 'have', 'head', 'hear', 'heat', 'held', 'hell', 'help', 'here', 'hide', 'high', 'hill', 'hint', 'hits', 'hold', 'hole', 'home', 'hope', 'host', 'hour', 'huge', 'hung', 'hunt', 'idea', 'inch', 'info', 'into', 'item', 'jobs', 'join', 'joke', 'jump', 'junk', 'just', 'keen', 'keep', 'kept', 'keys', 'kill', 'kind', 'king', 'knew', 'know', 'lack', 'lady', 'lain', 'land', 'last', 'late', 'laws', 'lazy', 'lead', 'leaf', 'left', 'legs', 'lend', 'less', 'lets', 'lied', 'lies', 'life', 'lift', 'like', 'line', 'link', 'list', 'live', 'load', 'loan', 'lock', 'logs', 'long', 'look', 'loop', 'lose', 'loss', 'lost', 'lots', 'love', 'luck', 'made', 'mail', 'main', 'make', 'many', 'mark', 'mass', 'mean', 'meet', 'mere', 'mess', 'mile', 'mind', 'mine', 'miss', 'mode', 'more', 'most', 'move', 'much', 'must', 'name', 'near', 'neck', 'need', 'news', 'next', 'nice', 'nine', 'none', 'note', 'numb', 'obey', 'odds', 'omit', 'once', 'ones', 'only', 'onto', 'open', 'ours', 'over', 'owed', 'owes', 'pack', 'page', 'paid', 'pain', 'pair', 'park', 'part', 'pass', 'past', 'path', 'pays', 'peak', 'pick', 'pile', 'pint', 'pipe', 'plan', 'play', 'plea', 'plot', 'plug', 'plus', 'poem', 'poet', 'poll', 'pool', 'poor', 'port', 'post', 'pull', 'pure', 'push', 'puts', 'putt', 'quit', 'race', 'rain', 'rare', 'rate', 'read', 'real', 'rely', 'rest', 'ride', 'rids', 'ring', 'rise', 'risk', 'road', 'role', 'roll', 'room', 'root', 'rule', 'runs', 'rush', 'safe', 'said', 'sake', 'sale', 'same', 'save', 'says', 'scan', 'seek', 'seem', 'seen', 'sees', 'self', 'sell', 'send', 'sent', 'sets', 'ship', 'shop', 'show', 'shut', 'side', 'sign', 'site', 'sits', 'size', 'slip', 'slow', 'soft', 'sold', 'some', 'soon', 'sort', 'spot', 'stay', 'step', 'stop', 'such', 'suit', 'sure', 'take', 'talk', 'tank', 'tape', 'task', 'team', 'tell', 'tend', 'term', 'test', 'text', 'than', 'that', 'them', 'then', 'they', 'thin', 'this', 'thus', 'tied', 'ties', 'till', 'time', 'told', 'took', 'town', 'trap', 'tree', 'trip', 'true', 'tune', 'turn', 'type', 'ugly', 'unit', 'upon', 'used', 'user', 'uses', 'vary', 'vast', 'very', 'vice', 'view', 'vote', 'wait', 'walk', 'wall', 'want', 'warm', 'warn', 'wash', 'ways', 'wear', 'week', 'well', 'went', 'were', 'west', 'what', 'when', 'whom', 'wide', 'wife', 'wild', 'will', 'wind', 'wine', 'wins', 'wire', 'wise', 'wish', 'with', 'word', 'wore', 'work', 'worn', 'year', 'your', 'zero'], | |
5: ['about', 'above', 'abuse', 'acted', 'added', 'admit', 'adopt', 'after', 'again', 'agree', 'ahead', 'aimed', 'alarm', 'album', 'alias', 'alive', 'allow', 'alone', 'along', 'alter', 'among', 'amuse', 'angle', 'angry', 'annoy', 'apart', 'apple', 'apply', 'areas', 'argue', 'arise', 'aside', 'asked', 'avoid', 'awake', 'award', 'aware', 'awful', 'backs', 'badly', 'based', 'bases', 'basic', 'basis', 'bears', 'began', 'begin', 'begun', 'being', 'below', 'binds', 'bites', 'black', 'blame', 'blank', 'block', 'board', 'books', 'borne', 'bound', 'boxes', 'brand', 'break', 'brief', 'bring', 'broke', 'brown', 'build', 'built', 'bytes', 'calls', 'cards', 'cares', 'carry', 'cases', 'catch', 'cause', 'cease', 'chain', 'chair', 'chaos', 'chars', 'cheap', 'child', 'chips', 'chose', 'claim', 'class', 'clean', 'clear', 'clock', 'close', 'coded', 'codes', 'comes', 'costs', 'could', 'count', 'court', 'cover', 'crash', 'crazy', 'crisp', 'cross', 'cycle', 'daily', 'dated', 'dates', 'datum', 'deals', 'dealt', 'death', 'deems', 'delay', 'depth', 'digit', 'dirty', 'discs', 'ditto', 'doing', 'doors', 'doubt', 'dozen', 'drawn', 'draws', 'dream', 'drink', 'drive', 'drops', 'drove', 'dying', 'early', 'earth', 'eaten', 'edits', 'eight', 'elect', 'empty', 'ended', 'enemy', 'enjoy', 'enter', 'entry', 'equal', 'error', 'evens', 'event', 'every', 'exact', 'exist', 'extra', 'facts', 'fails', 'faith', 'falls', 'false', 'fancy', 'fatal', 'fault', 'feeds', 'feels', 'fewer', 'field', 'fight', 'filed', 'files', 'fills', 'final', 'finds', 'first', 'fixed', 'fixes', 'flash', 'flied', 'flies', 'float', 'floor', 'flown', 'folks', 'force', 'forms', 'forth', 'found', 'frame', 'fresh', 'fries', 'front', 'fully', 'funds', 'funny', 'gains', 'games', 'given', 'gives', 'glass', 'going', 'goods', 'grand', 'grant', 'graph', 'grave', 'great', 'green', 'grind', 'gross', 'group', 'grown', 'grows', 'guard', 'guess', 'guide', 'habit', 'hands', 'handy', 'hangs', 'happy', 'heads', 'heard', 'hears', 'heart', 'heavy', 'hello', 'helps', 'hence', 'hides', 'hints', 'holds', 'holes', 'hoped', 'hopes', 'horse', 'hotel', 'hours', 'house', 'human', 'hurry', 'ideal', 'ideas', 'image', 'imply', 'index', 'inner', 'input', 'issue', 'items', 'joins', 'joint', 'judge', 'jumps', 'keeps', 'kills', 'kinds', 'knock', 'known', 'knows', 'label', 'lacks', 'lands', 'large', 'lasts', 'later', 'leach', 'leads', 'learn', 'least', 'leave', 'legal', 'level', 'light', 'liked', 'likes', 'limit', 'lines', 'links', 'lists', 'lived', 'lives', 'loads', 'local', 'locks', 'logic', 'looks', 'loose', 'lorry', 'loses', 'lower', 'lucky', 'lunch', 'lying', 'magic', 'major', 'makes', 'march', 'marks', 'marry', 'match', 'maybe', 'means', 'meant', 'media', 'meets', 'merit', 'messy', 'metal', 'might', 'miles', 'minds', 'minor', 'mixed', 'mixes', 'model', 'money', 'month', 'moral', 'mouth', 'moved', 'moves', 'movie', 'music', 'naive', 'named', 'names', 'nasty', 'needs', 'never', 'nicer', 'night', 'noise', 'noisy', 'north', 'noted', 'notes', 'novel', 'occur', 'offer', 'often', 'older', 'omits', 'opens', 'order', 'other', 'ought', 'outer', 'owing', 'owner', 'pages', 'pairs', 'paper', 'parts', 'party', 'patch', 'pause', 'payed', 'peace', 'phase', 'phone', 'picks', 'piece', 'place', 'plain', 'plane', 'plans', 'plant', 'plays', 'plots', 'point', 'posts', 'pound', 'power', 'press', 'price', 'prime', 'print', 'prior', 'prone', 'proof', 'prove', 'pulls', 'putts', 'queue', 'quick', 'quiet', 'quite', 'quits', 'quote', 'radio', 'raise', 'range', 'rapid', 'rates', 'reach', 'react', 'reads', 'ready', 'refer', 'reply', 'right', 'river', 'rooms', 'rough', 'round', 'route', 'rules', 'sadly', 'safer', 'saint', 'sales', 'saved', 'saves', 'scale', 'scene', 'score', 'scrap', 'seeks', 'seems', 'sells', 'sends', 'sense', 'serve', 'seven', 'shall', 'shame', 'shape', 'share', 'sharp', 'sheet', 'shelf', 'shell', 'shift', 'shoot', 'shops', 'short', 'shown', 'shows', 'shuts', 'sides', 'sight', 'signs', 'silly', 'since', 'sites', 'sizes', 'skill', 'sleep', 'small', 'smile', 'solid', 'solve', 'sorry', 'sorts', 'sound', 'south', 'space', 'spare', 'speak', 'speed', 'spell', 'spend', 'spent', 'spite', 'split', 'spoke', 'spots', 'staff', 'stage', 'stand', 'start', 'state', 'stays', 'steal', 'stick', 'still', 'stock', 'stone', 'stood', 'stops', 'store', 'stuck', 'study', 'stuff', 'style', 'sugar', 'suits', 'table', 'taken', 'takes', 'talks', 'tanks', 'tapes', 'tasks', 'taste', 'teach', 'teeth', 'tells', 'tends', 'terms', 'tests', 'thank', 'their', 'there', 'these', 'thing', 'think', 'third', 'those', 'three', 'threw', 'throw', 'tight', 'timed', 'times', 'title', 'today', 'token', 'tooth', 'topic', 'total', 'touch', 'trace', 'track', 'train', 'traps', 'trash', 'treat', 'trees', 'trial', 'trick', 'tried', 'tries', 'truck', 'truly', 'trunk', 'trust', 'truth', 'turns', 'twice', 'tying', 'typed', 'types', 'under', 'unite', 'units', 'until', 'upper', 'upset', 'usage', 'users', 'using', 'usual', 'vague', 'valid', 'value', 'video', 'views', 'visit', 'vital', 'voice', 'votes', 'waits', 'walks', 'walls', 'wants', 'warns', 'waste', 'watch', 'water', 'wears', 'weeks', 'weird', 'wheel', 'where', 'which', 'while', 'white', 'whole', 'whose', 'wider', 'wills', 'woman', 'women', 'words', 'works', 'world', 'worry', 'worse', 'worst', 'worth', 'would', 'write', 'wrong', 'wrote', 'years', 'young', 'yours'], | |
6: ['accept', 'access', 'accord', 'across', 'acting', 'action', 'active', 'actual', 'adding', 'adjust', 'admits', 'adopts', 'advice', 'advise', 'affair', 'affect', 'afford', 'afraid', 'agency', 'agreed', 'agrees', 'aiming', 'allows', 'almost', 'alters', 'always', 'amount', 'amused', 'amuses', 'animal', 'annoys', 'annual', 'answer', 'anyone', 'anyway', 'appeal', 'appear', 'argued', 'argues', 'arises', 'around', 'arrive', 'artist', 'asking', 'asleep', 'aspect', 'assume', 'assure', 'attach', 'attack', 'attend', 'author', 'autumn', 'avoids', 'backed', 'basing', 'became', 'become', 'before', 'begins', 'behalf', 'behave', 'behind', 'belong', 'better', 'beyond', 'bigger', 'binary', 'biting', 'bitten', 'boards', 'bodies', 'borrow', 'bother', 'bottle', 'bottom', 'bought', 'branch', 'breach', 'breaks', 'bridge', 'bright', 'brings', 'broken', 'bucket', 'budget', 'buffer', 'builds', 'buried', 'buries', 'button', 'buying', 'called', 'cannot', 'caught', 'caused', 'causes', 'chance', 'change', 'charge', 'choice', 'choose', 'chosen', 'church', 'circle', 'claims', 'clears', 'clever', 'closed', 'closer', 'closes', 'coding', 'coffee', 'column', 'coming', 'common', 'copied', 'copies', 'corner', 'counts', 'county', 'couple', 'course', 'covers', 'create', 'credit', 'crisis', 'crisps', 'cursor', 'cycles', 'damage', 'danger', 'dating', 'debate', 'decade', 'decent', 'decide', 'deduce', 'deemed', 'deeply', 'define', 'degree', 'delete', 'demand', 'depend', 'derive', 'design', 'desire', 'detail', 'detect', 'device', 'devote', 'differ', 'digits', 'dinner', 'direct', 'divide', 'dollar', 'domain', 'double', 'dozens', 'driven', 'driver', 'drives', 'during', 'easier', 'easily', 'eating', 'edited', 'editor', 'effect', 'effort', 'either', 'elects', 'enable', 'ending', 'enough', 'ensure', 'enters', 'entire', 'entity', 'eraser', 'errors', 'escape', 'evened', 'events', 'except', 'excess', 'excuse', 'exists', 'expand', 'expect', 'expert', 'extend', 'extent', 'factor', 'failed', 'fairly', 'fallen', 'family', 'famous', 'faster', 'father', 'faults', 'fewest', 'fields', 'figure', 'filing', 'filled', 'finger', 'finish', 'finite', 'firmly', 'fiscal', 'fishes', 'fitted', 'fixing', 'flight', 'floats', 'flying', 'follow', 'forced', 'forces', 'forget', 'forgot', 'formal', 'format', 'formed', 'former', 'fourth', 'freely', 'french', 'friend', 'future', 'gained', 'garden', 'gather', 'giving', 'global', 'gotten', 'grands', 'grants', 'grinds', 'ground', 'groups', 'growth', 'habits', 'handed', 'handle', 'hanged', 'happen', 'harder', 'hardly', 'having', 'headed', 'header', 'health', 'helped', 'hereby', 'hidden', 'hiding', 'higher', 'highly', 'honest', 'hoping', 'horses', 'ignore', 'images', 'impact', 'impose', 'inches', 'income', 'indeed', 'inform', 'inputs', 'insert', 'inside', 'insist', 'intend', 'invent', 'invite', 'issued', 'issues', 'itself', 'joined', 'killed', 'kindly', 'knocks', 'labels', 'lacked', 'ladies', 'landed', 'larger', 'latest', 'latter', 'layout', 'leaded', 'leader', 'learns', 'leaved', 'leaves', 'length', 'lesser', 'lesson', 'letter', 'levels', 'liable', 'lights', 'likely', 'liking', 'limits', 'linear', 'linked', 'listed', 'listen', 'little', 'living', 'loaded', 'locked', 'logged', 'longer', 'looked', 'losing', 'loudly', 'lowest', 'mainly', 'making', 'manage', 'manner', 'manual', 'marked', 'market', 'master', 'matter', 'medium', 'member', 'memory', 'merely', 'merits', 'method', 'middle', 'minded', 'minute', 'misled', 'missed', 'misses', 'misuse', 'mixing', 'models', 'modern', 'modify', 'moment', 'months', 'mostly', 'mother', 'motion', 'moving', 'myself', 'namely', 'naming', 'nation', 'nature', 'nearby', 'nearer', 'nearly', 'needed', 'nicest', 'nobody', 'normal', 'notice', 'notify', 'noting', 'number', 'object', 'obtain', 'occupy', 'occurs', 'offers', 'office', 'oldest', 'opened', 'oppose', 'option', 'orders', 'origin', 'others', 'output', 'owners', 'packet', 'papers', 'parent', 'partly', 'passed', 'passes', 'paying', 'people', 'period', 'permit', 'person', 'petrol', 'phrase', 'picked', 'pieces', 'placed', 'places', 'planet', 'played', 'please', 'plenty', 'pocket', 'points', 'police', 'policy', 'posted', 'pounds', 'powers', 'prefer', 'pretty', 'prices', 'prints', 'prompt', 'proper', 'proved', 'proves', 'public', 'pulled', 'purely', 'pushed', 'pushes', 'putted', 'quoted', 'quotes', 'raised', 'raises', 'random', 'rarely', 'rather', 'reader', 'really', 'reason', 'recall', 'recent', 'record', 'reduce', 'refers', 'refuse', 'regard', 'region', 'regret', 'reject', 'relate', 'remain', 'remark', 'remind', 'remote', 'remove', 'repair', 'repeat', 'report', 'resort', 'result', 'retain', 'return', 'reveal', 'review', 'rights', 'rubber', 'safely', 'safest', 'safety', 'sample', 'saving', 'saying', 'scheme', 'school', 'scores', 'screen', 'script', 'search', 'season', 'second', 'secret', 'secure', 'seeing', 'seemed', 'select', 'senior', 'serial', 'series', 'served', 'server', 'serves', 'settle', 'severe', 'shared', 'shares', 'should', 'showed', 'signal', 'signed', 'simple', 'simply', 'single', 'skills', 'slight', 'slower', 'slowly', 'smooth', 'social', 'solely', 'solved', 'solves', 'sooner', 'sorted', 'sought', 'sounds', 'source', 'spaces', 'speaks', 'speech', 'spells', 'spends', 'spirit', 'splits', 'spoken', 'spread', 'spring', 'square', 'stable', 'stages', 'stands', 'starts', 'stated', 'states', 'status', 'stayed', 'sticks', 'stones', 'stored', 'stores', 'stream', 'street', 'strict', 'strike', 'string', 'strong', 'struck', 'stupid', 'submit', 'subset', 'subtle', 'sudden', 'suffer', 'suited', 'summer', 'supply', 'surely', 'survey', 'switch', 'symbol', 'syntax', 'system', 'tables', 'taking', 'talked', 'target', 'taught', 'tested', 'thanks', 'theory', 'things', 'thinks', 'though', 'threat', 'thrown', 'throws', 'ticket', 'timing', 'titles', 'topics', 'toward', 'tracks', 'trains', 'travel', 'treats', 'trusts', 'trying', 'turned', 'twelve', 'twenty', 'typing', 'unable', 'unique', 'unless', 'unlike', 'update', 'upsets', 'useful', 'values', 'varied', 'varies', 'vastly', 'vector', 'virtue', 'vision', 'volume', 'waited', 'walked', 'wanted', 'warned', 'wasted', 'wastes', 'weapon', 'weight', 'wheels', 'whilst', 'widely', 'widest', 'willed', 'window', 'winter', 'wished', 'wishes', 'within', 'wonder', 'wooden', 'worded', 'worked', 'worker', 'worthy', 'writer', 'writes', 'yellow'], | |
7: ['ability', 'absence', 'accepts', 'accords', 'account', 'achieve', 'acquire', 'actions', 'address', 'adopted', 'advance', 'advised', 'advises', 'affairs', 'affects', 'against', 'allowed', 'already', 'altered', 'amongst', 'amounts', 'amusing', 'ancient', 'annoyed', 'another', 'answers', 'anybody', 'apology', 'appears', 'applied', 'applies', 'approve', 'arguing', 'arrange', 'arrived', 'arrives', 'article', 'aspects', 'assumed', 'assumes', 'assured', 'assures', 'attempt', 'attends', 'attract', 'authors', 'average', 'avoided', 'awkward', 'backing', 'balance', 'battery', 'bearing', 'because', 'becomes', 'believe', 'belongs', 'benefit', 'besides', 'betting', 'between', 'bidding', 'biggest', 'binding', 'biology', 'bizarre', 'borrows', 'bothers', 'bracket', 'briefly', 'brother', 'brought', 'burying', 'calling', 'capable', 'capital', 'captain', 'careful', 'carried', 'carries', 'catches', 'causing', 'central', 'century', 'certain', 'chances', 'changed', 'changes', 'channel', 'chapter', 'charged', 'charges', 'cheaper', 'checked', 'chooses', 'circuit', 'citizen', 'claimed', 'clarify', 'classes', 'cleared', 'clearer', 'clearly', 'closely', 'closest', 'closing', 'collect', 'college', 'combine', 'command', 'comment', 'company', 'compare', 'complex', 'compose', 'compute', 'concept', 'concern', 'confirm', 'confuse', 'connect', 'consist', 'contact', 'contain', 'content', 'context', 'control', 'convert', 'copying', 'corners', 'correct', 'corrupt', 'costing', 'council', 'counted', 'counter', 'country', 'courses', 'covered', 'crashed', 'crashes', 'created', 'creates', 'culture', 'cumming', 'curious', 'current', 'cutting', 'damaged', 'damages', 'dealing', 'decided', 'decides', 'declare', 'deeming', 'default', 'defined', 'defines', 'degrees', 'deleted', 'deletes', 'deliver', 'demands', 'depends', 'derived', 'derives', 'designs', 'desired', 'desires', 'despite', 'destroy', 'details', 'detects', 'develop', 'devices', 'devoted', 'devotes', 'digital', 'directs', 'discuss', 'dislike', 'display', 'distant', 'disturb', 'divided', 'divides', 'drastic', 'drawing', 'drivers', 'driving', 'dropped', 'dubious', 'earlier', 'easiest', 'economy', 'editing', 'edition', 'editors', 'effects', 'efforts', 'elected', 'element', 'enables', 'ensured', 'ensures', 'entered', 'entitle', 'entries', 'equally', 'evening', 'exactly', 'examine', 'example', 'exclude', 'execute', 'existed', 'expands', 'expects', 'expense', 'experts', 'explain', 'express', 'extends', 'extract', 'extreme', 'factors', 'failing', 'failure', 'falling', 'farther', 'fashion', 'fastest', 'feature', 'federal', 'feeding', 'feeling', 'figures', 'filling', 'finally', 'finding', 'fingers', 'firstly', 'fitting', 'flashed', 'flashes', 'floated', 'follows', 'forcing', 'foreign', 'forever', 'forgets', 'forming', 'fortune', 'forward', 'freedom', 'friends', 'further', 'gaining', 'garbage', 'general', 'genuine', 'getting', 'granted', 'graphic', 'greater', 'greatly', 'grosses', 'grounds', 'growing', 'guessed', 'guesses', 'handing', 'handled', 'handles', 'hanging', 'happens', 'happily', 'hardest', 'harmful', 'heading', 'healthy', 'hearing', 'heavily', 'helpful', 'helping', 'herself', 'highest', 'himself', 'history', 'hitting', 'holding', 'holiday', 'however', 'hundred', 'husband', 'ignored', 'ignores', 'illegal', 'imagine', 'implied', 'implies', 'imposed', 'imposes', 'improve', 'incline', 'include', 'informs', 'initial', 'inserts', 'insists', 'install', 'instant', 'instead', 'integer', 'intends', 'invalid', 'invents', 'invited', 'invites', 'involve', 'isolate', 'issuing', 'joining', 'justify', 'keeping', 'killing', 'knocked', 'knowing', 'lacking', 'landing', 'largely', 'largest', 'leading', 'leaving', 'lecture', 'legally', 'lessons', 'letters', 'letting', 'library', 'limited', 'linking', 'listing', 'loading', 'locking', 'logging', 'logical', 'longest', 'looking', 'machine', 'managed', 'manager', 'manages', 'manuals', 'marking', 'massive', 'matches', 'matters', 'maximum', 'meaning', 'measure', 'medical', 'mediums', 'meeting', 'members', 'mention', 'message', 'methods', 'million', 'minding', 'minimal', 'minimum', 'minutes', 'mislead', 'missing', 'mistake', 'mistook', 'monitor', 'morning', 'natural', 'naughty', 'nearest', 'needing', 'neither', 'nervous', 'network', 'nothing', 'noticed', 'notices', 'nowhere', 'numbers', 'numbest', 'objects', 'obscure', 'observe', 'obtains', 'obvious', 'offered', 'officer', 'offices', 'omitted', 'opening', 'operate', 'opinion', 'opposed', 'opposes', 'options', 'ordered', 'outside', 'overall', 'package', 'painful', 'partial', 'parties', 'passing', 'patient', 'pattern', 'perfect', 'perform', 'perhaps', 'permits', 'persons', 'phrases', 'picking', 'picture', 'placing', 'planned', 'plastic', 'playing', 'pleased', 'pleases', 'pointed', 'popular', 'posting', 'precise', 'prefers', 'prepare', 'present', 'pressed', 'presses', 'presume', 'prevent', 'primary', 'printed', 'printer', 'private', 'problem', 'process', 'produce', 'product', 'project', 'promise', 'propose', 'protect', 'protest', 'provide', 'proving', 'publish', 'pulling', 'purpose', 'pushing', 'putting', 'qualify', 'quality', 'quarter', 'quicker', 'quickly', 'quietly', 'quoting', 'raising', 'rapidly', 'reached', 'reaches', 'readers', 'readily', 'reading', 'reality', 'reasons', 'receive', 'records', 'recover', 'reduced', 'reduces', 'reflect', 'refused', 'refuses', 'regards', 'regular', 'rejects', 'related', 'relates', 'release', 'remains', 'remarks', 'reminds', 'removal', 'removed', 'removes', 'repeats', 'replace', 'replied', 'replies', 'reports', 'request', 'require', 'reserve', 'respect', 'respond', 'restart', 'restore', 'results', 'returns', 'reveals', 'reverse', 'rewrite', 'ridding', 'roughly', 'routine', 'rubbish', 'running', 'satisfy', 'schools', 'science', 'scratch', 'screens', 'seconds', 'section', 'seeking', 'seeming', 'selects', 'selling', 'seminar', 'sending', 'serious', 'service', 'serving', 'session', 'setting', 'settled', 'settles', 'several', 'sharing', 'shopped', 'shorter', 'shortly', 'showing', 'signals', 'signing', 'similar', 'simpler', 'sitting', 'slowest', 'smaller', 'society', 'solving', 'somehow', 'someone', 'soonest', 'sorting', 'sounded', 'sources', 'speaker', 'special', 'specify', 'spotted', 'spreads', 'started', 'stating', 'station', 'staying', 'stopped', 'storage', 'storing', 'strange', 'strikes', 'strings', 'student', 'studied', 'studies', 'subject', 'submits', 'succeed', 'success', 'suffers', 'suffice', 'suggest', 'suiting', 'summary', 'support', 'suppose', 'surface', 'survive', 'suspect', 'suspend', 'symbols', 'systems', 'talking', 'teacher', 'teaches', 'tedious', 'telling', 'testing', 'thereby', 'thought', 'through', 'tickets', 'tonight', 'totally', 'touched', 'touches', 'towards', 'traffic', 'trained', 'trapped', 'treated', 'trivial', 'trouble', 'trusted', 'turning', 'typical', 'unaware', 'unclear', 'unhappy', 'uniform', 'unknown', 'unusual', 'updated', 'updates', 'upwards', 'useless', 'usually', 'utility', 'utterly', 'vaguely', 'variety', 'various', 'varying', 'version', 'visible', 'waiting', 'walking', 'wanting', 'warning', 'wasting', 'watched', 'watches', 'wearing', 'weather', 'weekend', 'welcome', 'western', 'whereas', 'whereby', 'whether', 'whoever', 'willing', 'windows', 'winning', 'wishing', 'without', 'wonders', 'wording', 'workers', 'working', 'worried', 'worries', 'writing', 'written'], | |
8: ['absolute', 'academic', 'accepted', 'accident', 'accorded', 'accounts', 'accuracy', 'accurate', 'achieved', 'achieves', 'acquired', 'acquires', 'activity', 'actually', 'addition', 'adequate', 'admitted', 'adopting', 'advanced', 'advances', 'advising', 'affected', 'agreeing', 'allowing', 'altering', 'although', 'analogue', 'analysis', 'announce', 'annoying', 'answered', 'anyplace', 'anything', 'anywhere', 'apparent', 'appeared', 'applying', 'approach', 'approval', 'approved', 'approves', 'argument', 'arranged', 'arranges', 'arriving', 'articles', 'assembly', 'assuming', 'assuring', 'attached', 'attaches', 'attempts', 'attended', 'attitude', 'audience', 'avoiding', 'becoming', 'believed', 'believes', 'benefits', 'borrowed', 'bothered', 'brackets', 'branches', 'breaking', 'bringing', 'building', 'bulletin', 'business', 'campaign', 'capacity', 'carrying', 'cassette', 'catching', 'category', 'chairman', 'changing', 'channels', 'charging', 'cheapest', 'checking', 'chemical', 'children', 'choosing', 'claiming', 'clearest', 'clearing', 'collapse', 'collects', 'colleges', 'combined', 'combines', 'commands', 'comments', 'commonly', 'compared', 'compares', 'compiler', 'complain', 'complete', 'composed', 'composes', 'computed', 'computer', 'computes', 'concerns', 'concrete', 'confirms', 'confused', 'confuses', 'connects', 'consider', 'consists', 'constant', 'contains', 'contents', 'continue', 'contract', 'contrary', 'contrast', 'controls', 'convince', 'corrects', 'corrupts', 'counting', 'covering', 'crashing', 'creating', 'creation', 'creature', 'critical', 'customer', 'damaging', 'database', 'deciding', 'decision', 'declared', 'declares', 'decrease', 'dedicate', 'defining', 'definite', 'deleting', 'delivers', 'delivery', 'depended', 'deriving', 'describe', 'designed', 'desiring', 'destroys', 'detailed', 'detected', 'develops', 'devoting', 'directed', 'directly', 'director', 'disagree', 'disaster', 'discount', 'discover', 'displays', 'distance', 'distinct', 'district', 'disturbs', 'dividing', 'division', 'document', 'doubtful', 'dropping', 'earliest', 'economic', 'electing', 'election', 'electric', 'elements', 'elevator', 'emphasis', 'employee', 'engineer', 'enormous', 'ensuring', 'entering', 'entirely', 'entitled', 'entitles', 'entrance', 'estimate', 'evenings', 'everyone', 'evidence', 'examined', 'examines', 'examples', 'exchange', 'excluded', 'excludes', 'executed', 'executes', 'exercise', 'existing', 'expanded', 'expected', 'explains', 'explicit', 'extended', 'external', 'facility', 'familiar', 'farthest', 'feasible', 'features', 'feedback', 'finished', 'finishes', 'flashing', 'flexible', 'floating', 'followed', 'fraction', 'frequent', 'friendly', 'function', 'furthest', 'gasoline', 'generate', 'governor', 'graduate', 'granting', 'graphics', 'grateful', 'greatest', 'grinding', 'guessing', 'handling', 'happened', 'hardware', 'harmless', 'holidays', 'horrible', 'hospital', 'hundreds', 'identify', 'identity', 'ignoring', 'implying', 'imposing', 'improved', 'improves', 'incident', 'inclined', 'inclines', 'included', 'includes', 'increase', 'indicate', 'industry', 'inferior', 'infinite', 'informed', 'initials', 'innocent', 'inputted', 'inserted', 'insisted', 'installs', 'instance', 'integers', 'integral', 'intended', 'interact', 'interest', 'internal', 'interval', 'invented', 'inviting', 'involved', 'involves', 'irritate', 'isolated', 'isolates', 'keyboard', 'knocking', 'language', 'learning', 'lectures', 'lifetime', 'likewise', 'limiting', 'location', 'machines', 'magnetic', 'maintain', 'majority', 'managing', 'marriage', 'material', 'meanings', 'measured', 'measures', 'mechanic', 'meetings', 'mentions', 'messages', 'midnight', 'military', 'millions', 'minority', 'misleads', 'mistaken', 'mistakes', 'modified', 'modifies', 'mornings', 'movement', 'multiple', 'national', 'negative', 'networks', 'nonsense', 'normally', 'noticing', 'nowadays', 'numerous', 'objected', 'observed', 'observes', 'obtained', 'occasion', 'occupied', 'occupies', 'occurred', 'offering', 'official', 'omitting', 'operated', 'operates', 'operator', 'opinions', 'opposing', 'opposite', 'optional', 'ordering', 'ordinary', 'original', 'packages', 'parallel', 'patterns', 'peculiar', 'performs', 'personal', 'persuade', 'physical', 'pictures', 'planning', 'pleasant', 'pleasing', 'pointing', 'policies', 'position', 'positive', 'possible', 'possibly', 'powerful', 'prepared', 'prepares', 'presence', 'presents', 'preserve', 'pressing', 'pressure', 'prevents', 'previous', 'printers', 'printing', 'printout', 'probably', 'problems', 'produced', 'produces', 'products', 'progress', 'projects', 'promised', 'promises', 'promptly', 'properly', 'property', 'proposal', 'proposed', 'proposes', 'prospect', 'protects', 'provided', 'provides', 'publicly', 'puncture', 'purchase', 'purposes', 'quantity', 'question', 'quickest', 'quitting', 'randomly', 'reaching', 'reaction', 'readable', 'received', 'receives', 'recently', 'recorded', 'recovers', 'reducing', 'referred', 'reflects', 'refusing', 'regarded', 'register', 'rejected', 'relating', 'relation', 'relative', 'released', 'releases', 'relevant', 'reliable', 'religion', 'remained', 'remember', 'reminded', 'remotely', 'removing', 'repeated', 'replaced', 'replaces', 'replying', 'reported', 'requests', 'required', 'requires', 'research', 'reserved', 'reserves', 'resident', 'resource', 'respects', 'response', 'restored', 'restores', 'restrict', 'resulted', 'returned', 'revealed', 'sciences', 'searched', 'searches', 'secondly', 'sections', 'security', 'selected', 'sensible', 'sensibly', 'sentence', 'separate', 'sequence', 'services', 'sessions', 'settling', 'severely', 'shopping', 'shortage', 'shortest', 'shutting', 'simplest', 'slightly', 'smallest', 'software', 'solution', 'somebody', 'sometime', 'somewhat', 'sounding', 'southern', 'speakers', 'speaking', 'specific', 'spelling', 'spending', 'spotting', 'standard', 'standing', 'starting', 'stations', 'sticking', 'stopping', 'straight', 'strategy', 'strength', 'strictly', 'striking', 'strongly', 'students', 'studying', 'subjects', 'suddenly', 'suffered', 'suggests', 'suitable', 'suitably', 'superior', 'supplied', 'supplies', 'supports', 'supposed', 'supposes', 'surprise', 'survived', 'survives', 'suspects', 'suspends', 'switched', 'switches', 'teaching', 'tendency', 'terminal', 'terribly', 'thinking', 'thoughts', 'thousand', 'throwing', 'together', 'tomorrow', 'touching', 'training', 'transfer', 'trapping', 'treating', 'trusting', 'ultimate', 'unlikely', 'unwanted', 'updating', 'vacation', 'validity', 'valuable', 'variable', 'versions', 'watching', 'welcomed', 'welcomes', 'whatever', 'whenever', 'wherever', 'withdraw', 'wondered', 'worrying', 'yourself'], | |
9: ['abilities', 'accepting', 'according', 'achieving', 'acquiring', 'addressed', 'addresses', 'admitting', 'advancing', 'advantage', 'advertise', 'affecting', 'afternoon', 'agreement', 'algorithm', 'alternate', 'ambiguous', 'anonymous', 'answering', 'apologies', 'appearing', 'approving', 'arbitrary', 'arguments', 'arranging', 'assembler', 'assistant', 'associate', 'attaching', 'attempted', 'attending', 'attention', 'authority', 'automatic', 'available', 'backwards', 'basically', 'beautiful', 'beginning', 'believing', 'borrowing', 'bothering', 'broadcast', 'buildings', 'calculate', 'candidate', 'cardboard', 'carefully', 'certainly', 'character', 'collected', 'combining', 'commented', 'committee', 'community', 'comparing', 'complains', 'complaint', 'completed', 'completes', 'component', 'composing', 'computers', 'computing', 'concerned', 'condition', 'confident', 'confirmed', 'confusing', 'confusion', 'connected', 'considers', 'construct', 'contained', 'continued', 'continues', 'convinced', 'convinces', 'corrected', 'correctly', 'corrupted', 'criticism', 'currently', 'dangerous', 'decisions', 'declaring', 'dedicated', 'dedicates', 'delivered', 'depending', 'described', 'describes', 'designing', 'desirable', 'desperate', 'destroyed', 'detailing', 'detecting', 'determine', 'developed', 'different', 'difficult', 'directing', 'direction', 'directory', 'disappear', 'discovers', 'discussed', 'discusses', 'displayed', 'disturbed', 'documents', 'education', 'effective', 'efficient', 'elsewhere', 'embarrass', 'emergency', 'encounter', 'encourage', 'engineers', 'entitling', 'equipment', 'essential', 'establish', 'everybody', 'examining', 'excellent', 'exception', 'excessive', 'excluding', 'exclusive', 'executing', 'existence', 'expanding', 'expansion', 'expecting', 'expensive', 'explained', 'expressed', 'expresses', 'extending', 'extension', 'extensive', 'extremely', 'financial', 'finishing', 'following', 'forgotten', 'functions', 'generally', 'generated', 'generates', 'gradually', 'guarantee', 'happening', 'hopefully', 'identical', 'immediate', 'implement', 'important', 'improving', 'inability', 'inclining', 'including', 'incorrect', 'increased', 'increases', 'indicates', 'influence', 'informing', 'initially', 'inputting', 'inserting', 'insisting', 'installed', 'instantly', 'insurance', 'intending', 'intention', 'interests', 'interface', 'interpret', 'intervals', 'introduce', 'inventing', 'invisible', 'involving', 'irritated', 'irritates', 'isolating', 'justified', 'justifies', 'knowledge', 'languages', 'libraries', 'literally', 'locations', 'magnitude', 'maintains', 'materials', 'measuring', 'mechanics', 'mechanism', 'mentioned', 'mistaking', 'modifying', 'movements', 'naturally', 'necessary', 'necessity', 'numerical', 'objecting', 'objection', 'observing', 'obtaining', 'obviously', 'occasions', 'occupying', 'occurring', 'operating', 'operation', 'operators', 'otherwise', 'ourselves', 'paragraph', 'partially', 'perfectly', 'performed', 'permanent', 'permitted', 'persuaded', 'persuades', 'pointless', 'political', 'positions', 'potential', 'practical', 'precisely', 'preferred', 'preparing', 'presented', 'president', 'prevented', 'primitive', 'principle', 'procedure', 'processed', 'processes', 'processor', 'producing', 'promising', 'proposing', 'protected', 'providing', 'publicity', 'published', 'publishes', 'qualified', 'qualifies', 'questions', 'receiving', 'reception', 'recommend', 'recording', 'recovered', 'reduction', 'redundant', 'reference', 'referring', 'reflected', 'regarding', 'registers', 'regularly', 'rejecting', 'releasing', 'relevance', 'religious', 'reluctant', 'remaining', 'remembers', 'reminding', 'repeating', 'replacing', 'reporting', 'represent', 'reproduce', 'requested', 'requiring', 'reserving', 'resourced', 'resources', 'responses', 'restoring', 'restricts', 'resulting', 'returning', 'revealing', 'satisfied', 'satisfies', 'searching', 'secondary', 'secretary', 'selecting', 'selection', 'sensitive', 'sentences', 'sequences', 'seriously', 'similarly', 'sincerely', 'situation', 'solutions', 'someplace', 'something', 'sometimes', 'somewhere', 'specially', 'specified', 'specifies', 'splitting', 'spreading', 'standards', 'statement', 'statistic', 'structure', 'submitted', 'suffering', 'suggested', 'supplying', 'supported', 'supposing', 'surprised', 'surprises', 'surviving', 'suspected', 'suspended', 'suspicion', 'switching', 'technical', 'technique', 'telephone', 'temporary', 'terminals', 'therefore', 'thousands', 'transfers', 'translate', 'transport', 'treatment', 'uncertain', 'universal', 'unlimited', 'upsetting', 'vacations', 'variables', 'variation', 'virtually', 'welcoming', 'wonderful', 'wondering', 'yesterday'], | |
10: ['absolutely', 'acceptable', 'accessible', 'accidental', 'activities', 'additional', 'addressing', 'admittedly', 'advantages', 'advertised', 'advertises', 'algorithms', 'altogether', 'apparently', 'appearance', 'appreciate', 'arithmetic', 'artificial', 'associated', 'associates', 'assumption', 'atmosphere', 'attempting', 'attractive', 'automobile', 'background', 'beforehand', 'broadcasts', 'categories', 'characters', 'collecting', 'collection', 'commenting', 'commercial', 'commission', 'commitment', 'comparable', 'comparison', 'compatible', 'complained', 'complaints', 'completely', 'completing', 'complexity', 'complicate', 'components', 'compromise', 'compulsory', 'concerning', 'conclusion', 'conditions', 'conference', 'confirming', 'connecting', 'connection', 'considered', 'consistent', 'constraint', 'containing', 'continuing', 'continuous', 'contribute', 'controlled', 'convenient', 'convention', 'convincing', 'correcting', 'correction', 'corrupting', 'dedicating', 'definitely', 'definition', 'definitive', 'deliberate', 'delivering', 'democratic', 'department', 'describing', 'destroying', 'determined', 'determines', 'developing', 'dictionary', 'difference', 'difficulty', 'directions', 'disappears', 'discipline', 'discourage', 'discovered', 'discussing', 'discussion', 'displaying', 'distinctly', 'distribute', 'disturbing', 'documented', 'electronic', 'encounters', 'encouraged', 'encourages', 'engineered', 'equivalent', 'especially', 'eventually', 'everything', 'everywhere', 'exceptions', 'experience', 'experiment', 'explaining', 'expressing', 'expression', 'facilities', 'forgetting', 'frequently', 'generating', 'generation', 'government', 'guaranteed', 'guarantees', 'historical', 'implements', 'importance', 'impossible', 'impression', 'inadequate', 'incomplete', 'increasing', 'indication', 'individual', 'industrial', 'inevitably', 'installing', 'interested', 'interprets', 'introduced', 'introduces', 'invariably', 'invitation', 'irrelevant', 'irritating', 'justifying', 'laboratory', 'literature', 'maintained', 'meaningful', 'membership', 'mentioning', 'misleading', 'mysterious', 'objections', 'occasional', 'operations', 'opposition', 'originally', 'particular', 'performing', 'permission', 'permitting', 'personally', 'persuading', 'phenomenon', 'philosophy', 'population', 'postmaster', 'preferable', 'preferably', 'preference', 'preferring', 'presenting', 'presumably', 'preventing', 'previously', 'principles', 'processing', 'processors', 'production', 'programmer', 'properties', 'proportion', 'protecting', 'protection', 'publishing', 'qualifying', 'quantities', 'reasonable', 'reasonably', 'recommends', 'recovering', 'references', 'reflecting', 'reflection', 'regardless', 'registered', 'regulation', 'relatively', 'remembered', 'repeatedly', 'represents', 'requesting', 'resolution', 'resourcing', 'restricted', 'ridiculous', 'satisfying', 'scientific', 'separately', 'situations', 'specifying', 'statements', 'statistics', 'structures', 'submitting', 'subsequent', 'substitute', 'successful', 'sufficient', 'suggesting', 'suggestion', 'supervisor', 'supporting', 'supposedly', 'surprising', 'suspecting', 'suspending', 'techniques', 'technology', 'television', 'themselves', 'thoroughly', 'throughout', 'translated', 'translates', 'ultimately', 'underneath', 'understand', 'understood', 'university', 'unpleasant', 'unsuitable', 'whatsoever', 'widespread', 'worthwhile'], | |
11: ['accordingly', 'advertising', 'alternative', 'application', 'appreciated', 'appreciates', 'appropriate', 'arrangement', 'associating', 'association', 'authorities', 'calculation', 'circulation', 'combination', 'communicate', 'competition', 'complaining', 'complicated', 'complicates', 'composition', 'connections', 'consequence', 'considering', 'consistency', 'constraints', 'consumption', 'continually', 'controlling', 'conventions', 'definitions', 'demonstrate', 'description', 'determining', 'development', 'differences', 'differently', 'disappeared', 'discouraged', 'discourages', 'discovering', 'discussions', 'distinction', 'distinguish', 'distributed', 'distributes', 'documenting', 'educational', 'effectively', 'electronics', 'embarrassed', 'embarrasses', 'encountered', 'encouraging', 'engineering', 'environment', 'essentially', 'established', 'establishes', 'experienced', 'experiences', 'experiments', 'explanation', 'forthcoming', 'fortunately', 'fundamental', 'imagination', 'immediately', 'implemented', 'implication', 'importantly', 'improvement', 'independent', 'individuals', 'information', 'institution', 'instruction', 'intelligent', 'interesting', 'interpreted', 'introducing', 'investigate', 'maintaining', 'mathematics', 'meaningless', 'necessarily', 'observation', 'opportunity', 'performance', 'permanently', 'possibility', 'potentially', 'practically', 'preparation', 'programmers', 'publication', 'punctuation', 'recognition', 'recommended', 'registering', 'regulations', 'remembering', 'replacement', 'represented', 'requirement', 'responsible', 'restricting', 'significant', 'statistical', 'substantial', 'suggestions', 'temperature', 'temporarily', 'terminology', 'theoretical', 'traditional', 'transferred', 'translating', 'translation', 'understands', 'unfortunate', 'unnecessary'], | |
12: ['accidentally', 'alternatives', 'announcement', 'applications', 'appreciating', 'arrangements', 'broadcasting', 'calculations', 'circumstance', 'combinations', 'complicating', 'consequences', 'consequently', 'considerable', 'considerably', 'continuation', 'continuously', 'contribution', 'conventional', 'conversation', 'deliberately', 'descriptions', 'difficulties', 'disadvantage', 'disappearing', 'discouraging', 'distributing', 'distribution', 'embarrassing', 'encountering', 'establishing', 'experiencing', 'experimental', 'guaranteeing', 'implementing', 'implications', 'improvements', 'incidentally', 'incompatible', 'inconsistent', 'individually', 'institutions', 'instructions', 'intelligence', 'interpreting', 'intervention', 'introduction', 'manipulation', 'mathematical', 'nevertheless', 'occasionally', 'particularly', 'professional', 'recommending', 'relationship', 'representing', 'requirements', 'respectively', 'significance', 'simultaneous', 'sophisticate', 'specifically', 'successfully', 'sufficiently', 'transferring', 'unacceptable', 'universities', 'unreasonable'] | |
}; | |
}); | |
// lib/game/entities/particle.js | |
ig.baked = true; | |
ig.module('game.entities.particle').requires('impact.entity').defines(function () { | |
EntityParticle = ig.Entity.extend({ | |
size: { | |
x: 4, | |
y: 4 | |
}, | |
offset: { | |
x: 0, | |
y: 0 | |
}, | |
maxVel: { | |
x: 160, | |
y: 160 | |
}, | |
minBounceVelocity: 0, | |
type: ig.Entity.TYPE.NONE, | |
checkAgainst: ig.Entity.TYPE.NONE, | |
collides: ig.Entity.COLLIDES.LITE, | |
lifetime: 5, | |
fadetime: 1, | |
bounciness: 0.6, | |
friction: { | |
x: 20, | |
y: 0 | |
}, | |
init: function (x, y, settings) { | |
this.parent(x, y, settings); | |
this.vel.x = (Math.random() * 2 - 1) * this.vel.x; | |
this.vel.y = (Math.random() * 2 - 1) * this.vel.y; | |
this.currentAnim.flip.x = (Math.random() > 0.5); | |
this.currentAnim.flip.y = (Math.random() > 0.5); | |
this.currentAnim.gotoRandomFrame(); | |
this.idleTimer = new ig.Timer(); | |
}, | |
update: function () { | |
if (this.idleTimer.delta() > this.lifetime) { | |
this.kill(); | |
return; | |
} | |
this.currentAnim.alpha = this.idleTimer.delta().map(this.lifetime - this.fadetime, this.lifetime, 1, 0); | |
this.parent(); | |
} | |
}); | |
}); | |
// lib/game/entities/enemy.js | |
ig.baked = true; | |
ig.module('game.entities.enemy').requires('impact.entity', 'impact.font', 'game.words', 'game.entities.particle').defines(function () { | |
EntityEnemy = ig.Entity.extend({ | |
word: 'none', | |
remainingWord: 'none', | |
health: 8, | |
currentLetter: 0, | |
targeted: false, | |
font: new ig.Font('media/fonts/tungsten-18.png'), | |
fontActive: new ig.Font('media/fonts/tungsten-18-orange.png'), | |
speed: 10, | |
friction: { | |
x: 100, | |
y: 100 | |
}, | |
hitTimer: null, | |
dead: false, | |
angle: 0, | |
wordLength: { | |
min: 8, | |
max: 8 | |
}, | |
soundHit: new ig.Sound('media/sounds/hit.ogg'), | |
type: ig.Entity.TYPE.B, | |
checkAgainst: ig.Entity.TYPE.A, | |
init: function (x, y, settings) { | |
this.parent(x, y, settings); | |
this.health = Math.random().map(0, 1, this.wordLength.min, this.wordLength.max).round(); | |
this.word = this.getWordWithLength(this.health); | |
this.remainingWord = this.word; | |
this.hitTimer = new ig.Timer(0); | |
this.dieTimer = new ig.Timer(0); | |
ig.game.registerTarget(this.word.charAt(0), this); | |
this.angle = this.angleTo(ig.game.player); | |
}, | |
getWordWithLength: function (l) { | |
var w = 'wtf'; | |
for (var i = 0; i < 20; i++) { | |
if (l >= 2 && l <= 12) { | |
w = WORDS[l].random(); | |
} else { | |
w = String.fromCharCode('a'.charCodeAt(0) + (Math.random() * 26).floor()); | |
} | |
if (!ig.game.targets[w.charAt(0)].length) { | |
return w; | |
} | |
} | |
return w; | |
}, | |
target: function () { | |
this.targeted = true; | |
ig.game.currentTarget = this; | |
ig.game.unregisterTarget(this.word.charAt(0), this); | |
ig.game.entities.erase(this); | |
ig.game.entities.push(this); | |
}, | |
draw: function () { | |
ig.system.context.globalCompositeOperation = 'lighter'; | |
this.parent(); | |
ig.system.context.globalCompositeOperation = 'source-over'; | |
}, | |
drawLabel: function () { | |
if (!this.remainingWord.length) { | |
return; | |
} | |
var w = this.font.widthForString(this.word); | |
var x = (this.pos.x - 6).limit(w + 2, ig.system.width - 1); | |
var y = (this.pos.y + this.size.y - 10).limit(2, ig.system.height - 19); | |
var bx = ig.system.getDrawPos(x - w - 2); | |
var by = ig.system.getDrawPos(y - 1); | |
ig.system.context.fillStyle = 'rgba(0,0,0,0.5)'; | |
ig.system.context.fillRect(bx, by, w + 3, 19); | |
if (this.targeted) { | |
this.fontActive.draw(this.remainingWord, x, y, ig.Font.ALIGN.RIGHT); | |
} else { | |
this.font.draw(this.remainingWord, x, y, ig.Font.ALIGN.RIGHT); | |
} | |
}, | |
kill: function () { | |
ig.game.unregisterTarget(this.word.charAt(0), this); | |
if (ig.game.currentTarget == this) { | |
ig.game.currentTarget = null; | |
} | |
this.parent(); | |
}, | |
update: function () { | |
if (this.hitTimer.delta() > 0) { | |
this.vel.x = Math.cos(this.angle) * this.speed; | |
this.vel.y = Math.sin(this.angle) * this.speed; | |
} | |
this.parent(); | |
if (this.pos.x < -this.animSheet.width || this.pos.x > ig.system.width + 10 || this.pos.y > ig.system.height + 10 || this.pos.y < -this.animSheet.height - 30) { | |
this.kill(); | |
} | |
}, | |
hit: function () { | |
var numParticles = this.health <= 1 ? 10 : 4; | |
for (var i = 0; i < numParticles; i++) { | |
ig.game.spawnEntity(EntityExplosionParticle, this.pos.x, this.pos.y); | |
} | |
this.vel.x = -Math.cos(this.angle) * 20; | |
this.vel.y = -Math.sin(this.angle) * 20; | |
this.hitTimer.set(0.3); | |
this.receiveDamage(1); | |
ig.game.lastKillTimer.set(0.3); | |
this.soundHit.play(); | |
}, | |
isHitBy: function (letter) { | |
if (this.remainingWord.charAt(0) == letter) { | |
this.remainingWord = this.remainingWord.substr(1); | |
if (this.remainingWord.length == 0) { | |
ig.game.currentTarget = null; | |
ig.game.unregisterTarget(this.word.charAt(0), this); | |
this.dead = true; | |
} | |
return true; | |
} else { | |
return false; | |
} | |
}, | |
check: function (other) { | |
other.kill(); | |
this.kill(); | |
} | |
}); | |
EntityExplosionParticle = EntityParticle.extend({ | |
lifetime: 0.5, | |
fadetime: 0.5, | |
vel: { | |
x: 60, | |
y: 60 | |
}, | |
animSheet: new ig.AnimationSheet('media/sprites/explosion.png', 32, 32), | |
init: function (x, y, settings) { | |
this.addAnim('idle', 5, [0, 1, 2]); | |
this.parent(x, y, settings); | |
}, | |
draw: function () { | |
ig.system.context.globalCompositeOperation = 'lighter'; | |
this.parent(); | |
ig.system.context.globalCompositeOperation = 'source-over'; | |
}, | |
update: function () { | |
this.currentAnim.angle += 0.1 * ig.system.tick; | |
this.parent(); | |
} | |
}); | |
}); | |
// lib/game/entities/enemy-missle.js | |
ig.baked = true; | |
ig.module('game.entities.enemy-missle').requires('game.entities.enemy').defines(function () { | |
EntityEnemyMissle = EntityEnemy.extend({ | |
size: { | |
x: 8, | |
y: 15 | |
}, | |
offset: { | |
x: 6, | |
y: 7 | |
}, | |
animSheet: new ig.AnimationSheet('media/sprites/missle.png', 20, 26), | |
health: 4, | |
speed: 35, | |
targetTimer: null, | |
wordLength: { | |
min: 2, | |
max: 5 | |
}, | |
init: function (x, y, settings) { | |
this.parent(x, y, settings); | |
this.addAnim('idle', 1, [0]); | |
this.angle = settings.angle; | |
this.currentAnim.angle = this.angle - Math.PI / 2; | |
this.targetTimer = new ig.Timer(1); | |
}, | |
update: function () { | |
var d = this.targetTimer.delta(); | |
if (d > 0 && d < 0.7) { | |
var ad = this.angle - this.angleTo(ig.game.player); | |
this.angle -= ad * ig.system.tick * 2; | |
this.currentAnim.angle = this.angle - Math.PI / 2; | |
} | |
this.parent(); | |
} | |
}); | |
}); | |
// lib/game/entities/enemy-mine.js | |
ig.baked = true; | |
ig.module('game.entities.enemy-mine').requires('game.entities.enemy').defines(function () { | |
EntityEnemyMine = EntityEnemy.extend({ | |
size: { | |
x: 12, | |
y: 12 | |
}, | |
offset: { | |
x: 10, | |
y: 10 | |
}, | |
animSheet: new ig.AnimationSheet('media/sprites/mine.png', 32, 32), | |
speed: 30, | |
health: 6, | |
wordLength: { | |
min: 3, | |
max: 6 | |
}, | |
init: function (x, y, settings) { | |
this.parent(x, y, settings); | |
this.addAnim('idle', 1, [0]); | |
}, | |
update: function () { | |
this.angle = this.angleTo(ig.game.player); | |
this.parent(); | |
this.currentAnim.angle += 2 * ig.system.tick; | |
} | |
}); | |
}); | |
// lib/game/entities/enemy-destroyer.js | |
ig.baked = true; | |
ig.module('game.entities.enemy-destroyer').requires('game.entities.enemy').defines(function () { | |
EntityEnemyDestroyer = EntityEnemy.extend({ | |
size: { | |
x: 24, | |
y: 34 | |
}, | |
offset: { | |
x: 10, | |
y: 8 | |
}, | |
animSheet: new ig.AnimationSheet('media/sprites/destroyer.png', 43, 58), | |
health: 8, | |
speed: 20, | |
shootTimer: null, | |
wordLength: { | |
min: 7, | |
max: 10 | |
}, | |
init: function (x, y, settings) { | |
this.parent(x, y, settings); | |
this.addAnim('idle', 1, [0]); | |
this.shootTimer = new ig.Timer(5); | |
this.angle = (Math.random().map(0, 1, 67, 90) + (this.pos.x > ig.system.width / 2 ? 22.5 : 0)) * Math.PI / 180; | |
this.currentAnim.angle = this.angle - Math.PI / 2; | |
}, | |
update: function () { | |
this.parent(); | |
if (this.shootTimer.delta() > 0) { | |
this.shootTimer.reset(); | |
ig.game.spawnEntity(EntityEnemyMissle, this.pos.x + 12, this.pos.y + 22, { | |
angle: this.angle | |
}); | |
} | |
} | |
}); | |
}); | |
// lib/game/entities/enemy-oppressor.js | |
ig.baked = true; | |
ig.module('game.entities.enemy-oppressor').requires('game.entities.enemy').defines(function () { | |
EntityEnemyOppressor = EntityEnemy.extend({ | |
size: { | |
x: 36, | |
y: 58 | |
}, | |
offset: { | |
x: 16, | |
y: 10 | |
}, | |
animSheet: new ig.AnimationSheet('media/sprites/oppressor.png', 68, 88), | |
health: 10, | |
speed: 15, | |
shootTimer: null, | |
bullets: 16, | |
wordLength: { | |
min: 9, | |
max: 12 | |
}, | |
init: function (x, y, settings) { | |
this.parent(x, y - 18, settings); | |
this.addAnim('idle', 1, [0]); | |
this.shootTimer = new ig.Timer(7); | |
this.angle = Math.PI / 2; | |
}, | |
update: function () { | |
this.parent(); | |
if (this.shootTimer.delta() > 0) { | |
var inc = 140 / (this.bullets - 1); | |
var a = 20; | |
var radius = 21; | |
for (var i = 0; i < this.bullets; i++) { | |
var angle = a * Math.PI / 180; | |
var x = this.pos.x + 18 + Math.cos(angle) * radius; | |
var y = this.pos.y + 48 + Math.sin(angle) * radius; | |
ig.game.spawnEntity(EntityEnemyBullet, x, y, { | |
angle: angle | |
}); | |
a += inc; | |
} | |
this.shootTimer.reset(); | |
} | |
} | |
}); | |
EntityEnemyBullet = EntityEnemy.extend({ | |
size: { | |
x: 2, | |
y: 2 | |
}, | |
offset: { | |
x: 8, | |
y: 11 | |
}, | |
animSheet: new ig.AnimationSheet('media/sprites/bullet.png', 20, 24), | |
health: 1, | |
speed: 50, | |
wordLength: { | |
min: 1, | |
max: 1 | |
}, | |
init: function (x, y, settings) { | |
this.parent(x, y, settings); | |
this.addAnim('idle', 1, [0]); | |
this.angle = settings.angle; | |
this.currentAnim.angle = this.angle - Math.PI / 2; | |
} | |
}); | |
}); | |
// lib/game/entities/player.js | |
ig.baked = true; | |
ig.module('game.entities.player').requires('impact.entity', 'game.entities.particle').defines(function () { | |
EntityPlayer = ig.Entity.extend({ | |
animSheet: new ig.AnimationSheet('media/sprites/ship.png', 24, 24), | |
targetAngle: 0, | |
size: { | |
x: 8, | |
y: 8 | |
}, | |
offset: { | |
x: 8, | |
y: 8 | |
}, | |
angle: 0, | |
targetAngle: 0, | |
soundShoot: new ig.Sound('media/sounds/plasma.ogg'), | |
soundMiss: new ig.Sound('media/sounds/click.ogg'), | |
soundExplode: new ig.Sound('media/sounds/explosion.ogg'), | |
type: ig.Entity.TYPE.A, | |
init: function (x, y, settings) { | |
this.parent(x, y, settings); | |
this.addAnim('idle', 60, [0]); | |
this.addAnim('shoot', 0.05, [3, 2, 1, 0], true); | |
this.addAnim('miss', 0.05, [4, 5, 6], true); | |
}, | |
draw: function () { | |
ig.system.context.globalCompositeOperation = 'lighter'; | |
this.parent(); | |
ig.system.context.globalCompositeOperation = 'source-over'; | |
}, | |
update: function () { | |
if (this.currentAnim.loopCount > 0) { | |
this.currentAnim = this.anims.idle; | |
} | |
var ad = this.angle - this.targetAngle; | |
if (Math.abs(ad) < 0.02) { | |
this.angle = this.targetAngle; | |
} else { | |
this.angle -= ad * ig.system.tick * 10; | |
} | |
this.currentAnim.angle = this.angle; | |
this.parent(); | |
}, | |
kill: function () { | |
ig.game.setGameOver(); | |
this.soundExplode.play(); | |
for (var i = 0; i < 50; i++) { | |
ig.game.spawnEntity(EntityExplosionParticleFast, this.pos.x, this.pos.y); | |
} | |
this.pos.y = ig.system.height + 300; | |
this.parent(); | |
}, | |
shoot: function (target) { | |
this.currentAnim = this.anims.shoot.rewind(); | |
var ent = ig.game.spawnEntity(EntityPlasma, this.pos.x + 6, this.pos.y + 4); | |
ent.target = target; | |
var angle = this.angleTo(target); | |
this.targetAngle = angle + Math.PI / 2; | |
this.soundShoot.play(); | |
}, | |
miss: function () { | |
this.currentAnim = this.anims.miss.rewind(); | |
this.soundMiss.play(); | |
} | |
}); | |
EntityPlasma = ig.Entity.extend({ | |
speed: 800, | |
maxVel: { | |
x: 1000, | |
y: 1000 | |
}, | |
animSheet: new ig.AnimationSheet('media/sprites/plasma.png', 96, 96), | |
size: { | |
x: 4, | |
y: 4 | |
}, | |
offset: { | |
x: 46, | |
y: 46 | |
}, | |
distance: 100000, | |
init: function (x, y, settings) { | |
this.parent(x, y, settings); | |
this.addAnim('idle', 1, [0]); | |
}, | |
draw: function () { | |
ig.system.context.globalCompositeOperation = 'lighter'; | |
this.parent(); | |
ig.system.context.globalCompositeOperation = 'source-over'; | |
}, | |
update: function () { | |
if (this.target) { | |
var currentDistance = this.distanceTo(this.target); | |
if (currentDistance > this.distance || currentDistance < this.target.size.y) { | |
this.target.hit(); | |
this.kill(); | |
return; | |
} else { | |
var angle = this.angleTo(this.target); | |
this.currentAnim.angle = angle + Math.PI / 2; | |
this.vel.x = Math.cos(angle) * this.speed; | |
this.vel.y = Math.sin(angle) * this.speed; | |
} | |
this.distance = currentDistance; | |
this.parent(); | |
} else { | |
this.kill(); | |
} | |
} | |
}); | |
EntityExplosionParticleFast = EntityParticle.extend({ | |
lifetime: 2, | |
fadetime: 2, | |
maxVel: { | |
x: 1000, | |
y: 1000 | |
}, | |
vel: { | |
x: 100, | |
y: 100 | |
}, | |
animSheet: new ig.AnimationSheet('media/sprites/explosion.png', 32, 32), | |
init: function (x, y, settings) { | |
this.addAnim('idle', 5, [0, 1, 2]); | |
this.parent(x, y, settings); | |
}, | |
draw: function () { | |
ig.system.context.globalCompositeOperation = 'lighter'; | |
this.parent(); | |
ig.system.context.globalCompositeOperation = 'source-over'; | |
}, | |
update: function () { | |
this.currentAnim.angle += 0.1 * ig.system.tick; | |
this.parent(); | |
} | |
}); | |
}); | |
// lib/plugins/impact-splash-loader.js | |
ig.baked = true; | |
ig.module('plugins.impact-splash-loader').requires('impact.loader').defines(function () { | |
ig.ImpactSplashLoader = ig.Loader.extend({ | |
endTimer: 0, | |
fadeToWhiteTime: 200, | |
fadeToGameTime: 800, | |
end: function () { | |
this.parent(); | |
this.endTime = Date.now(); | |
ig.system.setDelegate(this); | |
}, | |
run: function () { | |
var t = Date.now() - this.endTime; | |
var alpha = 1; | |
if (t < this.fadeToWhiteTime) { | |
this.draw(); | |
alpha = t.map(0, this.fadeToWhiteTime, 0, 1); | |
} else if (t < this.fadeToGameTime) { | |
ig.game.run(); | |
alpha = t.map(this.fadeToWhiteTime, this.fadeToGameTime, 1, 0); | |
} else { | |
ig.system.setDelegate(ig.game); | |
return; | |
} | |
ig.system.context.fillStyle = 'rgba(255,255,255,' + alpha + ')'; | |
ig.system.context.fillRect(0, 0, ig.system.realWidth, ig.system.realHeight); | |
}, | |
draw: function () { | |
this._drawStatus += (this.status - this._drawStatus) / 5; | |
var ctx = ig.system.context; | |
var w = ig.system.realWidth; | |
var h = ig.system.realHeight; | |
var s = w / 340 / 3; | |
var c = (w - 340 * s) / 2; | |
ctx.fillStyle = 'rgba(0,0,0,0.8)'; | |
ctx.fillRect(0, 0, w, h); | |
ctx.fillStyle = '#888'; | |
ctx.textAlign = 'right'; | |
ctx.font = '10px Arial'; | |
ctx.fillText('http://impactjs.com', w - 10, h - 10); | |
ctx.textAlign = 'left'; | |
ctx.save(); | |
ctx.translate(c, h / 2.5); | |
ctx.scale(s, s); | |
ctx.lineWidth = '3'; | |
ctx.strokeStyle = '#666666'; | |
ctx.strokeRect(25, 160, 300, 20); | |
ctx.fillStyle = '#ffffff'; | |
ctx.fillRect(30, 165, 290 * this._drawStatus, 10); | |
this.drawPaths("rgb(255,255,255)", ig.ImpactSplashLoader.PATHS_IMPACT); | |
var comet = ig.ImpactSplashLoader.PATHS_COMET; | |
comet[5][0] = 3 - Math.random() * this._drawStatus * 7; | |
comet[5][1] = 3 - Math.random() * this._drawStatus * 10; | |
comet[7][0] = 29.5 - Math.random() * this._drawStatus * 10; | |
comet[7][1] = 40.4 - Math.random() * this._drawStatus * 10; | |
comet[9][0] = 16.1 - Math.random() * this._drawStatus * 10; | |
comet[9][1] = 36.1 - Math.random() * this._drawStatus * 5; | |
ctx.translate(-Math.random() * this._drawStatus * 7, -Math.random() * this._drawStatus * 5); | |
this.drawPaths("rgb(243,120,31)", comet); | |
ctx.restore(); | |
}, | |
drawPaths: function (color, paths) { | |
var ctx = ig.system.context; | |
ctx.fillStyle = color; | |
for (var i = 0; i < paths.length; i += 2) { | |
ctx[ig.ImpactSplashLoader.OPS[paths[i]]].apply(ctx, paths[i + 1]); | |
} | |
} | |
}); | |
ig.ImpactSplashLoader.OPS = { | |
bp: 'beginPath', | |
cp: 'closePath', | |
f: 'fill', | |
m: 'moveTo', | |
l: 'lineTo', | |
bc: 'bezierCurveTo' | |
}; | |
ig.ImpactSplashLoader.PATHS_COMET = ['bp', [], 'm', [85.1, 58.3], 'l', [0.0, 0.0], 'l', [29.5, 40.4], 'l', [16.1, 36.1], 'l', [54.6, 91.6], 'bc', [65.2, 106.1, 83.4, 106.7, 93.8, 95.7], 'bc', [103.9, 84.9, 98.6, 67.6, 85.1, 58.3], 'cp', [], 'm', [76.0, 94.3], 'bc', [68.5, 94.3, 62.5, 88.2, 62.5, 80.8], 'bc', [62.5, 73.3, 68.5, 67.2, 76.0, 67.2], 'bc', [83.5, 67.2, 89.6, 73.3, 89.6, 80.8], 'bc', [89.6, 88.2, 83.5, 94.3, 76.0, 94.3], 'cp', [], 'f', []]; | |
ig.ImpactSplashLoader.PATHS_IMPACT = ['bp', [], 'm', [128.8, 98.7], 'l', [114.3, 98.7], 'l', [114.3, 26.3], 'l', [128.8, 26.3], 'l', [128.8, 98.7], 'cp', [], 'f', [], 'bp', [], 'm', [159.2, 70.1], 'l', [163.6, 26.3], 'l', [184.6, 26.3], 'l', [184.6, 98.7], 'l', [170.3, 98.7], 'l', [170.3, 51.2], 'l', [164.8, 98.7], 'l', [151.2, 98.7], 'l', [145.7, 50.7], 'l', [145.7, 98.7], 'l', [134.1, 98.7], 'l', [134.1, 26.3], 'l', [155.0, 26.3], 'l', [159.2, 70.1], 'cp', [], 'f', [], 'bp', [], 'm', [204.3, 98.7], 'l', [189.8, 98.7], 'l', [189.8, 26.3], 'l', [211.0, 26.3], 'bc', [220.0, 26.3, 224.5, 30.7, 224.5, 39.7], 'l', [224.5, 60.1], 'bc', [224.5, 69.1, 220.0, 73.6, 211.0, 73.6], 'l', [204.3, 73.6], 'l', [204.3, 98.7], 'cp', [], 'm', [207.4, 38.7], 'l', [204.3, 38.7], 'l', [204.3, 61.2], 'l', [207.4, 61.2], 'bc', [209.1, 61.2, 210.0, 60.3, 210.0, 58.6], 'l', [210.0, 41.3], 'bc', [210.0, 39.5, 209.1, 38.7, 207.4, 38.7], 'cp', [], 'f', [], 'bp', [], 'm', [262.7, 98.7], 'l', [248.3, 98.7], 'l', [247.1, 88.2], 'l', [238.0, 88.2], 'l', [237.0, 98.7], 'l', [223.8, 98.7], 'l', [233.4, 26.3], 'l', [253.1, 26.3], 'l', [262.7, 98.7], 'cp', [], 'm', [239.4, 75.5], 'l', [245.9, 75.5], 'l', [242.6, 43.9], 'l', [239.4, 75.5], 'cp', [], 'f', [], 'bp', [], 'm', [300.9, 66.7], 'l', [300.9, 85.9], 'bc', [300.9, 94.9, 296.4, 99.4, 287.4, 99.4], 'l', [278.5, 99.4], 'bc', [269.5, 99.4, 265.1, 94.9, 265.1, 85.9], 'l', [265.1, 39.1], 'bc', [265.1, 30.1, 269.5, 25.6, 278.5, 25.6], 'l', [287.2, 25.6], 'bc', [296.2, 25.6, 300.7, 30.1, 300.7, 39.1], 'l', [300.7, 56.1], 'l', [286.4, 56.1], 'l', [286.4, 40.7], 'bc', [286.4, 38.9, 285.6, 38.1, 283.8, 38.1], 'l', [282.1, 38.1], 'bc', [280.4, 38.1, 279.5, 38.9, 279.5, 40.7], 'l', [279.5, 84.3], 'bc', [279.5, 86.1, 280.4, 86.9, 282.1, 86.9], 'l', [284.0, 86.9], 'bc', [285.8, 86.9, 286.6, 86.1, 286.6, 84.3], 'l', [286.6, 66.7], 'l', [300.9, 66.7], 'cp', [], 'f', [], 'bp', [], 'm', [312.5, 98.7], 'l', [312.5, 39.2], 'l', [303.7, 39.2], 'l', [303.7, 26.3], 'l', [335.8, 26.3], 'l', [335.8, 39.2], 'l', [327.0, 39.2], 'l', [327.0, 98.7], 'l', [312.5, 98.7], 'cp', [], 'f', [], ]; | |
}); | |
// lib/game/main.js | |
ig.baked = true; | |
ig.module('game.main').requires('impact.game', 'impact.font', 'game.menus', 'game.entities.enemy-missle', 'game.entities.enemy-mine', 'game.entities.enemy-destroyer', 'game.entities.enemy-oppressor', 'game.entities.player', 'plugins.impact-splash-loader').defines(function () { | |
Number.zeroes = '000000000000'; | |
Number.prototype.zeroFill = function (d) { | |
var s = this.toString(); | |
return Number.zeroes.substr(0, d - s.length) + s; | |
}; | |
ZType = ig.Game.extend({ | |
font: new ig.Font('media/fonts/tungsten-18.png'), | |
fontScore: new ig.Font('media/fonts/04b03-mono-digits.png'), | |
fontTitle: new ig.Font('media/fonts/tungsten-48.png'), | |
fontSelected: new ig.Font('media/fonts/tungsten-18-orange.png'), | |
spawnTimer: null, | |
targets: {}, | |
currentTarget: null, | |
yScroll: 0, | |
backdrop: new ig.Image('media/background/backdrop.png'), | |
grid: new ig.Image('media/background/grid.png'), | |
music: new ig.Sound('media/music/endure.ogg', false), | |
menu: null, | |
mode: 0, | |
score: 0, | |
streak: 0, | |
hits: 0, | |
misses: 0, | |
multiplier: 1, | |
wave: {}, | |
gameTime: 0, | |
kills: 0, | |
difficulty: 'NORMAL', | |
init: function () { | |
var bgmap = new ig.BackgroundMap(62, [ | |
[1] | |
], this.grid); | |
bgmap.repeat = true; | |
this.backgroundMaps.push(bgmap); | |
ig.music.add(this.music); | |
window.addEventListener('keydown', this.keydown.bind(this), false); | |
ig.input.bind(ig.KEY.ENTER, 'ok'); | |
ig.input.bind(ig.KEY.SPACE, 'ok'); | |
ig.input.bind(ig.KEY.MOUSE1, 'click'); | |
ig.input.bind(ig.KEY.BACKSPACE, 'void'); | |
ig.input.bind(ig.KEY.ESC, 'menu'); | |
ig.input.bind(ig.KEY.UP_ARROW, 'up'); | |
ig.input.bind(ig.KEY.DOWN_ARROW, 'down'); | |
ig.input.bind(ig.KEY.LEFT_ARROW, 'left'); | |
ig.input.bind(ig.KEY.RIGHT_ARROW, 'right'); | |
this.setTitle(); | |
window.focus(); | |
ig.system.canvas.onclick = function () { | |
window.focus(); | |
}; | |
}, | |
reset: function () { | |
this.entities = []; | |
this.currentTarget = null; | |
this.wave = ig.copy(ZType.WAVES[this.difficulty]); | |
var first = 'a'.charCodeAt(0), | |
last = 'z'.charCodeAt(0); | |
for (var i = first; i <= last; i++) { | |
this.targets[String.fromCharCode(i)] = []; | |
} | |
this.score = 0; | |
this.rs = 0; | |
this.streak = 0; | |
this.hits = 0; | |
this.misses = 0; | |
this.kills = 0; | |
this.multiplier = 1; | |
this.gameTime = 0; | |
this.lastKillTimer = new ig.Timer(); | |
this.spawnTimer = new ig.Timer(); | |
this.waveEndTimer = null; | |
}, | |
nextWave: function () { | |
this.wave.wave++; | |
this.wave.spawnWait = (this.wave.spawnWait * 0.97).limit(0.2, 1); | |
this.wave.spawn = []; | |
var dec = 0; | |
for (var t = 0; t < this.wave.types.length; t++) { | |
var type = this.wave.types[t]; | |
type.count -= dec; | |
if (this.wave.wave % type.incEvery == 0) { | |
type.count++; | |
dec++; | |
} | |
for (var s = 0; s < type.count; s++) { | |
this.wave.spawn.push(t); | |
} | |
} | |
this.wave.spawn.sort(function () { | |
return Math.random() - 0.5; | |
}); | |
}, | |
spawnCurrentWave: function () { | |
if (!this.wave.spawn.length) { | |
if (this.entities.length <= 1 && !this.waveEndTimer) { | |
this.waveEndTimer = new ig.Timer(2); | |
} else if (this.waveEndTimer && this.waveEndTimer.delta() > 0) { | |
this.waveEndTimer = null; | |
this.nextWave(); | |
} | |
} else if (this.spawnTimer.delta() > this.wave.spawnWait) { | |
this.spawnTimer.reset(); | |
var type = this.wave.types[this.wave.spawn.pop()].type; | |
var x = Math.random().map(0, 1, 10, ig.system.width - 10); | |
var y = -30; | |
this.spawnEntity(type, x, y, { | |
healthBoost: this.wave.healthBoost | |
}); | |
} | |
}, | |
registerTarget: function (letter, ent) { | |
this.targets[letter].push(ent); | |
}, | |
unregisterTarget: function (letter, ent) { | |
this.targets[letter].erase(ent); | |
}, | |
keydown: function (event) { | |
if (event.target.type == 'text' || event.ctrlKey || event.shiftKey || event.altKey || this.mode != ZType.MODE.GAME || this.menu) { | |
return true; | |
} | |
var c = event.which; | |
if (!((c > 64 && c < 91) || (c > 96 && c < 123))) { | |
return true; | |
} | |
event.stopPropagation(); | |
event.preventDefault(); | |
var letter = String.fromCharCode(c).toLowerCase(); | |
if (!this.currentTarget) { | |
var potentialTargets = this.targets[letter]; | |
var nearestDistance = -1; | |
var nearestTarget = null; | |
for (var i = 0; i < potentialTargets.length; i++) { | |
var distance = this.player.distanceTo(potentialTargets[i]); | |
if (distance < nearestDistance || !nearestTarget) { | |
nearestDistance = distance; | |
nearestTarget = potentialTargets[i]; | |
} | |
} | |
if (nearestTarget) { | |
nearestTarget.target(); | |
} else { | |
this.player.miss(); | |
this.multiplier = 1; | |
this.streak = 0; | |
this.misses++; | |
} | |
} | |
if (this.currentTarget) { | |
var c = this.currentTarget; | |
var hit = this.currentTarget.isHitBy(letter); | |
if (hit) { | |
this.player.shoot(c); | |
this.score += this.multiplier; | |
this.hits++; | |
this.streak++; | |
if (ZType.MULTIPLIER_TIERS[this.streak]) { | |
this.multiplier += 1; | |
} | |
if (c.dead) { | |
this.kills++; | |
} | |
} else { | |
this.player.miss(); | |
this.multiplier = 1; | |
this.streak = 0; | |
this.misses++; | |
} | |
} | |
return false; | |
}, | |
setGame: function () { | |
this.reset(); | |
this.menu = null; | |
this.player = this.spawnEntity(EntityPlayer, ig.system.width / 2, ig.system.height - 50); | |
this.mode = ZType.MODE.GAME; | |
this.nextWave(); | |
ig.music.play(); | |
}, | |
setGameOver: function () { | |
this.mode = ZType.MODE.GAME_OVER; | |
this.menu = new GameOverMenu(); | |
}, | |
setTitle: function () { | |
this.reset(); | |
this.mode = ZType.MODE.TITLE; | |
this.menu = new TitleMenu(); | |
}, | |
toggleMenu: function () { | |
if (this.mode == ZType.MODE.TITLE) { | |
if (this.menu instanceof TitleMenu) { | |
this.menu = new PauseMenu(); | |
} else { | |
this.menu = new TitleMenu(); | |
} | |
} else { | |
if (this.menu) { | |
this.menu = null; | |
} else { | |
this.menu = new PauseMenu(); | |
} | |
} | |
}, | |
update: function () { | |
if (ig.input.pressed('menu') && !this.menu) { | |
this.toggleMenu(); | |
} | |
if (this.menu) { | |
this.backgroundMaps[0].scroll.y -= 100 * ig.system.tick; | |
this.menu.update(); | |
if (!(this.menu instanceof GameOverMenu)) { | |
return; | |
} | |
} | |
this.parent(); | |
if (this.mode == ZType.MODE.GAME) { | |
this.spawnCurrentWave(); | |
} else if (ig.input.pressed('ok')) { | |
if (this.mode == ZType.MODE.TITLE) { | |
this.setGame(); | |
} else { | |
this.setTitle(); | |
} | |
} | |
this.yScroll -= 100 * ig.system.tick; | |
this.backgroundMaps[0].scroll.y += this.yScroll; | |
if (this.entities.length > 1 && this.mode == ZType.MODE.GAME) { | |
this.gameTime += ig.system.tick; | |
} | |
if (this.score - this.rs > 100 || ig.Timer.timeScale != 1) { | |
this.score = 0; | |
} | |
this.rs = this.score; | |
}, | |
draw: function () { | |
this.backdrop.draw(0, 0); | |
var d = this.lastKillTimer.delta(); | |
ig.system.context.globalAlpha = d < 0 ? d * -2 + 0.3 : 0.3; | |
for (var i = 0; i < this.backgroundMaps.length; i++) { | |
this.backgroundMaps[i].draw(); | |
} | |
ig.system.context.globalAlpha = 1; | |
for (var i = 0; i < this.entities.length; i++) { | |
this.entities[i].draw(); | |
} | |
for (var i = 0; i < this.entities.length; i++) { | |
this.entities[i].drawLabel && this.entities[i].drawLabel(); | |
} | |
if (this.mode == ZType.MODE.GAME) { | |
this.drawUI(); | |
} else if (this.mode == ZType.MODE.TITLE) { | |
this.drawTitle(); | |
} else if (this.mode == ZType.MODE.GAME_OVER) { | |
this.drawGameOver(); | |
} | |
if (this.menu) { | |
this.menu.draw(); | |
} | |
}, | |
drawUI: function () { | |
var s = '(' + this.multiplier + 'x) ' + this.score.zeroFill(6); | |
this.fontScore.draw(s, ig.system.width - 4, ig.system.height - 12, ig.Font.ALIGN.RIGHT); | |
if (this.waveEndTimer) { | |
var d = -this.waveEndTimer.delta(); | |
var a = d > 1.7 ? d.map(2, 1.7, 0, 1) : d < 1 ? d.map(1, 0, 1, 0) : 1; | |
var xs = ig.system.width / 2; | |
var ys = ig.system.height / 3 + (d < 1 ? Math.cos(1 - d).map(1, 0, 0, 250) : 0); | |
var w = this.wave.wave.zeroFill(3); | |
ig.system.context.globalAlpha = a; | |
this.fontTitle.draw('Wave ' + w + ' Clear', xs, ys, ig.Font.ALIGN.CENTER); | |
ig.system.context.globalAlpha = 1; | |
} | |
}, | |
drawTitle: function () { | |
var xs = ig.system.width / 2; | |
var ys = ig.system.height / 4; | |
this.fontTitle.draw('Z-Type', xs, ys, ig.Font.ALIGN.CENTER); | |
ig.system.context.globalAlpha = 0.8; | |
this.font.draw('Type to Shoot!', xs, ys + 90, ig.Font.ALIGN.CENTER); | |
ig.system.context.globalAlpha = 1; | |
var xc = 8; | |
var yc = ig.system.height - 40; | |
ig.system.context.globalAlpha = 0.6; | |
this.font.draw('Concept, Graphics & Programming: Dominic Szablewski', xc, yc); | |
this.font.draw('Music: Andreas Loesch', xc, yc + 20); | |
ig.system.context.globalAlpha = 1; | |
}, | |
drawGameOver: function () { | |
var xs = ig.system.width / 2; | |
var ys = ig.system.height / 4; | |
var acc = this.hits ? this.hits / (this.hits + this.misses) * 100 : 0; | |
var wpm = this.kills / (this.gameTime / 60); | |
this.fontTitle.draw('Game Over', xs, ys, ig.Font.ALIGN.CENTER); | |
this.fontTitle.draw('Final Score: ' + this.score.zeroFill(6), xs, ys + 90, ig.Font.ALIGN.CENTER); | |
this.font.draw('Accuracy: ' + acc.round(1) + '%', xs, ys + 144, ig.Font.ALIGN.CENTER); | |
this.font.draw('Words Per Minute: ' + wpm.round(1), xs, ys + 168, ig.Font.ALIGN.CENTER); | |
} | |
}); | |
ZType.MODE = { | |
TITLE: 0, | |
GAME: 1, | |
GAME_OVER: 2 | |
}; | |
ZType.MULTIPLIER_TIERS = { | |
25: 2, | |
50: 3, | |
100: 4 | |
}; | |
ZType.WAVES = { | |
NORMAL: { | |
wave: 0, | |
spawn: [], | |
spawnWait: 1, | |
healthBoost: 0, | |
types: [{ | |
type: EntityEnemyOppressor, | |
count: 0, | |
incEvery: 13 | |
}, { | |
type: EntityEnemyDestroyer, | |
count: 0, | |
incEvery: 5 | |
}, { | |
type: EntityEnemyMine, | |
count: 3, | |
incEvery: 2 | |
}] | |
}, | |
EXPERT: { | |
wave: 0, | |
spawn: [], | |
spawnWait: 0.7, | |
healthBoost: 0, | |
types: [{ | |
type: EntityEnemyOppressor, | |
count: 1, | |
incEvery: 7 | |
}, { | |
type: EntityEnemyDestroyer, | |
count: 2, | |
incEvery: 3 | |
}, { | |
type: EntityEnemyMine, | |
count: 9, | |
incEvery: 1 | |
}] | |
} | |
}; | |
ig.System.drawMode = ig.System.DRAW.SMOOTH; | |
ig.main('#canvas', ZType, 60, 360, 640, 1, ig.ImpactSplashLoader); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Is this the source code of ztype?