diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..8f96039 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +# editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/.gitignore b/.gitignore index e43b0f9..3d72576 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .DS_Store +.idea \ No newline at end of file diff --git a/README.md b/README.md index d38fbed..3acae25 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ CboxLauncher ============ -Cbox의 기본이 되는 Launcher 입니다. \ No newline at end of file +Cbox의 기본이 되는 Launcher 입니다. +# Prototype버전이며, v0.2로 다시 뵙겠습니다. \ No newline at end of file diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 3d2bca1..eba498d 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1,29 +1,29 @@ -{ - "prompt_for_name": { - "message": "What's your name?", - "description": "Ask for the user's name" - }, - "hello": { - "message": "Hello, $USER$", - "description": "Greet the user", - "placeholders": { - "user": { - "content": "$1", - "example": "Cira" - } - } - }, - "bye": { - "message": "Goodbye, $USER$. Come back to $OUR_SITE$ soon!", - "description": "Say goodbye to the user", - "placeholders": { - "our_site": { - "content": "Example.com" - }, - "user": { - "content": "$1", - "example": "Cira" - } - } - } +{ + "prompt_for_name": { + "message": "What's your name?", + "description": "Ask for the user's name" + }, + "hello": { + "message": "Hello, $USER$", + "description": "Greet the user", + "placeholders": { + "user": { + "content": "$1", + "example": "Cira" + } + } + }, + "bye": { + "message": "Goodbye, $USER$. Come back to $OUR_SITE$ soon!", + "description": "Say goodbye to the user", + "placeholders": { + "our_site": { + "content": "Example.com" + }, + "user": { + "content": "$1", + "example": "Cira" + } + } + } } \ No newline at end of file diff --git a/_locales/ko/messages.json b/_locales/ko/messages.json index 3d2bca1..f0ec740 100644 --- a/_locales/ko/messages.json +++ b/_locales/ko/messages.json @@ -1,29 +1,29 @@ -{ - "prompt_for_name": { - "message": "What's your name?", - "description": "Ask for the user's name" - }, - "hello": { - "message": "Hello, $USER$", - "description": "Greet the user", - "placeholders": { - "user": { - "content": "$1", - "example": "Cira" - } - } - }, - "bye": { - "message": "Goodbye, $USER$. Come back to $OUR_SITE$ soon!", - "description": "Say goodbye to the user", - "placeholders": { - "our_site": { - "content": "Example.com" - }, - "user": { - "content": "$1", - "example": "Cira" - } - } - } +images{ + "prompt_for_name": { + "message": "What's your name?", + "description": "Ask for the user's name" + }, + "hello": { + "message": "Hello, $USER$", + "description": "Greet the user", + "placeholders": { + "user": { + "content": "$1", + "example": "Cira" + } + } + }, + "bye": { + "message": "Goodbye, $USER$. Come back to $OUR_SITE$ soon!", + "description": "Say goodbye to the user", + "placeholders": { + "our_site": { + "content": "Example.com" + }, + "user": { + "content": "$1", + "example": "Cira" + } + } + } } \ No newline at end of file diff --git a/games/breakout.jpg b/games/breakout.jpg deleted file mode 100644 index fe24698..0000000 Binary files a/games/breakout.jpg and /dev/null differ diff --git a/games/breakout.png b/games/breakout.png new file mode 100644 index 0000000..65b0a73 Binary files /dev/null and b/games/breakout.png differ diff --git a/games/cboxtech.png b/games/cboxtech.png new file mode 100644 index 0000000..4c3ecab Binary files /dev/null and b/games/cboxtech.png differ diff --git a/games/cboxtest.png b/games/cboxtest.png new file mode 100644 index 0000000..4ee64e5 Binary files /dev/null and b/games/cboxtest.png differ diff --git a/games/dkingkong.jpg b/games/dkingkong.jpg deleted file mode 100644 index bbcef9e..0000000 Binary files a/games/dkingkong.jpg and /dev/null differ diff --git a/games/garaga.gif b/games/garaga.gif deleted file mode 100644 index 61989c0..0000000 Binary files a/games/garaga.gif and /dev/null differ diff --git a/games/padv.jpg b/games/padv.jpg deleted file mode 100644 index 88d12ab..0000000 Binary files a/games/padv.jpg and /dev/null differ diff --git a/games/penguin-adv.png b/games/penguin-adv.png new file mode 100644 index 0000000..ad9dfca Binary files /dev/null and b/games/penguin-adv.png differ diff --git a/games/ramface.jpg b/games/ramface.jpg deleted file mode 100644 index ae09ec3..0000000 Binary files a/games/ramface.jpg and /dev/null differ diff --git a/games/smario.jpg b/games/smario.jpg deleted file mode 100644 index 8c1a128..0000000 Binary files a/games/smario.jpg and /dev/null differ diff --git a/games/sugarpang.png b/games/sugarpang.png new file mode 100644 index 0000000..7060211 Binary files /dev/null and b/games/sugarpang.png differ diff --git a/images/android-256.png b/images/android-256.png new file mode 100755 index 0000000..c475926 Binary files /dev/null and b/images/android-256.png differ diff --git a/main.html b/main.html index d6ccc89..98500ed 100644 --- a/main.html +++ b/main.html @@ -7,23 +7,22 @@ + + + - -
-
-
Connect Game Controllers
- -
- Click button for connecting controllers. -

-
-
+
+
diff --git a/manifest.json b/manifest.json index 76a9612..748d43f 100644 --- a/manifest.json +++ b/manifest.json @@ -17,8 +17,32 @@ "128": "chrome-grey-128.png" } }, + "permissions": [ + "tabs", "http://*/*","https://*/*" + ], "update_url" : "http://localhost:8888/", "background": { - "scripts": ["static/background.js"] - } + "scripts": ["static/background.js"] + }, + "content_scripts": [ + { + "matches": [""], + "run_at": "document_start", + "js": ["static/jquery.js", + "static/libs/collie.min.js", + "static/libs/cocos2d.js", + "static/libs/ranking.js" + ], + "all_frames":true + }, + { + "matches": [""], + "run_at": "document_end", + "js": [ + "static/pubsub.js", + "static/cbox.controller.js" + ], + "all_frames":true + } + ] } diff --git a/sounds/slide.mp3 b/sounds/slide.mp3 new file mode 100644 index 0000000..9b4fa50 Binary files /dev/null and b/sounds/slide.mp3 differ diff --git a/static/backbone.tv.keyevent.js b/static/backbone.tv.keyevent.js index 6cb2e63..4f57c93 100644 --- a/static/backbone.tv.keyevent.js +++ b/static/backbone.tv.keyevent.js @@ -107,8 +107,7 @@ }, trigger: function(keyevent) { // the events can handle that occurred at body element only. - if (!(keyevent.srcElement instanceof HTMLBodyElement)) return this; - + // if (!(keyevent.srcElement instanceof HTMLBodyElement)) return this; var r = KeyEventListener.responder() , events = KeyEventListener._hotkeys[keyevent.which]; @@ -125,7 +124,7 @@ on: function(events, callback, context) { var keyEvents = this.keyEvents || (this.keyEvents = {}) , hotKeyEvents = KeyEventListener._hotkeys || (KeyEventListener._hotkeys = {}) - , event; + , event; events = events.split(/\s+/); while (event = events.shift()) { @@ -162,8 +161,53 @@ $(document).ready(function() { // register key event. - document.body.addEventListener('keyup', Backbone.KeyEventListener.trigger); - document.body.addEventListener('keydown', Backbone.KeyEventListener.trigger); + + var debug = false; + if (debug) { + document.body.addEventListener('keyup', Backbone.KeyEventListener.trigger); + document.body.addEventListener('keydown', Backbone.KeyEventListener.trigger); + } + + cbox.previousEvent = { + pX1: 0, + pY1: 0 + } + + cbox.addEventListener(function(event, context, cbox) { + if (event.type != 'Down') return; + + var keycode = undefined; + if (cbox.previousEvent.pX1 < event.pX1) + keycode = 39; + else if (cbox.previousEvent.pX1 > event.pX1) + keycode = 37; + if (cbox.previousEvent.pY1 < event.pY1) + keycode = 40; + else if (cbox.previousEvent.pY1 > event.pY1) + keycode = 38; + else if (event.btnA) + keycode = 13; + else if (event.btnB) + keycode = 27; + + // hard copy events + cbox.previousEvent.pX1 = event.pX1; + cbox.previousEvent.pY1 = event.pY1; + cbox.previousEvent.type = event.type; + + if (keycode) { + var ke = document.createEvent("KeyboardEvent"); + // Chromium Hack, http://goo.gl/QNwqH + Object.defineProperty(ke, 'keyCode', {get : function() {return this.keyCodeVal;}}); + Object.defineProperty(ke, 'which', {get : function() {return this.keyCodeVal;}}); + + ke.initKeyboardEvent(event.type == 'Down' ? 'keydown' : 'keyup', + true, true, null, false, false, false, false, keycode, keycode); + ke.keyCodeVal = keycode; + + Backbone.KeyEventListener.trigger(ke); + } + }); }); diff --git a/static/cbox.controller.js b/static/cbox.controller.js new file mode 100644 index 0000000..304b80d --- /dev/null +++ b/static/cbox.controller.js @@ -0,0 +1,17 @@ +/** + * Created with PyCharm. + * User: songhun + * Date: 11/8/12 + * Time: 3:37 PM + * To change this template use File | Settings | File Templates. + */ + + +var gameScript = $("#cboxscript").html(); +eval(gameScript); + +$(function(){ + pubsub.sub("controlls",function(msg){ + cboxgame.fireEvent(msg.data); + }); +}); diff --git a/static/cbox.css b/static/cbox.css index e433dbd..c64f3e6 100644 --- a/static/cbox.css +++ b/static/cbox.css @@ -1,107 +1,116 @@ +/* GLOBAL */ + html { - background-image: url(../images/chrome-grey-128.png), url(../images/cbox-bg-01.png); - background-position: left top, center center; + background-image: url(../images/cbox-bg-01.png); + background-position: center center; background-repeat: no-repeat; background-attachment: fixed; - background-size: 32px 32px, cover; + background-size: cover; } body { width: 100%; height: 100%; overflow: hidden; + margin:0; + padding: 0; } +/* HOME SCREEN AND SLIDERS */ + .homescreen { position: absolute; left: 50%; top: 50%; - width:1036px; - height:374px; - margin-left:-530px; - margin-top:-187px; - - /*border: 1px solid black;*/ + width:1024px; + height:648px; + margin-left:-512px; + margin-top:-324px; } -.homescreen .side .box.focus { - -webkit-transform: scale(1.05); - border: 2px solid white; +#android { + position: absolute; + background-image: url(../images/android-256.png); + background-position: center, center; + background-repeat: no-repeat; + background-size: 100%; + width:200px; + height:200px; + z-index: 20000; + margin-top: 46%; + left:-37px; } -.homescreen .box { - height:187px; - background-color: black; - background-repeat:no-repeat; - background-clip:content-box; - background-position:center; - background-size: contain; +#sliderview { + width:100%; + height:100%; + padding-left: 0px; } -.homescreen .box .titlebar { - width:262px; - height:30px; - background-color: white; - color: #bc8f8f; - font-size: 18pt; +#sliderview .slider:nth-child(1) { + -webkit-transform: scale(1); + z-index: 9999; + margin-top:-123px; } -.homescreen .box#center .titlebar { - position: absolute; - top: 348px; - width:500px; +#sliderview .slider:nth-child(2) { + -webkit-transform: scale(0.84); + z-index: 9998; + /* var w = 396, nth=2;(w * (nth - 1)) - ((w * 0.1608) * valocity) */ + left:300px; } -.homescreen .box#center { - float: left; - height:378px; - width: 500px; - margin-right: 4px; - border:2px solid rgba(0,0,0,0); - background-position: 0 0px; - background-size: 2500px 378px; +#sliderview .slider:nth-child(3) { + -webkit-transform: scale(0.68); + z-index: 9997; + /* valocity is 5 */ + left:505px; } -.homescreen .box#center.focus { - border:2px solid rgba(0,0,0,0.6); - - /* @HOLD - -webkit-animation:slide 8s; - -webkit-animation-iteration-count: infinite; - -webkit-animation-timing-function:erase-out; - -webkit-animation-delay: 1s; - */ +#sliderview .slider:nth-child(4) { + -webkit-transform: scale(0.52); + z-index: 9996; + /* valocity is 9 */ + left:617px; } -@-webkit-keyframes slide -{ - 0% {background-position: 0 0px;} - 25% {background-position: -500px 0px;} - 50% {background-position: -1000px 0px;} - 75% {background-position: -1500px 0px;} - 100% {background-position: -2000px 0px;} +#sliderview .slider:nth-child(5) { + -webkit-transform: scale(0.36); + z-index: 9995; + /* valocity is 14 */ + left: 692px; } -.homescreen .side { - width:262px; - float: left; -} -.homescreen .side:first-child { - margin-right: 4px; +.slider { + position: relative; + width:396px; + height:246px; + top: 50%; + margin-top: -25%; + margin-left: 62px; + background-position: center, center; + background-repeat: no-repeat; + background-size: 100% 100%; + -webkit-transition: left 300ms ease-out; } -.homescreen .side .box { - margin-bottom: 4px; +.slider .banner { + display: inline-block; + width: 100%; + height:100%; } -.shadow { - position: absolute; - bottom: -80px; - width:100%; - height:20px; - background: -webkit-radial-gradient(center, ellipse cover, rgba(10,10,10,0.5) 1%, rgba(255,255,255,0) 100%); + +.slider .reflect { + position: relative; + top:-4px; + width:396px; + height: 48px; } + +/* GAME LAUNCHER AND SANDBOX */ + .game-launcher { z-index: 99999; width: 100%; @@ -117,16 +126,13 @@ body { height: 100%; position: absolute; left: 0; - top: 0; + top: 0; } +/* OSX MODAL, OVERRAY AND CONTAINER */ #osx-modal-content {display:none;} - -/* Overlay */ #osx-overlay {background-color:#000; cursor:wait;} - -/* Container */ -#osx-container {background-color:#eee; color:#000; font: 16px/24px "Lucida Grande",Arial,sans-serif; padding-bottom:4px; width:600px; -moz-border-radius-bottomleft:6px; -webkit-border-bottom-left-radius:6px; -moz-border-radius-bottomright:6px; -webkit-border-bottom-right-radius:6px; border-radius:0 0 6px 6px; -moz-box-shadow:0 0 64px #000; -webkit-box-shadow:0 0 64px #000; box-shadow:0 0 64px #000;} +#osx-container {position: absolute; background-color:#eee; color:#000; margin: 0 auto; font: 16px/24px "Lucida Grande",Arial,sans-serif; padding-bottom:4px; width:600px; -moz-border-radius-bottomleft:6px; -webkit-border-bottom-left-radius:6px; -moz-border-radius-bottomright:6px; -webkit-border-bottom-right-radius:6px; border-radius:0 0 6px 6px; -moz-box-shadow:0 0 64px #000; -webkit-box-shadow:0 0 64px #000; box-shadow:0 0 64px #000;} #osx-container a {color:#ddd;} #osx-container #osx-modal-title {color:#000; background-color:#ddd; border-bottom:1px solid #ccc; font-weight:bold; padding:6px 8px; text-shadow:0 1px 0 #f4f4f4;} #osx-container .close {display:none; position:absolute; right:0; top:0;} @@ -135,4 +141,4 @@ body { #osx-container #osx-modal-data {font-size:12px; padding:6px 12px;} #osx-container h2 {margin:10px 0 6px;} #osx-container p {margin-bottom:10px;} -#osx-container span {color:#777;} \ No newline at end of file +#osx-container span {color:#777;} diff --git a/static/cbox.sdk.js b/static/cbox.sdk.js index b55c32e..53fc944 100644 --- a/static/cbox.sdk.js +++ b/static/cbox.sdk.js @@ -1,298 +1,614 @@ -/** - * Created with PyCharm. - * User: songhun - * Date: 10/27/12 - * Time: 3:12 PM - * To change this template use File | Settings | File Templates. - */ - -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Javascript module pattern: -// see http://en.wikipedia.org/wiki/Unobtrusive_JavaScript#Namespaces -// In essence, we define an anonymous function which is immediately called and -// returns a new object. The new object contains only the exported definitions; -// all other definitions in the anonymous function are inaccessible to external -// code. -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Javascript module pattern: -// see http://en.wikipedia.org/wiki/Unobtrusive_JavaScript#Namespaces -// In essence, we define an anonymous function which is immediately called and -// returns a new object. The new object contains only the exported definitions; -// all other definitions in the anonymous function are inaccessible to external -// code. -var common = (function () { - - /** - * Create the Native Client element as a child of the DOM element - * named "listener". - * - * @param {string} name The name of the example. - * @param {string} tool The name of the toolchain, e.g. "glibc", "newlib" etc. - * @param {string} config The name of the configruation, "Debug" or "Release" - * @param {number} width The width to create the plugin. - * @param {number} height The height to create the plugin. - */ - function createNaClModule(name, tool, config, width, height) { - var moduleEl = document.createElement('embed'); - moduleEl.setAttribute('name', 'nacl_module'); - moduleEl.setAttribute('id', 'nacl_module'); - moduleEl.setAttribute('width', width); - moduleEl.setAttribute('height',height); - moduleEl.setAttribute('src', tool + '/' + config + '/' + name + '.nmf'); - moduleEl.setAttribute('type', 'application/x-nacl'); - if (tool == 'win' || tool == 'linux' || tool == 'mac') { - mimetype = 'application/x-ppapi-' + config.toLowerCase(); - moduleEl.setAttribute('type', mimetype); - } - - // The element is wrapped inside a
, which has both a 'load' - // and a 'message' event listener attached. This wrapping method is used - // instead of attaching the event listeners directly to the element - // to ensure that the listeners are active before the NaCl module 'load' - // event fires. - var listenerDiv = document.getElementById('listener'); - console.log(listenerDiv, moduleEl); - listenerDiv.appendChild(moduleEl); - } - - /** Add the default "load" and "message" event listeners to the element with - * id "listener". - * - * The "load" event is sent when the module is successfully loaded. The - * "message" event is sent when the naclModule posts a message using - * PPB_Messaging.PostMessage() (in C) or pp::Instance().PostMessage() (in - * C++). - */ - function attachDefaultListeners() { - var listenerDiv = document.getElementById('listener'); - listenerDiv.addEventListener('load', moduleDidLoad, true); - listenerDiv.addEventListener('message', handleMessage, true); - - if (typeof window.attachListeners !== 'undefined') { - window.attachListeners(); - } - } - - /** - * Called when the NaCl module is loaded. - * - * This event listener is registered in createNaClModule above. - */ - function moduleDidLoad() { - common.naclModule = document.getElementById('nacl_module'); - updateStatus('SUCCESS'); - - if (typeof window.moduleDidLoad !== 'undefined') { - window.moduleDidLoad(); - } - } - - /** - * Hide the NaCl module's embed element. - * - * We don't want to hide by default; if we do, it is harder to determine that - * a plugin failed to load. Instead, call this function inside the example's - * "moduleDidLoad" function. - * - */ - function hideModule() { - // Setting common.naclModule.style.display = "None" doesn't work; the - // module will no longer be able to receive postMessages. - common.naclModule.style.height = "0"; - } - - /** - * Return true when |s| starts with the string |prefix|. - * - * @param {string} s The string to search. - * @param {string} prefix The prefix to search for in |s|. - */ - function startsWith(s, prefix) { - // indexOf would search the entire string, lastIndexOf(p, 0) only checks at - // the first index. See: http://stackoverflow.com/a/4579228 - return s.lastIndexOf(prefix, 0) === 0; - } - - /** - * Add a message to an element with id "log", separated by a
element. - * - * This function is used by the default "log:" message handler. - * - * @param {string} message The message to log. - */ - function logMessage(message) { - var logEl = document.getElementById('log'); - logEl.innerHTML += message + '
'; - console.log(message) - } - - /** - */ - var defaultMessageTypes = { - 'alert': alert, - 'log': logMessage - }; - - /** - * Called when the NaCl module sends a message to JavaScript (via - * PPB_Messaging.PostMessage()) - * - * This event listener is registered in createNaClModule above. - * - * @param {Event} message_event A message event. message_event.data contains - * the data sent from the NaCl module. - */ - function handleMessage(message_event) { - if (typeof message_event.data === 'string') { - for (var type in defaultMessageTypes) { - if (defaultMessageTypes.hasOwnProperty(type)) { - if (startsWith(message_event.data, type + ':')) { - func = defaultMessageTypes[type]; - func(message_event.data.slice(type.length + 1)); - } - } - } - } - - if (typeof window.handleMessage !== 'undefined') { - window.handleMessage(message_event); - } - } - - /** - * Called when the DOM content has loaded; i.e. the page's document is fully - * parsed. At this point, we can safely query any elements in the document via - * document.querySelector, document.getElementById, etc. - * - * @param {string} name The name of the example. - * @param {string} tool The name of the toolchain, e.g. "glibc", "newlib" etc. - * @param {string} config The name of the configuration, e.g. "Release", etc. - * @param {number} width The width to create the plugin. - * @param {number} height The height to create the plugin. - */ - function domContentLoaded(name, tool, config, width, height) { - // If the page loads before the Native Client module loads, then set the - // status message indicating that the module is still loading. Otherwise, - // do not change the status message. - updateStatus('Page loaded.'); - if (common.naclModule == null) { - updateStatus('Creating embed: ' + tool) - - // We use a non-zero sized embed to give Chrome space to place the bad - // plug-in graphic, if there is a problem. - width = typeof width !== 'undefined' ? width : 200; - height = typeof height !== 'undefined' ? height : 200; - attachDefaultListeners(); - createNaClModule(name, tool, config, width, height); - } else { - // It's possible that the Native Client module onload event fired - // before the page's onload event. In this case, the status message - // will reflect 'SUCCESS', but won't be displayed. This call will - // display the current message. - updateStatus('Waiting.'); - } - } - - /** Saved text to display in the element with id 'statusField'. */ - var statusText = 'NO-STATUSES'; - - /** - * Set the global status message. If the element with id 'statusField' - * exists, then set its HTML to the status message as well. - * - * @param {string} opt_message The message to set. If null or undefined, then - * set element 'statusField' to the message from the last call to - * updateStatus. - */ - function updateStatus(opt_message) { - console.log(opt_message); - } - - // The symbols to export. - return { - /** A reference to the NaCl module, once it is loaded. */ - naclModule: null, - - attachDefaultListeners: attachDefaultListeners, - domContentLoaded: domContentLoaded, - createNaClModule: createNaClModule, - hideModule: hideModule, - updateStatus: updateStatus - }; - -}()); - - -// Listen for the DOM content to be loaded. This event is fired when parsing of -// the page's document has finished. -document.addEventListener('DOMContentLoaded', function() { - var body = document.querySelector('body'); - var loadFunction = common.domContentLoaded; - - if (loadFunction) { - loadFunction("cbox_sdk", "static", "cbox_sdk", - 120, 30); - - } -}); - - - -jQuery(function ($) { - - var CBOX_SDK_focusIn = function(){ - //TODO : Hide Layer - }; - var CBOX_SDK_focusOut = function(){ - //TODO : Show Connect Layer - }; - - var CBOX_SDK_keyboard = function(){ - //TODO : Connect Here for Keyboard Events - console.log(arguments); - }; - var CBOX_SDK_gamepad : function(){ - //TODO : Connect Here for Gamepad Events - console.log(arguments); - }; - var CBOX_SDK_nunchuk : function(){ - //TODO : Connect Here for Nunchuk Events - console.log(arguments); - }; - - var _defaultFuncs = { - "CBOX_SDK_focusIn" : CBOX_SDK_focusIn, - "CBOX_SDK_focusOut" : CBOX_SDK_focusOut, - "CBOX_SDK_keyboard" : CBOX_SDK_keyboard, - "CBOX_SDK_gamepad" : CBOX_SDK_gamepad, - "CBOX_SDK_nunchuk" : CBOX_SDK_nunchuk - }; - - // Called by the common.js module. - window.handleMessage = function(message) { - var _order = []; - var func = function(){}; - - if (typeof message.data === 'string') { - if( message.data.indexOf("o::") == 0 ){ - _order = message.data.replace("o::","").split(":"); - func = _defaultFuncs[_order.shift()]; - if( _order.length > 1 ){ - func.apply(this||window,_order); - }else{ - func(); - } - } - } - } - - $("#osx-modal-content").fadeIn('slow'); - - -}); +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Javascript module pattern: +// see http://en.wikipedia.org/wiki/Unobtrusive_JavaScript#Namespaces +// In essence, we define an anonymous function which is immediately called and +// returns a new object. The new object contains only the exported definitions; +// all other definitions in the anonymous function are inaccessible to external +// code. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Javascript module pattern: +// see http://en.wikipedia.org/wiki/Unobtrusive_JavaScript#Namespaces +// In essence, we define an anonymous function which is immediately called and +// returns a new object. The new object contains only the exported definitions; +// all other definitions in the anonymous function are inaccessible to external +// code. +var common = (function () { + + /** + * Create the Native Client element as a child of the DOM element + * named "listener". + * + * @param {string} name The name of the example. + * @param {string} tool The name of the toolchain, e.g. "glibc", "newlib" etc. + * @param {string} config The name of the configruation, "Debug" or "Release" + * @param {number} width The width to create the plugin. + * @param {number} height The height to create the plugin. + */ + function createNaClModule(name, tool, config, width, height) { + var moduleEl = document.createElement('embed'); + moduleEl.setAttribute('name', 'nacl_module'); + moduleEl.setAttribute('id', 'nacl_module'); + moduleEl.setAttribute('width', width); + moduleEl.setAttribute('height',height); + moduleEl.setAttribute('src', tool + '/' + config + '/' + name + '.nmf'); + moduleEl.setAttribute('type', 'application/x-nacl'); + if (tool == 'win' || tool == 'linux' || tool == 'mac') { + mimetype = 'application/x-ppapi-' + config.toLowerCase(); + moduleEl.setAttribute('type', mimetype); + } + + // The element is wrapped inside a
, which has both a 'load' + // and a 'message' event listener attached. This wrapping method is used + // instead of attaching the event listeners directly to the element + // to ensure that the listeners are active before the NaCl module 'load' + // event fires. + var listenerDiv = document.getElementById('android'); + listenerDiv.appendChild(moduleEl); + } + + /** Add the default "load" and "message" event listeners to the element with + * id "listener". + * + * The "load" event is sent when the module is successfully loaded. The + * "message" event is sent when the naclModule posts a message using + * PPB_Messaging.PostMessage() (in C) or pp::Instance().PostMessage() (in + * C++). + */ + function attachDefaultListeners() { + var listenerDiv = document.getElementById('android'); + listenerDiv.addEventListener('load', moduleDidLoad, true); + listenerDiv.addEventListener('message', handleMessage, true); + + var listenerDiv2 = document.getElementById('listenerWebSocket'); + listenerDiv2.addEventListener('load', moduleDidLoad, true); + listenerDiv2.addEventListener('message', handleMessage2, true); + + + if (typeof window.attachListeners !== 'undefined') { + window.attachListeners(); + } + } + + /** + * Called when the NaCl module is loaded. + * + * This event listener is registered in createNaClModule above. + */ + function moduleDidLoad() { + common.naclModule = document.getElementById('nacl_module'); + updateStatus('SUCCESS'); + + if (typeof window.moduleDidLoad !== 'undefined') { + window.moduleDidLoad(); + } + } + + /** + * Hide the NaCl module's embed element. + * + * We don't want to hide by default; if we do, it is harder to determine that + * a plugin failed to load. Instead, call this function inside the example's + * "moduleDidLoad" function. + * + */ + function hideModule() { + // Setting common.naclModule.style.display = "None" doesn't work; the + // module will no longer be able to receive postMessages. + common.naclModule.style.height = "0"; + } + + /** + * Return true when |s| starts with the string |prefix|. + * + * @param {string} s The string to search. + * @param {string} prefix The prefix to search for in |s|. + */ + function startsWith(s, prefix) { + // indexOf would search the entire string, lastIndexOf(p, 0) only checks at + // the first index. See: http://stackoverflow.com/a/4579228 + return s.lastIndexOf(prefix, 0) === 0; + } + + /** + * Add a message to an element with id "log", separated by a
element. + * + * This function is used by the default "log:" message handler. + * + * @param {string} message The message to log. + */ + function logMessage(message) { + var logEl = document.getElementById('log'); + logEl.innerHTML += message + '
'; + console.log(message) + } + + /** + */ + var defaultMessageTypes = { + 'alert': alert, + 'log': logMessage + }; + + /** + * Called when the NaCl module sends a message to JavaScript (via + * PPB_Messaging.PostMessage()) + * + * This event listener is registered in createNaClModule above. + * + * @param {Event} message_event A message event. message_event.data contains + * the data sent from the NaCl module. + */ + function handleMessage(message_event) { + if (typeof message_event.data === 'string') { + for (var type in defaultMessageTypes) { + if (defaultMessageTypes.hasOwnProperty(type)) { + if (startsWith(message_event.data, type + ':')) { + func = defaultMessageTypes[type]; + func(message_event.data.slice(type.length + 1)); + } + } + } + } + + if (typeof window.handleMessage !== 'undefined') { + window.handleMessage(message_event); + } + } + + /** + * Called when the DOM content has loaded; i.e. the page's document is fully + * parsed. At this point, we can safely query any elements in the document via + * document.querySelector, document.getElementById, etc. + * + * @param {string} name The name of the example. + * @param {string} tool The name of the toolchain, e.g. "glibc", "newlib" etc. + * @param {string} config The name of the configuration, e.g. "Release", etc. + * @param {number} width The width to create the plugin. + * @param {number} height The height to create the plugin. + */ + function domContentLoaded(name, tool, config, width, height) { + // If the page loads before the Native Client module loads, then set the + // status message indicating that the module is still loading. Otherwise, + // do not change the status message. + updateStatus('Page loaded.'); + if (common.naclModule == null) { + updateStatus('Creating embed: ' + tool) + + // We use a non-zero sized embed to give Chrome space to place the bad + // plug-in graphic, if there is a problem. + width = typeof width !== 'undefined' ? width : 200; + height = typeof height !== 'undefined' ? height : 200; + attachDefaultListeners(); + createNaClModule(name, tool, config, width, height); + } else { + // It's possible that the Native Client module onload event fired + // before the page's onload event. In this case, the status message + // will reflect 'SUCCESS', but won't be displayed. This call will + // display the current message. + updateStatus('Waiting.'); + } + } + + /** Saved text to display in the element with id 'statusField'. */ + var statusText = 'NO-STATUSES'; + + /** + * Set the global status message. If the element with id 'statusField' + * exists, then set its HTML to the status message as well. + * + * @param {string} opt_message The message to set. If null or undefined, then + * set element 'statusField' to the message from the last call to + * updateStatus. + */ + function updateStatus(opt_message) { + console.log(opt_message); + } + + // The symbols to export. + return { + /** A reference to the NaCl module, once it is loaded. */ + naclModule: null, + + attachDefaultListeners: attachDefaultListeners, + domContentLoaded: domContentLoaded, + createNaClModule: createNaClModule, + hideModule: hideModule, + updateStatus: updateStatus + }; + +}()); + + +// Listen for the DOM content to be loaded. This event is fired when parsing of +// the page's document has finished. +document.addEventListener('DOMContentLoaded', function() { + var body = document.querySelector('body'); + var loadFunction = common.domContentLoaded; + + if (loadFunction) { + loadFunction("cbox_sdk", "static", "cbox_sdk", + 200, 200); + + } +}); + + +//기본 값 +var _nunchuck = { + joyX : 126, + joyY : 130, + accX : 76, + accY : 132, + accZ : 130, + btnC : 1, + btnZ : 1 +}; + +var updater = { + socket: null, + init : function() { + updater.socket = document.getElementById('websocket'); + updater.start(); + setTimeout(function(){ + updater.socket.postMessage('s;Start'); + },1000); + }, + start: function() { + var url = "ws://localhost:8889/gamesocket"; + + updater.socket.postMessage('o;' + url); + console.log(url); + + + }, + handleMessage: function(message_event) { + try{ + +// console.log(message_event.data); + var oData = $.parseJSON(message_event.data.replace("receive: ", "")); + //console.log(oData.aData); + nunchuck.joyX = oData.aData[0]; + nunchuck.joyY = oData.aData[1]; + nunchuck.accX = oData.aData[2]; + nunchuck.accY = oData.aData[3]; + nunchuck.accZ = oData.aData[4]; + nunchuck.btnZ = oData.aData[5]; + nunchuck.btnC = oData.aData[6]; + + if( _mode == 1 ){ + $jGameScreenIFrame[0].contentWindow._listen( nunchuck, _nunchuck); + } + + if( nunchuck.btnC == 1 ){ + if( _nunchuck.btnC == 0 ){ + // 클릭 된거임 + _nunchuck.btnC = 1; + if( _mode == 0 ){ + // 플랫폼인 경우엔 다음 게임 선택 + nextGame(); + } + } + }else{ + // 눌림 상태 설정 + _nunchuck.btnC = 0; + } + + if( nunchuck.btnZ == 1 ){ + if( _nunchuck.btnZ == 0 ){ + // 클릭 된거임 + _nunchuck.btnZ = 1; + if( _mode == 0 ){ + // 플랫폼인 경우엔 다음 게임 선택 + selectGame(); + } + } + }else{ + // 눌림 상태 설정 + _nunchuck.btnZ = 0; + } + + + }catch(e){ + console.log(e); + } + + } +}; + +var _mode = "home"; +jQuery(function ($) { + window.cbox = { + listener: undefined, + context: undefined, + addEventListener: function(listener, context) { + window.cbox.listener = listener; + }, + triggerEvent: function(ce) { + !window.cbox.listener || window.cbox.listener(ce, cbox.context, window.cbox); + pubsub.pub("controlls",{"data":ce}); + } + }; + + setTimeout(function(){ + updater.init(); + },1000); + + var CBOX_INPUT = { + pX1 : 0, + pY1 : 0, + pX2 : 0, + pY2 : 0, + pX3 : 0, + pY3 : 0, + btnA : 0, + btnB : 0, + btnY : 0, + btnX : 0, + btnLB : 0, + btnRB : 0, + btnLT : 0, + btnRT : 0, + btnBack : 0, + btnStart : 0, + accX : 0, + accY : 0, + accZ : 0 + }; + + var CBOX_SDK_focusIn = function(){ + var CBOX_INPUT = { + pX1 : 0, + pY1 : 0, + pX2 : 0, + pY2 : 0, + pX3 : 0, + pY3 : 0, + btnA : 0, + btnB : 0, + btnY : 0, + btnX : 0, + btnLB : 0, + btnRB : 0, + btnLT : 0, + btnRT : 0, + btnBack : 0, + btnStart : 0, + accX : 0, + accY : 0, + accZ : 0 + }; + }; + var CBOX_SDK_focusOut = function(){ + }; + + var CBOX_SDK_KEYMAP = { + 37 : 'left', + 38 : 'up', + 39 : 'right', + 40 : 'down', + 13 : 'btnA', //enter + 8 : 'back', + 27 : 'esc', + 65: 'btnA', // a + 83 : 'btnB', //s + 90 : 'btnY', //z + 88 : 'btnX' //x + }; + + var CBOX_SDK_keyboard = function(keycode,kind){ + //TODO : Connect Here for Keyboard Events + // console.log(CBOX_INPUT.pX, keycode, CBOX_SDK_KEYMAP[keycode], kind); + + // for KeyDown + if (kind == "Down") { + switch(CBOX_SDK_KEYMAP[keycode]){ + case "left" : + CBOX_INPUT.pX1 -= 2; + break; + case "up" : + CBOX_INPUT.pY1 -= 2; + break; + case "right" : + CBOX_INPUT.pX1 += 2; + break; + case "down" : + CBOX_INPUT.pY1 += 2; + break; + case "back" : + break; + case "esc" : + break; + case "btnA" : + CBOX_INPUT.btnA = 1; + break; + case "btnB" : + CBOX_INPUT.btnB = 1; + break; + case "btnY" : + CBOX_INPUT.btnY = 1; + break; + case "btnX" : + CBOX_INPUT.btnX = 1; + break; + }; + }else{ + switch(CBOX_SDK_KEYMAP[keycode]){ + case "btnA" : + CBOX_INPUT.btnA = 0; + break; + case "btnB" : + CBOX_INPUT.btnB = 0; + break; + case "btnY" : + CBOX_INPUT.btnY = 0; + break; + case "btnX" : + CBOX_INPUT.btnX = 0; + break; + }; + } + + // add more information about keycode + // CBOX_INPUT.keyCode = keycode; + CBOX_INPUT.type = kind; + + // trigger event to listener + cbox.triggerEvent(CBOX_INPUT, cbox.context, cbox); + }; + var i = 0; + var _btn = { + + } + var CBOX_SDK_gamepad = function(){ + //console.log(_mode); + if( _mode === "home"){ + i = (++i % 10); + }else{ + i = 0; + } + if( i == 0 ){ + //console.debug(arguments,arguments.length); + CBOX_INPUT.btnA = parseInt(arguments[4]); + CBOX_INPUT.btnB = parseInt(arguments[5]); + CBOX_INPUT.btnX= parseInt(arguments[6]); + CBOX_INPUT.btnY = parseInt(arguments[7]); + + CBOX_INPUT.btnLB = parseInt(arguments[8]); + CBOX_INPUT.btnRB = parseInt(arguments[9]); + CBOX_INPUT.btnLT= (arguments[10]>0)?1:0; + CBOX_INPUT.btnRT = (arguments[11]>0)?1:0; + + CBOX_INPUT.btnBack = parseInt(arguments[12]); + CBOX_INPUT.btnStart = parseInt(arguments[13]); + + + if(arguments[16] == 1){ + CBOX_INPUT.pY1 -= 2; + } + if(arguments[17] == 1 ){ + CBOX_INPUT.pY1 += 2; + } + if(arguments[18] == 1){ + CBOX_INPUT.pX1 -= 2; + } + if(arguments[19] == 1){ + CBOX_INPUT.pX1 += 2; + } + // for keyboard hack. :) + CBOX_INPUT.type = "Down"; + + if(arguments[0] <= 70){ + // left + CBOX_INPUT.pX3 -= 2; + }else if(arguments[0] >= 80){ + //right + CBOX_INPUT.pX3 += 2; + } + if(arguments[1] <= 90 ){ + // left + CBOX_INPUT.pY3 -= 2; + }else if(arguments[1] >= 110){ + //right + CBOX_INPUT.pY3 += 2; + } + + if(arguments[2] <= 70){ + // left + CBOX_INPUT.pX2 -= 2; + }else if(arguments[2] >= 80){ + //right + CBOX_INPUT.pX2 += 2; + } + if(arguments[3] <= 90 ){ + // left + CBOX_INPUT.pY2 -= 2; + }else if(arguments[3] >= 110){ + //right + CBOX_INPUT.pY2 += 2; + } + + + cbox.triggerEvent(CBOX_INPUT); + + + //joy1 - x arguments[0] // 73 50~100 + //joy1 - y arguments[1] // 98 0 ~200 + //joy2 - x arguments[2] // 72 50~100 + //joy2 - y arguments[3] // 105 0~200 + //btn A arguments[4] + //btn B arguments[5] + //btn X arguments[6] + //btn Y arguments[7] + //joy1 - x arguments[8] + //joy1 - x arguments[9] + //joy1 - x arguments[10] + //joy1 - x arguments[11] + //joy1 - x arguments[12] + //joy1 - x arguments[13] + //joy1 - x arguments[14] + //joy1 - x arguments[15] + //d but - up arguments[16] + //d but - down arguments[17] + //d but - left arguments[18] + //d but - right arguments[10] + //center X button arguments[20] + } + }; + + var CBOX_SDK_nunchuk = function(){ + // cbox.triggerEvent(CBOX_INPUT); + }; + + var _defaultFuncs = { + "CBOX_SDK_focusIn" : CBOX_SDK_focusIn, + "CBOX_SDK_focusOut" : CBOX_SDK_focusOut, + "CBOX_SDK_keyboard" : CBOX_SDK_keyboard, + "CBOX_SDK_gamepad" : CBOX_SDK_gamepad, + "CBOX_SDK_nunchuk" : CBOX_SDK_nunchuk + }; + + // Called by the common.js module. + window.handleMessage = function(message) { + var _order = []; + var func = function(){}; + + if (typeof message.data === 'string') { + if( message.data.indexOf("o::") == 0 ){ + _order = message.data.replace("o::","").split(":"); + func = _defaultFuncs[_order.shift()]; + if(func){ +// console.log(message.data); + if( _order.length > 1 ){ + func.apply(this||window,_order); + }else{ + func(); + } + } + } + } + } + + window.handleMessage2 = function(message) { + var _order = []; + var func = function(){}; + + console.log(message); + + return; + + + } + + + + + $("#osx-modal-content").fadeIn('slow'); + + +}); diff --git a/static/cbox_sdk/cbox_sdk.nmf b/static/cbox_sdk/cbox_sdk.nmf index cfdad9f..aad479e 100644 --- a/static/cbox_sdk/cbox_sdk.nmf +++ b/static/cbox_sdk/cbox_sdk.nmf @@ -1,11 +1,11 @@ -{ - "files": {}, - "program": { - "x86-64": { - "url": "cbox_sdk_x86_64.nexe" - }, - "x86-32": { - "url": "cbox_sdk_x86_32.nexe" - } - } -} +{ + "files": {}, + "program": { + "x86-64": { + "url": "cbox_sdk_x86_64.nexe" + }, + "x86-32": { + "url": "cbox_sdk_x86_32.nexe" + } + } +} diff --git a/static/cbox_sdk/cbox_sdk_x86_32.d b/static/cbox_sdk/cbox_sdk_x86_32.d index 408f674..58afe09 100644 --- a/static/cbox_sdk/cbox_sdk_x86_32.d +++ b/static/cbox_sdk/cbox_sdk_x86_32.d @@ -1 +1 @@ -newlib/Debug/cbox_sdk_x86_32.o: cbox_sdk.cc +newlib/Debug/cbox_sdk_x86_32.o: cbox_sdk.cc gamepad.h diff --git a/static/cbox_sdk/cbox_sdk_x86_32.nexe b/static/cbox_sdk/cbox_sdk_x86_32.nexe index f28bdf8..fcfcb4b 100755 Binary files a/static/cbox_sdk/cbox_sdk_x86_32.nexe and b/static/cbox_sdk/cbox_sdk_x86_32.nexe differ diff --git a/static/cbox_sdk/cbox_sdk_x86_32.o b/static/cbox_sdk/cbox_sdk_x86_32.o index e5a23b0..2fddbed 100644 Binary files a/static/cbox_sdk/cbox_sdk_x86_32.o and b/static/cbox_sdk/cbox_sdk_x86_32.o differ diff --git a/static/cbox_sdk/cbox_sdk_x86_64.d b/static/cbox_sdk/cbox_sdk_x86_64.d index 1b9f8ad..6516930 100644 --- a/static/cbox_sdk/cbox_sdk_x86_64.d +++ b/static/cbox_sdk/cbox_sdk_x86_64.d @@ -1 +1 @@ -newlib/Debug/cbox_sdk_x86_64.o: cbox_sdk.cc +newlib/Debug/cbox_sdk_x86_64.o: cbox_sdk.cc gamepad.h diff --git a/static/cbox_sdk/cbox_sdk_x86_64.nexe b/static/cbox_sdk/cbox_sdk_x86_64.nexe index e5bd111..8d40d26 100755 Binary files a/static/cbox_sdk/cbox_sdk_x86_64.nexe and b/static/cbox_sdk/cbox_sdk_x86_64.nexe differ diff --git a/static/cbox_sdk/cbox_sdk_x86_64.o b/static/cbox_sdk/cbox_sdk_x86_64.o index 6001a22..b4bc033 100644 Binary files a/static/cbox_sdk/cbox_sdk_x86_64.o and b/static/cbox_sdk/cbox_sdk_x86_64.o differ diff --git a/static/config.js b/static/config.js new file mode 100644 index 0000000..bc8e39c --- /dev/null +++ b/static/config.js @@ -0,0 +1,14 @@ +(function(window) { + + var GameConfig = [ + {title:'CBox소개', banner:'games/cboxtech.png', url:'redirect://https://github.com/organizations/CboxConsole'}, + {title:'Cbox컨트롤러', banner:'games/cboxtest.png', url:'http://localhost:8000/Xbox_Controller/index.html'}, + {title:'각설탕쌓기', banner:'games/sugarpang.png', url:'http://localhost:8000/Chrome_Pagoda/index.html'}, + {title:'크롬벽돌깨기', banner:'games/breakout.png', url:'http://localhost:8081/breakout/'}, + {title:'몽대륙', banner:'games/penguin-adv.png', url:'http://localhost:8000/Android_Adventure/index.html'} + ]; + + + window.GameConfig = GameConfig; + +})(window); diff --git a/static/game-launcher.js b/static/game-launcher.js index 696710e..d651e25 100644 --- a/static/game-launcher.js +++ b/static/game-launcher.js @@ -2,6 +2,7 @@ var GameLauncher = Backbone.View.extend({ className:'game-launcher', initialize: function() { this.on('hkeydown:esc', function() { + this.options.homescreen.trigger('game:exit'); this.remove(); this.trigger('launcher:exit'); }, this); @@ -14,4 +15,4 @@ var GameLauncher = Backbone.View.extend({ navigate: function(v, e) { if (this.to[e.keyid]) this.to[e.keyid].focusin(); } -}); \ No newline at end of file +}); diff --git a/static/game-sample.html b/static/game-sample.html index 9a64bf9..a774767 100644 --- a/static/game-sample.html +++ b/static/game-sample.html @@ -3,6 +3,12 @@ Cbox Console Game Sample Screen +
diff --git a/static/homescreen.js b/static/homescreen.js index eec50aa..273e006 100644 --- a/static/homescreen.js +++ b/static/homescreen.js @@ -1,40 +1,133 @@ -var Box = Backbone.View.extend({ - className:'box', - to:undefined, + +// Cbox homescreen +// @ragingwind +// version: 0.0.1 + +var Slider = Backbone.View.extend({ + className:'slider', initialize: function() { - this.on('keydown:up keydown:down keydown:right keydown:left', - this.navigate, this); - this.to = {}; + _.bindAll(this, 'reflect'); + }, + reflect: function() { + /* + reflect code from greate article. + "Cross-Browser CSS Reflections, Glows and Blurs" - http://goo.gl/iH72G + */ + var opt = { + canvas: this.$canvas[0], + img: this.$img[0], + reflection: 0.5, + bgcolor: '#000000', + height:246, + width:396 + }; + + if (opt.canvas.getContext) { + var ctx = opt.canvas.getContext("2d") + , gradient = ctx.createLinearGradient(0, 0, 0, opt.height * opt.reflection); + + gradient.addColorStop(1, "rgba(255, 255, 255, 1.0)"); + gradient.addColorStop(0, "rgba(255, 255, 255, " + (1 - opt.reflection) + ")"); + + ctx.save(); + ctx.translate(0, opt.height - 1); + ctx.scale(1, -1); + ctx.drawImage(opt.img, 0, 0, opt.width, opt.height); + ctx.restore(); + ctx.globalCompositeOperation = "destination-out"; + ctx.fillStyle = opt.color; + ctx.fillRect(0, opt.height * 0.5, opt.width, opt.height); + ctx.fillStyle = gradient; + ctx.rect(0, 0, opt.width, opt.height); + ctx.fill(); + delete ctx, gradient; + } }, render: function() { - if (this.options.game.title) - this.$el.append('
' + this.options.game.title + '
'); + this.$canvas = $(''); + this.$img = $(''); + + this.$img.load(this.reflect); + this.$el.append(this.$img); + this.$el.append(this.$canvas); - this.$el.css('background-image', 'url("games/' + this.options.game.banner + '")'); return this; - }, - navigate: function(v, e) { - if (this.to[e.keyid]) this.to[e.keyid].focusin(); } }); -var SideBox = Backbone.View.extend({ - className:'side', +var SliderView = Backbone.View.extend({ + max: 5, + id: 'sliderview', + top: 0, + animate: false, + keyevent: true, + sounds: [], initialize: function() { - this.boxes = { - upper: new Box({id:'upper', game:this.options.games[0]}), - down: new Box({id:'down', game:this.options.games[1]}) + this.on('keydown:left keydown:right', this.navigate, this); + this.on('keydown:enter', function() { + if (this.keyevent) { + var v = this.options.views[this.top - 1]; + this.superview.trigger('game:select', v.options.game); + } + }, this); + + for (var i = 0; i < 5; ++i) + this.sounds.push(new Audio('../sounds/slide.mp3')); + this.sounds.index = 0; + }, + playSound: function() { + if (this.sounds.index >= this.sounds.length) + this.sounds.index = 0 + this.sounds[this.sounds.index++].play(); + }, + navigate: function(v, e) { + if (this.keyevent) { + this.playSound(); + (e.keyid === 'left') ? this.enqueue() : this.dequeue(); + } + }, + enqueue: function() { + var v = this.options.views[this.top]; + if (v) { + var $s = this.$el.children('.slider'); + if ($s.length >= this.max) + $($s[$s.length - 1]).remove(); + + v.$el.css('opacity', 1); + this.$el.prepend(v.$el); + + this.top++; + } + }, + dequeue: function() { + if (this.animate) return; + if (this.top > 1) { + var self = this + , $v = $(self.$el.children('.slider')[0]); + + this.top--; + self.animate = true; + + // @DEPRECATD performance issue with sdk + if (true) { + $v.remove() + self.animate = false; + } + else { + $v.animate({'opacity':0.1}, { + duration:150, + step: function(now) {if (now > 0.5 && now < 0.6) $v.remove()}, + complete: function() {self.animate = false;} + }); + } } - this.on('keyevent:focusin', function() { - this.boxes.upper.focusin(); - }, this) }, render: function() { - _.each(this.boxes, function(p) { - p.on('keydown:enter', function() { - this.superview.trigger('box:select', p, p.options.game); - }, this); - this.add(p.render());}, this); + this.top = 0; + for (var i = 0; i < this.options.views.length; ++i) { + this.enqueue(); + } + return this; } }); @@ -42,42 +135,35 @@ var SideBox = Backbone.View.extend({ var Homescreen = Backbone.View.extend({ className:'homescreen', initialize: function() { - var games = this.options.games - this.boxes = { - left: new SideBox({id:'left', games:[games[0], games[3]]}), - center: new Box({id:'center', game:games[2]}), - right: new SideBox({id:'right', games:[games[1], games[5]]}) - } + var games = this.options.games; + // bind box selecting event to launch games. + this.on('game:select', function(game) { + // create and show game screen with the game parameter. + if (game.url.indexOf('redirect://') < 0) { + this.sliderview.keyevent = false; + var gl = new GameLauncher({game:game, homescreen:this}); + $('body').append(gl.render().$el); + } + else + window.open(game.url.split('redirect://')[1]); - this.boxes.center.on('keydown:enter', function() { - this.trigger('box:select', this.boxes.center, this.boxes.center.options.game); - }, this); + }, this); + + this.on('game:exit', function() { + this.sliderview.keyevent = true; + }, this); }, render: function() { - // sub boxes added to boxes view - _.each(this.boxes, function(p) {this.add(p.render());}, this); - - // mapping for key navigation - var center = this.boxes.center - , left = this.boxes.left.boxes - , right = this.boxes.right.boxes; - - left.upper.to.right = center; - left.upper.to.down = left.down; - left.down.to.right = center; - left.down.to.up = left.upper; - - right.upper.to.left = center; - right.upper.to.down = right.down; - right.down.to.left = center; - right.down.to.up = right.upper; - - center.to.left = this.boxes.left; - center.to.right = this.boxes.right; - center.focusin(); - - this.$el.append('
') + this.$el.append('
'); + var views = []; + _.each(this.options.games, function(game) { + views.push(new Slider({game:game}).render()) + }); + this.sliderview = new SliderView({views:views}).render(); + this.add(this.sliderview); + this.sliderview.focusin(); return this; - } + }, + }); diff --git a/static/jquery.transition.min.js b/static/jquery.transition.min.js new file mode 100644 index 0000000..096b426 --- /dev/null +++ b/static/jquery.transition.min.js @@ -0,0 +1 @@ +(function(a){function t(){setTimeout(x,0);return m=a.now()}function x(){m=void 0}var r={},k,q,y=/^(?:toggle|show|hide)$/,z=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,u,m,v=document.createElement("div").style,w;a.support.transition="MozTransition"in v?"MozTransition":"WebkitTransition"in v?"WebkitTransition":!1;a.cssNumber.color=a.cssNumber.backgroundColor=!0;w={linear:"linear",swing:"ease-out",bounce:"cubic-bezier(0,.35,.5,1.3)",easeInQuad:"cubic-bezier(.55,.085,.68,.53)",easeInCubic:"cubic-bezier(.55,.055,.675,.19)", easeInQuart:"cubic-bezier(.895,.03,.685,.22)",easeInQuint:"cubic-bezier(.755,.05,.855,.06)",easeInSine:"cubic-bezier(.47,0,.745,.715)",easeInExpo:"cubic-bezier(.95,.05,.795,.035)",easeInCirc:"cubic-bezier(.6,.04,.98,.335)",easeOutQuad:"cubic-bezier(.25,.46,.45,.94)",easeOutCubic:"cubic-bezier(.215,.61,.355,1)",easeOutQuart:"cubic-bezier(.165,.84,.44,1)",easeOutQuint:"cubic-bezier(.23,1,.32,1)",easeOutSine:"cubic-bezier(.39,.575,.565,1)",easeOutExpo:"cubic-bezier(.19,1,.22,1)",easeOutCirc:"cubic-bezier(.075,.82,.165,1)", easeInOutQuad:"cubic-bezier(.455,.03,.515,.955)",easeInOutCubic:"cubic-bezier(.645,.045,.355,1)",easeInOutQuart:"cubic-bezier(.77,0,.175,1)",easeInOutQuint:"cubic-bezier(.86,0,.07,1)",easeInOutSine:"cubic-bezier(.445,.05,.55,.95)",easeInOutExpo:"cubic-bezier(1,0,0,1)",easeInOutCirc:"cubic-bezier(.785,.135,.15,.86)"};a.fn.extend({animate:function(d,e,g,b){function f(){!1===i.queue&&a._mark(this);var c=a.extend({},i),f=1===this.nodeType,e=f&&a(this).is(":hidden"),b,h,g,j,n;n=a.cssProps;var m=!c.step&& a.support.transition,s=[],o,p;c.animatedProperties={};c.transition={};for(g in d)if(b=a.camelCase(g),g!==b&&(d[b]=d[g],delete d[g]),(h=a.cssHooks[b])&&"expand"in h)for(g in j=h.expand(d[b]),delete d[b],j)g in d||(d[g]=j[g]);for(b in d){h=d[b];a.isArray(h)?(j=c.animatedProperties[b]=h[1],h=d[b]=h[0]):j=c.animatedProperties[b]=c.specialEasing&&c.specialEasing[b]||c.easing||"swing";if(j=m&&f&&0").appendTo(j);p=o.css("display");o.remove();if("none"===p||""===p){k||(k=document.createElement("iframe"),k.frameBorder= k.width=k.height=0);j.appendChild(k);if(!q||!k.createElement)q=(k.contentWindow||k.contentDocument).document,q.write((a.support.boxModel?"":"")+""),q.close();o=q.createElement(h);q.body.appendChild(o);p=a.css(o,"display");j.removeChild(k)}r[h]=p}h="inline"===r[h]}h?this.style.display="inline-block":this.style.zoom=1}}null!=c.overflow&&(this.style.overflow="hidden");for(g in d)if(f=new a.fx(this,c,g),h=d[g],y.test(h))if(b=a._data(this,"toggle"+g)||("toggle"===h?e?"show": "hide":0))a._data(this,"toggle"+g,"show"===b?"hide":"show"),f[b]();else f[h]();else b=z.exec(h),n=f.cur(),b?(h=parseFloat(b[2]),j=b[3]||(a.cssNumber[g]?"":"px"),"px"!==j&&(a.style(this,g,(h||1)+j),n*=(h||1)/f.cur(),a.style(this,g,n+j)),b[1]&&(h=("-="===b[1]?-1:1)*h+n),f.custom(n,h,j)):f.custom(n,h,"");if(m&&s.length)for(g in j=this.style[m],e=window.getComputedStyle(this),this.style[m]=s.join()+(j&&j.indexOf("none")?","+j:""),c.transition)e[g],a.style.apply(null,c.transition[g].styleToSet);return!0} var i=a.speed(e,g,b);if(a.isEmptyObject(d))return this.each(i.complete,[!1]);d=a.extend({},d);return!1===i.queue?this.each(f):this.queue(i.queue,f)},stop:function(d,e,g){"string"!==typeof d&&(g=e,e=d,d=void 0);e&&!1!==d&&this.queue(d||"fx",[]);return this.each(function(){var b,f=false,e=a.timers,c=a._data(this),l=a.support.transition;g||a._unmark(true,this);if(d==null)for(b in c){if(c[b]&&c[b].stop&&b.indexOf(".run")===b.length-4){var k=c[b];a.removeData(this,b,true);k.stop(g)}}else if(c[b=d+".run"]&& c[b].stop){c=c[b];a.removeData(this,b,true);c.stop(g)}for(b=e.length;b--;)if(e[b].elem===this&&(d==null||e[b].queue===d)){if(g||l)e[b](g);g||e[b].saveState();f=true;e.splice(b,1)}(!g||!f)&&a.dequeue(this,d)})}});a.extend(a.fx.prototype,{cur:function(){if(null!=this.elem[this.prop]&&(!this.elem.style||null==this.elem.style[this.prop]))return this.elem[this.prop];var d,e=a.css(this.elem,this.prop);return isNaN(d=parseFloat(e))?!e||"auto"===e?0:e:d},custom:function(d,e,g){function b(a){return f.step(a)} var f=this,i=a.fx,c=f.options.transition,l=this.prop;this.startTime=m||t();this.end=e;this.now=this.start=d;this.pos=this.state=0;this.unit=g||this.unit||(a.cssNumber[l]?"":"px");b.queue=this.options.queue;b.elem=this.elem;b.saveState=function(){void 0===a._data(f.elem,"fxshow"+f.prop)&&(f.options.hide?a._data(f.elem,"fxshow"+f.prop,f.start):f.options.show&&a._data(f.elem,"fxshow"+f.prop,f.end))};(b.transition=c[l])?(a.timers.push(b),"transform"!=l&&(f.elem.style[c[l].real]=d+f.unit),a.fx.step[l]&& (e=Math.max(0,e)),c[l].styleToSet=[f.elem,l,e+f.unit],c[l].timeout=setTimeout(function(){a.timers.splice(a.timers.indexOf(b),1);f.step(!0)},f.options.duration+30)):b()&&a.timers.push(b)&&!u&&(u=setInterval(i.tick,i.interval))},step:function(d){var e,g=m||t(),b=!0,f=this.elem,i=this.options,c=i.transition[this.prop],l=g>=i.duration+this.startTime,k=a.support.transition;if(c||d||l){c?(clearTimeout(c.timeout),!d&&!l&&(this.elem.style[c.real]=a.css(this.elem,c.real))):(this.now=this.end,this.pos=this.state= 1,this.update());i.animatedProperties[this.prop]=!0;for(e in i.animatedProperties)!0!==i.animatedProperties[e]&&(b=!1);if(b){null!=i.overflow&&!a.support.shrinkWrapBlocks&&a.each(["","X","Y"],function(a,b){f.style["overflow"+b]=i.overflow[a]});i.hide&&a(f).hide();if(c){c=","+f.style[k];for(e in i.transition)c=c.split(i.transition[e].lower).join("_");c=c.replace(/, ?_[^,]*/g,"").substr(1);f.style[k]=c||"none";!c&&(f.style[k]=c)}if(i.hide||i.show)for(e in i.animatedProperties)(d||l)&&a.style(f,e,i.orig[e]), a.removeData(f,"fxshow"+e,!0),a.removeData(f,"toggle"+e,!0);if((e=i.complete)&&(d||l))i.complete=!1,e.call(f)}return!1}Infinity==i.duration?this.now=g:(d=g-this.startTime,this.state=d/i.duration,this.pos=a.easing[i.animatedProperties[this.prop]](this.state,d,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos);this.update();return!0}});a.extend(a.fx,{tick:function(){for(var d,e=a.timers,g=0;g 1) { + throw new Error('Object.create implementation only accepts the first parameter.'); + } + function F() {} + F.prototype = o; + return new F(); + }; +} + +if (!Function.prototype.bind) { + /** + * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind + */ + Function.prototype.bind = function (oThis) { + + if (typeof this !== "function") // closest thing possible to the ECMAScript 5 internal IsCallable function + throw new TypeError("Function.prototype.bind - what is trying to be fBound is not callable"); + + var aArgs = Array.prototype.slice.call(arguments, 1), + fToBind = this, + fNOP = function () {}, + fBound = function () { + return fToBind.apply(this instanceof fNOP ? this : oThis || window, aArgs.concat(Array.prototype.slice.call(arguments))); + }; + + fNOP.prototype = this.prototype; + fBound.prototype = new fNOP(); + + return fBound; + + }; +} + +if (!window.requestAnimationFrame) { + /** + * Provides requestAnimationFrame in a cross browser way. + * @see http://paulirish.com/2011/requestanimationframe-for-smart-animating/ + */ + window.requestAnimationFrame = ( function() { + return window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + window.oRequestAnimationFrame || + window.msRequestAnimationFrame || + function( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element ) { + window.setTimeout( callback, 1000 / 60 ); + }; + } )(); +} + +}, mimetype: "application/javascript", remote: false}; // END: /__builtin__/init.js + + +__jah__.resources["/__builtin__/path.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +/** @namespace */ +var path = { + /** + * Returns full directory path for the filename given. The path must be formed using forward slashes '/'. + * + * @param {String} path Path to return the directory name of + * @returns {String} Directory name + */ + dirname: function(path) { + var tokens = path.split('/'); + tokens.pop(); + return tokens.join('/'); + }, + + /** + * Returns just the filename portion of a path. + * + * @param {String} path Path to return the filename portion of + * @returns {String} Filename + */ + basename: function(path) { + var tokens = path.split('/'); + return tokens[tokens.length-1]; + }, + + /** + * Joins multiple paths together to form a single path + * @param {String} ... Any number of string arguments to join together + * @returns {String} The joined path + */ + join: function () { + return module.exports.normalize(Array.prototype.join.call(arguments, "/")); + }, + + /** + * Tests if a path exists + * + * @param {String} path Path to test + * @returns {Boolean} True if the path exists, false if not + */ + exists: function(path) { + return (__jah__.resources[path] !== undefined); + }, + + /** + * @private + */ + normalizeArray: function (parts, keepBlanks) { + var directories = [], prev; + for (var i = 0, l = parts.length - 1; i <= l; i++) { + var directory = parts[i]; + + // if it's blank, but it's not the first thing, and not the last thing, skip it. + if (directory === "" && i !== 0 && i !== l && !keepBlanks) continue; + + // if it's a dot, and there was some previous dir already, then skip it. + if (directory === "." && prev !== undefined) continue; + + // if it starts with "", and is a . or .., then skip it. + if (directories.length === 1 && directories[0] === "" && ( + directory === "." || directory === "..")) continue; + + if ( + directory === ".." + && directories.length + && prev !== ".." + && prev !== "." + && prev !== undefined + && (prev !== "" || keepBlanks) + ) { + directories.pop(); + prev = directories.slice(-1)[0] + } else { + if (prev === ".") directories.pop(); + directories.push(directory); + prev = directory; + } + } + return directories; + }, + + /** + * Returns the real path by expanding any '.' and '..' portions + * + * @param {String} path Path to normalize + * @param {Boolean} [keepBlanks=false] Whether to keep blanks. i.e. double slashes in a path + * @returns {String} Normalized path + */ + normalize: function (path, keepBlanks) { + return module.exports.normalizeArray(path.split("/"), keepBlanks).join("/"); + } +}; + +module.exports = path; + +}, mimetype: "application/javascript", remote: false}; // END: /__builtin__/path.js + + +__jah__.resources["/__builtin__/preloader.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +"use strict"; + +var events = require('events') + , remotes = require('remote_resources') + +function Preloader (items) { + this.count = 0 + this.loaded = 0 + this.queue = [] + + var listeners = {} + + if (items) { + this.addToQueue(items) + } + + var didLoadResource = function (ref) { + this.loaded++ + + // Must remove listener or we'll leak memory + if (listeners[ref]) { + events.removeListener(listeners[ref]); + } + events.trigger(this, 'load', this, ref); + + + if (this.loaded >= this.count) { + events.trigger(this, 'complete', this); + } + }.bind(this) + + this.load = function () { + if (this.queue.length == 0) { + events.trigger(this, 'complete', this); + return + } + // Store number of callbacks we're expecting + this.count += this.queue.length + + var ref, i + for (i=0; i 0) { + this.addToQueue(items) + } +} + +Preloader.prototype.clearQueue = function () { + this.queue.splice(0, this.queue.length) +} + + +exports.Preloader = Preloader; + +}, mimetype: "application/javascript", remote: false}; // END: /__builtin__/preloader.js + + +__jah__.resources["/__builtin__/remote_resources.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +"use strict" + +var util = require('./index'), + events = require('events') + +/** + * @namespace + */ +var remote_resources = {} + +/** + * @class + * @memberOf remote_resources + */ +function RemoteResource(url, path) { + this.url = url + this.path = path +} +remote_resources.RemoteResource = RemoteResource + +/** + * Load the remote resource via ajax + */ +remote_resources.RemoteResource.prototype.load = function () { + var xhr = new XMLHttpRequest() + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + __jah__.resources[this.path].data = xhr.responseText + __jah__.resources[this.path].loaded = true + + events.trigger(this, 'load', this) + } + }.bind(this) + + xhr.open('GET', this.url, true) + xhr.send(null) +} + +/** + * @class + * @memberOf remote_resources + * @extends remote_resources.RemoteResource + */ +function RemoteImage(url, path) { + RemoteResource.apply(this, arguments) +} +remote_resources.RemoteImage = RemoteImage + +remote_resources.RemoteImage.prototype = Object.create(RemoteResource.prototype) + +remote_resources.RemoteImage.prototype.load = function () { + var img = new Image() + __jah__.resources[this.path].data = img + + /** + * @ignore + */ + img.onload = function () { + __jah__.resources[this.path].loaded = true + events.trigger(this, 'load', this) + }.bind(this) + + /** + * @ignore + */ + img.onerror = function () { + console.warn("Failed to load resource: [%s] from [%s]", this.path, img.src) + __jah__.resources[this.path].loaded = true + events.trigger(this, 'load', this) + }.bind(this) + + img.src = this.url + + return img +} + + +/** + * @class + * @memberOf remote_resources + * @extends remote_resources.RemoteResource + */ +function RemoteScript(url, path) { + RemoteResource.apply(this, arguments) +} +remote_resources.RemoteScript = RemoteScript + +remote_resources.RemoteScript.prototype = Object.create(RemoteResource.prototype) + +remote_resources.RemoteScript.prototype.load = function () { + var script = document.createElement('script') + __jah__.resources[this.path].data = script + + /** + * @ignore + */ + script.onload = function () { + __jah__.resources[this.path].loaded = true + events.trigger(this, 'load', this) + }.bind(this) + + script.src = this.url + document.getElementsByTagName('head')[0].appendChild(script) + + return script +} + +remote_resources.getRemoteResourceConstructor = function (mime) { + mime = mime.split('/') + + var RemoteObj + if (mime[0] == 'image') { + RemoteObj = RemoteImage + } else if(mime[1] == 'javascript') { + RemoteObj = RemoteScript + } else { + RemoteObj = RemoteResource + } + + return RemoteObj +} + +remote_resources.getRemoteResource = function (resourcePath) { + var resource = __jah__.resources[resourcePath] + + if (!resource) { + return null + } + + if (resource.remoteResource) { + return resource.remoteResource + } + + var RemoteObj = remote_resources.getRemoteResourceConstructor(resource.mimetype) + + resource.remoteResource = new RemoteObj(resource.data, resourcePath) + + return resource.remoteResource +} + +module.exports = remote_resources + +}, mimetype: "application/javascript", remote: false}; // END: /__builtin__/remote_resources.js + + +__jah__.resources["/__builtin__/system.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +/** @namespace */ +var system = { + /** @namespace */ + stdio: { + /** + * Print text and objects to the debug console if the browser has one + * + * @param {*} Any value to output + */ + print: function() { + if (console) { + console.log.apply(console, arguments); + } else { + // TODO + } + } + } +}; + +if (window.console) { + system.console = window.console +} else { + system.console = { + log: function(){} + } +} + +}, mimetype: "application/javascript", remote: false}; // END: /__builtin__/system.js + +/*globals module exports resource require window Module __main_module_name__ */ +/*jslint undef: true, strict: true, white: true, newcap: true, browser: true, indent: 4 */ +(function(){ +"use strict"; + +var __main_module_name__ = '/main' + +var process = {} + , modulePaths = ['/__builtin__', '/__builtin__/libs', '/libs'] + , path; // path module, we will load this later + +function require (request, parent) { + return loadModule(request, parent).exports; +} + +function resource (resourcePath) { + var remotes = require('remote_resources') + + var res = __jah__.resources[resourcePath] + if (!res) { + throw new Error("Unable to find resource: " + resourcePath); + } + + if (res.remote && !res.loaded) { + return remotes.getRemoteResource(resourcePath) + } + + return res.data +} + +function resolveModulePath(request, parent) { + // If not a relative path then search the modulePaths for it + var start = request.substring(0, 2); + if (start !== "./" && start !== "..") { + return modulePaths; + } + + var parentIsIndex = path.basename(parent.filename).match(/^index\.js$/), + parentPath = parentIsIndex ? parent.id : path.dirname(parent.id); + + // Relative path so searching inside parent's directory + return [path.dirname(parent.filename)]; +} + +function findModulePath(id, dirs) { + + if (id.charAt(0) === '/') { + dirs = ['']; + } + for (var i = 0; i < dirs.length; i++) { + var dir = dirs[i]; + var p = path.join(dir, id); + + // Check for index first + if (path.exists(path.join(p, 'index.js'))) { + return path.join(p, 'index.js'); + } else if (path.exists(p + '.js')) { + return p + '.js'; + } + // console.log('findpath', id, dir, path.exists(path.join(p, 'index.js')), path.exists(p + '.js')); + } + + return false; +} + +function loadModule(request, parent) { + parent = parent || process.mainModule; + + var paths = resolveModulePath(request, parent), + filename = findModulePath(request, paths); + + if (filename === false) { + throw new Error("Unable to find module: " + request); + } + + + if (parent) { + var cachedModule = Module._moduleCache[filename]; + if (cachedModule) { + return cachedModule; + } + } + + var module = new Module(filename, parent); + + // Assign main module to process + if (request == __main_module_name__ && !process.mainModule) { + process.mainModule = module; + } + + // Run all the code in the module + module._initialize(filename); + + return module; +} + +function Module(id, parent) { + this.id = id; + this.parent = parent; + this.children = []; + this.exports = {}; + + if (parent) { + parent.children.push(this); + } + Module._moduleCache = Module._moduleCache || {} + Module._moduleCache[this.id] = this; + + this.filename = null; + this.dirname = null; +} + +Module.prototype._initialize = function (filename) { + var module = this; + function require(request) { + return loadModule(request, module).exports; + } + + this.filename = filename; + + // Work around incase this IS the path module + if (path) { + this.dirname = path.dirname(filename); + } else { + this.dirname = ''; + } + + require.paths = modulePaths; + require.main = process.mainModule; + + var mod = __jah__.resources[this.filename] + if (mod) { + mod.data.apply(this.exports, [this.exports, require, resource, this, this.filename, this.dirname]); + } else { + throw new Error("Unable to find module: " + this.filename) + } + + return this; +}; + +// Manually load the path module because we need it to load other modules +path = (new Module('path'))._initialize('/__builtin__/path.js').exports; + +var util = loadModule('/__builtin__/').exports; + +// Browser's DOM is ready for action +util.ready(function () { + + // Initialise the libs + var key, lib + for (key in __jah__.resources) { + if (__jah__.resources.hasOwnProperty(key)) { + // If matches /libs//init.js then run foo.main() + if (/^\/libs\/[^\/]+?\/init.js$/.test(key) || key == '/__builtin__/init.js') { + lib = loadModule(key.replace(/\.js$/, '')).exports + if (typeof lib.main == 'function') { + lib.main() + } + } + } + } + + // Initialise the main module + process.mainModule = loadModule(__main_module_name__); + + // Run application's main function + if (process.mainModule.exports.main) { + process.mainModule.exports.main(); + } +}); + +})() +// vim:ft=javascript + +})();(function(){ +__jah__.resources["/libs/cocos2d/ActionManager.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var util = require('util'), + Timer = require('./Scheduler').Timer, + Scheduler = require('./Scheduler').Scheduler + + +/** + * @class + * A singleton that manages all the actions. Normally you + * won't need to use this singleton directly. 99% of the cases you will use the + * cocos.nodes.Node interface, which uses this singleton. But there are some cases where + * you might need to use this singleton. Examples: + * + * * When you want to run an action where the target is different from a cocos.nodes.Node + * * When you want to pause / resume the actions + * + * @memberOf cocos + * @singleton + */ +function ActionManager () { + ActionManager.superclass.constructor.call(this) + + Scheduler.sharedScheduler.scheduleUpdate({target: this, priority: 0, paused: false}) + this.targets = [] +} + +ActionManager.inherit(Object, /** @lends cocos.ActionManager# */ { + targets: null, + currentTarget: null, + currentTargetSalvaged: null, + + /** + * Adds an action with a target. If the target is already present, then the + * action will be added to the existing target. If the target is not + * present, a new instance of this target will be created either paused or + * paused, and the action will be added to the newly created target. When + * the target is paused, the queued actions won't be 'ticked'. + * + * @opt {cocos.nodes.Node} target Node to run the action on + */ + addAction: function (opts) { + + var targetID = opts.target.id + var element = this.targets[targetID] + + if (!element) { + element = this.targets[targetID] = { + paused: false, + target: opts.target, + actions: [] + } + } + + element.actions.push(opts.action) + + opts.action.startWithTarget(opts.target) + }, + + /** + * Remove an action + * + * @param {cocos.actions.Action} action Action to remove + */ + removeAction: function (action) { + var targetID = action.originalTarget.id, + element = this.targets[targetID] + + if (!element) { + return + } + + var actionIndex = element.actions.indexOf(action) + + if (actionIndex == -1) { + return + } + + if (this.currentTarget == element) { + element.currentActionSalvaged = true + } + + element.actions[actionIndex] = null + element.actions.splice(actionIndex, 1); // Delete array item + + if (element.actions.length === 0) { + if (this.currentTarget == element) { + this.currentTargetSalvaged = true + } + } + + }, + + /** + * Fetch an action belonging to a cocos.nodes.Node + * + * @returns {cocos.actions.Action} + * + * @opts {cocos.nodes.Node} target Target of the action + * @opts {String} tag Tag of the action + */ + getActionFromTarget: function(opts) { + var tag = opts.tag, + targetID = opts.target.id + + var element = this.targets[targetID] + if (!element) { + return null + } + for (var i = 0; i < element.actions.length; i++ ) { + if (element.actions[i] && + (element.actions[i].tag === tag)) { + return element.actions[i] + } + } + // Not found + return null + }, + + /** + * Remove all actions for a cocos.nodes.Node + * + * @param {cocos.nodes.Node} target Node to remove all actions for + */ + removeAllActionsFromTarget: function (target) { + var targetID = target.id + + var element = this.targets[targetID] + if (!element) { + return + } + + delete this.targets[targetID] + // Delete everything in array but don't replace it incase something else has a reference + element.actions.splice(0, element.actions.length) + }, + + /** + * @private + */ + update: function (dt) { + var self = this + util.each(this.targets, function (currentTarget, i) { + + if (!currentTarget) { + return + } + self.currentTarget = currentTarget + + if (!currentTarget.paused) { + util.each(currentTarget.actions, function (currentAction, j) { + if (!currentAction) { + return + } + + currentTarget.currentAction = currentAction + currentTarget.currentActionSalvaged = false + + currentTarget.currentAction.step(dt) + + if (currentTarget.currentAction.isDone) { + currentTarget.currentAction.stop() + + var a = currentTarget.currentAction + currentTarget.currentAction = null + self.removeAction(a) + } + + currentTarget.currentAction = null + + }) + } + + if (self.currentTargetSalvaged && currentTarget.actions.length === 0) { + self.targets[i] = null + delete self.targets[i] + } + }) + }, + + pauseTarget: function (target) { + }, + + resumeTarget: function (target) { + // TODO + } +}) + +Object.defineProperty(ActionManager, 'sharedManager', { + /** + * A shared singleton instance of cocos.ActionManager + * + * @memberOf cocos.ActionManager + * @getter {cocos.ActionManager} sharedManager + */ + get: function () { + if (!ActionManager._instance) { + ActionManager._instance = new this() + } + + return ActionManager._instance + } + + , enumerable: true +}) + +exports.ActionManager = ActionManager + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/ActionManager.js + + +__jah__.resources["/libs/cocos2d/actions/Action.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var util = require('util'), + geo = require('geometry'), + ccp = geo.ccp + +/** + * @class + * Base class for Actions. Actions change properites of a Node gradually + * over time or instantly. + * + * @memberOf cocos.actions + */ +function Action () { +} + +Action.inherit(Object, /** @lends cocos.actions.Action# */ { + /** + * The Node the action is being performed on + * @type cocos.nodes.Node + */ + target: null, + originalTarget: null, + + /** + * Unique tag to identify the action + * @type String + */ + tag: null, + + /** + * Called every frame with its delta time. Overwrite this only if you're + * making a new base type of action. Usually you'll just want to override + * 'update' and extend from cocos.actions.ActionInstance or + * cocos.actions.ActionInterval. + * + * @param {Float} dt The delta time + */ + step: function (dt) { + console.warn("Action.step() Override me") + }, + + /** + * Called once per frame. Override this method with your implementation to + * update the target. + * + * @param {Float} time How much of the animation has played. 0.0 = just started, 1.0 just finished. + */ + update: function (time) { + console.warn("Action.update() Override me") + }, + + /** + * Called before the action start. It will also set the target. + * + * @param {cocos.nodes.Node} target The Node to run the action on + */ + startWithTarget: function (target) { + this.target = this.originalTarget = target + }, + + /** + * Called after the action has finished. It will set the 'target' to nil. + * Important: You should never call cocos.actions.Action#stop manually. + * Instead, use cocos.nodes.Node#stopAction(action) + */ + stop: function () { + this.target = null + }, + + /** + * @type Boolean + */ + get isDone () { + return true + }, + + /** + * Returns a copy of this Action but in reverse. Overwrite this and inside + * create a new instance of the action, but with the reverse values. + * + * @returns {cocos.actions.Action} A new instance of the Action but in reverse + */ + reverse: function () { + } +}) + +/** + * @class + * Repeats an action forever. To repeat an action for a limited number of + * times use the cocos.actions.Repeat action instead. + * + * @memberOf cocos.actions + * @extends cocos.actions.Action + * + * @param {cocos.actions.Action} action An action to repeat forever + */ +function RepeatForever (action) { + RepeatForever.superclass.constructor.call(this) + + this.other = action +} + +RepeatForever.inherit(Action, /** @lends cocos.actions.RepeatForever# */ { + other: null, + + startWithTarget: function (target) { + RepeatForever.superclass.startWithTarget.call(this, target) + + this.other.startWithTarget(this.target) + }, + + step: function (dt) { + this.other.step(dt) + if (this.other.isDone) { + var diff = dt - this.other.duration - this.other.elapsed + this.other.startWithTarget(this.target) + + this.other.step(diff) + } + }, + + get isDone () { + return false + }, + + reverse: function () { + return new RepeatForever(this.other.reverse()) + }, + + copy: function () { + return new RepeatForever(this.other.copy()) + } +}) + +/** + * @class + * Repeats an action a number of times. To repeat an action forever use the + * cocos.RepeatForever action instead. + * + * @memberOf cocos.actions + * @extends cocos.actions.Action + */ +function FiniteTimeAction () { + FiniteTimeAction.superclass.constructor.call(this) +} + +FiniteTimeAction.inherit(Action, /** @lends cocos.actions.FiniteTimeAction# */ { + /** + * Number of seconds to run the Action for + * @type Float + */ + duration: 2, + + /** @ignore */ + reverse: function () { + console.log('FiniteTimeAction.reverse() Override me') + } +}) + +/** + * @class + * Changes the speed of an action, making it take longer (speed>1) + * or less (speed<1) time. + * Useful to simulate 'slow motion' or 'fast forward' effect. + * @warning This action can't be Sequenceable because it is not an IntervalAction + * + * @memberOf cocos.actions + * @extends cocos.actions.Action + * + * @opt {cocos.actions.Action} action Action to change duration of + * @opt {Float} speed How much to multiply the duration by. Values > 1 increase duration, and < 1 will decrease duration. + */ +function Speed (opts) { + Speed.superclass.constructor.call(this, opts) + + this.other = opts.action + this.speed = opts.speed +} + +Speed.inherit(Action, /** @lends cocos.actions.Speed# */ { + /** + * The action being adjusted + * @type cocos.actions.Action + */ + other: null, + + /** + * Speed of the inner function + * @type Float + */ + speed: 1.0, + + startWithTarget: function (target) { + Speed.superclass.startWithTarget.call(this, target) + this.other.startWithTarget(this.target) + }, + + stop: function () { + this.other.stop() + Speed.superclass.stop.call(this) + }, + + step: function (dt) { + this.other.step(dt * this.speed) + }, + + get isDone () { + return this.other.isDone + }, + + copy: function () { + return new Speed({action: this.other.copy(), speed: this.speed}) + }, + + reverse: function () { + return new Speed({action: this.other.reverse(), speed: this.speed}) + } +}) + +/** + * @class + * An action that "follows" a node. + * + * @memberOf cocos.actions + * @extends cocos.actions.Action + * + * @example layer.runAction(new cocos.actions.Follow({target: hero})) + * + * @opt {cocos.nodes.Node} target + * @opt {geometry.Rect} worldBoundary + */ +function Follow (opts) { + Follow.superclass.constructor.call(this, opts) + + this.followedNode = opts.target + + var s = require('../Director').Director.sharedDirector.winSize + this.fullScreenSize = geo.ccp(s.width, s.height) + this.halfScreenSize = geo.ccpMult(this.fullScreenSize, geo.ccp(0.5, 0.5)) + + if (opts.worldBoundary !== undefined) { + this.boundarySet = true + this.leftBoundary = -((opts.worldBoundary.origin.x + opts.worldBoundary.size.width) - this.fullScreenSize.x) + this.rightBoundary = -opts.worldBoundary.origin.x + this.topBoundary = -opts.worldBoundary.origin.y + this.bottomBoundary = -((opts.worldBoundary.origin.y+opts.worldBoundary.size.height) - this.fullScreenSize.y) + + if (this.rightBoundary < this.leftBoundary) { + // screen width is larger than world's boundary width + //set both in the middle of the world + this.rightBoundary = this.leftBoundary = (this.leftBoundary + this.rightBoundary) / 2 + } + + if (this.topBoundary < this.bottomBoundary) { + // screen width is larger than world's boundary width + //set both in the middle of the world + this.topBoundary = this.bottomBoundary = (this.topBoundary + this.bottomBoundary) / 2 + } + + if ((this.topBoundary == this.bottomBoundary) && (this.leftBoundary == this.rightBoundary)) { + this.boundaryFullyCovered = true + } + } +} + +Follow.inherit(Action, /** @lends cocos.actions.Follow# */ { + /** + * Node to follow + * @type cocos.nodes.Node + */ + followedNode: null, + + /** + * Whether camera should be limited to certain area + * @type Boolean + */ + boundarySet: false, + + /** + * If this screen size is bigger than the boundary - update not needed + * @type Boolean + */ + boundaryFullyCovered: false, + + /** + * Fast access to half the screen dimensions + * @type geometry.Point + */ + halfScreenSize: null, + + /** + * Fast access to the screen dimensions + * @type geometry.Point + */ + fullScreenSize: null, + + /** + * Left edge of world + * @type Float + */ + leftBoundary: 0, + + /** + * Right edge of world + * @type Float + */ + rightBoundary: 0, + + /** + * Top edge of world + * @type Float + */ + topBoundary: 0, + + /** + * Bottom edge of world + * @type Float + */ + bottomBoundary: 0, + + step: function (dt) { + if (this.boundarySet) { + // whole map fits inside a single screen, no need to modify the position - unless map boundaries are increased + if (this.boundaryFullyCovered) { + return + } + var tempPos = geo.ccpSub(this.halfScreenSize, this.followedNode.position) + this.target.position = ccp( Math.min(Math.max(tempPos.x, this.leftBoundary), this.rightBoundary) + , Math.min(Math.max(tempPos.y, this.bottomBoundary), this.topBoundary) + ) + } else { + this.target.position = geo.ccpSub(this.halfScreenSize, this.followedNode.position) + } + }, + + get isDone () { + return !this.followedNode.isRunning + } +}) + + +exports.Action = Action +exports.RepeatForever = RepeatForever +exports.FiniteTimeAction = FiniteTimeAction +exports.Speed = Speed +exports.Follow = Follow + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/actions/Action.js + + +__jah__.resources["/libs/cocos2d/actions/ActionEase.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +"use strict" + +var util = require('util'), + ActionInterval = require('./ActionInterval').ActionInterval, + geo = require('geometry'), + ccp = geo.ccp + +/** + * @class + * Base class for Easing actions + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionInterval + * + * @opt {cocos.actions.ActionInterval} action + */ +function ActionEase (opts) { + if (!opts.action) { + throw "Ease: action argument must be non-nil" + } + ActionEase.superclass.constructor.call(this, {duration: opts.action.duration}) + + this.other = opts.action +} + +ActionEase.inherit(ActionInterval, /** @lends cocos.actions.ActionEase# */ { + other: null, + + startWithTarget: function(target) { + ActionEase.superclass.startWithTarget.call(this, target) + this.other.startWithTarget(this.target) + }, + + stop: function() { + this.other.stop() + ActionEase.superclass.stop.call(this) + }, + + copy: function() { + return new ActionEase({action: this.other.copy()}) + }, + + reverse: function() { + return new ActionEase({action: this.other.reverse()}) + } +}) + +/** + * @class + * Base class for Easing actions with rate parameter + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionEase + * + * @opt {cocos.actions.ActionInterval} action + * @opt {Float} rate + */ +function EaseRate (opts) { + EaseRate.superclass.constructor.call(this, opts) + + this.rate = opts.rate +} + +EaseRate.inherit(ActionEase, /** @lends cocos.actions.EaseRate# */ { + /** + * rate value for the actions + * @type {Float} + */ + rate: 0, + + copy: function() { + return new EaseRate({action: this.other.copy(), rate: this.rate}) + }, + + reverse: function() { + return new EaseRate({action: this.other.reverse(), rate: 1 / this.rate}) + } +}) + +/** + * @class + * Ease In action with a rate + * + * @memberOf cocos.actions + * @extends cocos.actions.EaseRate + */ +function EaseIn (opts) { + EaseIn.superclass.constructor.call(this, opts) +} + +EaseIn.inherit(EaseRate, /** @lends cocos.actions.EaseIn# */ { + update: function(t) { + this.other.update(Math.pow(t, this.rate)) + }, + + copy: function() { + return new EaseIn({action: this.other.copy(), rate: this.rate}) + }, + + reverse: function() { + return new EaseIn({action: this.other.reverse(), rate: 1 / this.rate}) + } +}) + +/** + * @class + * Ease Out action with a rate + * + * @memberOf cocos.actions + * @extends cocos.actions.EaseRate + */ +function EaseOut (opts) { + EaseOut.superclass.constructor.call(this, opts) +} + +EaseOut.inherit(EaseRate, /** @lends cocos.actions.EaseOut# */ { + update: function(t) { + this.other.update(Math.pow(t, 1/this.rate)) + }, + + copy: function() { + return new EaseOut({action: this.other.copy(), rate: this.rate}) + }, + + reverse: function() { + return new EaseOut({action: this.other.reverse(), rate: 1 / this.rate}) + } +}) + +/** + * @class + * Ease In then Out action with a rate + * + * @memberOf cocos.actions + * @extends cocos.actions.EaseRate + */ +function EaseInOut (opts) { + EaseInOut.superclass.constructor.call(this, opts) +} + +EaseInOut.inherit(EaseRate, /** @lends cocos.actions.EaseInOut# */ { + update: function(t) { + var sign = 1 + var r = Math.floor(this.rate) + if (r % 2 == 0) { + sign = -1 + } + t *= 2 + if (t < 1) { + this.other.update(0.5 * Math.pow(t, this.rate)) + } else { + this.other.update(sign * 0.5 * (Math.pow(t-2, this.rate) + sign * 2)) + } + }, + + copy: function() { + return new EaseInOut({action: this.other.copy(), rate: this.rate}) + }, + + reverse: function() { + return new EaseInOut({action: this.other.reverse(), rate: this.rate}) + } +}) + +/** + * @class + * Ease Exponential In action + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionEase + */ +function EaseExponentialIn (opts) { + EaseExponentialIn.superclass.constructor.call(this, opts) +} + +EaseExponentialIn.inherit(ActionEase, /** @lends cocos.actions.EaseExponentialIn# */ { + update: function(t) { + this.other.update((t == 0) ? 0 : (Math.pow(2, 10 * (t/1 - 1)) - 1 * 0.001)) + }, + + copy: function() { + return new EaseExponentialIn({action: this.other.copy()}) + }, + + reverse: function() { + return new exports.EaseExponentialOut({action: this.other.reverse()}) + } +}) + +/** + * @class + * EaseE xponential Out action + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionEase + */ +function EaseExponentialOut (opts) { + EaseExponentialOut.superclass.constructor.call(this, opts) +} + +EaseExponentialOut.inherit(ActionEase, /** @lends cocos.actions.EaseExponentialOut# */ { + update: function(t) { + this.other.update((t == 1) ? 1 : (-Math.pow(2, -10 * t/1) + 1)) + }, + + copy: function() { + return new EaseExponentialOut({action: this.other.copy()}) + }, + + reverse: function() { + return new exports.EaseExponentialIn({action: this.other.reverse()}) + } +}) + +/** + * @class + * Ease Exponential In then Out action + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionEase + */ +function EaseExponentialInOut (opts) { + EaseExponentialInOut.superclass.constructor.call(this, opts) +} + +EaseExponentialInOut.inherit(ActionEase, /** @lends cocos.actions.EaseExponentialInOut# */ { + update: function(t) { + t /= 0.5 + if (t < 1) { + t = 0.5 * Math.pow(2, 10 * (t - 1)) + } else { + t = 0.5 * (-Math.pow(2, -10 * (t - 1)) + 2) + } + this.other.update(t) + }, + + copy: function() { + return new EaseExponentialInOut({action: this.other.copy()}) + }, + + reverse: function() { + return new EaseExponentialInOut({action: this.other.reverse()}) + } +}) + +/** + * @class + * Ease Sine In action + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionEase + */ +function EaseSineIn (opts) { + EaseSineIn.superclass.constructor.call(this, opts) +} + +EaseSineIn.inherit(ActionEase, /** @lends cocos.actions.EaseSineIn# */ { + update: function(t) { + this.other.update(-1 * Math.cos(t * Math.PI_2) + 1) + }, + + copy: function() { + return new EaseSineIn({action: this.other.copy()}) + }, + + reverse: function() { + return new exports.EaseSineOut({action: this.other.reverse()}) + } +}) + +/** + * @class + * Ease Sine Out action + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionEase + */ +function EaseSineOut (opts) { + EaseSineOut.superclass.constructor.call(this, opts) +} + +EaseSineOut.inherit(ActionEase, /** @lends cocos.actions.EaseSineOut# */ { + update: function(t) { + this.other.update(Math.sin(t * Math.PI_2)) + }, + + copy: function() { + return new EaseSineOut({action: this.other.copy()}) + }, + + reverse: function() { + return new exports.EaseSineIn({action: this.other.reverse()}) + } +}) + +/** + * @class + * Ease Sine In then Out action + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionEase + */ +function EaseSineInOut (opts) { + EaseSineInOut.superclass.constructor.call(this, opts) +} + +EaseSineInOut.inherit(ActionEase, /** @lends cocos.actions.EaseSineInOut# */ { + update: function(t) { + this.other.update(-0.5 * (Math.cos(t * Math.PI) - 1)) + }, + + copy: function() { + return new EaseSineInOut({action: this.other.copy()}) + }, + + reverse: function() { + return new EaseSineInOut({action: this.other.reverse()}) + } +}) + + +/** + * @class + * Ease Elastic abstract class + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionEase + * + * @opt {cocos.actions.ActionInterval} action + * @opt {Float} period + */ +function EaseElastic (opts) { + EaseElastic.superclass.constructor.call(this, {action: opts.action}) + + if (opts.period !== undefined) { + this.period = opts.period + } +} + +EaseElastic.inherit(ActionEase, /** @lends cocos.actions.EaseElastic# */ { + /** + * Period of the wave in radians + * @type Float + * @default 0.3 + */ + period: 0.3, + + copy: function() { + return new EaseElastic({action: this.other.copy(), period: this.period}) + }, + + reverse: function() { + window.console.warn("EaseElastic reverse(): Override me") + return null + } +}) + +/** + * @class + * Ease Elastic In action + * + * @memberOf cocos.actions + * @extends cocos.actions.EaseElastic + */ +function EaseElasticIn (opts) { + EaseElasticIn.superclass.constructor.call(this, opts) +} + +EaseElasticIn.inherit(EaseElastic, /** @lends cocos.actions.EaseElasticIn# */ { + update: function(t) { + var newT = 0 + if (t == 0 || t == 1) { + newT = t + } else { + var s = this.period / 4 + t -= 1 + newT = -Math.pow(2, 10 * t) * Math.sin((t - s) * Math.PI*2 / this.period) + } + this.other.update(newT) + }, + + // Wish we could use base class's copy + copy: function() { + return new EaseElasticIn({action: this.other.copy(), period: this.period}) + }, + + reverse: function() { + return new exports.EaseElasticOut({action: this.other.reverse(), period: this.period}) + } +}) + +/** + * @class + * Ease Elastic Out action + * + * @memberOf cocos.actions + * @extends cocos.actions.EaseElastic + */ +function EaseElasticOut (opts) { + EaseElasticOut.superclass.constructor.call(this, opts) +} + +EaseElasticOut.inherit(EaseElastic, /** @lends cocos.actions.EaseElasticOut# */ { + update: function(t) { + var newT = 0 + if (t == 0 || t == 1) { + newT = t + } else { + var s = this.period / 4 + newT = Math.pow(2, -10 * t) * Math.sin((t - s) * Math.PI*2 / this.period) + 1 + } + this.other.update(newT) + }, + + copy: function() { + return new EaseElasticOut({action: this.other.copy(), period: this.period}) + }, + + reverse: function() { + return new exports.EaseElasticIn({action: this.other.reverse(), period: this.period}) + } +}) + +/** + * @class + * Ease Elastic In Out action + * + * @memberOf cocos.actions + * @extends cocos.actions.EaseElastic + */ +function EaseElasticInOut (opts) { + EaseElasticInOut.superclass.constructor.call(this, opts) +} + +EaseElasticInOut.inherit(EaseElastic, /** @lends cocos.actions.EaseElasticInOut# */ { + update: function(t) { + var newT = 0 + if (t == 0 || t == 1) { + newT = t + } else { + t *= 2 + if (this.period == 0) { + this.period = 0.3 * 1.5 + } + var s = this.period / 4 + + t -= 1 + if (t < 0) { + newT = -0.5 * Math.pow(2, 10 * t) * Math.sin((t - s) * Math.PI*2 / this.period) + } else { + newT = Math.pow(2, -10 * t) * Math.sin((t - s) * Math.PI*2 / this.period) * 0.5 + 1 + } + } + this.other.update(newT) + }, + + copy: function() { + return new EaseElasticInOut({action: this.other.copy(), period: this.period}) + }, + + reverse: function() { + return new EaseElasticInOut({action: this.other.reverse(), period: this.period}) + } +}) + +/** + * @class + * Ease Bounce abstract class + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionEase + */ +function EaseBounce (opts) { + EaseBounce.superclass.constructor.call(this, opts) +} + +EaseBounce.inherit(ActionEase, /** @lends cocos.actions.EaseBounce# */ { + bounceTime: function(t) { + // Direct cut & paste from CCActionEase.m, obviously. + // Glad someone else figured out all this math... + if (t < 1 / 2.75) { + return 7.5625 * t * t + } + else if (t < 2 / 2.75) { + t -= 1.5 / 2.75 + return 7.5625 * t * t + 0.75 + } + else if (t < 2.5 / 2.75) { + t -= 2.25 / 2.75 + return 7.5625 * t * t + 0.9375 + } + + t -= 2.625 / 2.75 + return 7.5625 * t * t + 0.984375 + } +}) + +/** + * @class + * Ease Bounce In action + * + * @memberOf cocos.actions + * @extends cocos.actions.EaseBounce + */ +function EaseBounceIn (opts) { + EaseBounceIn.superclass.constructor.call(this, opts) +} + +EaseBounceIn.inherit(EaseBounce, /** @lends cocos.actions.EaseBounceIn# */ { + update: function(t) { + var newT = 1 - this.bounceTime(1-t) + this.other.update(newT) + }, + + copy: function() { + return new EaseBounceIn({action: this.other.copy()}) + }, + + reverse: function() { + return new exports.EaseBounceOut({action: this.other.reverse()}) + } +}) + +/** + * @class + * Ease Bounce Out action + * + * @memberOf cocos.actions + * @extends cocos.actions.EaseBounce + */ +function EaseBounceOut (opts) { + EaseBounceOut.superclass.constructor.call(this, opts) +} + +EaseBounceOut.inherit(EaseBounce, /** @lends cocos.actions.EaseBounceOut# */ { + update: function(t) { + var newT = this.bounceTime(t) + this.other.update(newT) + }, + + copy: function() { + return new EaseBounceOut({action: this.other.copy()}) + }, + + reverse: function() { + return new exports.EaseBounceIn({action: this.other.reverse()}) + } +}) + +/** + * @class + * Ease Bounce In Out action + * + * @memberOf cocos.actions + * @extends cocos.actions.EaseBounce + */ +function EaseBounceInOut (opts) { + EaseBounceInOut.superclass.constructor.call(this, opts) +} + +EaseBounceInOut.inherit(EaseBounce, /** @lends cocos.actions.EaseBounceInOut# */ { + update: function(t) { + var newT = 0 + if (t < 0.5) { + t *= 2 + newT = (1 - this.bounceTime(1 - t)) * 0.5 + } else { + newT = this.bounceTime(t * 2 - 1) * 0.5 + 0.5 + } + this.other.update(newT) + }, + + copy: function() { + return new EaseBounceInOut({action: this.other.copy()}) + }, + + reverse: function() { + return new EaseBounceInOut({action: this.other.reverse()}) + } +}) + +/** + * @class + * Ease Back In action + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionEase + */ +function EaseBackIn (opts) { + EaseBackIn.superclass.constructor.call(this, opts) +} + +EaseBackIn.inherit(ActionEase, /** @lends cocos.actions.EaseBackIn# */ { + update: function(t) { + var overshoot = 1.70158 + this.other.update(t * t * ((overshoot + 1) * t - overshoot)) + }, + + copy: function() { + return new EaseBackIn({action: this.other.copy()}) + }, + + reverse: function() { + return new exports.EaseBackOut({action: this.other.reverse()}) + } +}) + +/** + * @class + * Ease Back Out action + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionEase + */ +function EaseBackOut (opts) { + EaseBackOut.superclass.constructor.call(this, opts) +} + +EaseBackOut.inherit(ActionEase, /** @lends cocos.actions.EaseBackOut# */ { + update: function(t) { + var overshoot = 1.70158 + t -= 1 + this.other.update(t * t * ((overshoot + 1) * t + overshoot) + 1) + }, + + copy: function() { + return new EaseBackOut({action: this.other.copy()}) + }, + + reverse: function() { + return new exports.EaseBackIn({action: this.other.reverse()}) + } +}) + +/** + * @class + * Ease Back In Out action + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionEase + */ +function EaseBackInOut (opts) { + EaseBackInOut.superclass.constructor.call(this, opts) +} + +EaseBackInOut.inherit(ActionEase, /** @lends cocos.actions.EaseBackInOut# */ { + update: function(t) { + // Where do these constants come from? + var overshoot = 1.70158 * 1.525 + t *= 2 + if (t < 1) { + this.other.update((t * t * ((overshoot + 1) * t - overshoot)) / 2) + } else { + t -= 2 + this.other.update((t * t * ((overshoot + 1) * t + overshoot)) / 2 + 1) + } + }, + + copy: function() { + return new EaseBackInOut({action: this.other.copy()}) + }, + + reverse: function() { + return new EaseBackInOut({action: this.other.reverse()}) + } +}) + +exports.ActionEase = ActionEase +exports.EaseRate = EaseRate +exports.EaseIn = EaseIn +exports.EaseOut = EaseOut +exports.EaseInOut = EaseInOut +exports.EaseExponentialIn = EaseExponentialIn +exports.EaseExponentialOut = EaseExponentialOut +exports.EaseExponentialInOut = EaseExponentialInOut +exports.EaseSineIn = EaseSineIn +exports.EaseSineOut = EaseSineOut +exports.EaseSineInOut = EaseSineInOut +exports.EaseElastic = EaseElastic +exports.EaseElasticIn = EaseElasticIn +exports.EaseElasticOut = EaseElasticOut +exports.EaseElasticInOut = EaseElasticInOut +exports.EaseBounce = EaseBounce +exports.EaseBounceIn = EaseBounceIn +exports.EaseBounceOut = EaseBounceOut +exports.EaseBounceInOut = EaseBounceInOut +exports.EaseBackIn = EaseBackIn +exports.EaseBackOut = EaseBackOut +exports.EaseBackInOut = EaseBackInOut + + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/actions/ActionEase.js + + +__jah__.resources["/libs/cocos2d/actions/ActionInstant.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var util = require('util'), + action = require('./Action'), + ccp = require('geometry').ccp + +/** + * @class + * Base class for actions that triggers instantly. They have no duration. + * + * @memberOf cocos.actions + * @extends cocos.actions.FiniteTimeAction + */ +function ActionInstant (opts) { + ActionInstant.superclass.constructor.call(this, opts) + + this.duration = 0 +} + +ActionInstant.inherit(action.FiniteTimeAction, /** @lends cocos.actions.ActionInstant */ { + get isDone () { + return true + }, + + step: function (dt) { + this.update(1) + }, + + update: function (t) { + // ignore + }, + + copy: function() { + return this + }, + + reverse: function () { + return this.copy() + } +}) + +/** + * @class + * Show a node + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionInstant + */ +function Show (opts) { + Show.superclass.constructor.call(this, opts) +} + +Show.inherit(ActionInstant, /** @lends cocos.actions.Show# */ { + startWithTarget: function(target) { + Show.superclass.startWithTarget.call(this, target) + this.target.visible = true + }, + + copy: function() { + return new Show() + }, + + reverse: function() { + return new exports.Hide() + } +}) + +/** + * @class + * Hide a node + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionInstant + */ +function Hide (opts) { + Hide.superclass.constructor.call(this, opts) +} + +Hide.inherit(ActionInstant, /** @lends cocos.actions.Hide# */ { + startWithTarget: function(target) { + Hide.superclass.startWithTarget.call(this, target) + this.target.visible = false + }, + + copy: function() { + return new Hide() + }, + + reverse: function() { + return new exports.Show() + } +}) + +/** + * @class + * Toggles the visibility of a node + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionInstant + */ +function ToggleVisibility (opts) { + ToggleVisibility.superclass.constructor.call(this, opts) +} + +ToggleVisibility.inherit(ActionInstant, /** @lends cocos.actions.ToggleVisibility# */ { + startWithTarget: function(target) { + ToggleVisibility.superclass.startWithTarget.call(this, target) + var vis = this.target.visible + this.target.visible = !vis + }, + + copy: function() { + return new ToggleVisibility() + } +}) + +/** + * @class + * Flips a sprite horizontally + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionInstant + * + * @opt {Boolean} flipX Should the sprite be flipped + */ +function FlipX (opts) { + FlipX.superclass.constructor.call(this, opts) + this.flipX = opts.flipX +} + +FlipX.inherit(ActionInstant, /** @lends cocos.actions.FlipX# */ { + flipX: false, + + startWithTarget: function (target) { + FlipX.superclass.startWithTarget.call(this, target) + + target.flipX = this.flipX + }, + + reverse: function () { + return new FlipX({flipX: !this.flipX}) + }, + + copy: function () { + return new FlipX({flipX: this.flipX}) + } +}) + +/** + * @class + * Flips a sprite vertically + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionInstant + * + * @opt {Boolean} flipY Should the sprite be flipped + */ +function FlipY (opts) { + FlipY.superclass.constructor.call(this, opts) + + this.flipY = opts.flipY +} + +FlipY.inherit(ActionInstant, /** @lends cocos.actions.FlipY# */ { + flipY: false, + + startWithTarget: function (target) { + FlipY.superclass.startWithTarget.call(this, target) + + target.flipY = this.flipY + }, + + reverse: function () { + return new FlipY({flipY: !this.flipY}) + }, + + copy: function () { + return new FlipY({flipY: this.flipY}) + } +}) + +/** + * @class + * Places the node in a certain position + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionInstant + * + * @opt {geometry.Point} position + */ +function Place (opts) { + Place.superclass.constructor.call(this, opts) + this.position = util.copy(opts.position) +} + +Place.inherit(ActionInstant, /** @lends cocos.actions.Place# */ { + position: null, + + startWithTarget: function(target) { + Place.superclass.startWithTarget.call(this, target) + this.target.position = this.position + }, + + copy: function() { + return new Place({position: this.position}) + } +}) + +/** + * @class + * Calls a 'callback' + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionInstant + * + * @opt {Object} target + * @opt {String|Function} method + */ +function CallFunc (opts) { + CallFunc.superclass.constructor.call(this, opts) + + // Save target & method so that copy() can recreate callback + this.target = opts.target + this.method = (typeof opts.method == 'function') ? opts.method : this.target[opts.method] + this.callback = this.method.bind(this.target) +} + +CallFunc.inherit(ActionInstant, /** @lends cocos.actions.CallFunc# */ { + callback: null, + target: null, + method: null, + + startWithTarget: function(target) { + CallFunc.superclass.startWithTarget.call(this, target) + this.execute(target) + }, + + execute: function(target) { + // Pass target to callback + this.callback.call(this, target) + }, + + copy: function() { + return new CallFunc({target: this.target, method: this.method}) + } +}) + +exports.ActionInstant = ActionInstant +exports.Show = Show +exports.Hide = Hide +exports.ToggleVisibility = ToggleVisibility +exports.FlipX = FlipX +exports.FlipY = FlipY +exports.Place = Place +exports.CallFunc = CallFunc + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/actions/ActionInstant.js + + +__jah__.resources["/libs/cocos2d/actions/ActionInterval.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var util = require('util'), + actions = require('./Action'), + geo = require('geometry'), + ccp = geo.ccp + +/** + * @ignore + * + * Creates multiple instances of actionType each given one action plus the next + * actionType instance + */ +function initWithActions (actionType, actions) { + var prev = actions[0].copy() + , now + , i + for (i=1; i= this.duration) + }, + + step: function (dt) { + if (this._firstTick) { + this._firstTick = false + this.elapsed = 0 + } else { + this.elapsed += dt + } + + this.update(Math.min(1, this.elapsed / this.duration)) + }, + + startWithTarget: function (target) { + ActionInterval.superclass.startWithTarget.call(this, target) + + this.elapsed = 0.0 + this._firstTick = true + }, + + copy: function() { + throw "copy() not implemented" + }, + + reverse: function () { + throw "Reverse Action not implemented" + } +}) + +/** + * @class + * Delays the action a certain amount of seconds + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionInterval + */ +function DelayTime () { + DelayTime.superclass.constructor.apply(this, arguments) +} + +DelayTime.inherit(ActionInterval, /** @lends cocos.actions.DelayTime# */ { + update: function (t) { + if (t === 1.0) { + this.stop() + } + }, + + copy: function () { + return new DelayTime({duration: this.duration}) + }, + + reverse: function () { + return new DelayTime({duration: this.duration}) + } +}) + + +/** + * @class + * Scales a cocos.Node object to a zoom factor by modifying it's scale attribute. + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionInterval + * + * @opt {Float} duration Number of seconds to run action for + * @opt {Float} [scale] Size to scale Node to + * @opt {Float} [scaleX] Size to scale width of Node to + * @opt {Float} [scaleY] Size to scale height of Node to + */ +function ScaleTo (opts) { + ScaleTo.superclass.constructor.call(this, opts) + + if (opts.scale !== undefined) { + this.endScaleX = this.endScaleY = opts.scale + } else { + this.endScaleX = opts.scaleX + this.endScaleY = opts.scaleY + } +} + +ScaleTo.inherit(ActionInterval, /** @lends cocos.actions.ScaleTo# */ { + /** + * Current X Scale + * @type Float + */ + scaleX: 1, + + /** + * Current Y Scale + * @type Float + */ + scaleY: 1, + + /** + * Initial X Scale + * @type Float + */ + startScaleX: 1, + + /** + * Initial Y Scale + * @type Float + */ + startScaleY: 1, + + /** + * Final X Scale + * @type Float + */ + endScaleX: 1, + + /** + * Final Y Scale + * @type Float + */ + endScaleY: 1, + + /** + * Delta X Scale + * @type Float + * @private + */ + deltaX: 0.0, + + /** + * Delta Y Scale + * @type Float + * @private + */ + deltaY: 0.0, + + startWithTarget: function (target) { + ScaleTo.superclass.startWithTarget.call(this, target) + + this.startScaleX = this.target.scaleX + this.startScaleY = this.target.scaleY + this.deltaX = this.endScaleX - this.startScaleX + this.deltaY = this.endScaleY - this.startScaleY + }, + + update: function (t) { + if (!this.target) { + return + } + + this.target.scaleX = this.startScaleX + this.deltaX * t + this.target.scaleY = this.startScaleY + this.deltaY * t + }, + + copy: function () { + return new ScaleTo({duration: this.duration, + scaleX: this.endScaleX, + scaleY: this.endScaleY}) + } +}) + +/** + * @class + * Scales a cocos.Node object to a zoom factor by modifying it's scale attribute. + * + * @memberOf cocos.actions + * @extends cocos.actions.ScaleTo + * + * @opt {Float} duration Number of seconds to run action for + * @opt {Float} [scale] Size to scale Node by + * @opt {Float} [scaleX] Size to scale width of Node by + * @opt {Float} [scaleY] Size to scale height of Node by + */ +function ScaleBy (opts) { + ScaleBy.superclass.constructor.call(this, opts) +} + +ScaleBy.inherit(ScaleTo, /** @lends cocos.actions.ScaleBy# */ { + startWithTarget: function (target) { + ScaleBy.superclass.startWithTarget.call(this, target) + + this.deltaX = this.startScaleX * this.endScaleX - this.startScaleX + this.deltaY = this.startScaleY * this.endScaleY - this.startScaleY + }, + + copy: function () { + return new ScaleBy({ duration: this.duration, + scaleX: this.endScaleX, + scaleY: this.endScaleY}) + }, + + reverse: function () { + return new ScaleBy({duration: this.duration, scaleX: 1 / this.endScaleX, scaleY: 1 / this.endScaleY}) + } +}) + + +/** + * @class + * Rotates a cocos.Node object to a certain angle by modifying its rotation + * attribute. The direction will be decided by the shortest angle. + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionInterval + * + * @opt {Float} duration Number of seconds to run action for + * @opt {Float} angle Angle in degrees to rotate to + */ +function RotateTo (opts) { + RotateTo.superclass.constructor.call(this, opts) + + this.dstAngle = opts.angle +} + +RotateTo.inherit(ActionInterval, /** @lends cocos.actions.RotateTo# */ { + /** + * Final angle + * @type Float + */ + dstAngle: 0, + + /** + * Initial angle + * @type Float + */ + startAngle: 0, + + /** + * Angle delta + * @type Float + */ + diffAngle: 0, + + startWithTarget: function (target) { + RotateTo.superclass.startWithTarget.call(this, target) + + this.startAngle = target.rotation + + if (this.startAngle > 0) { + this.startAngle = (this.startAngle % 360) + } else { + this.startAngle = (this.startAngle % -360) + } + + this.diffAngle = this.dstAngle - this.startAngle + if (this.diffAngle > 180) { + this.diffAngle -= 360 + } else if (this.diffAngle < -180) { + this.diffAngle += 360 + } + }, + + update: function (t) { + this.target.rotation = this.startAngle + this.diffAngle * t + }, + + copy: function () { + return new RotateTo({duration: this.duration, angle: this.dstAngle}) + } +}) + +/** + * @class + * Rotates a cocos.Node object to a certain angle by modifying its rotation + * attribute. The direction will be decided by the shortest angle. + * + * @memberOf cocos.actions + * @extends cocos.actions.RotateTo + * + * @opt {Float} duration Number of seconds to run action for + * @opt {Float} angle Angle in degrees to rotate by + */ +function RotateBy (opts) { + RotateBy.superclass.constructor.call(this, opts) + + this.angle = opts.angle +} + +RotateBy.inherit(RotateTo, /** @lends cocos.actions.RotateBy# */ { + /** + * Number of degrees to rotate by + * @type Float + */ + angle: 0, + + startWithTarget: function (target) { + RotateBy.superclass.startWithTarget.call(this, target) + + this.startAngle = this.target.rotation + }, + + update: function (t) { + this.target.rotation = this.startAngle + this.angle * t + }, + + copy: function () { + return new RotateBy({duration: this.duration, angle: this.angle}) + }, + + reverse: function () { + return new RotateBy({duration: this.duration, angle: -this.angle}) + } +}) + +/** + * @class + * Animates moving a cocos.nodes.Node object to a another point. + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionInterval + * + * @opt {Float} duration Number of seconds to run action for + * @opt {geometry.Point} position Destination position + */ +function MoveTo (opts) { + MoveTo.superclass.constructor.call(this, opts) + + this.endPosition = util.copy(opts.position) +} + +MoveTo.inherit(ActionInterval, /** @lends cocos.actions.MoveTo# */ { + delta: null, + startPosition: null, + endPosition: null, + + startWithTarget: function (target) { + MoveTo.superclass.startWithTarget.call(this, target) + + this.startPosition = util.copy(target.position) + this.delta = geo.ccpSub(this.endPosition, this.startPosition) + }, + + update: function (t) { + var startPosition = this.startPosition, + delta = this.delta + this.target.position = ccp(startPosition.x + delta.x * t, startPosition.y + delta.y * t) + }, + + copy: function() { + return new MoveTo({duration: this.duration, position: this.endPosition}) + } +}) + +/** + * @class + * Animates moving a cocos.node.Node object by a given number of pixels + * + * @memberOf cocos.actions + * @extends cocos.actions.MoveTo + * + * @opt {Float} duration Number of seconds to run action for + * @opt {geometry.Point} position Number of pixels to move by + */ +function MoveBy (opts) { + MoveBy.superclass.constructor.call(this, opts) + + this.delta = util.copy(opts.position) +} + +MoveBy.inherit(MoveTo, /** @lends cocos.actions.MoveBy# */ { + startWithTarget: function (target) { + var dTmp = this.delta + MoveBy.superclass.startWithTarget.call(this, target) + this.delta = dTmp + }, + + copy: function() { + return new MoveBy({duration: this.duration, position: this.delta}) + }, + + reverse: function() { + var delta = this.delta + return new MoveBy({duration: this.duration, position: geo.ccp(-delta.x, -delta.y)}) + } +}) + +/** + * @class + * Moves a cocos.nodes.Node simulating a parabolic jump movement by modifying its position attribute. + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionInterval + * + * @opt {Float} duration Number of seconds to run action for + * @opt {geometry.Point} startPosition Point at which jump starts + * @opt {geometry.Point} delta Number of pixels to jump by + * @opt {Float} height Height of jump + * @opt {Integer} jumps Number of times to repeat + */ +function JumpBy (opts) { + JumpBy.superclass.constructor.call(this, opts) + + this.delta = util.copy(opts.delta) + this.height = opts.height + this.jumps = opts.jumps +} + +JumpBy.inherit(ActionInterval, /** @lends cocos.actions.JumpBy# */ { + /** + * Number of pixels to jump by + * @type geometry.Point + */ + delta: null, + + /** + * Height of jump + * @type Float + */ + height: 0, + + /** + * Number of times to jump + * @type Integer + */ + jumps: 0, + + /** + * Starting point + * @type geometry.Point + */ + startPosition: null, + + copy: function() { + return new JumpBy({duration: this.duration, + delta: this.delta, + height: this.height, + jumps: this.jumps}) + }, + + startWithTarget: function(target) { + JumpBy.superclass.startWithTarget.call(this, target) + this.startPosition = target.position + }, + + update: function(t) { + // parabolic jump + var frac = (t * this.jumps) % 1.0 + var y = this.height * 4 * frac * (1 - frac) + y += this.delta.y * t + var x = this.delta.x * t + this.target.position = geo.ccp(this.startPosition.x + x, this.startPosition.y + y) + }, + + reverse: function() { + return new JumpBy({duration: this.duration, + delta: geo.ccp(-this.delta.x, -this.delta.y), + height: this.height, + jumps: this.jumps}) + } +}) + +/** + * @class + * Moves a Node to a parabolic position simulating a jump movement by modifying its position attribute. + * + * @memberOf cocos.actions + * @extends cocos.actions.JumpBy + */ +function JumpTo (opts) { + JumpTo.superclass.constructor.call(this, opts) +} + +JumpTo.inherit(JumpBy, /** @lends cocos.actions.JumpTo# */ { + startWithTarget: function(target) { + JumpTo.superclass.startWithTarget.call(this, target) + this.delta = geo.ccp(this.delta.x - this.startPosition.x, this.delta.y - this.startPosition.y) + } +}) + +/** + * @class + * An action that moves the target with a cubic Bezier curve by a certain distance. + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionInterval + * + * @opt {geometry.BezierConfig} bezier Bezier control points object + * @opt {Float} duration + */ +function BezierBy (opts) { + BezierBy.superclass.constructor.call(this, opts) + + this.config = util.copy(opts.bezier) +} + +BezierBy.inherit(ActionInterval, /** @lends cocos.actions.BezierBy# */ { + /** + * @type {geometry.BezierConfig} + */ + config: null, + + startPosition: null, + + startWithTarget: function(target) { + BezierBy.superclass.startWithTarget.call(this, target) + this.startPosition = this.target.position + }, + + update: function(t) { + var c = this.config + var xa = 0, + xb = c.controlPoint1.x, + xc = c.controlPoint2.x, + xd = c.endPosition.x, + ya = 0, + yb = c.controlPoint1.y, + yc = c.controlPoint2.y, + yd = c.endPosition.y + + var x = bezierat(xa, xb, xc, xd, t) + var y = bezierat(ya, yb, yc, yd, t) + + this.target.position = geo.ccpAdd(this.startPosition, geo.ccp(x, y)) + }, + + copy: function() { + return new BezierBy({bezier: this.config, duration: this.duration}) + }, + + reverse: function() { + var c = this.config, + bc = new geo.BezierConfig() + + bc.endPosition = geo.ccpNeg(c.endPosition) + bc.controlPoint1 = geo.ccpAdd(c.controlPoint2, geo.ccpNeg(c.endPosition)) + bc.controlPoint2 = geo.ccpAdd(c.controlPoint1, geo.ccpNeg(c.endPosition)) + + return new BezierBy({bezier: bc, duration: this.duration}) + } +}) + +/** + * @class + * An action that moves the target with a cubic Bezier curve to a destination point. + * + * @memberOf cocos.actions + * @extends cocos.actions.BezierBy + */ +function BezierTo (opts) { + BezierTo.superclass.constructor.call(this, opts) +} + +BezierTo.inherit(BezierBy, /** @lends cocos.actions.BezierTo# */ { + startWithTarget: function(target) { + BezierTo.superclass.startWithTarget.call(this, target) + + var c = this.config + c.controlPoint1 = geo.ccpSub(c.controlPoint1, this.startPosition) + c.controlPoint2 = geo.ccpSub(c.controlPoint2, this.startPosition) + c.endPosition = geo.ccpSub(c.endPosition, this.startPosition) + } +}) + +/** + * @class + * Blinks a Node object by modifying it's visible attribute + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionInterval + * + * @opt {Integer} blinks Number of times to blink + * @opt {Float} duration + */ +function Blink (opts) { + Blink.superclass.constructor.call(this, opts) + this.times = opts.blinks +} + +Blink.inherit(ActionInterval, /** @lends cocos.actions.Blink# */ { + /** + * @type {Integer} + */ + times: 1, + + update: function(t) { + if (!this.isDone) { + var slice = 1 / this.times + var m = t % slice + this.target.visible = (m > slice/2) + } + }, + + copy: function() { + return new Blink({duration: this.duration, blinks: this.times}) + }, + + reverse: function() { + return this.copy() + } +}) + +/** + * @class + * Fades out a cocos.nodes.Node to zero opacity + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionInterval + */ +function FadeOut (opts) { + FadeOut.superclass.constructor.call(this, opts) +} + +FadeOut.inherit(ActionInterval, /** @lends cocos.actions.FadeOut# */ { + update: function (t) { + var target = this.target + if (!target) return + target.opacity = 255 - (255 * t) + }, + + copy: function () { + return new FadeOut({duration: this.duration}) + }, + + reverse: function () { + return new exports.FadeIn({duration: this.duration}) + } +}) + + +/** + * @class + * Fades in a cocos.nodes.Node to 100% opacity + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionInterval + */ +function FadeIn (opts) { + FadeIn.superclass.constructor.call(this, opts) +} + +FadeIn.inherit(ActionInterval, /** @lends cocos.actions.FadeIn# */ { + update: function (t) { + var target = this.target + if (!target) return + target.opacity = t * 255 + }, + + copy: function () { + return new FadeIn({duration: this.duration}) + }, + + reverse: function () { + return new exports.FadeOut({duration: this.duration}) + } +}) + +/** + * @class + * Fades a cocos.nodes.Node to a given opacity + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionInterval + */ +function FadeTo (opts) { + FadeTo.superclass.constructor.call(this, opts) + this.toOpacity = opts.toOpacity +} + +FadeTo.inherit(ActionInterval, /** @lends cocos.actions.FadeTo# */ { + /** + * The final opacity + * @type Float + */ + toOpacity: null, + + /** + * The initial opacity + * @type Float + */ + fromOpacity: null, + + startWithTarget: function (target) { + FadeTo.superclass.startWithTarget.call(this, target) + this.fromOpacity = this.target.opacity + }, + + update: function (t) { + var target = this.target + if (!target) return + + target.opacity = this.fromOpacity + ( this.toOpacity - this.fromOpacity ) * t + }, + + copy: function() { + return new FadeTo({duration: this.duration, toOpacity: this.toOpacity}) + } +}) + +/** + * @class + * Runs a pair of actions sequentially, one after another + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionInterval + * + * @opt {cocos.actions.FiniteTimeAction} one 1st action to run + * @opt {cocos.actions.FiniteTimeAction} two 2nd action to run + */ +function Sequence (opts) { + if (opts.actions) { + return initWithActions(Object.getPrototypeOf(this).constructor, opts.actions) + } + + if (!opts.one) { + throw "Sequence argument one must be non-nil" + } + if (!opts.two) { + throw "Sequence argument two must be non-nil" + } + this.actions = [] + + var d = opts.one.duration + opts.two.duration + + Sequence.superclass.constructor.call(this, {duration: d}) + + this.actions[0] = opts.one + this.actions[1] = opts.two +} + +Sequence.inherit(ActionInterval, /** @lends cocos.actions.Sequence# */ { + /** + * Array of actions to run + * @type cocos.nodes.Node[] + */ + actions: null, + + split: 0, + last: 0, + + startWithTarget: function (target) { + Sequence.superclass.startWithTarget.call(this, target) + this.split = this.actions[0].duration / this.duration + this.last = -1 + }, + + stop: function () { + this.actions[0].stop() + this.actions[1].stop() + Sequence.superclass.stop.call(this) + }, + + update: function (t) { + // This is confusing but will hopefully work better in conjunction + // with modifer actions like Repeat & Spawn... + var found = 0 + var new_t = 0 + + if (t >= this.split) { + found = 1 + if (this.split == 1) { + new_t = 1 + } else { + new_t = (t - this.split) / (1 - this.split) + } + } else { + found = 0 + if (this.split != 0) { + new_t = t / this.split + } else { + new_t = 1 + } + } + if (this.last == -1 && found == 1) { + this.actions[0].startWithTarget(this.target) + this.actions[0].update(1) + this.actions[0].stop() + } + if (this.last != found) { + if (this.last != -1) { + this.actions[this.last].update(1) + this.actions[this.last].stop() + } + this.actions[found].startWithTarget(this.target) + } + this.actions[found].update(new_t) + this.last = found + }, + + copy: function () { + // Constructor will copy actions + return new Sequence({actions: this.actions}) + }, + + reverse: function() { + return new Sequence({actions: [this.actions[1].reverse(), this.actions[0].reverse()]}) + } +}) + +/** + * @class + * Repeats an action a number of times. + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionInterval + * + * @opt {cocos.actions.ActionInterval} action Action to repeat + * @opt {Integer} times Number of times to repeat + */ +function Repeat (opts) { + var d = opts.action.duration * opts.times + + Repeat.superclass.constructor.call(this, {duration: d}) + + this.times = opts.times + this.other = opts.action.copy() + this.total = 0 +} + +Repeat.inherit(ActionInterval, /** @lends cocos.actions.Repeat# */ { + times: 1, + total: 0, + other: null, + + startWithTarget: function(target) { + this.total = 0 + Repeat.superclass.startWithTarget.call(this, target) + this.other.startWithTarget(target) + }, + + stop: function() { + this.other.stop() + Repeat.superclass.stop.call(this) + }, + + update: function(dt) { + var t = dt * this.times + + if (t > (this.total+1)) { + this.other.update(1) + this.total += 1 + this.other.stop() + this.other.startWithTarget(this.target) + + // If repeat is over + if (this.total == this.times) { + // set it in the original position + this.other.update(0) + } else { + // otherwise start next repeat + this.other.update(t - this.total) + } + } else { + var r = t % 1.0 + + // fix last repeat position otherwise it could be 0 + if (dt == 1) { + r = 1 + this.total += 1 + } + this.other.update(Math.min(r, 1)) + } + }, + + get isDone() { + return this.total == this.times + }, + + copy: function() { + // Constructor copies action + return new Repeat({action: this.other, times: this.times}) + }, + + reverse: function() { + return new Repeat({action: this.other.reverse(), times: this.times}) + } +}) + +/** + * @class + * Executes multiple actions simultaneously + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionInterval + * + * @opt {cocos.actions.FiniteTimeAction} one: first action to spawn + * @opt {cocos.actions.FiniteTimeAction} two: second action to spawn + */ +function Spawn (opts) { + if (opts.actions) { + return initWithActions(Object.getPrototypeOf(this).constructor, opts.actions) + } + + var action1 = opts.one, + action2 = opts.two + + if (!action1 || !action2) { + throw "cocos.actions.Spawn: required actions missing" + } + var d1 = action1.duration, + d2 = action2.duration + + Spawn.superclass.constructor.call(this, {duration: Math.max(d1, d2)}) + + this.one = action1 + this.two = action2 + + if (d1 > d2) { + this.set('two', new Sequence({actions: [ + action2, + new DelayTime({duration: d1-d2}) + ]})) + } else if (d1 < d2) { + this.set('one', new Sequence({actions: [ + action1, + new DelayTime({duration: d2-d1}) + ]})) + } +} + +Spawn.inherit(ActionInterval, /** @lends cocos.actions.Spawn# */ { + one: null, + two: null, + + startWithTarget: function (target) { + Spawn.superclass.startWithTarget.call(this, target) + this.one.startWithTarget(this.target) + this.two.startWithTarget(this.target) + }, + + stop: function () { + this.one.stop() + this.two.stop() + Spawn.superclass.stop.call(this) + }, + + step: function (dt) { + if (this._firstTick) { + this._firstTick = false + this.elapsed = 0 + } else { + this.elapsed += dt + } + this.one.step(dt) + this.two.step(dt) + }, + + update: function (t) { + this.one.update(t) + this.two.update(t) + }, + + copy: function () { + return new Spawn({one: this.one.copy(), two: this.two.copy()}) + }, + + reverse: function () { + return new Spawn({one: this.one.reverse(), two: this.two.reverse()}) + } +}) + +/** + * @class + * Animates a sprite given the name of an Animation + * + * @memberOf cocos.actions + * @extends cocos.actions.ActionInterval + * + * @opt {Float} duration Number of seconds to run action for + * @opt {cocos.Animation} animation Animation to run + * @opt {Boolean} [restoreOriginalFrame=true] Return to first frame when finished + */ +function Animate (opts) { + this.animation = opts.animation + this.restoreOriginalFrame = opts.restoreOriginalFrame !== false + opts.duration = this.animation.frames.length * this.animation.delay + + Animate.superclass.constructor.call(this, opts) +} + +Animate.inherit(ActionInterval, /** @lends cocos.actions.Animate# */ { + animation: null, + restoreOriginalFrame: true, + origFrame: null, + + startWithTarget: function (target) { + Animate.superclass.startWithTarget.call(this, target) + + if (this.restoreOriginalFrame) { + this.origFrame = this.target.displayedFrame + } + }, + + stop: function () { + if (this.target && this.restoreOriginalFrame) { + var sprite = this.target + sprite.displayFrame = this.origFrame + } + + Animate.superclass.stop.call(this) + }, + + update: function (t) { + var frames = this.animation.frames, + numberOfFrames = frames.length, + idx = Math.floor(t * numberOfFrames) + + if (idx >= numberOfFrames) { + idx = numberOfFrames - 1 + } + + var sprite = this.target + if (!sprite.isFrameDisplayed(frames[idx])) { + sprite.displayFrame = frames[idx] + } + }, + + copy: function () { + return new Animate({animation: this.animation, restoreOriginalFrame: this.restoreOriginalFrame}) + } + +}) + +exports.ActionInterval = ActionInterval +exports.DelayTime = DelayTime +exports.ScaleTo = ScaleTo +exports.ScaleBy = ScaleBy +exports.RotateTo = RotateTo +exports.RotateBy = RotateBy +exports.MoveTo = MoveTo +exports.MoveBy = MoveBy +exports.JumpBy = JumpBy +exports.JumpTo = JumpTo +exports.BezierBy = BezierBy +exports.BezierTo = BezierTo +exports.Blink = Blink +exports.FadeIn = FadeIn +exports.FadeOut = FadeOut +exports.FadeTo = FadeTo +exports.Spawn = Spawn +exports.Sequence = Sequence +exports.Repeat = Repeat +exports.Animate = Animate + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/actions/ActionInterval.js + + +__jah__.resources["/libs/cocos2d/actions/index.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var util = require('util'), + path = require('path') + + +var modules = 'Action ActionInterval ActionInstant ActionEase'.split(' ') + +/** + * @memberOf cocos + * @namespace Actions used to animate or change a Node + */ +var actions = {} + +util.each(modules, function (mod, i) { + util.extend(actions, require('./' + mod)) +}) + +module.exports = actions + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/actions/index.js + + +__jah__.resources["/libs/cocos2d/Animation.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var util = require('util') + +/** + * @class + * A cocos.Animation object is used to perform animations on the Sprite objects. + * + * The Animation object contains cocos.SpriteFrame objects, and a possible delay between the frames. + * You can animate a cocos.Animation object by using the cocos.actions.Animate action. + * + * @memberOf cocos + * + * @opt {cocos.SpriteFrame[]} frames Frames to animate + * @opt {Float} [delay=0.0] Delay between each frame + * + * @example + * var animation = new cocos.Animation({frames: [f1, f2, f3], delay: 0.1}) + * sprite.runAction(new cocos.actions.Animate({animation: animation})) + */ +function Animation (opts) { + Animation.superclass.constructor.call(this, opts) + + this.frames = opts.frames || [] + this.delay = opts.delay || 0.0 +} + +Animation.inherit(Object, /** @lends cocos.Animation# */ { + /** + * Unique name for the animation + * @type String + */ + name: null + + /** + * Delay between each frame + * @type Float + */ + , delay: 0.0 + + /** + * Array of frames to animate + * @type cocos.SpriteFrame[] + */ + , frames: null +}) + +exports.Animation = Animation + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/Animation.js + + +__jah__.resources["/libs/cocos2d/AnimationCache.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var util = require('util'), + Plist = require('Plist').Plist + +/** + * @class + * + * @memberOf cocos + * @singleton + */ +function AnimationCache () { + AnimationCache.superclass.constructor.call(this) + + this.animations = {} +} + +AnimationCache.inherit(Object, /** @lends cocos.AnimationCache# */ { + /** + * Cached animations + * @type Object + */ + animations: null, + + /** + * Add an animation to the cache + * + * @opt {String} name Unique name of the animation + * @opt {cocos.Animcation} animation Animation to cache + */ + addAnimation: function (opts) { + var name = opts.name, + animation = opts.animation + + this.animations[name] = animation + }, + + /** + * Remove an animation from the cache + * + * @opt {String} name Unique name of the animation + */ + removeAnimation: function (opts) { + var name = opts.name + + delete this.animations[name] + }, + + /** + * Get an animation from the cache + * + * @opt {String} name Unique name of the animation + * @returns {cocos.Animation} Cached animation + */ + getAnimation: function (opts) { + var name = opts.name + + return this.animations[name] + } +}) + +Object.defineProperty(AnimationCache, 'sharedAnimationCache', { + /** + * A shared singleton instance of cocos.AnimationCache + * + * @memberOf cocos.AnimationCache + * @getter {cocos.AnimationCache} sharedAnimationCache + */ + get: function () { + if (!AnimationCache._instance) { + AnimationCache._instance = new this() + } + + return AnimationCache._instance + } + + , enumerable: true +}) + +exports.AnimationCache = AnimationCache + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/AnimationCache.js + + +__jah__.resources["/libs/cocos2d/config.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +module.exports = { + // Enable BObject's get/set/extend/etc methods + ENABLE_DEPRECATED_METHODS: false, + + // Invert the Y axis so origin is at the bottom left + FLIP_Y_AXIS: true, + + // No implemented yet + ENABLE_WEB_GL: false, + + SHOW_REDRAW_REGIONS: false +} + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/config.js + + +__jah__.resources["/libs/cocos2d/Director.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var util = require('util') + , events = require('events') + , geo = require('geometry') + , ccp = geo.ccp + +var EventDispatcher = require('./EventDispatcher').EventDispatcher + , TouchDispatcher = require('./TouchDispatcher').TouchDispatcher + , Scheduler = require('./Scheduler').Scheduler + +/** + * Create a new instance of Director. This is a singleton so you shouldn't use + * the constructor directly. Instead grab the shared instance using the + * cocos.Director.sharedDirector property. + * + * @class + * Creates and handles the main view and manages how and when to execute the + * Scenes. + * + * This class is a singleton so don't instantiate it yourself, instead use + * cocos.Director.sharedDirector to return the instance. + * + * @memberOf cocos + * @singleton + */ +function Director () { + if (Director._instance) { + throw new Error('Director instance already exists') + } + + this.sceneStack = [] + this.window = window + this.document = this.window.document + // this.window = parent.window + // this.document = this.window.document + + // Prevent writing to some properties + util.makeReadonly(this, 'canvas context sceneStack winSize isReady document window container isTouchScreen isMobile'.w) +} + +Director.inherit(Object, /** @lends cocos.Director# */ { + /** + * Background colour of the canvas. It can be any valid CSS colour. + * @type String + */ + backgroundColor: 'rgb(0, 0, 0)' + + /** + * DOM Window of the containing page + * + * The global 'window' property is a sandbox and not the global of the + * containing page. If you need to access the real window, use this + * property. + * + * @type DOMWindow + * @readonly + */ + , window: null + + /** + * DOM Document of the containing page + * + * The global 'document' property is a sandbox and not the global of the + * containing page. If you need to access the real document, use this + * property. + * + * @type Document + * @readonly + */ + , document: null + + /** + * Container DIV around the canvas + * + * This element is created dynamically. Its parent is the HTML element the + * script was added into. + * + * @type HTMLDivElement + * @readonly + */ + , container: null + + /** + * Canvas HTML element + * @type HTMLCanvasElement + * @readonly + */ + , canvas: null + + /** + * Canvas rendering context + * @type CanvasRenderingContext2D + * @readonly + */ + , context: null + + /** + * Stack of scenes + * @type cocos.nodes.Scene[] + * @readonly + */ + , sceneStack: null + + /** + * Size of the canvas + * @type geometry.Size + * @readonly + */ + , winSize: null + + /** + * Whether the scene is paused. When true the framerate will drop to conserve CPU + * @type Boolean + */ + , isPaused: false + + /** + * Maximum possible framerate + * @type Integer + */ + , maxFrameRate: 30 + + /** + * Should the framerate be drawn in the corner + * @type Boolean + */ + , displayFPS: false + + /** + * Scene that draws the preload progres bar + * @type cocos.nodes.PreloadScene + */ + , preloadScene: null + + /** + * Has everything been preloaded and ready to use + * @type Boolean + * @readonly + */ + , isReady: false + + /** + * Is this running on a touchscreen device. e.g. iPhone or iPad + * @type Boolean + * @readonly + */ + , isTouchScreen: false + + /** + * Are we running on a mobile device? + * @type Boolean + * @readonly + */ + , isMobile: false + + + /** + * Number of milliseconds since last frame + * @type Float + * @readonly + */ + , dt: 0 + + /** + * The current orientation. Only available on mobile devices + * @type String + * @readonly + */ + , orientation: 'unknown' + + /** + * @private + */ + , _nextDeltaTimeZero: false + + /** + * @private + * @type Float + */ + , _lastUpdate: 0 + + /** + * @private + * @type cocos.nodes.Scene + */ + , _nextScene: null + + , _forcedOrientation: null + + /** + * Make the canvas fullscreen. + * On mobile devices this will try to set the viewport to avoid scaling the canvas + */ + , fullscreen: function () { + throw new Error("Fullscreen is not implemented on non-mobile devices yet") + } + + /** + * Resize the canvas to any size + * + * @param {Float} width The new width of the canvas + * @param {Float} height The new height of the canvas + */ + , resize: function (width, height) { + if (!this.container) { + return + } + + events.trigger(this, 'beforeresize', {newSize: new geo.Size(width, height)}) + + this.container.style.width = width + 'px' + this.container.style.height = height + 'px' + this.canvas.width = width + this.canvas.height = height + + this._winSize = new geo.Size(width, height) + + var viewWidth = this.container.offsetWidth + , viewHeight = this.container.offsetHeight + this._viewSize = new geo.Size(viewWidth, viewHeight) + this._viewScale = new geo.Size(width / viewWidth, height / viewHeight) + + + if (cc.FLIP_Y_AXIS) { + this.context.translate(0, height) + this.context.scale(1, -1) + } + + events.trigger(this, 'resize') + } + + /** + * Append to an HTML element. It will create this canvas tag and attach + * event listeners + * + * @param {HTMLElement} view Any HTML element to add the application to + */ + , attachInView: function (view) { + var document = this.document + + view = view || window.container || document.body + + while (view.firstChild) { + view.removeChild(view.firstChild) + } + + // Wrapper
which can be used for adding special HTML elements if required + var container = this._container = document.createElement('div') + container.style.position = 'relative' + container.style.overflow = 'hidden' + view.appendChild(container) + + var canvas = document.createElement('canvas') + canvas.style.verticalAlign = 'bottom' + this._canvas = canvas + + var context = canvas.getContext('2d') + this._context = context + + this.resize(view.clientWidth, view.clientHeight) + + container.appendChild(canvas) + + this._setupEventCapturing() + + if (this._isFullscreen) { + this.fullscreen() + } + } + + , _setupEventCapturing: function () { + var document = this.document + , canvas = this.canvas + + var eventDispatcher = EventDispatcher.sharedDispatcher + + this._setupMouseEventCapturing() + + // Keyboard events + function keyDown(evt) { + this._keysDown = this._keysDown || {} + eventDispatcher.keyDown(evt) + } + function keyUp(evt) { + eventDispatcher.keyUp(evt) + } + + document.documentElement.addEventListener('keydown', keyDown, false) + document.documentElement.addEventListener('keyup', keyUp, false) + } + + , _setupMouseEventCapturing: function () { + var document = this.document + , canvas = this.canvas + + var eventDispatcher = EventDispatcher.sharedDispatcher + + var mouseDown = function (evt) { + evt.locationInWindow = ccp(evt.clientX, evt.clientY) + evt.locationInCanvas = this.convertEventToCanvas(evt) + + var mouseDragged = function (evt) { + evt.locationInWindow = ccp(evt.clientX, evt.clientY) + evt.locationInCanvas = this.convertEventToCanvas(evt) + + eventDispatcher.mouseDragged(evt) + }.bind(this) + + var mouseUp = function (evt) { + evt.locationInWindow = ccp(evt.clientX, evt.clientY) + evt.locationInCanvas = this.convertEventToCanvas(evt) + + document.body.removeEventListener('mousemove', mouseDragged, false) + document.body.removeEventListener('mouseup', mouseUp, false) + + + eventDispatcher.mouseUp(evt) + }.bind(this) + + document.body.addEventListener('mousemove', mouseDragged, false) + document.body.addEventListener('mouseup', mouseUp, false) + + eventDispatcher.mouseDown(evt) + }.bind(this) + + var mouseMoved = function (evt) { + evt.locationInWindow = ccp(evt.clientX, evt.clientY) + evt.locationInCanvas = this.convertEventToCanvas(evt) + + eventDispatcher.mouseMoved(evt) + }.bind(this) + + canvas.addEventListener('mousedown', mouseDown, false) + canvas.addEventListener('mousemove', mouseMoved, false) + } + + /** + * Create and push a Preload Scene which will draw a progress bar while + * also preloading all assets. + * + * If you wish to customise the preload scene first inherit from cocos.nodes.PreloadScene + * and then set Director.sharedDirector.preloadScene to an instance of your PreloadScene + */ + , runPreloadScene: function () { + if (!this.canvas) { + this.attachInView() + } + + var preloader = this.preloadScene + if (!preloader) { + var PreloadScene = this.preloadSceneConstructor || require('./nodes/ProgressBarPreloadScene').ProgressBarPreloadScene + preloader = new PreloadScene() + this.preloadScene = preloader + } + + events.addListener(preloader, 'complete', function (preloader) { + this._isReady = true + events.trigger(this, 'ready', this) + }.bind(this)) + + this.pushScene(preloader) + this.startAnimation() + } + + /** + * Enters the Director's main loop with the given Scene. Call it to run + * only your FIRST scene. Don't call it if there is already a running + * scene. + * + * @param {cocos.nodes.Scene} scene The scene to start + */ + , runWithScene: function (scene) { + var Scene = require('./nodes/Scene').Scene + if (!(scene instanceof Scene)) { + throw new Error("Director.runWithScene must be given an instance of Scene") + } + + if (this._runningScene) { + throw new Error("You can't run a Scene if another Scene is already running. Use replaceScene or pushScene instead") + } + + this.pushScene(scene) + this.startAnimation() + } + + /** + * Replaces the running scene with a new one. The running scene is + * terminated. ONLY call it if there is a running scene. + * + * @param {cocos.nodes.Scene} scene The scene to replace with + */ + , replaceScene: function (scene) { + var Scene = require('./nodes/Scene').Scene + if (!(scene instanceof Scene)) { + throw new Error("Director.replaceScene must be given an instance of Scene") + } + var index = this.sceneStack.length + + this._sendCleanupToScene = true + this.sceneStack.pop() + this.sceneStack.push(scene) + this._nextScene = scene + } + + /** + * Pops out a scene from the queue. This scene will replace the running + * one. The running scene will be deleted. If there are no more scenes in + * the stack the execution is terminated. ONLY call it if there is a + * running scene. + */ + , popScene: function () { + throw new Error("Not implemented yet") + } + + /** + * Suspends the execution of the running scene, pushing it on the stack of + * suspended scenes. The new scene will be executed. Try to avoid big + * stacks of pushed scenes to reduce memory allocation. ONLY call it if + * there is a running scene. + * + * @param {cocos.Scene} scene The scene to add to the stack + */ + , pushScene: function (scene) { + var Scene = require('./nodes/Scene').Scene + if (!(scene instanceof Scene)) { + throw new Error("Director.pushScene must be given an instance of Scene") + } + this._nextScene = scene + } + + /** + * The main loop is triggered again. Call this function only if + * cocos.Directory#stopAnimation was called earlier. + */ + , startAnimation: function () { + if (!this.canvas) { + this.attachInView() + } + + this._animating = true + this.animate() + } + + /** + * Draws the scene after waiting for the next animation frame time. This + * controls the framerate. + */ + , animate: function() { + if (this._animating) { + this.drawScene() + this.animate._bound = this.animate._bound || this.animate.bind(this) + window.requestAnimationFrame(this.animate._bound, this.canvas) + } + } + + /** + * Stops the animation. Nothing will be drawn. The main loop won't be + * triggered anymore. If you want to pause your animation call + * cocos.Directory#pause instead. + */ + , stopAnimation: function () { + if (this._animationTimer) { + clearInterval(this._animationTimer) + this._animationTimer = null + } + this._animating = false + } + + /** + * @private + * Calculate time since last call + */ + , _calculateDeltaTime: function () { + var now = (new Date()).getTime() / 1000 + + if (this._nextDeltaTimeZero) { + this.dt = 0 + this._nextDeltaTimeZero = false + } + + this.dt = Math.max(0, now - this._lastUpdate) + + this._lastUpdate = now + } + + /** + * @private + * The main run loop + */ + , drawScene: function () { + this._calculateDeltaTime() + + if (!this.isPaused) { + Scheduler.sharedScheduler.tick(this.dt) + } + + + var context = this.context + context.fillStyle = this.backgroundColor + context.fillRect(0, 0, this.winSize.width, this.winSize.height) + //this.canvas.width = this.canvas.width + + + if (this._nextScene) { + this._setNextScene() + } + + // TODO partial redrawing + var rect = new geo.Rect(0, 0, this.winSize.width, this.winSize.height) + + this._runningScene.visit(context, rect) + + if (this.displayFPS) { + this._showFPS() + } + } + + /** + * @private + * Initialises the next scene + */ + , _setNextScene: function () { + // TODO transitions + + if (this._runningScene) { + this._runningScene.onExit() + if (this._sendCleanupToScene) { + this._runningScene.cleanup() + } + } + + this._runningScene = this._nextScene + + this._nextScene = null + + this._runningScene.onEnter() + } + + /** + * Convert the coordinates in a mouse event so they're relative to the corner of the canvas + * + * @param {MouseEvent} evt + */ + , convertEventToCanvas: function (evt) { + return this.convertLocationToCanvas(evt.locationInWindow) + } + + , convertLocationToCanvas: function (loc, noScroll) { + var x = this.canvas.offsetLeft - (noScroll ? 0 : document.documentElement.scrollLeft) + , y = this.canvas.offsetTop - (noScroll ? 0 : document.documentElement.scrollTop) + + var o = this.canvas + while ((o = o.offsetParent)) { + x += o.offsetLeft - (noScroll ? 0 : o.scrollLeft) + y += o.offsetTop - (noScroll ? 0 : o.scrollTop) + } + + var p = geo.ccpSub(loc, ccp(x, y)) + if (cc.FLIP_Y_AXIS) { + p.y = this._viewSize.height - p.y + } + + p.x = p.x * this._viewScale.width + p.y = p.y * this._viewScale.height + + return p + } + + , convertTouchToCanvas: function (touch) { + return this.convertLocationToCanvas(new geo.Point(touch.pageX, touch.pageY), true) + } + + /** + * @private + * Draw the FPS counter + */ + , _showFPS: function () { + if (!this._fpsLabel) { + var Label = require('./nodes/Label').Label + this._fpsLabel = new Label({string: '', fontSize: 16}) + this._fpsLabel.anchorPoint = ccp(0, 0) + this._fpsLabel.position = ccp(10, 10) + this._frames = 0 + this._accumDt = 0 + } + + + this._frames++ + this._accumDt += this.dt + + if (this._accumDt > 1.0 / 3.0) { + var frameRate = this._frames / this._accumDt + this._frames = 0 + this._accumDt = 0 + + this._fpsLabel.string = 'FPS: ' + (Math.round(frameRate * 100) / 100).toString() + } + + + + this._fpsLabel.visit(this.context) + } + +}) + +Object.defineProperty(Director, 'sharedDirector', { + /** + * A shared singleton instance of cocos.Director + * + * @memberOf cocos.Director + * @getter {cocos.Director} sharedDirector + */ + get: function () { + if (!Director._instance) { + if (window.navigator.userAgent.match(/(iPhone|iPod|iPad|Android)/)) { + Director._instance = new DirectorTouchScreen() + } else { + Director._instance = new this() + } + } + + return Director._instance + } + + , enumerable: true +}) + +/** + * @class + * The Director singleton used on touch screen devices such as the iPhone, iPod and iPad + * + * @memberOf cocos + * @extends cocos.Director + */ +function DirectorTouchScreen () { + DirectorTouchScreen.superclass.constructor.call(this) + + // Hardcode some viewport sizes for iOS devices + var ua = window.navigator.userAgent + if (ua.match(/(iPhone|iPod)/)) { + this.viewportSize = { portrait: new geo.Size(320, 416) + , landscape: new geo.Size(480, 268) + } + } else if (ua.match(/(iPad)/)) { + this.viewportSize = { portrait: new geo.Size(768, 928) + , landscape: new geo.Size(1024, 672) + } + } +} + +DirectorTouchScreen.inherit(Director, /** @lends cocos.DirectorTouchScreen */ { + isTouchScreen: true + + , isMobile: true + + , viewportSize: null + + /** + * Force the device to prevent scaling and expand the canvas to fill the entire available screen area + */ + , fullscreen: function () { + this._isFullscreen = true + if (!this._container) { + return // Wait to be attached to view + } + + var viewport = this.document.querySelector('meta[name=viewport]') + if (!viewport) { + viewport = this.document.createElement('meta') + viewport.setAttribute('name', 'viewport') + this.document.querySelector('head').appendChild(viewport) + } + + this.container.style.position = 'fixed' + this.container.style.left = 0 + this.container.style.top = 0 + + events.addListener(this, 'orientationchange', this._adjustFullscreen.bind(this)) + this.document.body.addEventListener('touchstart', function (e) { + this.window.scrollTo(0, 0) + e.preventDefault() + }.bind(this)) + this._adjustFullscreen() + } + + /** + * @private + */ + , _adjustFullscreen: function () { + if (!this._container) { + return + } + + var vp + if (this._forcedOrientation == 'landscape' || this.orientation.match(/landscape/)) { + vp = this.viewportSize.landscape + } else { + vp = this.viewportSize.portrait + } + this.resize(vp.width, vp.height) + + var viewport = this.document.querySelector('meta[name=viewport]') + viewport.setAttribute('content', 'initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, width=' + this._winSize.width + ', height=' + this._winSize.height) + + // Rotate canvas to fake orientation + /* TODO + if (this._forcedOrientation == 'landscape' && !this.orientation.match(/landscape/)) { + this.container.style.WebkitTransformOrigin = '0 0' + this.container.style.WebkitTransform = 'translate(320px, 0) rotate(90deg)' + } else { + this.container.style.WebkitTransform = 'none' + } + */ + + this.window.scrollTo(0, 0) + } + + /** + * Forces the screen orientation on a mobile device + */ + , forceOrientation: function (orientation) { + this._forcedOrientation = orientation + if (this._isFullscreen) { + this._adjustFullscreen() + } + } + + , _setupEventCapturing: function () { + var document = this.document + + this._setupTouchEventCapturing() + + // Orientation detection + if (typeof top.window.orientation != 'undefined') { + this._updateOrientation() + document.body.addEventListener('orientationchange', this._updateOrientation.bind(this), false) + } + + } + + , _setupTouchEventCapturing: function () { + var document = this.document + , canvas = this.canvas + + // Touch events + var eventDispatcher = TouchDispatcher.sharedDispatcher + + var touchStart = function (evt) { + eventDispatcher.touchesBegan(evt) + }.bind(this) + + var touchMove = function (evt) { + eventDispatcher.touchesMoved(evt) + }.bind(this) + + var touchEnd = function (evt) { + eventDispatcher.touchesEnded(evt) + }.bind(this) + + var touchCancel = function (evt) { + eventDispatcher.touchesCancelled(evt) + }.bind(this) + + canvas.addEventListener('touchstart', touchStart, false) + canvas.addEventListener('touchmove', touchMove, false) + canvas.addEventListener('touchend', touchEnd, false) + canvas.addEventListener('touchcancel', touchCancel, false) + } + + , _updateOrientation: function () { + switch (top.window.orientation) { + case 0: + this.orientation = 'portrait' + break + + case 90: + this.orientation = 'landscapeLeft' + break + + case -90: + this.orientation = 'landscapeRight' + break + + case 180: + this.orientation = 'portraitUpsideDown' + break + } + + events.trigger(this, 'orientationchange') + } + +}) + +/** + * @class + * Pretends to run at a constant frame rate even if it slows down + * + * @memberOf cocos + * @extends cocos.Director + */ +function DirectorFixedSpeed () { + DirectorFixedSpeed.superclass.constructor.call(this) +} +DirectorFixedSpeed.inherit(Director, /** @lends cocos.DirectorFixedSpeed */ { + /** + * Frames per second to draw. + * @type Integer + */ + frameRate: 60 + + /** + * Calculate time since last call + * @private + */ + , _calculateDeltaTime: function () { + if (this._nextDeltaTimeZero) { + this.dt = 0 + this._nextDeltaTimeZero = false + } + + this.dt = 1.0 / this.frameRate + } + + /** + * The main loop is triggered again. Call this function only if + * cocos.Directory#stopAnimation was called earlier. + */ + , startAnimation: function () { + this._animationTimer = setInterval(this.drawScene.bind(this), 1000 / this.frameRate) + this.drawScene() + } + } +) +Object.defineProperty(DirectorFixedSpeed, 'sharedDirector', Object.getOwnPropertyDescriptor(Director, 'sharedDirector')) + +exports.Director = Director +exports.DirectorFixedSpeed = DirectorFixedSpeed + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/Director.js + + +__jah__.resources["/libs/cocos2d/EventDispatcher.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var util = require('util'), + geo = require('geometry') + +/** + * @class + * This singleton is responsible for dispatching Mouse and Keyboard events. + * + * @memberOf cocos + * @singleton + */ +function EventDispatcher () { + EventDispatcher.superclass.constructor.call(this) + + this.keyboardDelegates = [] + this.mouseDelegates = [] + + this._keysDown = {} +} + +EventDispatcher.inherit(Object, /** @lends cocos.EventDispatcher# */ { + dispatchEvents: true, + keyboardDelegates: null, + mouseDelegates: null, + _keysDown: null, + + addDelegate: function (opts) { + var delegate = opts.delegate, + priority = opts.priority, + flags = opts.flags, + list = opts.list + + var listElement = { + delegate: delegate, + priority: priority, + flags: flags + } + + var added = false + for (var i = 0; i < list.length; i++) { + var elem = list[i] + if (priority < elem.priority) { + // Priority is lower, so insert before elem + list.splice(i, 0, listElement) + added = true + break + } + } + + // High priority; append to array + if (!added) { + list.push(listElement) + } + }, + + removeDelegate: function (opts) { + var delegate = opts.delegate, + list = opts.list + + var idx = -1, + i + for (i = 0; i < list.length; i++) { + var l = list[i] + if (l.delegate == delegate) { + idx = i + break + } + } + if (idx == -1) { + return + } + list.splice(idx, 1) + }, + removeAllDelegates: function (opts) { + var list = opts.list + + list.splice(0, list.length - 1) + }, + + addMouseDelegate: function (opts) { + var delegate = opts.delegate, + priority = opts.priority + + var flags = 0 + + // TODO flags + + this.addDelegate({delegate: delegate, priority: priority, flags: flags, list: this.mouseDelegates}) + }, + + removeMouseDelegate: function (opts) { + var delegate = opts.delegate + + this.removeDelegate({delegate: delegate, list: this.mouseDelegates}) + }, + + removeAllMouseDelegate: function () { + this.removeAllDelegates({list: this.mouseDelegates}) + }, + + addKeyboardDelegate: function (opts) { + var delegate = opts.delegate, + priority = opts.priority + + var flags = 0 + + // TODO flags + + this.addDelegate({delegate: delegate, priority: priority, flags: flags, list: this.keyboardDelegates}) + }, + + removeKeyboardDelegate: function (opts) { + var delegate = opts.delegate + + this.removeDelegate({delegate: delegate, list: this.keyboardDelegates}) + }, + + removeAllKeyboardDelegate: function () { + this.removeAllDelegates({list: this.keyboardDelegates}) + }, + + + + // Mouse Events + + mouseDown: function (evt) { + if (!this.dispatchEvents) { + return + } + + this._previousMouseMovePosition = geo.ccp(evt.clientX, evt.clientY) + this._previousMouseDragPosition = geo.ccp(evt.clientX, evt.clientY) + + for (var i = 0; i < this.mouseDelegates.length; i++) { + var entry = this.mouseDelegates[i] + if (entry.delegate.mouseDown) { + var swallows = entry.delegate.mouseDown(evt) + if (swallows) { + break + } + } + } + }, + mouseMoved: function (evt) { + if (!this.dispatchEvents) { + return + } + + if (this._previousMouseMovePosition) { + evt.deltaX = evt.clientX - this._previousMouseMovePosition.x + evt.deltaY = evt.clientY - this._previousMouseMovePosition.y + if (cc.FLIP_Y_AXIS) { + evt.deltaY *= -1 + } + } else { + evt.deltaX = 0 + evt.deltaY = 0 + } + this._previousMouseMovePosition = geo.ccp(evt.clientX, evt.clientY) + + for (var i = 0; i < this.mouseDelegates.length; i++) { + var entry = this.mouseDelegates[i] + if (entry.delegate.mouseMoved) { + var swallows = entry.delegate.mouseMoved(evt) + if (swallows) { + break + } + } + } + }, + mouseDragged: function (evt) { + if (!this.dispatchEvents) { + return + } + + if (this._previousMouseDragPosition) { + evt.deltaX = evt.clientX - this._previousMouseDragPosition.x + evt.deltaY = evt.clientY - this._previousMouseDragPosition.y + if (cc.FLIP_Y_AXIS) { + evt.deltaY *= -1 + } + } else { + evt.deltaX = 0 + evt.deltaY = 0 + } + this._previousMouseDragPosition = geo.ccp(evt.clientX, evt.clientY) + + for (var i = 0; i < this.mouseDelegates.length; i++) { + var entry = this.mouseDelegates[i] + if (entry.delegate.mouseDragged) { + var swallows = entry.delegate.mouseDragged(evt) + if (swallows) { + break + } + } + } + }, + mouseUp: function (evt) { + if (!this.dispatchEvents) { + return + } + + for (var i = 0; i < this.mouseDelegates.length; i++) { + var entry = this.mouseDelegates[i] + if (entry.delegate.mouseUp) { + var swallows = entry.delegate.mouseUp(evt) + if (swallows) { + break + } + } + } + }, + + // Keyboard events + keyDown: function (evt) { + var kc = evt.keyCode + if (!this.dispatchEvents) { + return + } + + // Repeating key + if (this._keysDown[kc]) { + return this.keyRepeat(evt) + } + + this._keysDown[kc] = true + + for (var i = 0; i < this.keyboardDelegates.length; i++) { + var entry = this.keyboardDelegates[i] + if (entry.delegate.keyDown) { + var swallows = entry.delegate.keyDown(evt) + if (swallows) { + break + } + } + } + }, + + keyRepeat: function (evt) { + for (var i = 0; i < this.keyboardDelegates.length; i++) { + var entry = this.keyboardDelegates[i] + if (entry.delegate.keyRepeat) { + var swallows = entry.delegate.keyRepeat(evt) + if (swallows) { + break + } + } + } + }, + + keyUp: function (evt) { + if (!this.dispatchEvents) { + return + } + + var kc = evt.keyCode + if (this._keysDown[kc]) { + delete this._keysDown[kc] + } + + for (var i = 0; i < this.keyboardDelegates.length; i++) { + var entry = this.keyboardDelegates[i] + if (entry.delegate.keyUp) { + var swallows = entry.delegate.keyUp(evt) + if (swallows) { + break + } + } + } + } + +}) + +Object.defineProperty(EventDispatcher, 'sharedDispatcher', { + /** + * A shared singleton instance of cocos.EventDispatcher + * + * @memberOf cocos.EventDispatcher + * @getter {cocos.EventDispatcher} sharedDispatcher + */ + get: function () { + if (!EventDispatcher._instance) { + EventDispatcher._instance = new this() + } + + return EventDispatcher._instance + } + + , enumerable: true +}) + +exports.EventDispatcher = EventDispatcher + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/EventDispatcher.js + + +__jah__.resources["/libs/cocos2d/index.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var util = require('util'), + path = require('path') + + +var modules = 'nodes actions TextureAtlas Texture2D SpriteFrame SpriteFrameCache Director Animation AnimationCache Scheduler ActionManager TMXXMLParser'.split(' ') + +/** + * @namespace All cocos2d objects live in this namespace + */ +var cocos = { + nodes: require('./nodes'), + actions: require('./actions') +} + +util.each(modules, function (mod, i) { + util.extend(cocos, require('./' + mod)) +}) + +module.exports = cocos + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/index.js + + +__jah__.resources["/libs/cocos2d/init.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +var path = require('path') + + +exports.main = function () { + if (typeof cc == 'undefined') { + window.cc = {} + } + + require.paths.push(path.join(__dirname, 'libs')) + + require('./remote_resources_patch') + + require('./js_extensions') + + if (!cc.STANDALONE) { + // Link to the parent window's XHR object, IE9 will fail with cross-origin + // errors if we don't. + window.XMLHttpRequest = parent.XMLHttpRequest + } + + + // Load default cocos2d config + var config = require('./config') + for (var k in config) { + if (config.hasOwnProperty(k)) { + cc[k] = config[k] + } + } + + // Load appliaction config + if (path.exists('/config.js')) { + config = require('/config') + for (var k in config) { + if (config.hasOwnProperty(k)) { + cc[k] = config[k] + } + } + } + + if (cc.ENABLE_DEPRECATED_METHODS) { + require('./legacy') + } +}; + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/init.js + + +__jah__.resources["/libs/cocos2d/js_extensions.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var util = require('util') + +/** + * @memberOf Object + */ +function extend (target, parent, props) { + target.prototype = Object.create(parent.prototype) + target.prototype.constructor = target + + if (props) { + util.extend(target.prototype, props) + } + + return target +} + +/** + * @memberOf Function# + */ +function inherit (parent, props) { + return extend(this, parent, props) +} + +if (!Object.extend) { + Object.extend = extend +} + +if (!Function.prototype.inherit) { + Function.prototype.inherit = inherit +} +if (!('id' in Object.prototype)) { + + /** + * @ignore + * Every object has a unique ID. It only gets set the first time its accessed + */ + var nextObjectID = 1 + + Object.defineProperty(Object.prototype, 'id', { + get: function () { + if (this === Object.prototype || Object.getPrototypeOf(this) === Object.prototype) { + return + } + + + var id = nextObjectID++ + this.id = id + return id + }, + + /** @ignore + * Allow overwriting of 'id' property + */ + set: function (x) { + if (this === Object.prototype) { + return + } + if (Object.getPrototypeOf(this) === Object.prototype) { + Object.defineProperty(this, 'id', { + configurable: true, + writable: true, + enumerable: true, + value: x + }) + } else { + Object.defineProperty(this, 'id', { + configurable: true, + writable: true, + enumerable: false, + value: x + }) + } + + } + }) +} + +if (!('superclass' in Function.prototype)) { + Object.defineProperty(Function.prototype, 'superclass', { + /** + * The object prototype that this was inherited from + * @memberOf Function# + * @getter {Object} superclass + */ + get: function () { + return Object.getPrototypeOf(this.prototype) + }, + + /** @ignore + * Allow overwriting of 'superclass' property + */ + set: function (x) { + Object.defineProperty(this, 'superclass', { + configurable: true, + writable: true + }) + + this.superclass = x + } + }) +} +if (!('__superclass__' in Function.prototype)) { + Object.defineProperty(Function.prototype, '__superclass__', { + get: function () { + return Object.getPrototypeOf(this.prototype) + } + }) +} + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/js_extensions.js + + +__jah__.resources["/libs/cocos2d/legacy.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +/** + * @fileOverview + * + * Provides support for deprecated methods + */ + +var BObject = require('./libs/bobject').BObject + , util = require('./libs/util') + +/** + * @ignore + */ +function applyAccessors (obj) { + obj.get = BObject.get + obj.set = BObject.set + obj.extend = BObject.extend + obj.create = BObject.create + + 'get set extend triggerBeforeChanged triggerChanged'.w + .forEach(function (prop) { + obj.prototype[prop] = BObject.prototype[prop] + if (!obj.prototype.hasOwnProperty('init')) { + obj.prototype.init = obj + } + }) +} + +var pkgs = { _: 'ActionManager Director SpriteFrame TMXXMLParser Animation EventDispatcher SpriteFrameCache Texture2D AnimationCache Scheduler TextureAtlas'.w + , nodes: 'AtlasNode BatchNode index Label LabelAtlas Layer Menu MenuItem Node PreloadScene ProgressBar RenderTexture Scene Sprite TMXLayer TMXTiledMap Transition'.w + , actions: 'Action ActionEase ActionInterval ActionInstant'.w + } + +for (var ns in pkgs) { + var modules = pkgs[ns] + , dir = (ns == '_') ? '' : ns + '/' + + modules.forEach(function (n) { + var mod = require('./' + dir + n) + for (var m in mod) { + if (mod.hasOwnProperty(m) && typeof mod[m] == 'function') { + applyAccessors(mod[m]) + } + } + }) + +} + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/legacy.js + + +__jah__.resources["/libs/cocos2d/libs/base64.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +/** + * Thin wrapper around JXG's Base64 utils + */ + +/** @ignore */ +var JXG = require('JXGUtil'); + +/** @namespace */ +var base64 = { + /** + * Decode a base64 encoded string into a binary string + * + * @param {String} input Base64 encoded data + * @returns {String} Binary string + */ + decode: function(input) { + return JXG.Util.Base64.decode(input); + }, + + /** + * Decode a base64 encoded string into a byte array + * + * @param {String} input Base64 encoded data + * @returns {Integer[]} Array of bytes + */ + decodeAsArray: function(input, bytes) { + bytes = bytes || 1; + + var dec = JXG.Util.Base64.decode(input), + ar = [], i, j, len; + + for (i = 0, len = dec.length/bytes; i < len; i++){ + ar[i] = 0; + for (j = bytes-1; j >= 0; --j){ + ar[i] += dec.charCodeAt((i *bytes) +j) << (j *8); + } + } + return ar; + }, + + /** + * Encode a binary string into base64 + * + * @param {String} input Binary string + * @returns {String} Base64 encoded data + */ + encode: function(input) { + return JXG.Util.Base64.encode(input); + } +}; + +module.exports = base64; + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/libs/base64.js + + +__jah__.resources["/libs/cocos2d/libs/bobject.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +/*globals module exports resource require*/ +/*jslint undef: true, strict: true, white: true, newcap: true, browser: true, indent: 4 */ +"use strict"; + +var util = require('util'), + events = require('events'); + + +/** + * @ignore + */ +function getAccessors(obj) { + if (!obj.js_accessors_) { + obj.js_accessors_ = {}; + } + return obj.js_accessors_; +} + +/** + * @ignore + */ +function getBindings(obj) { + if (!obj.js_bindings_) { + obj.js_bindings_ = {}; + } + return obj.js_bindings_; +} + +/** + * @ignore + */ +function addAccessor(obj, key, target, targetKey, noNotify) { + getAccessors(obj)[key] = { + key: targetKey, + target: target + }; + + if (!noNotify) { + obj.triggerChanged(key); + } +} + + +/** + * @ignore + */ +var objectID = 0; + +/** + * @class + * [DEPRECATED] A bindable object. Allows observing and binding to its properties. + * + * @deprecated Since 0.2. Most functionality is now provided using ECMAScript 5 accessors and events.addPropertyListener + * @see events.addPropertyListener + * @see Defining Getters and Setters + */ +function BObject () { + return this.init.apply(this, arguments) +} +BObject.prototype = util.extend(BObject.prototype, /** @lends BObject# */{ + /** + * The constructor for subclasses. Overwrite this for any initalisation you + * need to do. + * @ignore + */ + init: function () {}, + + /** + * Get a property from the object. Always use this instead of trying to + * access the property directly. This will ensure all bindings, setters and + * getters work correctly. + * + * @param {String} key Name of property to get or dot (.) separated path to a property + * @returns {*} Value of the property + */ + get: function (key) { + var next = false + if (~key.indexOf('.')) { + var tokens = key.split('.'); + key = tokens.shift(); + next = tokens.join('.'); + } + + + var accessor = getAccessors(this)[key], + val; + if (accessor) { + val = accessor.target.get(accessor.key); + } else { + // Call getting function + if (this['get_' + key]) { + val = this['get_' + key](); + } else { + val = this[key]; + } + } + + if (next) { + return val.get(next); + } else { + return val; + } + }, + + + /** + * Set a property on the object. Always use this instead of trying to + * access the property directly. This will ensure all bindings, setters and + * getters work correctly. + * + * @param {String} key Name of property to get + * @param {*} value New value for the property + */ + set: function (key, value) { + var accessor = getAccessors(this)[key], + oldVal = this.get(key); + + + this.triggerBeforeChanged(key, oldVal); + + if (accessor) { + accessor.target.set(accessor.key, value); + } else { + + if (this['set_' + key]) { + this['set_' + key](value); + } else { + this[key] = value; + } + } + this.triggerChanged(key, oldVal); + }, + + /** + * Set multiple propertys in one go + * + * @param {Object} kvp An Object where the key is a property name and the value is the value to assign to the property + * + * @example + * var props = { + * monkey: 'ook', + * cat: 'meow', + * dog: 'woof' + * }; + * foo.setValues(props); + * console.log(foo.get('cat')); // Logs 'meow' + */ + setValues: function (kvp) { + for (var x in kvp) { + if (kvp.hasOwnProperty(x)) { + this.set(x, kvp[x]); + } + } + }, + + changed: function (key) { + }, + + /** + * @private + */ + notify: function (key, oldVal) { + var accessor = getAccessors(this)[key]; + if (accessor) { + accessor.target.notify(accessor.key, oldVal); + } + }, + + /** + * @private + */ + triggerBeforeChanged: function (key, oldVal) { + events.trigger(this, key.toLowerCase() + '_before_changed', oldVal); + }, + + /** + * @private + */ + triggerChanged: function (key, oldVal) { + events.trigger(this, key.toLowerCase() + '_changed', oldVal); + }, + + /** + * Bind the value of a property on this object to that of another object so + * they always have the same value. Setting the value on either object will update + * the other too. + * + * @param {String} key Name of the property on this object that should be bound + * @param {BOject} target Object to bind to + * @param {String} [targetKey=key] Key on the target object to bind to + * @param {Boolean} [noNotify=false] Set to true to prevent this object's property triggering a 'changed' event when adding the binding + */ + bindTo: function (key, target, targetKey, noNotify) { + targetKey = targetKey || key; + var self = this; + this.unbind(key); + + var oldVal = this.get(key); + + // When bound property changes, trigger a 'changed' event on this one too + getBindings(this)[key] = events.addListener(target, targetKey.toLowerCase() + '_changed', function (oldVal) { + self.triggerChanged(key, oldVal); + }); + + addAccessor(this, key, target, targetKey, noNotify); + }, + + /** + * Remove binding from a property which set setup using BObject#bindTo. + * + * @param {String} key Name of the property on this object to unbind + */ + unbind: function (key) { + var binding = getBindings(this)[key]; + if (!binding) { + return; + } + + delete getBindings(this)[key]; + events.removeListener(binding); + // Grab current value from bound property + var val = this.get(key); + delete getAccessors(this)[key]; + // Set bound value + this[key] = val; + }, + + /** + * Remove all bindings on this object + */ + unbindAll: function () { + var keys = [], + bindings = getBindings(this); + for (var k in bindings) { + if (bindings.hasOwnProperty(k)) { + this.unbind(k); + } + } + } +}); + + +/** + * Create a new instance of this object + * @returns {BObject} New instance of this object + */ +BObject.create = function () { + var ret = Object.create(this.prototype) + , ret2 = ret.constructor.apply(ret, arguments); + return ret2 || ret; +}; + +/** + * Create a new subclass by extending this one + * @returns {Object} A new subclass of this object + */ +BObject.extend = function (targetOrProperties, parent) { + var target, properties + if (arguments.length < 2) { + properties = targetOrProperties + parent = this + } else { + target = targetOrProperties + } + + if (arguments.length > 1 && this !== BObject) { + throw new Error("extend only accepts 1 argument") + } + + target = target || function () { + return this.init.apply(this, arguments) + } + + var args = [], i, x; + + // Copy 'static' properties + util.extend(target, parent) + + // Add given properties to the prototype + target.prototype = Object.create(parent.prototype) + target.prototype.constructor = target + if (properties) { + util.extend(target.prototype, properties) + } + + // Create new instance + return target +}; + +/** + * Get a property from the class. Always use this instead of trying to + * access the property directly. This will ensure all bindings, setters and + * getters work correctly. + * + * @function + * @param {String} key Name of property to get + * @returns {*} Value of the property + */ +BObject.get = BObject.prototype.get; + +/** + * Set a property on the class. Always use this instead of trying to + * access the property directly. This will ensure all bindings, setters and + * getters work correctly. + * + * @function + * @param {String} key Name of property to get + * @param {*} value New value for the property + */ +BObject.set = BObject.prototype.set; + +var BArray = BObject.extend(/** @lends BArray# */{ + + /** + * @constructs + * [DEPRECATED] A bindable array. Allows observing for changes made to its contents + * + * @deprecated Since 0.2 + * @extends BObject + * @param {Array} [array=[]] A normal JS array to use for data + */ + init: function (array) { + this.array = array || []; + this.set('length', this.array.length); + }, + + /** + * Get an item + * + * @param {Integer} i Index to get item from + * @returns {*} Value stored in the array at index 'i' + */ + getAt: function (i) { + return this.array[i]; + }, + + /** + * Set an item -- Overwrites any existing item at index + * + * @param {Integer} i Index to set item to + * @param {*} value Value to assign to index + */ + setAt: function (i, value) { + var oldVal = this.array[i]; + this.array[i] = value; + + events.trigger(this, 'set_at', i, oldVal); + }, + + /** + * Insert a new item into the array without overwriting anything + * + * @param {Integer} i Index to insert item at + * @param {*} value Value to insert + */ + insertAt: function (i, value) { + this.array.splice(i, 0, value); + this.set('length', this.array.length); + events.trigger(this, 'insert_at', i); + }, + + /** + * Remove item from the array and return it + * + * @param {Integer} i Index to remove + * @returns {*} Value that was removed + */ + removeAt: function (i) { + var oldVal = this.array[i]; + this.array.splice(i, 1); + this.set('length', this.array.length); + events.trigger(this, 'remove_at', i, oldVal); + + return oldVal; + }, + + /** + * Get the internal Javascript Array instance + * + * @returns {Array} Internal Javascript Array + */ + getArray: function () { + return this.array; + }, + + /** + * Append a value to the end of the array and return its new length + * + * @param {*} value Value to append to the array + * @returns {Integer} New length of the array + */ + push: function (value) { + this.insertAt(this.array.length, value); + return this.array.length; + }, + + /** + * Remove value from the end of the array and return it + * + * @returns {*} Value that was removed + */ + pop: function () { + return this.removeAt(this.array.length - 1); + } +}); + +exports.BObject = BObject; +exports.BArray = BArray; + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/libs/bobject.js + + +__jah__.resources["/libs/cocos2d/libs/geometry.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var util = require('util') + +var RE_PAIR = /\{\s*([\d.\-]+)\s*,\s*([\d.\-]+)\s*\}/, + RE_DOUBLE_PAIR = /\{\s*(\{[\s\d,.\-]+\})\s*,\s*(\{[\s\d,.\-]+\})\s*\}/ + +Math.PI_2 = 1.57079632679489661923132169163975144 /* pi/2 */ + +/** @namespace */ +var geometry = { + /** + * @class + * A 2D point in space + * + * @param {Float} x X value + * @param {Float} y Y value + */ + Point: function (x, y) { + /** + * X coordinate + * @type Float + */ + this.x = x + + /** + * Y coordinate + * @type Float + */ + this.y = y + }, + + /** + * @class + * A 3D point in space + * + * @param {Float} x X value + * @param {Float} y Y value + * @param {Float} z Z value + */ + Point3D: function (x, y, z) { + /** + * X coordinate + * @type Float + */ + this.x = x + + /** + * Y coordinate + * @type Float + */ + this.y = y + + /** + * Z coordinate + * @type Float + */ + this.z = z + }, + + /** + * @class + * A 2D size + * + * @param {Float} w Width + * @param {Float} h Height + */ + Size: function (w, h) { + /** + * Width + * @type Float + */ + this.width = w + + /** + * Height + * @type Float + */ + this.height = h + }, + + /** + * @class + * A 3D size + * + * @param {Float} w Width + * @param {Float} h Height + * @param {Float} d Depth + */ + Size3D: function (w, h, d) { + /** + * Width + * @type Float + */ + this.width = w + + /** + * Height + * @type Float + */ + this.height = h + + /** + * Depth + * @type Float + */ + this.depth = d + }, + + /** + * @class + * A rectangle + * + * @param {Float} x X value + * @param {Float} y Y value + * @param {Float} w Width + * @param {Float} h Height + */ + Rect: function (x, y, w, h) { + /** + * Coordinate in 2D space + * @type geometry.Point + */ + this.origin = new geometry.Point(x, y) + + /** + * Size in 2D space + * @type geometry.Size + */ + this.size = new geometry.Size(w, h) + }, + + /** + * @class + * Transform matrix + * + * @param {Float} a + * @param {Float} b + * @param {Float} c + * @param {Float} d + * @param {Float} tx + * @param {Float} ty + */ + TransformMatrix: function (a, b, c, d, tx, ty) { + this.a = a + this.b = b + this.c = c + this.d = d + this.tx = tx + this.ty = ty + }, + + /** + * @class + * Bezier curve control object + * + * @param {geometry.Point} controlPoint1 + * @param {geometry.Point} controlPoint2 + * @param {geometry.Point} endPoint + */ + BezierConfig: function(p1, p2, ep) { + this.controlPoint1 = util.copy(p1) + this.controlPoint2 = util.copy(p2) + this.endPosition = util.copy(ep) + }, + + /** + * Creates a geometry.Point instance + * + * @param {Float} x X coordinate + * @param {Float} y Y coordinate + * @returns {geometry.Point} + */ + ccp: function (x, y) { + return module.exports.pointMake(x, y) + }, + + /** + * Add the values of two points together + * + * @param {geometry.Point} p1 First point + * @param {geometry.Point} p2 Second point + * @returns {geometry.Point} New point + */ + ccpAdd: function (p1, p2) { + return geometry.ccp(p1.x + p2.x, p1.y + p2.y) + }, + + /** + * Subtract the values of two points + * + * @param {geometry.Point} p1 First point + * @param {geometry.Point} p2 Second point + * @returns {geometry.Point} New point + */ + ccpSub: function (p1, p2) { + return geometry.ccp(p1.x - p2.x, p1.y - p2.y) + }, + + /** + * Muliply the values of two points together + * + * @param {geometry.Point} p1 First point + * @param {geometry.Point} p2 Second point + * @returns {geometry.Point} New point + */ + ccpMult: function (p1, p2) { + return geometry.ccp(p1.x * p2.x, p1.y * p2.y) + }, + + + /** + * Invert the values of a geometry.Point + * + * @param {geometry.Point} p Point to invert + * @returns {geometry.Point} New point + */ + ccpNeg: function (p) { + return geometry.ccp(-p.x, -p.y) + }, + + /** + * Round values on a geometry.Point to whole numbers + * + * @param {geometry.Point} p Point to round + * @returns {geometry.Point} New point + */ + ccpRound: function (p) { + return geometry.ccp(Math.round(p.x), Math.round(p.y)) + }, + + /** + * Round up values on a geometry.Point to whole numbers + * + * @param {geometry.Point} p Point to round + * @returns {geometry.Point} New point + */ + ccpCeil: function (p) { + return geometry.ccp(Math.ceil(p.x), Math.ceil(p.y)) + }, + + /** + * Round down values on a geometry.Point to whole numbers + * + * @param {geometry.Point} p Point to round + * @returns {geometry.Point} New point + */ + ccpFloor: function (p) { + return geometry.ccp(Math.floor(p.x), Math.floor(p.y)) + }, + + /** + * A point at 0x0 + * + * @returns {geometry.Point} New point at 0x0 + */ + PointZero: function () { + return geometry.ccp(0, 0) + }, + + /** + * @returns {geometry.Rect} + */ + rectMake: function (x, y, w, h) { + return new geometry.Rect(x, y, w, h) + }, + + /** + * @returns {geometry.Rect} + */ + rectFromString: function (str) { + var matches = str.match(RE_DOUBLE_PAIR), + p = geometry.pointFromString(matches[1]), + s = geometry.sizeFromString(matches[2]) + + return geometry.rectMake(p.x, p.y, s.width, s.height) + }, + + /** + * @returns {geometry.Size} + */ + sizeMake: function (w, h) { + return new geometry.Size(w, h) + }, + + /** + * @returns {geometry.Size} + */ + sizeFromString: function (str) { + var matches = str.match(RE_PAIR), + w = parseFloat(matches[1]), + h = parseFloat(matches[2]) + + return geometry.sizeMake(w, h) + }, + + /** + * @returns {geometry.Point} + */ + pointMake: function (x, y) { + return new geometry.Point(x, y) + }, + + /** + * @returns {geometry.Point} + */ + pointFromString: function (str) { + var matches = str.match(RE_PAIR), + x = parseFloat(matches[1]), + y = parseFloat(matches[2]) + + return geometry.pointMake(x, y) + }, + + /** + * @returns {Boolean} + */ + rectContainsPoint: function (r, p) { + return ((p.x >= r.origin.x && p.x <= r.origin.x + r.size.width) && + (p.y >= r.origin.y && p.y <= r.origin.y + r.size.height)) + }, + + /** + * Returns the smallest rectangle that contains the two source rectangles. + * + * @param {geometry.Rect} r1 + * @param {geometry.Rect} r2 + * @returns {geometry.Rect} + */ + rectUnion: function (r1, r2) { + var rect = new geometry.Rect(0, 0, 0, 0) + + rect.origin.x = Math.min(r1.origin.x, r2.origin.x) + rect.origin.y = Math.min(r1.origin.y, r2.origin.y) + rect.size.width = Math.max(r1.origin.x + r1.size.width, r2.origin.x + r2.size.width) - rect.origin.x + rect.size.height = Math.max(r1.origin.y + r1.size.height, r2.origin.y + r2.size.height) - rect.origin.y + + return rect + }, + + /** + * @returns {Boolean} + */ + rectOverlapsRect: function (r1, r2) { + if (r1.origin.x + r1.size.width < r2.origin.x) { + return false + } + if (r2.origin.x + r2.size.width < r1.origin.x) { + return false + } + if (r1.origin.y + r1.size.height < r2.origin.y) { + return false + } + if (r2.origin.y + r2.size.height < r1.origin.y) { + return false + } + + return true + }, + + /** + * Returns the overlapping portion of 2 rectangles + * + * @param {geometry.Rect} lhsRect First rectangle + * @param {geometry.Rect} rhsRect Second rectangle + * @returns {geometry.Rect} The overlapping portion of the 2 rectangles + */ + rectIntersection: function (lhsRect, rhsRect) { + + var intersection = new geometry.Rect( + Math.max(geometry.rectGetMinX(lhsRect), geometry.rectGetMinX(rhsRect)), + Math.max(geometry.rectGetMinY(lhsRect), geometry.rectGetMinY(rhsRect)), + 0, + 0 + ) + + intersection.size.width = Math.min(geometry.rectGetMaxX(lhsRect), geometry.rectGetMaxX(rhsRect)) - geometry.rectGetMinX(intersection) + intersection.size.height = Math.min(geometry.rectGetMaxY(lhsRect), geometry.rectGetMaxY(rhsRect)) - geometry.rectGetMinY(intersection) + + return intersection + }, + + /** + * @returns {Boolean} + */ + pointEqualToPoint: function (point1, point2) { + return (point1.x == point2.x && point1.y == point2.y) + }, + + /** + * @returns {Boolean} + */ + sizeEqualToSize: function (size1, size2) { + return (size1.width == size2.width && size1.height == size2.height) + }, + + /** + * @returns {Boolean} + */ + rectEqualToRect: function (rect1, rect2) { + return (module.exports.sizeEqualToSize(rect1.size, rect2.size) && module.exports.pointEqualToPoint(rect1.origin, rect2.origin)) + }, + + /** + * @returns {Float} + */ + rectGetMinX: function (rect) { + return rect.origin.x + }, + + /** + * @returns {Float} + */ + rectGetMinY: function (rect) { + return rect.origin.y + }, + + /** + * @returns {Float} + */ + rectGetMaxX: function (rect) { + return rect.origin.x + rect.size.width + }, + + /** + * @returns {Float} + */ + rectGetMaxY: function (rect) { + return rect.origin.y + rect.size.height + }, + + boundingRectMake: function (p1, p2, p3, p4) { + var minX = Math.min(p1.x, p2.x, p3.x, p4.x) + var minY = Math.min(p1.y, p2.y, p3.y, p4.y) + var maxX = Math.max(p1.x, p2.x, p3.x, p4.x) + var maxY = Math.max(p1.y, p2.y, p3.y, p4.y) + + return new geometry.Rect(minX, minY, (maxX - minX), (maxY - minY)) + }, + + /** + * @returns {geometry.Point} + */ + pointApplyAffineTransform: function (point, t) { + + /* + aPoint.x * aTransform.a + aPoint.y * aTransform.c + aTransform.tx, + aPoint.x * aTransform.b + aPoint.y * aTransform.d + aTransform.ty + */ + + return new geometry.Point(t.a * point.x + t.c * point.y + t.tx, t.b * point.x + t.d * point.y + t.ty) + + }, + + /** + * Apply a transform matrix to a rectangle + * + * @param {geometry.Rect} rect Rectangle to transform + * @param {geometry.TransformMatrix} trans TransformMatrix to apply to rectangle + * @returns {geometry.Rect} A new transformed rectangle + */ + rectApplyAffineTransform: function (rect, trans) { + + var p1 = geometry.ccp(geometry.rectGetMinX(rect), geometry.rectGetMinY(rect)) + var p2 = geometry.ccp(geometry.rectGetMaxX(rect), geometry.rectGetMinY(rect)) + var p3 = geometry.ccp(geometry.rectGetMinX(rect), geometry.rectGetMaxY(rect)) + var p4 = geometry.ccp(geometry.rectGetMaxX(rect), geometry.rectGetMaxY(rect)) + + p1 = geometry.pointApplyAffineTransform(p1, trans) + p2 = geometry.pointApplyAffineTransform(p2, trans) + p3 = geometry.pointApplyAffineTransform(p3, trans) + p4 = geometry.pointApplyAffineTransform(p4, trans) + + return geometry.boundingRectMake(p1, p2, p3, p4) + }, + + /** + * Inverts a transform matrix + * + * @param {geometry.TransformMatrix} trans TransformMatrix to invert + * @returns {geometry.TransformMatrix} New transform matrix + */ + affineTransformInvert: function (trans) { + var determinant = 1 / (trans.a * trans.d - trans.b * trans.c) + + return new geometry.TransformMatrix( + determinant * trans.d, + -determinant * trans.b, + -determinant * trans.c, + determinant * trans.a, + determinant * (trans.c * trans.ty - trans.d * trans.tx), + determinant * (trans.b * trans.tx - trans.a * trans.ty) + ) + }, + + /** + * Multiply 2 transform matrices together + * @param {geometry.TransformMatrix} lhs Left matrix + * @param {geometry.TransformMatrix} rhs Right matrix + * @returns {geometry.TransformMatrix} New transform matrix + */ + affineTransformConcat: function (lhs, rhs) { + return new geometry.TransformMatrix( + lhs.a * rhs.a + lhs.b * rhs.c, + lhs.a * rhs.b + lhs.b * rhs.d, + lhs.c * rhs.a + lhs.d * rhs.c, + lhs.c * rhs.b + lhs.d * rhs.d, + lhs.tx * rhs.a + lhs.ty * rhs.c + rhs.tx, + lhs.tx * rhs.b + lhs.ty * rhs.d + rhs.ty + ) + }, + + /** + * @returns {Float} + */ + degreesToRadians: function (angle) { + return angle / 180.0 * Math.PI + }, + + /** + * @returns {Float} + */ + radiansToDegrees: function (angle) { + return angle * (180.0 / Math.PI) + }, + + /** + * Translate (move) a transform matrix + * + * @param {geometry.TransformMatrix} trans TransformMatrix to translate + * @param {Float} tx Amount to translate along X axis + * @param {Float} ty Amount to translate along Y axis + * @returns {geometry.TransformMatrix} A new TransformMatrix + */ + affineTransformTranslate: function (trans, tx, ty) { + var newTrans = util.copy(trans) + newTrans.tx = trans.tx + trans.a * tx + trans.c * ty + newTrans.ty = trans.ty + trans.b * tx + trans.d * ty + return newTrans + }, + + /** + * Rotate a transform matrix + * + * @param {geometry.TransformMatrix} trans TransformMatrix to rotate + * @param {Float} angle Angle in radians + * @returns {geometry.TransformMatrix} A new TransformMatrix + */ + affineTransformRotate: function (trans, angle) { + var sin = Math.sin(angle), + cos = Math.cos(angle) + + return new geometry.TransformMatrix( + trans.a * cos + trans.c * sin, + trans.b * cos + trans.d * sin, + trans.c * cos - trans.a * sin, + trans.d * cos - trans.b * sin, + trans.tx, + trans.ty + ) + }, + + /** + * Scale a transform matrix + * + * @param {geometry.TransformMatrix} trans TransformMatrix to scale + * @param {Float} sx X scale factor + * @param {Float} [sy=sx] Y scale factor + * @returns {geometry.TransformMatrix} A new TransformMatrix + */ + affineTransformScale: function (trans, sx, sy) { + if (sy === undefined) { + sy = sx + } + + return new geometry.TransformMatrix(trans.a * sx, trans.b * sx, trans.c * sy, trans.d * sy, trans.tx, trans.ty) + }, + + /** + * @returns {geometry.TransformMatrix} identity matrix + */ + affineTransformIdentity: function () { + return new geometry.TransformMatrix(1, 0, 0, 1, 0, 0) + } +} + +Object.defineProperty(geometry.Point, 'zero', { + /** + * Point(0, 0) + * + * @memberOf geometry.Point + * @getter geometry.Point zero + */ + get: function () { + return new geometry.Point(0, 0) + } +}) + +module.exports = geometry + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/libs/geometry.js + + +__jah__.resources["/libs/cocos2d/libs/gzip.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +/** + * @fileoverview + */ + +/** @ignore */ +var JXG = require('./JXGUtil'); + +/** + * @namespace + * Wrappers around JXG's GZip utils + * @see JXG.Util + */ +var gzip = { + /** + * Unpack a gzipped byte array + * + * @param {Integer[]} input Byte array + * @returns {String} Unpacked byte string + */ + unzip: function(input) { + return (new JXG.Util.Unzip(input)).unzip()[0][0]; + }, + + /** + * Unpack a gzipped byte string encoded as base64 + * + * @param {String} input Byte string encoded as base64 + * @returns {String} Unpacked byte string + */ + unzipBase64: function(input) { + return (new JXG.Util.Unzip(JXG.Util.Base64.decodeAsArray(input))).unzip()[0][0]; + }, + + /** + * Unpack a gzipped byte string encoded as base64 + * + * @param {String} input Byte string encoded as base64 + * @param {Integer} bytes Bytes per array item + * @returns {Integer[]} Unpacked byte array + */ + unzipBase64AsArray: function(input, bytes) { + bytes = bytes || 1; + + var dec = this.unzipBase64(input), + ar = [], i, j, len; + for (i = 0, len = dec.length/bytes; i < len; i++){ + ar[i] = 0; + for (j = bytes-1; j >= 0; --j){ + ar[i] += dec.charCodeAt((i *bytes) +j) << (j *8); + } + } + return ar; + }, + + /** + * Unpack a gzipped byte array + * + * @param {Integer[]} input Byte array + * @param {Integer} bytes Bytes per array item + * @returns {Integer[]} Unpacked byte array + */ + unzipAsArray: function (input, bytes) { + bytes = bytes || 1; + + var dec = this.unzip(input), + ar = [], i, j, len; + for (i = 0, len = dec.length/bytes; i < len; i++){ + ar[i] = 0; + for (j = bytes-1; j >= 0; --j){ + ar[i] += dec.charCodeAt((i *bytes) +j) << (j *8); + } + } + return ar; + } + +}; + +module.exports = gzip; + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/libs/gzip.js + + +__jah__.resources["/libs/cocos2d/libs/JXGUtil.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +/* + Copyright 2008,2009 + Matthias Ehmann, + Michael Gerhaeuser, + Carsten Miller, + Bianca Valentin, + Alfred Wassermann, + Peter Wilfahrt + + This file is part of JSXGraph. + + JSXGraph is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JSXGraph is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with JSXGraph. If not, see . +*/ + +/** + * @fileoverview Utilities for uncompressing and base64 decoding + */ + +/** @namespace */ +var JXG = {}; + +/** + * @class Util class + * Class for gunzipping, unzipping and base64 decoding of files. + * It is used for reading GEONExT, Geogebra and Intergeo files. + * + * Only Huffman codes are decoded in gunzip. + * The code is based on the source code for gunzip.c by Pasi Ojala + * @see http://www.cs.tut.fi/~albert/Dev/gunzip/gunzip.c + * @see http://www.cs.tut.fi/~albert + */ +JXG.Util = {}; + +/** + * Unzip zip files + */ +JXG.Util.Unzip = function (barray){ + var outputArr = [], + output = "", + debug = false, + gpflags, + files = 0, + unzipped = [], + crc, + buf32k = new Array(32768), + bIdx = 0, + modeZIP=false, + + CRC, SIZE, + + bitReverse = [ + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff + ], + + cplens = [ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 + ], + + cplext = [ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99 + ], /* 99==invalid */ + + cpdist = [ + 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0007, 0x0009, 0x000d, + 0x0011, 0x0019, 0x0021, 0x0031, 0x0041, 0x0061, 0x0081, 0x00c1, + 0x0101, 0x0181, 0x0201, 0x0301, 0x0401, 0x0601, 0x0801, 0x0c01, + 0x1001, 0x1801, 0x2001, 0x3001, 0x4001, 0x6001 + ], + + cpdext = [ + 0, 0, 0, 0, 1, 1, 2, 2, + 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, + 11, 11, 12, 12, 13, 13 + ], + + border = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15], + + bA = barray, + + bytepos=0, + bitpos=0, + bb = 1, + bits=0, + + NAMEMAX = 256, + + nameBuf = [], + + fileout; + + function readByte(){ + bits+=8; + if (bytepos"); + return bA[bytepos++]; + } else + return -1; + }; + + function byteAlign(){ + bb = 1; + }; + + function readBit(){ + var carry; + bits++; + carry = (bb & 1); + bb >>= 1; + if (bb==0){ + bb = readByte(); + carry = (bb & 1); + bb = (bb>>1) | 0x80; + } + return carry; + }; + + function readBits(a) { + var res = 0, + i = a; + + while(i--) { + res = (res<<1) | readBit(); + } + if(a) { + res = bitReverse[res]>>(8-a); + } + return res; + }; + + function flushBuffer(){ + //document.write('FLUSHBUFFER:'+buf32k); + bIdx = 0; + }; + function addBuffer(a){ + SIZE++; + //CRC=updcrc(a,crc); + buf32k[bIdx++] = a; + outputArr.push(String.fromCharCode(a)); + //output+=String.fromCharCode(a); + if(bIdx==0x8000){ + //document.write('ADDBUFFER:'+buf32k); + bIdx=0; + } + }; + + function HufNode() { + this.b0=0; + this.b1=0; + this.jump = null; + this.jumppos = -1; + }; + + var LITERALS = 288; + + var literalTree = new Array(LITERALS); + var distanceTree = new Array(32); + var treepos=0; + var Places = null; + var Places2 = null; + + var impDistanceTree = new Array(64); + var impLengthTree = new Array(64); + + var len = 0; + var fpos = new Array(17); + fpos[0]=0; + var flens; + var fmax; + + function IsPat() { + while (1) { + if (fpos[len] >= fmax) + return -1; + if (flens[fpos[len]] == len) + return fpos[len]++; + fpos[len]++; + } + }; + + function Rec() { + var curplace = Places[treepos]; + var tmp; + if (debug) + document.write("
len:"+len+" treepos:"+treepos); + if(len==17) { //war 17 + return -1; + } + treepos++; + len++; + + tmp = IsPat(); + if (debug) + document.write("
IsPat "+tmp); + if(tmp >= 0) { + curplace.b0 = tmp; /* leaf cell for 0-bit */ + if (debug) + document.write("
b0 "+curplace.b0); + } else { + /* Not a Leaf cell */ + curplace.b0 = 0x8000; + if (debug) + document.write("
b0 "+curplace.b0); + if(Rec()) + return -1; + } + tmp = IsPat(); + if(tmp >= 0) { + curplace.b1 = tmp; /* leaf cell for 1-bit */ + if (debug) + document.write("
b1 "+curplace.b1); + curplace.jump = null; /* Just for the display routine */ + } else { + /* Not a Leaf cell */ + curplace.b1 = 0x8000; + if (debug) + document.write("
b1 "+curplace.b1); + curplace.jump = Places[treepos]; + curplace.jumppos = treepos; + if(Rec()) + return -1; + } + len--; + return 0; + }; + + function CreateTree(currentTree, numval, lengths, show) { + var i; + /* Create the Huffman decode tree/table */ + //document.write("
createtree
"); + if (debug) + document.write("currentTree "+currentTree+" numval "+numval+" lengths "+lengths+" show "+show); + Places = currentTree; + treepos=0; + flens = lengths; + fmax = numval; + for (i=0;i<17;i++) + fpos[i] = 0; + len = 0; + if(Rec()) { + //fprintf(stderr, "invalid huffman tree\n"); + if (debug) + alert("invalid huffman tree\n"); + return -1; + } + if (debug){ + document.write('
Tree: '+Places.length); + for (var a=0;a<32;a++){ + document.write("Places["+a+"].b0="+Places[a].b0+"
"); + document.write("Places["+a+"].b1="+Places[a].b1+"
"); + } + } + + return 0; + }; + + function DecodeValue(currentTree) { + var len, i, + xtreepos=0, + X = currentTree[xtreepos], + b; + + /* decode one symbol of the data */ + while(1) { + b=readBit(); + if (debug) + document.write("b="+b); + if(b) { + if(!(X.b1 & 0x8000)){ + if (debug) + document.write("ret1"); + return X.b1; /* If leaf node, return data */ + } + X = X.jump; + len = currentTree.length; + for (i=0;i>1); + if(j > 23) { + j = (j<<1) | readBit(); /* 48..255 */ + + if(j > 199) { /* 200..255 */ + j -= 128; /* 72..127 */ + j = (j<<1) | readBit(); /* 144..255 << */ + } else { /* 48..199 */ + j -= 48; /* 0..151 */ + if(j > 143) { + j = j+136; /* 280..287 << */ + /* 0..143 << */ + } + } + } else { /* 0..23 */ + j += 256; /* 256..279 << */ + } + if(j < 256) { + addBuffer(j); + //document.write("out:"+String.fromCharCode(j)); + /*fprintf(errfp, "@%d %02x\n", SIZE, j);*/ + } else if(j == 256) { + /* EOF */ + break; + } else { + var len, dist; + + j -= 256 + 1; /* bytes + EOF */ + len = readBits(cplext[j]) + cplens[j]; + + j = bitReverse[readBits(5)]>>3; + if(cpdext[j] > 8) { + dist = readBits(8); + dist |= (readBits(cpdext[j]-8)<<8); + } else { + dist = readBits(cpdext[j]); + } + dist += cpdist[j]; + + /*fprintf(errfp, "@%d (l%02x,d%04x)\n", SIZE, len, dist);*/ + for(j=0;jparam: "+literalCodes+" "+distCodes+" "+lenCodes+"
"); + for(j=0; j<19; j++) { + ll[j] = 0; + } + + // Get the decode tree code lengths + + //document.write("
"); + for(j=0; jll:'+ll); + len = distanceTree.length; + for (i=0; idistanceTree"); + for(var a=0;a"+distanceTree[a].b0+" "+distanceTree[a].b1+" "+distanceTree[a].jump+" "+distanceTree[a].jumppos); + /*if (distanceTree[a].jumppos!=-1) + document.write(" "+distanceTree[a].jump.b0+" "+distanceTree[a].jump.b1); + */ + } + } + //document.write('
tree created'); + + //read in literal and distance code lengths + n = literalCodes + distCodes; + i = 0; + var z=-1; + if (debug) + document.write("
n="+n+" bits: "+bits+"
"); + while(i < n) { + z++; + j = DecodeValue(distanceTree); + if (debug) + document.write("
"+z+" i:"+i+" decode: "+j+" bits "+bits+"
"); + if(j<16) { // length of code in bits (0..15) + ll[i++] = j; + } else if(j==16) { // repeat last length 3 to 6 times + var l; + j = 3 + readBits(2); + if(i+j > n) { + flushBuffer(); + return 1; + } + l = i ? ll[i-1] : 0; + while(j--) { + ll[i++] = l; + } + } else { + if(j==17) { // 3 to 10 zero length codes + j = 3 + readBits(3); + } else { // j == 18: 11 to 138 zero length codes + j = 11 + readBits(7); + } + if(i+j > n) { + flushBuffer(); + return 1; + } + while(j--) { + ll[i++] = 0; + } + } + } + /*for(j=0; jliteralTree"); + while(1) { + j = DecodeValue(literalTree); + if(j >= 256) { // In C64: if carry set + var len, dist; + j -= 256; + if(j == 0) { + // EOF + break; + } + j--; + len = readBits(cplext[j]) + cplens[j]; + + j = DecodeValue(distanceTree); + if(cpdext[j] > 8) { + dist = readBits(8); + dist |= (readBits(cpdext[j]-8)<<8); + } else { + dist = readBits(cpdext[j]); + } + dist += cpdist[j]; + while(len--) { + var c = buf32k[(bIdx - dist) & 0x7fff]; + addBuffer(c); + } + } else { + addBuffer(j); + } + } + } + } while(!last); + flushBuffer(); + + byteAlign(); + return 0; +}; + +JXG.Util.Unzip.prototype.unzipFile = function(name) { + var i; + this.unzip(); + //alert(unzipped[0][1]); + for (i=0;i"); + } + */ + //alert(bA); + nextFile(); + return unzipped; + }; + + function nextFile(){ + if (debug) + alert("NEXTFILE"); + outputArr = []; + var tmp = []; + modeZIP = false; + tmp[0] = readByte(); + tmp[1] = readByte(); + if (debug) + alert("type: "+tmp[0]+" "+tmp[1]); + if (tmp[0] == parseInt("78",16) && tmp[1] == parseInt("da",16)){ //GZIP + if (debug) + alert("GEONExT-GZIP"); + DeflateLoop(); + if (debug) + alert(outputArr.join('')); + unzipped[files] = new Array(2); + unzipped[files][0] = outputArr.join(''); + unzipped[files][1] = "geonext.gxt"; + files++; + } + if (tmp[0] == parseInt("1f",16) && tmp[1] == parseInt("8b",16)){ //GZIP + if (debug) + alert("GZIP"); + //DeflateLoop(); + skipdir(); + if (debug) + alert(outputArr.join('')); + unzipped[files] = new Array(2); + unzipped[files][0] = outputArr.join(''); + unzipped[files][1] = "file"; + files++; + } + if (tmp[0] == parseInt("50",16) && tmp[1] == parseInt("4b",16)){ //ZIP + modeZIP = true; + tmp[2] = readByte(); + tmp[3] = readByte(); + if (tmp[2] == parseInt("3",16) && tmp[3] == parseInt("4",16)){ + //MODE_ZIP + tmp[0] = readByte(); + tmp[1] = readByte(); + if (debug) + alert("ZIP-Version: "+tmp[1]+" "+tmp[0]/10+"."+tmp[0]%10); + + gpflags = readByte(); + gpflags |= (readByte()<<8); + if (debug) + alert("gpflags: "+gpflags); + + var method = readByte(); + method |= (readByte()<<8); + if (debug) + alert("method: "+method); + + readByte(); + readByte(); + readByte(); + readByte(); + + var crc = readByte(); + crc |= (readByte()<<8); + crc |= (readByte()<<16); + crc |= (readByte()<<24); + + var compSize = readByte(); + compSize |= (readByte()<<8); + compSize |= (readByte()<<16); + compSize |= (readByte()<<24); + + var size = readByte(); + size |= (readByte()<<8); + size |= (readByte()<<16); + size |= (readByte()<<24); + + if (debug) + alert("local CRC: "+crc+"\nlocal Size: "+size+"\nlocal CompSize: "+compSize); + + var filelen = readByte(); + filelen |= (readByte()<<8); + + var extralen = readByte(); + extralen |= (readByte()<<8); + + if (debug) + alert("filelen "+filelen); + i = 0; + nameBuf = []; + while (filelen--){ + var c = readByte(); + if (c == "/" | c ==":"){ + i = 0; + } else if (i < NAMEMAX-1) + nameBuf[i++] = String.fromCharCode(c); + } + if (debug) + alert("nameBuf: "+nameBuf); + + //nameBuf[i] = "\0"; + if (!fileout) + fileout = nameBuf; + + var i = 0; + while (i < extralen){ + c = readByte(); + i++; + } + + CRC = 0xffffffff; + SIZE = 0; + + if (size = 0 && fileOut.charAt(fileout.length-1)=="/"){ + //skipdir + if (debug) + alert("skipdir"); + } + if (method == 8){ + DeflateLoop(); + if (debug) + alert(outputArr.join('')); + unzipped[files] = new Array(2); + unzipped[files][0] = outputArr.join(''); + unzipped[files][1] = nameBuf.join(''); + files++; + //return outputArr.join(''); + } + skipdir(); + } + } + }; + +function skipdir(){ + var crc, + tmp = [], + compSize, size, os, i, c; + + if ((gpflags & 8)) { + tmp[0] = readByte(); + tmp[1] = readByte(); + tmp[2] = readByte(); + tmp[3] = readByte(); + + if (tmp[0] == parseInt("50",16) && + tmp[1] == parseInt("4b",16) && + tmp[2] == parseInt("07",16) && + tmp[3] == parseInt("08",16)) + { + crc = readByte(); + crc |= (readByte()<<8); + crc |= (readByte()<<16); + crc |= (readByte()<<24); + } else { + crc = tmp[0] | (tmp[1]<<8) | (tmp[2]<<16) | (tmp[3]<<24); + } + + compSize = readByte(); + compSize |= (readByte()<<8); + compSize |= (readByte()<<16); + compSize |= (readByte()<<24); + + size = readByte(); + size |= (readByte()<<8); + size |= (readByte()<<16); + size |= (readByte()<<24); + + if (debug) + alert("CRC:"); + } + + if (modeZIP) + nextFile(); + + tmp[0] = readByte(); + if (tmp[0] != 8) { + if (debug) + alert("Unknown compression method!"); + return 0; + } + + gpflags = readByte(); + if (debug){ + if ((gpflags & ~(parseInt("1f",16)))) + alert("Unknown flags set!"); + } + + readByte(); + readByte(); + readByte(); + readByte(); + + readByte(); + os = readByte(); + + if ((gpflags & 4)){ + tmp[0] = readByte(); + tmp[2] = readByte(); + len = tmp[0] + 256*tmp[1]; + if (debug) + alert("Extra field size: "+len); + for (i=0;ihttp://www.webtoolkit.info/ +*/ +JXG.Util.Base64 = { + + // private property + _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", + + // public method for encoding + encode : function (input) { + var output = [], + chr1, chr2, chr3, enc1, enc2, enc3, enc4, + i = 0; + + input = JXG.Util.Base64._utf8_encode(input); + + while (i < input.length) { + + chr1 = input.charCodeAt(i++); + chr2 = input.charCodeAt(i++); + chr3 = input.charCodeAt(i++); + + enc1 = chr1 >> 2; + enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); + enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); + enc4 = chr3 & 63; + + if (isNaN(chr2)) { + enc3 = enc4 = 64; + } else if (isNaN(chr3)) { + enc4 = 64; + } + + output.push([this._keyStr.charAt(enc1), + this._keyStr.charAt(enc2), + this._keyStr.charAt(enc3), + this._keyStr.charAt(enc4)].join('')); + } + + return output.join(''); + }, + + // public method for decoding + decode : function (input, utf8) { + var output = [], + chr1, chr2, chr3, + enc1, enc2, enc3, enc4, + i = 0; + + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); + + while (i < input.length) { + + enc1 = this._keyStr.indexOf(input.charAt(i++)); + enc2 = this._keyStr.indexOf(input.charAt(i++)); + enc3 = this._keyStr.indexOf(input.charAt(i++)); + enc4 = this._keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + output.push(String.fromCharCode(chr1)); + + if (enc3 != 64) { + output.push(String.fromCharCode(chr2)); + } + if (enc4 != 64) { + output.push(String.fromCharCode(chr3)); + } + } + + output = output.join(''); + + if (utf8) { + output = JXG.Util.Base64._utf8_decode(output); + } + return output; + + }, + + // private method for UTF-8 encoding + _utf8_encode : function (string) { + string = string.replace(/\r\n/g,"\n"); + var utftext = ""; + + for (var n = 0; n < string.length; n++) { + + var c = string.charCodeAt(n); + + if (c < 128) { + utftext += String.fromCharCode(c); + } + else if((c > 127) && (c < 2048)) { + utftext += String.fromCharCode((c >> 6) | 192); + utftext += String.fromCharCode((c & 63) | 128); + } + else { + utftext += String.fromCharCode((c >> 12) | 224); + utftext += String.fromCharCode(((c >> 6) & 63) | 128); + utftext += String.fromCharCode((c & 63) | 128); + } + + } + + return utftext; + }, + + // private method for UTF-8 decoding + _utf8_decode : function (utftext) { + var string = [], + i = 0, + c = 0, c2 = 0, c3 = 0; + + while ( i < utftext.length ) { + c = utftext.charCodeAt(i); + if (c < 128) { + string.push(String.fromCharCode(c)); + i++; + } + else if((c > 191) && (c < 224)) { + c2 = utftext.charCodeAt(i+1); + string.push(String.fromCharCode(((c & 31) << 6) | (c2 & 63))); + i += 2; + } + else { + c2 = utftext.charCodeAt(i+1); + c3 = utftext.charCodeAt(i+2); + string.push(String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63))); + i += 3; + } + } + return string.join(''); + }, + + _destrip: function (stripped, wrap){ + var lines = [], lineno, i, + destripped = []; + + if (wrap==null) + wrap = 76; + + stripped.replace(/ /g, ""); + lineno = stripped.length / wrap; + for (i = 0; i < lineno; i++) + lines[i]=stripped.substr(i * wrap, wrap); + if (lineno != stripped.length / wrap) + lines[lines.length]=stripped.substr(lineno * wrap, stripped.length-(lineno * wrap)); + + for (i = 0; i < lines.length; i++) + destripped.push(lines[i]); + return destripped.join('\n'); + }, + + decodeAsArray: function (input){ + var dec = this.decode(input), + ar = [], i; + for (i=0;i255){ + switch (c) { + case 8364: c=128; + break; + case 8218: c=130; + break; + case 402: c=131; + break; + case 8222: c=132; + break; + case 8230: c=133; + break; + case 8224: c=134; + break; + case 8225: c=135; + break; + case 710: c=136; + break; + case 8240: c=137; + break; + case 352: c=138; + break; + case 8249: c=139; + break; + case 338: c=140; + break; + case 381: c=142; + break; + case 8216: c=145; + break; + case 8217: c=146; + break; + case 8220: c=147; + break; + case 8221: c=148; + break; + case 8226: c=149; + break; + case 8211: c=150; + break; + case 8212: c=151; + break; + case 732: c=152; + break; + case 8482: c=153; + break; + case 353: c=154; + break; + case 8250: c=155; + break; + case 339: c=156; + break; + case 382: c=158; + break; + case 376: c=159; + break; + default: + break; + } + } + return c; +}; + +/** + * Decoding string into utf-8 + * @param {String} string to decode + * @return {String} utf8 decoded string + */ +JXG.Util.utf8Decode = function(utftext) { + var string = []; + var i = 0; + var c = 0, c1 = 0, c2 = 0; + + while ( i < utftext.length ) { + c = utftext.charCodeAt(i); + + if (c < 128) { + string.push(String.fromCharCode(c)); + i++; + } else if((c > 191) && (c < 224)) { + c2 = utftext.charCodeAt(i+1); + string.push(String.fromCharCode(((c & 31) << 6) | (c2 & 63))); + i += 2; + } else { + c2 = utftext.charCodeAt(i+1); + c3 = utftext.charCodeAt(i+2); + string.push(String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63))); + i += 3; + } + }; + return string.join(''); +}; + +// Added to exports for Cocos2d +module.exports = JXG; + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/libs/JXGUtil.js + + +__jah__.resources["/libs/cocos2d/libs/Plist.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +/** @ignore + * XML Node types + */ +var ELEMENT_NODE = 1 + , ATTRIBUTE_NODE = 2 + , TEXT_NODE = 3 + , CDATA_SECTION_NODE = 4 + , ENTITY_REFERENCE_NODE = 5 + , ENTITY_NODE = 6 + , PROCESSING_INSTRUCTION_NODE = 7 + , COMMENT_NODE = 8 + , DOCUMENT_NODE = 9 + , DOCUMENT_TYPE_NODE = 10 + , DOCUMENT_FRAGMENT_NODE = 11 + , NOTATION_NODE = 12 + +/** + * @class + * An object representation of an XML Property List file + * + * @opt {String} [file] The path to a .plist file + * @opt {String} [data] The contents of a .plist file + */ +function Plist (opts) { + var file = opts['file'], + data = opts['data'] + + if (file && !data) { + data = resource(file) + } + + + var parser = new DOMParser(), + doc = parser.parseFromString(data, 'text/xml'), + plist = doc.documentElement + + if (plist.tagName != 'plist') { + throw "Not a plist file" + } + + + // Get first real node + var node = null + for (var i = 0, len = plist.childNodes.length; i < len; i++) { + node = plist.childNodes[i] + if (node.nodeType == ELEMENT_NODE) { + break + } + } + + this.data = this._parseNode(node) +} + +Plist.inherit(Object, /** @lends Plist# */ { + /** + * The unserialized data inside the Plist file + * @type Object + */ + data: null, + + /** + * @private + * Parses an XML node inside the Plist file + * @returns {Object/Array/String/Integer/Float} A JS representation of the node value + */ + _parseNode: function(node) { + var data = null + switch(node.tagName) { + case 'dict': + data = this._parseDict(node); + break + case 'array': + data = this._parseArray(node); + break + case 'string': + // FIXME - This needs to handle Firefox's 4KB nodeValue limit + data = node.firstChild.nodeValue + break + case 'false': + data = false + break + case 'true': + data = true + break + case 'real': + data = parseFloat(node.firstChild.nodeValue) + break + case 'integer': + data = parseInt(node.firstChild.nodeValue, 10) + break + } + + return data + }, + + /** + * @private + * Parses a node in a plist file + * + * @param {XMLElement} + * @returns {Object} A simple key/value JS Object representing the + */ + _parseDict: function(node) { + var data = {} + + var key = null + for (var i = 0, len = node.childNodes.length; i < len; i++) { + var child = node.childNodes[i] + if (child.nodeType != ELEMENT_NODE) { + continue + } + + // Grab the key, next noe should be the value + if (child.tagName == 'key') { + key = child.firstChild.nodeValue + } else { + // Parse the value node + data[key] = this._parseNode(child) + } + } + + + return data + }, + + /** + * @private + * Parses an node in a plist file + * + * @param {XMLElement} + * @returns {Array} A simple JS Array representing the + */ + _parseArray: function(node) { + var data = [] + + for (var i = 0, len = node.childNodes.length; i < len; i++) { + var child = node.childNodes[i] + if (child.nodeType != ELEMENT_NODE) { + continue + } + + data.push(this._parseNode(child)) + } + + return data + } +}) + +exports.Plist = Plist + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/libs/Plist.js + + +__jah__.resources["/libs/cocos2d/libs/uri.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +/** + * @namespace + * URI utilities + */ +var uri = { + isURL: function (uri) { + return /^(file|http|https):\/\//.test(uri) + } +} + +module.exports = uri + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/libs/uri.js + + +__jah__.resources["/libs/cocos2d/libs/util.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +var path = require('path'); + + +/** + * @namespace + * Useful utility functions + */ +var util = { + /** + * Merge two or more objects and return the result. + * + * @param {Object} firstObject First object to merge with + * @param {Object} secondObject Second object to merge with + * @param {Object} [...] More objects to merge + * @returns {Object} A new object containing the properties of all the objects passed in + */ + merge: function(firstObject, secondObject) { + var result = {}; + + for (var i = 0; i < arguments.length; i++) { + var obj = arguments[i]; + + for (var x in obj) { + if (!obj.hasOwnProperty(x)) { + continue; + } + + result[x] = obj[x]; + } + }; + + return result; + }, + + /** + * Creates a deep copy of an object + * + * @param {Object} obj The Object to copy + * @returns {Object} A copy of the original Object + */ + copy: function(obj) { + if (obj === null) { + return null; + } + + var copy; + + if (obj instanceof Array) { + copy = []; + for (var i = 0, len = obj.length; i < len; i++) { + copy[i] = util.copy(obj[i]); + } + } else if (typeof(obj) == 'object') { + if (typeof(obj.copy) == 'function') { + copy = obj.copy(); + } else { + copy = {}; + + var o, x; + for (x in obj) { + copy[x] = util.copy(obj[x]); + } + } + } else { + // Primative type. Doesn't need copying + copy = obj; + } + + return copy; + }, + + /** + * Iterates over an array and calls a function for each item. + * + * @param {Array} arr An Array to iterate over + * @param {Function} func A function to call for each item in the array + * @returns {Array} The original array + */ + each: function(arr, func) { + var i = 0, + len = arr.length; + for (i = 0; i < len; i++) { + func(arr[i], i); + } + + return arr; + }, + + /** + * Iterates over an array, calls a function for each item and returns the results. + * + * @param {Array} arr An Array to iterate over + * @param {Function} func A function to call for each item in the array + * @returns {Array} The return values from each function call + */ + map: function(arr, func) { + var i = 0, + len = arr.length, + result = []; + + for (i = 0; i < len; i++) { + result.push(func(arr[i], i)); + } + + return result; + }, + + extend: function(target, ext) { + if (arguments.length < 2) { + throw "You must provide at least a target and 1 object to extend from" + } + + var i, j, obj, key, val, descriptor; + + for (i = 1; i < arguments.length; i++) { + obj = arguments[i]; + for (key in obj) { + // Don't copy built-ins + if (!obj.hasOwnProperty(key)) { + continue; + } + + descriptor = Object.getOwnPropertyDescriptor(obj, key) + + // Accessor descriptories are copied as is + if (descriptor.get || descriptor.set) { + Object.defineProperty(target, key, descriptor); + continue; + } + + val = descriptor.value; + + // Don't copy undefineds or references to target (would cause infinite loop) + if (val === undefined || val === target) { + continue; + } + + // Replace existing function and store reference to it in .base + if (val instanceof Function && target[key] && val !== target[key]) { + val.base = target[key]; + val._isProperty = val.base._isProperty; + } + + if (val instanceof Function) { + // If this function observes make a reference to it so we can set + // them up when this get instantiated + if (val._observing) { + // Force a COPY of the array or we will probably end up with various + // classes sharing the same one. + if (!target._observingFunctions) { + target._observingFunctions = []; + } else { + target._observingFunctions = target._observingFunctions.slice(0); + } + + + for (j = 0; j 0) { + this.removeChild(this.children[0]) + } + + for (var i = 0; i < n; i++) { + var a = s.charCodeAt(i) - this.mapStartChar, + row = (a % this.itemsPerRow), + col = Math.floor(a / this.itemsPerRow) + + var left = row * this.itemWidth, + top = col * this.itemHeight + + var tile = new Sprite({rect: new geo.Rect(left, top, this.itemWidth, this.itemHeight), + textureAtlas: this.textureAtlas}) + + tile.position = new geo.Point(i * this.itemWidth, 0) + tile.anchorPoint = new geo.Point(0, 0) + tile.opacity = this.opacity + + this.addChild({child: tile}) + } + } +}) + +exports.LabelAtlas = LabelAtlas + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/nodes/LabelAtlas.js + + +__jah__.resources["/libs/cocos2d/nodes/Layer.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var util = require('util') + , events = require('events') + , ccp = require('geometry').ccp + +var Node = require('./Node').Node + , Director = require('../Director').Director + , EventDispatcher = require('../EventDispatcher').EventDispatcher + , TouchDispatcher = require('../TouchDispatcher').TouchDispatcher + +/** + * @class + * A fullscreen Node. You need at least 1 layer in your app to add other nodes to. + * + * @memberOf cocos.nodes + * @extends cocos.nodes.Node + */ +function Layer () { + Layer.superclass.constructor.call(this) + + var s = Director.sharedDirector.winSize + + this.isRelativeAnchorPoint = false + this.anchorPoint = ccp(0.5, 0.5) + this.contentSize = s + + if (!Director.sharedDirector.isTouchScreen) { + events.addPropertyListener(this, 'isMouseEnabled', 'change', function () { + if (this.isRunning) { + if (this.isMouseEnabled) { + EventDispatcher.sharedDispatcher.addMouseDelegate({delegate: this, priority: this.mouseDelegatePriority}) + } else { + EventDispatcher.sharedDispatcher.removeMouseDelegate({delegate: this}) + } + } + }.bind(this)) + + events.addPropertyListener(this, 'isKeyboardEnabled', 'change', function () { + if (this.isRunning) { + if (this.isKeyboardEnabled) { + EventDispatcher.sharedDispatcher.addKeyboardDelegate({delegate: this, priority: this.keyboardDelegatePriority}) + } else { + EventDispatcher.sharedDispatcher.removeKeyboardDelegate({delegate: this}) + } + } + }.bind(this)) + } +} + +Layer.inherit(Node, /** @lends cocos.nodes.Layer# */ { + /** + * When true causes this layer to receive mouse events + * @type Boolean + */ + isMouseEnabled: false + + /** + * When true causes this layer to receive keyboard events + * @type Boolean + */ + , isKeyboardEnabled: false + , mouseDelegatePriority: 0 + , keyboardDelegatePriority: 0 + + /** + * When true on touch screen devices causes this layer to receive touch events + * @type Boolean + */ + , get isTouchEnabled () { + return this._isTouchEnabled + } + , set isTouchEnabled (enabled) { + if (!Director.sharedDirector.isTouchScreen) { + throw new Error("Only touch screen devices can listen for touch events") + } + + if (this._isTouchEnabled != enabled) { + this._isTouchEnabled = enabled + if (this.isRunning) { + if (enabled) { + this.registerWithTouchDispatcher() + } else { + TouchDispatcher.sharedDispatcher.removeDelegate(this) + } + } + } + } + , _isTouchEnabled: false + + /** + * Override this method in your layer if you wish to change the type of + * touch event dispatchment you want + */ + , registerWithTouchDispatcher: function () { + TouchDispatcher.sharedDispatcher.addStandardDelegate(this, 0) + } + + , onEnter: function () { + if (Director.sharedDirector.isTouchScreen) { + if (this._isTouchEnabled) { + this.registerWithTouchDispatcher() + } + } else { + if (this.isMouseEnabled) { + EventDispatcher.sharedDispatcher.addMouseDelegate({delegate: this, priority: this.mouseDelegatePriority}) + } + if (this.isKeyboardEnabled) { + EventDispatcher.sharedDispatcher.addKeyboardDelegate({delegate: this, priority: this.keyboardDelegatePriority}) + } + } + + Layer.superclass.onEnter.call(this) + } + + , onExit: function () { + if (Director.sharedDirector.isTouchScreen) { + TouchDispatcher.sharedDispatcher.removeDelegate(this) + } else { + if (this.isMouseEnabled) { + EventDispatcher.sharedDispatcher.removeMouseDelegate({delegate: this}) + } + if (this.isKeyboardEnabled) { + EventDispatcher.sharedDispatcher.removeKeyboardDelegate({delegate: this}) + } + } + + Layer.superclass.onExit.call(this) + } +}) + +module.exports.Layer = Layer + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/nodes/Layer.js + + +__jah__.resources["/libs/cocos2d/nodes/Menu.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var util = require('util'), + Layer = require('./Layer').Layer, + Director = require('../Director').Director, + MenuItem = require('./MenuItem').MenuItem, + geom = require('geometry'), ccp = geom.ccp + +var TouchDispatcher = require('../TouchDispatcher').TouchDispatcher + +/** + * @private + * @constant + */ +var kMenuStateWaiting = 0 + +/** + * @private + * @constant + */ +var kMenuStateTrackingTouch = 1 + +var kMenuTouchPriority = -128 + +/** + * @class + * A fullscreen node used to render a selection of menu options + * + * @memberOf cocos.nodes + * @extends cocos.nodes.Layer + * + * @opt {cocos.nodes.MenuItem[]} items An array of MenuItems to draw on the menu + */ +function Menu (opts) { + Menu.superclass.constructor.call(this, opts) + + var items = opts.items + + if (Director.sharedDirector.isTouchScreen) { + this.isTouchEnabled = true + } else { + this.isMouseEnabled = true + } + + var s = Director.sharedDirector.winSize + + this.isRelativeAnchorPoint = false + this.anchorPoint = ccp(0.5, 0.5) + this.contentSize = s + + this.position = ccp(s.width / 2, s.height / 2) + + + if (items) { + var z = 0 + items.forEach(function (item) { + this.addChild({child: item, z: z++}) + }.bind(this)) + } +} + +Menu.inherit(Layer, /** @lends cocos.nodes.Menu# */ { + mouseDelegatePriority: (-Number.MAX_VALUE + 1), + state: kMenuStateWaiting, + selectedItem: null, + color: null, + + addChild: function (opts) { + if (!opts.child instanceof MenuItem) { + throw "Menu only supports MenuItem objects as children" + } + + Menu.superclass.addChild.call(this, opts) + }, + + // Touch Events + registerWithTouchDispatcher: function () { + TouchDispatcher.sharedDispatcher.addTargetedDelegate(this, kMenuTouchPriority, true) + }, + + itemForTouch: function (event) { + var location = Director.sharedDirector.convertTouchToCanvas(event.touch) + + var children = this.children + for (var i = 0, len = children.length; i < len; i++) { + var item = children[i] + + if (item.visible && item.isEnabled) { + var local = item.convertToNodeSpace(location) + + var r = item.rect + r.origin = ccp(0, 0) + + if (geom.rectContainsPoint(r, local)) { + return item + } + + } + } + + return null + }, + + touchBegan: function (evt) { + if (this.state != kMenuStateWaiting || !this.visible) { + return false + } + + for (var c = this.parent; c; c = c.parent) { + if (!c.visible) + return false + } + + var selectedItem = this.itemForTouch(evt) + this.selectedItem = selectedItem + if (selectedItem) { + selectedItem.selected() + this.state = kMenuStateTrackingTouch + + return true + } + + return false + }, + + touchEnded: function (evt) { + var selItem = this.selectedItem + + if (selItem) { + selItem.unselected() + selItem.activate() + } + + if (this.state != kMenuStateWaiting) { + this.state = kMenuStateWaiting + } + }, + + touchCancelled: function (evt) { + var selItem = this.selectedItem + + if (selItem) { + selItem.unselected() + } + + if (this.state != kMenuStateWaiting) { + this.state = kMenuStateWaiting + } + }, + + touchMoved: function (evt) { + var currentItem = this.itemForTouch(evt) + + if (currentItem != this.selectedItem) { + if (this.selectedItem) { + this.selectedItem.unselected() + } + this.selectedItem = currentItem + if (this.selectedItem) { + this.selectedItem.selected() + } + } + }, + + + // Mouse Events + itemForMouseEvent: function (event) { + var location = event.locationInCanvas + + var children = this.children + for (var i = 0, len = children.length; i < len; i++) { + var item = children[i] + + if (item.visible && item.isEnabled) { + var local = item.convertToNodeSpace(location) + + var r = item.rect + r.origin = ccp(0, 0) + + if (geom.rectContainsPoint(r, local)) { + return item + } + + } + } + + return null + }, + + mouseUp: function (event) { + var selItem = this.selectedItem + + if (selItem) { + selItem.unselected() + selItem.activate() + } + + if (this.state != kMenuStateWaiting) { + this.state = kMenuStateWaiting + } + if (selItem) { + return true + } + return false + + }, + mouseDown: function (event) { + if (this.state != kMenuStateWaiting || !this.visible) { + return false + } + + var selectedItem = this.itemForMouseEvent(event) + this.selectedItem = selectedItem + if (selectedItem) { + selectedItem.selected() + this.state = kMenuStateTrackingTouch + + return true + } + + return false + }, + + mouseDragged: function (event) { + var currentItem = this.itemForMouseEvent(event) + + if (currentItem != this.selectedItem) { + if (this.selectedItem) { + this.selectedItem.unselected() + } + this.selectedItem = currentItem + if (this.selectedItem) { + this.selectedItem.selected() + } + } + + if (currentItem && this.state == kMenuStateTrackingTouch) { + return true + } + + return false + + } + +}) + +exports.Menu = Menu + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/nodes/Menu.js + + +__jah__.resources["/libs/cocos2d/nodes/MenuItem.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var util = require('util'), + Node = require('./Node').Node, + Sprite = require('./Sprite').Sprite, + rectMake = require('geometry').rectMake, + ccp = require('geometry').ccp + +/** + * @class + * Base class for any buttons or options in a menu + * + * @memberOf cocos.nodes + * @extends cocos.nodes.Node + * + * @opt {Function} callback Function to call when menu item is activated + */ +function MenuItem (opts) { + MenuItem.superclass.constructor.call(this, opts) + + var callback = opts.callback + + this.anchorPoint = ccp(0.5, 0.5) + this.callback = callback +} + +MenuItem.inherit(Node, /** @lends cocos.nodes.MenuItem# */ { + _isEnabled: true, + isSelected: false, + callback: null, + + activate: function () { + if (this.isEnabled && this.callback) { + this.callback(this) + } + }, + + /** + * @getter rect + * @type geometry.Rect + */ + get rect () { + return rectMake( + this.position.x - this.contentSize.width * this.anchorPoint.x, + this.position.y - this.contentSize.height * this.anchorPoint.y, + this.contentSize.width, + this.contentSize.height + ) + }, + + get isEnabled () { + return this._isEnabled + }, + + set isEnabled (enabled) { + this._isEnabled = enabled + }, + + selected: function () { + this.isSelected = true + }, + + unselected: function () { + this.isSelected = false + } +}) + +/** + * @class + * A menu item that accepts any cocos.nodes.Node + * + * @memberOf cocos.nodes + * @extends cocos.nodes.MenuItem + * + * @opt {cocos.nodes.Node} normalImage Main Node to draw + * @opt {cocos.nodes.Node} selectedImage Node to draw when menu item is selected + * @opt {cocos.nodes.Node} disabledImage Node to draw when menu item is disabled + */ +function MenuItemSprite (opts) { + MenuItemSprite.superclass.constructor.call(this, opts) + + var normalImage = opts.normalImage, + selectedImage = opts.selectedImage, + disabledImage = opts.disabledImage + + this.normalImage = normalImage + this.selectedImage = selectedImage + this.disabledImage = disabledImage + + this.contentSize = normalImage.contentSize +} + +MenuItemSprite.inherit(MenuItem, /** @lends cocos.nodes.MenuItemSprite# */ { + _normalImage: null, + _selectedImage: null, + _disabledImage: null, + + get normalImage () { + return this._normalImage + }, + + set normalImage (image) { + if (image != this.normalImage) { + image.anchorPoint = ccp(0, 0) + image.visible = true + this.removeChild({child: this.normalImage, cleanup: true}) + this.addChild(image) + + this._normalImage = image + } + }, + + get selectedImage () { + return this._selectedImage + }, + + set selectedImage (image) { + if (image != this.selectedImage) { + image.anchorPoint = ccp(0, 0) + image.visible = false + this.removeChild({child: this.selectedImage, cleanup: true}) + this.addChild(image) + + this._selectedImage = image + } + }, + + get disabledImage () { + return this._disabledImage + }, + + set disabledImage (image) { + if (image != this.disabledImage) { + image.anchorPoint = ccp(0, 0) + image.visible = false + this.removeChild({child: this.disabledImage, cleanup: true}) + this.addChild(image) + + this._disabledImage = image + } + }, + + selected: function () { + MenuItemSprite.superclass.selected.call(this) + + if (this.selectedImage) { + this.normalImage.visible = false + this.selectedImage.visible = true + if (this.disabledImage) this.disabledImage.visible = false + } else { + this.normalImage.visible = true + if (this.disabledImage) this.disabledImage.visible = false + } + }, + + unselected: function () { + MenuItemSprite.superclass.unselected.call(this) + + this.normalImage.visible = true + if (this.selectedImage) this.selectedImage.visible = false + if (this.disabledImage) this.disabledImage.visible = false + }, + + get isEnabled () { + return this._isEnabled + }, + + set isEnabled (enabled) { + this._isEnabled = enabled + + if (enabled) { + this.normalImage.visible = true + if (this.selectedImage) this.selectedImage.visible = false + if (this.disabledImage) this.disabledImage.visible = false + } else { + if (this.disabledImage) { + this.normalImage.visible = false + if (this.selectedImage) this.selectedImage.visible = false + this.disabledImage.visible = true + } else { + this.normalImage.visible = true + if (this.selectedImage) this.selectedImage.visible = false + } + } + } +}) + +/** + * @class + * MenuItem that accepts image files + * + * @memberOf cocos.nodes + * @extends cocos.nodes.MenuItemSprite + * + * @opt {String} normalImage Main image file to draw + * @opt {String} selectedImage Image file to draw when menu item is selected + * @opt {String} disabledImage Image file to draw when menu item is disabled + */ +function MenuItemImage (opts) { + var normalI = opts.normalImage, + selectedI = opts.selectedImage, + disabledI = opts.disabledImage, + callback = opts.callback + + var normalImage = new Sprite({file: normalI}), + selectedImage = new Sprite({file: selectedI}), + disabledImage = null + + if (disabledI) { + disabledImage = new Sprite({file: disabledI}) + } + + MenuItemImage.superclass.constructor.call(this, {normalImage: normalImage, selectedImage: selectedImage, disabledImage: disabledImage, callback: callback}) +} + +MenuItemImage.inherit(MenuItemSprite) + +exports.MenuItem = MenuItem +exports.MenuItemImage = MenuItemImage +exports.MenuItemSprite = MenuItemSprite + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/nodes/MenuItem.js + + +__jah__.resources["/libs/cocos2d/nodes/Node.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +//{{{ Imports +var util = require('util') + , events = require('events') + , geo = require('geometry') + , ccp = geo.ccp + +var Scheduler = require('../Scheduler').Scheduler + , ActionManager = require('../ActionManager').ActionManager +//}}} + +/** + * @class + * The base class all visual elements extend from + * + * @memberOf cocos.nodes + */ +function Node () { + this._contentSize = new geo.Size(0, 0) + this._anchorPoint = ccp(0.0, 0.0) + this.anchorPointInPixels = ccp(0, 0) + this._position = ccp(0, 0) + this.children = [] + + events.addListener(this, 'dirtytransform', this._dirtyTransform.bind(this)) +} + +Node.inherit(Object, /** @lends cocos.nodes.Node# */ { + /** + * Is the node visible + * @type Boolean + */ + get visible () { return this._visible } + , set visible (x) { this._visible = x; this._dirtyDraw() } + , _visible: true + + /** + * Position relative to parent node + * @type geometry.Point + */ + , get position () { return this._position } + , set position (x) { this._position = x; events.trigger(this, 'dirtytransform', {target: this, property: 'position'}) } + , _position: null + + , get ready () { return this._ready } + , set ready (x) { this._ready = !!x; x && events.trigger(this, 'ready', {target: this}) } + , _ready: true + + /** + * Parent node + * @type cocos.nodes.Node + * @readonly + */ + , parent: null + + /** + * Unique tag to identify the node + * @type String + */ + , tag: null + + /** + * Size of the node + * @type geometry.Size + */ + , get contentSize () { return this._contentSize } + , set contentSize (x) { this._contentSize = x; events.trigger(this, 'dirtytransform', {target: this, property: 'contentSize'}); this._updateAnchorPointInPixels() } + , _contentSize: null + + /** + * Nodes Z index. i.e. draw order + * @type Integer + */ + , zOrder: 0 + + /** + * Anchor point for scaling and rotation. 0x0 is top left and 1x1 is bottom right + * @type geometry.Point + */ + , get anchorPoint () { return this._anchorPoint } + , set anchorPoint (x) { this._anchorPoint = x; events.trigger(this, 'dirtytransform', {target: this, property: 'anchorPoint'}); this._updateAnchorPointInPixels() } + + /** + * Anchor point for scaling and rotation in pixels from top left + * @type geometry.Point + */ + , anchorPointInPixels: null + + /** + * Rotation angle in degrees + * @type Float + */ + , get rotation () { return this._rotation } + , set rotation (x) { this._rotation = x; events.trigger(this, 'dirtytransform', {target: this, property: 'rotation'}) } + , _rotation: 0 + + /** + * X scale factor + * @type Float + */ + , get scaleX () { return this._scaleX } + , set scaleX (x) { this._scaleX = x; events.trigger(this, 'dirtytransform', {target: this, property: 'scaleX'}) } + + /** + * @ignore + */ + , _scaleX: 1 + + /** + * Y scale factor + * @type Float + */ + , get scaleY () { return this._scaleY } + , set scaleY (x) { this._scaleY = x; events.trigger(this, 'dirtytransform', {target: this, property: 'scaleY'}) } + + /** + * @ignore + */ + , _scaleY: 1 + + /** + * Opacity of the Node. 0 is totally transparent, 255 is totally opaque + * @type Float + */ + , get opacity () { return this._opacity } + , set opacity (x) { this._opacity = x; this._dirtyDraw() } + , _opacity: 255 + + /** + * Is the node active in the scene + * @type Boolean + * @readonly + */ + , isRunning: false + + /** + * Is the anchor point relative to the Node + * @type Boolean + */ + , get isRelativeAnchorPoint () { return this._isRelativeAnchorPoint } + , set isRelativeAnchorPoint (x) { this._isRelativeAnchorPoint = x; events.trigger(this, 'dirtytransform', {target: this, property: 'isRelativeAnchorPoint'}) } + , _isRelativeAnchorPoint: true + + /** + * Has a property changed the requires recaculation of the transform matrix + * @type Boolean + */ + , isTransformDirty: true + + , isInverseDirty: true + + , inverse: null + + /** + * Current transform matrix used to render the Node. Set by cocos.nodes.Node#nodeToParentTransform + * @type Boolean + */ + , transformMatrix: null + + /** + * The child Nodes + * @type {cocos.nodes.Node[]} + */ + , children: null + + /** + * @private + * Calculates the anchor point in pixels and updates the + * anchorPointInPixels property + */ + , _updateAnchorPointInPixels: function () { + var ap = this.anchorPoint + , cs = this.contentSize + this.anchorPointInPixels = ccp(cs.width * ap.x, cs.height * ap.y) + } + + /** + * Add a child Node + * + * @opt {cocos.nodes.Node} child The child node to add + * @opt {Integer} [z] Z Index for the child + * @opt {Integer|String} [tag] A tag to reference the child with + * @returns {cocos.nodes.Node} The node the child was added to. i.e. 'this' + */ + , addChild: function (opts) { + if (opts instanceof Node) { + return this.addChild({child: opts}) + } + + var child = opts.child + , z = opts.z + , tag = opts.tag + , added = false + + if (z === undefined || z === null) { + z = child.zOrder + } + + //this.insertChild({child: child, z:z}) + + + var childLen = this.children.length + , i, c + for (i = 0; i < childLen; i++) { + c = this.children[i] + if (c.zOrder > z) { + added = true + this.children.splice(i, 0, child) + break + } + } + + if (!added) { + this.children.push(child) + } + + child.tag = tag + child.zOrder = z + child.parent = this + + if (this.isRunning) { + child.onEnter() + } + + return this + } + + /** + * Get a child node via its tag. Returns null if no Node is found + * + * @opt {String} tag Tag of the Node to return + * + * @returns cocos.nodes.Node + */ + , getChild: function (opts) { + var tag = opts.tag + + for (var i = 0; i < this.children.length; i++) { + if (this.children[i].tag == tag) { + return this.children[i] + } + } + + return null + } + + /** + * Remove a child node. + * + * If 'cleanup' is true all actions and scheduled methods will be removed + * from the child and its children. You must set this to 'true' if you're + * removing the object forever or you will have a memory leak. + * + * @opt {cocos.nodes.Node} child The Node to remove + * @opt {Boolean} [cleanup=false] Should a cleanup be performed after removing the Node + */ + , removeChild: function (opts) { + if (opts instanceof Node) { + return this.removeChild({child: opts}) + } + + var child = opts.child + , cleanup = opts.cleanup + + if (!child) { + return + } + + var children = this.children + , idx = children.indexOf(child) + + if (idx > -1) { + this._detachChild({child: child, cleanup: cleanup}) + } + } + + /** + * Remove all child nodes. + * + * If 'cleanup' is true all actions and scheduled methods will be removed + * from the child and its children. + * + * @opt {Boolean} [cleanup=false] Should a cleanup be performed after removing the Node + */ + , removeChildren: function (opts) { + var children = this.children + , isRunning = this.isRunning + + // Perform cleanup on each child but can't call removeChild() + // due to Array.splice's destructive nature during iteration. + for (var i = 0; i < children.length; i++) { + if (opts.cleanup) { + children[i].cleanup() + } + if (isRunning) { + children[i].onExit() + } + children[i].parent = null + } + // Now safe to empty children list + this.children = [] + } + + /** + * @private + * Detach the child node from this node + * + * @opt {cocos.nodes.Node} child The Node to remove + * @opt {Boolean} [cleanup=false] Should a cleanup be performed after removing the Node + */ + , _detachChild: function (opts) { + var child = opts.child + , cleanup = opts.cleanup + + var children = this.children + , isRunning = this.isRunning + , idx = children.indexOf(child) + + if (isRunning) { + child.onExit() + } + + if (cleanup) { + child.cleanup() + } + + child.parent = null + children.splice(idx, 1) + } + + /** + * Change the Z index of a child node. Other child nodes will have their Z + * index adjusted to accommodate. + * + * @opt {cocos.nodes.Node} child Child node to reorder + * @opt {Integer} z The new Z index for the child + */ + , reorderChild: function (opts) { + var child = opts.child + , z = opts.z + , pos = this.children.indexOf(child) + + if (pos == -1) { + throw "Node isn't a child of this node" + } + + child.zOrder = z + + // Remove child + this.children.splice(pos, 1) + + // Add child back at correct location + var added = false + , childLen = this.children.length + , i, c + for (i = 0; i < childLen; i++) { + c = this.children[i] + if (c.zOrder > z) { + added = true + this.children.splice(i, 0, child) + break + } + } + + if (!added) { + this.children.push(child) + } + } + + /** + * Draws the node. Override to do custom drawing. If it's less efficient to + * draw only the area inside the rect then don't bother. The result will be + * clipped to that area anyway. + * + * @param {CanvasRenderingContext2D} context Canvas rendering context + * @param {geometry.Rect} rect Rectangular region that needs redrawing. Limit drawing to this area only if it's more efficient to do so. + */ + , draw: function (context, rect) { + // All draw code goes here + } + + /** + * The scale factor for the node. Only valid is scaleX and scaleY are identical + * + * @type Float + */ + , get scale () { + if (this.scaleX != this.scaleY) { + throw "scaleX and scaleY aren't identical" + } + + return this.scaleX + } + + /** + * Sets both scaleX and scaleY to the given value + * + * @type Float + */ + , set scale (val) { + this.scaleX = val + this.scaleY = val + } + + /** + * Schedule a timer to call the 'update' method on this node every frame + * + * @opt {Integer} [priority=0] Priority order for when the method should be called + */ + , scheduleUpdate: function (opts) { + opts = opts || {} + var priority = opts.priority || 0 + + Scheduler.sharedScheduler.scheduleUpdate({target: this, priority: priority, paused: !this.isRunning}) + } + + , unscheduleUpdate: function () { + Scheduler.sharedScheduler.unscheduleUpdateForTarget(this) + } + + /** + * Triggered when the node is added to a scene + * + * @event + */ + , onEnter: function () { + this.children.forEach(function (child) { child.onEnter() }) + + this.resumeSchedulerAndActions() + this.isRunning = true + } + + /** + * Triggered when the node is removed from a scene + * + * @event + */ + , onExit: function () { + this.pauseSchedulerAndActions() + this.isRunning = false + + this.children.forEach(function (child) { child.onExit() }) + } + + /** + * Stop and remove all actions and scheduled method calls on itself and + * children + */ + , cleanup: function () { + this.stopAllActions() + this.unscheduleAllSelectors() + this.children.forEach(function (child) { child.cleanup() }) + } + + , resumeSchedulerAndActions: function () { + Scheduler.sharedScheduler.resumeTarget(this) + ActionManager.sharedManager.resumeTarget(this) + } + + /** + * Temporarily pause scheduled methods and actions + */ + , pauseSchedulerAndActions: function () { + Scheduler.sharedScheduler.pauseTarget(this) + ActionManager.sharedManager.pauseTarget(this) + } + + /** + * Remove a specific scheduled method call + */ + , unscheduleSelector: function (selector) { + Scheduler.sharedScheduler.unschedule({target: this, method: selector}) + } + + /** + * Remove all scheduled methods calls + */ + , unscheduleAllSelectors: function () { + Scheduler.sharedScheduler.unscheduleAllSelectorsForTarget(this) + } + + /** + * Stop all running actions on this node + */ + , stopAllActions: function () { + ActionManager.sharedManager.removeAllActionsFromTarget(this) + } + + /** + * Called automatically every frame and triggers the call to 'draw' this + * node and its children in the correct order. + * + * For custom drawing override the 'draw' method. Only override this if you + * really need to do something special. + * + * @param {CanvasRenderingContext2D} context Canvas rendering context + * @param {geometry.Rect} [rect] Area that needs redrawing + */ + , visit: function (context, rect) { + if (!this.visible) { + return + } + + context.save() + + this.transform(context) + + // Set alpha value (global only for now) + context.globalAlpha = this.opacity / 255.0 + + // Adjust redraw region by nodes position + if (rect) { + var pos = this.position + rect = new geo.Rect(rect.origin.x - pos.x, rect.origin.y - pos.y, rect.size.width, rect.size.height) + } + + // Draw background nodes + this.children.forEach(function (child, i) { + if (child.zOrder < 0) { + child.visit(context, rect) + } + }) + + this.draw(context, rect) + + // Draw foreground nodes + this.children.forEach(function (child, i) { + if (child.zOrder >= 0) { + child.visit(context, rect) + } + }) + + context.restore() + } + + /** + * Transforms the node by its scale, rotation and position. Called automatically when one of these changes + * + * @param {CanvasRenderingContext2D} context Canvas rendering context + */ + , transform: function (context) { + // Translate + if (this.isRelativeAnchorPoint && (this.anchorPointInPixels.x !== 0 || this.anchorPointInPixels.y !== 0)) { + context.translate(Math.round(-this.anchorPointInPixels.x), Math.round(-this.anchorPointInPixels.y)) + } + + if (this.anchorPointInPixels.x !== 0 || this.anchorPointInPixels.y !== 0) { + context.translate(Math.round(this.position.x + this.anchorPointInPixels.x), Math.round(this.position.y + this.anchorPointInPixels.y)) + } else { + context.translate(Math.round(this.position.x), Math.round(this.position.y)) + } + + // Rotate + if (cc.FLIP_Y_AXIS) { + context.rotate(-geo.degreesToRadians(this.rotation)) + } else { + context.rotate(geo.degreesToRadians(this.rotation)) + } + + // Scale + context.scale(this.scaleX, this.scaleY) + + if (this.anchorPointInPixels.x !== 0 || this.anchorPointInPixels.y !== 0) { + context.translate(Math.round(-this.anchorPointInPixels.x), Math.round(-this.anchorPointInPixels.y)) + } + } + + /** + * Run an action on the node + * + * @param {cocos.actions.Action} action Action to run + */ + , runAction: function (action) { + ActionManager.sharedManager.addAction({action: action, target: this, paused: this.isRunning}) + } + + /** + * @opt {String} tag Tag of the action to return + */ + , getAction: function (opts) { + return ActionManager.sharedManager.getActionFromTarget({target: this, tag: opts.tag}) + } + + , nodeToParentTransform: function () { + if (this.isTransformDirty) { + this.transformMatrix = geo.affineTransformIdentity() + + if (!this.isRelativeAnchorPoint && !geo.pointEqualToPoint(this.anchorPointInPixels, ccp(0, 0))) { + this.transformMatrix = geo.affineTransformTranslate(this.transformMatrix, this.anchorPointInPixels.x, this.anchorPointInPixels.y) + } + + if (!geo.pointEqualToPoint(this.position, ccp(0, 0))) { + this.transformMatrix = geo.affineTransformTranslate(this.transformMatrix, this.position.x, this.position.y) + } + + if (this.rotation !== 0) { + this.transformMatrix = geo.affineTransformRotate(this.transformMatrix, -geo.degreesToRadians(this.rotation)) + } + if (!(this.scaleX == 1 && this.scaleY == 1)) { + this.transformMatrix = geo.affineTransformScale(this.transformMatrix, this.scaleX, this.scaleY) + } + + if (!geo.pointEqualToPoint(this.anchorPointInPixels, ccp(0, 0))) { + this.transformMatrix = geo.affineTransformTranslate(this.transformMatrix, -this.anchorPointInPixels.x, -this.anchorPointInPixels.y) + } + + this.isTransformDirty = false + + } + + return this.transformMatrix + } + + , parentToNodeTransform: function () { + // TODO + } + + , nodeToWorldTransform: function () { + var t = this.nodeToParentTransform() + + var p + for (p = this.parent; p; p = p.parent) { + t = geo.affineTransformConcat(t, p.nodeToParentTransform()) + } + + return t + } + + , worldToNodeTransform: function () { + return geo.affineTransformInvert(this.nodeToWorldTransform()) + } + + , convertToNodeSpace: function (worldPoint) { + return geo.pointApplyAffineTransform(worldPoint, this.worldToNodeTransform()) + } + + /** + * Rectangle bounding box relative to its parent Node + * + * @type geometry.Rect + */ + , get boundingBox () { + if (this.isTransformDirty || !this._boundingBox) { + this._updateBoundingBox() + } + return this._boundingBox + } + + + , _updateBoundingBox: function () { + var cs = this.contentSize + , rect = new geo.Rect(0, 0, cs.width, cs.height) + + this._boundingBox = geo.rectApplyAffineTransform(rect, this.nodeToParentTransform()) + } + + /** + * Rectangle bounding box relative to the world + * + * @type geometry.Rect + */ + , get worldBoundingBox () { + var cs = this.contentSize + , rect = new geo.Rect(0, 0, cs.width, cs.height) + + rect = geo.rectApplyAffineTransform(rect, this.nodeToWorldTransform()) + return rect + } + + /** + * The area of the node currently visible on screen. Returns an rect even + * if visible is false. + * + * @type geometry.Rect + */ + , get visibleRect () { + var s = require('../Director').Director.sharedDirector.winSize + , rect = new geo.Rect(0, 0, s.width, s.height) + + return geo.rectApplyAffineTransform(rect, this.worldToNodeTransform()) + } + + /** + * @private + */ + , _dirtyTransform: function () { + var oldBB = this.boundingBox + this.isTransformDirty = true + this._dirtyDraw(oldBB) + events.trigger(this, 'transformdirty', oldBB) + } + + , _dirtyDraw: function (oldBB) { + events.trigger(this, 'drawdirty', (oldBB instanceof geo.Rect) ? oldBB : void(0)) + } + + /** + * Schedules a custom method with an interval time in seconds. + * If time is 0, it will be ticked every frame. + * If time is 0, it is recommended to use 'scheduleUpdate' instead. + * + * If the method is already scheduled, then the interval parameter will + * be updated without scheduling it again. + * + * @opt {String|Function} method Function of method name to schedule + * @opt {Float} [interval=0] Interval in seconds + */ + , schedule: function (opts) { + if (typeof opts == 'string') { + return this.schedule({method: opts, interval: 0}) + } + + opts.interval = opts.interval || 0 + + Scheduler.sharedScheduler.schedule({target: this, method: opts.method, interval: opts.interval, paused: this.isRunning}) + } + + /** + * Unschedules a custom method + * + * @param {String|Function} method + */ + , unschedule: function (method) { + if (!method) { + return + } + + if (typeof method == 'string') { + method = this[method] + } + + Scheduler.sharedScheduler.unschedule({target: this, method: method}) + } + +}) + +module.exports.Node = Node + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/nodes/Node.js + + +__jah__.resources["/libs/cocos2d/nodes/PreloadScene.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var Scene = require('./Scene').Scene, + Director = require('../Director').Director, + Label = require('./Label').Label, + ProgressBar = require('./ProgressBar').ProgressBar, + Preloader = require('preloader').Preloader, + RemoteResource = require('remote_resources').RemoteResource, + geo = require('geometry'), + util = require('util'), + events = require('events') + + +/** + * @class + * To customise the preload screen you should inherit from + * cocos.nodes.PreloadScene and then set Director.sharedDirector.preloadSceneConstructor + * to your PreloadScene. + * + * @memberOf cocos.nodes + * @extends cocos.nodes.Scene + */ +function PreloadScene (opts) { + PreloadScene.superclass.constructor.call(this, opts) + + // Setup preloader + var preloader = new Preloader() // The main preloader + this.preloader = preloader + + // Listen for preload events + events.addListener(preloader, 'load', function (preloader, uri) { + events.trigger(this, 'load', preloader, uri) + }.bind(this)) + + events.addListener(preloader, 'complete', function (preloader) { + events.trigger(this, 'complete', preloader) + }.bind(this)) +} + +PreloadScene.inherit(Scene, /** @lends cocos.nodes.PreloadScene# */ { + preloader: null + + /** + * True when we're going to preload the queue + * @type Boolean + */ + , isReady: false + + , load: function () { + if (this.isRunning) { + this.populateQueue() + this.preloader.load() + } + + this.isReady = true + } + , populateQueue: function () { + this.preloader.addEverythingToQueue() + } + , onEnter: function () { + PreloadScene.superclass.onEnter.call(this) + + if (this.isReady) { + this.preloader.load() + } + } + +}) + +exports.PreloadScene = PreloadScene + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/nodes/PreloadScene.js + + +__jah__.resources["/libs/cocos2d/nodes/ProgressBar.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var Node = require('./Node').Node, + util = require('util'), + geo = require('geometry'), + events = require('events'), + Sprite = require('./Sprite').Sprite + +/** + * @class + * + * @memberOf cocos.nodes + * @extends cocos.nodes.Node + */ +function ProgressBar (opts) { + ProgressBar.superclass.constructor.call(this, opts) + var size = new geo.Size(272, 32) + this.contentSize = size + this.anchorPoint = new geo.Point(0.5, 0.5) + + var s + if (opts.emptyImage) { + s = new Sprite({file: opts.emptyImage, rect: new geo.Rect(0, 0, size.width, size.height)}) + s.anchorPoint = new geo.Point(0, 0) + this.emptySprite = s + this.addChild({child: s}) + } + if (opts.fullImage) { + s = new Sprite({file: opts.fullImage, rect: new geo.Rect(0, 0, 0, size.height)}) + s.anchorPoint = new geo.Point(0, 0) + this.fullSprite = s + this.addChild({child: s}) + } + + events.addPropertyListener(this, 'maxValue', 'change', this.updateImages.bind(this)) + events.addPropertyListener(this, 'value', 'change', this.updateImages.bind(this)) + + this.updateImages() +} + +ProgressBar.inherit(Node, /** @lends cocos.nodes.ProgressBar# */ { + emptySprite: null, + fullSprite: null, + maxValue: 100, + value: 0, + + updateImages: function () { + var empty = this.emptySprite, + full = this.fullSprite, + value = this.value, + size = this.contentSize, + maxValue = this.maxValue, + ratio = (value / maxValue) + + var diff = Math.round(size.width * ratio) + if (diff === 0) { + full.visible = false + } else { + full.visible = true + full.rect = new geo.Rect(0, 0, diff, size.height) + full.contentSize = new geo.Size(diff, size.height) + } + + if ((size.width - diff) === 0) { + empty.visible = false + } else { + empty.visible = true + empty.rect = new geo.Rect(diff, 0, size.width - diff, size.height) + empty.position = new geo.Point(diff, 0) + empty.contentSize = new geo.Size(size.width - diff, size.height) + } + } +}) + +exports.ProgressBar = ProgressBar + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/nodes/ProgressBar.js + + +__jah__.resources["/libs/cocos2d/nodes/ProgressBarPreloadScene.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var PreloadScene = require('./PreloadScene').PreloadScene + , Director = require('../Director').Director + , Label = require('./Label').Label + , ProgressBar = require('./ProgressBar').ProgressBar + , Preloader = require('preloader').Preloader + , RemoteResource = require('remote_resources').RemoteResource + , geo = require('geometry') + , util = require('util') + , events = require('events') + + +/** + * @class + * PreloadScene that draws a progress bar and 'please wait' message + * + * @memberOf cocos.nodes + * @extends cocos.nodes.PreloadScene + */ +function ProgressBarPreloadScene (opts) { + ProgressBarPreloadScene.superclass.constructor.call(this, opts) + var size = Director.sharedDirector.winSize + + // Setup 'please wait' label + var label = new Label({ + fontSize: 14, + fontName: 'Helvetica', + fontColor: '#ffffff', + string: 'Please wait...' + }) + label.position = new geo.Point(size.width / 2, (size.height / 2) + 32) + this.label = label + this.addChild({child: label}) + + // Preloader for the progress bar assets + var loadingPreloader = new Preloader([this.emptyImage, this.fullImage]) + + // When progress bar resources have loaded then draw them and load all the rest + events.addListener(loadingPreloader, 'complete', function (preloader) { + this.createProgressBar() + this.load() + }.bind(this)) + + loadingPreloader.load() +} + +ProgressBarPreloadScene.inherit(PreloadScene, /** @lends cocos.nodes.ProgressBarPreloadScene# */ { + progressBar: null, + label: null, + emptyImage: "/libs/cocos2d/resources/progress-bar-empty.png", + fullImage: "/libs/cocos2d/resources/progress-bar-full.png", + + createProgressBar: function () { + var preloader = this.preloader, + size = Director.sharedDirector.winSize + + var progressBar = new ProgressBar({ + emptyImage: "/libs/cocos2d/resources/progress-bar-empty.png", + fullImage: "/libs/cocos2d/resources/progress-bar-full.png" + }) + + progressBar.position = new geo.Point(size.width / 2, size.height / 2) + + this.progressBar = progressBar + this.addChild({child: progressBar}) + + events.addListener(preloader, 'load', function (preloader, uri) { + progressBar.maxValue = preloader.count + progressBar.value = preloader.loaded + }) + } +}) + +exports.ProgressBarPreloadScene = ProgressBarPreloadScene + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/nodes/ProgressBarPreloadScene.js + + +__jah__.resources["/libs/cocos2d/nodes/RenderTexture.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var util = require('util'), + evt = require('events'), + Node = require('./Node').Node, + geo = require('geometry'), + Sprite = require('./Sprite').Sprite, + TextureAtlas = require('../TextureAtlas').TextureAtlas, + ccp = geo.ccp + +/** + * @class + * An in-memory canvas which can be drawn to in the background before drawing on screen + * + * @memberOf cocos.nodes + * @extends cocos.nodes.Node + * + * @opt {Integer} width The width of the canvas + * @opt {Integer} height The height of the canvas + */ +function RenderTexture (opts) { + RenderTexture.superclass.constructor.call(this, opts) + + var width = opts.width, + height = opts.height + + evt.addPropertyListener(this, 'contentSize', 'change', this._resizeCanvas.bind(this)) + + this.canvas = document.createElement('canvas') + this.context = this.canvas.getContext('2d') + + var atlas = new TextureAtlas({canvas: this.canvas}) + this.sprite = new Sprite({textureAtlas: atlas, rect: {origin: ccp(0, 0), size: {width: width, height: height}}}) + + this.contentSize = geo.sizeMake(width, height) + this.addChild(this.sprite) + this.anchorPoint = ccp(0, 0) + this.sprite.anchorPoint = ccp(0, 0) + +} + +RenderTexture.inherit(Node, /** @lends cocos.nodes.RenderTexture# */ { + canvas: null, + context: null, + sprite: null, + + /** + * @private + */ + _resizeCanvas: function () { + var size = this.contentSize, + canvas = this.canvas + + canvas.width = size.width + canvas.height = size.height + if (cc.FLIP_Y_AXIS) { + this.context.scale(1, -1) + this.context.translate(0, -canvas.height) + } + + var s = this.sprite + if (s) { + s.textureRect = {rect: geo.rectMake(0, 0, size.width, size.height)} + } + }, + + /** + * Clear the canvas + */ + clear: function (rect) { + if (rect) { + this.context.clearRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height) + } else { + this.canvas.width = this.canvas.width + if (cc.FLIP_Y_AXIS) { + this.context.scale(1, -1) + this.context.translate(0, -this.canvas.height) + } + } + } +}) + +module.exports.RenderTexture = RenderTexture + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/nodes/RenderTexture.js + + +__jah__.resources["/libs/cocos2d/nodes/Scene.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var Node = require('./Node').Node + , Director = require('../Director').Director + , geo = require('geometry') + + +/** + * @class + * A Scene defines the entire view. e.g. A welcome screen, settings menu and + * game world will each be a differen Scene. + * + * Your Scene will contain one or more Layers which build up the user interface. + * + * Only one Scene can be visible at a time but you can swap between them when + * you need to show different components of the application. Think of them like + * full screen windows. Only the active Scene will receive calls to draw itself. + * + * @example + * var scene = new Scene() + * , layer = new Layer() + * scene.addChild(layer) + * Director.sharedDirector.runWithScene(scene) + * + * @memberOf cocos.nodes + * @extends cocos.nodes.Node + */ +function Scene () { + Scene.superclass.constructor.call(this) + + var s = Director.sharedDirector.winSize + + this.isRelativeAnchorPoint = false + this.anchorPoint = new geo.Point(0.5, 0.5) + this.contentSize = s +} + +Scene.inherit(Node) + +module.exports.Scene = Scene + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/nodes/Scene.js + + +__jah__.resources["/libs/cocos2d/nodes/Sprite.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var util = require('util') + , events = require('events') + , geo = require('geometry') + , ccp = geo.ccp + +var Director = require('../Director').Director + , SpriteFrameCache = require('../SpriteFrameCache').SpriteFrameCache + , TextureAtlas = require('../TextureAtlas').TextureAtlas + , Node = require('./Node').Node + +/** + * @class + * A 2D graphic that can be animated + * + * @memberOf cocos.nodes + * @extends cocos.nodes.Node + * + * @opt {String} file Path to image to use as sprite atlas + * @opt {Rect} [rect] The rect in the sprite atlas image file to use as the sprite + */ +function Sprite (opts) { + Sprite.superclass.constructor.call(this, opts) + + opts = opts || {} + + var file = opts.file + , url = opts.url + , textureAtlas = opts.textureAtlas + , texture = opts.texture + , frame = opts.frame + , spritesheet = opts.spritesheet + , rect = opts.rect + , frameName = opts.frameName + + this.anchorPoint = ccp(0.5, 0.5) + + this.offsetPosition = ccp(0, 0) + this.unflippedOffsetPositionFromCenter = ccp(0, 0) + + if (frameName) { + frame = SpriteFrameCache.sharedSpriteFrameCache.getSpriteFrame(frameName) + } + + if (frame) { + texture = frame.texture + rect = frame.rect + } + + events.addListener(this, 'dirtytransform', this._updateQuad.bind(this)) + events.addPropertyListener(this, 'textureAtlas', 'change', this._updateTextureQuad.bind(this)) + + if (url || file || texture) { + textureAtlas = new TextureAtlas({ url: url, file: file, texture: texture }) + } else if (spritesheet) { + textureAtlas = spritesheet.textureAtlas + this.useSpriteSheet = true + } else if (!textureAtlas) { + //throw "Sprite has no texture" + } + + if (!rect && textureAtlas) { + if (!url) { + rect = new geo.Rect(0, 0, textureAtlas.texture.size.width, textureAtlas.texture.size.height) + } else { + // Loading remote image, wait for it to finish before setting rect + events.addListener(textureAtlas, 'load', function () { + if (!this.rect) { + this.rect = new geo.Rect(0, 0, textureAtlas.texture.size.width, textureAtlas.texture.size.height) + } + }.bind(this)) + } + } + + if (rect) { + this.rect = rect + this.contentSize = rect.size + + this.quad = { drawRect: {origin: ccp(0, 0), size: rect.size} + , textureRect: rect + } + } + + this.textureAtlas = textureAtlas + + if (frame) { + this.displayFrame = frame + } +} + +Sprite.inherit(Node, /** @lends cocos.nodes.Sprite# */{ + textureAtlas: null + , dirty: true + , recursiveDirty: true + , quad: null + , flipX: false + , flipY: false + , offsetPosition: null + , unflippedOffsetPositionFromCenter: null + , untrimmedSize: null + + /** + * The rectangle area in the source image where the sprite is + * @type geometry.Rect + */ + , get rect () { return this._rect } + , set rect (x) { + this._rect = x; + if (!this.quad) { + this.quad = { drawRect: {origin: ccp(0, 0), size: this._rect.size} + , textureRect: this._rect + } + } + if (!this.contentSize || (this.contentSize.width == 0 && this.contentSize.height == 0)) { + this.contentSize = this._rect.size + } + events.trigger(this, 'dirtytransform', {target: this, property: 'rect'}) + } + , _rect: null + + /** + * @private + */ + , _updateTextureQuad: function (obj, key, texture, oldTexture) { + if (oldTexture) { + oldTexture.removeQuad({quad: this.quad}) + } + + if (texture) { + texture.insertQuad({quad: this.quad}) + } + } + + /** + * @type geometry.Rect + */ + , set textureCoords (rect) { + var quad = this.quad + if (!quad) { + quad = { + drawRect: geo.rectMake(0, 0, 0, 0), + textureRect: geo.rectMake(0, 0, 0, 0) + } + } + + quad.textureRect = util.copy(rect) + + this.quad = quad + } + + /** + * @type geometry.Rect + */ + , set textureRect (opts) { + var rect = opts.rect + , rotated = !!opts.rotated + , untrimmedSize = opts.untrimmedSize || rect.size + + this.contentSize = untrimmedSize + this.rect = util.copy(rect) + this.textureCoords = rect + + var quad = this.quad + + var relativeOffset = util.copy(this.unflippedOffsetPositionFromCenter) + + if (this.flipX) { + relativeOffset.x = -relativeOffset.x + } + if (this.flipY) { + relativeOffset.y = -relativeOffset.y + } + + var offsetPosition = util.copy(this.offsetPosition) + offsetPosition.x = relativeOffset.x + (this.contentSize.width - rect.size.width) / 2 + offsetPosition.y = -relativeOffset.y + (this.contentSize.height - rect.size.height) / 2 + + quad.drawRect.origin = util.copy(offsetPosition) + quad.drawRect.size = util.copy(rect.size) + if (this.flipX) { + quad.drawRect.size.width *= -1 + quad.drawRect.origin.x = -rect.size.width + } + if (this.flipY) { + quad.drawRect.size.height *= -1 + quad.drawRect.origin.y = -rect.size.height + } + + this.quad = quad + } + + /** + * @private + */ + , _updateQuad: function () { + if (!this.rect) { + return + } + if (!this.quad) { + this.quad = { drawRect: geo.rectMake(0, 0, 0, 0) + , textureRect: geo.rectMake(0, 0, 0, 0) + } + } + + var relativeOffset = util.copy(this.unflippedOffsetPositionFromCenter) + + if (this.flipX) { + relativeOffset.x = -relativeOffset.x + } + if (this.flipY) { + relativeOffset.y = -relativeOffset.y + } + + var offsetPosition = util.copy(this.offsetPosition) + offsetPosition.x = relativeOffset.x + (this.contentSize.width - this.rect.size.width) / 2 + offsetPosition.y = relativeOffset.y + (this.contentSize.height - this.rect.size.height) / 2 + + this.quad.textureRect = util.copy(this.rect) + this.quad.drawRect.origin = util.copy(offsetPosition) + this.quad.drawRect.size = util.copy(this.rect.size) + + if (this.flipX) { + this.quad.drawRect.size.width *= -1 + this.quad.drawRect.origin.x = -this.rect.size.width + } + if (this.flipY) { + this.quad.drawRect.size.height *= -1 + this.quad.drawRect.origin.y = -this.rect.size.height + } + } + + , updateTransform: function (ctx) { + if (!this.useSpriteSheet) { + throw "updateTransform is only valid when Sprite is being rendered using a SpriteSheet" + } + + if (!this.visible) { + this.dirty = false + this.recursiveDirty = false + return + } + + // TextureAtlas has hard reference to this quad so we can just update it directly + this.quad.drawRect.origin = new geo.Point( this.position.x - this.anchorPointInPixels.x * this.scaleX + , this.position.y - this.anchorPointInPixels.y * this.scaleY + ) + this.quad.drawRect.size = new geo.Size( this.rect.size.width * this.scaleX + , this.rect.size.height * this.scaleY + ) + + this.dirty = false + this.recursiveDirty = false + } + + , draw: function (ctx) { + if (!this.quad) { + return + } + this.textureAtlas.drawQuad(ctx, this.quad) + } + + , isFrameDisplayed: function (frame) { + if (!this.rect || !this.textureAtlas) { + return false + } + return (frame.texture === this.textureAtlas.texture && geo.rectEqualToRect(frame.rect, this.rect)) + } + + + /** + * @type cocos.SpriteFrame + */ + , set displayFrame (frame) { + if (!frame) { + delete this.quad + return + } + this.unflippedOffsetPositionFromCenter = util.copy(frame.offset) + + // change texture + if (!this.textureAtlas || frame.texture !== this.textureAtlas.texture) { + this.textureAtlas = new TextureAtlas({texture: frame.texture}) + } + + this.textureRect = {rect: frame.rect, rotated: frame.rotated, untrimmedSize: frame.originalSize} + } +}) + +module.exports.Sprite = Sprite + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/nodes/Sprite.js + + +__jah__.resources["/libs/cocos2d/nodes/TMXLayer.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var util = require('util') + , uri = require('uri') + , events = require('events') + , SpriteBatchNode = require('./BatchNode').SpriteBatchNode + , Sprite = require('./Sprite').Sprite + , TMXOrientationOrtho = require('../TMXOrientation').TMXOrientationOrtho + , TMXOrientationHex = require('../TMXOrientation').TMXOrientationHex + , TMXOrientationIso = require('../TMXOrientation').TMXOrientationIso + , geo = require('geometry') + , ccp = geo.ccp + , Node = require('./Node').Node + + + +var FLIPPED_HORIZONTALLY_FLAG = 0x80000000 + , FLIPPED_VERTICALLY_FLAG = 0x40000000 + , FLIPPED_DIAGONALLY_FLAG = 0x20000000 + +/** + * @class + * A tile map layer loaded from a TMX file. This will probably automatically be made by cocos.TMXTiledMap + * + * @memberOf cocos.nodes + * @extends cocos.nodes.SpriteBatchNode + * + * @opt {cocos.TMXTilesetInfo} tilesetInfo + * @opt {cocos.TMXLayerInfo} layerInfo + * @opt {cocos.TMXMapInfo} mapInfo + */ +function TMXLayer (opts) { + var tilesetInfo = opts.tilesetInfo, + layerInfo = opts.layerInfo, + mapInfo = opts.mapInfo + + var size = layerInfo.layerSize, + totalNumberOfTiles = size.width * size.height + + var tex = null + if (tilesetInfo) { + tex = tilesetInfo.sourceImage + } + + if (uri.isURL(tex)) { + TMXLayer.superclass.constructor.call(this, {url: tex}) + } else { + TMXLayer.superclass.constructor.call(this, {file: tex}) + } + + + this.anchorPoint = ccp(0, 0) + + this.layerName = layerInfo.name + this.layerSize = layerInfo.layerSize + this.tiles = layerInfo.tiles + this.minGID = layerInfo.minGID + this.maxGID = layerInfo.maxGID + this.opacity = layerInfo.opacity + this.properties = util.copy(layerInfo.properties) + + this.tileset = tilesetInfo + this.mapTileSize = mapInfo.tileSize + this.layerOrientation = mapInfo.orientation + + var offset = this.calculateLayerOffset(layerInfo.offset) + this.position = offset + + this.contentSize = new geo.Size(this.layerSize.width * this.mapTileSize.width, (this.layerSize.height * this.mapTileSize.height) + this.tileset.tileSize.height) +} + +TMXLayer.inherit(SpriteBatchNode, /** @lends cocos.nodes.TMXLayer# */ { + layerSize: null, + layerName: '', + tiles: null, + tilset: null, + layerOrientation: 0, + mapTileSize: null, + properties: null, + + calculateLayerOffset: function (pos) { + var ret = ccp(0, 0) + + switch (this.layerOrientation) { + case TMXOrientationOrtho: + ret = ccp(pos.x * this.mapTileSize.width, pos.y * this.mapTileSize.height) + break + case TMXOrientationIso: + // TODO + break + case TMXOrientationHex: + // TODO + break + } + + return ret + }, + + setupTiles: function () { + if (!this.ready) { + events.addListenerOnce(this, 'ready', this.setupTiles.bind(this)) + return + } + + this.tileset.imageSize = this.texture.contentSize + + this.parseInternalProperties() + + for (var y = 0; y < this.layerSize.height; y++) { + for (var x = 0; x < this.layerSize.width; x++) { + + var pos = x + this.layerSize.width * y + , gid = this.tiles[pos] + , flipH = gid & FLIPPED_HORIZONTALLY_FLAG + , flipV = gid & FLIPPED_VERTICALLY_FLAG + , flipD = gid & FLIPPED_DIAGONALLY_FLAG + + // Remove flip flags + gid &= ~( FLIPPED_HORIZONTALLY_FLAG + | FLIPPED_VERTICALLY_FLAG + | FLIPPED_DIAGONALLY_FLAG + ) + + + if (gid !== 0) { + this.appendTile({ gid: gid + , position: new geo.Point(x, y) + , flipH: flipH + , flipV: flipV + , flipD: flipD + }) + + // Optimization: update min and max GID rendered by the layer + this.minGID = Math.min(gid, this.minGID) + this.maxGID = Math.max(gid, this.maxGID) + } + } + } + }, + + propertyNamed: function (name) { + return this.properties[name] + }, + + parseInternalProperties: function () { + var vertexz = this.properties.cc_vertexz + + if (vertexz) { + if (vertexz === 'automatic') { + this._useAutomaticVertexZ = true + } else { + this._vertexZvalue = parseInt(vertexz, 10) + } + } + }, + + appendTile: function (opts) { + var gid = opts.gid, + pos = opts.position + + var z = pos.x + pos.y * this.layerSize.width + + var rect = this.tileset.rectForGID(gid) + var tile = new Sprite({rect: rect, textureAtlas: this.textureAtlas}) + tile.position = this.positionAt(pos) + tile.opacity = this.opacity + + var anchorX = 0 + , anchorY = 0 + if (opts.flipH) { + tile.scaleX = -1 + anchorX = 1 + } + if (opts.flipV) { + tile.scaleY = -1 + anchorY = 1 + } + if (opts.flipD) { + console.warn("Diagonal flipped tiles are unsupported") + } + + tile.anchorPoint = new geo.Point(anchorX, anchorY) + + this.addChild({ child: tile + , z: this.vertexZForPos(pos) + , tag: z + }) + + return tile + }, + positionAt: function (pos) { + switch (this.layerOrientation) { + case TMXOrientationOrtho: + return this.positionForOrthoAt(pos) + case TMXOrientationIso: + return this.positionForIsoAt(pos) + /* + case TMXOrientationHex: + // TODO + */ + default: + return ccp(0, 0) + } + }, + + vertexZForPos: function (pos) { + var maxVal = 0 + if (this._useAutomaticVertexZ) { + switch (this.layerOrientation) { + case TMXOrientationIso: + maxVal = this.layerSize.width + this.layerSize.height + return -(maxVal - (pos.x + pos.y)) + case TMXOrientationOrtho: + return -(this.layerSize.height - pos.y) + case CCTMXOrientationHex: + throw new Error("TMX Hexa zOrder not supported") + default: + throw new Error("TMX invalid value") + } + } else { + return this._vertexZvalue + } + }, + + positionForOrthoAt: function (pos) { + var overlap = this.mapTileSize.height - this.tileset.tileSize.height + var x = Math.floor(pos.x * this.mapTileSize.width + 0.49) + var y + if (cc.FLIP_Y_AXIS) { + y = Math.floor((this.layerSize.height - pos.y - 1) * this.mapTileSize.height + 0.49) + } else { + y = Math.floor(pos.y * this.mapTileSize.height + 0.49) + overlap + } + return ccp(x, y) + }, + + positionForIsoAt: function (pos) { + var mapTileSize = this.mapTileSize, + layerSize = this.layerSize + + if (cc.FLIP_Y_AXIS) { + return ccp( + mapTileSize.width / 2 * (layerSize.width + pos.x - pos.y - 1), + mapTileSize.height / 2 * ((layerSize.height * 2 - pos.x - pos.y) - 2) + ) + } else { + throw "Isometric tiles without cc.FLIP_Y_AXIS is currently unsupported" + } + }, + + /** + * Get the tile at a specifix tile coordinate + * + * @param {geometry.Point} pos Position of tile to get in tile coordinates (not pixels) + * @returns {cocos.nodes.Sprite} The tile + */ + tileAt: function (pos) { + var layerSize = this.layerSize, + tiles = this.tiles + + if (pos.x < 0 || pos.y < 0 || pos.x >= layerSize.width || pos.y >= layerSize.height) { + throw "TMX Layer: Invalid position" + } + + var tile, + gid = this.tileGIDAt(pos) + + // if GID is 0 then no tile exists at that point + if (gid) { + var z = pos.x + pos.y * layerSize.width + tile = this.getChild({tag: z}) + } + + return tile + }, + + + tileGID: function (pos) { + var tilesPerRow = this.layerSize.width, + tilePos = pos.x + (pos.y * tilesPerRow) + + return this.tiles[tilePos] + }, + tileGIDAt: function (pos) { + return this.tileGID(pos) + }, + + removeTile: function (pos) { + var gid = this.tileGID(pos) + if (gid === 0) { + // Tile is already blank + return + } + + var tiles = this.tiles, + tilesPerRow = this.layerSize.width, + tilePos = pos.x + (pos.y * tilesPerRow) + + + tiles[tilePos] = 0 + + var sprite = this.getChild({tag: tilePos}) + if (sprite) { + this.removeChild({child: sprite}) + } + } +}) + +exports.TMXLayer = TMXLayer + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/nodes/TMXLayer.js + + +__jah__.resources["/libs/cocos2d/nodes/TMXTiledMap.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var util = require('util'), + geo = require('geometry'), + ccp = geo.ccp, + Node = require('./Node').Node, + TMXOrientationOrtho = require('../TMXOrientation').TMXOrientationOrtho, + TMXOrientationHex = require('../TMXOrientation').TMXOrientationHex, + TMXOrientationIso = require('../TMXOrientation').TMXOrientationIso, + TMXLayer = require('./TMXLayer').TMXLayer, + TMXMapInfo = require('../TMXXMLParser').TMXMapInfo + +/** + * @class + * A TMX Map loaded from a .tmx file + * + * @memberOf cocos.nodes + * @extends cocos.nodes.Node + * + * @opt {String} file The file path of the TMX map to load + */ +function TMXTiledMap (opts) { + TMXTiledMap.superclass.constructor.call(this, opts) + + this.anchorPoint = ccp(0, 0) + + var mapInfo + + var initialize = function () { + this.mapSize = mapInfo.mapSize + this.tileSize = mapInfo.tileSize + this.mapOrientation = mapInfo.orientation + this.objectGroups = mapInfo.objectGroups + this.properties = mapInfo.properties + this.tileProperties = mapInfo.tileProperties + + // Add layers to map + var idx = 0 + mapInfo.layers.forEach(function (layerInfo) { + if (layerInfo.visible) { + var child = this.parseLayer({layerInfo: layerInfo, mapInfo: mapInfo}) + this.addChild({child: child, z: idx, tag: idx}) + + var childSize = child.contentSize + var currentSize = this.contentSize + currentSize.width = Math.max(currentSize.width, childSize.width) + currentSize.height = Math.max(currentSize.height, childSize.height) + this.contentSize = currentSize + + idx++ + } + }.bind(this)) + }.bind(this) + + + if (opts.file) { + mapInfo = new TMXMapInfo({file: opts.file}) + initialize() + } else if (opts.url) { + var xhr = new XMLHttpRequest + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + var url = opts.url + + // Create absolute URL + if (/^\/\//.test(url)) { + // URL prefixed with double slash + url = window.location.protocol + url + } else if (/^\//.test(url)) { + // URL with single slash prefix + url = window.location.protocol + "//" + window.location.hostname + url + } else { + url = window.location.href.replace(/\/[^\/]*$/, '/') + url + } + + mapInfo = new TMXMapInfo({filename: url, xml: xhr.responseText}) + initialize() + } + } + xhr.open('GET', opts.url, true) + xhr.send(null) + } else if (opts.xml) { + mapInfo = new TMXMapInfo({xml: opts.xml}) + initialize() + } +} + + +TMXTiledMap.inherit(Node, /** @lends cocos.nodes.TMXTiledMap# */ { + mapSize: null, + tileSize: null, + mapOrientation: 0, + objectGroups: null, + properties: null, + tileProperties: null, + + parseLayer: function (opts) { + var tileset = this.tilesetForLayer(opts) + var layer = new TMXLayer({ tilesetInfo: tileset + , layerInfo: opts.layerInfo + , mapInfo: opts.mapInfo + }) + + layer.setupTiles() + + return layer + }, + + tilesetForLayer: function (opts) { + var layerInfo = opts.layerInfo, + mapInfo = opts.mapInfo, + size = layerInfo.layerSize + + // Reverse loop + var tileset + for (var i = mapInfo.tilesets.length - 1; i >= 0; i--) { + tileset = mapInfo.tilesets[i] + + for (var y = 0; y < size.height; y++) { + for (var x = 0; x < size.width; x++) { + var pos = x + size.width * y, + gid = layerInfo.tiles[pos] + + if (gid !== 0 && gid >= tileset.firstGID) { + return tileset + } + } // for (var x + } // for (var y + } // for (var i + + //console.log("cocos2d: Warning: TMX Layer '%s' has no tiles", layerInfo.name) + return tileset + }, + + /** + * Get a layer + * + * @opt {String} name The name of the layer to get + * @returns {cocos.nodes.TMXLayer} The layer requested + */ + getLayer: function (opts) { + var layerName = opts.name, + layer = null + + this.children.forEach(function (item) { + if (item instanceof TMXLayer && item.layerName == layerName) { + layer = item + } + }) + if (layer !== null) { + return layer + } + }, + + /** + * Return the ObjectGroup for the secific group + * + * @opt {String} name The object group name + * @returns {cocos.TMXObjectGroup} The object group + */ + getObjectGroup: function (opts) { + var objectGroupName = opts.name, + objectGroup = null + + this.objectGroups.forEach(function (item) { + if (item.name == objectGroupName) { + objectGroup = item + } + }) + if (objectGroup !== null) { + return objectGroup + } + }, + + /** + * @deprected Since v0.2. You should now use cocos.TMXTiledMap#getObjectGroup. + */ + objectGroupNamed: function (opts) { + console.warn('TMXTiledMap#objectGroupNamed is deprected. Use TMXTiledMap#getObjectGroup instread') + return this.getObjectGroup(opts) + } +}) + +exports.TMXTiledMap = TMXTiledMap + + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/nodes/TMXTiledMap.js + + +__jah__.resources["/libs/cocos2d/nodes/Transition.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var geo = require('geometry'), + util = require('util'), + actions = require('../actions') + +var Scene = require('./Scene').Scene, + Director = require('../Director').Director, + EventDispatcher = require('../EventDispatcher').EventDispatcher, + Scheduler = require('../Scheduler').Scheduler + +/** @ignore + * Orientation Type used by some transitions + */ +var tOrientation = { + kOrientationLeftOver: 0, + kOrientationRightOver: 1, + kOrientationUpOver: 0, + kOrientationDownOver: 1 +} + +/** + * @class + * Base class for Transition scenes + * + * @memberOf cocos.nodes + * @extends cocos.nodes.Scene + * + * @opt {Float} duration How long the transition should last + * @opt {cocos.nodes.Scene} scene Income scene + */ +function TransitionScene (opts) { + TransitionScene.superclass.constructor.call(this, opts) + + this.duration = opts.duration + if (!opts.scene) { + throw "TransitionScene requires scene property" + } + this.inScene = opts.scene + this.outScene = Director.sharedDirector._runningScene + + if (this.inScene == this.outScene) { + throw "Incoming scene must be different from the outgoing scene" + } + EventDispatcher.sharedDispatcher.dispatchEvents = false + this.sceneOrder() +} + +TransitionScene.inherit(Scene, /** @lends cocos.nodes.TransitionScene# */ { + /** + * Incoming scene + * @type {cocos.nodes.Scene} + */ + inScene: null, + + /** + * Outgoing (current) scene + * @type {cocos.nodes.Scene} + */ + outScene: null, + + /** + * transition duration + * @type Float + */ + duration: null, + + inSceneOnTop: null, + sendCleanupToScene: null, + + /** + * Called after the transition finishes + */ + finish: function () { + var is = this.inScene, + os = this.outScene + + /* clean up */ + is.visible = true + is.position = geo.PointZero() + is.scale = 1.0 + is.rotation = 0 + + os.visible = false + os.position = geo.PointZero() + os.scale = 1.0 + os.rotation = 0 + + Scheduler.sharedScheduler.schedule({ + target: this, + method: this.setNewScene, + interval: 0 + }) + }, + + /** + * Used by some transitions to hide the outer scene + */ + hideOutShowIn: function () { + this.inScene.visible = true + this.outScene.visible = false + }, + + setNewScene: function (dt) { + var dir = Director.sharedDirector + + this.unscheduleSelector(this.setNewScene) + // Save 'send cleanup to scene' + // Not sure if it's cool to be accessing all these Director privates like this... + this.sendCleanupToScene = dir._sendCleanupToScene + + dir.replaceScene(this.inScene) + + // enable events while transitions + EventDispatcher.sharedDispatcher.dispatchEvents = true + + // issue #267 + this.outScene.visible = true + }, + + sceneOrder: function () { + this.inSceneOnTop = true + }, + + draw: function (context, rect) { + if (this.inSceneOnTop) { + this.outScene.visit(context, rect) + this.inScene.visit(context, rect) + } else { + this.inScene.visit(context, rect) + this.outScene.visit(context, rect) + } + }, + + onEnter: function () { + TransitionScene.superclass.onEnter.call(this) + this.inScene.onEnter() + // outScene_ should not receive the onEnter callback + }, + + onExit: function () { + TransitionScene.superclass.onExit.call(this) + this.outScene.onExit() + // inScene_ should not receive the onExit callback + // only the onEnterTransitionDidFinish + if (this.inScene.hasOwnProperty('onEnterTransitionDidFinish')) { + this.inScene.onEnterTransitionDidFinish() + } + }, + + cleanup: function () { + TransitionScene.superclass.cleanup.call(this) + + if (this.sendCleanupToScene) { + this.outScene.cleanup() + } + } +}) + +/** + * @class + * Rotate and zoom out the outgoing scene, and then rotate and zoom in the incoming + * + * @memberOf cocos.nodes + * @extends cocos.nodes.TransitionScene + */ +function TransitionRotoZoom (opts) { + TransitionRotoZoom.superclass.constructor.call(this, opts) +} + +TransitionRotoZoom.inherit(TransitionScene, /** @lends cocos.nodes.TransitionRotoZoom# */ { + onEnter: function() { + TransitionRotoZoom.superclass.onEnter.call(this) + + var dur = this.duration + this.inScene.scale = 0.001 + this.outScene.scale = 1.0 + + this.inScene.anchorPoint = geo.ccp(0.5, 0.5) + this.outScene.anchorPoint = geo.ccp(0.5, 0.5) + + var outzoom = [ + new actions.Spawn({actions: [ + new actions.ScaleBy({scale: 0.001, duration: dur/2}), + new actions.RotateBy({angle: 360*2, duration: dur/2}) + ]}), + new actions.DelayTime({duration: dur/2})] + + // Can't nest sequences or reverse them very easily, so incoming scene actions must be put + // together manually for now... + var inzoom = [ + new actions.DelayTime({duration: dur/2}), + + new actions.Spawn({actions: [ + new actions.ScaleTo({scale: 1.0, duration: dur/2}), + new actions.RotateBy({angle: -360*2, duration: dur/2}) + ]}), + new actions.CallFunc({ + target: this, + method: this.finish + }) + ] + + // Sequence init() copies actions + this.outScene.runAction(new actions.Sequence({actions: outzoom})) + this.inScene.runAction(new actions.Sequence({actions: inzoom})) + } +}) + +/** + * @class + * Move in from to the left the incoming scene. + * + * @memberOf cocos.nodes + * @extends cocos.nodes.TransitionScene + */ +function TransitionMoveInL (opts) { + TransitionMoveInL.superclass.constructor.call(this, opts) +} + +TransitionMoveInL.inherit(TransitionScene, /** @lends cocos.nodes.TransitionMoveInL# */ { + onEnter: function () { + TransitionMoveInL.superclass.onEnter.call(this) + + this.initScenes() + + this.inScene.runAction(new actions.Sequence({actions: [ + this.action(), + new actions.CallFunc({ + target: this, + method: this.finish + })] + })) + }, + + action: function () { + return new actions.MoveTo({ + position: geo.ccp(0, 0), + duration: this.duration + }) + }, + + initScenes: function () { + var s = Director.sharedDirector.winSize + this.inScene.position = geo.ccp(-s.width, 0) + } +}) + +/** + * @class + * Move in from to the right the incoming scene. + * + * @memberOf cocos.nodes + * @extends cocos.nodes.TransitionMoveInL + */ +function TransitionMoveInR (opts) { + TransitionMoveInR.superclass.constructor.call(this, opts) +} + +TransitionMoveInR.inherit(TransitionMoveInL, /** @lends cocos.nodes.TransitionMoveInR# */ { + initScenes: function () { + var s = Director.sharedDirector.winSize + this.inScene.position = geo.ccp(s.width, 0) + } +}) + +/** + * @class + * Move the incoming scene in from the top. + * + * @memberOf cocos.nodes + * @extends cocos.nodes.TransitionMoveInL + */ +function TransitionMoveInT (opts) { + TransitionMoveInT.superclass.constructor.call(this, opts) +} + +TransitionMoveInT.inherit(TransitionMoveInL, /** @lends cocos.nodes.TransitionMoveInT# */ { + initScenes: function () { + var s = Director.sharedDirector.winSize + this.inScene.position = geo.ccp(0, s.height) + } +}) + +/** + * @class + * Move the incoming scene in from the bottom. + * + * @memberOf cocos.nodes + * @extends cocos.nodes.TransitionMoveInL + */ +function TransitionMoveInB (opts) { + TransitionMoveInB.superclass.constructor.call(this, opts) +} + +TransitionMoveInB.inherit(TransitionMoveInL, /** @lends cocos.nodes.TransitionMoveInB# */ { + initScenes: function () { + var s = Director.sharedDirector.winSize + this.inScene.position = geo.ccp(0, -s.height) + } +}) + +/** + * @class + * Slide in the incoming scene from the left. + * + * @memberOf cocos.nodes + * @extends cocos.nodes.TransitionScene + */ +function TransitionSlideInL (opts) { + TransitionSlideInL.superclass.constructor.call(this, opts) +} + +TransitionSlideInL.inherit(TransitionScene, /** @lends cocos.nodes.TransitionSlideInL# */ { + onEnter: function () { + TransitionSlideInL.superclass.onEnter.call(this) + + this.initScenes() + + var movein = this.action() + var moveout = this.action() + var outAction = new actions.Sequence({ + actions: [ + moveout, + new actions.CallFunc({ + target: this, + method: this.finish + })] + }) + this.inScene.runAction(movein) + this.outScene.runAction(outAction) + }, + + sceneOrder: function () { + this.inSceneOnTop = false + }, + + initScenes: function () { + var s = Director.sharedDirector.winSize + this.inScene.position = geo.ccp(-s.width, 0) + }, + + action: function () { + var s = Director.sharedDirector.winSize + return new actions.MoveBy({ + position: geo.ccp(s.width, 0), + duration: this.duration + }) + } +}) + +/** + * @class + * Slide in the incoming scene from the right. + * + * @memberOf cocos.nodes + * @extends cocos.nodes.TransitionSlideInL + */ +function TransitionSlideInR (opts) { + TransitionSlideInR.superclass.constructor.call(this, opts) +} + +TransitionSlideInR.inherit(TransitionSlideInL, /** @lends cocos.nodes.TransitionSlideInR# */ { + sceneOrder: function () { + this.inSceneOnTop = true + }, + + initScenes: function () { + var s = Director.sharedDirector.winSize + this.inScene.position = geo.ccp(s.width, 0) + }, + + action: function () { + var s = Director.sharedDirector.winSize + return new actions.MoveBy({ + position: geo.ccp(-s.width, 0), + duration: this.duration + }) + } +}) + +/** + * @class + * Slide in the incoming scene from the top. + * + * @memberOf cocos.nodes + * @extends cocos.nodes.TransitionSlideInL + */ +function TransitionSlideInT (opts) { + TransitionSlideInT.superclass.constructor.call(this, opts) +} + +TransitionSlideInT.inherit(TransitionSlideInL, /** @lends cocos.nodes.TransitionSlideInT# */ { + sceneOrder: function () { + this.inSceneOnTop = false + }, + + initScenes: function () { + var s = Director.sharedDirector.winSize + this.inScene.position = geo.ccp(0, s.height) + }, + + action: function () { + var s = Director.sharedDirector.winSize + return new actions.MoveBy({ + position: geo.ccp(0, -s.height), + duration: this.duration + }) + } +}) + +/** + * @class + * Slide in the incoming scene from the bottom. + * + * @memberOf cocos.nodes + * @extends cocos.nodes.TransitionSlideInL + */ +function TransitionSlideInB (opts) { + TransitionSlideInB.superclass.constructor.call(this, opts) +} + +TransitionSlideInB.inherit(TransitionSlideInL, /** @lends cocos.nodes.TransitionSlideInB# */ { + sceneOrder: function () { + this.inSceneOnTop = true + }, + + initScenes: function () { + var s = Director.sharedDirector.winSize + this.inScene.position = geo.ccp(0, -s.height) + }, + + action: function () { + var s = Director.sharedDirector.winSize + return new actions.MoveBy({ + position: geo.ccp(0, s.height), + duration: this.duration + }) + } +}) + +exports.TransitionScene = TransitionScene +exports.TransitionRotoZoom = TransitionRotoZoom +exports.TransitionMoveInL = TransitionMoveInL +exports.TransitionMoveInR = TransitionMoveInR +exports.TransitionMoveInT = TransitionMoveInT +exports.TransitionMoveInB = TransitionMoveInB +exports.TransitionSlideInL = TransitionSlideInL +exports.TransitionSlideInR = TransitionSlideInR +exports.TransitionSlideInT = TransitionSlideInT +exports.TransitionSlideInB = TransitionSlideInB + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/nodes/Transition.js + + +__jah__.resources["/libs/cocos2d/remote_resources_patch.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +var remote_resources = require('remote_resources') + , RemoteFont = require('./RemoteFont').RemoteFont + +var originalGetRemoteResourceConstructor = remote_resources.getRemoteResourceConstructor + +remote_resources.getRemoteResourceConstructor = function (mimetype) { + var RemoteObj + if (/\bfont\b/.test(mimetype)) { + RemoteObj = RemoteFont + } else { + RemoteObj = originalGetRemoteResourceConstructor(mimetype) + } + + return RemoteObj +} + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/remote_resources_patch.js + + +__jah__.resources["/libs/cocos2d/RemoteFont.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +var events = require('events') + , remote_resources = require('remote_resources') + +var fontTestElement + , ctx +/** + * Very crude way to test for when a font has loaded + * + * While a font is loading they will be drawn as blank onto a canvas. + * This function creates a small canvas and tests the pixels to see if the + * given font draws. If it does then we can assume the font loaded. + */ +function hasFontLoaded (window, fontName) { + var testSize = 16 + if (!fontTestElement) { + fontTestElement = window.document.createElement('canvas') + fontTestElement.width = testSize + fontTestElement.height = testSize + fontTestElement.style.display = 'none' + + ctx = fontTestElement.getContext('2d') + window.document.body.appendChild(fontTestElement) + } + + fontTestElement.width = testSize + ctx.fillStyle = 'rgba(0, 0, 0, 0)' + ctx.fillRect(0, 0, testSize, testSize) + ctx.font = testSize + "px __cc2d_" + fontName + ctx.fillStyle = 'rgba(255, 255, 255, 1)' + ctx.fillText("M", 0, testSize); + + var pixels = ctx.getImageData(0, 0, testSize, testSize).data + + for (var i = 0; i < testSize * testSize; i++) { + if (pixels[i * 4] != 0) { + fontTestElement.parentNode.removeChild(fontTestElement) + fontTestElement = null + return true + } + } + + return false +} + +/** + * @class + * @memberOf cocos + * @extends remote_resources.RemoteResource + */ +function RemoteFont(url, path) { + remote_resources.RemoteResource.apply(this, arguments) +} + +RemoteFont.prototype = Object.create(remote_resources.RemoteResource.prototype) + +RemoteFont.prototype.load = function () { + var window = require('./Director').Director.sharedDirector.window + + var fontName = this.path.split('/').pop().split('.')[0] + var fontFace = "@font-face { \ + font-family: '__cc2d_" + fontName + "'; \ + src: url(" + this.url + "); \ + }" + + var t = document.createElement('style') + t.appendChild(document.createTextNode(fontFace)) + window.document.body.appendChild(t) + + var ticker = setInterval(function () { + if (hasFontLoaded(window, fontName)) { + __jah__.resources[this.path].loaded = true + events.trigger(this, 'load', this) + clearInterval(ticker) + } + }.bind(this), 100) +} + +exports.RemoteFont = RemoteFont + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/RemoteFont.js + + +__jah__.resources["/libs/cocos2d/resources/progress-bar-empty.png"] = {data: __jah__.assetURL + "/libs/cocos2d/resources/progress-bar-empty.png", mimetype: "image/png", remote: true}; +__jah__.resources["/libs/cocos2d/resources/progress-bar-full.png"] = {data: __jah__.assetURL + "/libs/cocos2d/resources/progress-bar-full.png", mimetype: "image/png", remote: true}; +__jah__.resources["/libs/cocos2d/Scheduler.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var util = require('util') + +/** @ignore */ +function HashUpdateEntry() { + this.timers = [] + this.timerIndex = 0 + this.currentTimer = null + this.currentTimerSalvaged = false + this.paused = false +} + +/** @ignore */ +function HashMethodEntry() { + this.timers = [] + this.timerIndex = 0 + this.currentTimer = null + this.currentTimerSalvaged = false + this.paused = false +} + +/** + * @class + * Runs a function repeatedly at a fixed interval + * + * @memberOf cocos + * + * @opt {Function} callback The function to run at each interval + * @opt {Float} interval Number of milliseconds to wait between each exectuion of callback + */ +function Timer (opts) { + this.callback = opts.callback + this.interval = opts.interval || 0 + this.elapsed = -1 +} + +Timer.inherit(Object, /** @lends cocos.Timer# */ { + callback: null, + interval: 0, + elapsed: -1, + + /** + * @private + */ + update: function (dt) { + if (this.elapsed == -1) { + this.elapsed = 0 + } else { + this.elapsed += dt + } + + if (this.elapsed >= this.interval) { + this.callback(this.elapsed) + this.elapsed = 0 + } + } +}) + +/** + * @class + * Runs the timers + * + * @memberOf cocos + * + * @singleton + */ +function Scheduler () { + this.updates0 = [] + this.updatesNeg = [] + this.updatesPos = [] + this.hashForUpdates = {} + this.hashForMethods = {} +} +Scheduler.inherit(Object, /** @lends cocos.Scheduler# */ { + updates0: null, + updatesNeg: null, + updatesPos: null, + hashForUpdates: null, + hashForMethods: null, + timeScale: 1.0, + + /** + * The scheduled method will be called every 'interval' seconds. + * If paused is YES, then it won't be called until it is resumed. + * If 'interval' is 0, it will be called every frame, but if so, it recommened to use 'scheduleUpdateForTarget:' instead. + * If the selector is already scheduled, then only the interval parameter will be updated without re-scheduling it again. + */ + schedule: function (opts) { + var target = opts.target, + method = (typeof opts.method == 'function') ? opts.method : target[opts.method], + interval = opts.interval, + paused = opts.paused || false + + var element = this.hashForMethods[target.id] + + if (!element) { + element = new HashMethodEntry() + this.hashForMethods[target.id] = element + element.target = target + element.paused = paused + } else if (element.paused != paused) { + throw "cocos.Scheduler. Trying to schedule a method with a pause value different than the target" + } + + var timer = new Timer({callback: method.bind(target), interval: interval}) + element.timers.push(timer) + }, + + /** + * Schedules the 'update' selector for a given target with a given priority. + * The 'update' selector will be called every frame. + * The lower the priority, the earlier it is called. + */ + scheduleUpdate: function (opts) { + var target = opts.target, + priority = opts.priority, + paused = opts.paused + + var i, len + var entry = {target: target, priority: priority, paused: paused} + var added = false + + if (priority === 0) { + this.updates0.push(entry) + } else if (priority < 0) { + for (i = 0, len = this.updatesNeg.length; i < len; i++) { + if (priority < this.updatesNeg[i].priority) { + this.updatesNeg.splice(i, 0, entry) + added = true + break + } + } + + if (!added) { + this.updatesNeg.push(entry) + } + } else /* priority > 0 */{ + for (i = 0, len = this.updatesPos.length; i < len; i++) { + if (priority < this.updatesPos[i].priority) { + this.updatesPos.splice(i, 0, entry) + added = true + break + } + } + + if (!added) { + this.updatesPos.push(entry) + } + } + + this.hashForUpdates[target.id] = entry + }, + + /** + * 'tick' the scheduler. + * You should NEVER call this method, unless you know what you are doing. + */ + tick: function (dt) { + var i, len, x + if (this.timeScale != 1.0) { + dt *= this.timeScale + } + + var entry + for (i = 0, len = this.updatesNeg.length; i < len; i++) { + entry = this.updatesNeg[i] + if (entry && !entry.paused) { + entry.target.update(dt) + } + } + + + for (i = 0, len = this.updates0.length; i < len; i++) { + entry = this.updates0[i] + if (entry && !entry.paused) { + entry.target.update(dt) + } + } + + for (i = 0, len = this.updatesPos.length; i < len; i++) { + entry = this.updatesPos[i] + if (entry && !entry.paused) { + entry.target.update(dt) + } + } + + for (x in this.hashForMethods) { + if (this.hashForMethods.hasOwnProperty(x)) { + entry = this.hashForMethods[x] + + if (entry) { + for (i = 0, len = entry.timers.length; i < len; i++) { + var timer = entry.timers[i] + if (timer) { + timer.update(dt) + } + } + } + } + } + + }, + + /** + * Unshedules a selector for a given target. + * If you want to unschedule the "update", use unscheduleUpdateForTarget. + */ + unschedule: function (opts) { + if (!opts.target || !opts.method) { + return + } + + var target = opts.target, + method = (typeof opts.method == 'function') ? opts.method : target[opts.method] + + var element = this.hashForMethods[opts.target.id] + if (element) { + for (var i=0; i 0 */{ + this.updatesPos.splice(this.updatesPos.indexOf(elementUpdate), 1) + } + } + // Release HashMethodEntry object + this.hashForUpdates[id] = null + }, + + /** + * Unschedules all selectors from all targets. + * You should NEVER call this method, unless you know what you are doing. + */ + unscheduleAllSelectors: function () { + var i, x, entry + + // Custom selectors + for (x in this.hashForMethods) { + if (this.hashForMethods.hasOwnProperty(x)) { + entry = this.hashForMethods[x] + this.unscheduleAllSelectorsForTarget(entry.target) + } + } + // Updates selectors + for (i = 0, len = this.updatesNeg.length; i < len; i++) { + entry = this.updatesNeg[i] + if (entry) { + this.unscheduleUpdateForTarget(entry.target) + } + } + + for (i = 0, len = this.updates0.length; i < len; i++) { + entry = this.updates0[i] + if (entry) { + this.unscheduleUpdateForTarget(entry.target) + } + } + + for (i = 0, len = this.updatesPos.length; i < len; i++) { + entry = this.updatesPos[i] + if (entry) { + this.unscheduleUpdateForTarget(entry.target) + } + } + }, + + /** + * Unschedules all selectors for a given target. + * This also includes the "update" selector. + */ + unscheduleAllSelectorsForTarget: function (target) { + if (!target) { + return + } + // Custom selector + var element = this.hashForMethods[target.id] + if (element) { + element.paused = true + element.timers = []; // Clear all timers + } + // Release HashMethodEntry object + this.hashForMethods[target.id] = null + + // Update selector + this.unscheduleUpdateForTarget(target) + }, + + /** + * Pauses the target. + * All scheduled selectors/update for a given target won't be 'ticked' until the target is resumed. + * If the target is not present, nothing happens. + */ + + pauseTarget: function (target) { + var element = this.hashForMethods[target.id] + if (element) { + element.paused = true + } + + var elementUpdate = this.hashForUpdates[target.id] + if (elementUpdate) { + elementUpdate.paused = true + } + }, + + /** + * Resumes the target. + * The 'target' will be unpaused, so all schedule selectors/update will be 'ticked' again. + * If the target is not present, nothing happens. + */ + resumeTarget: function (target) { + var element = this.hashForMethods[target.id] + if (element) { + element.paused = false + } + + var elementUpdate = this.hashForUpdates[target.id] + //console.log('foo', target.id, elementUpdate) + if (elementUpdate) { + elementUpdate.paused = false + } + } +}) + +Object.defineProperty(Scheduler, 'sharedScheduler', { + /** + * A shared singleton instance of cocos.Scheduler + * + * @memberOf cocos.Scheduler + * @getter {cocos.Scheduler} sharedScheduler + */ + get: function () { + if (!Scheduler._instance) { + Scheduler._instance = new this() + } + + return Scheduler._instance + } + + , enumerable: true +}) + +exports.Timer = Timer +exports.Scheduler = Scheduler + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/Scheduler.js + + +__jah__.resources["/libs/cocos2d/SpriteFrame.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var util = require('util'), + geo = require('geometry'), + ccp = geo.ccp + +/** + * @class + * Represents a single frame of animation for a cocos.Sprite + * + * A SpriteFrame has: + * - texture: A Texture2D that will be used by the Sprite + * - rectangle: A rectangle of the texture + * + * @example + * var frame = new SpriteFrame({texture: texture, rect: rect}) + * sprite.displayFrame = frame + * + * @memberOf cocos + * + * @opt {cocos.Texture2D} texture The texture to draw this frame using + * @opt {geometry.Rect} rect The rectangle inside the texture to draw + */ +function SpriteFrame (opts) { + SpriteFrame.superclass.constructor.call(this, opts) + + this.texture = opts.texture + this.rect = opts.rect + this.rotated = !!opts.rotate + this.offset = opts.offset || ccp(0, 0) + this.originalSize = opts.originalSize || util.copy(this.rect.size) +} + +SpriteFrame.inherit(Object, /** @lends cocos.SpriteFrame# */ { + rect: null, + rotated: false, + offset: null, + originalSize: null, + texture: null, + + /** + * @ignore + */ + toString: function () { + return "[object SpriteFrame | TextureName=" + this.texture.name + ", Rect = (" + this.rect.origin.x + ", " + this.rect.origin.y + ", " + this.rect.size.width + ", " + this.rect.size.height + ")]" + }, + + /** + * Make a copy of this frame + * + * @returns {cocos.SpriteFrame} Exact copy of this object + */ + copy: function () { + return new SpriteFrame({rect: this.rect, rotated: this.rotated, offset: this.offset, originalSize: this.originalSize, texture: this.texture}) + } + +}) + +exports.SpriteFrame = SpriteFrame + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/SpriteFrame.js + + +__jah__.resources["/libs/cocos2d/SpriteFrameCache.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var util = require('util'), + geo = require('geometry'), + Plist = require('Plist').Plist, + SpriteFrame = require('./SpriteFrame').SpriteFrame, + Texture2D = require('./Texture2D').Texture2D + +/** + * @class + * + * @memberOf cocos + * @singleton + */ +function SpriteFrameCache () { + SpriteFrameCache.superclass.constructor.call(this) + + this.spriteFrames = {} + this.spriteFrameAliases = {} +} + +SpriteFrameCache.inherit(Object, /** @lends cocos.SpriteFrameCache# */ { + /** + * List of sprite frames + * @type Object + */ + spriteFrames: null, + + /** + * List of sprite frame aliases + * @type Object + */ + spriteFrameAliases: null, + + /** + * Add SpriteFrame(s) to the cache + * + * @param {String} opts.file The filename of a Zwoptex .plist containing the frame definiitons. + */ + addSpriteFrames: function (opts) { + var plistPath = opts.file, + plist = new Plist({file: plistPath}), + plistData = plist.data + + + var metaDataDict = plistData.metadata, + framesDict = plistData.frames + + var format = 0, + texturePath = null + + if (metaDataDict) { + format = metaDataDict.format + // Get texture path from meta data + texturePath = metaDataDict.textureFileName + } + + if (!texturePath) { + // No texture path so assuming it's the same name as the .plist but ending in .png + texturePath = plistPath.replace(/\.plist$/i, '.png') + } + + + var texture = new Texture2D({file: texturePath}) + + // Add frames + for (var frameDictKey in framesDict) { + if (framesDict.hasOwnProperty(frameDictKey)) { + var frameDict = framesDict[frameDictKey], + spriteFrame = null + + switch (format) { + case 0: + var x = frameDict.x, + y = frameDict.y, + w = frameDict.width, + h = frameDict.height, + ox = frameDict.offsetX, + oy = frameDict.offsetY, + ow = frameDict.originalWidth, + oh = frameDict.originalHeight + + // check ow/oh + if (!ow || !oh) { + //console.log("cocos2d: WARNING: originalWidth/Height not found on the CCSpriteFrame. AnchorPoint won't work as expected. Regenerate the .plist") + } + + if (cc.FLIP_Y_AXIS) { + oy *= -1 + } + + // abs ow/oh + ow = Math.abs(ow) + oh = Math.abs(oh) + + // create frame + spriteFrame = new SpriteFrame({texture: texture, + rect: geo.rectMake(x, y, w, h), + rotate: false, + offset: geo.ccp(ox, oy), + originalSize: geo.sizeMake(ow, oh)}) + break + + case 1: + case 2: + var frame = geo.rectFromString(frameDict.frame), + rotated = !!frameDict.rotated, + offset = geo.pointFromString(frameDict.offset), + sourceSize = geo.sizeFromString(frameDict.sourceSize) + + if (cc.FLIP_Y_AXIS) { + offset.y *= -1 + } + + + // create frame + spriteFrame = new SpriteFrame({texture: texture, + rect: frame, + rotate: rotated, + offset: offset, + originalSize: sourceSize}) + break + + case 3: + var spriteSize = geo.sizeFromString(frameDict.spriteSize), + spriteOffset = geo.pointFromString(frameDict.spriteOffset), + spriteSourceSize = geo.sizeFromString(frameDict.spriteSourceSize), + textureRect = geo.rectFromString(frameDict.textureRect), + textureRotated = frameDict.textureRotated + + + if (cc.FLIP_Y_AXIS) { + spriteOffset.y *= -1 + } + + // get aliases + var aliases = frameDict.aliases + for (var i = 0, len = aliases.length; i < len; i++) { + var alias = aliases[i] + this.spriteFrameAliases[frameDictKey] = alias + } + + // create frame + spriteFrame = new SpriteFrame({texture: texture, + rect: geo.rectMake(textureRect.origin.x, textureRect.origin.y, spriteSize.width, spriteSize.height), + rotate: textureRotated, + offset: spriteOffset, + originalSize: spriteSourceSize}) + break + + default: + throw "Unsupported Zwoptex format: " + format + } + + // Add sprite frame + this.spriteFrames[frameDictKey] = spriteFrame + } + } + }, + + /** + * Get a single SpriteFrame + * + * @param {String} opts.name The name of the sprite frame + * @returns {cocos.SpriteFrame} The sprite frame + */ + getSpriteFrame: function (opts) { + var name = opts.name || opts + + var frame = this.spriteFrames[name] + + if (!frame) { + // No frame, look for an alias + var key = this.spriteFrameAliases[name] + + if (key) { + frame = this.spriteFrames[key] + } + + if (!frame) { + throw "Unable to find frame: " + name + } + } + + return frame + } +}) + +Object.defineProperty(SpriteFrameCache, 'sharedSpriteFrameCache', { + /** + * A shared singleton instance of cocos.SpriteFrameCache + * + * @memberOf cocos.SpriteFrameCache + * @getter {cocos.SpriteFrameCache} sharedSpriteFrameCache + */ + get: function () { + if (!SpriteFrameCache._instance) { + SpriteFrameCache._instance = new this() + } + + return SpriteFrameCache._instance + } + + , enumerable: true +}) + +exports.SpriteFrameCache = SpriteFrameCache + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/SpriteFrameCache.js + + +__jah__.resources["/libs/cocos2d/Texture2D.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var util = require('util'), + events = require('events'), + RemoteResource = require('remote_resources').RemoteResource + +/** + * @class + * + * @memberOf cocos + * + * @opt {String} [file] The file path of the image to use as a texture + * @opt {Texture2D|HTMLImageElement} [data] Image data to read from + */ +function Texture2D (opts) { + var file = opts.file + , url = opts.url + , data = opts.data + , texture = opts.texture + + if (url) { + this.name = url + data = new Image() + data.src = url + } else if (file) { + this.name = file + data = resource(file) + } else if (texture) { + this.name = texture.name + data = texture.imgElement + } + + this.size = {width: 0, height: 0} + + if (data instanceof RemoteResource) { + events.addListenerOnce(data, 'load', this.dataDidLoad.bind(this, data)) + this.imgElement = data.load() + } else if (url) { + this.imgElement = data + this.imgElement.onload = this.dataDidLoad.bind(this, data) + } else { + this.imgElement = data + this.dataDidLoad(data) + } +} + +Texture2D.inherit(Object, /** @lends cocos.Texture2D# */ { + imgElement: null, + size: null, + name: null, + isLoaded: false, + + dataDidLoad: function (data) { + this.isLoaded = true + this.size = {width: this.imgElement.width, height: this.imgElement.height} + events.trigger(this, 'load', this) + }, + + drawAtPoint: function (ctx, point) { + if (!this.isLoaded) { + return + } + ctx.drawImage(this.imgElement, point.x, point.y) + }, + drawInRect: function (ctx, rect) { + if (!this.isLoaded) { + return + } + ctx.drawImage(this.imgElement, + rect.origin.x, rect.origin.y, + rect.size.width, rect.size.height + ) + }, + + /** + * @getter data + * @type {String} Base64 encoded image data + */ + get data () { + return this.imgElement ? this.imgElement.src : null + }, + + /** + * @getter contentSize + * @type {geometry.Size} Size of the texture + */ + get contentSize () { + return this.size + }, + + get pixelsWide () { + return this.size.width + }, + + get pixelsHigh () { + return this.size.height + } +}) + +exports.Texture2D = Texture2D + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/Texture2D.js + + +__jah__.resources["/libs/cocos2d/TextureAtlas.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var util = require('util'), + events = require('events'), + Texture2D = require('./Texture2D').Texture2D + + +/* QUAD STRUCTURE + quad = { + drawRect: , // Where the quad is drawn to + textureRect: // The slice of the texture to draw in drawRect + } +*/ + +/** + * @class + * A single texture that can represent lots of smaller images + * + * @memberOf cocos + * + * @opt {String} [url] Remote URL of the image to use as a texture + * @opt {String} [file] Local file path of the image to use as a texture + * @opt {Texture2D|HTMLImageElement} [data] Image data to read from + * @opt {CanvasElement} [canvas] A canvas to use as a texture + */ +function TextureAtlas (opts) { + var file = opts.file + , url = opts.url + , data = opts.data + , texture = opts.texture + , canvas = opts.canvas + + if (canvas) { + // If we've been given a canvas element then we'll use that for our image + this.imgElement = canvas + } else { + texture = new Texture2D({ url: url, texture: texture, file: file, data: data }) + events.addListenerOnce(texture, 'load', function () { + events.trigger(this, 'load') + }.bind(this)) + this.texture = texture + this.imgElement = texture.imgElement + } + + this.quads = [] +} + +TextureAtlas.inherit(Object, /** @lends cocos.TextureAtlas# */ { + quads: null, + imgElement: null, + texture: null, + + insertQuad: function (opts) { + var quad = opts.quad, + index = opts.index || 0 + + this.quads.splice(index, 0, quad) + }, + removeQuad: function (opts) { + var index = opts.index + + this.quads.splice(index, 1) + }, + + + drawQuads: function (ctx) { + this.quads.forEach(function (quad) { + if (!quad) return + this.drawQuad(ctx, quad) + }.bind(this)) + }, + + drawQuad: function (ctx, quad) { + var sx = quad.textureRect.origin.x, + sy = quad.textureRect.origin.y, + sw = quad.textureRect.size.width, + sh = quad.textureRect.size.height + + var dx = quad.drawRect.origin.x, + dy = quad.drawRect.origin.y, + dw = quad.drawRect.size.width, + dh = quad.drawRect.size.height + + + var scaleX = 1 + var scaleY = 1 + + if (cc.FLIP_Y_AXIS) { + dy -= dh + dh *= -1 + } + + + if (dw < 0) { + dw *= -1 + scaleX = -1 + } + + if (dh < 0) { + dh *= -1 + scaleY = -1 + } + + ctx.scale(scaleX, scaleY) + + + var img = this.imgElement + ctx.drawImage(img, + sx, sy, // Draw slice from x,y + sw, sh, // Draw slice size + dx, dy, // Draw at 0, 0 + dw, dh // Draw size + ) + + if (cc.FLIP_Y_AXIS) { + ctx.scale(1, -1) + } else { + ctx.scale(1, 1) + } + } +}) + +exports.TextureAtlas = TextureAtlas + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/TextureAtlas.js + + +__jah__.resources["/libs/cocos2d/TMXOrientation.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +/** + * @memberOf cocos + * @namespace + */ +var TMXOrientation = /** @lends cocos.TMXOrientation */ { + /** + * Orthogonal orientation + * @constant + */ + TMXOrientationOrtho: 1, + + /** + * Hexagonal orientation + * @constant + */ + TMXOrientationHex: 2, + + /** + * Isometric orientation + * @constant + */ + TMXOrientationIso: 3 +} + +module.exports = TMXOrientation + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/TMXOrientation.js + + +__jah__.resources["/libs/cocos2d/TMXXMLParser.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var util = require('util') + , uri = require('uri') + , path = require('path') + , ccp = require('geometry').ccp + , base64 = require('base64') + , gzip = require('gzip') + , TMXOrientationOrtho = require('./TMXOrientation').TMXOrientationOrtho + , TMXOrientationHex = require('./TMXOrientation').TMXOrientationHex + , TMXOrientationIso = require('./TMXOrientation').TMXOrientationIso + +/** + * @class + * + * @memberOf cocos + */ +function TMXTilesetInfo () { +} + +TMXTilesetInfo.inherit(Object, /** @lends cocos.TMXTilesetInfo# */ { + name: '', + firstGID: 0, + tileSize: null, + spacing: 0, + margin: 0, + sourceImage: null, + + rectForGID: function (gid) { + var rect = {size: {}, origin: ccp(0, 0)} + rect.size = util.copy(this.tileSize) + + gid = gid - this.firstGID + + var imgSize = this.imageSize + + var maxX = Math.floor((imgSize.width - this.margin * 2 + this.spacing) / (this.tileSize.width + this.spacing)) + + rect.origin.x = (gid % maxX) * (this.tileSize.width + this.spacing) + this.margin + rect.origin.y = Math.floor(gid / maxX) * (this.tileSize.height + this.spacing) + this.margin + + return rect + } +}) + +/** + * @class + * + * @memberOf cocos + */ +function TMXLayerInfo () { + this.properties = {} + this.offset = ccp(0, 0) +} + +TMXLayerInfo.inherit(Object, /** @lends cocos.TMXLayerInfo# */ { + name: '', + layerSize: null, + tiles: null, + visible: true, + opacity: 255, + minGID: 100000, + maxGID: 0, + properties: null, + offset: null +}) + +/** + * @class + * + * @memberOf cocos + */ +function TMXObjectGroup () { + this.properties = {} + this.objects = {} + this.offset = ccp(0, 0) +} + +TMXObjectGroup.inherit(Object, /** @lends cocos.TMXObjectGroup# */ { + name: '', + properties: null, + offset: null, + objects: null, + + /** + * Get the value for the specific property name + * + * @opt {String} name Property name + * @returns {String} Property value + */ + getProperty: function (opts) { + var propertyName = opts.name + return this.properties[propertyName] + }, + + /** + * @deprected Since v0.2. You should now use cocos.TMXObjectGroup#getProperty + */ + propertyNamed: function (opts) { + console.warn('TMXObjectGroup#propertyNamed is deprected. Use TMXTiledMap#getProperty instread') + return this.getProperty(opts) + }, + + /** + * Get the object for the specific object name. It will return the 1st + * object found on the array for the given name. + * + * @opt {String} name Object name + * @returns {Object} Object + */ + getObject: function (opts) { + var objectName = opts.name + var object = null + + this.objects.forEach(function (item) { + if (item.name == objectName) { + object = item + } + }) + if (object !== null) { + return object + } + }, + + /** + * @deprected Since v0.2. You should now use cocos.TMXObjectGroup#getProperty + */ + objectNamed: function (opts) { + console.warn('TMXObjectGroup#objectNamed is deprected. Use TMXObjectGroup#getObject instread') + return this.getObject(opts) + } +}) + +/** + * @class + * + * @memberOf cocos + * + * @param {String} tmxFile The file path of the TMX file to load + */ +function TMXMapInfo (opts) { + this.tilesets = [] + this.layers = [] + this.objectGroups = [] + this.properties = {} + this.tileProperties = {} + this.filename = opts.filename || opts.file || '' + + this.parseXMLFile(opts) +} + +TMXMapInfo.inherit(Object, /** @lends cocos.TMXMapInfo# */ { + filename: '', + orientation: 0, + mapSize: null, + tileSize: null, + layer: null, + tilesets: null, + objectGroups: null, + properties: null, + tileProperties: null, + + parseXMLFile: function (opts) { + var parser = new DOMParser() + , doc + + if (opts.file) + doc = parser.parseFromString(resource(opts.file), 'text/xml') + else if (opts.xml) + doc = parser.parseFromString(opts.xml, 'text/xml') + + // PARSE + var map = doc.documentElement + + // Set Orientation + switch (map.getAttribute('orientation')) { + case 'orthogonal': + this.orientation = TMXOrientationOrtho + break + case 'isometric': + this.orientation = TMXOrientationIso + break + case 'hexagonal': + this.orientation = TMXOrientationHex + break + default: + throw "cocos2d: TMXFomat: Unsupported orientation: " + map.getAttribute('orientation') + } + this.mapSize = {width: parseInt(map.getAttribute('width'), 10), height: parseInt(map.getAttribute('height'), 10)} + this.tileSize = {width: parseInt(map.getAttribute('tilewidth'), 10), height: parseInt(map.getAttribute('tileheight'), 10)} + + + // PARSE + var tilesets = map.getElementsByTagName('tileset') + var i, j, len, jen, s + for (i = 0, len = tilesets.length; i < len; i++) { + var t = tilesets[i] + , externalTilesetName = t.getAttribute('source') + + var tileset = new TMXTilesetInfo() + tileset.firstGID = parseInt(t.getAttribute('firstgid'), 10) + + // Tileset is in external file, load in XML from there -- Must + // happen AFTER 'firstGID' is obtained because firstGID is stored + // in the main .tmx file, not the .tsx + if (externalTilesetName) { + // FIXME needs to support opts.url too + var externalTilesetPath = path.join(path.dirname(opts.file), externalTilesetName) + t = parser.parseFromString(resource(externalTilesetPath), 'text/xml').documentElement + } + + tileset.name = t.getAttribute('name') + if (t.getAttribute('spacing')) { + tileset.spacing = parseInt(t.getAttribute('spacing'), 10) + } + if (t.getAttribute('margin')) { + tileset.margin = parseInt(t.getAttribute('margin'), 10) + } + + s = {} + s.width = parseInt(t.getAttribute('tilewidth'), 10) + s.height = parseInt(t.getAttribute('tileheight'), 10) + tileset.tileSize = s + + // PARSE We assume there's only 1 + var image = t.getElementsByTagName('image')[0] + if (externalTilesetName) { + tileset.sourceImage = path.join(path.dirname(externalTilesetPath), image.getAttribute('source')) + } else { + // Check of URL or file path + if (uri.isURL(this.filename)) { + var base = path.dirname(this.filename) + tileset.sourceImage = path.dirname(this.filename) + '/' + image.getAttribute('source') + } else { + tileset.sourceImage = path.join(path.dirname(this.filename), image.getAttribute('source')) + } + } + + this.tilesets.push(tileset) + } + + // PARSE s + var layers = map.getElementsByTagName('layer') + for (i = 0, len = layers.length; i < len; i++) { + var l = layers[i] + var data = l.getElementsByTagName('data')[0] + var layer = new TMXLayerInfo() + + layer.name = l.getAttribute('name') + if (l.getAttribute('visible') !== false) { + layer.visible = true + } else { + layer.visible = !!parseInt(l.getAttribute('visible'), 10) + } + + s = {} + s.width = parseInt(l.getAttribute('width'), 10) + s.height = parseInt(l.getAttribute('height'), 10) + layer.layerSize = s + + var opacity = l.getAttribute('opacity') + if (!opacity && opacity !== 0) { + layer.opacity = 255 + } else { + layer.opacity = 255 * parseFloat(opacity) + } + + var x = parseInt(l.getAttribute('x'), 10), + y = parseInt(l.getAttribute('y'), 10) + if (isNaN(x)) { + x = 0 + } + if (isNaN(y)) { + y = 0 + } + layer.offset = ccp(x, y) + + + // Firefox has a 4KB limit on node values. It will split larger + // nodes up into multiple nodes. So, we'll stitch them back + // together. + var nodeValue = '' + for (j = 0, jen = data.childNodes.length; j < jen; j++) { + nodeValue += data.childNodes[j].nodeValue + } + + // Unpack the tilemap data + var compression = data.getAttribute('compression') + switch (compression) { + case 'gzip': + layer.tiles = gzip.unzipBase64AsArray(nodeValue, 4) + break + + // Uncompressed + case null: + case '': + layer.tiles = base64.decodeAsArray(nodeValue, 4) + break + + default: + throw "Unsupported TMX Tile Map compression: " + compression + } + + // Parties in + var properties = l.querySelectorAll('properties > property') + , propertiesValue = {} + , property + for (j = 0; j < properties.length; j++) { + property = properties[j] + if (property.getAttribute('name')) { + propertiesValue[property.getAttribute('name')] = property.getAttribute('value') + } + } + + layer.properties = propertiesValue + this.layers.push(layer) + } + + // TODO PARSE + + // PARSE + var objectgroups = map.getElementsByTagName('objectgroup') + for (i = 0, len = objectgroups.length; i < len; i++) { + var g = objectgroups[i], + objectGroup = new TMXObjectGroup() + + objectGroup.name = g.getAttribute('name') + + properties = g.querySelectorAll('objectgroup > properties property') + propertiesValue = {} + property + + for (j = 0; j < properties.length; j++) { + property = properties[j] + if (property.getAttribute('name')) { + propertiesValue[property.getAttribute('name')] = property.getAttribute('value') + } + } + + objectGroup.properties = propertiesValue + + var objectsArray = [], + objects = g.querySelectorAll('object') + + for (j = 0; j < objects.length; j++) { + var object = objects[j] + var objectValue = { + x : parseInt(object.getAttribute('x'), 10), + y : parseInt(object.getAttribute('y'), 10), + width : parseInt(object.getAttribute('width'), 10), + height : parseInt(object.getAttribute('height'), 10) + } + + if (cc.FLIP_Y_AXIS) { + objectValue.y = (this.mapSize.height * this.tileSize.height) - objectValue.y - objectValue.height + } + + if (object.getAttribute('name')) { + objectValue.name = object.getAttribute('name') + } + if (object.getAttribute('type')) { + objectValue.type = object.getAttribute('type') + } + properties = object.querySelectorAll('property') + for (var k = 0; k < properties.length; k++) { + property = properties[k] + if (property.getAttribute('name')) { + objectValue[property.getAttribute('name')] = property.getAttribute('value') + } + } + objectsArray.push(objectValue) + + } + objectGroup.objects = objectsArray + this.objectGroups.push(objectGroup) + } + + + // PARSE + var properties = doc.querySelectorAll('map > properties > property') + + for (i = 0; i < properties.length; i++) { + var property = properties[i] + if (property.getAttribute('name')) { + this.properties[property.getAttribute('name')] = property.getAttribute('value') + } + } + } +}) + +exports.TMXMapInfo = TMXMapInfo +exports.TMXLayerInfo = TMXLayerInfo +exports.TMXTilesetInfo = TMXTilesetInfo +exports.TMXObjectGroup = TMXObjectGroup + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/TMXXMLParser.js + + +__jah__.resources["/libs/cocos2d/TouchDispatcher.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { +'use strict' + +var util = require('util') + , geo = require('geometry') + + +var kCCTouchSelectorBeganBit = 1 << 0 + , kCCTouchSelectorMovedBit = 1 << 1 + , kCCTouchSelectorEndedBit = 1 << 2 + , kCCTouchSelectorCancelledBit = 1 << 3 + , kCCTouchSelectorAllBits = ( kCCTouchSelectorBeganBit | kCCTouchSelectorMovedBit | kCCTouchSelectorEndedBit | kCCTouchSelectorCancelledBit) + +// Touch types +var kCCTouchBegan = 1 + , kCCTouchMoved = 2 + , kCCTouchEnded = 3 + , kCCTouchCancelled = 4 + , kCCTouchMax = 5 + +function TouchHandler (delegate, priority) { + this.delegate = delegate + this.priority = priority +} + +function StandardTouchHandler (delegate, priority) { + StandardTouchHandler.superclass.constructor.call(this, delegate, priority) +} +StandardTouchHandler.inherit(TouchHandler) + +function TargetedTouchHandler (delegate, priority, swallowsTouches) { + TargetedTouchHandler.superclass.constructor.call(this, delegate, priority) + + this.swallowsTouches = swallowsTouches + this.claimedTouches = {} +} +TargetedTouchHandler.inherit(TouchHandler) + +/** + * @class + * This singleton is responsible for dispatching Touch events on some devices + * + * @memberOf cocos + * @singleton + */ +function TouchDispatcher () { + this.standardHandlers = [] + this.targetedHandlers = [] + + this._toRemove = false + this._toAdd = false + this._toQuit = false + this._locked = false + + this._handlersToAdd = [] + this._handlersToRemove = [] +} + +TouchDispatcher.inherit(Object, /** @lends cocos.TouchDispatcher# */ { + dispatchEvents: true + , standardHandlers: null + , targetedHandlers: null + + , forceAddHandler: function (handler, array) { + var i = 0 + array.forEach(function (h) { + if (h.priority < handler.priority) { + i++ + } + + if (h.delegate == handler.delegate) { + throw new Error ("Delegate already added to touch dispatcher") + } + }.bind(this)) + + array.splice(i, 0, handler) + } + + , addStandardDelegate: function (delegate, priority) { + var handler = new StandardTouchHandler(delegate, priority) + + if (this._locked) { + this._handlersToAdd.push(handler) + this._toAdd = true + } else { + this.forceAddHandler(handler, this.standardHandlers) + } + } + + , addTargetedDelegate: function (delegate, priority, swallowsTouches) { + var handler = new TargetedTouchHandler(delegate, priority, !!swallowsTouches) + + if (this._locked) { + this._handlersToAdd.push(handler) + this._toAdd = true + } else { + this.forceAddHandler(handler, this.targetedHandlers) + } + } + + , forceRemoveDelegate: function (delegate) { + var i, handler + for (i = 0; i < this.targetedHandlers.length; i++) { + handler = this.targetedHandlers[i] + if (handler.delegate === delegate) { + this.targetedHandlers.splice(i, 1) + handler.claimedTouches + break + } + } + + for (i = 0; i < this.standardHandlers.length; i++) { + handler = this.standardHandlers[i] + if (handler.delegate === delegate) { + this.standardHandlers.splice(i, 1) + break + } + } + } + + , removeDelegate: function (delegate) { + if (!delegate) { + return + } + + if (this._locked) { + this._handlersToRemove.push(delegate) + this._toRemove = true + } else { + this.forceRemoveDelegate(delegate) + } + } + + , forceRemoveAllDelegates: function () { + this.standardHandlers.splice(0, this.standardHandlers.length) + this.targetedHandlers.splice(0, this.targetedHandlers.length) + } + + , removeAllDelegates: function () { + if (this._locked) { + this._toQuit = true + } else { + this.forceRemoveAllDelegates() + } + } + + , findHandler: function (delegate) { + var i, handler + for (i = 0; i < this.targetedHandlers.length; i++) { + handler = this.targetedHandlers[i] + if (handler.delegate === delegate) { + return handler + } + } + + for (i = 0; i < this.standardHandlers.length; i++) { + handler = this.standardHandlers[i] + if (handler.delegate === delegate) { + return handler + } + } + + return null + } + , rearrangeHandlers: function (array) { + array.sort(function (first, second) { + return first.priority - second.priority + }) + } + + , setDelegatePriority: function (delegate, priority) { + if (!delegate) throw new Error("Got nil touch delegate") + + var handler = this.findHandler(delegate) + if (!handler) throw new Error("Delegate not found") + + handler.priority = priority + + this.rearrangeHandlers(this.targetedHandlers) + this.rearrangeHandlers(this.standardHandlers) + } + + , ontouches: function (evt, touchType) { + this._locked = true + + var director = require('./Director').Director.sharedDirector + + var i, j, touch, handler, idx + + // Can't modify the evt.touches object directly -- and we only need to if we're doing both types of handlers + var needsMutableSet = this.targetedHandlers.length && this.standardHandlers.length + , mutableTouches = needsMutableSet ? Array.prototype.splice.call(evt.changedTouches, 0) : evt.changedTouches + + for (i = 0; i < mutableTouches.length; i++) { + touch = mutableTouches[i] + touch.locationInCanvas = director.convertTouchToCanvas(touch) + } + + // Process Targeted handlers first + if (this.targetedHandlers.length > 0) { + var claimed = false + for (i = 0; i < mutableTouches.length; i++) { + touch = mutableTouches[i] + + for (j = 0; j < this.targetedHandlers.length; j++) { + handler = this.targetedHandlers[j] + + claimed = false + // Touch began + if (touchType == kCCTouchBegan) { + if (handler.delegate.touchBegan) { + claimed = handler.delegate.touchBegan({touch: touch, originalEvent: evt}) + } + if (claimed) { + handler.claimedTouches[touch.identifier] = touch + } + } + // Touch move, end, cancel + else if (handler.claimedTouches[touch.identifier]) { + claimed = true + switch (touchType) { + case kCCTouchMoved: + if (handler.delegate.touchMoved) handler.delegate.touchMoved({touch: touch, originalEvent: evt}) + break + + case kCCTouchEnded: + console.log('touch end') + if (handler.delegate.touchEnded) handler.delegate.touchEnded({touch: touch, originalEvent: evt}) + delete handler.claimedTouches[touch.identifier] + break + + case kCCTouchCancelled: + if (handler.delegate.touchCancelled) handler.delegate.touchCancelled({touch: touch, originalEvent: evt}) + delete handler.claimedTouches[touch.identifier] + break + } + } + + if (claimed && handler.swallowsTouches) { + if (needsMutableSet) { + idx = mutableTouches.indexOf(touch) + mutableTouches.splice(idx, 1) + // Removed item, so knock loop back one + i-- + } + break + } + } + } + } + + // Standard touch handling + if (this.standardHandlers.length > 0 && mutableTouches.length > 0) { + for (j = 0; j < this.standardHandlers.length; j++) { + handler = this.standardHandlers[j] + switch (touchType) { + case kCCTouchBegan: + if (handler.delegate.touchesBegan) + handler.delegate.touchesBegan({touches: mutableTouches, originalEvent: evt}) + break + + case kCCTouchMoved: + if (handler.delegate.touchesMoved) + handler.delegate.touchesMoved({touches: mutableTouches, originalEvent: evt}) + break + + case kCCTouchEnded: + if (handler.delegate.touchesEnded) + handler.delegate.touchesEnded({touches: mutableTouches, originalEvent: evt}) + break + + case kCCTouchCancelled: + if (handler.delegate.touchesCancelled) + handler.delegate.touchesCancelled({touches: mutableTouches, originalEvent: evt}) + break + } + } + } + + this._locked = false + if (this._toRemove) { + this._toRemove = false + for (i = 0; i < this._handlersToRemove.length; i++) { + this.forceRemoveDelegate(this._handlersToRemove[i]) + } + // Clear the array in place + this._handlersToRemove.splice(0, this._handlersToRemove.length) + } + + if (this._toAdd) { + this._toAdd = false + for (i = 0; i < this._handlersToAdd.length; i++) { + handler = this._handlersToAdd[i] + if (handler instanceof TargetedTouchHandler) { + this.forceAddHandler(handler, this.targetedHandlers) + } else { + this.forceAddHandler(handler, this.standardHandlers) + } + } + // Clear the array in place + this._handlersToAdd.splice(0, this._handlersToAdd.length) + } + + if (this._toQuit) { + this._toQuit = false + this.forceRemoveAllDelegates() + } + } + + , touchesBegan: function (evt) { + if (this.dispatchEvents) + this.ontouches(evt, kCCTouchBegan) + } + + , touchesMoved: function (evt) { + if (this.dispatchEvents) + this.ontouches(evt, kCCTouchMoved) + } + + , touchesEnded: function (evt) { + if (this.dispatchEvents) + this.ontouches(evt, kCCTouchEnded) + } + + , touchesCancelled: function (evt) { + if (this.dispatchEvents) + this.ontouches(evt, kCCTouchCancelled) + } + +}) + +Object.defineProperty(TouchDispatcher, 'sharedDispatcher', { + /** + * A shared singleton instance of cocos.TouchDispatcher + * + * @memberOf cocos.TouchDispatcher + * @getter {cocos.TouchDispatcher} sharedDispatcher + */ + get: function () { + if (!TouchDispatcher._instance) { + TouchDispatcher._instance = new this() + } + + return TouchDispatcher._instance + } + + , enumerable: true +}) + +exports.TouchDispatcher = TouchDispatcher +exports.TouchHandler = TouchHandler + +// vim:et:st=4:fdm=marker:fdl=0:fdc=1 + +}, mimetype: "application/javascript", remote: false}; // END: /libs/cocos2d/TouchDispatcher.js + + +})(); + + ;(function(){ + __jah__.resources["/main.js"] = {data: function (exports, require, resource, module, __filename, __dirname) { + var modules = { cocos: require('cocos2d') + , events: require('events') + , geo: require('geometry') + } + + var skip = 'nodes actions'.w + + var modName, mod, key + for (modName in modules) { + mod = modules[modName] + for (key in mod) { + if (mod.hasOwnProperty(key) && skip.indexOf(key) == -1) { + cc[key] = mod[key] + } + } + } + window.cc = cc + + }, mimetype: "application/javascript", remote: false}; // END: /main.js + + + })(); + + + __jah__.__triggerReady() +})({STANDALONE: true}) diff --git a/static/libs/collie.min.js b/static/libs/collie.min.js new file mode 100644 index 0000000..6b42430 --- /dev/null +++ b/static/libs/collie.min.js @@ -0,0 +1,578 @@ + +var collie=collie||{};(function(){collie.version="1.0.0";collie.Class=function(f,e){var c=null;if("$init" in f){c=f.$init; +delete f.$init}var d=function(){if(c!==null){c.apply(this,arguments)}};if(typeof e!="undefined"){d=function(){e.apply(this,arguments); +if(c!==null){c.apply(this,arguments)}};var b=function(){};b.prototype=e.prototype;d.$super=e.prototype;d.prototype=new b(); +d.prototype.constructor=d}for(var a in f){if(f.hasOwnProperty(a)&&a!="prototype"){d.prototype[a]=f[a]}}return d};collie.util=new (collie.Class({$init:function(){this._sCSSPrefix=null; +this._htDeviceInfo=null;this._bSupport3d=null;this._bSupportCSS3=null;this._htBoundary={left:0,right:0,top:0,bottom:0}},getDisplayObjectById:function(a){return collie.DisplayObject.htFactory[a] +},getDisplayObjectByName:function(b){for(var a in collie.DisplayObject.htFactory){if(collie.DisplayObject.htFactory[a].get("name")==b){return collie.DisplayObject.htFactory[a] +}}return false},getDeviceInfo:function(){if(this._htDeviceInfo!==null){return this._htDeviceInfo}var c=null;var b=false;var e=typeof CanvasRenderingContext2D!="undefined"; +var g=false;var h=false;var d=false;var f=navigator.userAgent;var a=0;if(/android/i.test(f)){g=true;c=f.toString().match(/android ([0-9]\.[0-9])/i); +if(c&&c[1]){a=parseFloat(c[1])}}else{if(/(iphone|ipad|ipod)/i.test(f)){h=true;c=f.toString().match(/([0-9]_[0-9])/i);if(c&&c[1]){a=parseFloat(c[1].replace(/_/,".")) +}}else{b=true;if(/(MSIE)/i.test(f)){d=true;c=f.toString().match(/MSIE ([0-9])/i);if(c&&c[1]){a=parseInt(c[1],10)}}}}this._htDeviceInfo={supportCanvas:e,desktop:b,android:g?a:false,ios:h?a:false,ie:d?a:false}; +return this._htDeviceInfo},getCSSPrefix:function(f,b){var d="";if(this._sCSSPrefix===null){this._sCSSPrefix="";if(typeof document.body.style.webkitTransform!=="undefined"){this._sCSSPrefix="-webkit-" +}else{if(typeof document.body.style.MozTransform!=="undefined"){this._sCSSPrefix="-moz-"}else{if(typeof document.body.style.OTransform!=="undefined"){this._sCSSPrefix="-o-" +}else{if(typeof document.body.style.msTransform!=="undefined"){this._sCSSPrefix="-ms-"}}}}}d=this._sCSSPrefix+(f?f:"");if(b){var e=d.split("-"); +d="";for(var c=0,a=e.length;c=4) +}return this._bSupport3d},toRad:function(a){return a*Math.PI/180},toDeg:function(a){return a*180/Math.PI},approximateValue:function(a){return Math.round(a*10000000)/10000000 +},fixAngle:function(a){var b=collie.util.toDeg(a);b-=Math.floor(b/360)*360;return collie.util.toRad(b)},getDistance:function(b,d,a,c){return Math.sqrt(Math.pow(a-b,2)+Math.pow(c-d,2)) +},getBoundary:function(b){var g=Number.MAX_VALUE;var f=Number.MAX_VALUE;var e=Number.MIN_VALUE;var d=Number.MIN_VALUE;for(var c=0,a=b.length; +cd.get("zIndex")){e.splice(c,0,d); +b=true;break}}if(!b){e.push(d)}},addEventListener:function(b,d,c,a){if("addEventListener" in b){b.addEventListener(d,c,a) +}else{b.attachEvent("on"+d,c,a)}},removeEventListener:function(b,d,c,a){if("removeEventListener" in b){b.removeEventListener(d,c,a) +}else{b.detachEvent("on"+d,c,a)}},stopEventDefault:function(a){a=a||window.event;if("preventDefault" in a){a.preventDefault() +}a.returnValue=false}}))();if(collie.util.getDeviceInfo().ios){window.addEventListener("load",function(){setTimeout(function(){document.body.scrollTop=0 +},300)})}if(!Function.prototype.bind){Function.prototype.bind=function(a){if(typeof this!=="function"){throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable") +}var e=Array.prototype.slice.call(arguments,1),d=this,b=function(){},c=function(){return d.apply(this instanceof b?this:a,e.concat(Array.prototype.slice.call(arguments))) +};b.prototype=this.prototype;c.prototype=new b();return c}}})();collie.Effect=function(e){if(this instanceof arguments.callee){throw new Error("You can't create a instance of this") +}var c=/^(\-?[0-9\.]+)(%|px|pt|em)?$/,d=/^rgb\(([0-9]+)\s?,\s?([0-9]+)\s?,\s?([0-9]+)\)$/i,f=/^#([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i,b=/^#([0-9A-F])([0-9A-F])([0-9A-F])$/i; +var a=function(h){var j=h,g;if(c.test(h)){j=parseFloat(h);g=RegExp.$2||""}else{if(d.test(h)){j=[parseInt(RegExp.$1,10),parseInt(RegExp.$2,10),parseInt(RegExp.$3,10)]; +g="color"}else{if(f.test(h=h.replace(b,"#$1$1$2$2$3$3"))){j=[parseInt(RegExp.$1,16),parseInt(RegExp.$2,16),parseInt(RegExp.$3,16)]; +g="color"}}}return{nValue:j,sUnit:g}};return function(j,k){var g;if(arguments.length>1){j=a(j);k=a(k);g=k.sUnit}else{k=a(j); +j=null;g=k.sUnit}if(j&&k&&j.sUnit!=k.sUnit){throw new Error("unit error")}j=j&&j.nValue;k=k&&k.nValue;var h=function(o){var m=e(o),q=function(p,r){return(r-p)*m+p+g +};if(g=="color"){var n=Math.max(0,Math.min(255,parseInt(q(j[0],k[0]),10)))<<16;n|=Math.max(0,Math.min(255,parseInt(q(j[1],k[1]),10)))<<8; +n|=Math.max(0,Math.min(255,parseInt(q(j[2],k[2]),10)));n=n.toString(16).toUpperCase();for(var l=0;6-n.length;l++){n="0"+n +}return"#"+n}return q(j,k)};if(j===null){h.setStart=function(l){l=a(l);if(l.sUnit!=g){throw new Error("unit eror")}j=l.nValue +}}return h}};collie.Effect.linear=collie.Effect(function(a){return a});collie.Effect.easeInSine=collie.Effect(function(a){return(a==1)?1:-Math.cos(a*(Math.PI/2))+1 +});collie.Effect.easeOutSine=collie.Effect(function(a){return Math.sin(a*(Math.PI/2))});collie.Effect.easeInOutSine=collie.Effect(function(a){return(a<0.5)?collie.Effect.easeInSine(0,1)(2*a)*0.5:collie.Effect.easeOutSine(0,1)((2*a)-1)*0.5+0.5 +});collie.Effect.easeOutInSine=collie.Effect(function(a){return(a<0.5)?collie.Effect.easeOutSine(0,1)(2*a)*0.5:collie.Effect.easeInSine(0,1)((2*a)-1)*0.5+0.5 +});collie.Effect.easeInQuad=collie.Effect(function(a){return a*a});collie.Effect.easeOutQuad=collie.Effect(function(a){return -(a*(a-2)) +});collie.Effect.easeInOutQuad=collie.Effect(function(a){return(a<0.5)?collie.Effect.easeInQuad(0,1)(2*a)*0.5:collie.Effect.easeOutQuad(0,1)((2*a)-1)*0.5+0.5 +});collie.Effect.easeOutInQuad=collie.Effect(function(a){return(a<0.5)?collie.Effect.easeOutQuad(0,1)(2*a)*0.5:collie.Effect.easeInQuad(0,1)((2*a)-1)*0.5+0.5 +});collie.Effect.easeInCubic=collie.Effect(function(a){return Math.pow(a,3)});collie.Effect.easeOutCubic=collie.Effect(function(a){return Math.pow((a-1),3)+1 +});collie.Effect.easeInOutCubic=collie.Effect(function(a){return(a<0.5)?collie.Effect.easeIn(0,1)(2*a)*0.5:collie.Effect.easeOut(0,1)((2*a)-1)*0.5+0.5 +});collie.Effect.easeOutInCubic=collie.Effect(function(a){return(a<0.5)?collie.Effect.easeOut(0,1)(2*a)*0.5:collie.Effect.easeIn(0,1)((2*a)-1)*0.5+0.5 +});collie.Effect.easeInQuart=collie.Effect(function(a){return Math.pow(a,4)});collie.Effect.easeOutQuart=collie.Effect(function(a){return -(Math.pow(a-1,4)-1) +});collie.Effect.easeInOutQuart=collie.Effect(function(a){return(a<0.5)?collie.Effect.easeInQuart(0,1)(2*a)*0.5:collie.Effect.easeOutQuart(0,1)((2*a)-1)*0.5+0.5 +});collie.Effect.easeOutInQuart=collie.Effect(function(a){return(a<0.5)?collie.Effect.easeOutQuart(0,1)(2*a)*0.5:collie.Effect.easeInQuart(0,1)((2*a)-1)*0.5+0.5 +});collie.Effect.easeInQuint=collie.Effect(function(a){return Math.pow(a,5)});collie.Effect.easeOutQuint=collie.Effect(function(a){return Math.pow(a-1,5)+1 +});collie.Effect.easeInOutQuint=collie.Effect(function(a){return(a<0.5)?collie.Effect.easeInQuint(0,1)(2*a)*0.5:collie.Effect.easeOutQuint(0,1)((2*a)-1)*0.5+0.5 +});collie.Effect.easeOutInQuint=collie.Effect(function(a){return(a<0.5)?collie.Effect.easeOutQuint(0,1)(2*a)*0.5:collie.Effect.easeInQuint(0,1)((2*a)-1)*0.5+0.5 +});collie.Effect.easeInCircle=collie.Effect(function(a){return -(Math.sqrt(1-(a*a))-1)});collie.Effect.easeOutCircle=collie.Effect(function(a){return Math.sqrt(1-(a-1)*(a-1)) +});collie.Effect.easeInOutCircle=collie.Effect(function(a){return(a<0.5)?collie.Effect.easeInCircle(0,1)(2*a)*0.5:collie.Effect.easeOutCircle(0,1)((2*a)-1)*0.5+0.5 +});collie.Effect.easeOutInCircle=collie.Effect(function(a){return(a<0.5)?collie.Effect.easeOutCircle(0,1)(2*a)*0.5:collie.Effect.easeInCircle(0,1)((2*a)-1)*0.5+0.5 +});collie.Effect.easeInBack=collie.Effect(function(a){var b=1.70158;return(a==1)?1:(a/1)*(a/1)*((1+b)*a-b)});collie.Effect.easeOutBack=collie.Effect(function(a){var b=1.70158; +return(a===0)?0:(a=a/1-1)*a*((b+1)*a+b)+1});collie.Effect.easeInOutBack=collie.Effect(function(a){return(a<0.5)?collie.Effect.easeInBack(0,1)(2*a)*0.5:collie.Effect.easeOutBack(0,1)((2*a)-1)*0.5+0.5 +});collie.Effect.easeInElastic=collie.Effect(function(c){var d=0,b=0,e;if(c===0){return 0}if((c/=1)==1){return 1}if(!d){d=0.3 +}if(!b||b<1){b=1;e=d/4}else{e=d/(2*Math.PI)*Math.asin(1/b)}return -(b*Math.pow(2,10*(c-=1))*Math.sin((c-1)*(2*Math.PI)/d)) +});collie.Effect.easeOutElastic=collie.Effect(function(c){var d=0,b=0,e;if(c===0){return 0}if((c/=1)==1){return 1}if(!d){d=0.3 +}if(!b||b<1){b=1;e=d/4}else{e=d/(2*Math.PI)*Math.asin(1/b)}return(b*Math.pow(2,-10*c)*Math.sin((c-e)*(2*Math.PI)/d)+1)}); +collie.Effect.easeInOutElastic=collie.Effect(function(c){var d=0,b=0,e;if(c===0){return 0}if((c/=1/2)==2){return 1}if(!d){d=(0.3*1.5) +}if(!b||b<1){b=1;e=d/4}else{e=d/(2*Math.PI)*Math.asin(1/b)}if(c<1){return -0.5*(b*Math.pow(2,10*(c-=1))*Math.sin((c-e)*(2*Math.PI)/d)) +}return b*Math.pow(2,-10*(c-=1))*Math.sin((c-e)*(2*Math.PI)/d)*0.5+1});collie.Effect.easeOutBounce=collie.Effect(function(a){if(a<(1/2.75)){return(7.5625*a*a) +}else{if(a<(2/2.75)){return(7.5625*(a-=(1.5/2.75))*a+0.75)}else{if(a<(2.5/2.75)){return(7.5625*(a-=(2.25/2.75))*a+0.9375) +}else{return(7.5625*(a-=(2.625/2.75))*a+0.984375)}}}});collie.Effect.easeInBounce=collie.Effect(function(a){return 1-collie.Effect.easeOutBounce(0,1)(1-a) +});collie.Effect.easeInOutBounce=collie.Effect(function(a){return(a<0.5)?collie.Effect.easeInBounce(0,1)(2*a)*0.5:collie.Effect.easeOutBounce(0,1)((2*a)-1)*0.5+0.5 +});collie.Effect.easeInExpo=collie.Effect(function(a){return(a===0)?0:Math.pow(2,10*(a-1))});collie.Effect.easeOutExpo=collie.Effect(function(a){return(a==1)?1:-Math.pow(2,-10*a/1)+1 +});collie.Effect.easeInOutExpo=collie.Effect(function(a){return(a<0.5)?collie.Effect.easeInExpo(0,1)(2*a)*0.5:collie.Effect.easeOutExpo(0,1)((2*a)-1)*0.5+0.5 +});collie.Effect.easeOutInExpo=collie.Effect(function(a){return(a<0.5)?collie.Effect.easeOutExpo(0,1)(2*a)*0.5:collie.Effect.easeInExpo(0,1)((2*a)-1)*0.5+0.5 +});collie.Effect._cubicBezier=function(b,d,a,c){return function(o){var l=3*b,n=3*(a-b)-l,e=1-l-n,k=3*d,m=3*(c-d)-k,p=1-k-m; +function j(q){return((e*q+n)*q+l)*q}function h(q){return((p*q+m)*q+k)*q}function f(q){return(3*e*q+2*n)*q+l}function g(q,y){var w,v,t,r,u,s; +for(t=q,s=0;s<8;s++){r=j(t)-q;if(Math.abs(r)v){return v}while(wr){w=t}else{v=t}t=(v-w)*0.5+w}return t}return h(g(o,1/200)) +}};collie.Effect.cubicBezier=function(b,d,a,c){return collie.Effect(collie.Effect._cubicBezier(b,d,a,c))};collie.Effect.cubicEase=collie.Effect.cubicBezier(0.25,0.1,0.25,1); +collie.Effect.cubicEaseIn=collie.Effect.cubicBezier(0.42,0,1,1);collie.Effect.cubicEaseOut=collie.Effect.cubicBezier(0,0,0.58,1); +collie.Effect.cubicEaseInOut=collie.Effect.cubicBezier(0.42,0,0.58,1);collie.Effect.cubicEaseOutIn=collie.Effect.cubicBezier(0,0.42,1,0.58); +collie.Effect.overphase=collie.Effect(function(a){a/=0.652785;return(Math.sqrt((2-a)*a)+(0.1*a)).toFixed(5)});collie.Effect.sinusoidal=collie.Effect(function(a){return(-Math.cos(a*Math.PI)/2)+0.5 +});collie.Effect.mirror=collie.Effect(function(a){return(a<0.5)?collie.Effect.sinusoidal(0,1)(a*2):collie.Effect.sinusoidal(0,1)(1-(a-0.5)*2) +});collie.Effect.pulse=function(a){return collie.Effect(function(b){return(-Math.cos((b*(a-0.5)*2)*Math.PI)/2)+0.5})};collie.Effect.wave=function(b,a){return collie.Effect(function(c){return(a||1)*(Math.sin(b*(c*360)*Math.PI/180)).toFixed(5) +})};collie.Effect.easeIn=collie.Effect.easeInCubic;collie.Effect.easeOut=collie.Effect.easeOutCubic;collie.Effect.easeInOut=collie.Effect.easeInOutCubic; +collie.Effect.easeOutIn=collie.Effect.easeOutInCubic;collie.Effect.bounce=collie.Effect.easeOutBounce;collie.Effect.elastic=collie.Effect.easeInElastic; +collie.Component=collie.Class({$init:function(){this._bInitOption=false;this._htOption={};this._htOptionSetter={};this._htHandler={} +},option:function(b,d,c){if(typeof b=="object"){if(!this._bInitOption){this._htOption=collie.util.cloneObject(b);this._bInitOption=true +}else{for(var a in b){this.option(a,b[a],c)}}}else{if(typeof b=="string"){if(d!==undefined){if(!c||typeof this._htOption[b]=="undefined"){this._htOption[b]=d; +if(this._htOptionSetter[b]!==undefined){this._htOptionSetter[b](d)}this._bInitOption=true}}else{return this._htOption[b]}}else{return this._htOption +}}},optionSetter:function(b,a){this._htOptionSetter[b]=a},fireEvent:function(e,c){if(this._htHandler[e]!==undefined&&this._htHandler[e].length>0){c=c||{}; +oCustomEvent=new collie.ComponentEvent(e,c);var f=this._htHandler[e].concat();var b=false;for(var d=0,a=f.length;d=j){h(f)}}).bind(this)}if(e&&e!==null){d=(function(k,m,l){b.push([k,m,l]);if(b.length+g>=j){e(b)}}).bind(this)}for(var c in f){this.addImage(c,f[c],a,d) +}},addImage:function(d,c,e,b){if(this.getImage(d)){if(e&&e!==null){e(this.getImage(d),d,c)}return}if((d in this._htImageWhileLoading)&&this._addMarkCallback(d,e,b)){return +}this._nCount++;this._markImage(d);var a=new Image();if(this.USE_PRERENDERING_DOM&&collie.Renderer.getRenderingMode()=="dom"&&collie.util.getSupportCSS3d()&&!collie.util.getDeviceInfo().android){a.style.webkitTransform="translateZ(0)"; +a.style.position="absolute";a.style.visibility="hidden";collie.Renderer.getElement().appendChild(a)}this._htImageWhileLoading[d]=a; +a.onload=(function(f){this._addImage(a,d);if(e&&e!==null){e(a,d,c)}a.onerror=a.onload=null;this._deleteWhileLoading(d)}).bind(this); +a.onerror=(function(f){if(this._htImageRetryCount[d]-1}},getElement:function(){return this._el +},clear:function(){return true},resize:function(b,a,d){if(d){var c=b/this._oLayer.option("width");var e=a/this._oLayer.option("height"); +this._oEvent.setEventRatio(c,e);this._el.style[collie.util.getCSSPrefix("transform-origin",true)]="0 0";if(collie.util.getSupportCSS3d()){this._el.style[collie.util.getCSSPrefix("transform",true)]="scale3d("+c+", "+e+", 1)" +}else{this._el.style[collie.util.getCSSPrefix("transform",true)]="scale("+c+", "+e+")"}}else{this._el.style.width=b+"px"; +this._el.style.height=a+"px"}}});collie.LayerEvent=collie.Class({THRESHOLD_CLICK:7,$init:function(a){this._oLayer=a;this._bHasTouchEvent=!!("ontouchstart" in window); +this._fOnEvent=this._onEvent.bind(this);this._oMousedownObject=null;this._htEventRatio={width:1,height:1};this._bAttached=false +},attachEvent:function(){var a=collie.Renderer.getElement();if(this._oLayer.option("useEvent")){if(this._bHasTouchEvent){collie.util.addEventListener(a,"touchstart",this._fOnEvent); +collie.util.addEventListener(a,"touchend",this._fOnEvent);collie.util.addEventListener(a,"touchmove",this._fOnEvent);collie.util.addEventListener(a,"touchcancel",this._fOnEvent) +}else{collie.util.addEventListener(a,"mousedown",this._fOnEvent);collie.util.addEventListener(a,"mouseup",this._fOnEvent); +collie.util.addEventListener(a,"mousemove",this._fOnEvent)}this._bAttached=true}},detachEvent:function(){var a=collie.Renderer.getElement(); +if(this._bAttached){if(this._bHasTouchEvent){collie.util.removeEventListener(a,"touchstart",this._fOnEvent);collie.util.removeEventListener(a,"touchend",this._fOnEvent); +collie.util.removeEventListener(a,"touchmove",this._fOnEvent);collie.util.removeEventListener(a,"touchcancel",this._fOnEvent) +}else{collie.util.removeEventListener(a,"mousedown",this._fOnEvent);collie.util.removeEventListener(a,"mouseup",this._fOnEvent); +collie.util.removeEventListener(a,"mousemove",this._fOnEvent)}this._bAttached=false}},_onEvent:function(n){if(!this._oLayer.option("useEvent")){return +}n=n||window.event;var p=this._bHasTouchEvent?n.changedTouches[0]:n||window.event;var g=this._bHasTouchEvent?this._getEventTargetElement(n):n.target||n.srcElement; +var m=g.ownerDocument||document;var h=m.body||m.documentElement;var q=this._bHasTouchEvent?p.pageX:p.pageX||p.clientX+h.scrollLeft-m.body.clientLeft; +var o=this._bHasTouchEvent?p.pageY:p.pageY||p.clientY+h.scrollTop-m.body.clientTop;var b=n.type;var l=null;var f=collie.Renderer.getPosition(); +var k=q-f.x;var j=o-f.y;if(b=="touchcancel"){if(this._htEventStartPos!==null){k=this._htEventStartPos.x;j=this._htEventStartPos.y +}}b=this._convertEventType(b);if(b=="mousemove"||b=="mousedown"){if(collie.Renderer.isPreventDefault()){collie.util.stopEventDefault(n) +}}if(b=="mousedown"){this._htEventStartPos={x:k,y:j}}var a=this._fireEvent(n,b,k,j);if(b=="mouseup"){var d=this.THRESHOLD_CLICK*this._htEventRatio.width; +var c=this.THRESHOLD_CLICK*this._htEventRatio.height;if(this._htEventStartPos&&this._htEventStartPos.x-d<=k&&k<=this._htEventStartPos.x+d&&this._htEventStartPos.y-c<=j&&j<=this._htEventStartPos.y+c){this._fireEvent(n,"click",k,j) +}this._htEventStartPos=null}collie.Renderer.setEventStatus(b,a)},_fireEvent:function(d,h,g,f){var b=null;var a=true;if(h!="mousemove"&&!collie.Renderer.isStopEvent(h)){var c=this._oLayer.getChildren(); +b=this._getTargetOnHitEvent(c,g,f);if(b){a=this._bubbleEvent(b,h,d,g,f);if(h=="mousedown"){this._setMousedownObject(b)}if(h=="mouseup"){this._unsetMousedownObject(b) +}}}if(h=="mouseup"&&this._getMousedownObject()!==null){b=this._getMousedownObject();this._bubbleEvent(b,h,d,g,f);this._unsetMousedownObject(b) +}if(a){this._oLayer.fireEvent(h,{event:d,displayObject:b,x:g,y:f})}return !!b},_getTargetOnHitEvent:function(a,e,d){var b=null; +if(a instanceof Array){for(var c=a.length-1;c>=0;c--){if(a[c].hasChild()){b=this._getTargetOnHitEvent(a[c].getChildren(),e,d); +if(b){return b}}b=this._getTargetOnHitEvent(a[c],e,d);if(b){return b}}}else{return this._isPointInDisplayObjectBoundary(a,e,d)?a:false +}},_convertEventType:function(b){var a=b;switch(b){case"touchstart":a="mousedown";break;case"touchmove":a="mousemove";break; +case"touchend":case"touchcancel":a="mouseup";break;case"tap":a="click";break}return a},_getEventTargetElement:function(b){var a=b.target; +while(a.nodeType!=1){a=a.parentNode}return a},_bubbleEvent:function(a,g,b,f,c,d){if(a.fireEvent(g,{displayObject:d||a,event:b,x:f,y:c})===false){return false +}if(a.getParent()&&!this._bubbleEvent(a.getParent(),g,b,f,c,a)){return false}return true},_isPointInDisplayObjectBoundary:function(d,a,f){if(!d.get("useEvent")||!d.get("visible")||!d.get("width")||!d.get("height")||(d.get("useEvent")=="auto"&&!d.hasAttachedHandler())){return false +}a/=this._htEventRatio.width;f/=this._htEventRatio.height;var b=d.getHitAreaBoundary();if(b.left<=a&&a<=b.right&&b.top<=f&&f<=b.bottom){if(!d.get("hitArea")){return true +}else{var e=d.getRelatedPosition();a-=e.x;f-=e.y;var c=d.get("hitArea");c=collie.Transform.points(d,c);return this._isPointInPolygon(c,a,f) +}}return false},_isPointInPolygon:function(c,g,f){var e=false;for(var d=0,b=c.length-1,a=c.length;df)!=(c[b][1]>f)&&(g<(c[b][0]-c[d][0])*(f-c[d][1])/(c[b][1]-c[d][1])+c[d][0])){e=!e +}}return e},_setMousedownObject:function(a){this._oMousedownObject=a},_unsetMousedownObject:function(a){if(this._oMousedownObject==a){this._oMousedownObject=null +}},_getMousedownObject:function(){return this._oMousedownObject},setEventRatio:function(b,a){this._htEventRatio.width=b||this._htEventRatio.width; +this._htEventRatio.height=a||this._htEventRatio.height},getEventRatio:function(){return this._htEventRatio}});collie.Layer=collie.Class({type:"layer",$init:function(a){this.option({width:320,height:480,useEvent:true,visible:true,freeze:false}); +if(a!==undefined){this.option(a)}this.drawCount=0;this.optionSetter("visible",this._setVisible.bind(this));this._bChanged=false; +this._aDisplayObjects=[];this._bLoaded=false;this._oEvent=new collie.LayerEvent(this);this._makeDrawing();this._setVisible() +},_makeDrawing:function(){this._oDrawing=collie.Renderer.getRenderingMode()=="dom"?new collie.LayerDOM(this):new collie.LayerCanvas(this) +},getDrawing:function(){return this._oDrawing},getEvent:function(){return this._oEvent},load:function(b,a){this.unload(); +this._bLoaded=true;this.getElement().style.zIndex=a;this._elParent=b;this._elParent.style.width=Math.max(parseInt(this._elParent.style.width||0,10),this.option("width"))+"px"; +this._elParent.style.height=Math.max(parseInt(this._elParent.style.height||0,10),this.option("height"))+"px";this._elParent.appendChild(this.getElement()) +},unload:function(){if(this.isLoaded()){this._oEvent.detachEvent();this._elParent.removeChild(this.getElement());this._elParent=null; +this._bLoaded=false}},attachEvent:function(){this._oEvent.attachEvent()},detachEvent:function(){this._oEvent.detachEvent() +},_setVisible:function(){if(this.getElement()){this.getElement().style.display=this.option("visible")?"block":"none"}},isLoaded:function(){return this._bLoaded +},addChild:function(a){collie.util.pushWithSort(this._aDisplayObjects,a);a.setLayer(this);this.setChanged()},addChildren:function(b){for(var c=0,a=b.length; +c=0;b--){if(a[b]){this.removeChild(a[b],b)}}},changeDisplayObjectZIndex:function(a){this.removeChild(a); +this.addChild(a)},getChildren:function(){return this._aDisplayObjects},hasChild:function(){return this._aDisplayObjects&&this._aDisplayObjects.length>0 +},setChanged:function(){this._bChanged=true},isChanged:function(){return this._bChanged},unsetChanged:function(){this._bChanged=false +},getContext:function(){return("getContext" in this._oDrawing)?this._oDrawing.getContext():false},getElement:function(){return("getElement" in this._oDrawing)?this._oDrawing.getElement():false +},update:function(e){this.drawCount=0;if(!this.isChanged()||this.option("freeze")){return}this.clear();this.unsetChanged(); +var c=this.option("width");var b=this.option("height");for(var d=0,a=this._aDisplayObjects.length;d0||F>0){for(var o=0; +oz.width?K.width-(g-z.width):K.width; +var v=f>z.height?K.height-(f-z.height):K.height;this.drawImage(h,0,0,s,v,(c/k)+o*K.width,(b/k)+E*K.height,s,v)}}}}else{this.drawImage(h,z.offsetX,z.offsetY,Math.min(K.width,z.width),Math.min(K.height,z.height),c/k,b/k,z.width,z.height) +}}}if(z.debugHitArea&&z.hitArea){if(this._oDebugHitArea===null){this._oDebugHitArea=new collie.Polyline({x:0,y:0,width:z.width,height:z.height,strokeColor:z.debugHitArea===true?"yellow":z.debugHitArea,strokeWidth:3}).addTo(this._oDisplayObject); +this._oDebugHitArea.setPointData(z.hitArea)}}if(this._oDisplayObject.hasChild()&&(!z.useCache||(this._oDisplayObject.isChanged()&&!this._oDisplayObject.isChanged(true)))){var m=this._oDisplayObject.getChildren(); +for(var J=0,r=m.length;J0},getChildren:function(){return this._aDisplayObjects +},getParent:function(){return this._oParent||false},setParent:function(a){this._oParent=a},unsetParent:function(){this._oParent=null +},leave:function(){var a=null;if(this._oParent!==null){a=this._oParent}else{if(this._oLayer){a=this.getLayer()}}if(a){a.removeChild(this) +}return this},getId:function(){return this._sId},getImage:function(){return this._elImage||null},getImageSize:function(){return this._htImageSize||false +},setImage:function(a){if(typeof a=="string"||!a){if(this._htGetImageData!==null&&this._htGetImageData.name!=a){collie.ImageManager.cancelGetImage(this._htGetImageData.name,this._htGetImageData.callback); +this._htGetImageData=null}if(!a){this._elImage=null;this.setChanged()}else{this._htGetImageData={name:a,callback:(function(b){this.setImage(b) +}).bind(this)};collie.ImageManager.getImage(this._htGetImageData.name,this._htGetImageData.callback)}return}if(this._elImage&&this._elImage==a){return +}this._elImage=a;this._nImageWidth=a.width;this._nImageHeight=a.height;this._htImageSize={width:this._bRetinaDisplay?this._nImageWidth/2:this._nImageWidth,height:this._bRetinaDisplay?this._nImageHeight/2:this._nImageHeight}; +if(!this._bCustomSize){this.set({width:this._htImageSize.width,height:this._htImageSize.height})}this._setSpritePosition("spriteX",this.get("spriteX")); +this._setSpritePosition("spriteY",this.get("spriteY"));this.setDirty("backgroundImage");this.setChanged()},getDrawing:function(){return this._oDrawing +},setChanged:function(a){if(this._bChanged||(a&&this._bChangedTransforms)){return}if(this._oLayer!==null){this._oLayer.setChanged() +}if(!a){this._bChanged=true}this._bChangedTransforms=true;if(this._oParent){this._oParent.setChanged(false)}},unsetChanged:function(){this._bChanged=false; +this._bChangedTransforms=false},isChanged:function(a){return !a?(this._bChanged||this._bChangedTransforms):!this._bChanged&&this._bChangedTransforms +},setLayer:function(b){if(this._sId in collie.DisplayObject.htFactory){throw new Error("Exists DisplayObject Id "+this._sId) +}collie.DisplayObject.htFactory[this._sId]=this;var d=this.get();this._oLayer=b;this._makeDrawing();this._oDrawing.load(); +this.setChanged();if(typeof d.x=="string"||typeof d.y=="string"){this.align(typeof d.x=="string"?d.x:false,typeof d.y=="string"?d.y:false) +}if(this._nPositionRight!==null){this.right(this._nPositionRight);this._nPositionRight=null}if(this._nPositionBottom!==null){this.bottom(this._nPositionBottom); +this._nPositionBottom=null}for(var c=0,a=this._aDisplayObjects.length;c=0||j<=a||g+c.height>=0||g<=e))){this._oDrawing.draw(b,j,g,a,e,h) +}this.unsetChanged();this._resetDirty();if(this._sRenderingMode=="canvas"||!this.get("visible")){return}if(this.hasChild()){for(var d=0,f=this._aDisplayObjects.length; +db){do{g-=(b-e) +}while(g>b)}}}else{g=Math.max(e,g);g=Math.min(b,g)}if(g!=c.x){this.set("x",g,true)}}if(c.rangeY){d=c.rangeY[0];a=c.rangeY[1]; +if(c.positionRepeat){if(fa){do{f-=(a-d)}while(f>a)}}}else{f=Math.max(d,f);f=Math.min(a,f) +}if(f!=c.y){this.set("y",f,true)}}},_makeHitAreaBoundary:function(){this._htHitAreaBoundary=collie.util.getBoundary(this.get("hitArea")) +},align:function(f,b,e){if(!this.getLayer()){return}e=e||this.getParent();var d=this.get();var c=0;var a=0;var h=0;var g=0; +if(e){c=e.get("width");a=e.get("height")}else{c=this.getLayer().option("width");a=this.getLayer().option("height")}if(f!==false){h=(f=="right")?c-d.width:c/2-d.width/2; +this.set("x",h)}if(b!==false){g=(b=="bottom")?a-d.height:a/2-d.height/2;this.set("y",g)}},right:function(b){var a=0;if(this._oParent){a=this._oParent.get("width") +}if(!a&&this._oLayer){a=this._oLayer.option("width")}if(a){this.set("x",a-(this._htOption.width+b))}else{this._nPositionRight=b +}return this},bottom:function(b){var a=0;if(this._oParent){a=this._oParent.get("height")}if(!a&&this._oLayer){a=this._oLayer.option("height") +}if(a){this.set("y",a-(this._htOption.height+b))}else{this._nPositionBottom=b}return this},resizeFixedRatio:function(c,b){if(this.getImage()){var a=this.getImage().width; +var d=this.getImage().height;if(c){b=c*(d/a)}else{if(b){c=b*(a/d)}}this.set("width",Math.round(c));this.set("height",Math.round(b)) +}},_setSpritePosition:function(n,f){if(this._elImage){var a=this.getImageSize();var g=this.get();var l=g.width;var m=g.height; +var h=g.spriteLength-1;var k=(a.width/g.width)-1;var j=(a.height/g.height)-1;var c=a.width-1;var b=a.height-1;if(h>=0&&mk&&m0)||(("mousedown" in this._htHandler)&&this._htHandler.mousedown.length>0)||(("mouseup" in this._htHandler)&&this._htHandler.mouseup.length>0)){return true +}else{return false}},move:function(h,f,e,j){var c=this._htOption.x;var b=this._htOption.y;var a=collie.util.getDistance(c,b,h,f); +var d=Math.round((a/e)*1000);if(this._oTimerMove!==null){this._oTimerMove.stop();this._oTimerMove=null}if(!e||d");var d=e.style;d.font=this._getFontText(); +d.color=this._htOption.fontColor;d.padding=this._getPadding().replace(/ /g,"px ")+"px";d.width=this._getMaxWidth()+"px";d.height=this._getMaxHeight()+"px"; +d.lineHeight=this._getLineHeight()+"px";d.textAlign=this._htOption.textAlign;if(this._elText.innerHTML!=b){this._elText.innerHTML=b +}this.unsetChanged();this._getDOMTextWidth();this._triggerGetTextWidth()},_getDOMTextWidth:function(){if(this._elText!==null){this._nTextWidth=this._elText.offsetWidth +}},_getFontText:function(){return this._htOption.fontWeight+" "+(this._htOption.fontSize*this._nRatio)+"px "+this._htOption.fontFamily +},_getLineHeight:function(){return this._htOption.lineHeight=="auto"?(this._htOption.fontSize*this._nRatio):this._htOption.lineHeight*this._nRatio +},_fillTextMultiline:function(d,g,f){var c=this._getPadding("left");var e=this._htOption.ellipsisMaxLine;this._nTextWidth=0; +for(var b=0;b=e-1){if(d.length>e){d[b]=this._insertEllipsisText(d[b]);d.splice(b+1,d.length-(b+1)) +}}var a=this._oContext.measureText(d[b]).width;if(this._htOption.textAlign=="center"){c=this._getMaxWidth()/2-a/2+this._getPadding("left") +}else{if(this._htOption.textAlign=="right"){c=((this._htOption.width*this._nRatio)-this._getPadding("right"))-a}}this._oContext.fillText(d[b],g+c,f+this._getTopPosition(b+1)); +this._nTextWidth=Math.max(this._nTextWidth,a)}},_getMaxWidth:function(){return(this.get("width")*this._nRatio)-(this._getPadding("left")+this._getPadding("right")) +},_getMaxHeight:function(){return(this.get("height")*this._nRatio)-(this._getPadding("top")+this._getPadding("bottom"))},_getTopPosition:function(a){return this._getLineHeight()*(a-1)+this._getPadding("top") +},_getPadding:function(b){var e=this.get("padding")||"0 0 0 0";var c=e.split(" ");for(var d=0,a=c.length;d0;c--){d=b.substr(0,c)+this.get("ellipsisString"); +if(this._oContext.measureText(d).width<=a){return d}}return b},_wordWrap:function(a,d){var c=d||this._sText;var b=1;if(!c){return"" +}d=c.substr(0,1);while(this._oContext.measureText(d).width<=a){b++;if(b>c.length){return d}d=c.substr(0,b);if(c.substr(b-1,1)=="\n"){break +}}b=Math.max(1,b-1);d=c.substr(0,b);if(c.substr(b,1)=="\n"){b++}if(c.length>b){d+="\n"+(this._wordWrap(a,c.substr(b)))}return d +},text:function(a){this._nTextWidth=0;this._aCallbackTextWidth=[];this._sText=a.toString();this.setChanged();return this},getTextWidth:function(a){if(a){this._aCallbackTextWidth.push(a) +}if(this._nTextWidth){this._triggerGetTextWidth();return this._nTextWidth/this._nRatio}},_triggerGetTextWidth:function(){if(this._aCallbackTextWidth.length>0){for(var b=0,a=this._aCallbackTextWidth.length; +bb){this.reset();return}if(this._nFrameAtRunLastest===null){this._nFrameAtRunLastest=b;this._nRunningTime=0; +a=0}this._nRunningTime+=a;this._nCount++;if(this._nRunningTime>=this._nDuration){this._nCountCycle++;if(!this._isEndValue()&&this._htOption.loop&&this._htOption.loop<=this._nCountCycle){this._setEndValue() +}else{if(!this._htOption.loop||this._htOption.loop>this._nCountCycle){this.fireEvent("end");this._nFrameAtRunLastest=b;this._nRunningTime=this._nRunningTime-this._nDuration; +this._nValue=this._htOption.from;this._transitionValue(this._nRunningTime)}else{this.complete();return}}}else{if(this._nRunningTime>0){this._transitionValue(this._nRunningTime) +}}this._htCallback.timer=this;this._htCallback.frame=b;this._htCallback.duration=this._nDuration;this._htCallback.cycle=this._nCountCycle; +this._htCallback.runningTime=this._nRunningTime;this._htCallback.from=this._htOption.from;this._htCallback.to=this._htOption.to; +this._htCallback.value=this._nValue;this.triggerCallback(this._htCallback);if(this._nRunningTime>0){this._nFrameAtRunLastest=b +}},_transitionValue:function(c){if(this._bIsArrayValue){this._nValue=[];for(var b=0,a=this._htOption.from.length;bc){this.reset();return}if(this._nFrameAtRunLastest===null){this._nFrameAtRunLastest=c;this._nRunningTime=0; +this._nRunLastestTime=0;a=0}this._nRunningTime+=a;var b=Math.max(1,Math.floor((this._nRunningTime-this._nRunLastestTime)/this._nDuration))-1; +if(this._nCount===0&&this._nBeforeDelay){if(this._nRunLastestTime+this._nBeforeDelay<=this._nRunningTime){this.reset();this._nBeforeDelay=0 +}return}if(this._nRunningTime===0||this._nRunLastestTime+this._nDuration<=this._nRunningTime){this._nCount+=this._htOption.useRealTime?1+b:1; +this._fCallback({timer:this,frame:c,duration:this._nDuration,count:this._nCount,skippedCount:b,runningTime:this._nRunningTime}); +if(this._htOption.loop&&this._htOption.loop<=this._nCount){this.complete();return}this._nFrameAtRunLastest=c;this._nRunLastestTime=this._nRunningTime +}}},collie.Animation);collie.AnimationCycle=collie.Class({$init:function(b,d,a){this._nFPS=null;this._htCallback={};var c=this._setterFPS.bind(this); +this.optionSetter("valueSet",this._setterValueSet.bind(this));this.optionSetter("to",c);this.optionSetter("from",c);this.option({delay:0,from:0,to:0,step:1,loop:0,set:"spriteX",useRealTime:true,valueSet:null,start:null}); +this.option(a||{});this._nFrameAtRunLastest=null;this._nRunLastestTime=null;this._nRunningTime=null;this.setDuration(d);this.reset() +},reset:function(){this._nCount=0;this._nCountCycle=0;this._nFrameAtRunLastest=null;this._nRunningTime=null;this._nRunLastestTime=null; +this._nValue=(this._htOption.start!==null?this._htOption.start:this._htOption.from)-this._htOption.step},_setterValueSet:function(){var a=this._htOption.valueSet; +if(a&&a instanceof Array){this.option({from:0,to:a.length-1,step:1})}},_setterFPS:function(){if(this._nFPS!==null&&typeof this._htOption.to!="undefined"&&typeof this._htOption.from!="undefined"){var a=(this._htOption.to-this._htOption.from)+1; +this._nDuration=Math.round(1000/this._nFPS*a)}},setDuration:function(a){this._nDuration=parseInt(a,10);if(/fps/i.test(a)&&typeof this._htOption.to!="undefined"&&typeof this._htOption.from!="undefined"){this._nFPS=parseInt(a,10); +this._setterFPS()}else{this._nFPS=null}},setValue:function(a){this._nValue=a},getValue:function(){return this._htOption.valueSet?this._htOption.valueSet[this._nValue]:this._nValue +},run:function(g,e){if(typeof g=="undefined"){g=collie.Renderer.getInfo().frame}if(this._nFrameAtRunLastest>g){this.reset(); +return}if(this._nFrameAtRunLastest===null){this._nFrameAtRunLastest=g;this._nRunLastestTime=0;this._nRunningTime=0;e=0}if(!e){e=0 +}var d=this._htOption;var c=d.to-d.from;this._nTotalCount=c/d.step;this._nTerm=this._nDuration/this._nTotalCount;this._nRunningTime+=e; +var f=(!d.useRealTime)?0:Math.max(1,Math.floor((this._nRunningTime-this._nRunLastestTime)/this._nTerm))-1;if(this._nRunningTime===0||this._nRunLastestTime+this._nTerm<=this._nRunningTime){this._nValue+=(d.step*(1+f)); +this._nCount+=(1+f);if(d.from<=d.to?this._nValue>=d.to:this._nValue<=d.to){var b=(this._nValue-d.to)/d.step;var a=Math.ceil(b/(this._nTotalCount+1)); +b=b%(this._nTotalCount+1);if(b){this._nCountCycle+=a;this._nValue=d.from+(b-1)*d.step}else{this._nCountCycle+=1;this._nValue=d.to +}this.fireEvent("end")}this._htCallback.timer=this;this._htCallback.frame=g;this._htCallback.duration=this._nDuration;this._htCallback.count=this._nCount; +this._htCallback.skippedCount=f;this._htCallback.runningTime=this._nRunningTime;this._htCallback.value=this.getValue();this._htCallback.cycle=this._nCountCycle; +this._htCallback.step=d.step;this._htCallback.from=d.from;this._htCallback.to=d.to;this.triggerCallback(this._htCallback); +if(d.loop&&this._nCountCycle>=d.loop){this.complete();return}this._nFrameAtRunLastest=g;this._nRunLastestTime=this._nRunningTime +}}},collie.Animation);collie.AnimationDelay=collie.Class({$init:function(a,b){this.reset()},reset:function(){this._nFrameAtRunLastest=null; +this._nRunningTime=null;this._nRunLastestTime=null},run:function(b,a){if(b===undefined){b=collie.Renderer.getInfo().frame +}if(this._nFrameAtRunLastest>b){this.reset();return}if(this._nFrameAtRunLastest===null){this._nFrameAtRunLastest=b;this._nRunLastestTime=0; +this._nRunningTime=0;a=0}this._nRunningTime+=a;if(this._nRunLastestTime+this._nDuration<=this._nRunningTime){if(this._fCallback){this._fCallback({timer:this,frame:b,duration:this._nDuration,runningTime:this._nRunningTime}) +}this.complete()}}},collie.Animation);collie.AnimationTimeline=collie.Class({$init:function(d,c){this.option("loop",1);this.option(c||{}); +this.setOptionEvent(c);this._htAnimations={};this._aTimeline=null;this._aRunningAnimation=null;this._nRunningTime=null;this._nCountCycle=0; +if(d){for(var b=0,a=d.length;be){this.reset();return}if(this._nFrameAtRunLastest===null){this._nFrameAtRunLastest=e;this._nRunningTime=0; +d=0}this._nRunningTime+=d;if(this._aTimeline.length>0){while(this._aTimeline[0]<=this._nRunningTime){var c=this._aTimeline.shift(); +for(var b=0,a=this._htAnimations[c].length;b0){for(var b=0;b=this._aAnimations.length){this._nCount++;this.fireEvent("end",{count:this._nCount}); +if(!this._htOption.loop||this._htOption.loop>this._nCount){this._nAnimationIdx=0}else{this.complete();return}}this._aAnimations[this._nAnimationIdx].stop(); +this._aAnimations[this._nAnimationIdx].start()},reset:function(){this._nFrameAtRunLastest=null;this._nAnimationIdx=null;this._nCount=0 +},run:function(b,a){if(this._aAnimations.length<1){return}if(b===undefined){b=collie.Renderer.getInfo().frame}if(this._nFrameAtRunLastest>b){this.reset(); +return}if(this._nFrameAtRunLastest===null){this._nFrameAtRunLastest=b}if(this._nAnimationIdx===null){this.next()}this._aAnimations[this._nAnimationIdx].run(b,a) +}},collie.Animation);collie.TimerList=collie.Class({$init:function(){this._aList=[]},add:function(a){this._aList.unshift(a) +},remove:function(c){for(var b=0,a=this._aList.length;b=0;a--){if(this._aList[a]){if(this._aList[a].isPlaying()){this._aList[a].run(c,b)}else{this._aList.splice(a,1)}}}}});collie.Timer=new (collie.Class({$init:function(){this._oList=new collie.TimerList() +},run:function(b,a){this._oList.run(b,a)},stopAll:function(){this._oList.stopAll()},removeAll:function(){this._oList.removeAll() +},queue:function(c,a){var b=new collie.AnimationQueue(c,a);b.setTimerList(this._oList);return b},repeat:function(b,d,a){var c=new collie.AnimationRepeat(b,d,a); +c.setTimerList(this._oList);return c},transition:function(b,d,a){var c=new collie.AnimationTransition(b,d,a);c.setTimerList(this._oList); +return c},cycle:function(b,d,a){var c=new collie.AnimationCycle(b,d,a);c.setTimerList(this._oList);return c},delay:function(b,d,a){var c=new collie.AnimationDelay(b,d,a); +c.setTimerList(this._oList);return c},timeline:function(b,a){var c=new collie.AnimationTimeline(b,a);c.setTimerList(this._oList); +return c}}))();collie.Renderer=new (collie.Class({DEFAULT_FPS:"60fps",RETINA_DISPLAY:"auto",DEBUG_USE_DELAY:false,DEBUG_MAX_DELAY:200,DEBUG_RENDERING_MODE:"auto",$init:function(){this._sRequestAnimationFrameName=this._getNameAnimationFrame(); +this._sCancelAnimationFrameName=this._getNameAnimationFrame(true);this._bPlaying=false;this._bPause=false;this._nFPS=0;this._nDuration=0; +this._nCurrentFrame=0;this._nSkippedFrame=0;this._nBeforeFrameTime=null;this._nBeforeRenderingTime=0;this._aLayerList=[]; +this._fRender=this._render.bind(this);this._fCallback=null;this._htCallback={};this._elContainer=document.createElement("div"); +this._elContainer.className="_collie_container";this._elContainer.style.position="relative";this._elContainer.style.overflow="hidden"; +this._elParent=null;this._nDebugDelayedTime=0;this._oRenderingTimer=null;this._bLoaded=false;this._sRenderingMode=null;this._bUseRetinaDisplay=null; +this._htEventStatus={};this._htPosition={};this._bIsPreventDefault=true;this._fRefresh=this.refresh.bind(this);collie.util.addEventListener(window,"pageshow",this._onPageShow.bind(this)); +collie.util.addEventListener(window,"pagehide",this._onPageHide.bind(this));collie.util.addEventListener(window,"resize",this._fRefresh) +},_onPageShow:function(){if(!this.isPlaying()&&this._bPause){this.resume()}},_onPageHide:function(){if(this.isPlaying()){this.pause() +}},refresh:function(){if(this._elParent!==null){var e=this._elParent.ownerDocument||this._elParent.document||document;var a=e.documentElement; +var c=e.body;if("getBoundingClientRect" in this._elParent){var b=this._elParent.getBoundingClientRect();this._htPosition.x=b.left; +this._htPosition.x+=a.scrollLeft||c.scrollLeft;this._htPosition.y=b.top;this._htPosition.y+=a.scrollTop||c.scrollTop;this._htPosition.width=b.width; +this._htPosition.height=b.height}else{this._htPosition.x=0;this._htPosition.y=0;this._htPosition.width=this._elParent.offsetWidth; +this._htPosition.height=this._elParent.offsetHeight;for(var d=this._elParent;d;d=d.offsetParent){this._htPosition.x+=d.offsetLeft; +this._htPosition.y+=d.offsetTop}for(var d=this._elParent.parentNode;d;d=d.parentNode){if(d.tagName=="BODY"){break}if(d.tagName=="TR"){this._htPosition.y+=2 +}this._htPosition.x-=d.scrollLeft;this._htPosition.y-=d.scrollTop}}}},getPosition:function(){return this._bLoaded?this._htPosition:false +},addLayer:function(b){if(!b||!("type" in b)||b.type!="layer"){throw new Error("oLayer is not Layer instnace")}for(var c=0,a=this._aLayerList.length; +c=0;a--){this._aLayerList[a].unload() +}this._aLayerList=[]},resetLayerEvent:function(){for(var b=0,a=this._aLayerList.length;b=0;b--){this._aLayerList[b].attachEvent()}},getElement:function(){return this._elContainer +},getDuration:function(){return this._nDuration},getInfo:function(){this._htCallback.frame=this._nCurrentFrame;this._htCallback.skippedFrame=this._nSkippedFrame; +this._htCallback.fps=this._nFPS;this._htCallback.duration=this._nDuration;this._htCallback.renderingTime=this._nBeforeRenderingTime; +this._htCallback.beforeFrameTime=this._nBeforeFrameTime;return this._htCallback},getRenderingMode:function(){if(this._sRenderingMode===null){var a=collie.util.getDeviceInfo(); +this._sRenderingMode=this.DEBUG_RENDERING_MODE;if(!this._sRenderingMode||this._sRenderingMode=="auto"){if((a.android&&(a.android>=3||a.android<2.2))||!a.supportCanvas||(a.ios&&a.ios<5)){this._sRenderingMode="dom" +}else{this._sRenderingMode="canvas"}}if(!a.supportCanvas){this._sRenderingMode="dom"}}return this._sRenderingMode},setRenderingMode:function(a){this.DEBUG_RENDERING_MODE=a.toString().toLowerCase(); +this._sRenderingMode=null},isRetinaDisplay:function(){if(this._bUseRetinaDisplay===null){this._bUseRetinaDisplay=this.RETINA_DISPLAY!="auto"?this.RETINA_DISPLAY:window.devicePixelRatio>=2&&!collie.util.getDeviceInfo().android; +var a=collie.util.getDeviceInfo();if(a.ie&&a.ie<9){this._bUseRetinaDisplay=false}}return this._bUseRetinaDisplay},setRetinaDisplay:function(a){this.RETINA_DISPLAY=a; +this._bUseRetinaDisplay=null},_getNameAnimationFrame:function(b){var d=["","webkit","moz","ms","o"];var e=b?d[c]+(c===0?"c":"C")+"ancelAnimationFrame":d[c]+(c===0?"r":"R")+"equestAnimationFrame"; +for(var c=0,a=d.length;c=0;b--){this._aLayerList[b].attachEvent() +}}},unload:function(){if(this._bLoaded){for(var b=0,a=this._aLayerList.length;b