Last active
April 13, 2017 22:21
-
-
Save illnyang/9d01ba1cda793f5501d4a15ec8eae2fc to your computer and use it in GitHub Desktop.
epic donttap src hack
This file contains hidden or 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
| /* | |
| (c) 2013-2014 GameMix Inc. All rights reserved. | |
| */ | |
| (function() { | |
| var requestAnimFrame = window.requestAnimFrame = function() { | |
| return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) { | |
| window.setTimeout(callback, 1e3 / 60) | |
| } | |
| }(); | |
| var cancelAnimFrame = window.cancelAnimFrame = function() { | |
| return window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || window.oCancelAnimationFrame || window.msCancelAnimationFrame || function() { | |
| window.clearTimeout.apply(window, arguments) | |
| } | |
| }(); | |
| navigator.vibrate = function() { | |
| return navigator.vibrate || navigator.mozVibrate || navigator.webkitVibrate || navigator.oVibrate || navigator.msVibrate || (navigator.notification ? function(l) { | |
| navigator.notification.vibrate(l) | |
| } : null) || new Function | |
| }(); | |
| var console = function() { | |
| return window.console || { | |
| log: new Function, | |
| debug: new Function, | |
| warn: new Function, | |
| error: new Function, | |
| clear: new Function | |
| } | |
| }(); | |
| var DOM = { | |
| get: function(el) { | |
| r = el == document || el == window || el instanceof HTMLElement ? el : document.getElementById(el); | |
| if (r == null) { | |
| console.log(el) | |
| } | |
| return r | |
| }, | |
| attr: function(el, attr, value) { | |
| if (value) { | |
| this.get(el).setAttribute(attr, value) | |
| } else { | |
| return this.get(el).getAttribute(attr) | |
| } | |
| }, | |
| on: function(el, evt, handler) { | |
| var split = evt.split(" "); | |
| for (var i in split) { | |
| this.get(el).addEventListener(split[i], handler, false) | |
| } | |
| }, | |
| un: function(el, evt, handler) { | |
| var split = evt.split(" "); | |
| for (var i in split) { | |
| this.get(el).removeEventListener(split[i], handler, false) | |
| } | |
| }, | |
| show: function(el) { | |
| this.get(el).style.display = "block" | |
| }, | |
| hide: function(el) { | |
| this.get(el).style.display = "none" | |
| }, | |
| offset: function(el) { | |
| el = this.get(el); | |
| return { | |
| x: el.clientLeft + window.scrollLeft, | |
| y: el.clientTop + window.scrollTop | |
| }; | |
| var pos = { | |
| x: 0, | |
| y: 0 | |
| }; | |
| do { | |
| pos.x += el.offsetLeft || 0; | |
| pos.y += el.offsetTop || 0 | |
| } while ((el = el.parentNode) !== null); | |
| return pos | |
| }, | |
| query: function(query) { | |
| if (!document.querySelectorAll) return null; | |
| var q = document.querySelectorAll(query); | |
| return q | |
| }, | |
| queryOne: function(query) { | |
| if (!document.querySelector) return null; | |
| var q = document.querySelector(query); | |
| return q | |
| }, | |
| create: function(type) { | |
| return document.createElement(type) | |
| }, | |
| positionRelativeTo: function(element, clientX, clientY) { | |
| var offset = DOM.offset(element); | |
| return { | |
| x: clientX - offset.x, | |
| y: clientY - offset.y | |
| } | |
| }, | |
| fitScreen: function(element, ratio) { | |
| var clientRatio = window.innerWidth / window.innerHeight; | |
| var width, height; | |
| if (clientRatio <= ratio) { | |
| width = window.innerWidth; | |
| height = width / ratio | |
| } else { | |
| height = window.innerHeight; | |
| width = height * ratio | |
| } | |
| element = DOM.get(element); | |
| element.style.width = width + "px"; | |
| element.style.height = height + "px"; | |
| return { | |
| width: width, | |
| height: height | |
| } | |
| }, | |
| saveCanvas: function(element) { | |
| var src = this.get(element); | |
| var can = this.create("canvas"); | |
| can.width = src.width; | |
| can.height = src.height; | |
| var c = can.getContext("2d"); | |
| c.drawImage(src, 0, 0); | |
| return can | |
| }, | |
| fadeIn: function(element, duration, callback) { | |
| element = this.get(element); | |
| duration = duration || 1e3; | |
| this.show(element); | |
| element.style.opacity = 0; | |
| Util.interpolate(element.style, { | |
| opacity: 1 | |
| }, duration, callback) | |
| }, | |
| fadeOut: function(element, duration, callback) { | |
| element = this.get(element); | |
| duration = duration || 1e3; | |
| this.show(element); | |
| element.style.opacity = 1; | |
| Util.interpolate(element.style, { | |
| opacity: 0 | |
| }, duration, function() { | |
| DOM.hide(element); | |
| if (callback) callback() | |
| }) | |
| }, | |
| notify: function(htmlMessage, duration, container) { | |
| container = container ? this.get(container) : document.body; | |
| this.notification = this.notification || function() { | |
| var block = DOM.create("div"); | |
| container.appendChild(block); | |
| DOM.applyStyle(block, { | |
| zIndex: 999999, | |
| position: "absolute", | |
| bottom: "10px", | |
| width: "100%", | |
| textAlign: "center" | |
| }); | |
| var message = DOM.create("span"); | |
| block.appendChild(message); | |
| DOM.applyStyle(message, { | |
| backgroundColor: "rgba(0,0,0,0.7)", | |
| border: "1px solid white", | |
| borderRadius: "3px", | |
| margin: "auto", | |
| color: "white", | |
| padding: "2px", | |
| paddingLeft: "10px", | |
| paddingRight: "10px", | |
| width: "50%", | |
| fontSize: "0.7em", | |
| boxShadow: "0px 0px 2px black" | |
| }); | |
| return { | |
| block: block, | |
| message: message, | |
| queue: [], | |
| add: function(message, duration) { | |
| this.queue.push({ | |
| message: message, | |
| duration: duration | |
| }); | |
| if (this.queue.length == 1) { | |
| this.applyOne() | |
| } | |
| }, | |
| applyOne: function() { | |
| var notif = this.queue[0]; | |
| this.message.innerHTML = notif.message; | |
| DOM.fadeIn(this.block, 500); | |
| setTimeout(function() { | |
| DOM.fadeOut(DOM.notification.block, 500, function() { | |
| DOM.notification.queue.shift(); | |
| if (DOM.notification.queue.length > 0) { | |
| DOM.notification.applyOne() | |
| } | |
| }) | |
| }, notif.duration + 500) | |
| } | |
| } | |
| }(); | |
| duration = duration || 3e3; | |
| this.notification.add(htmlMessage, duration) | |
| }, | |
| applyStyle: function(element, style) { | |
| element = this.get(element); | |
| for (var i in style) { | |
| element.style[i] = style[i] | |
| } | |
| }, | |
| populate: function(elements) { | |
| var res = {}; | |
| for (var i in elements) { | |
| res[i] = DOM.get(elements[i]); | |
| if (!res[i]) console.log("Element #" + elements[i] + " not found") | |
| } | |
| return res | |
| } | |
| }; | |
| var Util = { | |
| preload: function(images, callbackProgress, callbackEnd, callbackError) { | |
| var loadOne = function() { | |
| if (remaining.length == 0) { | |
| end(loaded) | |
| } else { | |
| var img = new Image; | |
| img.onerror = function() { | |
| console.log("Couldn't load " + src); | |
| error(src) | |
| }; | |
| img.onload = function() { | |
| if (this.complete) { | |
| progress(this, 1 - remaining.length / nbImages); | |
| setTimeout(loadOne, document.location.search.indexOf("fakelag") >= 0 ? 1e3 : 1) | |
| } | |
| }; | |
| var src = remaining.pop(); | |
| img.src = src; | |
| loaded[src] = img | |
| } | |
| }; | |
| var remaining = images.slice(0); | |
| var end = callbackEnd || new Function; | |
| var progress = callbackProgress || new Function; | |
| var error = callbackError || new Function; | |
| var nbImages = remaining.length; | |
| var loaded = {}; | |
| setTimeout(loadOne, 1) | |
| }, | |
| rand: function(min, max) { | |
| return Math.random() * (max - min) + min | |
| }, | |
| randomPick: function() { | |
| var i = parseInt(Util.rand(0, arguments.length)); | |
| return arguments[i] | |
| }, | |
| limit: function(n, min, max) { | |
| if (n < min) return min; | |
| else if (n > max) return max; | |
| else return n | |
| }, | |
| sign: function(n) { | |
| if (n > 0) return 1; | |
| else if (n == 0) return 0; | |
| else return -1 | |
| }, | |
| cookie: { | |
| set: function(name, value, ttl) { | |
| if (ttl == undefined) ttl = 1e3 * 3600 * 24 * 365; | |
| document.cookie = name + "=;path=/;expires=Thu, 01-Jan-1970 00:00:01 GMT"; | |
| var expires = new Date; | |
| expires.setTime(expires.getTime() + ttl); | |
| document.cookie = [name + "=" + value + "; ", "expires=" + expires.toGMTString() + "; ", "path=/"].join("") | |
| }, | |
| get: function(name) { | |
| var cookie = document.cookie.split("; "); | |
| for (var i in cookie) { | |
| var spl = cookie[i].split("="); | |
| if (spl.length == 2 && spl[0] == name) { | |
| return spl[1] | |
| } | |
| } | |
| return undefined | |
| } | |
| }, | |
| storage: window.localStorage ? { | |
| getItem: function(item) { | |
| return window.localStorage.getItem(item) | |
| }, | |
| setItem: function(item, value) { | |
| try { | |
| window.localStorage.setItem(item, value) | |
| } catch (e) { | |
| console.log("Local storage issue: " + e) | |
| } | |
| } | |
| } : { | |
| getItem: function(item) { | |
| return Util.cookie.get(item) | |
| }, | |
| setItem: function(item, value) { | |
| Util.cookie.set(item, value) | |
| } | |
| }, | |
| merge: function(template, object) { | |
| if (!object) { | |
| return template | |
| } | |
| for (var i in template) { | |
| if (!(i in object)) { | |
| object[i] = template[i] | |
| } else { | |
| if (typeof template[i] == "object" && !(object[i] instanceof Array)) { | |
| object[i] = arguments.callee.call(this, template[i], object[i]) | |
| } | |
| } | |
| } | |
| return object | |
| }, | |
| copyObject: function(obj) { | |
| var res = {}; | |
| for (var i in obj) { | |
| res[i] = obj[i] | |
| } | |
| return res | |
| }, | |
| isTouchScreen: function() { | |
| var bool = "orientation" in window || "orientation" in window.screen || "mozOrientation" in window.screen || "ontouchstart" in window || window.DocumentTouch && document instanceof DocumentTouch || "ontouchstart" in document.documentElement; | |
| if (bool) { | |
| bool = bool && Detect.isMobile() | |
| } | |
| return bool || window.location.search.indexOf("touch") >= 0 | |
| }, | |
| distance: function(x1, y1, x2, y2) { | |
| return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)) | |
| }, | |
| arrayUnique: function(a) { | |
| for (var i = 0; i < a.length; i++) { | |
| var j = i + 1; | |
| while (a[j]) { | |
| if (a[i] == a[j]) { | |
| a.splice(j, 1) | |
| } else { | |
| j++ | |
| } | |
| } | |
| } | |
| }, | |
| analyzeParameters: function() { | |
| var res = {}; | |
| var tmp; | |
| var params = window.location.search.substr(1).split("&"); | |
| for (var i = 0; i < params.length; i++) { | |
| tmp = params[i].split("="); | |
| res[tmp[0]] = tmp[1] | |
| } | |
| return res | |
| }, | |
| interpolate: function(obj, props, duration, callback) { | |
| var before = {}; | |
| for (var i in props) { | |
| before[i] = parseFloat(obj[i]) | |
| } | |
| var tStart = Date.now(); | |
| (function() { | |
| var now = Date.now(); | |
| var prct = Math.min(1, (now - tStart) / duration); | |
| for (var i in props) { | |
| obj[i] = prct * (props[i] - before[i]) + before[i] | |
| } | |
| if (prct < 1) { | |
| requestAnimFrame(arguments.callee) | |
| } else { | |
| if (callback) { | |
| callback.call(obj) | |
| } | |
| } | |
| })() | |
| }, | |
| addZeros: function(n, length) { | |
| var res = n.toString(); | |
| while (res.length < length) res = "0" + res; | |
| return res | |
| }, | |
| formatDate: function(format, date, options) { | |
| date = date || new Date; | |
| options = Util.merge({ | |
| months: ["January", "February", "March", "April", "May", "June", "August", "September", "October", "November", "December"] | |
| }, options); | |
| var res = ""; | |
| var formatNext = false; | |
| for (var i = 0; i < format.length; i++) { | |
| if (format.charAt(i) == "%") { | |
| formatNext = true | |
| } else if (formatNext) { | |
| formatNext = false; | |
| switch (format.charAt(i)) { | |
| case "%": | |
| res += "%"; | |
| break; | |
| case "M": | |
| res += options.months[date.getMonth()]; | |
| break; | |
| case "d": | |
| res += date.getDate(); | |
| break; | |
| case "Y": | |
| res += date.getFullYear(); | |
| break; | |
| case "m": | |
| res += date.getMonth(); | |
| break | |
| } | |
| } else { | |
| res += format.charAt(i) | |
| } | |
| } | |
| return res | |
| }, | |
| keyOf: function(object, element) { | |
| for (var i in object) { | |
| if (object[i] == element) { | |
| return i | |
| } | |
| } | |
| return null | |
| } | |
| }; | |
| var Ajax = { | |
| send: function(url, method, params, success, fail) { | |
| var xhr; | |
| if (window.XMLHttpRequest) { | |
| xhr = new XMLHttpRequest | |
| } else if (window.ActiveXObject) { | |
| try { | |
| xhr = new ActiveXObject("Msxml2.XMLHTTP") | |
| } catch (e) { | |
| xhr = new ActiveXObject("Microsoft.XMLHTTP") | |
| } | |
| } else { | |
| console.log("AJAX not supported by your browser."); | |
| return false | |
| } | |
| success = success || new Function; | |
| fail = fail || new Function; | |
| method = method.toUpperCase(); | |
| params = params || {}; | |
| var paramsArray = []; | |
| for (var i in params) { | |
| paramsArray.push(i + "=" + params[i]) | |
| } | |
| var paramsString = paramsArray.join("&"); | |
| if (method == "GET") { | |
| url += "?" + paramsString | |
| } | |
| xhr.open(method, url, true); | |
| xhr.onreadystatechange = function() { | |
| if (xhr.readyState != 4) return; | |
| if (xhr.status != 200) { | |
| fail(xhr.status, xhr.responseText) | |
| } else { | |
| success(xhr.status, xhr.responseText) | |
| } | |
| }; | |
| if (method == "POST") { | |
| xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); | |
| xhr.send(paramsString) | |
| } else { | |
| xhr.send(null) | |
| } | |
| } | |
| }; | |
| var ArrayManager = { | |
| elements: [], | |
| arrays: [], | |
| remove: function(array, element) { | |
| this.arrays.push(array); | |
| this.elements.push(element) | |
| }, | |
| flush: function() { | |
| var ind; | |
| for (var i in this.arrays) { | |
| ind = this.arrays[i].indexOf(this.elements[i]); | |
| if (ind >= 0) { | |
| this.arrays[i].splice(ind, 1) | |
| } | |
| } | |
| this.arrays = []; | |
| this.elements = [] | |
| }, | |
| init: function() { | |
| this.arrays = []; | |
| this.elements = [] | |
| } | |
| }; | |
| var Encoder = { | |
| buildString: function(tab) { | |
| var s = "", | |
| content; | |
| for (var i in tab) { | |
| content = tab[i].toString(); | |
| content = content.replace(/=/g, " "); | |
| content = content.replace(/\|/g, " "); | |
| s += i + "=" + content + "|" | |
| } | |
| return s | |
| }, | |
| encode: function(hash) { | |
| var str = Encoder.buildString(hash); | |
| var key = ~~Util.rand(1, 255); | |
| var encodedString = Encoder.encodeString(str, key); | |
| return encodeURIComponent(encodedString) | |
| }, | |
| encodeString: function(s, cle) { | |
| var enc = "", | |
| c; | |
| for (var i = 0; i < s.length; i++) { | |
| c = s.charCodeAt(i); | |
| enc += String.fromCharCode((c + cle) % 256) | |
| } | |
| enc = String.fromCharCode(cle) + enc; | |
| return enc | |
| } | |
| }; | |
| var Detect = { | |
| agent: navigator.userAgent.toLowerCase(), | |
| isMobile: function() { | |
| return this.isAndroid() || this.isFirefoxOS() || this.isWindowsMobile() || this.isIOS() | |
| }, | |
| isAndroid: function() { | |
| return this.agent.indexOf("android") >= 0 | |
| }, | |
| isFirefoxOS: function() { | |
| return !this.isAndroid() && this.agent.indexOf("firefox") >= 0 && this.agent.indexOf("mobile") >= 0 | |
| }, | |
| isIOS: function() { | |
| return this.agent.indexOf("ios") >= 0 || this.agent.indexOf("ipod") >= 0 || this.agent.indexOf("ipad") >= 0 || this.agent.indexOf("iphone") >= 0 | |
| }, | |
| isWindowsMobile: function() { | |
| return this.agent.indexOf("windows") >= 0 && this.agent.indexOf("mobile") >= 0 || this.agent.indexOf("iemobile") >= 0 | |
| }, | |
| isTizen: function() { | |
| return this.agent.indexOf("tizen") >= 0 | |
| } | |
| }; | |
| var resourceManager = { | |
| processImages: function(images) { | |
| var canvas = DOM.create("canvas"); | |
| var c = canvas.getContext("2d"); | |
| resources.folder = resources.folder || ""; | |
| R.image = R.image || {}; | |
| if (resources.image) { | |
| for (var i in resources.image) { | |
| R.image[i] = images[resources.folder + resources.image[i]] | |
| } | |
| } | |
| R.pattern = R.pattern || {}; | |
| if (resources.pattern) { | |
| for (var i in resources.pattern) { | |
| R.pattern[i] = c.createPattern(images[resources.folder + resources.pattern[i]], "repeat") | |
| } | |
| } | |
| R.sprite = R.sprite || {}; | |
| if (resources.sprite) { | |
| for (var i in resources.sprite) { | |
| R.sprite[i] = this.createSprite(images[resources.folder + resources.sprite[i].sheet], resources.sprite[i]); | |
| if (resources.sprite[i].pattern) { | |
| R.pattern[i] = c.createPattern(R.sprite[i], "repeat") | |
| } | |
| } | |
| } | |
| R.animation = R.animation || {}; | |
| if (resources.animation) { | |
| for (var i in resources.animation) { | |
| R.animation[i] = []; | |
| for (var j = 0; j < resources.animation[i].length; j++) { | |
| if (R.sprite[resources.animation[i][j]]) { | |
| R.animation[i].push(R.sprite[resources.animation[i][j]]) | |
| } else { | |
| console.log("Error for animation " + i + ': sprite "' + resources.animation[i][j] + '" not found') | |
| } | |
| } | |
| } | |
| } | |
| R.raw = R.raw || {}; | |
| if (resources.raw) { | |
| for (var i in resources.raw) { | |
| R.raw[i] = resources.raw[i] instanceof Function ? resources.raw[i]() : resources.raw[i] | |
| } | |
| } | |
| R.string = R.string || {}; | |
| if (resources.string) { | |
| var lang = this.getLanguage(resources.string); | |
| if (!resources.string[lang]) { | |
| var pp = function(obj) { | |
| if (typeof obj == "string") { | |
| return | |
| } else { | |
| var o = {}; | |
| for (var i in obj) { | |
| if (typeof obj[i] == "string") { | |
| o[i] = "{" + i + "}" | |
| } else { | |
| o[i] = pp(obj[i]) | |
| } | |
| } | |
| return o | |
| } | |
| }; | |
| resources.string[lang] = pp(resources.string.en) | |
| } | |
| for (var i in resources.string[lang]) { | |
| R.string[i] = resources.string[lang][i] | |
| } | |
| for (var i in R.string) { | |
| if (i.charAt(0) == "$") { | |
| try { | |
| DOM.get(i.substring(1)).innerHTML = R.string[i] | |
| } catch (e) { | |
| console.log("DOM element " + i + " does not exist") | |
| } | |
| } | |
| } | |
| } | |
| resources = null; | |
| resourceManager = null | |
| }, | |
| createSprite: function(image, details) { | |
| var canvas = DOM.create("canvas"); | |
| var c = canvas.getContext("2d"); | |
| canvas.width = details.width; | |
| canvas.height = details.height; | |
| c.drawImage(image, details.x, details.y, details.width, details.height, 0, 0, details.width, details.height); | |
| return canvas | |
| }, | |
| getNecessaryImages: function() { | |
| var res = []; | |
| for (var i in resources.image) { | |
| res.push(resources.folder + resources.image[i]) | |
| } | |
| for (var i in resources.pattern) { | |
| res.push(resources.folder + resources.pattern[i]) | |
| } | |
| for (var i in resources.sprite) { | |
| res.push(resources.folder + resources.sprite[i].sheet) | |
| } | |
| Util.arrayUnique(res); | |
| return res | |
| }, | |
| getLanguage: function(languages) { | |
| var lang = null; | |
| var browser_language = null; | |
| var params = Util.analyzeParameters(); | |
| if (params.lang) { | |
| return params.lang | |
| } | |
| if (navigator && navigator.userAgent && (browser_language = navigator.userAgent.match(/android.*\W(\w\w)-(\w\w)\W/i))) { | |
| browser_language = browser_language[1] | |
| } | |
| if (!browser_language && navigator) { | |
| if (navigator.language) { | |
| browser_language = navigator.language | |
| } else if (navigator.browserLanguage) { | |
| browser_language = navigator.browserLanguage | |
| } else if (navigator.systemLanguage) { | |
| browser_language = navigator.systemLanguage | |
| } else if (navigator.userLanguage) { | |
| browser_language = navigator.userLanguage | |
| } | |
| browser_language = browser_language.substr(0, 2) | |
| } | |
| for (var i in languages) { | |
| if (browser_language.indexOf(i) >= 0) { | |
| lang = i; | |
| break | |
| } else if (!lang) { | |
| lang = i | |
| } | |
| } | |
| return lang | |
| } | |
| }; | |
| var cycleManager = { | |
| init: function(cycle, fpsMin) { | |
| this.pause = false; | |
| this.oncycle = cycle; | |
| var hidden, visibilityChange; | |
| if (typeof document.hidden !== "undefined") { | |
| hidden = "hidden"; | |
| visibilityChange = "visibilitychange" | |
| } else if (typeof document.mozHidden !== "undefined") { | |
| hidden = "mozHidden"; | |
| visibilityChange = "mozvisibilitychange" | |
| } else if (typeof document.msHidden !== "undefined") { | |
| hidden = "msHidden"; | |
| visibilityChange = "msvisibilitychange" | |
| } else if (typeof document.webkitHidden !== "undefined") { | |
| hidden = "webkitHidden"; | |
| visibilityChange = "webkitvisibilitychange" | |
| } | |
| this.focus = true; | |
| if (!hidden) { | |
| DOM.on(window, "focus", function() { | |
| cycleManager.focus = true | |
| }); | |
| DOM.on(window, "blur", function() { | |
| cycleManager.focus = false | |
| }) | |
| } else { | |
| DOM.on(document, visibilityChange, function() { | |
| cycleManager.focus = !document[hidden] | |
| }) | |
| } | |
| this.lastCycle = Date.now(); | |
| this.fpsMin = fpsMin || 10; | |
| this.framesUntilNextStat = 0; | |
| this.lastStat = 0; | |
| this.fakeLag = document.location.search.indexOf("fakelag") >= 0; | |
| this.fps = 0; | |
| this.requestId = null; | |
| this.init = null; | |
| this.resume(); | |
| if (window.kik && kik.browser && kik.browser.on) { | |
| kik.browser.on("background", function() { | |
| cycleManager.stop() | |
| }); | |
| kik.browser.on("foreground", function() { | |
| cycleManager.resume() | |
| }) | |
| } | |
| }, | |
| stop: function() { | |
| this.pause = true; | |
| cancelAnimFrame(this.requestId) | |
| }, | |
| resume: function() { | |
| this.pause = false; | |
| cancelAnimFrame(this.requestId); | |
| (function() { | |
| cycleManager.cycle(); | |
| cycleManager.requestId = requestAnimFrame(arguments.callee) | |
| })() | |
| }, | |
| cycle: function() { | |
| var now = Date.now(); | |
| var elapsed = Math.min((now - this.lastCycle) / 1e3, 1 / this.fpsMin); | |
| this.lastCycle = now; | |
| if (!this.pause) { | |
| try { | |
| this.oncycle(elapsed) | |
| } catch (e) { | |
| console.log("Error: " + e + " - ") | |
| } | |
| this.framesUntilNextStat--; | |
| if (this.framesUntilNextStat <= 0) { | |
| this.framesUntilNextStat = 60; | |
| this.fps = ~~(60 * 1e3 / (Date.now() - this.lastStat + elapsed)); | |
| this.lastStat = Date.now() | |
| } | |
| } | |
| } | |
| }; | |
| var resizer = { | |
| init: function(width, height, element, desktop) { | |
| this.enabled = Util.isTouchScreen() || desktop; | |
| this.targetWidth = width; | |
| this.targetHeight = height; | |
| this.element = element; | |
| this.dimensions = { | |
| width: width, | |
| height: height | |
| }; | |
| this.scale = 1; | |
| if (Util.isTouchScreen() || desktop) { | |
| DOM.on(window, "resize orientationchange", function() { | |
| resizer.resize() | |
| }); | |
| this.resize(); | |
| this.toResize = null | |
| } | |
| this.init = null | |
| }, | |
| resize: function() { | |
| if (!this.toResize && this.enabled) { | |
| this.toResize = setTimeout(function() { | |
| if (!resizer.enabled) return; | |
| window.scrollTo(0, 1); | |
| resizer.toResize = null; | |
| resizer.dimensions = DOM.fitScreen(resizer.element, resizer.targetWidth / resizer.targetHeight); | |
| resizer.scale = resizer.dimensions.height / resizer.targetHeight | |
| }, 1e3) | |
| } | |
| } | |
| }; | |
| if (window.cordova) { | |
| document.addEventListener("deviceready", function() { | |
| cordova.exec(null, null, "SplashScreen", "hide", []); | |
| DOM.notify('More HTML5 games available at <a style="color:white" href="' + GameParams.moregamesurl + '">' + GameParams.moregamesurl + "</a>", 3e3) | |
| }, false) | |
| } | |
| if (!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.originalOpen = window.open; | |
| Number.prototype.mod = function(n) { | |
| return (this % n + n) % n | |
| }; | |
| function extend(subClass, superClass) { | |
| if (!subClass.extends || !subClass.extends[superClass]) { | |
| for (var i in superClass.prototype) { | |
| if (!subClass.prototype[i]) { | |
| subClass.prototype[i] = superClass.prototype[i] | |
| } | |
| } | |
| subClass.extends = subClass.extends || {}; | |
| subClass.extends[superClass] = true | |
| } | |
| } | |
| function extendPrototype(superClass, proto) { | |
| var subProto = {}; | |
| for (var i in superClass.prototype) { | |
| subProto[i] = superClass.prototype[i] | |
| } | |
| for (var i in proto) { | |
| subProto[i] = proto[i] | |
| } | |
| return subProto | |
| } | |
| function ResourceLoader(settings) { | |
| this.settings = settings; | |
| this.appCache = window.applicationCache; | |
| this.finished = false; | |
| this.message = null | |
| } | |
| ResourceLoader.prototype.load = function(end, canvas) { | |
| this.endCallback = end; | |
| this.canvasOutput = canvas; | |
| if (!this.appCache || this.appCache.status === this.appCache.UNCACHED) { | |
| this.loadResources() | |
| } else { | |
| this.loadCache() | |
| } | |
| }; | |
| ResourceLoader.prototype.loadCache = function() { | |
| this.message = "Updating..."; | |
| this.appCache.addEventListener("checking", this.checkingCache.bind(this), false); | |
| this.appCache.addEventListener("noupdate", this.loadResources.bind(this), false); | |
| this.appCache.addEventListener("obsolete", this.loadResources.bind(this), false); | |
| this.appCache.addEventListener("error", this.loadResources.bind(this), false); | |
| this.appCache.addEventListener("cached", this.loadResources.bind(this), false); | |
| this.appCache.addEventListener("downloading", this.updatingCache.bind(this), false); | |
| this.appCache.addEventListener("progress", this.updatingCacheProgress.bind(this), false); | |
| this.appCache.addEventListener("updateready", this.updatingCacheReady.bind(this), false); | |
| if (this.appCache.status === this.appCache.IDLE) { | |
| try { | |
| this.appCache.update() | |
| } catch (e) { | |
| this.loadResources() | |
| } | |
| } | |
| }; | |
| ResourceLoader.prototype.checkingCache = function() { | |
| if (!this.finished) { | |
| this.showProgress(this.canvasOutput, 0) | |
| } | |
| }; | |
| ResourceLoader.prototype.updatingCache = function(e) { | |
| if (this.canvasOutput && !this.finished) { | |
| this.showProgress(this.canvasOutput, 0) | |
| } | |
| }; | |
| ResourceLoader.prototype.updatingCacheProgress = function(e) { | |
| if (this.canvasOutput && !this.finished) { | |
| this.showProgress(this.canvasOutput, e.loaded / e.total || 0) | |
| } | |
| }; | |
| ResourceLoader.prototype.updatingCacheReady = function(e) { | |
| if (!this.finished) { | |
| this.finished = true; | |
| try { | |
| this.appCache.swapCache() | |
| } catch (e) {} | |
| location.reload() | |
| } | |
| }; | |
| ResourceLoader.prototype.loadResources = function() { | |
| this.message = "Loading assets. Please wait..."; | |
| this.R = {}; | |
| this.processLanguage(this.R); | |
| var images = this.getNecessaryImages(); | |
| var loader = this; | |
| Util.preload(images, this.resourcesProgress.bind(this), this.resourcesLoaded.bind(this), this.resourcesError.bind(this)) | |
| }; | |
| ResourceLoader.prototype.resourcesError = function(imageSrc) { | |
| alert("Could not load " + imageSrc + ".\nUnable to launch.") | |
| }; | |
| ResourceLoader.prototype.resourcesProgress = function(img, progress) { | |
| if (this.canvasOutput && !this.finished) { | |
| this.showProgress(this.canvasOutput, progress) | |
| } | |
| }; | |
| ResourceLoader.prototype.resourcesLoaded = function(loadedImages) { | |
| if (!this.finished) { | |
| this.finished = true; | |
| this.processImages(loadedImages, this.R); | |
| this.endCallback(this.R) | |
| } | |
| }; | |
| ResourceLoader.prototype.showProgress = function(canvas, progress) { | |
| var ctx = canvas.getContext("2d"); | |
| ctx.fillStyle = "#000"; | |
| ctx.fillRect(0, 0, canvas.width, canvas.height); | |
| ctx.font = "10px Arial"; | |
| ctx.fillStyle = "gray"; | |
| ctx.textAlign = "center"; | |
| ctx.textBaseline = "middle"; | |
| ctx.fillText(this.message, canvas.width / 2, canvas.height / 2 - 20); | |
| ctx.fillRect(0, canvas.height / 2 - 5, canvas.width, 10); | |
| ctx.fillStyle = "white"; | |
| ctx.fillRect(0, canvas.height / 2 - 5, progress * canvas.width, 10); | |
| ctx.fillStyle = "black"; | |
| ctx.textAlign = "right"; | |
| ctx.fillText(~~(progress * 100) + "%", progress * canvas.width - 2, canvas.height / 2) | |
| }; | |
| ResourceLoader.prototype.createSprite = function(image, details) { | |
| var canvas = document.createElement("canvas"); | |
| var c = canvas.getContext("2d"); | |
| canvas.width = details.width; | |
| canvas.height = details.height; | |
| c.drawImage(image, details.x, details.y, details.width, details.height, 0, 0, details.width, details.height); | |
| return canvas | |
| }; | |
| ResourceLoader.prototype.getNecessaryImages = function() { | |
| var res = []; | |
| for (var i in this.settings.image) { | |
| res.push(this.settings.folder + this.settings.image[i]) | |
| } | |
| for (var i in this.settings.pattern) { | |
| res.push(this.settings.folder + this.settings.pattern[i]) | |
| } | |
| for (var i in this.settings.sprite) { | |
| res.push(this.settings.folder + this.settings.sprite[i].sheet) | |
| } | |
| Util.arrayUnique(res); | |
| return res | |
| }; | |
| ResourceLoader.prototype.getLanguage = function(languages) { | |
| var lang = null; | |
| var browser_language = null; | |
| var params = Util.analyzeParameters(); | |
| if (params.lang) { | |
| return params.lang | |
| } | |
| if (navigator && navigator.userAgent && (browser_language = navigator.userAgent.match(/android.*\W(\w\w)-(\w\w)\W/i))) { | |
| browser_language = browser_language[1] | |
| } | |
| if (!browser_language && navigator) { | |
| if (navigator.language) { | |
| browser_language = navigator.language | |
| } else if (navigator.browserLanguage) { | |
| browser_language = navigator.browserLanguage | |
| } else if (navigator.systemLanguage) { | |
| browser_language = navigator.systemLanguage | |
| } else if (navigator.userLanguage) { | |
| browser_language = navigator.userLanguage | |
| } | |
| browser_language = browser_language.substr(0, 2) | |
| } | |
| for (var i in languages) { | |
| if (browser_language.indexOf(i) >= 0) { | |
| lang = i; | |
| break | |
| } else if (!lang) { | |
| lang = i | |
| } | |
| } | |
| return lang | |
| }; | |
| ResourceLoader.prototype.processImages = function(images, R) { | |
| var canvas = DOM.create("canvas"); | |
| var c = canvas.getContext("2d"); | |
| this.settings.folder = this.settings.folder || ""; | |
| R.image = R.image || {}; | |
| if (this.settings.image) { | |
| for (var i in this.settings.image) { | |
| R.image[i] = images[this.settings.folder + this.settings.image[i]] | |
| } | |
| } | |
| R.pattern = R.pattern || {}; | |
| if (this.settings.pattern) { | |
| for (var i in this.settings.pattern) { | |
| R.pattern[i] = c.createPattern(images[this.settings.folder + this.settings.pattern[i]], "repeat"); | |
| R.pattern[i].width = images[this.settings.folder + this.settings.pattern[i]].width; | |
| R.pattern[i].height = images[this.settings.folder + this.settings.pattern[i]].height | |
| } | |
| } | |
| R.sprite = R.sprite || {}; | |
| if (this.settings.sprite) { | |
| for (var i in this.settings.sprite) { | |
| R.sprite[i] = this.createSprite(images[this.settings.folder + this.settings.sprite[i].sheet], this.settings.sprite[i]); | |
| if (this.settings.sprite[i].pattern) { | |
| R.pattern[i] = c.createPattern(R.sprite[i], "repeat"); | |
| R.pattern[i].width = R.sprite[i].width; | |
| R.pattern[i].height = R.sprite[i].height | |
| } | |
| } | |
| } | |
| R.animation = R.animation || {}; | |
| if (this.settings.animation) { | |
| for (var i in this.settings.animation) { | |
| R.animation[i] = []; | |
| for (var j = 0; j < this.settings.animation[i].length; j++) { | |
| if (R.sprite[this.settings.animation[i][j]]) { | |
| R.animation[i].push(R.sprite[this.settings.animation[i][j]]) | |
| } else { | |
| console.log("Error for animation " + i + ': sprite "' + this.settings.animation[i][j] + '" not found') | |
| } | |
| } | |
| } | |
| } | |
| R.raw = R.raw || {}; | |
| if (this.settings.raw) { | |
| for (var i in this.settings.raw) { | |
| R.raw[i] = this.settings.raw[i] instanceof Function ? this.settings.raw[i]() : this.settings.raw[i] | |
| } | |
| } | |
| }; | |
| ResourceLoader.prototype.processLanguage = function(R) { | |
| R.string = R.string || {}; | |
| if (this.settings.string) { | |
| this.language = this.getLanguage(this.settings.string); | |
| if (!this.settings.string[this.language]) { | |
| var pp = function(obj) { | |
| if (typeof obj == "string") { | |
| return | |
| } else { | |
| var o = {}; | |
| for (var i in obj) { | |
| if (typeof obj[i] == "string") { | |
| o[i] = "{" + i + "}" | |
| } else { | |
| o[i] = pp(obj[i]) | |
| } | |
| } | |
| return o | |
| } | |
| }; | |
| this.settings.string[this.language] = pp(this.settings.string.en) | |
| } | |
| for (var i in this.settings.string[this.language]) { | |
| R.string[i] = this.settings.string[this.language][i] | |
| } | |
| for (var i in R.string) { | |
| if (i.charAt(0) == "$") { | |
| try { | |
| DOM.get(i.substring(1)).innerHTML = R.string[i] | |
| } catch (e) { | |
| console.log("DOM element " + i + " does not exist") | |
| } | |
| } | |
| } | |
| } | |
| }; | |
| function Resizer(options) { | |
| this.delay = options.delay || 0; | |
| this.element = options.element || null; | |
| this.baseWidth = options.baseWidth; | |
| this.baseHeight = options.baseHeight; | |
| this.onResize = options.onResize; | |
| this.enabled = true; | |
| this.resizeTimeout = null | |
| } | |
| Resizer.prototype = { | |
| needsResize: function(maxWidth, maxHeight) { | |
| clearTimeout(this.resizeTimeout); | |
| if (this.enabled) { | |
| this.maxWidth = maxWidth; | |
| this.maxHeight = maxHeight; | |
| this.resizeTimeout = setTimeout(this.resize.bind(this), this.delay) | |
| } | |
| }, | |
| resize: function() { | |
| this.resizeTimeout = null; | |
| var dimensions = this.getFittingDimensions(this.maxWidth, this.maxHeight); | |
| this.element.style.width = dimensions.width + "px"; | |
| this.element.style.height = dimensions.height + "px"; | |
| if (this.onResize) { | |
| this.onResize.call(this) | |
| } | |
| }, | |
| scaleX: function() { | |
| return parseInt(this.element.style.width) / this.baseWidth || 1 | |
| }, | |
| scaleY: function() { | |
| return parseInt(this.element.style.height) / this.baseHeight || 1 | |
| }, | |
| getFittingDimensions: function(maxWidth, maxHeight) { | |
| var availableRatio = maxWidth / maxHeight; | |
| var baseRatio = this.baseWidth / this.baseHeight; | |
| var ratioDifference = Math.abs(availableRatio - baseRatio); | |
| var width, height; | |
| if (ratioDifference <= .1) { | |
| width = maxWidth; | |
| height = maxHeight | |
| } else if (availableRatio <= baseRatio) { | |
| width = maxWidth; | |
| height = width / baseRatio | |
| } else { | |
| height = maxHeight; | |
| width = height * baseRatio | |
| } | |
| return { | |
| width: width, | |
| height: height | |
| } | |
| } | |
| }; | |
| (function() { | |
| var cache = {}; | |
| var ctx = null, | |
| usingWebAudio = true, | |
| noAudio = false; | |
| try { | |
| if (typeof AudioContext !== "undefined") { | |
| ctx = new AudioContext | |
| } else if (typeof webkitAudioContext !== "undefined") { | |
| ctx = new webkitAudioContext | |
| } else { | |
| usingWebAudio = false | |
| } | |
| } catch (e) { | |
| usingWebAudio = false | |
| } | |
| if (!usingWebAudio) { | |
| if (typeof Audio !== "undefined") { | |
| try { | |
| new Audio | |
| } catch (e) { | |
| noAudio = true | |
| } | |
| } else { | |
| noAudio = true | |
| } | |
| } | |
| if (usingWebAudio) { | |
| var masterGain = typeof ctx.createGain === "undefined" ? ctx.createGainNode() : ctx.createGain(); | |
| masterGain.gain.value = 1; | |
| masterGain.connect(ctx.destination) | |
| } | |
| var HowlerGlobal = function() { | |
| this._volume = 1; | |
| this._muted = false; | |
| this.usingWebAudio = usingWebAudio; | |
| this.noAudio = noAudio; | |
| this._howls = [] | |
| }; | |
| HowlerGlobal.prototype = { | |
| volume: function(vol) { | |
| var self = this; | |
| vol = parseFloat(vol); | |
| if (vol >= 0 && vol <= 1) { | |
| self._volume = vol; | |
| if (usingWebAudio) { | |
| masterGain.gain.value = vol | |
| } | |
| for (var key in self._howls) { | |
| if (self._howls.hasOwnProperty(key) && self._howls[key]._webAudio === false) { | |
| for (var i = 0; i < self._howls[key]._audioNode.length; i++) { | |
| self._howls[key]._audioNode[i].volume = self._howls[key]._volume * self._volume | |
| } | |
| } | |
| } | |
| return self | |
| } | |
| return usingWebAudio ? masterGain.gain.value : self._volume | |
| }, | |
| mute: function() { | |
| this._setMuted(true); | |
| return this | |
| }, | |
| unmute: function() { | |
| this._setMuted(false); | |
| return this | |
| }, | |
| _setMuted: function(muted) { | |
| var self = this; | |
| self._muted = muted; | |
| if (usingWebAudio) { | |
| masterGain.gain.value = muted ? 0 : self._volume | |
| } | |
| for (var key in self._howls) { | |
| if (self._howls.hasOwnProperty(key) && self._howls[key]._webAudio === false) { | |
| for (var i = 0; i < self._howls[key]._audioNode.length; i++) { | |
| self._howls[key]._audioNode[i].muted = muted | |
| } | |
| } | |
| } | |
| } | |
| }; | |
| var Howler = new HowlerGlobal; | |
| var audioTest = null; | |
| if (!noAudio) { | |
| audioTest = new Audio; | |
| var codecs = { | |
| mp3: !!audioTest.canPlayType("audio/mpeg;").replace(/^no$/, ""), | |
| opus: !!audioTest.canPlayType('audio/ogg; codecs="opus"').replace(/^no$/, ""), | |
| ogg: !!audioTest.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/, ""), | |
| wav: !!audioTest.canPlayType('audio/wav; codecs="1"').replace(/^no$/, ""), | |
| m4a: !!(audioTest.canPlayType("audio/x-m4a;") || audioTest.canPlayType("audio/aac;")).replace(/^no$/, ""), | |
| mp4: !!(audioTest.canPlayType("audio/x-mp4;") || audioTest.canPlayType("audio/aac;")).replace(/^no$/, ""), | |
| weba: !!audioTest.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/, "") | |
| } | |
| } | |
| var Howl = function(o) { | |
| var self = this; | |
| self._autoplay = o.autoplay || false; | |
| self._buffer = o.buffer || false; | |
| self._duration = o.duration || 0; | |
| self._format = o.format || null; | |
| self._loop = o.loop || false; | |
| self._loaded = false; | |
| self._sprite = o.sprite || {}; | |
| self._src = o.src || ""; | |
| self._pos3d = o.pos3d || [0, 0, -.5]; | |
| self._volume = o.volume !== undefined ? o.volume : 1; | |
| self._urls = o.urls || []; | |
| self._rate = o.rate || 1; | |
| self._model = o.model || null; | |
| self._onload = [o.onload || function() {}]; | |
| self._onloaderror = [o.onloaderror || function() {}]; | |
| self._onend = [o.onend || function() {}]; | |
| self._onpause = [o.onpause || function() {}]; | |
| self._onplay = [o.onplay || function() {}]; | |
| self._onendTimer = []; | |
| self._webAudio = usingWebAudio && !self._buffer; | |
| self._audioNode = []; | |
| if (self._webAudio) { | |
| self._setupAudioNode() | |
| } | |
| Howler._howls.push(self); | |
| self.load() | |
| }; | |
| Howl.prototype = { | |
| load: function() { | |
| var self = this, | |
| url = null; | |
| if (noAudio) { | |
| self.on("loaderror"); | |
| return | |
| } | |
| for (var i = 0; i < self._urls.length; i++) { | |
| var ext, urlItem; | |
| if (self._format) { | |
| ext = self._format | |
| } else { | |
| urlItem = self._urls[i].toLowerCase().split("?")[0]; | |
| ext = urlItem.match(/.+\.([^?]+)(\?|$)/); | |
| ext = ext && ext.length >= 2 ? ext : urlItem.match(/data\:audio\/([^?]+);/); | |
| if (ext) { | |
| ext = ext[1] | |
| } else { | |
| self.on("loaderror"); | |
| return | |
| } | |
| } | |
| if (codecs[ext]) { | |
| url = self._urls[i]; | |
| break | |
| } | |
| } | |
| if (!url) { | |
| self.on("loaderror"); | |
| return | |
| } | |
| self._src = url; | |
| if (self._webAudio) { | |
| loadBuffer(self, url) | |
| } else { | |
| var newNode = new Audio; | |
| newNode.addEventListener("error", function() { | |
| if (newNode.error && newNode.error.code === 4) { | |
| HowlerGlobal.noAudio = true | |
| } | |
| self.on("loaderror", { | |
| type: newNode.error ? newNode.error.code : 0 | |
| }) | |
| }, false); | |
| self._audioNode.push(newNode); | |
| newNode.src = url; | |
| newNode._pos = 0; | |
| newNode.preload = "auto"; | |
| newNode.volume = Howler._muted ? 0 : self._volume * Howler.volume(); | |
| cache[url] = self; | |
| var listener = function() { | |
| self._duration = Math.ceil(newNode.duration * 10) / 10; | |
| if (Object.getOwnPropertyNames(self._sprite).length === 0) { | |
| self._sprite = { | |
| _default: [0, self._duration * 1e3] | |
| } | |
| } | |
| if (!self._loaded) { | |
| self._loaded = true; | |
| self.on("load") | |
| } | |
| if (self._autoplay) { | |
| self.play() | |
| } | |
| newNode.removeEventListener("canplaythrough", listener, false) | |
| }; | |
| newNode.addEventListener("canplaythrough", listener, false); | |
| newNode.load() | |
| } | |
| return self | |
| }, | |
| urls: function(urls) { | |
| var self = this; | |
| if (urls) { | |
| self.stop(); | |
| self._urls = typeof urls === "string" ? [urls] : urls; | |
| self._loaded = false; | |
| self.load(); | |
| return self | |
| } else { | |
| return self._urls | |
| } | |
| }, | |
| play: function(sprite, callback) { | |
| var self = this; | |
| if (typeof sprite === "function") { | |
| callback = sprite | |
| } | |
| if (!sprite || typeof sprite === "function") { | |
| sprite = "_default" | |
| } | |
| if (!self._loaded) { | |
| self.on("load", function() { | |
| self.play(sprite, callback) | |
| }); | |
| return self | |
| } | |
| if (!self._sprite[sprite]) { | |
| if (typeof callback === "function") callback(); | |
| return self | |
| } | |
| self._inactiveNode(function(node) { | |
| node._sprite = sprite; | |
| var pos = node._pos > 0 ? node._pos : self._sprite[sprite][0] / 1e3, | |
| duration = self._sprite[sprite][1] / 1e3 - node._pos; | |
| var loop = !!(self._loop || self._sprite[sprite][2]); | |
| var soundId = typeof callback === "string" ? callback : Math.round(Date.now() * Math.random()) + "", | |
| timerId; | |
| (function() { | |
| var data = { | |
| id: soundId, | |
| sprite: sprite, | |
| loop: loop | |
| }; | |
| timerId = setTimeout(function() { | |
| if (!self._webAudio && loop) { | |
| self.stop(data.id).play(sprite, data.id) | |
| } | |
| if (self._webAudio && !loop) { | |
| self._nodeById(data.id).paused = true; | |
| self._nodeById(data.id)._pos = 0 | |
| } | |
| if (!self._webAudio && !loop) { | |
| self.stop(data.id) | |
| } | |
| self.on("end", soundId) | |
| }, duration * 1e3); | |
| self._onendTimer.push({ | |
| timer: timerId, | |
| id: data.id | |
| }) | |
| })(); | |
| if (self._webAudio) { | |
| var loopStart = self._sprite[sprite][0] / 1e3, | |
| loopEnd = self._sprite[sprite][1] / 1e3; | |
| node.id = soundId; | |
| node.paused = false; | |
| refreshBuffer(self, [loop, loopStart, loopEnd], soundId); | |
| self._playStart = ctx.currentTime; | |
| node.gain.value = self._volume; | |
| if (typeof node.bufferSource.start === "undefined") { | |
| node.bufferSource.noteGrainOn(0, pos, duration) | |
| } else { | |
| node.bufferSource.start(0, pos, duration) | |
| } | |
| } else { | |
| if (node.readyState === 4 || !node.readyState && navigator.isCocoonJS) { | |
| node.readyState = 4; | |
| node.id = soundId; | |
| node.currentTime = pos; | |
| node.muted = Howler._muted || node.muted; | |
| node.volume = self._volume * Howler.volume(); | |
| setTimeout(function() { | |
| node.play() | |
| }, 0) | |
| } else { | |
| self._clearEndTimer(soundId); | |
| (function() { | |
| var sound = self, | |
| playSprite = sprite, | |
| fn = callback, | |
| newNode = node; | |
| var listener = function() { | |
| sound.play(playSprite, fn); | |
| newNode.removeEventListener("canplaythrough", listener, false) | |
| }; | |
| newNode.addEventListener("canplaythrough", listener, false) | |
| })(); | |
| return self | |
| } | |
| } | |
| self.on("play"); | |
| if (typeof callback === "function") callback(soundId); | |
| return self | |
| }); | |
| return self | |
| }, | |
| pause: function(id) { | |
| var self = this; | |
| if (!self._loaded) { | |
| self.on("play", function() { | |
| self.pause(id) | |
| }); | |
| return self | |
| } | |
| self._clearEndTimer(id); | |
| var activeNode = id ? self._nodeById(id) : self._activeNode(); | |
| if (activeNode) { | |
| activeNode._pos = self.pos(null, id); | |
| if (self._webAudio) { | |
| if (!activeNode.bufferSource || activeNode.paused) { | |
| return self | |
| } | |
| activeNode.paused = true; | |
| if (typeof activeNode.bufferSource.stop === "undefined") { | |
| activeNode.bufferSource.noteOff(0) | |
| } else { | |
| activeNode.bufferSource.stop(0) | |
| } | |
| } else { | |
| activeNode.pause() | |
| } | |
| } | |
| self.on("pause"); | |
| return self | |
| }, | |
| stop: function(id) { | |
| var self = this; | |
| if (!self._loaded) { | |
| self.on("play", function() { | |
| self.stop(id) | |
| }); | |
| return self | |
| } | |
| self._clearEndTimer(id); | |
| var activeNode = id ? self._nodeById(id) : self._activeNode(); | |
| if (activeNode) { | |
| activeNode._pos = 0; | |
| if (self._webAudio) { | |
| if (!activeNode.bufferSource || activeNode.paused) { | |
| return self | |
| } | |
| activeNode.paused = true; | |
| if (typeof activeNode.bufferSource.stop === "undefined") { | |
| activeNode.bufferSource.noteOff(0) | |
| } else { | |
| activeNode.bufferSource.stop(0) | |
| } | |
| } else if (!isNaN(activeNode.duration)) { | |
| activeNode.pause(); | |
| activeNode.currentTime = 0 | |
| } | |
| } | |
| return self | |
| }, | |
| mute: function(id) { | |
| var self = this; | |
| if (!self._loaded) { | |
| self.on("play", function() { | |
| self.mute(id) | |
| }); | |
| return self | |
| } | |
| var activeNode = id ? self._nodeById(id) : self._activeNode(); | |
| if (activeNode) { | |
| if (self._webAudio) { | |
| activeNode.gain.value = 0 | |
| } else { | |
| activeNode.muted = true | |
| } | |
| } | |
| return self | |
| }, | |
| unmute: function(id) { | |
| var self = this; | |
| if (!self._loaded) { | |
| self.on("play", function() { | |
| self.unmute(id) | |
| }); | |
| return self | |
| } | |
| var activeNode = id ? self._nodeById(id) : self._activeNode(); | |
| if (activeNode) { | |
| if (self._webAudio) { | |
| activeNode.gain.value = self._volume | |
| } else { | |
| activeNode.muted = false | |
| } | |
| } | |
| return self | |
| }, | |
| volume: function(vol, id) { | |
| var self = this; | |
| vol = parseFloat(vol); | |
| if (vol >= 0 && vol <= 1) { | |
| self._volume = vol; | |
| if (!self._loaded) { | |
| self.on("play", function() { | |
| self.volume(vol, id) | |
| }); | |
| return self | |
| } | |
| var activeNode = id ? self._nodeById(id) : self._activeNode(); | |
| if (activeNode) { | |
| if (self._webAudio) { | |
| activeNode.gain.value = vol | |
| } else { | |
| activeNode.volume = vol * Howler.volume() | |
| } | |
| } | |
| return self | |
| } else { | |
| return self._volume | |
| } | |
| }, | |
| loop: function(loop) { | |
| var self = this; | |
| if (typeof loop === "boolean") { | |
| self._loop = loop; | |
| return self | |
| } else { | |
| return self._loop | |
| } | |
| }, | |
| sprite: function(sprite) { | |
| var self = this; | |
| if (typeof sprite === "object") { | |
| self._sprite = sprite; | |
| return self | |
| } else { | |
| return self._sprite | |
| } | |
| }, | |
| pos: function(pos, id) { | |
| var self = this; | |
| if (!self._loaded) { | |
| self.on("load", function() { | |
| self.pos(pos) | |
| }); | |
| return typeof pos === "number" ? self : self._pos || 0 | |
| } | |
| pos = parseFloat(pos); | |
| var activeNode = id ? self._nodeById(id) : self._activeNode(); | |
| if (activeNode) { | |
| if (pos >= 0) { | |
| self.pause(id); | |
| activeNode._pos = pos; | |
| self.play(activeNode._sprite, id); | |
| return self | |
| } else { | |
| return self._webAudio ? activeNode._pos + (ctx.currentTime - self._playStart) : activeNode.currentTime | |
| } | |
| } else if (pos >= 0) { | |
| return self | |
| } else { | |
| for (var i = 0; i < self._audioNode.length; i++) { | |
| if (self._audioNode[i].paused && self._audioNode[i].readyState === 4) { | |
| return self._webAudio ? self._audioNode[i]._pos : self._audioNode[i].currentTime | |
| } | |
| } | |
| } | |
| }, | |
| pos3d: function(x, y, z, id) { | |
| var self = this; | |
| y = typeof y === "undefined" || !y ? 0 : y; | |
| z = typeof z === "undefined" || !z ? -.5 : z; | |
| if (!self._loaded) { | |
| self.on("play", function() { | |
| self.pos3d(x, y, z, id) | |
| }); | |
| return self | |
| } | |
| if (x >= 0 || x < 0) { | |
| if (self._webAudio) { | |
| var activeNode = id ? self._nodeById(id) : self._activeNode(); | |
| if (activeNode) { | |
| self._pos3d = [x, y, z]; | |
| activeNode.panner.setPosition(x, y, z); | |
| activeNode.panner.panningModel = self._model || "HRTF" | |
| } | |
| } | |
| } else { | |
| return self._pos3d | |
| } | |
| return self | |
| }, | |
| fade: function(from, to, len, callback, id) { | |
| var self = this, | |
| diff = Math.abs(from - to), | |
| dir = from > to ? "down" : "up", | |
| steps = diff / .01, | |
| stepTime = len / steps; | |
| if (!self._loaded) { | |
| self.on("load", function() { | |
| self.fade(from, to, len, callback, id) | |
| }); | |
| return self | |
| } | |
| self.volume(from, id); | |
| for (var i = 1; i <= steps; i++) { | |
| (function() { | |
| var change = self._volume + (dir === "up" ? .01 : -.01) * i, | |
| vol = Math.round(1e3 * change) / 1e3, | |
| toVol = to; | |
| setTimeout(function() { | |
| self.volume(vol, id); | |
| if (vol === toVol) { | |
| if (callback) callback() | |
| } | |
| }, stepTime * i) | |
| })() | |
| } | |
| }, | |
| fadeIn: function(to, len, callback) { | |
| return this.volume(0).play().fade(0, to, len, callback) | |
| }, | |
| fadeOut: function(to, len, callback, id) { | |
| var self = this; | |
| return self.fade(self._volume, to, len, function() { | |
| if (callback) callback(); | |
| self.pause(id); | |
| self.on("end") | |
| }, id) | |
| }, | |
| _nodeById: function(id) { | |
| var self = this, | |
| node = self._audioNode[0]; | |
| for (var i = 0; i < self._audioNode.length; i++) { | |
| if (self._audioNode[i].id === id) { | |
| node = self._audioNode[i]; | |
| break | |
| } | |
| } | |
| return node | |
| }, | |
| _activeNode: function() { | |
| var self = this, | |
| node = null; | |
| for (var i = 0; i < self._audioNode.length; i++) { | |
| if (!self._audioNode[i].paused) { | |
| node = self._audioNode[i]; | |
| break | |
| } | |
| } | |
| self._drainPool(); | |
| return node | |
| }, | |
| _inactiveNode: function(callback) { | |
| var self = this, | |
| node = null; | |
| for (var i = 0; i < self._audioNode.length; i++) { | |
| if (self._audioNode[i].paused && self._audioNode[i].readyState === 4) { | |
| callback(self._audioNode[i]); | |
| node = true; | |
| break | |
| } | |
| } | |
| self._drainPool(); | |
| if (node) { | |
| return | |
| } | |
| var newNode; | |
| if (self._webAudio) { | |
| newNode = self._setupAudioNode(); | |
| callback(newNode) | |
| } else { | |
| self.load(); | |
| newNode = self._audioNode[self._audioNode.length - 1]; | |
| newNode.addEventListener(navigator.isCocoonJS ? "canplaythrough" : "loadedmetadata", function() { | |
| callback(newNode) | |
| }) | |
| } | |
| }, | |
| _drainPool: function() { | |
| var self = this, | |
| inactive = 0, | |
| i; | |
| for (i = 0; i < self._audioNode.length; i++) { | |
| if (self._audioNode[i].paused) { | |
| inactive++ | |
| } | |
| } | |
| for (i = self._audioNode.length - 1; i >= 0; i--) { | |
| if (inactive <= 5) { | |
| break | |
| } | |
| if (self._audioNode[i].paused) { | |
| if (self._webAudio) { | |
| self._audioNode[i].disconnect(0) | |
| } | |
| inactive--; | |
| self._audioNode.splice(i, 1) | |
| } | |
| } | |
| }, | |
| _clearEndTimer: function(soundId) { | |
| var self = this, | |
| index = 0; | |
| for (var i = 0; i < self._onendTimer.length; i++) { | |
| if (self._onendTimer[i].id === soundId) { | |
| index = i; | |
| break | |
| } | |
| } | |
| var timer = self._onendTimer[index]; | |
| if (timer) { | |
| clearTimeout(timer.timer); | |
| self._onendTimer.splice(index, 1) | |
| } | |
| }, | |
| _setupAudioNode: function() { | |
| var self = this, | |
| node = self._audioNode, | |
| index = self._audioNode.length; | |
| node[index] = typeof ctx.createGain === "undefined" ? ctx.createGainNode() : ctx.createGain(); | |
| node[index].gain.value = self._volume; | |
| node[index].paused = true; | |
| node[index]._pos = 0; | |
| node[index].readyState = 4; | |
| node[index].connect(masterGain); | |
| node[index].panner = ctx.createPanner(); | |
| node[index].panner.panningModel = self._model || "equalpower"; | |
| node[index].panner.setPosition(self._pos3d[0], self._pos3d[1], self._pos3d[2]); | |
| node[index].panner.connect(node[index]); | |
| return node[index] | |
| }, | |
| on: function(event, fn) { | |
| var self = this, | |
| events = self["_on" + event]; | |
| if (typeof fn === "function") { | |
| events.push(fn) | |
| } else { | |
| for (var i = 0; i < events.length; i++) { | |
| if (fn) { | |
| events[i].call(self, fn) | |
| } else { | |
| events[i].call(self) | |
| } | |
| } | |
| } | |
| return self | |
| }, | |
| off: function(event, fn) { | |
| var self = this, | |
| events = self["_on" + event], | |
| fnString = fn.toString(); | |
| for (var i = 0; i < events.length; i++) { | |
| if (fnString === events[i].toString()) { | |
| events.splice(i, 1); | |
| break | |
| } | |
| } | |
| return self | |
| }, | |
| unload: function() { | |
| var self = this; | |
| var nodes = self._audioNode; | |
| for (var i = 0; i < self._audioNode.length; i++) { | |
| if (!nodes[i].paused) { | |
| self.stop(nodes[i].id) | |
| } | |
| if (!self._webAudio) { | |
| nodes[i].src = "" | |
| } else { | |
| nodes[i].disconnect(0) | |
| } | |
| } | |
| for (i = 0; i < self._onendTimer.length; i++) { | |
| clearTimeout(self._onendTimer[i].timer) | |
| } | |
| var index = Howler._howls.indexOf(self); | |
| if (index !== null && index >= 0) { | |
| Howler._howls.splice(index, 1) | |
| } | |
| delete cache[self._src]; | |
| self = null | |
| } | |
| }; | |
| if (usingWebAudio) { | |
| var loadBuffer = function(obj, url) { | |
| if (url in cache) { | |
| obj._duration = cache[url].duration; | |
| loadSound(obj) | |
| } else { | |
| var xhr = new XMLHttpRequest; | |
| xhr.open("GET", url, true); | |
| xhr.responseType = "arraybuffer"; | |
| xhr.onload = function() { | |
| ctx.decodeAudioData(xhr.response, function(buffer) { | |
| if (buffer) { | |
| cache[url] = buffer; | |
| loadSound(obj, buffer) | |
| } | |
| }, function(err) { | |
| obj.on("loaderror") | |
| }) | |
| }; | |
| xhr.onerror = function() { | |
| if (obj._webAudio) { | |
| obj._buffer = true; | |
| obj._webAudio = false; | |
| obj._audioNode = []; | |
| delete obj._gainNode; | |
| obj.load() | |
| } | |
| }; | |
| try { | |
| xhr.send() | |
| } catch (e) { | |
| xhr.onerror() | |
| } | |
| } | |
| }; | |
| var loadSound = function(obj, buffer) { | |
| obj._duration = buffer ? buffer.duration : obj._duration; | |
| if (Object.getOwnPropertyNames(obj._sprite).length === 0) { | |
| obj._sprite = { | |
| _default: [0, obj._duration * 1e3] | |
| } | |
| } | |
| if (!obj._loaded) { | |
| obj._loaded = true; | |
| obj.on("load") | |
| } | |
| if (obj._autoplay) { | |
| obj.play() | |
| } | |
| }; | |
| var refreshBuffer = function(obj, loop, id) { | |
| var node = obj._nodeById(id); | |
| node.bufferSource = ctx.createBufferSource(); | |
| node.bufferSource.buffer = cache[obj._src]; | |
| node.bufferSource.connect(node.panner); | |
| node.bufferSource.loop = loop[0]; | |
| if (loop[0]) { | |
| node.bufferSource.loopStart = loop[1]; | |
| node.bufferSource.loopEnd = loop[1] + loop[2] | |
| } | |
| node.bufferSource.playbackRate.value = obj._rate | |
| } | |
| } | |
| if (typeof define === "function" && define.amd) { | |
| define(function() { | |
| return { | |
| Howler: Howler, | |
| Howl: Howl | |
| } | |
| }) | |
| } | |
| if (typeof exports !== "undefined") { | |
| exports.Howler = Howler; | |
| exports.Howl = Howl | |
| } | |
| if (typeof window !== "undefined") { | |
| window.Howler = Howler; | |
| window.Howl = Howl | |
| } | |
| })(); | |
| (function(g, m, a, p, i) { | |
| g["GameMixAPIName"] = i; | |
| g[i] = g[i] || function(f) { | |
| g[i].q = g[i].q || []; | |
| g[i].q.push(f) | |
| }; | |
| g[i]({ | |
| apiDomain: p | |
| }); | |
| var s = m.createElement(a), | |
| d = m.getElementsByTagName(a)[0]; | |
| s.type = "text/javascript"; | |
| s.async = true; | |
| s.src = p + "/v1/gm.js"; | |
| d.parentNode.insertBefore(s, d) | |
| })(window, document, "script", "http://gmapi.gamemix.com", "gmapi"); | |
| gmapi("donttap"); | |
| window.googletag = window.googletag || {}; | |
| googletag.cmd = googletag.cmd || []; | |
| (function() { | |
| var gads = document.createElement("script"); | |
| gads.async = true; | |
| gads.type = "text/javascript"; | |
| var useSSL = "https:" == document.location.protocol; | |
| gads.src = (useSSL ? "https:" : "http:") + "//www.googletagservices.com/tag/js/gpt.js"; | |
| var node = document.getElementsByTagName("script")[0]; | |
| node.parentNode.insertBefore(gads, node) | |
| })(); | |
| function Area(x, y, w, h, settings) { | |
| this.x = x; | |
| this.y = y; | |
| this.width = w; | |
| this.height = h; | |
| this.enabled = true; | |
| settings = settings || {}; | |
| this.onactionperformed = settings.actionPerformed; | |
| this.onactionstart = settings.actionStart; | |
| this.onactioncancel = settings.actionCancel | |
| } | |
| Area.prototype = { | |
| contains: function(x, y) { | |
| return x >= this.x && y >= this.y && x <= this.x + this.width && y <= this.y + this.height | |
| }, | |
| actionPerformed: function(x, y) { | |
| if (this.onactionperformed) { | |
| this.onactionperformed(x, y) | |
| } | |
| }, | |
| actionStart: function(x, y) { | |
| if (this.onactionstart) { | |
| this.onactionstart(x, y) | |
| } | |
| }, | |
| actionCancel: function(x, y) { | |
| if (this.onactioncancel) { | |
| this.onactioncancel(x, y) | |
| } | |
| } | |
| }; | |
| function Screen(game) { | |
| this.game = game; | |
| this.areas = []; | |
| this.currentActionArea = null; | |
| this.view = null | |
| } | |
| Screen.prototype = { | |
| cycle: function(elapsed) {}, | |
| touchStart: function(x, y) { | |
| for (var i in this.areas) { | |
| if (this.areas[i].enabled && this.areas[i].contains(x, y)) { | |
| this.currentActionArea = this.areas[i]; | |
| this.currentActionArea.actionStart(x, y); | |
| break | |
| } | |
| } | |
| }, | |
| touchMove: function(x, y) { | |
| if (this.currentActionArea && !this.currentActionArea.contains(x, y)) { | |
| this.currentActionArea.actionCancel(x, y); | |
| this.currentActionArea = null | |
| } | |
| }, | |
| touchEnd: function(x, y) { | |
| if (this.currentActionArea && this.currentActionArea.contains(x, y)) { | |
| this.currentActionArea.actionPerformed(x, y) | |
| } | |
| this.currentActionArea = null | |
| }, | |
| create: function() {}, | |
| destroy: function() {}, | |
| addArea: function(area) { | |
| this.areas.push(area) | |
| }, | |
| areaContains: function(x, y) { | |
| for (var i in this.areas) { | |
| if (this.areas[i].enabled && this.areas[i].contains(x, y)) { | |
| return true | |
| } | |
| } | |
| return false | |
| }, | |
| getId: function() { | |
| return undefined | |
| } | |
| }; | |
| function DisplayableObject() { | |
| this.parent = null; | |
| this.x = this.y = 0; | |
| this.rotation = 0; | |
| this.scaleX = this.scaleY = 1; | |
| this.alpha = 1; | |
| this.visible = true | |
| } | |
| DisplayableObject.prototype = { | |
| applyTransforms: function(c) { | |
| if (this.x != 0 || this.y != 0) c.translate(this.x, this.y); | |
| if (this.scaleX != 1 || this.scaleY != 1) c.scale(this.scaleX, this.scaleY); | |
| if (this.rotation != 0) c.rotate(this.rotation); | |
| if (this.alpha != 1) c.globalAlpha *= this.alpha | |
| }, | |
| doRender: function(c) { | |
| if (this.visible && this.alpha > .01 && this.scaleX != 0 && this.scaleY != 0) { | |
| c.save(); | |
| this.applyTransforms(c); | |
| this.render(c); | |
| c.restore() | |
| } | |
| }, | |
| render: function(c) { | |
| throw new Error("Rendering undefined") | |
| }, | |
| remove: function() { | |
| if (this.parent) { | |
| this.parent.removeChild(this) | |
| } | |
| }, | |
| leaves: function() { | |
| return 1 | |
| } | |
| }; | |
| function DisplayableContainer() { | |
| DisplayableObject.call(this); | |
| this.children = [] | |
| } | |
| DisplayableContainer.prototype = extendPrototype(DisplayableObject, { | |
| render: function(c) { | |
| var i = -1; | |
| while (this.children[++i]) { | |
| this.children[i].doRender(c) | |
| } | |
| }, | |
| addChild: function(child) { | |
| if (child.parent) { | |
| child.parent.removeChild(child) | |
| } | |
| this.children.push(child); | |
| child.parent = this; | |
| child.parentIndex = this.children.length - 1 | |
| }, | |
| removeChild: function(child) { | |
| if (!isNaN(child.parentIndex)) { | |
| this.children.splice(child.parentIndex, 1); | |
| for (var i = child.parentIndex; i < this.children.length; i++) { | |
| this.children[i].parentIndex-- | |
| } | |
| child.parent = null; | |
| child.parentIndex = null | |
| } | |
| }, | |
| clear: function() { | |
| for (var i in this.children) { | |
| this.children[i].parent = null; | |
| this.children[i].parentIndex = null | |
| } | |
| this.children = [] | |
| }, | |
| leaves: function() { | |
| var total = 0; | |
| for (var i in this.children) { | |
| total += this.children[i].leaves() | |
| } | |
| return total | |
| } | |
| }); | |
| function DisplayableRectangle() { | |
| DisplayableContainer.call(this); | |
| this.color = "#000"; | |
| this.width = 0; | |
| this.height = 0 | |
| } | |
| DisplayableRectangle.prototype = extendPrototype(DisplayableContainer, { | |
| render: function(c) { | |
| c.fillStyle = this.color; | |
| c.fillRect(0, 0, this.width, this.height); | |
| DisplayableContainer.prototype.render.call(this, c) | |
| } | |
| }); | |
| function DisplayableShape(drawFunction) { | |
| DisplayableObject.call(this); | |
| this.drawFunction = drawFunction | |
| } | |
| DisplayableShape.prototype = extendPrototype(DisplayableObject, { | |
| render: function(c) { | |
| this.drawFunction(c) | |
| } | |
| }); | |
| function DisplayableTextField() { | |
| DisplayableObject.call(this); | |
| this.text = null; | |
| this.font = "12pt Arial"; | |
| this.textAlign = "left"; | |
| this.textBaseline = "top"; | |
| this.color = "#000"; | |
| this.shadowColor = null; | |
| this.shadowOffsetX = 0; | |
| this.shadowOffsetY = 0 | |
| } | |
| DisplayableTextField.prototype = extendPrototype(DisplayableObject, { | |
| render: function(c) { | |
| if (this.text != null && this.text.toString().length > 0) { | |
| c.font = this.font; | |
| c.textAlign = this.textAlign; | |
| c.textBaseline = this.textBaseline; | |
| if (this.shadowColor) { | |
| c.fillStyle = this.shadowColor; | |
| c.fillText(this.text, this.shadowOffsetX, this.shadowOffsetY) | |
| } | |
| c.fillStyle = this.color; | |
| c.fillText(this.text, 0, 0) | |
| } | |
| } | |
| }); | |
| function DisplayableImage() { | |
| DisplayableObject.call(this); | |
| this.image = null; | |
| this.anchorX = this.anchorY = 0 | |
| } | |
| DisplayableImage.prototype = extendPrototype(DisplayableObject, { | |
| render: function(c) { | |
| c.drawImage(this.image, this.anchorX, this.anchorY) | |
| } | |
| }); | |
| function Tween(object, property, from, to, duration, delay, onFinish) { | |
| this.object = object; | |
| this.delayLeft = delay || 0; | |
| this.duration = duration; | |
| this.elapsed = 0; | |
| this.property = property; | |
| this.from = from; | |
| this.to = to; | |
| this.onFinish = onFinish; | |
| this.finished = false; | |
| object[property] = from | |
| } | |
| Tween.prototype = { | |
| cycle: function(e) { | |
| if (this.delayLeft > 0) { | |
| this.delayLeft -= e; | |
| this.object[this.property] = this.from | |
| } | |
| if (this.delayLeft <= 0) { | |
| this.elapsed += e; | |
| if (this.elapsed >= this.duration) { | |
| this.finish() | |
| } else { | |
| this.progress() | |
| } | |
| } | |
| }, | |
| finish: function() { | |
| if (!this.finished) { | |
| this.finished = true; | |
| this.delayLeft = 0; | |
| this.elapsed = this.duration; | |
| this.object[this.property] = this.to; | |
| if (this.onFinish) { | |
| this.onFinish.call(this) | |
| } | |
| } | |
| }, | |
| isFinished: function() { | |
| return this.elapsed >= this.duration | |
| }, | |
| progress: function() { | |
| var prct = this.duration > 0 ? this.elapsed / this.duration : 1; | |
| this.object[this.property] = prct * (this.to - this.from) + this.from | |
| } | |
| }; | |
| var TweenPool = { | |
| tweens: [], | |
| cycle: function(e) { | |
| var i = 0; | |
| while (this.tweens[i]) { | |
| this.tweens[i].cycle(e); | |
| if (!this.tweens[i].isFinished()) { | |
| i++ | |
| } else { | |
| this.tweens.splice(i, 1) | |
| } | |
| } | |
| }, | |
| remove: function(tw) { | |
| var index = this.tweens.indexOf(tw); | |
| if (index >= 0) { | |
| this.tweens.splice(index, 1) | |
| } | |
| }, | |
| add: function(tw) { | |
| this.tweens.push(tw) | |
| } | |
| }; | |
| function Button(settings, action) { | |
| DisplayableObject.call(this); | |
| this.pressed = false; | |
| this.action = action; | |
| this.width = settings.width || 300; | |
| this.height = settings.height || 80; | |
| this.bgColor = settings.bgColor || "#ffffff"; | |
| this.borderColor = settings.lineColor || "#000"; | |
| this.borderRadius = settings.borderRadius || 10; | |
| this.textColor = settings.textColor || "#000"; | |
| this.fontSize = settings.fontSize || 40; | |
| this.outlineColor = settings.outlineColor || "#000"; | |
| this.outlineWidth = settings.outlineWidth || 0; | |
| this.id = settings.id || undefined; | |
| this.setContent(settings.content) | |
| } | |
| Button.prototype = extendPrototype(DisplayableObject, { | |
| setContent: function(arg0) { | |
| this.text = this.image = null; | |
| if (typeof arg0 == "string") { | |
| this.type = "button"; | |
| this.text = arg0; | |
| this.id = this.text | |
| } else { | |
| this.type = "image"; | |
| this.image = arg0; | |
| this.width = arg0.width; | |
| this.height = arg0.height | |
| } | |
| }, | |
| render: function(c) { | |
| if (this.text) { | |
| c.save(); | |
| c.translate(.5, .5); | |
| c.globalAlpha *= this.pressed ? .5 : 1; | |
| c.beginPath(); | |
| c.fillStyle = this.bgColor; | |
| c.strokeStyle = this.borderColor; | |
| c.lineWidth = 2; | |
| c.moveTo(0, this.borderRadius); | |
| c.arc(this.borderRadius, this.borderRadius, this.borderRadius, Math.PI, -Math.PI / 2, false); | |
| c.arc(this.width - this.borderRadius, this.borderRadius, this.borderRadius, -Math.PI / 2, 0, false); | |
| c.arc(this.width - this.borderRadius, this.height - this.borderRadius, this.borderRadius, 0, Math.PI / 2, false); | |
| c.arc(this.borderRadius, this.height - this.borderRadius, this.borderRadius, Math.PI / 2, Math.PI, false); | |
| c.closePath(); | |
| c.fill(); | |
| c.stroke(); | |
| c.restore(); | |
| c.font = this.fontSize + "pt Bariol"; | |
| c.textAlign = "center"; | |
| c.textBaseline = "middle"; | |
| c.fillStyle = this.textColor; | |
| c.fillText(this.text, this.width / 2, this.height / 2); | |
| if (this.outlineWidth > 0) { | |
| c.lineWidth = this.outlineWidth; | |
| c.strokeStyle = this.outlineColor; | |
| c.strokeText(this.text, this.width / 2, this.height / 2 + 3) | |
| } | |
| } else { | |
| c.globalAlpha *= this.pressed ? .5 : 1; | |
| c.drawImage(this.image, 0, 0, this.image.width, this.image.height, 0, 0, this.width, this.height) | |
| } | |
| }, | |
| getArea: function() { | |
| var me = this; | |
| return new Area(this.x, this.y, this.width, this.height, { | |
| actionStart: function() { | |
| me.pressed = true | |
| }, | |
| actionPerformed: function() { | |
| me.pressed = false; | |
| me.action(); | |
| Tracker.event("button-clicked", "button-" + me.id) | |
| }, | |
| actionCancel: function() { | |
| me.pressed = false | |
| } | |
| }) | |
| } | |
| }); | |
| var P = { | |
| width: 640, | |
| height: 960, | |
| gridWidth: 4, | |
| gridHeight: 4, | |
| leaderboardKey: "tap-lb", | |
| gameURL: "http://www.donttap.com/", | |
| facebookShareURL: "https://www.facebook.com/sharer/sharer.php?t=%text%&u=%url%", | |
| twitterShareURL: "https://twitter.com/intent/tweet?text=%text%", | |
| cocoon: !!window.isCocoon, | |
| inAppGames: window.location.href.indexOf("inappgames") !== -1 || window.location.href.indexOf("utm_source=ubersocialios") !== -1 && window.location.href.indexOf("utm_medium=inapp") !== -1 | |
| }; | |
| var AdsSettings = { | |
| ads: { | |
| tablet: { | |
| slot: "/20973361/whiteblock_iPad_300x600", | |
| width: 300, | |
| height: 600, | |
| interval: 6, | |
| check: function() { | |
| return navigator.userAgent.toLowerCase().indexOf("ipad") >= 0 | |
| } | |
| }, | |
| mobile: { | |
| slot: "/20973361/whiteblock_mobile_300x250", | |
| width: 300, | |
| height: 250, | |
| interval: 4, | |
| check: function() { | |
| return Util.isTouchScreen() | |
| } | |
| }, | |
| web: { | |
| slot: "/20973361/whiteblock_desktop_300x600", | |
| width: 300, | |
| height: 600, | |
| interval: 5, | |
| check: function() { | |
| return true | |
| } | |
| } | |
| } | |
| }; | |
| window.addToHomeConfig = { | |
| touchIcon: true, | |
| autostart: false | |
| }; | |
| var resources = { | |
| folder: "img/", | |
| image: { | |
| menu_bg: "menu-bg.png", | |
| end_bg: "end-bg.png", | |
| character: "character.png", | |
| logo: "logo.png", | |
| button_fb: "fb.png", | |
| button_twitter: "twitter.png", | |
| button_fb_clean: "fb-clean.png", | |
| button_twitter_clean: "twitter-clean.png", | |
| gameover_bg: "gameover-bg.png", | |
| button_kik_white: "kik-white.png", | |
| button_kik_black: "kik-black.png", | |
| button_menu_white: "menu-white.png", | |
| button_menu_black: "menu-black.png", | |
| button_retry: "retry.png", | |
| bubble: "bubble.png", | |
| domain: "domain.png" | |
| } | |
| }; | |
| DOM.on(window, "load", function() { | |
| DOM.un(window, "load", arguments.callee); | |
| can = DOM.get("gamecanvas"); | |
| can.width = P.width; | |
| can.height = P.height; | |
| ctx = can.getContext("2d"); | |
| window.resizer = new Resizer({ | |
| element: DOM.get("viewport"), | |
| delay: 10, | |
| baseWidth: P.width, | |
| baseHeight: P.height, | |
| onResize: function() { | |
| window.scrollTo(0, 1) | |
| } | |
| }); | |
| var getDimensionsAndResize = function() { | |
| var w = window.innerWidth; | |
| var h = window.innerHeight; | |
| window.resizer.needsResize(w, h) | |
| }; | |
| if (!P.cocoon) { | |
| DOM.on(window, "resize orientationchange", getDimensionsAndResize); | |
| getDimensionsAndResize() | |
| } | |
| if (document.location.search.indexOf("domconsole") >= 0) { | |
| window.console = new DOMConsole | |
| } | |
| Tracker.stage("screen-loading"); | |
| var loader = new ResourceLoader(resources); | |
| loader.load(function(res) { | |
| R = res; | |
| if (Util.isTouchScreen()) { | |
| window.scrollTo(0, 1) | |
| } | |
| new Game(resizer) | |
| }, can) | |
| }); | |
| function Game() { | |
| Game.instance = this; | |
| window.G = this; | |
| this.curScreen = null; | |
| var me = this; | |
| this.lastCycleDate = Date.now(); | |
| this.frameCount = 0; | |
| this.leaderboard = new LocalLeaderboard; | |
| this.leaderboard.load(); | |
| var mode; | |
| if (window.kik && kik.message) { | |
| Tracker.event("kik-message", "kik-message-open"); | |
| if (kik.message.mode) { | |
| switch (kik.message.mode) { | |
| case "endurance": | |
| mode = new EnduranceMode(this); | |
| break; | |
| case "pattern": | |
| mode = new PatternMode(this); | |
| break; | |
| case "frenzy": | |
| mode = new FrenzyMode(this); | |
| break | |
| } | |
| } | |
| } | |
| if (mode) { | |
| this.newGame(mode) | |
| } else { | |
| this.menu() | |
| } | |
| cycleManager.init(this.cycle.bind(this)); | |
| DOM.on(document.body, "touchstart mousedown", this.handleDownEvent.bind(this)); | |
| DOM.on(document.body, "touchmove mousemove", this.handleMoveEvent.bind(this)); | |
| DOM.on(document.body, "touchend mouseup touchcancel", this.handleUpEvent.bind(this)); | |
| DOM.on("ad-close-button", "click touchend", this.closeAd.bind(this)); | |
| DOM.on("ad-over", "click touchend", this.closeAd.bind(this)); | |
| this.kikInit(); | |
| var sounds = ["a6", "a7", "a8", "c6", "c7", "c8", "c9", "d6", "d7", "d8", "f6", "f7", "f8", "g6", "g7", "g8"]; | |
| var s; | |
| this.sounds = []; | |
| for (var i in sounds) { | |
| s = new Howl({ | |
| urls: ["sound/" + sounds[i] + ".mp3", "sound/" + sounds[i] + ".ogg"], | |
| volume: 1 | |
| }); | |
| this.sounds.push(s) | |
| } | |
| this.initAds() | |
| } | |
| Game.prototype = { | |
| setScreen: function(screen, noTransition, isOverlay) { | |
| if (this.curScreen) { | |
| this.curScreen.destroy() | |
| } | |
| var suffix; | |
| if (location.search.indexOf("amazon") >= 0) { | |
| suffix = "amazon" | |
| } else if (P.cocoon) { | |
| if (Detect.isAndroid()) { | |
| suffix = "nativeandroid" | |
| } else { | |
| suffix = "nativeios" | |
| } | |
| } else { | |
| if (window.kik && kik.send) { | |
| suffix = "kik" | |
| } else if ("standalone" in window.navigator && window.navigator.standalone) { | |
| suffix = "homescreen" | |
| } else { | |
| suffix = "nonkik" | |
| } | |
| } | |
| Tracker.stage("screen-" + screen.getId() + "-" + suffix); | |
| this.curScreen = screen; | |
| this.curScreen.create(); | |
| this.stage = this.curScreen.view | |
| }, | |
| cycle: function(elapsed) { | |
| this.lastCycleDate = Date.now(); | |
| var before = Date.now(); | |
| this.curScreen.cycle(elapsed); | |
| TweenPool.cycle(elapsed); | |
| ctx.fillStyle = "#000"; | |
| ctx.fillRect(0, 0, P.width, P.height); | |
| var between = Date.now(); | |
| this.stage.doRender(ctx); | |
| var after = Date.now(); | |
| if (P.showFrameRate) { | |
| ctx.textAlign = "left"; | |
| ctx.fillStyle = "#ffffff"; | |
| ctx.fillText("FPS: " + cycleManager.fps, 10, 10); | |
| ctx.fillText("Total: " + (after - before), 10, 20); | |
| ctx.fillText("Cycle: " + (between - before), 10, 30); | |
| ctx.fillText("Render: " + (after - between), 10, 40); | |
| ctx.fillText("Theoretical: " + Math.round(1e3 / Math.max(1, after - before)), 10, 50); | |
| ctx.fillText("Size: " + this.stage.leaves(), 10, 60) | |
| } | |
| }, | |
| getPosition: function(e) { | |
| if (e.touches) e = e.touches[e.touches.length - 1]; | |
| var canRect = can.getBoundingClientRect(); | |
| if (!P.cocoon) { | |
| res = { | |
| x: (e.clientX - canRect.left) / (canRect.width / P.width), | |
| y: (e.clientY - canRect.top) / (canRect.height / P.height) | |
| } | |
| } else { | |
| res = { | |
| x: e.clientX, | |
| y: e.clientY | |
| } | |
| } | |
| return res | |
| }, | |
| handleDownEvent: function(e) { | |
| if (Date.now() - this.lastCycleDate >= 1e3) { | |
| cycleManager.stop(); | |
| cycleManager.resume() | |
| } | |
| var evtType = e.type.indexOf("touch") >= 0 ? "touch" : "mouse"; | |
| this.inputType = this.inputType || evtType; | |
| if (evtType != this.inputType) return; | |
| if (this.adOpen) return; | |
| this.down = true; | |
| this.lastEvent = this.getPosition(e); | |
| this.curScreen.touchStart(this.lastEvent.x, this.lastEvent.y); | |
| if (evtType == "touch") {} | |
| }, | |
| handleMoveEvent: function(e) { | |
| this.lastEvent = this.getPosition(e); | |
| if (this.down) { | |
| e.preventDefault(); | |
| this.curScreen.touchMove(this.lastEvent.x, this.lastEvent.y) | |
| } | |
| if (this.inputType == "touch") { | |
| e.preventDefault() | |
| } | |
| }, | |
| handleUpEvent: function(e) { | |
| if (this.down) { | |
| this.curScreen.touchEnd(this.lastEvent.x, this.lastEvent.y); | |
| this.down = false; | |
| this.lastEvent = null | |
| } | |
| window.scrollTo(0, 1) | |
| }, | |
| newGame: function(mode, isRetry) { | |
| this.lastMode = mode; | |
| this.setScreen(new GameplayScreen(this, this.lastMode)); | |
| addToHome.close(); | |
| if (!Detect.isIOS() && P.cocoon) { | |
| CocoonJS.Ad.hideBanner() | |
| } | |
| }, | |
| gameOver: function() { | |
| Tracker.event("end-mode", "end-mode-" + this.lastMode.getId()); | |
| this.setScreen(new EndScreen(this, this.lastMode)); | |
| window.gmga("gamedone"); | |
| this.gamesToNextAd--; | |
| if (this.gamesToNextAd <= 0) { | |
| this.showAd() | |
| } | |
| addToHome.show(); | |
| if (this.lastMode.isSuccess()) { | |
| var lb = this.lastMode.getLeaderboardId(); | |
| var score = this.lastMode.getLeaderboardScore(); | |
| gmapi(function(api) { | |
| api.game.leaderboard.sendScore(score, { | |
| levelName: lb | |
| }) | |
| }) | |
| } | |
| if (!Detect.isIOS() && P.cocoon) { | |
| this.showCocoonAd() | |
| } | |
| }, | |
| menu: function() { | |
| this.lastMode = null; | |
| this.setScreen(new MenuScreen(this)) | |
| }, | |
| retry: function() { | |
| this.newGame(this.lastMode, true) | |
| }, | |
| getSocialText: function() { | |
| if (this.lastMode && this.lastMode.isSuccess()) { | |
| return this.lastMode.getSocialText() | |
| } else { | |
| return "Play #DontTap on your phone, tablet, and desktop computer at " + P.gameURL + "! #WhiteTile" | |
| } | |
| }, | |
| open: function(url) { | |
| if (P.cocoon) { | |
| CocoonJS.App.openURL.apply(CocoonJS.App, arguments) | |
| } else { | |
| window.open.apply(window, arguments) | |
| } | |
| }, | |
| shareKik: function() { | |
| Tracker.event("share", "share-kik-" + (this.lastMode && this.lastMode.isSuccess() ? "score" : "generic")); | |
| var title = this.getSocialText(); | |
| var data = {}; | |
| if (this.lastMode && this.lastMode.isSuccess()) { | |
| data.mode = this.lastMode.getId(); | |
| data.score = this.lastMode.getScore() | |
| } | |
| kik.send({ | |
| title: title, | |
| text: "Can you beat me?", | |
| pic: "promo/kik-icon.png", | |
| data: data | |
| }) | |
| }, | |
| shareFacebook: function(mode) { | |
| Tracker.event("share", "share-facebook-" + (this.lastMode && this.lastMode.isSuccess() ? "score" : "generic")); | |
| var url = P.facebookShareURL.replace("%text%", encodeURIComponent(this.getSocialText())).replace("%url%", encodeURIComponent(P.gameURL)); | |
| this.open(url, "shareFbWindow", "width=650,height=440,scrollbars=yes,location=no") | |
| }, | |
| shareTwitter: function(mode) { | |
| Tracker.event("share", "share-twitter-" + (this.lastMode && this.lastMode.isSuccess() ? "score" : "generic")); | |
| var url = P.twitterShareURL.replace("%text%", encodeURIComponent(this.getSocialText())); | |
| this.open(url, "shareTwitterWindow", "width=450,height=450,scrollbars=yes,location=no") | |
| }, | |
| rate: function() { | |
| if (Util.isAndroid()) { | |
| CocoonJS.App.openURL(P.googlePlayURL) | |
| } else { | |
| CocoonJS.App.openURL(P.appStoreURL) | |
| } | |
| }, | |
| kikInit: function() { | |
| if (window.kik) { | |
| if (kik.browser) { | |
| if (kik.browser.setOrientationLock) { | |
| kik.browser.setOrientationLock("portrait") | |
| } | |
| if (kik.browser.statusBar) { | |
| kik.browser.statusBar(false) | |
| } | |
| } | |
| if (kik.metrics && kik.metrics.enableGoogleAnalytics) { | |
| kik.metrics.enableGoogleAnalytics() | |
| } | |
| } | |
| }, | |
| playSound: function(n) { | |
| this.sounds[n].play() | |
| }, | |
| initCocoonAds: function() { | |
| console.log("Initializing cocoon ads"); | |
| var me = this; | |
| CocoonJS.Ad.onFullScreenShown.addEventListener(function() {}); | |
| CocoonJS.Ad.onFullScreenHidden.addEventListener(function() { | |
| CocoonJS.Ad.refreshFullScreen() | |
| }); | |
| CocoonJS.Ad.onFullScreenReady.addEventListener(function() {}); | |
| CocoonJS.Ad.preloadFullScreen() | |
| }, | |
| showCocoonAd: function() { | |
| console.log("Show a cocoon ad"); | |
| CocoonJS.Ad.showFullScreen(); | |
| return true | |
| }, | |
| initGoogleAds: function() { | |
| var me = this; | |
| googletag.cmd.push(function() { | |
| me.adSlot = googletag.defineSlot(me.adSettings.slot, [me.adSettings.width, me.adSettings.height], "ad").addService(googletag.pubads()); | |
| googletag.pubads().enableSingleRequest(); | |
| googletag.enableServices(); | |
| googletag.display("ad"); | |
| me.adCreated = true | |
| }); | |
| var container = DOM.get("ad-container"); | |
| container.style.width = this.adSettings.width + "px"; | |
| container.style.height = this.adSettings.height + "px" | |
| }, | |
| getAdInterval: function() { | |
| return this.adSettings.interval | |
| }, | |
| initAds: function() { | |
| if (!this.adsInitted) { | |
| this.adsInitted = true; | |
| for (var i in AdsSettings.ads) { | |
| if (AdsSettings.ads[i].check()) { | |
| this.adSettings = AdsSettings.ads[i]; | |
| break | |
| } | |
| } | |
| if (this.adSettings) { | |
| if (P.cocoon) { | |
| this.initCocoonAds() | |
| } else { | |
| this.initGoogleAds() | |
| } | |
| this.gamesToNextAd = this.getAdInterval() | |
| } | |
| } | |
| }, | |
| closeAd: function() { | |
| if (this.adOpen) { | |
| if (P.cocoon) { | |
| CocoonJS.Ad.hideBanner() | |
| } else { | |
| this.adOpen = false; | |
| ga("send", "event", "ad", "close", "close-ad"); | |
| DOM.hide("ad-over"); | |
| var me = this; | |
| googletag.cmd.push(function() { | |
| googletag.pubads().refresh([me.adSettings.slot]) | |
| }) | |
| } | |
| } | |
| }, | |
| showAd: function() { | |
| if (this.adsInitted) { | |
| console.log("showing ad?"); | |
| var res; | |
| if (P.cocoon) { | |
| res = this.showCocoonAd() | |
| } else { | |
| DOM.show("ad-over"); | |
| this.adOpen = true; | |
| res = true | |
| } | |
| if (res) { | |
| ga("send", "event", "ad", "show", "show-ad"); | |
| this.gamesToNextAd = this.getAdInterval() | |
| } | |
| } | |
| } | |
| }; | |
| var Tracker = { | |
| suffix: function() { | |
| if ("standalone" in window.navigator && navigator.standalone) { | |
| return "-homescreen" | |
| } else if (window.cordova || P.cocoon) { | |
| return "-native" | |
| } else if (window.kik && kik.send) { | |
| return "-kik" | |
| } else if (P.amazon) { | |
| return "-amazon" | |
| } else { | |
| return "-web" | |
| } | |
| }, | |
| event: function(eventCategory, eventLabel, eventValue) { | |
| if (window.cordova && window.gaPlugin) { | |
| gaPlugin.trackEvent(function() { | |
| console.log("Sent event data") | |
| }, function(e) { | |
| console.log("Error while sending event data: " + e) | |
| }, "gameevent", eventCategory + this.suffix(), eventLabel + this.suffix(), eventValue || 0) | |
| } else if (window.ga) { | |
| ga("send", "event", "gameevent", eventCategory + this.suffix(), eventLabel + this.suffix(), eventValue || 0) | |
| } | |
| }, | |
| stage: function(stageLabel) { | |
| var page = "/stage-" + stageLabel + this.suffix(); | |
| if (window.cordova && window.gaPlugin) { | |
| gaPlugin.trackPage(function() { | |
| console.log("Sent page view") | |
| }, function(e) { | |
| console.log("Error while sending page view: " + e) | |
| }, page) | |
| } else if (window.ga) { | |
| ga("send", "pageview", page) | |
| } | |
| } | |
| }; | |
| function LocalLeaderboard() { | |
| this.scores = {} | |
| } | |
| LocalLeaderboard.prototype = { | |
| load: function() { | |
| var json = Util.storage.getItem(P.leaderboardKey); | |
| if (json) { | |
| this.scores = JSON.parse(json) | |
| } else { | |
| this.scores = {} | |
| } | |
| }, | |
| save: function() { | |
| Util.storage.setItem(P.leaderboardKey, JSON.stringify(this.scores)) | |
| }, | |
| getScores: function(mode) { | |
| return this.scores[mode.getId()] || [] | |
| }, | |
| addScore: function(mode, score) { | |
| var i; | |
| if (!this.scores[mode.getId()]) { | |
| this.scores[mode.getId()] = [] | |
| } | |
| i = 0; | |
| while (i < this.scores[mode.getId()].length && mode.compareScores(score, this.scores[mode.getId()][i].score) < 0) { | |
| i++ | |
| } | |
| this.scores[mode.getId()].splice(i, 0, { | |
| score: score, | |
| date: Date.now() | |
| }); | |
| this.save() | |
| }, | |
| getHighscore: function(mode) { | |
| if (!this.scores[mode.getId()]) { | |
| return 0 | |
| } | |
| return this.scores[mode.getId()][0] || null | |
| } | |
| }; | |
| function GameMode() {} | |
| GameMode.prototype = { | |
| initialize: function(screen) { | |
| this.screen = screen | |
| }, | |
| launch: function() { | |
| this.screen.showMessage("Tap the black tiles!") | |
| }, | |
| tappedHighlighted: function(tile) {}, | |
| tappedWrong: function(tile) {}, | |
| cycle: function(e) {}, | |
| getScore: function() { | |
| return 0 | |
| }, | |
| getFormattedScore: function(s) { | |
| return s.toString() | |
| }, | |
| end: function(reason) { | |
| this.screen.over(reason) | |
| }, | |
| getId: function() { | |
| return null | |
| }, | |
| getInstructions: function() { | |
| return null | |
| }, | |
| getBgColor: function() { | |
| return "#000" | |
| }, | |
| getGaugeValue: function() { | |
| return .5 | |
| }, | |
| getTimeValue: function() { | |
| return 0 | |
| }, | |
| isSuccess: function() { | |
| return true | |
| }, | |
| getScoreType: function() { | |
| return "points" | |
| }, | |
| compareScores: function(s1, s2) { | |
| return s1 - s2 | |
| }, | |
| getLeaderboardId: function() { | |
| return null | |
| }, | |
| getLeaderboardScore: function() { | |
| return 0 | |
| } | |
| }; | |
| function EnduranceMode() { | |
| GameMode.call(this) | |
| } | |
| EnduranceMode.prototype = extendPrototype(GameMode, { | |
| getId: function() { | |
| return "endurance" | |
| }, | |
| getInstructions: function() { | |
| return ["10 seconds for", "every 40 taps"] | |
| }, | |
| initialize: function(screen) { | |
| GameMode.prototype.initialize.call(this, screen); | |
| this.score = 0; | |
| this.timeLeft = 0; | |
| this.gaugeValue = 0; | |
| this.powerUpMode = false | |
| }, | |
| launch: function() { | |
| GameMode.prototype.launch.call(this); | |
| this.refill(); | |
| var ind; | |
| for (var i = 0; i < 3; i++) { | |
| do { | |
| ind = ~~(Math.random() * this.screen.tiles.length) | |
| } while (this.screen.tiles[ind].isHighlighted()); | |
| this.screen.tiles[ind].highlight() | |
| } | |
| }, | |
| refill: function() { | |
| this.timeLeft += 10; | |
| this.tilesToRefill = 40; | |
| this.screen.showMessage("+10 seconds"); | |
| this.screen.showAddTime(10) | |
| }, | |
| cycle: function(e) { | |
| this.timeLeft -= e; | |
| if (this.timeLeft <= 0) { | |
| this.end("Time's up") | |
| } else { | |
| this.gaugeValue = Math.max(0, this.gaugeValue - e * .3) | |
| } | |
| }, | |
| getScore: function() { | |
| return this.score | |
| }, | |
| tappedHighlighted: function(tile) { | |
| tile.disable(); | |
| this.screen.showOk(tile, "+1"); | |
| if (!this.powerUpMode) { | |
| var ind; | |
| do { | |
| ind = ~~(Math.random() * this.screen.tiles.length) | |
| } while (ind == this.screen.tiles.indexOf(tile) || this.screen.tiles[ind].isHighlighted()); | |
| this.screen.tiles[ind].highlight(); | |
| this.gaugeValue = Math.min(1, this.gaugeValue + .08); | |
| if (this.gaugeValue == 1) { | |
| this.powerUp() | |
| } | |
| } else { | |
| var fullWhite = true; | |
| for (var i = 0; i < this.screen.tiles.length; i++) { | |
| if (this.screen.tiles[i].isHighlighted()) { | |
| fullWhite = false; | |
| break | |
| } | |
| } | |
| if (fullWhite) { | |
| this.powerUpMode = false; | |
| for (var i = 0; i < 3; i++) { | |
| do { | |
| ind = ~~(Math.random() * this.screen.tiles.length) | |
| } while (this.screen.tiles[ind].isHighlighted()); | |
| this.screen.tiles[ind].highlight() | |
| } | |
| } | |
| } | |
| this.tilesToRefill--; | |
| if (this.tilesToRefill <= 0) { | |
| this.refill() | |
| } | |
| this.score++ | |
| }, | |
| powerUp: function() { | |
| this.powerUpMode = true; | |
| this.gaugeValue = 0; | |
| for (var i = 0; i < this.screen.tiles.length; i++) { | |
| (function(t) { | |
| setTimeout(function() { | |
| t.highlight() | |
| }, Math.random() * 500) | |
| })(this.screen.tiles[i]) | |
| } | |
| this.screen.showMessage("Uber power up") | |
| }, | |
| tappedWrong: function(tile) { | |
| this.screen.showError(tile); | |
| this.end(["You tapped", "a white tile!"]) | |
| }, | |
| getGaugeValue: function() { | |
| return this.gaugeValue | |
| }, | |
| getTimeValue: function() { | |
| return this.timeLeft | |
| }, | |
| getSocialText: function() { | |
| return "I scored " + this.score + " in Endurance playing Don't Tap! Can you beat me? Let's play: " + P.gameURL + " #donttap #whitetile" | |
| }, | |
| getLeaderboardId: function() { | |
| return "endurance" | |
| }, | |
| getLeaderboardScore: function() { | |
| return this.score | |
| } | |
| }); | |
| function FrenzyMode() { | |
| GameMode.call(this) | |
| } | |
| FrenzyMode.prototype = extendPrototype(GameMode, { | |
| getId: function() { | |
| return "frenzy" | |
| }, | |
| getInstructions: function() { | |
| return ["30 seconds,", "nothing more"] | |
| }, | |
| initialize: function(screen) { | |
| GameMode.prototype.initialize.call(this, screen); | |
| this.score = 0; | |
| this.timeLeft = 30; | |
| this.gaugeValue = 0 | |
| }, | |
| launch: function() { | |
| GameMode.prototype.launch.call(this); | |
| var ind; | |
| for (var i = 0; i < 3; i++) { | |
| do { | |
| ind = ~~(Math.random() * this.screen.tiles.length) | |
| } while (this.screen.tiles[ind].isHighlighted()); | |
| this.screen.tiles[ind].highlight() | |
| } | |
| }, | |
| cycle: function(e) { | |
| this.timeLeft -= e; | |
| if (this.timeLeft <= 0) { | |
| this.end("Time's up") | |
| } else { | |
| this.gaugeValue = Math.max(0, this.gaugeValue - e * .3) | |
| } | |
| }, | |
| getScore: function() { | |
| return this.score | |
| }, | |
| tappedHighlighted: function(tile) { | |
| var multiplier = Math.max(1, Math.ceil(this.gaugeValue * 5)); | |
| var t = null; | |
| if (multiplier > 1) { | |
| t = "x" + multiplier | |
| } | |
| this.score += multiplier; | |
| tile.disable(); | |
| this.screen.showOk(tile, "+" + multiplier); | |
| var ind; | |
| do { | |
| ind = ~~(Math.random() * this.screen.tiles.length) | |
| } while (ind == this.screen.tiles.indexOf(tile) || this.screen.tiles[ind].isHighlighted()); | |
| this.screen.tiles[ind].highlight(); | |
| this.gaugeValue = Math.min(1, this.gaugeValue + .08) | |
| }, | |
| tappedWrong: function(tile) { | |
| this.screen.showError(tile); | |
| this.end(["You tapped", "a white tile!"]) | |
| }, | |
| getBgColor: function() { | |
| return "#ffffff" | |
| }, | |
| getGaugeValue: function() { | |
| return this.gaugeValue | |
| }, | |
| getTimeValue: function() { | |
| return this.timeLeft | |
| }, | |
| getSocialText: function() { | |
| return "I scored " + this.score + " in Frenzy playing Don't Tap! Can you beat me? Let's play: " + P.gameURL + " #donttap #whitetile" | |
| }, | |
| getLeaderboardId: function() { | |
| return "frenzy" | |
| }, | |
| getLeaderboardScore: function() { | |
| return this.score | |
| } | |
| }); | |
| function PatternMode() { | |
| GameMode.call(this) | |
| } | |
| PatternMode.prototype = extendPrototype(GameMode, { | |
| getId: function() { | |
| return "pattern" | |
| }, | |
| getInstructions: function() { | |
| return ["Clear all", "the patterns"] | |
| }, | |
| initialize: function(screen) { | |
| GameMode.prototype.initialize.call(this, screen); | |
| this.score = 0; | |
| this.time = 0; | |
| this.gaugeValue = 0; | |
| this.patternsToClear = 15 | |
| }, | |
| nextPattern: function() { | |
| this.newPattern(this.patternSize()) | |
| }, | |
| patternSize: function() { | |
| return 4 | |
| }, | |
| newPattern: function(size) { | |
| for (var i = 0; i < size && i < this.screen.tiles.length; i++) { | |
| do { | |
| ind = ~~(Math.random() * this.screen.tiles.length) | |
| } while (this.screen.tiles[ind].isHighlighted()); | |
| this.screen.tiles[ind].highlight() | |
| } | |
| }, | |
| allWhite: function() { | |
| for (var i = 0; i < this.screen.tiles.length; i++) { | |
| if (this.screen.tiles[i].isHighlighted()) { | |
| return false | |
| } | |
| } | |
| return true | |
| }, | |
| launch: function() { | |
| GameMode.prototype.launch.call(this); | |
| this.nextPattern() | |
| }, | |
| cycle: function(e) { | |
| this.time += e; | |
| this.gaugeValue = Math.max(0, this.gaugeValue - e * .3) | |
| }, | |
| getTimeValue: function() { | |
| return this.time | |
| }, | |
| tappedHighlighted: function(tile) { | |
| tile.disable(); | |
| this.screen.showOk(tile); | |
| if (this.allWhite()) { | |
| this.patternsToClear--; | |
| if (this.patternsToClear > 0) { | |
| this.nextPattern() | |
| } else { | |
| this.end("All clear") | |
| } | |
| } | |
| this.score++; | |
| this.gaugeValue = Math.min(1, this.gaugeValue + .08) | |
| }, | |
| tappedWrong: function(tile) { | |
| this.screen.showError(tile); | |
| this.end(["You tapped", "a white tile!"]) | |
| }, | |
| getBgColor: function() { | |
| return "#333333" | |
| }, | |
| getGaugeValue: function() { | |
| return this.gaugeValue | |
| }, | |
| isSuccess: function() { | |
| return this.patternsToClear == 0 | |
| }, | |
| getScore: function() { | |
| return this.time | |
| }, | |
| getScoreType: function() { | |
| return "time" | |
| }, | |
| getFormattedScore: function(s) { | |
| return Math.round(s * 100) / 100 | |
| }, | |
| compareScores: function(s1, s2) { | |
| return s2 - s1 | |
| }, | |
| getSocialText: function() { | |
| return "I cleared all the tiles in " + this.getFormattedScore(this.time) + "s in Patterns playing Don't Tap! Can you beat me? Let's play: " + P.gameURL + " #donttap #whitetile" | |
| }, | |
| getLeaderboardId: function() { | |
| return "pattern" | |
| }, | |
| getLeaderboardScore: function() { | |
| return this.time * 1e3 | |
| } | |
| }); | |
| function MenuScreen(game) { | |
| Screen.call(this, game) | |
| } | |
| MenuScreen.prototype = extendPrototype(Screen, { | |
| create: function() { | |
| this.view = new DisplayableContainer; | |
| this.bg = new DisplayableImage; | |
| this.bg.image = R.image.menu_bg; | |
| this.view.addChild(this.bg); | |
| var character = new DisplayableImage; | |
| character.image = R.image.character; | |
| character.x = 300; | |
| character.y = 500; | |
| this.view.addChild(character); | |
| var logo = new DisplayableImage; | |
| logo.image = R.image.logo; | |
| logo.x = 100; | |
| logo.y = 100; | |
| this.view.addChild(logo); | |
| var domain = new DisplayableImage; | |
| domain.image = R.image.domain; | |
| domain.x = (P.width - domain.image.width) / 2; | |
| domain.y = P.height - 50; | |
| this.view.addChild(domain); | |
| var me = this; | |
| this.enduranceButton = new Button({ | |
| content: "Endurance", | |
| bgColor: "#000", | |
| textColor: "#ffffff", | |
| width: 270, | |
| height: 92 | |
| }, function() { | |
| me.game.newGame(new EnduranceMode) | |
| }); | |
| this.enduranceButton.x = 64; | |
| this.enduranceButton.y = 514; | |
| this.view.addChild(this.enduranceButton); | |
| this.addArea(this.enduranceButton.getArea()); | |
| this.frenzyButton = new Button({ | |
| content: "Frenzy", | |
| width: 270, | |
| height: 92 | |
| }, function() { | |
| me.game.newGame(new FrenzyMode) | |
| }); | |
| this.frenzyButton.x = 64; | |
| this.frenzyButton.y = 726; | |
| this.view.addChild(this.frenzyButton); | |
| this.addArea(this.frenzyButton.getArea()); | |
| this.patternButton = new Button({ | |
| content: "Pattern", | |
| bgColor: "#333333", | |
| textColor: "#ffffff", | |
| width: 270, | |
| height: 92 | |
| }, function() { | |
| me.game.newGame(new PatternMode) | |
| }); | |
| this.patternButton.x = 64; | |
| this.patternButton.y = 620; | |
| this.view.addChild(this.patternButton); | |
| this.addArea(this.patternButton.getArea()); | |
| if (!P.inAppGames) { | |
| this.fbButton = new Button({ | |
| content: R.image.button_fb, | |
| id: "facebook-menu" | |
| }, function() { | |
| me.game.shareFacebook() | |
| }); | |
| this.fbButton.x = 104; | |
| this.fbButton.y = 832; | |
| this.view.addChild(this.fbButton); | |
| this.addArea(this.fbButton.getArea()); | |
| this.twitterButton = new Button({ | |
| content: R.image.button_twitter, | |
| id: "twitter-menu" | |
| }, function() { | |
| me.game.shareTwitter() | |
| }); | |
| this.twitterButton.x = 212; | |
| this.twitterButton.y = 832; | |
| this.view.addChild(this.twitterButton); | |
| this.addArea(this.twitterButton.getArea()) | |
| } | |
| if (P.cocoon) { | |
| this.rateButton = new Button({ | |
| content: "Rate!", | |
| bgColor: "#000", | |
| textColor: "#ffffff", | |
| width: 90, | |
| height: 30, | |
| fontSize: 18 | |
| }, function() { | |
| me.game.rate() | |
| }); | |
| this.rateButton.x = 55; | |
| this.rateButton.y = 363 | |
| } | |
| TweenPool.add(new Tween(character, "x", P.width, character.x, .3, .5)); | |
| TweenPool.add(new Tween(logo, "alpha", 0, 1, .5, 1.5)); | |
| TweenPool.add(new Tween(this.enduranceButton, "alpha", 0, 1, .3, 2)); | |
| TweenPool.add(new Tween(this.patternButton, "alpha", 0, 1, .3, 2.3)); | |
| TweenPool.add(new Tween(this.frenzyButton, "alpha", 0, 1, .3, 2.6)); | |
| if (P.cocoon) TweenPool.add(new Tween(this.rateButton, "alpha", 0, 1, .3, 2.9)); | |
| if (this.twitterButton) { | |
| TweenPool.add(new Tween(this.twitterButton, "alpha", 0, 1, .3, 2.9)) | |
| } | |
| if (this.fbButton) { | |
| TweenPool.add(new Tween(this.fbButton, "alpha", 0, 1, .3, 2.9)) | |
| } | |
| var versionArea = new Area(200, 340, 200, 100, { | |
| actionPerformed: function() { | |
| version.visible = true | |
| } | |
| }); | |
| this.addArea(versionArea); | |
| var version = new DisplayableTextField; | |
| this.view.addChild(version); | |
| with(version) { | |
| text = window.gameVersion; | |
| x = P.width - 5; | |
| y = P.height - 5; | |
| textAlign = "right"; | |
| textBaseline = "bottom"; | |
| color = "black"; | |
| font = "20pt Arial"; | |
| visible = false | |
| } | |
| }, | |
| destroy: function() {}, | |
| getId: function() { | |
| return "menu" | |
| } | |
| }); | |
| function GameplayScreen(game, mode) { | |
| Screen.call(this, game); | |
| this.mode = mode | |
| } | |
| GameplayScreen.prototype = extendPrototype(Screen, { | |
| create: function() { | |
| this.view = new DisplayableContainer; | |
| this.background = new DisplayableRectangle; | |
| this.background.color = this.mode.getBgColor(); | |
| this.background.width = P.width; | |
| this.background.height = P.height; | |
| this.view.addChild(this.background); | |
| this.tilesContainer = new DisplayableRectangle; | |
| this.tilesContainer.width = P.width * (window.kik && kik.send ? .8 : 1); | |
| this.tilesContainer.height = this.tilesContainer.width; | |
| this.tilesContainer.x = (P.width - this.tilesContainer.width) / 2; | |
| this.tilesContainer.y = (P.height - this.tilesContainer.height) / 2; | |
| this.view.addChild(this.tilesContainer); | |
| this.tiles = []; | |
| this.tileMatrix = []; | |
| var t, tWidth = ~~(this.tilesContainer.width / P.gridWidth), | |
| tHeight = ~~(this.tilesContainer.height / P.gridHeight), | |
| me = this; | |
| for (var i = 0; i < P.gridWidth; i++) { | |
| this.tileMatrix.push([]); | |
| for (var j = 0; j < P.gridHeight; j++) { | |
| t = new Tile(function() { | |
| me.tilePressed(this) | |
| }); | |
| t.x = this.tilesContainer.x + i * tWidth; | |
| t.y = this.tilesContainer.y + j * tHeight; | |
| t.width = tWidth; | |
| t.height = tHeight; | |
| this.view.addChild(t); | |
| this.addArea(t.getArea()); | |
| this.tiles.push(t); | |
| this.tileMatrix[i].push(t) | |
| } | |
| } | |
| var labelY = 32; | |
| var labelSize = 16; | |
| var valueY = 80; | |
| var valueSize = 52; | |
| var scoreValueSize = 72; | |
| var scoreValueY = 90; | |
| this.scoreLabel = new DisplayableTextField; | |
| this.scoreLabel.visible = this.mode.getScoreType() == "points"; | |
| this.view.addChild(this.scoreLabel); | |
| with(this.scoreLabel) { | |
| textAlign = "center"; | |
| textBaseline = "middle"; | |
| x = P.width / 2; | |
| y = labelY; | |
| color = "#bababa"; | |
| font = labelSize + "pt Bariol"; | |
| text = "SCORE" | |
| } | |
| this.scoreTf = new DisplayableTextField; | |
| this.scoreTf.visible = this.mode.getScoreType() == "points"; | |
| this.view.addChild(this.scoreTf); | |
| with(this.scoreTf) { | |
| textAlign = "center"; | |
| textBaseline = "middle"; | |
| x = P.width / 2; | |
| y = scoreValueY; | |
| color = "#ff0000"; | |
| font = scoreValueSize + "pt Bariol"; | |
| color = "#1ba7c0" | |
| } | |
| this.timeLabel = new DisplayableTextField; | |
| this.view.addChild(this.timeLabel); | |
| with(this.timeLabel) { | |
| textAlign = "center"; | |
| textBaseline = "middle"; | |
| x = P.width - 100; | |
| y = labelY; | |
| color = "#bababa"; | |
| font = labelSize + "pt Bariol"; | |
| text = "TIME" | |
| } | |
| this.timeTf = new DisplayableTextField; | |
| this.view.addChild(this.timeTf); | |
| with(this.timeTf) { | |
| textAlign = "center"; | |
| textBaseline = "middle"; | |
| x = P.width - 100; | |
| y = valueY; | |
| color = "#f1ac37"; | |
| font = valueSize + "pt Bariol" | |
| } | |
| this.highscoreLabel = new DisplayableTextField; | |
| this.view.addChild(this.highscoreLabel); | |
| with(this.highscoreLabel) { | |
| textAlign = "center"; | |
| textBaseline = "middle"; | |
| x = 100; | |
| y = labelY; | |
| color = "#bababa"; | |
| font = labelSize + "pt Bariol"; | |
| text = "HI-SCORE" | |
| } | |
| this.highscoreTf = new DisplayableTextField; | |
| this.view.addChild(this.highscoreTf); | |
| with(this.highscoreTf) { | |
| textAlign = "center"; | |
| textBaseline = "middle"; | |
| x = 100; | |
| y = valueY; | |
| color = "#bababa"; | |
| font = valueSize + "pt Bariol"; | |
| var hs = this.game.leaderboard.getHighscore(this.mode); | |
| text = hs ? this.mode.getFormattedScore(hs.score) : 0 | |
| } | |
| switch (this.mode.getScoreType()) { | |
| case "points": | |
| this.highscoreTf.x = this.highscoreLabel.x = 100; | |
| this.timeLabel.x = this.timeTf.x = P.width - 100; | |
| this.scoreLabel.x = this.scoreTf.x = P.width / 2; | |
| break; | |
| case "time": | |
| this.timeLabel.x = this.timeTf.x = P.width * 2 / 3; | |
| this.highscoreLabel.x = this.highscoreTf.x = P.width / 3; | |
| break | |
| } | |
| this.gauge = new GaugeView; | |
| this.gauge.width = ~~(P.width * .75); | |
| this.gauge.height = 16; | |
| this.gauge.x = (P.width - this.gauge.width) / 2; | |
| this.gauge.y = P.height - 60; | |
| this.view.addChild(this.gauge); | |
| this.message = new DisplayableTextField; | |
| this.view.addChild(this.message); | |
| with(this.message) { | |
| color = "#ffa500"; | |
| font = "52pt Bariol"; | |
| textAlign = "center"; | |
| textBaseline = "middle"; | |
| x = P.width / 2; | |
| y = P.height / 2 - 40; | |
| visible = false | |
| } | |
| var countDown = new DisplayableRectangle; | |
| countDown.width = P.width; | |
| countDown.height = P.height; | |
| countDown.color = "rgba(0,0,0,0.9)"; | |
| this.view.addChild(countDown); | |
| var instructions = new DisplayableTextField; | |
| with(instructions) { | |
| x = P.width / 2; | |
| y = P.height / 2 + 120; | |
| color = "#00abcd"; | |
| textBaseline = "middle"; | |
| textAlign = "center"; | |
| font = "20pt Bariol"; | |
| text = this.mode.getInstructions() | |
| } | |
| var messageQueue = [this.mode.getInstructions()].concat(3, 2, 1); | |
| var countDownTfContainer = new DisplayableContainer; | |
| countDownTfContainer.x = P.width / 2; | |
| countDownTfContainer.y = P.height / 2; | |
| this.view.addChild(countDownTfContainer); | |
| var me = this; | |
| var count = 3; | |
| var down = function() { | |
| if (messageQueue.length > 0) { | |
| var msg = messageQueue.shift(); | |
| if (!(msg instanceof Array)) { | |
| msg = [msg] | |
| } | |
| countDownTfContainer.clear(); | |
| var tf, lineSize = 96; | |
| for (var i = 0; i < msg.length; i++) { | |
| tf = new DisplayableTextField; | |
| countDownTfContainer.addChild(tf); | |
| with(tf) { | |
| textAlign = "center"; | |
| textBaseline = "middle"; | |
| font = (msg[i].toString().length < 5 ? 160 : 60) + "pt Bariol"; | |
| color = "#00abcd"; | |
| text = msg[i].toString(); | |
| y = lineSize / 2 + (i - msg.length / 2) * lineSize | |
| } | |
| } | |
| setTimeout(arguments.callee, 1e3); | |
| TweenPool.add(new Tween(countDownTfContainer, "scaleX", 1, 0, .2, .8)); | |
| TweenPool.add(new Tween(countDownTfContainer, "scaleY", 1, 0, .2, .8)); | |
| TweenPool.add(new Tween(countDownTfContainer, "alpha", 1, 0, .2, .8)) | |
| } else { | |
| TweenPool.add(new Tween(countDown, "alpha", 1, 0, .2, 0, function() { | |
| this.object.remove() | |
| })); | |
| me.launch() | |
| } | |
| }; | |
| down(); | |
| this.mode.initialize(this); | |
| this.shakeTime = 0; | |
| if (window.crossPromo) { | |
| window.crossPromo.hide() | |
| } | |
| }, | |
| destroy: function() { | |
| if (window.crossPromo) { | |
| window.crossPromo.show() | |
| } | |
| }, | |
| launch: function() { | |
| this.launched = true; | |
| this.mode.launch(); | |
| this.showMessage("Tap the black tiles!") | |
| }, | |
| tilePressed: function(tile) { | |
| if (!this.isOver && this.launched) { | |
| if (tile.isHighlighted()) { | |
| this.mode.tappedHighlighted(tile) | |
| } else { | |
| this.mode.tappedWrong(tile) | |
| } | |
| } | |
| }, | |
| updateGauge: function() { | |
| this.gauge.value = this.mode.getGaugeValue() | |
| }, | |
| updateDisplayedScore: function() { | |
| this.previouslyDisplayedScore = this.previouslyDisplayedScore || 0; | |
| var s = this.mode.getScore(); | |
| this.scoreTf.text = s.toString(); | |
| if (s > this.previouslyDisplayedScore) { | |
| this.animateScore() | |
| } | |
| this.previouslyDisplayedScore = s | |
| }, | |
| updateDisplayedTime: function() { | |
| var t = this.mode.getTimeValue(); | |
| if (isNaN(t)) { | |
| this.timeTf.text = null | |
| } else { | |
| this.timeTf.text = Util.addZeros(Math.ceil(t), 2); | |
| if (t > 5) { | |
| this.timeTf.color = "#f1ac37" | |
| } else { | |
| this.timeTf.color = ~~(t * 2 % 2) == 0 ? "#ff0000" : "#f1ac37" | |
| } | |
| } | |
| }, | |
| animateScore: function() { | |
| this.timeScoreAnimated = .3; | |
| TweenPool.add(new Tween(this.scoreTf, "scaleX", 2, 1, .3)); | |
| TweenPool.add(new Tween(this.scoreTf, "scaleY", 2, 1, .3)) | |
| }, | |
| cycle: function(e) { | |
| if (!this.isOver && this.launched) { | |
| this.mode.cycle(e); | |
| this.updateDisplayedScore(); | |
| this.updateDisplayedTime(); | |
| this.updateGauge() | |
| } | |
| this.timeScoreAnimated -= e; | |
| this.scoreTf.color = this.timeScoreAnimated > 0 ? "#00ff00" : "#1ba7c0"; | |
| this.view.x = 0; | |
| this.view.y = 0; | |
| this.shakeTime -= e; | |
| if (this.shakeTime > 0) { | |
| this.view.x = ~~Util.rand(-10, 10); | |
| this.view.y = ~~Util.rand(-10, 10) | |
| } | |
| }, | |
| showMessage: function(t) { | |
| this.message.visible = true; | |
| this.message.text = t; | |
| TweenPool.add(new Tween(this.message, "scaleX", 0, 1, .2)); | |
| TweenPool.add(new Tween(this.message, "scaleY", 0, 1, .2)); | |
| clearTimeout(this.toClearMessage); | |
| this.toClearMessage = setTimeout(this.hideMessage.bind(this), 2e3) | |
| }, | |
| showBubbleMessage: function(a) { | |
| a = a instanceof Array ? a : [a]; | |
| this.hideMessage(); | |
| var container = new DisplayableContainer; | |
| container.x = P.width / 2; | |
| container.y = P.height / 2; | |
| this.view.addChild(container); | |
| var bubble = new DisplayableImage; | |
| bubble.image = R.image.bubble; | |
| bubble.anchorX = -bubble.image.width / 2; | |
| bubble.anchorY = -bubble.image.height / 2; | |
| container.addChild(bubble); | |
| TweenPool.add(new Tween(container, "scaleX", 0, 1, .2)); | |
| TweenPool.add(new Tween(container, "scaleY", 0, 1, .2)); | |
| var tf, lineSize = 48; | |
| for (var i = 0; i < a.length; i++) { | |
| tf = new DisplayableTextField; | |
| container.addChild(tf); | |
| with(tf) { | |
| textAlign = "center"; | |
| textBaseline = "middle"; | |
| font = "40pt Bariol"; | |
| color = "#ffffff"; | |
| text = a[i]; | |
| y = lineSize / 2 + (i - a.length / 2) * lineSize | |
| } | |
| } | |
| }, | |
| hideMessage: function() { | |
| this.message.visible = false | |
| }, | |
| over: function(reason) { | |
| this.isOver = true; | |
| this.showBubbleMessage(reason); | |
| setTimeout(this.game.gameOver.bind(this.game), 1e3); | |
| if (this.mode.isSuccess()) { | |
| this.game.leaderboard.addScore(this.mode, this.mode.getScore()) | |
| } | |
| }, | |
| shake: function() { | |
| this.shakeTime = .5; | |
| if (!P.cocoon) { | |
| navigator.vibrate(500) | |
| } | |
| }, | |
| showError: function(tile) { | |
| var error = new DisplayableRectangle; | |
| error.color = "#ff0000"; | |
| error.x = tile.x; | |
| error.y = tile.y; | |
| error.width = tile.width; | |
| error.height = tile.height; | |
| tile.parent.addChild(error); | |
| TweenPool.add(new Tween(error, "alpha", 1, 0, .2)); | |
| this.shake() | |
| }, | |
| showOk: function(tile, msg, msgColor) { | |
| var indic = new DisplayableRectangle; | |
| indic.color = "#00ff00"; | |
| indic.x = tile.x; | |
| indic.y = tile.y; | |
| indic.width = tile.width; | |
| indic.height = tile.height; | |
| tile.parent.addChild(indic); | |
| TweenPool.add(new Tween(indic, "alpha", 1, 0, .2)); | |
| this.lastTap = Date.now(); | |
| if (msg) { | |
| var tf = new DisplayableTextField; | |
| tile.parent.addChild(tf); | |
| with(tf) { | |
| textAlign = "center"; | |
| textBaseline = "middle"; | |
| x = tile.x + tile.width / 2; | |
| y = tile.y + tile.height / 2; | |
| color = msgColor || "red"; | |
| text = msg; | |
| font = "40pt Bariol" | |
| } | |
| TweenPool.add(new Tween(tf, "alpha", 1, 0, .2)) | |
| } | |
| this.game.playSound(this.tiles.indexOf(tile)) | |
| }, | |
| showAddTime: function(t) { | |
| var tf = new DisplayableTextField; | |
| this.view.addChild(tf); | |
| with(tf) { | |
| text = "+" + t; | |
| color = this.timeTf.color; | |
| font = this.timeTf.font; | |
| textAlign = "center"; | |
| textBaseline = "middle"; | |
| x = this.timeTf.x; | |
| y = this.timeTf.y + 100 | |
| } | |
| TweenPool.add(new Tween(tf, "y", tf.y, this.timeTf.y, .2, 0, function() { | |
| this.object.remove() | |
| })) | |
| }, | |
| getId: function() { | |
| return "gameplay-" + this.mode.getId() | |
| } | |
| }); | |
| function EndScreen(game, mode) { | |
| Screen.call(this, game); | |
| this.mode = mode | |
| } | |
| EndScreen.prototype = extendPrototype(Screen, { | |
| create: function() { | |
| this.view = new DisplayableContainer; | |
| this.backgroundColor = new DisplayableRectangle; | |
| this.backgroundColor.width = P.width; | |
| this.backgroundColor.height = P.height; | |
| this.backgroundColor.color = this.mode.getBgColor(); | |
| this.view.addChild(this.backgroundColor); | |
| this.background = new DisplayableImage; | |
| this.background.image = R.image.gameover_bg; | |
| this.background.alpha = 0; | |
| this.view.addChild(this.background); | |
| var char = new DisplayableImage; | |
| char.image = R.image.end_bg; | |
| char.x = P.width - char.image.width - 100; | |
| char.y = P.height - char.image.height - 100; | |
| this.view.addChild(char); | |
| var textColor = this.mode.getBgColor() == "#ffffff" ? "#000" : "#ffffff"; | |
| var valueColor1 = "#178fff"; | |
| var valueColor2 = "#178fff"; | |
| var youScored = new DisplayableTextField; | |
| this.view.addChild(youScored); | |
| with(youScored) { | |
| x = 384; | |
| y = 194; | |
| textAlign = "right"; | |
| textBaseline = "middle"; | |
| color = textColor; | |
| font = "56pt Bariol"; | |
| text = "You scored " | |
| } | |
| var score = new DisplayableTextField; | |
| this.view.addChild(score); | |
| with(score) { | |
| x = 384; | |
| y = 194; | |
| textAlign = "left"; | |
| textBaseline = "middle"; | |
| color = valueColor1; | |
| font = "68pt Bariol"; | |
| text = this.mode.getScore().toString() | |
| } | |
| if (!this.mode.isSuccess()) { | |
| youScored.text = "You failed"; | |
| youScored.textAlign = "center"; | |
| youScored.x = P.width / 2; | |
| score.text = "" | |
| } else { | |
| youScored.text = "You scored "; | |
| score.text = this.mode.getFormattedScore(this.mode.getScore()) | |
| } | |
| var dateLabel = new DisplayableTextField; | |
| this.view.addChild(dateLabel); | |
| with(dateLabel) { | |
| x = P.width / 3; | |
| y = 280; | |
| textAlign = "center"; | |
| textBaseline = "middle"; | |
| color = textColor; | |
| font = "28pt Bariol"; | |
| text = "DATE" | |
| } | |
| var scoreLabel = new DisplayableTextField; | |
| this.view.addChild(scoreLabel); | |
| with(scoreLabel) { | |
| x = P.width * 2 / 3; | |
| y = 280; | |
| textAlign = "center"; | |
| textBaseline = "middle"; | |
| color = textColor; | |
| font = "28pt Bariol"; | |
| text = "SCORE" | |
| } | |
| var scores = this.game.leaderboard.getScores(this.mode); | |
| var date, score, nextY = dateLabel.y + 50; | |
| for (var i = 0; i < 8; i++) { | |
| date = new DisplayableTextField; | |
| this.view.addChild(date); | |
| with(date) { | |
| x = P.width / 3; | |
| y = nextY; | |
| textAlign = "center"; | |
| textBaseline = "middle"; | |
| font = "36pt Bariol" | |
| } | |
| score = new DisplayableTextField; | |
| this.view.addChild(score); | |
| with(score) { | |
| x = P.width * 2 / 3; | |
| y = nextY; | |
| textAlign = "center"; | |
| textBaseline = "middle"; | |
| font = "36pt Bariol" | |
| } | |
| score.color = date.color = i % 2 == 0 ? valueColor1 : valueColor2; | |
| if (scores[i]) { | |
| score.text = this.mode.getFormattedScore(scores[i].score); | |
| var d = new Date(scores[i].date); | |
| date.text = d.getMonth() + 1 + "/" + d.getDate() + "/" + d.getFullYear() | |
| } else { | |
| score.text = date.text = "--" | |
| } | |
| nextY += 50 | |
| } | |
| var sc = this; | |
| var buttons = []; | |
| var button_suffix = this.mode.getBgColor() == "#ffffff" ? "_black" : "_white"; | |
| buttons.push(new Button({ | |
| content: R.image.button_retry, | |
| id: "retry-end" | |
| }, function() { | |
| sc.game.retry() | |
| })); | |
| buttons.push(new Button({ | |
| content: R.image["button_menu" + button_suffix], | |
| id: "menu-end" | |
| }, function() { | |
| sc.game.menu() | |
| })); | |
| if (window.kik && kik.send) { | |
| buttons.push(new Button({ | |
| content: R.image["button_kik" + button_suffix], | |
| id: "kik-end" | |
| }, function() { | |
| sc.game.shareKik() | |
| })) | |
| } | |
| for (var i = 0; i < buttons.length; i++) { | |
| buttons[i].x = P.width / 2 + 40 + (i - buttons.length / 2) * (buttons[i].width + 80); | |
| buttons[i].y = 800 - buttons[i].height / 2; | |
| this.view.addChild(buttons[i]); | |
| this.addArea(buttons[i].getArea()) | |
| } | |
| if (!P.inAppGames) { | |
| this.fbButton = new Button({ | |
| content: R.image.button_fb_clean, | |
| id: "facebook-end" | |
| }, function() { | |
| sc.game.shareFacebook() | |
| }); | |
| this.fbButton.x = P.width - this.fbButton.width - 40; | |
| this.fbButton.y = 40; | |
| this.view.addChild(this.fbButton); | |
| this.addArea(this.fbButton.getArea()); | |
| this.twitterButton = new Button({ | |
| content: R.image.button_twitter_clean, | |
| id: "twitter-end" | |
| }, function() { | |
| sc.game.shareTwitter() | |
| }); | |
| this.twitterButton.x = this.fbButton.x - this.twitterButton.width - 40; | |
| this.twitterButton.y = 40; | |
| this.view.addChild(this.twitterButton); | |
| this.addArea(this.twitterButton.getArea()) | |
| } | |
| }, | |
| destroy: function() {}, | |
| getId: function() { | |
| return "end" | |
| } | |
| }); | |
| function Tile(onClick) { | |
| DisplayableRectangle.call(this); | |
| this.color = "#ffffff"; | |
| this.highlightAlpha = 0; | |
| this.highlightTween = null; | |
| this.onClick = onClick | |
| } | |
| Tile.prototype = extendPrototype(DisplayableRectangle, { | |
| getArea: function() { | |
| return new Area(this.x, this.y, this.width, this.height, { | |
| actionStart: this.actionStart.bind(this), | |
| actionCancel: this.actionCancel.bind(this) | |
| }) | |
| }, | |
| actionStart: function() { | |
| this.onClick.call(this) | |
| }, | |
| actionCancel: function() {}, | |
| highlight: function() { | |
| this.highlighted = true; | |
| this.highlightAlpha = 1; | |
| if (this.highlightTween) { | |
| this.highlightTween.finish() | |
| } | |
| this.highlightTween = new Tween(this, "highlightAlpha", 0, 1, .2); | |
| TweenPool.add(this.highlightTween) | |
| }, | |
| disable: function() { | |
| this.highlighted = false; | |
| if (this.highlightTween) { | |
| this.highlightTween.finish() | |
| } | |
| this.highlightAlpha = 0 | |
| }, | |
| isHighlighted: function() { | |
| return this.highlighted | |
| }, | |
| render: function(c) { | |
| DisplayableRectangle.prototype.render.call(this, c); | |
| c.globalAlpha = this.highlightAlpha; | |
| c.fillStyle = "#000"; | |
| c.fillRect(0, 0, this.width, this.height); | |
| c.globalAlpha = 1; | |
| c.strokeStyle = "#b8b8b8"; | |
| c.strokeRect(.5, .5, this.width - 1, this.height - 1) | |
| } | |
| }); | |
| function LeaderboardView(scores) { | |
| DisplayableContainer.call(this); | |
| this.scores = scores; | |
| this.populate() | |
| } | |
| LeaderboardView.prototype = extendPrototype(DisplayableContainer, { | |
| populate: function() { | |
| var dateTf, scoreTf, nextY = 0; | |
| for (var i = 0; i < 5; i++) { | |
| dateTf = new DisplayableTextField; | |
| this.addChild(dateTf); | |
| with(dateTf) { | |
| color = "#ffffff"; | |
| textAlign = "right"; | |
| x = P.width / 2 - 5; | |
| y = nextY; | |
| font = "10pt Arial"; | |
| textBaseline = "top"; | |
| text = "1/1/1" | |
| } | |
| nextY += 20 | |
| } | |
| } | |
| }); | |
| function SinView() { | |
| DisplayableShape.call(this, this.drawCurve.bind(this)); | |
| this.amplitude = 0 | |
| } | |
| SinView.prototype = extendPrototype(DisplayableShape, { | |
| drawCurve: function(c) { | |
| c.strokeStyle = "#ffffff"; | |
| c.beginPath(); | |
| c.moveTo(0, 0); | |
| var a; | |
| for (var x = 0; x < P.width; x++) { | |
| a = (1 - Math.abs(x - P.width / 2) / (P.width / 2)) * this.amplitude; | |
| c.lineTo(x, Math.sin(Date.now() / 50 + x * Math.PI / 5) * a * 20) | |
| } | |
| c.stroke() | |
| } | |
| }); | |
| function GaugeView() { | |
| DisplayableObject.call(this); | |
| this.width = 100; | |
| this.height = 3; | |
| this.value = 0 | |
| } | |
| GaugeView.prototype = extendPrototype(DisplayableObject, { | |
| render: function(c) { | |
| c.fillStyle = "#1076a8"; | |
| c.fillRect(0, 0, this.width, this.height); | |
| c.fillStyle = "#33e4fb"; | |
| c.fillRect(1, 1, (this.width - 2) * this.value, this.height - 2) | |
| } | |
| }); | |
| var addToHome = function(w) { | |
| var nav = w.navigator, | |
| isIDevice = "platform" in nav && /iphone|ipod|ipad/gi.test(nav.platform), | |
| isIPad, isRetina, isSafari, isStandalone, OSVersion, startX = 0, | |
| startY = 0, | |
| lastVisit = 0, | |
| isExpired, isSessionActive, isReturningVisitor, balloon, overrideChecks, positionInterval, closeTimeout, options = { | |
| autostart: true, | |
| returningVisitor: false, | |
| animationIn: "drop", | |
| animationOut: "fade", | |
| startDelay: 2e3, | |
| lifespan: 15e3, | |
| bottomOffset: 14, | |
| expire: 0, | |
| message: "", | |
| touchIcon: false, | |
| arrow: true, | |
| hookOnLoad: true, | |
| closeButton: true, | |
| iterations: 100 | |
| }, | |
| intl = { | |
| ar: '<span dir="rtl">قم بتثبيت هذا التطبيق على <span dir="ltr">%device:</span>انقر<span dir="ltr">%icon</span> ØŒ<strong>ثم اضÙÙ‡ الى الشاشة الرئيسية.</strong></span>', | |
| ca_es: "Per instal·lar aquesta aplicació al vostre %device premeu %icon i llavors <strong>Afegir a pantalla d'inici</strong>.", | |
| cs_cz: "Pro instalaci aplikace na Váš %device, stisknÄ›te %icon a v nabÃdce <strong>PÅ™idat na plochu</strong>.", | |
| da_dk: "Tilføj denne side til din %device: tryk på %icon og derefter <strong>Føj til hjemmeskærm</strong>.", | |
| de_de: "Installieren Sie diese App auf Ihrem %device: %icon antippen und dann <strong>Zum Home-Bildschirm</strong>.", | |
| el_gr: "Εγκαταστήσετε αυτήν την ΕφαÏμογή στήν συσκευή σας %device: %icon μετά πατάτε <strong>Î Ïοσθήκη σε ΑφετηÏία</strong>.", | |
| en_us: "Install this web app on your %device: tap %icon and then <strong>Add to Home Screen</strong>.", | |
| es_es: "Para instalar esta app en su %device, pulse %icon y seleccione <strong>Añadir a pantalla de inicio</strong>.", | |
| fi_fi: "Asenna tämä web-sovellus laitteeseesi %device: paina %icon ja sen jälkeen valitse <strong>Lisää Koti-valikkoon</strong>.", | |
| fr_fr: "Ajoutez cette application sur votre %device en cliquant sur %icon, puis <strong>Ajouter à l'écran d'accueil</strong>.", | |
| he_il: '<span dir="rtl">התקן ×פליקציה זו על ×”-%device שלך: הקש %icon ו××– <strong>הוסף למסך הבית</strong>.</span>', | |
| hr_hr: "Instaliraj ovu aplikaciju na svoj %device: klikni na %icon i odaberi <strong>Dodaj u poÄetni zaslon</strong>.", | |
| hu_hu: "TelepÃtse ezt a web-alkalmazást az Ön %device-jára: nyomjon a %icon-ra majd a <strong>FÅ‘képernyÅ‘höz adás</strong> gombra.", | |
| it_it: "Installa questa applicazione sul tuo %device: premi su %icon e poi <strong>Aggiungi a Home</strong>.", | |
| ja_jp: "ã“ã®ã‚¦ã‚§ãƒ–アプリをã‚ãªãŸã®%deviceã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹ã«ã¯%iconをタップã—ã¦<strong>ホーム画é¢ã«è¿½åŠ </strong>ã‚’é¸ã‚“ã§ãã ã•ã„。", | |
| ko_kr: '%deviceì— ì›¹ì•±ì„ ì„¤ì¹˜í•˜ë ¤ë©´ %iconì„ í„°ì¹˜ 후 "í™ˆí™”ë©´ì— ì¶”ê°€"를 ì„ íƒí•˜ì„¸ìš”', | |
| nb_no: "Installer denne appen på din %device: trykk på %icon og deretter <strong>Legg til på Hjem-skjerm</strong>", | |
| nl_nl: "Installeer deze webapp op uw %device: tik %icon en dan <strong>Voeg toe aan beginscherm</strong>.", | |
| pl_pl: "Aby zainstalować tę aplikacje na %device: naciśnij %icon a następnie <strong>Dodaj jako ikonę</strong>.", | |
| pt_br: "Instale este aplicativo em seu %device: aperte %icon e selecione <strong>Adicionar à Tela Inicio</strong>.", | |
| pt_pt: "Para instalar esta aplicação no seu %device, prima o %icon e depois em <strong>Adicionar ao ecrã principal</strong>.", | |
| ru_ru: "УÑтановите Ñто веб-приложение на ваш %device: нажмите %icon, затем <strong>Добавить в «Домой»</strong>.", | |
| sv_se: "Lägg till denna webbapplikation på din %device: tryck på %icon och därefter <strong>Lägg till på hemskärmen</strong>.", | |
| th_th: "ติดตั้งเว็บà¹à¸à¸žà¸¯ นี้บน %device ขà¸à¸‡à¸„ุณ: à¹à¸•ะ %icon à¹à¸¥à¸° <strong>เพิ่มที่หน้าจà¸à¹‚ฮม</strong>", | |
| tr_tr: "Bu uygulamayı %device'a eklemek için %icon simgesine sonrasında <strong>Ana Ekrana Ekle</strong> düğmesine basın.", | |
| uk_ua: "Ð’Ñтановіть цей веб Ñайт на Ваш %device: натиÑніть %icon, а потім <strong>Ðа початковий екран</strong>.", | |
| zh_cn: "您å¯ä»¥å°†æ¤åº”用安装到您的 %device 上。请按 %icon ç„¶åŽé€‰æ‹©<strong>æ·»åŠ è‡³ä¸»å±å¹•</strong>。", | |
| zh_tw: "您å¯ä»¥å°‡æ¤æ‡‰ç”¨ç¨‹å¼å®‰è£åˆ°æ‚¨çš„ %device 上。請按 %icon 然後點é¸<strong>åŠ å…¥ä¸»ç•«é¢èž¢å¹•</strong>。" | |
| }; | |
| function init() { | |
| if (!isIDevice) return; | |
| var now = Date.now(), | |
| i; | |
| if (w.addToHomeConfig) { | |
| for (i in w.addToHomeConfig) { | |
| options[i] = w.addToHomeConfig[i] | |
| } | |
| } | |
| if (!options.autostart) options.hookOnLoad = false; | |
| isIPad = /ipad/gi.test(nav.platform); | |
| isRetina = w.devicePixelRatio && w.devicePixelRatio > 1; | |
| isSafari = /Safari/i.test(nav.appVersion) && !/CriOS/i.test(nav.appVersion); | |
| isStandalone = nav.standalone; | |
| OSVersion = nav.appVersion.match(/OS (\d+_\d+)/i); | |
| OSVersion = OSVersion && OSVersion[1] ? +OSVersion[1].replace("_", ".") : 0; | |
| lastVisit = +w.localStorage.getItem("addToHome"); | |
| isSessionActive = w.sessionStorage.getItem("addToHomeSession"); | |
| isReturningVisitor = options.returningVisitor ? lastVisit && lastVisit + 28 * 24 * 60 * 60 * 1e3 > now : true; | |
| if (!lastVisit) lastVisit = now; | |
| isExpired = isReturningVisitor && lastVisit <= now; | |
| if (options.hookOnLoad) w.addEventListener("load", loaded, false); | |
| else if (!options.hookOnLoad && options.autostart) loaded() | |
| } | |
| function loaded() { | |
| w.removeEventListener("load", loaded, false); | |
| if (!isReturningVisitor) w.localStorage.setItem("addToHome", Date.now()); | |
| else if (options.expire && isExpired) w.localStorage.setItem("addToHome", Date.now() + options.expire * 6e4); | |
| if (!overrideChecks && (!isSafari || !isExpired || isSessionActive || isStandalone || !isReturningVisitor)) return; | |
| var touchIcon = "", | |
| platform = nav.platform.split(" ")[0], | |
| language = nav.language.replace("-", "_"); | |
| balloon = document.createElement("div"); | |
| balloon.id = "addToHomeScreen"; | |
| balloon.style.cssText += "left:-9999px;-webkit-transition-property:-webkit-transform,opacity;-webkit-transition-duration:0;-webkit-transform:translate3d(0,0,0);position:" + (OSVersion < 5 ? "absolute" : "fixed"); | |
| if (options.message in intl) { | |
| language = options.message; | |
| options.message = "" | |
| } | |
| if (options.message === "") { | |
| options.message = language in intl ? intl[language] : intl["en_us"] | |
| } | |
| if (options.touchIcon) { | |
| touchIcon = isRetina ? document.querySelector('head link[rel^=apple-touch-icon][sizes="114x114"],head link[rel^=apple-touch-icon][sizes="144x144"],head link[rel^=apple-touch-icon]') : document.querySelector('head link[rel^=apple-touch-icon][sizes="57x57"],head link[rel^=apple-touch-icon]'); | |
| if (touchIcon) { | |
| touchIcon = '<span style="background-image:url(' + touchIcon.href + ')" class="addToHomeTouchIcon"></span>' | |
| } | |
| } | |
| balloon.className = (OSVersion >= 7 ? "addToHomeIOS7 " : "") + (isIPad ? "addToHomeIpad" : "addToHomeIphone") + (touchIcon ? " addToHomeWide" : ""); | |
| balloon.innerHTML = touchIcon + options.message.replace("%device", platform).replace("%icon", OSVersion >= 4.2 ? '<span class="addToHomeShare"></span>' : '<span class="addToHomePlus">+</span>') + (options.arrow ? '<span class="addToHomeArrow"' + (OSVersion >= 7 && isIPad && touchIcon ? ' style="margin-left:-32px"' : "") + "></span>" : "") + (options.closeButton ? '<span class="addToHomeClose">×</span>' : ""); | |
| document.body.appendChild(balloon); | |
| if (options.closeButton) { | |
| balloon.addEventListener("click", clicked, false); | |
| balloon.querySelector(".addToHomeClose").addEventListener("touchstart", close, false) | |
| } | |
| if (!isIPad && OSVersion >= 6) window.addEventListener("orientationchange", orientationCheck, false); | |
| setTimeout(show, options.startDelay) | |
| } | |
| function show() { | |
| var duration, iPadXShift = 208; | |
| if (isIPad) { | |
| if (OSVersion < 5) { | |
| startY = w.scrollY; | |
| startX = w.scrollX | |
| } else if (OSVersion < 6) { | |
| iPadXShift = 160 | |
| } else if (OSVersion >= 7) { | |
| iPadXShift = 143 | |
| } | |
| balloon.style.top = startY + options.bottomOffset + "px"; | |
| balloon.style.left = Math.max(startX + iPadXShift - Math.round(balloon.offsetWidth / 2), 9) + "px"; | |
| switch (options.animationIn) { | |
| case "drop": | |
| duration = "0.6s"; | |
| balloon.style.webkitTransform = "translate3d(0," + -(w.scrollY + options.bottomOffset + balloon.offsetHeight) + "px,0)"; | |
| break; | |
| case "bubble": | |
| duration = "0.6s"; | |
| balloon.style.opacity = "0"; | |
| balloon.style.webkitTransform = "translate3d(0," + (startY + 50) + "px,0)"; | |
| break; | |
| default: | |
| duration = "1s"; | |
| balloon.style.opacity = "0" | |
| } | |
| } else { | |
| startY = w.innerHeight + w.scrollY; | |
| if (OSVersion < 5) { | |
| startX = Math.round((w.innerWidth - balloon.offsetWidth) / 2) + w.scrollX; | |
| balloon.style.left = startX + "px"; | |
| balloon.style.top = startY - balloon.offsetHeight - options.bottomOffset + "px" | |
| } else { | |
| balloon.style.left = "50%"; | |
| balloon.style.marginLeft = -Math.round(balloon.offsetWidth / 2) - (w.orientation % 180 && OSVersion >= 6 && OSVersion < 7 ? 40 : 0) + "px"; | |
| balloon.style.bottom = options.bottomOffset + "px" | |
| } | |
| switch (options.animationIn) { | |
| case "drop": | |
| duration = "1s"; | |
| balloon.style.webkitTransform = "translate3d(0," + -(startY + options.bottomOffset) + "px,0)"; | |
| break; | |
| case "bubble": | |
| duration = "0.6s"; | |
| balloon.style.webkitTransform = "translate3d(0," + (balloon.offsetHeight + options.bottomOffset + 50) + "px,0)"; | |
| break; | |
| default: | |
| duration = "1s"; | |
| balloon.style.opacity = "0" | |
| } | |
| } | |
| balloon.offsetHeight; | |
| balloon.style.webkitTransitionDuration = duration; | |
| balloon.style.opacity = "1"; | |
| balloon.style.webkitTransform = "translate3d(0,0,0)"; | |
| balloon.addEventListener("webkitTransitionEnd", transitionEnd, false); | |
| closeTimeout = setTimeout(close, options.lifespan) | |
| } | |
| function manualShow(override) { | |
| if (!isIDevice || balloon) return; | |
| overrideChecks = override; | |
| loaded() | |
| } | |
| function close() { | |
| clearInterval(positionInterval); | |
| clearTimeout(closeTimeout); | |
| closeTimeout = null; | |
| if (!balloon) return; | |
| var posY = 0, | |
| posX = 0, | |
| opacity = "1", | |
| duration = "0"; | |
| if (options.closeButton) balloon.removeEventListener("click", clicked, false); | |
| if (!isIPad && OSVersion >= 6) window.removeEventListener("orientationchange", orientationCheck, false); | |
| if (OSVersion < 5) { | |
| posY = isIPad ? w.scrollY - startY : w.scrollY + w.innerHeight - startY; | |
| posX = isIPad ? w.scrollX - startX : w.scrollX + Math.round((w.innerWidth - balloon.offsetWidth) / 2) - startX | |
| } | |
| balloon.style.webkitTransitionProperty = "-webkit-transform,opacity"; | |
| switch (options.animationOut) { | |
| case "drop": | |
| if (isIPad) { | |
| duration = "0.4s"; | |
| opacity = "0"; | |
| posY += 50 | |
| } else { | |
| duration = "0.6s"; | |
| posY += balloon.offsetHeight + options.bottomOffset + 50 | |
| } | |
| break; | |
| case "bubble": | |
| if (isIPad) { | |
| duration = "0.8s"; | |
| posY -= balloon.offsetHeight + options.bottomOffset + 50 | |
| } else { | |
| duration = "0.4s"; | |
| opacity = "0"; | |
| posY -= 50 | |
| } | |
| break; | |
| default: | |
| duration = "0.8s"; | |
| opacity = "0" | |
| } | |
| balloon.addEventListener("webkitTransitionEnd", transitionEnd, false); | |
| balloon.style.opacity = opacity; | |
| balloon.style.webkitTransitionDuration = duration; | |
| balloon.style.webkitTransform = "translate3d(" + posX + "px," + posY + "px,0)" | |
| } | |
| function clicked() { | |
| w.sessionStorage.setItem("addToHomeSession", "1"); | |
| isSessionActive = true; | |
| close() | |
| } | |
| function transitionEnd() { | |
| balloon.removeEventListener("webkitTransitionEnd", transitionEnd, false); | |
| balloon.style.webkitTransitionProperty = "-webkit-transform"; | |
| balloon.style.webkitTransitionDuration = "0.2s"; | |
| if (!closeTimeout) { | |
| balloon.parentNode.removeChild(balloon); | |
| balloon = null; | |
| return | |
| } | |
| if (OSVersion < 5 && closeTimeout) positionInterval = setInterval(setPosition, options.iterations) | |
| } | |
| function setPosition() { | |
| var matrix = new WebKitCSSMatrix(w.getComputedStyle(balloon, null).webkitTransform), | |
| posY = isIPad ? w.scrollY - startY : w.scrollY + w.innerHeight - startY, | |
| posX = isIPad ? w.scrollX - startX : w.scrollX + Math.round((w.innerWidth - balloon.offsetWidth) / 2) - startX; | |
| if (posY == matrix.m42 && posX == matrix.m41) return; | |
| balloon.style.webkitTransform = "translate3d(" + posX + "px," + posY + "px,0)" | |
| } | |
| function reset() { | |
| w.localStorage.removeItem("addToHome"); | |
| w.sessionStorage.removeItem("addToHomeSession") | |
| } | |
| function orientationCheck() { | |
| balloon.style.marginLeft = -Math.round(balloon.offsetWidth / 2) - (w.orientation % 180 && OSVersion >= 6 && OSVersion < 7 ? 40 : 0) + "px" | |
| } | |
| init(); | |
| return { | |
| show: manualShow, | |
| close: close, | |
| reset: reset | |
| } | |
| }(window); | |
| (function() { | |
| if (!P.cocoon) { | |
| (function(i, s, o, g, r, a, m) { | |
| i["GoogleAnalyticsObject"] = r; | |
| i[r] = i[r] || function() { | |
| (i[r].q = i[r].q || []).push(arguments) | |
| }, i[r].l = 1 * new Date; | |
| a = s.createElement(o), m = s.getElementsByTagName(o)[0]; | |
| a.async = 1; | |
| a.src = g; | |
| m.parentNode.insertBefore(a, m) | |
| })(window, document, "script", "//www.google-analytics.com/analytics.js", "ga") | |
| } else if (!window.cordova) { | |
| var interfaceReady = false; | |
| var queue = []; | |
| var flushQueue = function() { | |
| var cmd; | |
| while (cmd = queue.shift()) { | |
| forwardCmd(cmd) | |
| } | |
| }; | |
| var forwardCmd = function(cmd) { | |
| console.log("Sending " + cmd + " to the Webview"); | |
| CocoonJS.App.forwardAsync(cmd) | |
| }; | |
| var addToQueue = function(cmd) { | |
| queue.push(cmd); | |
| if (interfaceReady) { | |
| flushQueue() | |
| } | |
| }; | |
| window.gaInterfaceIsReady = function() { | |
| CocoonJS.App.forwardAsync("CocoonJS.App.show(0, 0, " + window.innerWidth * window.devicePixelRatio + "," + window.innerHeight * window.devicePixelRatio + ");"); | |
| interfaceReady = true; | |
| flushQueue() | |
| }; | |
| console.log("Creating GAI interface"); | |
| CocoonJS.App.loadInTheWebView("http://more.gamemix.com/cocoonoverlay.html?currentGame=donttap"); | |
| window.ga = function() { | |
| var args = ""; | |
| for (var i = 0; i < arguments.length; i++) { | |
| if (i > 0) { | |
| args += "," | |
| } | |
| args += JSON.stringify(arguments[i]) | |
| } | |
| var cmd = "window.ga(" + args + ")"; | |
| addToQueue(cmd) | |
| } | |
| } | |
| ga("require", "displayfeatures"); | |
| ga("create", "UA-50290430-1"); | |
| (function(g, m, c, d, a) { | |
| g["GameMixGA"] = a; | |
| g[a] = g[a] || function(f) { | |
| g[a].q = g[a].q || []; | |
| g[a].q.push(f) | |
| }; | |
| g[a]({ | |
| gmgaDomain: d | |
| }); | |
| var s = m.createElement(c), | |
| p = m.getElementsByTagName(c)[0]; | |
| s.type = "text/javascript"; | |
| s.async = true; | |
| s.src = d + "/client/gmga.js"; | |
| p.parentNode.insertBefore(s, p) | |
| })(window, document, "script", "http://gmga.gamemix.com", "gmga"); | |
| gmga("donttap") | |
| })() | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment