OSDN Git Service

実ゆっくりに向きを追加。次回は左向きのときの座標あわせを行う。TODO要確認
[yukkurioverwint/YukkuriOverwinter.git] / enchant.js
1 /**
2 * enchant.js v0.7.0
3 * http://enchantjs.com
4 *
5 * Copyright Ubiquitous Entertainment Inc.
6 * Released under the MIT license.
7 */
8
9 (function(window, undefined){
10
11 /**
12  * ECMA-262 5th edition Functions
13  */
14 if (typeof Object.defineProperty !== 'function') {
15     Object.defineProperty = function(obj, prop, desc) {
16         if ('value' in desc) {
17             obj[prop] = desc.value;
18         }
19         if ('get' in desc) {
20             obj.__defineGetter__(prop, desc.get);
21         }
22         if ('set' in desc) {
23             obj.__defineSetter__(prop, desc.set);
24         }
25         return obj;
26     };
27 }
28 if (typeof Object.defineProperties !== 'function') {
29     Object.defineProperties = function(obj, descs) {
30         for (var prop in descs) {
31             if (descs.hasOwnProperty(prop)) {
32                 Object.defineProperty(obj, prop, descs[prop]);
33             }
34         }
35         return obj;
36     };
37 }
38 if (typeof Object.create !== 'function') {
39     Object.create = function(prototype, descs) {
40         function F() {
41         }
42
43         F.prototype = prototype;
44         var obj = new F();
45         if (descs != null) {
46             Object.defineProperties(obj, descs);
47         }
48         return obj;
49     };
50 }
51 if (typeof Object.getPrototypeOf !== 'function') {
52     Object.getPrototypeOf = function(obj) {
53         return obj.__proto__;
54     };
55 }
56
57 if (typeof Function.prototype.bind !== 'function') {
58     Function.prototype.bind = function(thisObject) {
59         var func = this;
60         var args = Array.prototype.slice.call(arguments, 1);
61         var Nop = function() {
62         };
63         var bound = function() {
64             var a = args.concat(Array.prototype.slice.call(arguments));
65             return func.apply(
66                 this instanceof Nop ? this : thisObject || window, a);
67         };
68         Nop.prototype = func.prototype;
69         bound.prototype = new Nop();
70         return bound;
71     };
72 }
73
74 window.getTime = (function() {
75     var origin;
76     if (window.performance && window.performance.now) {
77         origin = Date.now();
78         return function() {
79             return origin + window.performance.now();
80         };
81     } else if (window.performance && window.performance.webkitNow) {
82         origin = Date.now();
83         return function() {
84             return origin + window.performance.webkitNow();
85         };
86     } else {
87         return Date.now;
88     }
89 }());
90
91 /**
92  * define requestAnimationFrame
93  */
94 window.requestAnimationFrame =
95     window.requestAnimationFrame ||
96     window.mozRequestAnimationFrame ||
97     window.webkitRequestAnimationFrame ||
98     window.msRequestAnimationFrame ||
99     (function() {
100         var lastTime = window.getTime();
101         var frame = 1000 / 60;
102         return function(func) {
103             var _id = setTimeout(function() {
104                 lastTime = window.getTime();
105                 func(lastTime);
106             }, Math.max(0, lastTime + frame - window.getTime()));
107             return _id;
108         };
109     }());
110
111 /**
112  [lang:ja]
113  * グローバルにライブラリのクラスをエクスポートする.
114  *
115  * 引数に何も渡さない場合enchant.jsで定義されたクラス及びプラグインで定義されたクラス
116  * 全てがエクスポートされる. 引数が一つ以上の場合はenchant.jsで定義されたクラスのみ
117  * がデフォルトでエクスポートされ, プラグインのクラスをエクスポートしたい場合は明示的に
118  * プラグインの識別子を引数として渡す必要がある.
119  *
120  * @example
121  *   enchant();     // 全てのクラスがエクスポートされる
122  *   enchant('');   // enchant.js本体のクラスのみがエクスポートされる
123  *   enchant('ui'); // enchant.js本体のクラスとui.enchant.jsのクラスがエクスポートされる
124  *
125  * @param {...String} [modules] エクスポートするモジュール. 複数指定できる.
126  [/lang]
127  [lang:en]
128  * Export the library classes globally.
129  *
130  * When no arguments are given, all classes defined in enchant.js as well as all classes defined in
131  * plugins will be exported. When more than one argument is given, by default only classes defined
132  * in enchant.js will be exported. When you wish to export plugin classes you must explicitly deliver
133  * the plugin identifiers as arguments.
134  *
135  * @example
136  *   enchant();     // All classes will be exported.
137  *   enchant('');   // Only classes in enchant.js will be exported.
138  *   enchant('ui'); // enchant.js classes and ui.enchant.js classes will be exported.
139  *
140  * @param {...String} [modules] Export module. Multiple designations possible.
141  [/lang]
142  [lang:de]
143  * Globaler Export der Programmbibliotheken.
144  *
145  * Wenn keine Argument übergeben werden, werden alle Klassen die in enchant.js und in den Plugins
146  * definiert sind exportiert. Falls mehr als ein Argument übergeben wurde, werden standardmäßig nur Klassen
147  * die in enchant.js selbst definiert sind exporitert. Wenn auch Plugin Klassen exportiert werden sollen,
148  * müssen die Plugin Bezeichner explizit als Argumente übergeben werden.
149  *
150  * @example
151  *   enchant();     // alle Klassen werden exportiert.
152  *   enchant('');   // nur Klassen die in enchant.js definiert sind werden exportiert.
153  *   enchant('ui'); // enchant.js Klassen und ui.enchant.js Klassen werden exportiert.
154  *
155  * @param {...String} [modules] Module die exportiert werden sollen.
156  [/lang]
157  * @global
158  * @type {Object}
159  * @name enchant
160  */
161 var enchant = function(modules) {
162     if (modules != null) {
163         if (!(modules instanceof Array)) {
164             modules = Array.prototype.slice.call(arguments);
165         }
166         modules = modules.filter(function(module) {
167             return [module].join();
168         });
169     }
170     (function include(module, prefix) {
171         var submodules = [],
172             i, len;
173         for (var prop in module) {
174             if (module.hasOwnProperty(prop)) {
175                 if (typeof module[prop] === 'function') {
176                     window[prop] = module[prop];
177                 } else if (typeof module[prop] === 'object' && module[prop] !== null && Object.getPrototypeOf(module[prop]) === Object.prototype) {
178                     if (modules == null) {
179                         submodules.push(prop);
180                     } else {
181                         i = modules.indexOf(prefix + prop);
182                         if (i !== -1) {
183                             submodules.push(prop);
184                             modules.splice(i, 1);
185                         }
186                     }
187                 }
188             }
189         }
190
191         for (i = 0, len = submodules.length; i < len; i++) {
192             include(module[submodules[i]], prefix + submodules[i] + '.');
193         }
194     }(enchant, ''));
195
196     // issue 185
197     if (enchant.Class.getInheritanceTree(window.Game).length <= enchant.Class.getInheritanceTree(window.Core).length) {
198         window.Game = window.Core;
199     }
200
201     if (modules != null && modules.length) {
202         throw new Error('Cannot load module: ' + modules.join(', '));
203     }
204 };
205
206 /**
207  * export enchant
208  */
209 window.enchant = enchant;
210
211 window.addEventListener("message", function(msg, origin) {
212     try {
213         var data = JSON.parse(msg.data);
214         if (data.type === "event") {
215             enchant.Core.instance.dispatchEvent(new enchant.Event(data.value));
216         } else if (data.type === "debug") {
217             switch (data.value) {
218                 case "start":
219                     enchant.Core.instance.start();
220                     break;
221                 case "pause":
222                     enchant.Core.instance.pause();
223                     break;
224                 case "resume":
225                     enchant.Core.instance.resume();
226                     break;
227                 case "tick":
228                     enchant.Core.instance._tick();
229                     break;
230                 default:
231                     break;
232             }
233         }
234     } catch (e) {
235         // ignore
236     }
237 }, false);
238
239 /**
240  * @name enchant.Class
241  * @class
242  [lang:ja]
243  * クラスのクラス.
244  *
245  * @param {Function} [superclass] 継承するクラス.
246  * @param {*} definition クラス定義.
247  [/lang]
248  [lang:en]
249  * A Class representing a class which supports inheritance.
250  *
251  * @param {Function} [superclass] The class from which the
252  * new class will inherit the class definition.
253  * @param {*} definition Class definition.
254  [/lang]
255  [lang:de]
256  * Eine Klasse für Klassen, die Vererbung unterstützen.
257  *
258  * @param {Function} [superclass] Die Klasse, deren Klassendefinition
259  * die neue Klasse erben wird.
260  * @param {*} definition Klassendefinition.
261  [/lang]
262  * @constructor
263  */
264 enchant.Class = function(superclass, definition) {
265     return enchant.Class.create(superclass, definition);
266 };
267
268 /**
269  [lang:ja]
270  * クラスを作成する.
271  *
272  * ほかのクラスを継承したクラスを作成する場合, コンストラクタはデフォルトで
273  * 継承元のクラスのものが使われる. コンストラクタをオーバーライドする場合継承元の
274  * コンストラクタを適用するには明示的に呼び出す必要がある.
275  *
276  * @example
277  *   var Ball = Class.create({ // 何も継承しないクラスを作成する
278  *       initialize: function(radius) { ... }, // メソッド定義
279  *       fall: function() { ... }
280  *   });
281  *
282  *   var Ball = Class.create(Sprite);  // Spriteを継承したクラスを作成する
283  *   var Ball = Class.create(Sprite, { // Spriteを継承したクラスを作成する
284  *       initialize: function(radius) { // コンストラクタを上書きする
285  *          Sprite.call(this, radius*2, radius*2); // 継承元のコンストラクタを適用する
286  *          this.image = core.assets['ball.gif'];
287  *       }
288  *   });
289  *
290  * @param {Function} [superclass] 継承するクラス.
291  * @param {*} [definition] クラス定義.
292  [/lang]
293  [lang:en]
294  * Create a class.
295  *
296  * When defining classes that inherit from other classes, the previous class is used as a base with
297  * the superclass's constructor as default. When overriding the default constructor, it is necessary
298  * to explicitly call the previous constructor to ensure a correct class initialization.
299  *
300  * @example
301  *   var Ball = Class.create({ // Creates independent class.
302  *       initialize: function(radius) { ... }, // Method definition.
303  *       fall: function() { ... }
304  *   });
305  *
306  *   var Ball = Class.create(Sprite);  // Creates a class inheriting from "Sprite"
307  *   var Ball = Class.create(Sprite, { // Creates a class inheriting "Sprite"
308  *       initialize: function(radius) { // Overwrites constructor
309  *          Sprite.call(this, radius*2, radius*2); // Applies previous constructor.
310  *          this.image = core.assets['ball.gif'];
311  *       }
312  *   });
313  *
314  * @param {Function} [superclass] The class from which the
315  * new class will inherit the class definition.
316  * @param {*} [definition] Class definition.
317  [/lang]
318  [lang:de]
319  * Erstellt eine neue Klasse
320  *
321  * Wenn eine Klasse definiert wird, die von einer anderen Klasse erbt, wird der Konstruktor der
322  * Basisklasse als Standard definiert. Sollte dieser Konstruktor in der neuen Klasse überschrieben
323  * werden, sollte der vorherige Konstruktor explizit aufgerufen werden, um eine korrekte
324  * Klasseninitialisierung sicherzustellen.
325  *
326  * @example
327  *   var Ball = Class.create({ // definiert eine unabhängige Klasse.
328  *       initialize: function(radius) { ... }, // Methodendefinitionen
329  *       fall: function() { ... }
330  *   });
331  *
332  *   var Ball = Class.create(Sprite);  // definiert eine Klasse die von "Sprite" erbt.
333  *   var Ball = Class.create(Sprite, { // definiert eine Klasse die von "Sprite" erbt.
334  *       initialize: function(radius) { // überschreibt den Standardkonstruktor.
335  *          Sprite.call(this, radius*2, radius*2); // Aufruf des Konstruktors der Basisklasse.
336  *          this.image = core.assets['ball.gif'];
337  *       }
338  *   });
339  *
340  * @param {Function} [superclass] The class from which the
341  * new class will inherit the class definition.
342  * @param {*} [definition] Class definition.
343  [/lang]
344  [lang:de]
345  * Erstellt eine neue Klasse
346  *
347  * Wenn eine Klasse definiert wird, die von einer anderen Klasse erbt, wird der Konstruktor der
348  * Basisklasse als Standard definiert. Sollte dieser Konstruktor in der neuen Klasse überschrieben
349  * werden, sollte der vorherige Konstruktor explizit aufgerufen werden, um eine korrekte
350  * Klasseninitialisierung sicherzustellen.
351  * 
352  * @example
353  *   var Ball = Class.create({ // definiert eine unabhängige Klasse.
354  *       initialize: function(radius) { ... }, // Methodendefinitionen
355  *       fall: function() { ... }
356  *   });
357  *
358  *   var Ball = Class.create(Sprite);  // definiert eine Klasse die von "Sprite" erbt.
359  *   var Ball = Class.create(Sprite, { // definiert eine Klasse die von "Sprite" erbt.
360  *       initialize: function(radius) { // überschreibt den Standardkonstruktor.
361  *          Sprite.call(this, radius*2, radius*2); // Aufruf des Konstruktors der Basisklasse.
362  *          this.image = core.assets['ball.gif'];
363  *       }
364  *   });
365  *
366  * @param {Function} [superclass] Die Klasse, deren Klassendefinition
367  * die neue Klasse erben wird.
368  * @param {*} definition Klassendefinition.
369  [/lang]
370  * @static
371  */
372 enchant.Class.create = function(superclass, definition) {
373     if (superclass == null && definition){
374         throw new Error("superclass is undefined (enchant.Class.create)");
375     }else if(superclass == null){
376         throw new Error("definition is undefined (enchant.Class.create)");
377     }
378
379     if (arguments.length === 0) {
380         return enchant.Class.create(Object, definition);
381     } else if (arguments.length === 1 && typeof arguments[0] !== 'function') {
382         return enchant.Class.create(Object, arguments[0]);
383     }
384
385     for (var prop in definition) {
386         if (definition.hasOwnProperty(prop)) {
387             if (typeof definition[prop] === 'object' && definition[prop] !== null && Object.getPrototypeOf(definition[prop]) === Object.prototype) {
388                 if (!('enumerable' in definition[prop])) {
389                     definition[prop].enumerable = true;
390                 }
391             } else {
392                 definition[prop] = { value: definition[prop], enumerable: true, writable: true };
393             }
394         }
395     }
396     var Constructor = function() {
397         if (this instanceof Constructor) {
398             Constructor.prototype.initialize.apply(this, arguments);
399         } else {
400             return new Constructor();
401         }
402     };
403     Constructor.prototype = Object.create(superclass.prototype, definition);
404     Constructor.prototype.constructor = Constructor;
405     if (Constructor.prototype.initialize == null) {
406         Constructor.prototype.initialize = function() {
407             superclass.apply(this, arguments);
408         };
409     }
410
411     var tree = this.getInheritanceTree(superclass);
412     for (var i = 0, l = tree.length; i < l; i++) {
413         if (typeof tree[i]._inherited === 'function') {
414             tree[i]._inherited(Constructor);
415             break;
416         }
417     }
418
419     return Constructor;
420 };
421
422 /**
423  [lang:ja]
424  * クラスの継承関係を取得する.
425  [/lang]
426  [lang:en]
427  * Get the inheritance tree of this class.
428  [/lang]
429  * @param {ConstructorFunction}
430  * @return {...ConstructorFunction}
431  */
432 enchant.Class.getInheritanceTree = function(Constructor) {
433     var ret = [];
434     var C = Constructor;
435     var proto = C.prototype;
436     while (C !== Object) {
437         ret.push(C);
438         proto = Object.getPrototypeOf(proto);
439         C = proto.constructor;
440     }
441     return ret;
442 };
443
444 /**
445  * @namespace
446  [lang:ja]
447  * enchant.js の環境変数.
448  * new Core() を呼ぶ前に変更することで変更することで, 動作設定を変えることができる.
449  [/lang]
450  [lang:en]
451  * enchant.js environment variables.
452  * Execution settings can be changed by modifying these before calling new Core().
453  [/lang]
454  [lang:de]
455  * Umgebungsvariable.
456  [/lang]
457  * @type {Object}
458  */
459 enchant.ENV = {
460     /**
461      [lang:ja]
462      * enchant.js のバージョン.
463      * @type {String}
464      [/lang]
465      [lang:en]
466      * Version of enchant.js
467      * @type {String}
468      [/lang]
469      [lang:de]
470      * Version of enchant.js
471      * @type {String}
472      [/lang]
473      */
474     VERSION: "0.6.1",
475     /**
476      * The CSS vendor prefix of the current browser.
477      * @type {String}
478      */
479     VENDOR_PREFIX: (function() {
480         var ua = navigator.userAgent;
481         if (ua.indexOf('Opera') !== -1) {
482             return 'O';
483         } else if (ua.indexOf('MSIE') !== -1) {
484             return 'ms';
485         } else if (ua.indexOf('WebKit') !== -1) {
486             return 'webkit';
487         } else if (navigator.product === 'Gecko') {
488             return 'Moz';
489         } else {
490             return '';
491         }
492     }()),
493     /**
494      * Determines if the current browser supports touch.
495      * @type {Boolean} True, if touch is enabled.
496      */
497     TOUCH_ENABLED: (function() {
498         var div = document.createElement('div');
499         div.setAttribute('ontouchstart', 'return');
500         return typeof div.ontouchstart === 'function';
501     }()),
502     /**
503      * Determines if the current browser is an iPhone with a retina display.
504      * @return {Boolean} True, if this display is a retina display
505      */
506     RETINA_DISPLAY: (function() {
507         if (navigator.userAgent.indexOf('iPhone') !== -1 && window.devicePixelRatio === 2) {
508             var viewport = document.querySelector('meta[name="viewport"]');
509             if (viewport == null) {
510                 viewport = document.createElement('meta');
511                 document.head.appendChild(viewport);
512             }
513             viewport.setAttribute('content', 'width=640');
514             return true;
515         } else {
516             return false;
517         }
518     }()),
519     /**
520      * Determines if Flash should be used to play sound instead of the
521      * native audio class, given the current browser.
522      * @type {Boolean} True, if flash should be used.
523      */
524     USE_FLASH_SOUND: (function() {
525         var ua = navigator.userAgent;
526         var vendor = navigator.vendor || "";
527         // non-local access, not on mobile mobile device, not on safari
528         return (location.href.indexOf('http') === 0 && ua.indexOf('Mobile') === -1 && vendor.indexOf('Apple') !== -1);
529     }()),
530     /**
531      * If click/touch event occurs for these tags the setPreventDefault() method will not be called.
532      */
533     USE_DEFAULT_EVENT_TAGS: ['input', 'textarea', 'select', 'area'],
534     CANVAS_DRAWING_METHODS: [
535         'putImageData', 'drawImage', 'drawFocusRing', 'fill', 'stroke',
536         'clearRect', 'fillRect', 'strokeRect', 'fillText', 'strokeText'
537     ],
538     /**
539      * Keybind Table.
540      * You can use 'left', 'up', 'right', 'down', 'a', or 'b' for preset events.
541      * @example
542      * enchant.ENV.KEY_BIND_TABLE = {
543      *    37: 'left',
544      *    38: 'up',
545      *    39: 'right',
546      *    40: 'down',
547      *    32: 'a', //-> use 'space' key as 'a button'
548      * }
549      * The default key bindings only bind 'left', 'up', 'right', and 'down' to the arrow keys.
550      */
551     KEY_BIND_TABLE: {
552         37: 'left',
553         38: 'up',
554         39: 'right',
555         40: 'down'
556     },
557     PREVENT_DEFAULT_KEY_CODES: [37, 38, 39, 40, 32],
558     /**
559      * @type {Boolean}
560      */
561     SOUND_ENABLED_ON_MOBILE_SAFARI: false,
562     /**
563      * Determines if WebAudioAPI is enabled.
564      * (true: use WebAudioAPI instead of Audio element if possible)
565      */
566     USE_WEBAUDIO: (function(){
567         return location.protocol !== 'file:';
568     }()),
569     /**
570      * Determines if animation feature is enabled.
571      * (true: Timeline instance will be generated for every new Node)
572      */
573     USE_ANIMATION: true
574 };
575
576 /**
577  * @scope enchant.Event.prototype
578  */
579 enchant.Event = enchant.Class.create({
580     /**
581      * @name enchant.Event
582      * @class
583      [lang:ja]
584      * DOM Event風味の独自イベント実装を行ったクラス.
585      * ただしフェーズの概念はなし.
586      * @param {String} type Eventのタイプ
587      [/lang]
588      [lang:en]
589      * A class for an independent implementation of events similar to DOM Events.
590      * Does not include phase concepts.
591      * @param {String} type Event type.
592      [/lang]
593      [lang:de]
594      * Eine Klasse für eine unabhängige Implementierung von Ereignissen 
595      * (Events), ähnlich wie DOM Events.
596      * Jedoch wird das Phasenkonzept nicht unterstützt.
597      * @param {String} type Event Typ.
598      [/lang]
599      * @constructs
600      */
601     initialize: function(type) {
602         /**
603          [lang:ja]
604          * イベントのタイプ.
605          [/lang]
606          [lang:en]
607          * The type of the event.
608          [/lang]
609          [lang:de]
610          * Typ des Ereignis.
611          [/lang]
612          * @type {String}
613          */
614         this.type = type;
615         /**
616          [lang:ja]
617          * イベントのターゲット.
618          [/lang]
619          [lang:en]
620          * The target of the event.
621          [/lang]
622          [lang:de]
623          * Ziel des Ereignis.
624          [/lang]
625          * @type {*}
626          */
627         this.target = null;
628         /**
629          [lang:ja]
630          * イベント発生位置のx座標.
631          [/lang]
632          [lang:en]
633          * The x-coordinate of the event's occurrence.
634          [/lang]
635          [lang:de]
636          * X Koordinate des Auftretens des Ereignis.
637          [/lang]
638          * @type {Number}
639          */
640         this.x = 0;
641         /**
642          [lang:ja]
643          * イベント発生位置のy座標.
644          [/lang]
645          [lang:en]
646          * The y-coordinate of the event's occurrence.
647          [/lang]
648          [lang:de]
649          * Y Koordinate des Auftretens des Ereignis.
650          [/lang]
651          * @type {Number}
652          */
653         this.y = 0;
654         /**
655          [lang:ja]
656          * イベントを発行したオブジェクトを基準とするイベント発生位置のx座標.
657          [/lang]
658          [lang:en]
659          * The x-coordinate of the event's occurrence relative to the object
660          * which issued the event.
661          [/lang]
662          [lang:de]
663          * X Koordinate des lokalen Koordinatensystems des Auftretens des Ereignis.
664          [/lang]
665          * @type {Number}
666          */
667         this.localX = 0;
668         /**
669          [lang:ja]
670          * イベントを発行したオブジェクトを基準とするイベント発生位置のy座標.
671          [/lang]
672          [lang:en]
673          * The y-coordinate of the event's occurrence relative to the object
674          * which issued the event.
675          [/lang]
676          [lang:de]
677          * Y Koordinate des lokalen Koordinatensystems des Auftretens des Ereignis.
678          [/lang]
679          * @type {Number}
680          */
681         this.localY = 0;
682     },
683     _initPosition: function(pageX, pageY) {
684         var core = enchant.Core.instance;
685         this.x = this.localX = (pageX - core._pageX) / core.scale;
686         this.y = this.localY = (pageY - core._pageY) / core.scale;
687     }
688 });
689
690 /**
691  [lang:ja]
692  * Coreのロード完了時に発生するイベント.
693  *
694  * 画像のプリロードを行う場合ロードが完了するのを待ってゲーム開始時の処理を行う必要がある.
695  * 発行するオブジェクト: {@link enchant.Core}
696  *
697  * @example
698  *   var core = new Core(320, 320);
699  *   core.preload('player.gif');
700  *   core.onload = function() {
701  *      ... // ゲーム開始時の処理を記述
702  *   };
703  *   core.start();
704  *
705  [/lang]
706  [lang:en]
707  * An event dispatched once the core has finished loading.
708  *
709  * When preloading images, it is necessary to wait until preloading is complete
710  * before starting the game.
711  * Issued by: {@link enchant.Core}
712  *
713  * @example
714  *   var core = new Core(320, 320);
715  *   core.preload('player.gif');
716  *   core.onload = function() {
717  *      ... // Description of initial core processing
718  *   };
719  *   core.start();
720  *
721  [/lang]
722  [lang:de]
723  * Ereignis, dass auftritt wenn das Laden des Spieles abgeschlossen wurde.
724  *
725  * Wenn Grafiken im voraus geladen werden ist es notwendig, auf dieses Ereignis zu warten bis mit
726  * diesen gearbeitet werden kann. 
727  * Objekt des Auftretens: {@link enchant.Core}
728  *
729  * @example
730  *   var core = new Core(320, 320);
731  *   core.preload('player.gif');
732  *   core.onload = function() {
733  *      ... // initialisierung des Spieles 
734  *   };
735  *   core.start();
736  *
737  [/lang]
738  * @type {String}
739  */
740 enchant.Event.LOAD = 'load';
741
742 /**
743  [lang:ja]
744  * エラーの発生をCoreに伝える際に発生するイベント.
745  * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Surface}, {@link enchant.WebAudioSound}, {@link enchant.DOMSound}
746  [/lang]
747  [lang:en]
748  * An event dispatched when an error occurs.
749  * Issued by: {@link enchant.Core}, {@link enchant.Surface}, {@link enchant.WebAudioSound}, {@link enchant.DOMSound}
750  [/lang]
751  */
752 enchant.Event.ERROR = 'error';
753
754 /**
755  [lang:ja]
756  * 表示サイズが変わったときに発生するイベント.
757  * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
758  [/lang]
759  [lang:en]
760  * An event dispatched when the display size is changed.
761  * Issued by: {@link enchant.Core}, {@link enchant.Scene}
762  [/lang]
763  @type {String}
764  */
765 enchant.Event.CORE_RESIZE = 'coreresize';
766
767 /**
768  [lang:ja]
769  * Coreのロード進行中に発生するイベント.
770  * プリロードする画像が一枚ロードされる度に発行される. 発行するオブジェクト: {@link enchant.LoadingScene}
771  [/lang]
772  [lang:en]
773  * An event dispatched while the core is loading.
774  * Dispatched each time an image is preloaded. Issued by: {@link enchant.LoadingScene}
775  [/lang]
776  [lang:de]
777  * Ereignis, welches während des Ladens des Spieles auftritt.
778  * Das Ereignis tritt jedesmal auf, wenn eine im voraus geladene Grafik geladen wurde.
779  * Objekt des Auftretens: {@link enchant.LoadingScene}
780  [/lang]
781  * @type {String}
782  */
783 enchant.Event.PROGRESS = 'progress';
784
785 /**
786  [lang:ja]
787  * フレーム開始時に発生するイベント.
788  * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Node}
789  [/lang]
790  [lang:en]
791  * An event dispatched when a new frame is being processed.
792  * Issued by: {@link enchant.Core}, {@link enchant.Node}
793  [/lang]
794  [lang:de]
795  * Ereignis, welches auftritt wenn ein neuer Frame bearbeitet wird.
796  * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Node}
797  [/lang]
798  * @type {String}
799  */
800 enchant.Event.ENTER_FRAME = 'enterframe';
801
802 /**
803  [lang:ja]
804  * フレーム終了時に発生するイベント.
805  * 発行するオブジェクト: {@link enchant.Core}
806  [/lang]
807  [lang:en]
808  * An event dispatched when frame processing is about to end.
809  * Issued by: {@link enchant.Core}
810  [/lang]
811  [lang:de]
812  * Ereignis, welches auftritt wenn ein Frame beendet wird.
813  * Objekt des Auftretens: {@link enchant.Core}
814  [/lang]
815  * @type {String}
816  */
817 enchant.Event.EXIT_FRAME = 'exitframe';
818
819 /**
820  [lang:ja]
821  * Sceneが開始したとき発生するイベント.
822  * 発行するオブジェクト: {@link enchant.Scene}
823  [/lang]
824  [lang:en]
825  * An event dispatched when a Scene begins.
826  * Issued by: {@link enchant.Scene}
827  [/lang]
828  [lang:de]
829  * Ereignis, dass auftritt wenn eine neue Szene
830  * ({@link enchant.Scene}) beginnt.
831  * Objekt des Auftretens: {@link enchant.Scene}
832  [/lang]
833  * @type {String}
834  */
835 enchant.Event.ENTER = 'enter';
836
837 /**
838  [lang:ja]
839  * Sceneが終了したとき発生するイベント.
840  * 発行するオブジェクト: {@link enchant.Scene}
841  [/lang]
842  [lang:en]
843  * An event dispatched when a Scene ends.
844  * Issued by: {@link enchant.Scene}
845  [/lang]
846  [lang:de]
847  * Ereignis, dass auftritt wenn eine Szene
848  * ({@link enchant.Scene}) endet.
849  * Objekt des Auftretens: {@link enchant.Scene}
850  [/lang]
851  * @type {String}
852  */
853 enchant.Event.EXIT = 'exit';
854
855 /**
856  [lang:ja]
857  * Nodeに子が追加されたとき発生するイベント.
858  * 発行するオブジェクト: {@link enchant.Group}, {@link enchant.Scene}
859  [/lang]
860  [lang:en]
861  * An event dispatched when a Child has been added to a Node.
862  * Issued by: {@link enchant.Group}, {@link enchant.Scene}
863  [/lang]
864  [lang:de]
865  * Ereignis, welchses auftritt wenn ein Kindelement zu einem Node
866  * hinzugefügt wird.
867  * Objekt des Auftretens: {@link enchant.Group}, {@link enchant.Scene}
868  [/lang]
869  * @type {String}
870  */
871 enchant.Event.CHILD_ADDED = 'childadded';
872
873 /**
874  [lang:ja]
875  * NodeがGroupに追加されたとき発生するイベント.
876  * 発行するオブジェクト: {@link enchant.Node}
877  [/lang]
878  [lang:en]
879  * An event dispatched when a Node has been added to a Group.
880  * Issued by: {@link enchant.Node}
881  [/lang]
882  [lang:de]
883  * Ereignis, welchses auftritt wenn der Node zu einer Gruppe
884  * hinzugefügt wird.
885  * Objekt des Auftretens: {@link enchant.Node}
886  [/lang]
887  * @type {String}
888  */
889 enchant.Event.ADDED = 'added';
890
891 /**
892  [lang:ja]
893  * NodeがSceneに追加されたとき発生するイベント.
894  * 発行するオブジェクト: {@link enchant.Node}
895  [/lang]
896  [lang:en]
897  * An event dispatched when a Node has been added to a Scene.
898  * Issued by: {@link enchant.Node}
899  [/lang]
900  [lang:de]
901  * Ereignis, welchses auftritt wenn der Node zu einer Szene
902  * hinzugefügt wird.
903  * Objekt des Auftretens: {@link enchant.Node}
904  [/lang]
905  * @type {String}
906  */
907 enchant.Event.ADDED_TO_SCENE = 'addedtoscene';
908
909 /**
910  [lang:ja]
911  * Nodeから子が削除されたとき発生するイベント.
912  * 発行するオブジェクト: {@link enchant.Group}, {@link enchant.Scene}
913  * @type {String}
914  [/lang]
915  [lang:en]
916  * An event dispatched when a Child has been removed from a Node.
917  * Issued by: {@link enchant.Group}, {@link enchant.Scene}
918  * @type {String}
919  [/lang]
920  [lang:de]
921  * Ereignis, welchses auftritt wenn ein Kindelement von einem Node
922  * entfernt wird.
923  * Objekt des Auftretens: {@link enchant.Group}, {@link enchant.Scene}
924  [/lang]
925  * @type {String}
926  */
927 enchant.Event.CHILD_REMOVED = 'childremoved';
928
929 /**
930  [lang:ja]
931  * NodeがGroupから削除されたとき発生するイベント.
932  * 発行するオブジェクト: {@link enchant.Node}
933  [/lang]
934  [lang:en]
935  * An event dispatched when a Node has been deleted from a Group.
936  * Issued by: {@link enchant.Node}
937  [/lang]
938  [lang:de]
939  * Ereignis, welchses auftritt wenn der Node aus einer Gruppe
940  * entfernt wird.
941  * Objekt des Auftretens: {@link enchant.Node}
942  [/lang]
943  * @type {String}
944  */
945 enchant.Event.REMOVED = 'removed';
946
947 /**
948  [lang:ja]
949  * NodeがSceneから削除されたとき発生するイベント.
950  * 発行するオブジェクト: {@link enchant.Node}
951  [/lang]
952  [lang:en]
953  * An event dispatched when a Node has been deleted from a Scene.
954  * Issued by: {@link enchant.Node}
955  [/lang]
956  [lang:de]
957  * Ereignis, welchses auftritt wenn der Node aus einer Szene
958  * entfernt wird.
959  * Objekt des Auftretens: {@link enchant.Node}
960  [/lang]
961  * @type {String}
962  */
963 enchant.Event.REMOVED_FROM_SCENE = 'removedfromscene';
964
965 /**
966  [lang:ja]
967  * Nodeに対するタッチが始まったとき発生するイベント.
968  * クリックもタッチとして扱われる. 発行するオブジェクト: {@link enchant.Node}
969  [/lang]
970  [lang:en]
971  * An event dispatched when a touch event intersecting the Node has begun.
972  * A mouse event counts as a touch event. Issued by: {@link enchant.Node}
973  [/lang]
974  [lang:de]
975  * Ereignis, welchses auftritt wenn ein Touch auf einen Node
976  * beginnt. Klicks werden als Touch behandelt.
977  * Objekt des Auftretens: {@link enchant.Node}
978  [/lang]
979  * @type {String}
980  */
981 enchant.Event.TOUCH_START = 'touchstart';
982
983 /**
984  [lang:ja]
985  * Nodeに対するタッチが移動したとき発生するイベント.
986  * クリックもタッチとして扱われる. 発行するオブジェクト: {@link enchant.Node}
987  [/lang]
988  [lang:en]
989  * An event dispatched when a touch event intersecting the Node has been moved.
990  * A mouse event counts as a touch event. Issued by: {@link enchant.Node}
991  [/lang]
992  [lang:de]
993  * Ereignis, welchses auftritt wenn ein Touch auf einen Node
994  * bewegt wurde. Klicks werden als Touch behandelt.
995  * Objekt des Auftretens: {@link enchant.Node}
996  [/lang]
997  * @type {String}
998  */
999 enchant.Event.TOUCH_MOVE = 'touchmove';
1000
1001 /**
1002  [lang:ja]
1003  * Nodeに対するタッチが終了したとき発生するイベント.
1004  * クリックもタッチとして扱われる. 発行するオブジェクト: {@link enchant.Node}
1005  [/lang]
1006  [lang:en]
1007  * An event dispatched when a touch event intersecting the Node has ended.
1008  * A mouse event counts as a touch event. Issued by: {@link enchant.Node}
1009  [/lang]
1010  [lang:de]
1011  * Ereignis, welchses auftritt wenn ein Touch auf einen Node
1012  * endet. Klicks werden als Touch behandelt.
1013  * Objekt des Auftretens: {@link enchant.Node}
1014  [/lang]
1015  * @type {String}
1016  */
1017 enchant.Event.TOUCH_END = 'touchend';
1018
1019 /**
1020  [lang:ja]
1021  * Entityがレンダリングされるときに発生するイベント.
1022  * 発行するオブジェクト: {@link enchant.Entity}
1023  [/lang]
1024  [lang:en]
1025  * An event dispatched when an Entity has been rendered.
1026  * Issued by: {@link enchant.Entity}
1027  [/lang]
1028  [lang:de]
1029  * Ereignis, welchses auftritt wenn eine Entity
1030  * gerendert wird.
1031  * Objekt des Auftretens: {@link enchant.Entity}
1032  [/lang]
1033  * @type {String}
1034  */
1035 enchant.Event.RENDER = 'render';
1036
1037 /**
1038  [lang:ja]
1039  * ボタン入力が始まったとき発生するイベント.
1040  * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1041  [/lang]
1042  [lang:en]
1043  * An event dispatched when any button has been pressed.
1044  * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1045  [/lang]
1046  [lang:de]
1047  * Ereignis, welchses auftritt wenn ein Knopf gedückt wird.
1048  * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1049  [/lang]
1050  * @type {String}
1051  */
1052 enchant.Event.INPUT_START = 'inputstart';
1053
1054 /**
1055  [lang:ja]
1056  * ボタン入力が変化したとき発生するイベント.
1057  * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1058  [/lang]
1059  [lang:en]
1060  * An event dispatched when button inputs have changed.
1061  * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1062  [/lang]
1063  [lang:de]
1064  * Ereignis, welchses auftritt wenn eine Knopfeingabe verändert wird.
1065  * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1066  [/lang]
1067  * @type {String}
1068  */
1069 enchant.Event.INPUT_CHANGE = 'inputchange';
1070
1071 /**
1072  [lang:ja]
1073  * ボタン入力が終了したとき発生するイベント.
1074  * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1075  [/lang]
1076  [lang:en]
1077  * An event dispatched when all button inputs have ended.
1078  * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1079  [/lang]
1080  [lang:de]
1081  * Ereignis, welchses auftritt wenn eine Knopf losgelassen wird.
1082  * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1083  [/lang]
1084  * @type {String}
1085  */
1086 enchant.Event.INPUT_END = 'inputend';
1087
1088 /**
1089  [lang:ja]
1090  * leftボタンが押された発生するイベント.
1091  * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1092  [/lang]
1093  [lang:en]
1094  * An event dispatched when the 'left' button is pressed.
1095  * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1096  [/lang]
1097  [lang:de]
1098  * Ereignis, welchses auftritt wenn der "Nach Links"-Knopf gedrückt wird.
1099  * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1100  [/lang]
1101  * @type {String}
1102  */
1103 enchant.Event.LEFT_BUTTON_DOWN = 'leftbuttondown';
1104
1105 /**
1106  [lang:ja]
1107  * leftボタンが離された発生するイベント.
1108  * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1109  [/lang]
1110  [lang:en]
1111  * An event dispatched when the 'left' button is released.
1112  * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1113  [/lang]
1114  [lang:de]
1115  * Ereignis, welchses auftritt wenn der "Nach Links"-Knopf losgelassen wird.
1116  * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1117  [/lang]
1118  * @type {String}
1119  */
1120 enchant.Event.LEFT_BUTTON_UP = 'leftbuttonup';
1121
1122 /**
1123  [lang:ja]
1124  * rightボタンが押された発生するイベント.
1125  * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1126  [/lang]
1127  [lang:en]
1128  * An event dispatched when the 'right' button is pressed.
1129  * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1130  [/lang]
1131  [lang:de]
1132  * Ereignis, welchses auftritt wenn der "Nach Rechts"-Knopf gedrückt wird.
1133  * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1134  [/lang]
1135  * @type {String}
1136  */
1137 enchant.Event.RIGHT_BUTTON_DOWN = 'rightbuttondown';
1138
1139 /**
1140  [lang:ja]
1141  * rightボタンが離された発生するイベント.
1142  * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1143  [/lang]
1144  [lang:en]
1145  * An event dispatched when the 'right' button is released.
1146  * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1147  [/lang]
1148  [lang:de]
1149  * Ereignis, welchses auftritt wenn der "Nach Rechts"-Knopf losgelassen wird.
1150  * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1151  [/lang]
1152  * @type {String}
1153  */
1154 enchant.Event.RIGHT_BUTTON_UP = 'rightbuttonup';
1155
1156 /**
1157  [lang:ja]
1158  * upボタンが押された発生するイベント.
1159  * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1160  [/lang]
1161  [lang:en]
1162  * An event dispatched when the 'up' button is pressed.
1163  * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1164  [/lang]
1165  [lang:de]
1166  * Ereignis, welchses auftritt wenn der "Nach Oben"-Knopf gedrückt wird.
1167  * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1168  [/lang]
1169  * @type {String}
1170  */
1171 enchant.Event.UP_BUTTON_DOWN = 'upbuttondown';
1172
1173 /**
1174  [lang:ja]
1175  * upボタンが離された発生するイベント.
1176  * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1177  [/lang]
1178  [lang:en]
1179  * An event dispatched when the 'up' button is released.
1180  * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1181  [/lang]
1182  [lang:de]
1183  * Ereignis, welchses auftritt wenn der "Nach Oben"-Knopf losgelassen wird.
1184  * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1185  [/lang]
1186  * @type {String}
1187  */
1188 enchant.Event.UP_BUTTON_UP = 'upbuttonup';
1189
1190 /**
1191  [lang:ja]
1192  * downボタンが離された発生するイベント.
1193  * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1194  [/lang]
1195  [lang:en]
1196  * An event dispatched when the 'down' button is pressed.
1197  * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1198  [/lang]
1199  [lang:de]
1200  * Ereignis, welchses auftritt wenn der "Nach Unten"-Knopf gedrückt wird.
1201  * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1202  [/lang]
1203  * @type {String}
1204  */
1205 enchant.Event.DOWN_BUTTON_DOWN = 'downbuttondown';
1206
1207 /**
1208  [lang:ja]
1209  * downボタンが離された発生するイベント.
1210  * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1211  [/lang]
1212  [lang:en]
1213  * An event dispatched when the 'down' button is released.
1214  * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1215  [/lang]
1216  [lang:de]
1217  * Ereignis, welchses auftritt wenn der "Nach Unten"-Knopf losgelassen wird.
1218  * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1219  [/lang]
1220  * @type {String}
1221  */
1222 enchant.Event.DOWN_BUTTON_UP = 'downbuttonup';
1223
1224 /**
1225  [lang:ja]
1226  * aボタンが押された発生するイベント.
1227  * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1228  [/lang]
1229  [lang:en]
1230  * An event dispatched when the 'a' button is pressed.
1231  * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1232  [/lang]
1233  [lang:de]
1234  * Ereignis, welchses auftritt wenn der "A"-Knopf gedrückt wird.
1235  * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1236  [/lang]
1237  * @type {String}
1238  */
1239 enchant.Event.A_BUTTON_DOWN = 'abuttondown';
1240
1241 /**
1242  [lang:ja]
1243  * aボタンが離された発生するイベント.
1244  * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1245  [/lang]
1246  [lang:en]
1247  * An event dispatched when the 'a' button is released.
1248  * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1249  [/lang]
1250  [lang:de]
1251  * Ereignis, welchses auftritt wenn der "A"-Knopf losgelassen wird.
1252  * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1253  [/lang]
1254  * @type {String}
1255  */
1256 enchant.Event.A_BUTTON_UP = 'abuttonup';
1257
1258 /**
1259  [lang:ja]
1260  * bボタンが押された発生するイベント.
1261  * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1262  [/lang]
1263  [lang:en]
1264  * An event dispatched when the 'b' button is pressed.
1265  * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1266  [/lang]
1267  [lang:de]
1268  * Ereignis, welchses auftritt wenn der "B"-Knopf gedrückt wird.
1269  * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1270  [/lang]
1271  * @type {String}
1272  */
1273 enchant.Event.B_BUTTON_DOWN = 'bbuttondown';
1274
1275 /**
1276  [lang:ja]
1277  * bボタンが離された発生するイベント.
1278  * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1279  [/lang]
1280  [lang:en]
1281  * An event dispatched when the 'b' button is released.
1282  * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1283  [/lang]
1284  [lang:de]
1285  * Ereignis, welchses auftritt wenn der "B"-Knopf losgelassen wird.
1286  * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1287  [/lang]
1288  * @type {String}
1289  */
1290 enchant.Event.B_BUTTON_UP = 'bbuttonup';
1291
1292 /**
1293  [lang:ja]
1294  * アクションがタイムラインに追加された時に発行されるイベント
1295  * looped が設定されている時も、アクションは一度タイムラインから削除されもう一度追加される
1296  [/lang]
1297  [lang:en]
1298  * An event dispatched when an Action has been added to a Timeline.
1299  * When looped, an Action is removed from the timeline and added back into it.
1300  [/lang]
1301  * @type {String}
1302  *
1303  */
1304 enchant.Event.ADDED_TO_TIMELINE = "addedtotimeline";
1305
1306 /**
1307  [lang:ja]
1308  * アクションがタイムラインから削除された時に発行されるイベント
1309  * looped が設定されている時も、アクションは一度タイムラインから削除されもう一度追加される
1310  [/lang]
1311  [lang:en]
1312  * An event dispatched when an Action has been removed from a Timeline.
1313  * When looped, an Action is removed from the timeline and added back into it.
1314  [/lang]
1315  * @type {String}
1316  */
1317 enchant.Event.REMOVED_FROM_TIMELINE = "removedfromtimeline";
1318
1319 /**
1320  [lang:ja]
1321  * アクションが開始された時に発行されるイベント
1322  [/lang]
1323  [lang:en]
1324  * An event dispatched when an Action begins.
1325  [/lang]
1326  * @type {String}
1327  */
1328 enchant.Event.ACTION_START = "actionstart";
1329
1330 /**
1331  [lang:ja]
1332  * アクションが終了するときに発行されるイベント
1333  [/lang]
1334  [lang:en]
1335  * An event dispatched when an Action finishes.
1336  [/lang]
1337  * @type {String}
1338  */
1339 enchant.Event.ACTION_END = "actionend";
1340
1341 /**
1342  [lang:ja]
1343  * アクションが1フレーム経過するときに発行されるイベント
1344  [/lang]
1345  [lang:en]
1346  * An event dispatched when an Action has gone through one frame.
1347  [/lang]
1348  * @type {String}
1349  */
1350 enchant.Event.ACTION_TICK = "actiontick";
1351
1352 /**
1353  [lang:ja]
1354  * アクションが追加された時に、タイムラインに対して発行されるイベント
1355  [/lang]
1356  [lang:en]
1357  * An event dispatched to the Timeline when an Action is added.
1358  [/lang]
1359  * @type {String}
1360  */
1361 enchant.Event.ACTION_ADDED = "actionadded";
1362
1363 /**
1364  [lang:ja]
1365  * アクションが削除された時に、タイムラインに対して発行されるイベント
1366  [/lang]
1367  [lang:en]
1368  * An event dispatched to the Timeline when an Action is removed.
1369  [/lang]
1370  * @type {String}
1371  */
1372 enchant.Event.ACTION_REMOVED = "actionremoved";
1373
1374 /**
1375  * @scope enchant.EventTarget.prototype
1376  */
1377 enchant.EventTarget = enchant.Class.create({
1378     /**
1379      * @name enchant.EventTarget
1380      * @class
1381      [lang:ja]
1382      * DOM Event風味の独自イベント実装を行ったクラス.
1383      * ただしフェーズの概念はなし.
1384      [/lang]
1385      [lang:en]
1386      * A class for implementation of events similar to DOM Events.
1387      * However, it does not include the concept of phases.
1388      [/lang]
1389      [lang:de]
1390      * Eine Klasse für eine unabhängige Implementierung von Ereignissen 
1391      * (Events), ähnlich wie DOM Events.
1392      * Jedoch wird das Phasenkonzept nicht unterstützt.
1393      [/lang]
1394      * @extends {enchant.Event}
1395      * @constructs
1396      */
1397     initialize: function() {
1398         this._listeners = {};
1399     },
1400     /**
1401      [lang:ja]
1402      * イベントリスナを追加する.
1403      * @param {String} type イベントのタイプ.
1404      * @param {function(e:enchant.Event)} listener 追加するイベントリスナ.
1405      [/lang]
1406      [lang:en]
1407      * Add a new event listener which will be executed when the event
1408      * is dispatched.
1409      * @param {String} type Type of the events.
1410      * @param {function(e:enchant.Event)} listener Event listener to be added.
1411      [/lang]
1412      [lang:de]
1413      * Fügt einen neuen Ereignisbeobachter hinzu, welcher beim Auftreten des
1414      * Events ausgeführt wird.
1415      * @param {String} type Ereignis Typ.
1416      * @param {function(e:enchant.Event)} listener Der Ereignisbeobachter 
1417      * der hinzugefügt wird.
1418      [/lang]
1419      */
1420     addEventListener: function(type, listener) {
1421         var listeners = this._listeners[type];
1422         if (listeners == null) {
1423             this._listeners[type] = [listener];
1424         } else if (listeners.indexOf(listener) === -1) {
1425             listeners.unshift(listener);
1426
1427         }
1428     },
1429     /**
1430      * Synonym for addEventListener
1431      * @see {enchant.EventTarget#addEventListener}
1432      * @param {String} type Type of the events.
1433      * @param {function(e:enchant.Event)} listener Event listener to be added.
1434      */
1435     on: function() {
1436         this.addEventListener.apply(this, arguments);
1437     },
1438     /**
1439      [lang:ja]
1440      * イベントリスナを削除する.
1441      * @param {String} type イベントのタイプ.
1442      * @param {function(e:enchant.Event)} listener 削除するイベントリスナ.
1443      [/lang]
1444      [lang:en]
1445      * Delete an event listener.
1446      * @param {String} type Type of the events.
1447      * @param {function(e:enchant.Event)} listener Event listener to be deleted.
1448      [/lang]
1449      [lang:de]
1450      * Entfernt einen Ereignisbeobachter.
1451      * @param {String} type Ereignis Typ.
1452      * @param {function(e:enchant.Event)} listener Der Ereignisbeobachter 
1453      * der entfernt wird.
1454      [/lang]
1455      */
1456     removeEventListener: function(type, listener) {
1457         var listeners = this._listeners[type];
1458         if (listeners != null) {
1459             var i = listeners.indexOf(listener);
1460             if (i !== -1) {
1461                 listeners.splice(i, 1);
1462             }
1463         }
1464     },
1465     /**
1466      [lang:ja]
1467      * すべてのイベントリスナを削除する.
1468      * @param [String] type イベントのタイプ.
1469      [/lang]
1470      [lang:en]
1471      * Clear all defined event listeners of a given type.
1472      * If no type is given, all listeners will be removed.
1473      * @param [String] type Type of the events.
1474      [/lang]
1475      [lang:de]
1476      * Entfernt alle Ereignisbeobachter für einen Typ.
1477      * Wenn kein Typ gegeben ist, werden alle 
1478      * Ereignisbeobachter entfernt.
1479      * @param [String] type Ereignis Typ.
1480      [/lang]
1481      */
1482     clearEventListener: function(type) {
1483         if (type != null) {
1484             delete this._listeners[type];
1485         } else {
1486             this._listeners = {};
1487         }
1488     },
1489     /**
1490      [lang:ja]
1491      * イベントを発行する.
1492      * @param {enchant.Event} e 発行するイベント.
1493      [/lang]
1494      [lang:en]
1495      * Issue an event.
1496      * @param {enchant.Event} e Event to be issued.
1497      [/lang]
1498      [lang:de]
1499      * Löst ein Ereignis aus.
1500      * @param {enchant.Event} e Ereignis das ausgelöst werden soll.
1501      [/lang]
1502      */
1503     dispatchEvent: function(e) {
1504         e.target = this;
1505         e.localX = e.x - this._offsetX;
1506         e.localY = e.y - this._offsetY;
1507         if (this['on' + e.type] != null){
1508             this['on' + e.type](e);
1509         }
1510         var listeners = this._listeners[e.type];
1511         if (listeners != null) {
1512             listeners = listeners.slice();
1513             for (var i = 0, len = listeners.length; i < len; i++) {
1514                 listeners[i].call(this, e);
1515             }
1516         }
1517     }
1518 });
1519
1520 /**
1521  * @scope enchant.Core.prototype
1522  */
1523 (function() {
1524     var core;
1525     /**
1526      * @scope enchant.Core.prototype
1527      */
1528     enchant.Core = enchant.Class.create(enchant.EventTarget, {
1529         /**
1530          * @name enchant.Core
1531          * @class
1532             [lang:ja]
1533          * アプリケーションのメインループ, シーンを管理するクラス.
1534          *
1535          * インスタンスは一つしか存在することができず, すでにインスタンスが存在する状態で
1536          * コンストラクタを実行した場合既存のものが上書きされる. 存在するインスタンスには
1537          * enchant.Core.instanceからアクセスできる.
1538          *
1539          * @param {Number} width 画面の横幅.
1540          * @param {Number} height 画面の高さ.
1541          [/lang]
1542          [lang:en]
1543          * A class for controlling the core’s main loop and scenes.
1544          *
1545          * There can be only one instance at a time. When the
1546          * constructor is executed while an instance exists, the
1547          * existing instance will be overwritten. The existing instance
1548          * can be accessed from {@link enchant.Core.instance}.
1549          *
1550          * @param {Number} width The width of the core viewport.
1551          * @param {Number} height The height of the core viewport.
1552          [/lang]
1553          [lang:de]
1554          * Klasse, welche die Spielschleife und Szenen kontrolliert.
1555          *
1556          * Es kann immer nur eine Instanz geben und sollte der Konstruktor ausgeführt werden,
1557          * obwohl bereits eine Instanz existiert, wird die vorherige Instanz überschrieben.
1558          * Auf die aktuell existierende Instanz kann über die {@link enchant.Core.instance}
1559          * Variable zugegriffen werden.
1560          *
1561          * @param {Number} width Die Breite des Spieles.
1562          * @param {Number} height Die Höhe des Spieles.
1563          [/lang]
1564          * @constructs
1565          * @extends enchant.EventTarget
1566          */
1567         initialize: function(width, height) {
1568             if (window.document.body === null) {
1569                 // @TODO postpone initialization after window.onload
1570                 throw new Error("document.body is null. Please excute 'new Core()' in window.onload.");
1571             }
1572
1573             enchant.EventTarget.call(this);
1574             var initial = true;
1575             if (core) {
1576                 initial = false;
1577                 core.stop();
1578             }
1579             core = enchant.Core.instance = this;
1580
1581             this._calledTime = 0;
1582             this._mousedownID = 0;
1583             this._surfaceID = 0;
1584             this._soundID = 0;
1585
1586             this._scenes = [];
1587
1588             width = width || 320;
1589             height = height || 320;
1590
1591             var stage = document.getElementById('enchant-stage');
1592             var scale, sWidth, sHeight;
1593             if (!stage) {
1594                 stage = document.createElement('div');
1595                 stage.id = 'enchant-stage';
1596                 stage.style.position = 'absolute';
1597
1598                 if (document.body.firstChild) {
1599                     document.body.insertBefore(stage, document.body.firstChild);
1600                 } else {
1601                     document.body.appendChild(stage);
1602                 }
1603                 scale = Math.min(
1604                     window.innerWidth / width,
1605                     window.innerHeight / height
1606                 );
1607                 this._pageX = 0;
1608                 this._pageY = 0;
1609             } else {
1610                 var style = window.getComputedStyle(stage);
1611                 sWidth = parseInt(style.width, 10);
1612                 sHeight = parseInt(style.height, 10);
1613                 if (sWidth && sHeight) {
1614                     scale = Math.min(
1615                         sWidth / width,
1616                         sHeight / height
1617                     );
1618                 } else {
1619                     scale = 1;
1620                 }
1621                 while (stage.firstChild) {
1622                     stage.removeChild(stage.firstChild);
1623                 }
1624                 stage.style.position = 'relative';
1625
1626                 var bounding = stage.getBoundingClientRect();
1627                 this._pageX = Math.round(window.scrollX || window.pageXOffset + bounding.left);
1628                 this._pageY = Math.round(window.scrollY || window.pageYOffset + bounding.top);
1629             }
1630             stage.style.fontSize = '12px';
1631             stage.style.webkitTextSizeAdjust = 'none';
1632             stage.style.webkitTapHighlightColor = 'rgba(0, 0, 0, 0)';
1633             this._element = stage;
1634
1635             this.addEventListener('coreresize', this._oncoreresize);
1636
1637             this._width = width;
1638             this._height = height;
1639             this.scale = scale;
1640
1641             /**
1642              [lang:ja]
1643              * フレームレート.
1644              [/lang]
1645              [lang:en]
1646              * The frame rate of the core.
1647              [/lang]
1648              [lang:de]
1649              * Frame Rate des Spieles.
1650              [/lang]
1651              * @type {Number}
1652              */
1653             this.fps = 30;
1654             /**
1655              [lang:ja]
1656              * アプリの開始からのフレーム数.
1657              [/lang]
1658              [lang:en]
1659              * The number of frames processed since the core was started.
1660              [/lang]
1661              [lang:de]
1662              * Anzahl der Frames seit dem Spielestart.
1663              [/lang]
1664              * @type {Number}
1665              */
1666             this.frame = 0;
1667             /**
1668              [lang:ja]
1669              * アプリが実行可能な状態かどうか.
1670              [/lang]
1671              [lang:en]
1672              * Indicates whether or not the core can be executed.
1673              [/lang]
1674              [lang:de]
1675              * Zeigt an ob das Spiel ausgeführt werden kann.
1676              [/lang]
1677              * @type {Boolean}
1678              */
1679             this.ready = false;
1680             /**
1681              [lang:ja]
1682              * アプリが実行状態かどうか.
1683              [/lang]
1684              [lang:en]
1685              * Indicates whether or not the core is currently running.
1686              [/lang]
1687              [lang:de]
1688              * Zeigt an ob das Spiel derzeit ausgeführt wird.
1689              [/lang]
1690              * @type {Boolean}
1691              */
1692             this.running = false;
1693             /**
1694              [lang:ja]
1695              * ロードされた画像をパスをキーとして保存するオブジェクト.
1696              [/lang]
1697              [lang:en]
1698              * Object which stores loaded assets using the path as a key.
1699              [/lang]
1700              [lang:de]
1701              * Geladene Objekte werden unter dem Pfad als Schlüssel in diesem Objekt abgelegt.
1702              [/lang]
1703              * @type {Object.<String, Surface>}
1704              */
1705             this.assets = {};
1706             var assets = this._assets = [];
1707             (function detectAssets(module) {
1708                 if (module.assets) {
1709                     enchant.Core.instance.preload(module.assets);
1710                 }
1711                 for (var prop in module) {
1712                     if (module.hasOwnProperty(prop)) {
1713                         if (typeof module[prop] === 'object' && module[prop] !== null && Object.getPrototypeOf(module[prop]) === Object.prototype) {
1714                             detectAssets(module[prop]);
1715                         }
1716                     }
1717                 }
1718             }(enchant));
1719
1720             /**
1721              [lang:ja]
1722              * 現在のScene. Sceneスタック中の一番上のScene.
1723              [/lang]
1724              [lang:en]
1725              * The Scene which is currently displayed. This Scene is on top of Scene stack.
1726              [/lang]
1727              [lang:de]
1728              * Die aktuell dargestellte Szene.
1729              * Diese Szene befindet sich oben auf dem Stapelspeicher.
1730              [/lang]
1731              * @type {enchant.Scene}
1732              */
1733             this.currentScene = null;
1734             /**
1735              [lang:ja]
1736              * ルートScene. Sceneスタック中の一番下のScene.
1737              [/lang]
1738              [lang:en]
1739              * The root Scene. The Scene at bottom of the Scene stack.
1740              [/lang]
1741              [lang:de]
1742              * Die Ursprungsszene.
1743              * Diese Szene befindet sich unten auf dem Stapelspeicher.
1744              [/lang]
1745              * @type {enchant.Scene}
1746              */
1747             this.rootScene = new enchant.Scene();
1748             this.pushScene(this.rootScene);
1749             /**
1750              [lang:ja]
1751              * ローディング時に表示されるScene.
1752              [/lang]
1753              [lang:en]
1754              * The Scene to be displayed during loading.
1755              [/lang]
1756              [lang:de]
1757              * Die Szene, welche während des Ladevorgangs dargestellt wird.
1758              [/lang]
1759              * @type {enchant.Scene}
1760              */
1761             this.loadingScene = new enchant.LoadingScene();
1762
1763             /**
1764              [lang:ja]
1765              * 一度でも game.start() が呼ばれたことがあるかどうか。
1766              [/lang]
1767              [/lang:ja]
1768              * Indicates whether or not game.start() has been called.
1769              [/lang]
1770              * @type {Boolean}
1771              * @private
1772              */
1773             this._activated = false;
1774
1775             this._offsetX = 0;
1776             this._offsetY = 0;
1777
1778             /**
1779              [lang:ja]
1780              * アプリに対する入力状態を保存するオブジェクト.
1781              [/lang]
1782              [lang:en]
1783              * Object that saves the current input state for the core.
1784              [/lang]
1785              [lang:de]
1786              * Objekt, welches den aktuellen Eingabestatus des Spieles speichert.
1787              [/lang]
1788              * @type {Object.<String, Boolean>}
1789              */
1790             this.input = {};
1791             if (!enchant.ENV.KEY_BIND_TABLE) {
1792                 enchant.ENV.KEY_BIND_TABLE = {};
1793             }
1794             this._keybind = enchant.ENV.KEY_BIND_TABLE;
1795             this.pressedKeysNum = 0;
1796             this._internalButtondownListeners = {};
1797             this._internalButtonupListeners = {};
1798
1799             for (var prop in this._keybind) {
1800                 this.keybind(prop, this._keybind[prop]);
1801             }
1802
1803             if (initial) {
1804                 stage = enchant.Core.instance._element;
1805                 var evt;
1806                 document.addEventListener('keydown', function(e) {
1807                     core.dispatchEvent(new enchant.Event('keydown'));
1808                     if (enchant.ENV.PREVENT_DEFAULT_KEY_CODES.indexOf(e.keyCode) !== -1) {
1809                         e.preventDefault();
1810                         e.stopPropagation();
1811                     }
1812
1813                     if (!core.running) {
1814                         return;
1815                     }
1816                     var button = core._keybind[e.keyCode];
1817                     if (button) {
1818                         evt = new enchant.Event(button + 'buttondown');
1819                         core.dispatchEvent(evt);
1820                     }
1821                 }, true);
1822                 document.addEventListener('keyup', function(e) {
1823                     if (!core.running) {
1824                         return;
1825                     }
1826                     var button = core._keybind[e.keyCode];
1827                     if (button) {
1828                         evt = new enchant.Event(button + 'buttonup');
1829                         core.dispatchEvent(evt);
1830                     }
1831                 }, true);
1832
1833                 if (enchant.ENV.TOUCH_ENABLED) {
1834                     stage.addEventListener('touchstart', function(e) {
1835                         var tagName = (e.target.tagName).toLowerCase();
1836                         if (enchant.ENV.USE_DEFAULT_EVENT_TAGS.indexOf(tagName) === -1) {
1837                             e.preventDefault();
1838                             if (!core.running) {
1839                                 e.stopPropagation();
1840                             }
1841                         }
1842                     }, true);
1843                     stage.addEventListener('touchmove', function(e) {
1844                         var tagName = (e.target.tagName).toLowerCase();
1845                         if (enchant.ENV.USE_DEFAULT_EVENT_TAGS.indexOf(tagName) === -1) {
1846                             e.preventDefault();
1847                             if (!core.running) {
1848                                 e.stopPropagation();
1849                             }
1850                         }
1851                     }, true);
1852                     stage.addEventListener('touchend', function(e) {
1853                         var tagName = (e.target.tagName).toLowerCase();
1854                         if (enchant.ENV.USE_DEFAULT_EVENT_TAGS.indexOf(tagName) === -1) {
1855                             e.preventDefault();
1856                             if (!core.running) {
1857                                 e.stopPropagation();
1858                             }
1859                         }
1860                     }, true);
1861                 }
1862                 stage.addEventListener('mousedown', function(e) {
1863                     var tagName = (e.target.tagName).toLowerCase();
1864                     if (enchant.ENV.USE_DEFAULT_EVENT_TAGS.indexOf(tagName) === -1) {
1865                         e.preventDefault();
1866                         core._mousedownID++;
1867                         if (!core.running) {
1868                             e.stopPropagation();
1869                         }
1870                     }
1871                 }, true);
1872                 stage.addEventListener('mousemove', function(e) {
1873                     var tagName = (e.target.tagName).toLowerCase();
1874                     if (enchant.ENV.USE_DEFAULT_EVENT_TAGS.indexOf(tagName) === -1) {
1875                         e.preventDefault();
1876                         if (!core.running) {
1877                             e.stopPropagation();
1878                         }
1879                     }
1880                 }, true);
1881                 stage.addEventListener('mouseup', function(e) {
1882                     var tagName = (e.target.tagName).toLowerCase();
1883                     if (enchant.ENV.USE_DEFAULT_EVENT_TAGS.indexOf(tagName) === -1) {
1884                         e.preventDefault();
1885                         if (!core.running) {
1886                             e.stopPropagation();
1887                         }
1888                     }
1889                 }, true);
1890                 core._touchEventTarget = {};
1891                 if (enchant.ENV.TOUCH_ENABLED) {
1892                     stage.addEventListener('touchstart', function(e) {
1893                         var core = enchant.Core.instance;
1894                         var evt = new enchant.Event(enchant.Event.TOUCH_START);
1895                         var touches = e.changedTouches;
1896                         var touch, target;
1897                         for (var i = 0, l = touches.length; i < l; i++) {
1898                             touch = touches[i];
1899                             evt._initPosition(touch.pageX, touch.pageY);
1900                             target = core.currentScene._determineEventTarget(evt);
1901                             core._touchEventTarget[touch.identifier] = target;
1902                             target.dispatchEvent(evt);
1903                         }
1904                     }, false);
1905                     stage.addEventListener('touchmove', function(e) {
1906                         var core = enchant.Core.instance;
1907                         var evt = new enchant.Event(enchant.Event.TOUCH_MOVE);
1908                         var touches = e.changedTouches;
1909                         var touch, target;
1910                         for (var i = 0, l = touches.length; i < l; i++) {
1911                             touch = touches[i];
1912                             target = core._touchEventTarget[touch.identifier];
1913                             if (target) {
1914                                 evt._initPosition(touch.pageX, touch.pageY);
1915                                 target.dispatchEvent(evt);
1916                             }
1917                         }
1918                     }, false);
1919                     stage.addEventListener('touchend', function(e) {
1920                         var core = enchant.Core.instance;
1921                         var evt = new enchant.Event(enchant.Event.TOUCH_END);
1922                         var touches = e.changedTouches;
1923                         var touch, target;
1924                         for (var i = 0, l = touches.length; i < l; i++) {
1925                             touch = touches[i];
1926                             target = core._touchEventTarget[touch.identifier];
1927                             if (target) {
1928                                 evt._initPosition(touch.pageX, touch.pageY);
1929                                 target.dispatchEvent(evt);
1930                                 delete core._touchEventTarget[touch.identifier];
1931                             }
1932                         }
1933                     }, false);
1934                 }
1935                 stage.addEventListener('mousedown', function(e) {
1936                     var core = enchant.Core.instance;
1937                     var evt = new enchant.Event(enchant.Event.TOUCH_START);
1938                     evt._initPosition(e.pageX, e.pageY);
1939                     var target = core.currentScene._determineEventTarget(evt);
1940                     core._touchEventTarget[core._mousedownID] = target;
1941                     target.dispatchEvent(evt);
1942                 }, false);
1943                 stage.addEventListener('mousemove', function(e) {
1944                     var core = enchant.Core.instance;
1945                     var evt = new enchant.Event(enchant.Event.TOUCH_MOVE);
1946                     evt._initPosition(e.pageX, e.pageY);
1947                     var target = core._touchEventTarget[core._mousedownID];
1948                     if (target) {
1949                         target.dispatchEvent(evt);
1950                     }
1951                 }, false);
1952                 stage.addEventListener('mouseup', function(e) {
1953                     var core = enchant.Core.instance;
1954                     var evt = new enchant.Event(enchant.Event.TOUCH_END);
1955                     evt._initPosition(e.pageX, e.pageY);
1956                     var target = core._touchEventTarget[core._mousedownID];
1957                     if (target) {
1958                         target.dispatchEvent(evt);
1959                     }
1960                     delete core._touchEventTarget[core._mousedownID];
1961                 }, false);
1962             }
1963         },
1964         /**
1965          [lang:ja]
1966          * 画面の横幅.
1967          [/lang]
1968          [lang:en]
1969          * The width of the core screen.
1970          [/lang]
1971          [lang:de]
1972          * Breite des Spieles.
1973          [/lang]
1974          * @type {Number}
1975          */
1976         width: {
1977             get: function() {
1978                 return this._width;
1979             },
1980             set: function(w) {
1981                 this._width = w;
1982                 this._dispatchCoreResizeEvent();
1983             }
1984         },
1985         /**
1986          [lang:ja]
1987          * 画面の高さ.
1988          [/lang]
1989          [lang:en]
1990          * The height of the core screen.
1991          [/lang]
1992          [lang:de]
1993          * Höhe des Spieles.
1994          [/lang]
1995          * @type {Number}
1996          */
1997         height: {
1998             get: function() {
1999                 return this._height;
2000             },
2001             set: function(h) {
2002                 this._height = h;
2003                 this._dispatchCoreResizeEvent();
2004             }
2005         },
2006         /**
2007          [lang:ja]
2008          * 画面の表示倍率.
2009          [/lang]
2010          [lang:en]
2011          * The scaling of the core rendering.
2012          [/lang]
2013          [lang:de]
2014          * Skalierung der Spieldarstellung.
2015          [/lang]
2016          * @type {Number}
2017          */
2018         scale: {
2019             get: function() {
2020                 return this._scale;
2021             },
2022             set: function(s) {
2023                 this._scale = s;
2024                 this._dispatchCoreResizeEvent();
2025             }
2026         },
2027         _dispatchCoreResizeEvent: function() {
2028             var e = new enchant.Event('coreresize');
2029             e.width = this._width;
2030             e.height = this._height;
2031             e.scale = this._scale;
2032             this.dispatchEvent(e);
2033         },
2034         _oncoreresize: function(e) {
2035             this._element.style.width = Math.floor(this._width * this._scale) + 'px';
2036             this._element.style.height = Math.floor(this._height * this._scale) + 'px';
2037             var scene;
2038             for (var i = 0, l = this._scenes.length; i < l; i++) {
2039                 scene = this._scenes[i];
2040                 scene.dispatchEvent(e);
2041             }
2042         },
2043         /**
2044          [lang:ja]
2045          * ファイルのプリロードを行う.
2046          *
2047          * プリロードを行うよう設定されたファイルは{@link enchant.Core#start}が実行されるとき
2048          * ロードが行われる. 全てのファイルのロードが完了したときはCoreオブジェクトからload
2049          * イベントが発行され, Coreオブジェクトのassetsプロパティから画像ファイルの場合は
2050          * Surfaceオブジェクトとして, 音声ファイルの場合はSoundオブジェクトとして,
2051          * その他の場合は文字列としてアクセスできるようになる.
2052          *
2053          * なおこのSurfaceオブジェクトは{@link enchant.Surface.load}を使って作成されたものである
2054          * ため直接画像操作を行うことはできない. enchant.Surface.loadの項を参照.
2055          *
2056          * @example
2057          *   core.preload('player.gif');
2058          *   core.onload = function() {
2059          *      var sprite = new Sprite(32, 32);
2060          *      sprite.image = core.assets['player.gif']; // パス名でアクセス
2061          *      ...
2062          *   };
2063          *   core.start();
2064          *
2065          * @param {...String} assets プリロードするファイルのパス. 複数指定できる.
2066          [/lang]
2067          [lang:en]
2068          * File preloader.
2069          *
2070          * Loads the files specified in the parameters when
2071          * {@link enchant.Core#start} is called.
2072          * When all files are loaded, a {@link enchant.Event.LOAD}
2073          * event is dispatched from the Core object. Depending on the
2074          * type of each file, different objects will be created and
2075          * stored in {@link enchant.Core#assets} Variable.
2076          *
2077          * When an image file is loaded, a {@link enchant.Surface} is
2078          * created. If a sound file is loaded, an {@link enchant.Sound}
2079          * object is created. Any other file type will be accessible
2080          * as a string.
2081          *
2082          * In addition, because this Surface object is created with
2083          * {@link enchant.Surface.load}, it is not possible to
2084          * manipulate the image directly.
2085          * Refer to the {@link enchant.Surface.load} documentation.
2086          *
2087          * @example
2088          *   core.preload('player.gif');
2089          *   core.onload = function() {
2090          *      var sprite = new Sprite(32, 32);
2091          *      sprite.image = core.assets['player.gif']; // Access via path
2092          *      ...
2093          *   };
2094          *   core.start();
2095          *
2096          * @param {...String} assets Path of images to be preloaded.
2097          * Multiple settings possible.
2098          [/lang]
2099          [lang:de]
2100          * Lässt Dateien im voraus laden.
2101          *
2102          * Diese Methode setzt die Dateien die im voraus geladen werden sollen. Wenn {@link enchant.Core#start}
2103          * aufgerufen wird, findet das tatsächliche laden der Resource statt. Sollten alle Dateien vollständig
2104          * geladen sein, wird ein {@link enchant.Event.LOAD} Ereignis auf dem Core Objekt ausgelöst.
2105          * Abhängig von den Dateien die geladen werden sollen, werden unterschiedliche Objekte erstellt und in
2106          * dem {@link enchant.Core#assets} Feld gespeichert.
2107          * Falls ein Bild geladen wird, wird ein {@link enchant.Surface} Objekt erstellt. Wenn es eine Ton Datei ist,
2108          * wird ein {@link enchant.Sound} Objekt erstellt. Ansonsten kann auf die Datei über einen String zugegriffen werden.
2109          *
2110          * Da die Surface Objekte mittels {@link enchant.Surface.load} erstellt werden ist zusätlich ist zu beachten, dass
2111          * eine direkte Objektmanipulation nicht möglich ist.
2112          * Für diesen Fall ist auf die {@link enchant.Surface.load} Dokumentation zu verweisen.
2113          *
2114          * @example
2115          *   core.preload('player.gif');
2116          *   core.onload = function() {
2117          *      var sprite = new Sprite(32, 32);
2118          *      sprite.image = core.assets['player.gif']; // zugriff mittels Dateipfades
2119          *      ...
2120          *   };
2121          *   core.start();
2122          *
2123          * @param {...String} assets Pfade zu den Dateien die im voraus geladen werden sollen.
2124          * Mehrfachangaben möglich.
2125          [/lang]
2126          * @return {enchant.Core} this
2127          */
2128         preload: function(assets) {
2129             var a;
2130             if (!(assets instanceof Array)) {
2131                 if (typeof assets === 'object') {
2132                     a = [];
2133                     for (var name in assets) {
2134                         if (assets.hasOwnProperty(name)) {
2135                             a.push([ assets[name], name ]);
2136                         }
2137                     }
2138                     assets = a;
2139                 } else {
2140                     assets = Array.prototype.slice.call(arguments);
2141                 }
2142             }
2143             Array.prototype.push.apply(this._assets, assets);
2144             return this;
2145         },
2146         /**
2147          [lang:ja]
2148          * ファイルのロードを行う.
2149          *
2150          * @param {String} [src] asset ロードするファイルのパス.
2151          * @param {String} [alias] ロードするファイルに設定したい名前.
2152          * @param {Function} [callback] ファイルのロードが完了したときに呼び出される関数.
2153          * @param {Function} [onerror] ファイルのロードに失敗したときに呼び出される関数.
2154          [/lang]
2155          [lang:en]
2156          * Loads a file.
2157          *
2158          * @param {String} [src] File path of the resource to be loaded.
2159          * @param {String} [asset] Name you want to designate for the resource to be loaded.
2160          * @param {Function} [callback] Function to be called if the file loads successfully.
2161          * @param {Function} [onerror] Function to be called if the file fails to load.
2162          [/lang]
2163          [lang:de]
2164          * Laden von Dateien.
2165          *
2166          * @param {String} asset Pfad zu der Datei die geladen werden soll.
2167          * @param {Function} [callback] Funktion die ausgeführt wird wenn das laden abgeschlossen wurde.
2168          [/lang]
2169          */
2170         load: function(src, alias, callback, onerror) {
2171             var assetName, offset;
2172             if (typeof arguments[1] === 'string') {
2173                 assetName = alias;
2174                 offset = 1;
2175             } else {
2176                 assetName = src;
2177                 offset = 0;
2178             }
2179             callback = arguments[1 + offset] || function() {};
2180             onerror = arguments[2 + offset] || function() {};
2181
2182             var ext = enchant.Core.findExt(src);
2183
2184             return enchant.Deferred.next(function() {
2185                 var d = new enchant.Deferred();
2186                 var _callback = function(e) {
2187                     d.call(e);
2188                     callback.call(this, e);
2189                 };
2190                 var _onerror = function(e) {
2191                     d.fail(e);
2192                     onerror.call(this, e);
2193                 };
2194                 if (enchant.Core._loadFuncs[ext]) {
2195                     enchant.Core.instance.assets[assetName] = enchant.Core._loadFuncs[ext](src, ext, _callback, _onerror);
2196                 } else {
2197                     var req = new XMLHttpRequest();
2198                     req.open('GET', src, true);
2199                     req.onreadystatechange = function() {
2200                         if (req.readyState === 4) {
2201                             if (req.status !== 200 && req.status !== 0) {
2202                                 // throw new Error(req.status + ': ' + 'Cannot load an asset: ' + src);
2203                                 var e = new enchant.Event('error');
2204                                 e.message = req.status + ': ' + 'Cannot load an asset: ' + src;
2205                                 _onerror.call(enchant.Core.instance, e);
2206                             }
2207
2208                             var type = req.getResponseHeader('Content-Type') || '';
2209                             if (type.match(/^image/)) {
2210                                 core.assets[assetName] = enchant.Surface.load(src, _callback, _onerror);
2211                             } else if (type.match(/^audio/)) {
2212                                 core.assets[assetName] = enchant.Sound.load(src, type, _callback, _onerror);
2213                             } else {
2214                                 core.assets[assetName] = req.responseText;
2215                                 _callback.call(enchant.Core.instance, new enchant.Event('laod'));
2216                             }
2217                         }
2218                     };
2219                     req.send(null);
2220                 }
2221                 return d;
2222             });
2223         },
2224         /**
2225          [lang:ja]
2226          * アプリを起動する.
2227          *
2228          * enchant.Core#fpsで設定されたフレームレートに従ってenchant.Core#currentSceneの
2229          * フレームの更新が行われるようになる. プリロードする画像が存在する場合はロードが
2230          * 始まりローディング画面が表示される.
2231          [/lang]
2232          [lang:en]
2233          * Start the core.
2234          *
2235          * Sets the framerate of the {@link enchant.Core#currentScene}
2236          * according to the value stored in {@link enchant.core#fps}. If
2237          * there are images to preload, loading will begin and the
2238          * loading screen will be displayed.
2239          [/lang]
2240          [lang:de]
2241          * Starte das Spiel
2242          *
2243          * Je nach der Frame Rate definiert in {@link enchant.Core#fps}, wird der Frame in der
2244          * {@link enchant.Core#currentScene} aktualisiert. Sollten Dateien die im voraus geladen werden
2245          * sollen vorhanden sein, beginnt das laden dieser Dateien und der Ladebildschirm wird dargestellt.
2246          [/lang]
2247          * @return {enchant.Deferred} Deferred
2248          */
2249         start: function(deferred) {
2250             var onloadTimeSetter = function() {
2251                 this.frame = 0;
2252                 this.removeEventListener('load', onloadTimeSetter);
2253             };
2254             this.addEventListener('load', onloadTimeSetter);
2255
2256             this.currentTime = window.getTime();
2257             this.running = true;
2258             this.ready = true;
2259
2260             if (!this._activated) {
2261                 this._activated = true;
2262                 if (enchant.ENV.SOUND_ENABLED_ON_MOBILE_SAFARI && !core._touched &&
2263                     (navigator.userAgent.indexOf('iPhone OS') !== -1 ||
2264                     navigator.userAgent.indexOf('iPad') !== -1)) {
2265                     var d = new enchant.Deferred();
2266                     var scene = new enchant.Scene();
2267                     scene.backgroundColor = '#000';
2268                     var size = Math.round(core.width / 10);
2269                     var sprite = new enchant.Sprite(core.width, size);
2270                     sprite.y = (core.height - size) / 2;
2271                     sprite.image = new enchant.Surface(core.width, size);
2272                     sprite.image.context.fillStyle = '#fff';
2273                     sprite.image.context.font = (size - 1) + 'px bold Helvetica,Arial,sans-serif';
2274                     var width = sprite.image.context.measureText('Touch to Start').width;
2275                     sprite.image.context.fillText('Touch to Start', (core.width - width) / 2, size - 1);
2276                     scene.addChild(sprite);
2277                     document.addEventListener('mousedown', function waitTouch() {
2278                         document.removeEventListener('mousedown', waitTouch);
2279                         core._touched = true;
2280                         core.removeScene(scene);
2281                         core.start(d);
2282                     }, false);
2283                     core.pushScene(scene);
2284                     return d;
2285                 }
2286             }
2287
2288             this._requestNextFrame(0);
2289
2290             var ret = this._requestPreload()
2291                 .next(function() {
2292                     enchant.Core.instance.loadingScene.dispatchEvent(new enchant.Event(enchant.Event.LOAD));
2293                 });
2294
2295             if (deferred) {
2296                 ret.next(function(arg) {
2297                     deferred.call(arg);
2298                 })
2299                 .error(function(arg) {
2300                     deferred.fail(arg);
2301                 });
2302             }
2303
2304             return ret;
2305         },
2306         _requestPreload: function() {
2307             var o = {};
2308             var loaded = 0,
2309                 len = 0,
2310                 loadFunc = function() {
2311                     var e = new enchant.Event('progress');
2312                     e.loaded = ++loaded;
2313                     e.total = len;
2314                     core.loadingScene.dispatchEvent(e);
2315                 };
2316             this._assets
2317                 .reverse()
2318                 .forEach(function(asset) {
2319                     var src, name;
2320                     if (asset instanceof Array) {
2321                         src = asset[0];
2322                         name = asset[1];
2323                     } else {
2324                         src = name = asset;
2325                     }
2326                     if (!o[name]) {
2327                         o[name] = this.load(src, name, loadFunc);
2328                         len++;
2329                     }
2330                 }, this);
2331
2332             this.pushScene(this.loadingScene);
2333             return enchant.Deferred.parallel(o);
2334         },
2335         /**
2336          [lang:ja]
2337          * アプリをデバッグモードで開始する.
2338          *
2339          * enchant.Core.instance._debug フラグを true にすることでもデバッグモードをオンにすることができる
2340          [/lang]
2341          [lang:en]
2342          * Start application in debug mode.
2343          *
2344          * Core debug mode can be turned on even if the
2345          * enchant.Core.instance._debug flag is already set to true.
2346          [/lang]
2347          [lang:de]
2348          * Startet den Debug-Modus des Spieles.
2349          *
2350          * Auch wenn die enchant.Core.instance._debug Variable gesetzt ist,
2351          * kann der Debug-Modus gestartet werden.
2352          [/lang]
2353          * @return {enchant.Deferred} Deferred
2354          */
2355         debug: function() {
2356             this._debug = true;
2357             return this.start();
2358         },
2359         actualFps: {
2360             get: function() {
2361                 return this._actualFps || this.fps;
2362             }
2363         },
2364         /**
2365          [lang:ja]
2366          * 次のフレームの実行を要求する.
2367          * @param {Number} requestAnimationFrameを呼び出すまでの遅延時間.
2368          [/lang]
2369          [lang:en]
2370          * Requests the next frame.
2371          * @param {Number} Amount of time to delay before calling requestAnimationFrame.
2372          [/lang]
2373          * @private
2374          */
2375         _requestNextFrame: function(delay) {
2376             if (!this.ready) {
2377                 return;
2378             }
2379             if (this.fps >= 60 || delay <= 16) {
2380                 this._calledTime = window.getTime();
2381                 window.requestAnimationFrame(this._callTick);
2382             } else {
2383                 setTimeout(function() {
2384                     var core = enchant.Core.instance;
2385                     core._calledTime = window.getTime();
2386                     window.requestAnimationFrame(core._callTick);
2387                 }, Math.max(0, delay));
2388             }
2389         },
2390         /**
2391          [lang:ja]
2392          * {@link enchant.Core#_tick}を呼び出す.
2393          [/lang]
2394          [lang:en]
2395          * Calls {@link enchant.Core#_tick}.
2396          [/lang]
2397          * @param {Number} [time]
2398          * @private
2399          */
2400         _callTick: function(time) {
2401             enchant.Core.instance._tick(time);
2402         },
2403         _tick: function(time) {
2404             var e = new enchant.Event('enterframe');
2405             var now = window.getTime();
2406             var elapsed = e.elapsed = now - this.currentTime;
2407
2408             this._actualFps = elapsed > 0 ? (1000 / elapsed) : 0;
2409
2410             var nodes = this.currentScene.childNodes.slice();
2411             var push = Array.prototype.push;
2412             while (nodes.length) {
2413                 var node = nodes.pop();
2414                 node.age++;
2415                 node.dispatchEvent(e);
2416                 if (node.childNodes) {
2417                     push.apply(nodes, node.childNodes);
2418                 }
2419             }
2420
2421             this.currentScene.age++;
2422             this.currentScene.dispatchEvent(e);
2423             this.dispatchEvent(e);
2424
2425             this.dispatchEvent(new enchant.Event('exitframe'));
2426             this.frame++;
2427             now = window.getTime();
2428             this.currentTime = now;
2429             this._requestNextFrame(1000 / this.fps - (now - this._calledTime));
2430         },
2431         getTime: function() {
2432             return window.getTime();
2433         },
2434         /**
2435          [lang:ja]
2436          * アプリを停止する.
2437          *
2438          * フレームは更新されず, ユーザの入力も受け付けなくなる.
2439          * enchant.Core#startで再開できる.
2440          [/lang]
2441          [lang:en]
2442          * Stops the core.
2443          *
2444          * The frame will not be updated, and player input will not be accepted anymore.
2445          * Core can be restarted using {@link enchant.Core#start}.
2446          [/lang]
2447          [lang:de]
2448          * Stoppt das Spiel.
2449          *
2450          * Der Frame wird nicht mehr aktualisiert und Spielereingaben werden nicht
2451          * mehr akzeptiert. Das spiel kann mit der {@link enchant.Core#start} Methode
2452          * erneut gestartet werden.
2453          [/lang]
2454          */
2455         stop: function() {
2456             this.ready = false;
2457             this.running = false;
2458         },
2459         /**
2460          [lang:ja]
2461          * アプリを一時停止する.
2462          *
2463          * フレームは更新されず, ユーザの入力は受け付ける.
2464          * enchant.Core#startで再開できる.
2465          [/lang]
2466          [lang:en]
2467          * Stops the core.
2468          *
2469          * The frame will not be updated, and player input will not be accepted anymore.
2470          * Core can be started again using {@link enchant.Core#start}.
2471          [/lang]
2472          [lang:de]
2473          * Stoppt das Spiel.
2474          *
2475          * Der Frame wird nicht mehr aktualisiert und Spielereingaben werden nicht
2476          * mehr akzeptiert. Das spiel kann mit der {@link enchant.Core#start} Methode
2477          * erneut gestartet werden.
2478          [/lang]
2479          */
2480         pause: function() {
2481             this.ready = false;
2482         },
2483         /**
2484          [lang:ja]
2485          * アプリを再開する。
2486          [/lang]
2487          [lang:en]
2488          * Resumes the core.
2489          [/lang]
2490          [lang:de]
2491          * Setzt die Ausführung des Spieles fort.
2492          [/lang]
2493          */
2494         resume: function() {
2495             if (this.ready) {
2496                 return;
2497             }
2498             this.currentTime = window.getTime();
2499             this.ready = true;
2500             this.running = true;
2501             this._requestNextFrame(0);
2502         },
2503
2504         /**
2505          [lang:ja]
2506          * 新しいSceneに移行する.
2507          *
2508          * Sceneはスタック状に管理されており, 表示順序もスタックに積み上げられた順に従う.
2509          * enchant.Core#pushSceneを行うとSceneをスタックの一番上に積むことができる. スタックの
2510          * 一番上のSceneに対してはフレームの更新が行われる.
2511          *
2512          * @param {enchant.Scene} scene 移行する新しいScene.
2513          * @return {enchant.Scene} 新しいScene.
2514          [/lang]
2515          [lang:en]
2516          * Switch to a new Scene.
2517          *
2518          * Scenes are controlled using a stack, and the display order also obeys that stack order.
2519          * When {@link enchant.Core#pushScene} is executed, the Scene can be brought to the top of stack.
2520          * Frames will be updated in the Scene which is on the top of the stack.
2521          *
2522          * @param {enchant.Scene} scene The new scene to be switched to.
2523          * @return {enchant.Scene} The new Scene.
2524          [/lang]
2525          [lang:de]
2526          * Wechselt zu einer neuen Szene.
2527          *
2528          * Szenen werden durch einen Stapelspeicher kontrolliert und die Darstellungsreihenfolge
2529          * folgt ebenfalls der Ordnung des Stapelspeichers.
2530          * Wenn die {@link enchant.Core#pushScene} Methode ausgeführt wird, wird die Szene auf dem
2531          * Stapelspeicher oben abgelegt. Der Frame wird immer in der Szene ganz oben auf dem Stapelspeicher
2532          * aktualisiert.
2533          *
2534          * @param {enchant.Scene} scene Die neue Szene zu der gewechselt werden soll.
2535          * @return {enchant.Scene} Die neue Szene.
2536          [/lang]
2537          */
2538         pushScene: function(scene) {
2539             this._element.appendChild(scene._element);
2540             if (this.currentScene) {
2541                 this.currentScene.dispatchEvent(new enchant.Event('exit'));
2542             }
2543             this.currentScene = scene;
2544             this.currentScene.dispatchEvent(new enchant.Event('enter'));
2545             return this._scenes.push(scene);
2546         },
2547         /**
2548          [lang:ja]
2549          * 現在のSceneを終了させ前のSceneに戻る.
2550          *
2551          * Sceneはスタック状に管理されており, 表示順序もスタックに積み上げられた順に従う.
2552          * enchant.Core#popSceneを行うとスタックの一番上のSceneを取り出すことができる.
2553          *
2554          * @return {enchant.Scene} 終了させたScene.
2555          [/lang]
2556          [lang:en]
2557          * Ends the current Scene, return to the previous Scene.
2558          *
2559          * Scenes are controlled using a stack, and the display order also obeys that stack order.
2560          * When {@link enchant.Core#popScene} is executed, the Scene at the top of the stack
2561          * will be removed and returned.
2562          *
2563          * @return {enchant.Scene} Ended Scene.
2564          [/lang]
2565          [lang:de]
2566          * Beendet die aktuelle Szene und wechselt zu der vorherigen Szene.
2567          *
2568          * Szenen werden durch einen Stapelspeicher kontrolliert und die Darstellungsreihenfolge
2569          * folgt ebenfalls der Ordnung des Stapelspeichers.
2570          * Wenn die {@link enchant.Core#popScene} Methode ausgeführt wird, wird die Szene oben auf dem
2571          * Stapelspeicher entfernt und liefert diese als Rückgabewert.
2572          *
2573          * @return {enchant.Scene} Die Szene, die beendet wurde.
2574          [/lang]
2575          */
2576         popScene: function() {
2577             if (this.currentScene === this.rootScene) {
2578                 return this.currentScene;
2579             }
2580             this._element.removeChild(this.currentScene._element);
2581             this.currentScene.dispatchEvent(new enchant.Event('exit'));
2582             this.currentScene = this._scenes[this._scenes.length - 2];
2583             this.currentScene.dispatchEvent(new enchant.Event('enter'));
2584             return this._scenes.pop();
2585         },
2586         /**
2587          [lang:ja]
2588          * 現在のSceneを別のSceneにおきかえる.
2589          *
2590          * enchant.Core#popScene, enchant.Core#pushSceneを同時に行う.
2591          *
2592          * @param {enchant.Scene} scene おきかえるScene.
2593          * @return {enchant.Scene} 新しいScene.
2594          [/lang]
2595          [lang:en]
2596          * Overwrites the current Scene with a new Scene.
2597          *
2598          * {@link enchant.Core#popScene}, {@link enchant.Core#pushScene} are executed after
2599          * each other to replace to current scene with the new scene.
2600          *
2601          * @param {enchant.Scene} scene The new scene which will replace the previous scene.
2602          * @return {enchant.Scene} The new Scene.
2603          [/lang]
2604          [lang:de]
2605          * Ersetzt die aktuelle Szene durch eine neue Szene.
2606          *
2607          * {@link enchant.Core#popScene}, {@link enchant.Core#pushScene} werden nacheinander
2608          * ausgeführt um die aktuelle Szene durch die neue zu ersetzen.
2609          *
2610          * @param {enchant.Scene} scene Die neue Szene, welche die aktuelle Szene ersetzen wird.
2611          * @return {enchant.Scene} Die neue Szene.
2612          [/lang]
2613          */
2614         replaceScene: function(scene) {
2615             this.popScene();
2616             return this.pushScene(scene);
2617         },
2618         /**
2619          [lang:ja]
2620          * Scene削除する.
2621          *
2622          * Sceneスタック中からSceneを削除する.
2623          *
2624          * @param {enchant.Scene} scene 削除するScene.
2625          * @return {enchant.Scene} 削除したScene.
2626          [/lang]
2627          [lang:en]
2628          * Removes a Scene.
2629          *
2630          * Removes a Scene from the Scene stack.
2631          *
2632          * @param {enchant.Scene} scene Scene to be removed.
2633          * @return {enchant.Scene} The deleted Scene.
2634          [/lang]
2635          [lang:de]
2636          * Entfernt eine Szene.
2637          *
2638          * Entfernt eine Szene aus dem Szenen-Stapelspeicher.
2639          *
2640          * @param {enchant.Scene} scene Die Szene die entfernt werden soll.
2641          * @return {enchant.Scene} Die entfernte Szene.
2642          [/lang]
2643          */
2644         removeScene: function(scene) {
2645             if (this.currentScene === scene) {
2646                 return this.popScene();
2647             } else {
2648                 var i = this._scenes.indexOf(scene);
2649                 if (i !== -1) {
2650                     this._scenes.splice(i, 1);
2651                     this._element.removeChild(scene._element);
2652                     return scene;
2653                 } else {
2654                     return null;
2655                 }
2656             }
2657         },
2658         /**
2659          [lang:ja]
2660          * キーバインドを設定する.
2661          *
2662          * @param {Number} key キーバインドを設定するキーコード.
2663          * @param {String} button 割り当てるボタン.
2664          [/lang]
2665          [lang:en]
2666          * Set a key binding.
2667          *
2668          * @param {Number} key Key code for the button which will be bound.
2669          * @param {String} button The enchant.js button (left, right, up, down, a, b).
2670          [/lang]
2671          [lang:de]
2672          * Bindet eine Taste.
2673          *
2674          * @param {Number} key Der Tastencode der Taste die gebunden werden soll.
2675          * @param {String} button Der enchant.js Knopf (left, right, up, down, a, b).
2676          [/lang]
2677          * @return {enchant.Core} this
2678          */
2679         keybind: function(key, button) {
2680             this._keybind[key] = button;
2681             var onxbuttondown = function(e) {
2682                 var inputEvent;
2683                 if (!this.input[button]) {
2684                     this.input[button] = true;
2685                     inputEvent = new enchant.Event((this.pressedKeysNum++) ? 'inputchange' : 'inputstart');
2686                     this.dispatchEvent(inputEvent);
2687                     this.currentScene.dispatchEvent(inputEvent);
2688                 }
2689                 this.currentScene.dispatchEvent(e);
2690             };
2691             var onxbuttonup = function(e) {
2692                 var inputEvent;
2693                 if (this.input[button]) {
2694                     this.input[button] = false;
2695                     inputEvent = new enchant.Event((--this.pressedKeysNum) ? 'inputchange' : 'inputend');
2696                     this.dispatchEvent(inputEvent);
2697                     this.currentScene.dispatchEvent(inputEvent);
2698                 }
2699                 this.currentScene.dispatchEvent(e);
2700             };
2701
2702             this.addEventListener(button + 'buttondown', onxbuttondown);
2703             this.addEventListener(button + 'buttonup', onxbuttonup);
2704
2705             this._internalButtondownListeners[key] = onxbuttondown;
2706             this._internalButtonupListeners[key] = onxbuttonup;
2707             return this;
2708         },
2709         /**
2710          [lang:ja]
2711          * キーバインドを削除する.
2712          * @param {Number} key 削除するキーコード.
2713          [/lang]
2714          [lang:en]
2715          * Delete a key binding.
2716          *
2717          * @param {Number} key Key code that want to delete.
2718          [/lang]
2719          [lang:de]
2720          * Entbindet eine Taste.
2721          *
2722          * @param {Number} key Der Tastencode der entfernt werden soll.
2723          [/lang]
2724          * @return {enchant.Core} this
2725          */
2726         keyunbind: function(key) {
2727             if (!this._keybind[key]) {
2728                 return this;
2729             }
2730             var buttondowns = this._internalButtondownListeners;
2731             var buttonups = this._internalButtonupListeners;
2732
2733             this.removeEventListener(key + 'buttondown', buttondowns);
2734             this.removeEventListener(key + 'buttonup', buttonups);
2735
2736             delete buttondowns[key];
2737             delete buttonups[key];
2738
2739             delete this._keybind[key];
2740
2741             return this;
2742         },
2743         /**
2744          [lang:ja]
2745          * Core#start が呼ばれてから経過した時間を取得する
2746          * @return {Number} 経過した時間 (秒)
2747          [/lang]
2748          [lang:en]
2749          * Get the elapsed core time (not actual) from when core.start was called.
2750          * @return {Number} The elapsed time (seconds)
2751          [/lang]
2752          [lang:de]
2753          * Liefert die vergange Spielzeit (keine reale) die seit dem Aufruf von core.start
2754          * vergangen ist.
2755          * @return {Number} Die vergangene Zeit (Sekunden)
2756          [/lang]
2757          */
2758         getElapsedTime: function() {
2759             return this.frame / this.fps;
2760         }
2761     });
2762
2763     /**
2764      [lang:ja]
2765      * 拡張子に対応したアセットのロード関数.
2766      * ロード関数はファイルのパス, 拡張子, コールバックを引数に取り,
2767      * 対応したクラスのインスタンスを返す必要がある.
2768      * コールバックはEvent.LOADとEvent.ERRORでハンドルする.
2769      [/lang]
2770      * @static
2771      * @private
2772      * @type {Object.<String, Function>}
2773      */
2774     enchant.Core._loadFuncs = {};
2775     enchant.Core._loadFuncs['jpg'] =
2776         enchant.Core._loadFuncs['jpeg'] =
2777             enchant.Core._loadFuncs['gif'] =
2778                 enchant.Core._loadFuncs['png'] =
2779                     enchant.Core._loadFuncs['bmp'] = function(src, ext, callback, onerror) {
2780                         return enchant.Surface.load(src, callback, onerror);
2781                     };
2782     enchant.Core._loadFuncs['mp3'] =
2783         enchant.Core._loadFuncs['aac'] =
2784             enchant.Core._loadFuncs['m4a'] =
2785                 enchant.Core._loadFuncs['wav'] =
2786                     enchant.Core._loadFuncs['ogg'] = function(src, ext, callback, onerror) {
2787                         return enchant.Sound.load(src, 'audio/' + ext, callback, onerror);
2788                     };
2789
2790     /**
2791      * Get the file extension from a path
2792      * @param path
2793      * @return {*}
2794      */
2795     enchant.Core.findExt = function(path) {
2796         var matched = path.match(/\.\w+$/);
2797         if (matched && matched.length > 0) {
2798             return matched[0].slice(1).toLowerCase();
2799         }
2800
2801         // for data URI
2802         if (path.indexOf('data:') === 0) {
2803             return path.split(/[\/;]/)[1].toLowerCase();
2804         }
2805         return null;
2806     };
2807
2808     /**
2809      [lang:ja]
2810      * 現在のCoreインスタンス.
2811      [/lang]
2812      [lang:en]
2813      * The Current Core instance.
2814      [/lang]
2815      [lang:de]
2816      * Die aktuelle Instanz des Spieles.
2817      [/lang]
2818      * @type {enchant.Core}
2819      * @static
2820      */
2821     enchant.Core.instance = null;
2822 }());
2823
2824 /**
2825  * enchant.Core is moved to enchant.Core from v0.6
2826  * @type {*}
2827  */
2828 enchant.Game = enchant.Core;
2829 /**
2830  * @scope enchant.Node.prototype
2831  */
2832 enchant.Node = enchant.Class.create(enchant.EventTarget, {
2833     /**
2834      * @name enchant.Node
2835      * @class
2836      [lang:ja]
2837      * Sceneをルートとした表示オブジェクトツリーに属するオブジェクトの基底クラス.
2838      * 直接使用することはない.
2839      [/lang]
2840      [lang:en]
2841      * Base class for objects in the display tree which is rooted at a Scene.
2842      * Not to be used directly.
2843      [/lang]
2844      [lang:de]
2845      * Basisklasse für Objekte die im Darstellungsbaum, 
2846      * dessen Wurzel eine Szene ist, enthalten sind.
2847      * Sollte nicht direkt verwendet werden.
2848      [/lang]
2849      * @constructs
2850      * @extends enchant.EventTarget
2851      */
2852     initialize: function() {
2853         enchant.EventTarget.call(this);
2854
2855         this._dirty = false;
2856
2857         this._matrix = [ 1, 0, 0, 1, 0, 0 ];
2858
2859         this._x = 0;
2860         this._y = 0;
2861         this._offsetX = 0;
2862         this._offsetY = 0;
2863
2864         /**
2865          [lang:ja]
2866          * Node が画面に表示されてから経過したフレーム数。
2867          * {@link enchant.Event.ENTER_FRAME} イベントを受け取る前にインクリメントされる。
2868          * (ENTER_FRAME イベントのリスナが初めて実行される時に 1 となる。)
2869          [/lang]
2870          [lang:en]
2871          * The age (frames) of this node which will be increased before this node receives {@link enchant.Event.ENTER_FRAME} event.
2872          [/lang]
2873          [lang:de]
2874          * Das Alter (Frames) dieses Nodes welches vor dem {@link enchant.Event.ENTER_FRAME} Ereignis erhöht wird.
2875          [/lang]
2876          * @type {Number}
2877          */
2878         this.age = 0;
2879
2880         /**
2881          [lang:ja]
2882          * Nodeの親Node.
2883          [/lang]
2884          [lang:en]
2885          * Parent Node of this Node.
2886          [/lang]
2887          [lang:de]
2888          * Der Eltern-Node dieses Node.
2889          [/lang]
2890          * @type {enchant.Group}
2891          */
2892         this.parentNode = null;
2893         /**
2894          [lang:ja]
2895          * Nodeが属しているScene.
2896          [/lang]
2897          [lang:en]
2898          * Scene to which Node belongs.
2899          [/lang]
2900          [lang:de]
2901          * Die Szene, zu welcher dieser Node gehört.
2902          [/lang]
2903          * @type {enchant.Scene}
2904          */
2905         this.scene = null;
2906
2907         this.addEventListener('touchstart', function(e) {
2908             if (this.parentNode) {
2909                 this.parentNode.dispatchEvent(e);
2910             }
2911         });
2912         this.addEventListener('touchmove', function(e) {
2913             if (this.parentNode) {
2914                 this.parentNode.dispatchEvent(e);
2915             }
2916         });
2917         this.addEventListener('touchend', function(e) {
2918             if (this.parentNode) {
2919                 this.parentNode.dispatchEvent(e);
2920             }
2921         });
2922
2923         /**
2924          [lang:ja]
2925          * Node が生成される際に、tl プロパティに Timeline オブジェクトを追加している
2926          [/lang]
2927          */
2928         if(enchant.ENV.USE_ANIMATION){
2929             var tl = this.tl = new enchant.Timeline(this);
2930         }
2931     },
2932     /**
2933      [lang:ja]
2934      * Nodeを移動する.
2935      * @param {Number} x 移動先のx座標.
2936      * @param {Number} y 移動先のy座標.
2937      [/lang]
2938      [lang:en]
2939      * Move the Node to the given target location.
2940      * @param {Number} x Target x coordinates.
2941      * @param {Number} y Target y coordinates.
2942      [/lang]
2943      [lang:de]
2944      * Bewegt diesen Node zu den gegebenen Ziel Koordinaten.
2945      * @param {Number} x Ziel x Koordinaten.
2946      * @param {Number} y Ziel y Koordinaten.
2947      [/lang]
2948      */
2949     moveTo: function(x, y) {
2950         this._x = x;
2951         this._y = y;
2952         this._dirty = true;
2953     },
2954     /**
2955      [lang:ja]
2956      * Nodeを移動する.
2957      * @param {Number} x 移動するx軸方向の距離.
2958      * @param {Number} y 移動するy軸方向の距離.
2959      [/lang]
2960      [lang:en]
2961      * Move the Node relative to its current position.
2962      * @param {Number} x x axis movement distance.
2963      * @param {Number} y y axis movement distance.
2964      [/lang]
2965      [lang:de]
2966      * Bewegt diesen Node relativ zur aktuellen Position.
2967      * @param {Number} x Distanz auf der x Achse.
2968      * @param {Number} y Distanz auf der y Achse.
2969      [/lang]
2970      */
2971     moveBy: function(x, y) {
2972         this._x += x;
2973         this._y += y;
2974         this._dirty = true;
2975     },
2976     /**
2977      [lang:ja]
2978      * Nodeのx座標.
2979      [/lang]
2980      [lang:en]
2981      * x coordinates of the Node.
2982      [/lang]
2983      [lang:de]
2984      * Die x Koordinaten des Nodes.
2985      [/lang]
2986      * @type {Number}
2987      */
2988     x: {
2989         get: function() {
2990             return this._x;
2991         },
2992         set: function(x) {
2993             this._x = x;
2994             this._dirty = true;
2995         }
2996     },
2997     /**
2998      [lang:ja]
2999      * Nodeのy座標.
3000      [/lang]
3001      [lang:en]
3002      * y coordinates of the Node.
3003      [/lang]
3004      [lang:de]
3005      * Die y Koordinaten des Nodes.
3006      [/lang]
3007      * @type {Number}
3008      */
3009     y: {
3010         get: function() {
3011             return this._y;
3012         },
3013         set: function(y) {
3014             this._y = y;
3015             this._dirty = true;
3016         }
3017     },
3018     _updateCoordinate: function() {
3019         var node = this;
3020         var tree = [ node ];
3021         var parent = node.parentNode;
3022         var scene = this.scene;
3023         while (parent && node._dirty) {
3024             tree.unshift(parent);
3025             node = node.parentNode;
3026             parent = node.parentNode;
3027         }
3028         var matrix = enchant.Matrix.instance;
3029         var stack = matrix.stack;
3030         var mat = [];
3031         var newmat, ox, oy;
3032         stack.push(tree[0]._matrix);
3033         for (var i = 1, l = tree.length; i < l; i++) {
3034             node = tree[i];
3035             newmat = [];
3036             matrix.makeTransformMatrix(node, mat);
3037             matrix.multiply(stack[stack.length - 1], mat, newmat);
3038             node._matrix = newmat;
3039             stack.push(newmat);
3040             ox = (typeof node._originX === 'number') ? node._originX : node._width / 2 || 0;
3041             oy = (typeof node._originY === 'number') ? node._originY : node._height / 2 || 0;
3042             var vec = [ ox, oy ];
3043             matrix.multiplyVec(newmat, vec, vec);
3044             node._offsetX = vec[0] - ox;
3045             node._offsetY = vec[1] - oy;
3046             node._dirty = false;
3047         }
3048         matrix.reset();
3049     },
3050     remove: function() {
3051         if (this._listener) {
3052             this.clearEventListener();
3053         }
3054         if (this.parentNode) {
3055             this.parentNode.removeChild(this);
3056         }
3057     }
3058 });
3059
3060 var _intersectBetweenClassAndInstance = function(Class, instance) {
3061     var ret = [];
3062     var c;
3063     for (var i = 0, l = Class.collection.length; i < l; i++) {
3064         c = Class.collection[i];
3065         if (instance._intersectOne(c)) {
3066             ret.push(c);
3067         }
3068     }
3069     return ret;
3070 };
3071
3072 var _intersectBetweenClassAndClass = function(Class1, Class2) {
3073     var ret = [];
3074     var c1, c2;
3075     for (var i = 0, l = Class1.collection.length; i < l; i++) {
3076         c1 = Class1.collection[i];
3077         for (var j = 0, ll = Class2.collection.length; j < ll; j++) {
3078             c2 = Class2.collection[j];
3079             if (c1._intersectOne(c2)) {
3080                 ret.push([ c1, c2 ]);
3081             }
3082         }
3083     }
3084     return ret;
3085 };
3086
3087 var _intersectStrictBetweenClassAndInstance = function(Class, instance) {
3088     var ret = [];
3089     var c;
3090     for (var i = 0, l = Class.collection.length; i < l; i++) {
3091         c = Class.collection[i];
3092         if (instance._intersectStrictOne(c)) {
3093             ret.push(c);
3094         }
3095     }
3096     return ret;
3097 };
3098
3099 var _intersectStrictBetweenClassAndClass = function(Class1, Class2) {
3100     var ret = [];
3101     var c1, c2;
3102     for (var i = 0, l = Class1.collection.length; i < l; i++) {
3103         c1 = Class1.collection[i];
3104         for (var j = 0, ll = Class2.collection.length; j < ll; j++) {
3105             c2 = Class2.collection[j];
3106             if (c1._intersectStrictOne(c2)) {
3107                 ret.push([ c1, c2 ]);
3108             }
3109         }
3110     }
3111     return ret;
3112 };
3113
3114 var _staticIntersect = function(other) {
3115     if (other instanceof enchant.Entity) {
3116         return _intersectBetweenClassAndInstance(this, other);
3117     } else if (typeof other === 'function' && other.collection) {
3118         return _intersectBetweenClassAndClass(this, other);
3119     }
3120     return false;
3121 };
3122
3123 var _staticIntersectStrict = function(other) {
3124     if (other instanceof enchant.Entity) {
3125         return _intersectStrictBetweenClassAndInstance(this, other);
3126     } else if (typeof other === 'function' && other.collection) {
3127         return _intersectStrictBetweenClassAndClass(this, other);
3128     }
3129     return false;
3130 };
3131
3132 /**
3133  * @scope enchant.Entity.prototype
3134  */
3135 enchant.Entity = enchant.Class.create(enchant.Node, {
3136     /**
3137      * @name enchant.Entity
3138      * @class
3139      [lang:ja]
3140      * DOM上で表示する実体を持ったクラス. 直接使用することはない.
3141      [/lang]
3142      [lang:en]
3143      * A class with objects displayed as DOM elements. Not to be used directly.
3144      [/lang]
3145      [lang:de]
3146      * Eine Klasse die Objekte mit Hilfe von DOM Elementen darstellt.
3147      * Sollte nicht direkt verwendet werden.
3148      [/lang]
3149      * @constructs
3150      * @extends enchant.Node
3151      */
3152     initialize: function() {
3153         var core = enchant.Core.instance;
3154         enchant.Node.call(this);
3155
3156         this._rotation = 0;
3157         this._scaleX = 1;
3158         this._scaleY = 1;
3159
3160         this._touchEnabled = true;
3161         this._clipping = false;
3162
3163         this._originX = null;
3164         this._originY = null;
3165
3166         this._width = 0;
3167         this._height = 0;
3168         this._backgroundColor = null;
3169         this._debugColor = '#0000ff';
3170         this._opacity = 1;
3171         this._visible = true;
3172         this._buttonMode = null;
3173
3174         this._style = {};
3175         this.__styleStatus = {};
3176
3177         /**
3178          [lang:ja]
3179          * Entityを描画する際の合成処理を設定する.
3180          * Canvas上に描画する際のみ有効.
3181          * CanvasのコンテキストのglobalCompositeOperationにセットされる.
3182          [/lang]
3183          */
3184         this.compositeOperation = null;
3185
3186         /**
3187          [lang:ja]
3188          * Entityにボタンの機能を設定する.
3189          * Entityに対するタッチ, クリックをleft, right, up, down, a, bいずれかの
3190          * ボタン入力として割り当てる.
3191          [/lang]
3192          [lang:en]
3193          * Defines this Entity as a button.
3194          * When touched or clicked the corresponding button event is dispatched.
3195          * Valid buttonModes are: left, right, up, down, a, b. 
3196          [/lang]
3197          [lang:de]
3198          * Definiert diese Entity als Schaltfläche (Button).
3199          * Bei einem Klick oder Touch wird das entsprechende
3200          * Button Ereignis (Event) ausgelöst.
3201          * Mögliche buttonModes sind: left, right, up, down, a, b. 
3202          [/lang]
3203          * @type {String}
3204          */
3205         this.buttonMode = null;
3206         /**
3207          [lang:ja]
3208          * Entityが押されているかどうか.
3209          * {@link enchant.Entity.buttonMode}が設定されているときだけ機能する.
3210          [/lang]
3211          [lang:en]
3212          * Indicates if this Entity is being clicked.
3213          * Only works when {@link enchant.Entity.buttonMode} is set.
3214          [/lang]
3215          [lang:de]
3216          * Zeigt an, ob auf die Entity geklickt wurde.
3217          * Funktioniert nur wenn {@link enchant.Entity.buttonMode} gesetzt ist.
3218          [/lang]
3219          * @type {Boolean}
3220          */
3221         this.buttonPressed = false;
3222         this.addEventListener('touchstart', function() {
3223             if (!this.buttonMode) {
3224                 return;
3225             }
3226             this.buttonPressed = true;
3227             var e = new enchant.Event(this.buttonMode + 'buttondown');
3228             this.dispatchEvent(e);
3229             core.dispatchEvent(e);
3230         });
3231         this.addEventListener('touchend', function() {
3232             if (!this.buttonMode) {
3233                 return;
3234             }
3235             this.buttonPressed = false;
3236             var e = new enchant.Event(this.buttonMode + 'buttonup');
3237             this.dispatchEvent(e);
3238             core.dispatchEvent(e);
3239         });
3240
3241         this.enableCollection();
3242     },
3243     /**
3244      [lang:ja]
3245      * Entityの横幅.
3246      [/lang]
3247      [lang:en]
3248      * The width of the Entity.
3249      [/lang]
3250      [lang:de]
3251      * Die Breite der Entity.
3252      [/lang]
3253      * @type {Number}
3254      */
3255     width: {
3256         get: function() {
3257             return this._width;
3258         },
3259         set: function(width) {
3260             this._width = width;
3261             this._dirty = true;
3262         }
3263     },
3264     /**
3265      [lang:ja]
3266      * Entityの高さ.
3267      [/lang]
3268      [lang:en]
3269      * The height of the Entity.
3270      [/lang]
3271      [lang:de]
3272      * Die Höhe der Entity.
3273      [/lang]
3274      * @type {Number}
3275      */
3276     height: {
3277         get: function() {
3278             return this._height;
3279         },
3280         set: function(height) {
3281             this._height = height;
3282             this._dirty = true;
3283         }
3284     },
3285     /**
3286      [lang:ja]
3287      * Entityの背景色.
3288      * CSSの'color'プロパティと同様の形式で指定できる.
3289      [/lang]
3290      [lang:en]
3291      * The Entity background color.
3292      * Must be provided in the same format as the CSS 'color' property.
3293      [/lang]
3294      [lang:de]
3295      * Die Hintergrundfarbe der Entity.
3296      * Muss im gleichen Format definiert werden wie das CSS 'color' Attribut.
3297      [/lang]
3298      * @type {String}
3299      */
3300     backgroundColor: {
3301         get: function() {
3302             return this._backgroundColor;
3303         },
3304         set: function(color) {
3305             this._backgroundColor = color;
3306         }
3307     },
3308     /**
3309      [lang:ja]
3310      * Entityのデバッグの枠色.
3311      * CSSの'color'プロパティと同様の形式で指定できる.
3312      [/lang]
3313      [lang:en]
3314      * The Entity debug color.
3315      * Must be provided in the same format as the CSS 'color' property.
3316      [/lang]
3317      * @type {String}
3318      */
3319     debugColor: {
3320         get: function() {
3321             return this._debugColor;
3322         },
3323         set: function(color) {
3324             this._debugColor = color;
3325         }
3326     },
3327     /**
3328      [lang:ja]
3329      * Entityの透明度.
3330      * 0から1までの値を設定する(0が完全な透明, 1が完全な不透明).
3331      [/lang]
3332      [lang:en]
3333      * The transparency of this entity.
3334      * Defines the transparency level from 0 to 1
3335      * (0 is completely transparent, 1 is completely opaque).
3336      [/lang]
3337      [lang:de]
3338      * Transparenz der Entity.
3339      * Definiert den Level der Transparenz von 0 bis 1
3340      * (0 ist komplett transparent, 1 ist vollständig deckend).
3341      [/lang]
3342      * @type {Number}
3343      */
3344     opacity: {
3345         get: function() {
3346             return this._opacity;
3347         },
3348         set: function(opacity) {
3349             this._opacity = parseFloat(opacity);
3350         }
3351     },
3352     /**
3353      [lang:ja]
3354      * Entityを表示するかどうかを指定する.
3355      [/lang]
3356      [lang:en]
3357      * Indicates whether or not to display this Entity.
3358      [/lang]
3359      [lang:de]
3360      * Zeigt an, ob die Entity dargestellt werden soll oder nicht.
3361      [/lang]
3362      * @type {Boolean}
3363      */
3364     visible: {
3365         get: function() {
3366             return this._visible;
3367         },
3368         set: function(visible) {
3369             this._visible = visible;
3370         }
3371     },
3372     /**
3373      [lang:ja]
3374      * Entityのタッチを有効にするかどうかを指定する.
3375      [/lang]
3376      [lang:en]
3377      * Indicates whether or not this Entity can be touched.
3378      [/lang]
3379      [lang:de]
3380      * Definiert ob auf die Entity geklickt werden kann. 
3381      [/lang]
3382      * @type {Boolean}
3383      */
3384     touchEnabled: {
3385         get: function() {
3386             return this._touchEnabled;
3387         },
3388         set: function(enabled) {
3389             this._touchEnabled = enabled;
3390             if (enabled) {
3391                 this._style.pointerEvents = 'all';
3392             } else {
3393                 this._style.pointerEvents = 'none';
3394             }
3395         }
3396     },
3397     /**
3398      [lang:ja]
3399      * Entityの矩形が交差しているかどうかにより衝突判定を行う.
3400      * @param {*} other 衝突判定を行うEntityなどx, y, width, heightプロパティを持ったObject.
3401      * @return {Boolean} 衝突判定の結果.
3402      [/lang]
3403      [lang:en]
3404      * Performs a collision detection based on whether or not the bounding rectangles are intersecting.
3405      * @param {*} other An object like Entity, with the properties x, y, width, height, which are used for the 
3406      * collision detection.
3407      * @return {Boolean} True, if a collision was detected.
3408      [/lang]
3409      [lang:de]
3410      * Führt eine Kollisionsdetektion durch, die überprüft ob eine Überschneidung zwischen den
3411      * begrenzenden Rechtecken existiert. 
3412      * @param {*} other Ein Objekt wie Entity, welches x, y, width und height Variablen besitzt,
3413      * mit dem die Kollisionsdetektion durchgeführt wird.
3414      * @return {Boolean} True, falls eine Kollision festgestellt wurde.
3415      [/lang]
3416      */
3417     intersect: function(other) {
3418         if (other instanceof enchant.Entity) {
3419             return this._intersectOne(other);
3420         } else if (typeof other === 'function' && other.collection) {
3421             return _intersectBetweenClassAndInstance(other, this);
3422         }
3423         return false;
3424     },
3425     _intersectOne: function(other) {
3426         if (this._dirty) {
3427             this._updateCoordinate();
3428         } if (other._dirty) {
3429             other._updateCoordinate();
3430         }
3431         return this._offsetX < other._offsetX + other.width && other._offsetX < this._offsetX + this.width &&
3432             this._offsetY < other._offsetY + other.height && other._offsetY < this._offsetY + this.height;
3433     },
3434     intersectStrict: function(other) {
3435         if (other instanceof enchant.Entity) {
3436             return this._intersectStrictOne(other);
3437         } else if (typeof other === 'function' && other.collection) {
3438             return _intersectStrictBetweenClassAndInstance(other, this);
3439         }
3440         return false;
3441     },
3442     _intersectStrictOne: function(other) {
3443         if (this._dirty) {
3444             this._updateCoordinate();
3445         } if (other._dirty) {
3446             other._updateCoordinate();
3447         }
3448         var rect1 = this.getOrientedBoundingRect(),
3449             rect2 = other.getOrientedBoundingRect(),
3450             lt1 = rect1.leftTop, rt1 = rect1.rightTop,
3451             lb1 = rect1.leftBottom, rb1 = rect1.rightBottom,
3452             lt2 = rect2.leftTop, rt2 = rect2.rightTop,
3453             lb2 = rect2.leftBottom, rb2 = rect2.rightBottom,
3454             ltx1 = lt1[0], lty1 = lt1[1], rtx1 = rt1[0], rty1 = rt1[1],
3455             lbx1 = lb1[0], lby1 = lb1[1], rbx1 = rb1[0], rby1 = rb1[1],
3456             ltx2 = lt2[0], lty2 = lt2[1], rtx2 = rt2[0], rty2 = rt2[1],
3457             lbx2 = lb2[0], lby2 = lb2[1], rbx2 = rb2[0], rby2 = rb2[1],
3458             t1 = [ rtx1 - ltx1, rty1 - lty1 ],
3459             r1 = [ rbx1 - rtx1, rby1 - rty1 ],
3460             b1 = [ lbx1 - rbx1, lby1 - rby1 ],
3461             l1 = [ ltx1 - lbx1, lty1 - lby1 ],
3462             t2 = [ rtx2 - ltx2, rty2 - lty2 ],
3463             r2 = [ rbx2 - rtx2, rby2 - rty2 ],
3464             b2 = [ lbx2 - rbx2, lby2 - rby2 ],
3465             l2 = [ ltx2 - lbx2, lty2 - lby2 ],
3466             cx1 = (ltx1 + rtx1 + lbx1 + rbx1) >> 2,
3467             cy1 = (lty1 + rty1 + lby1 + rby1) >> 2,
3468             cx2 = (ltx2 + rtx2 + lbx2 + rbx2) >> 2,
3469             cy2 = (lty2 + rty2 + lby2 + rby2) >> 2,
3470             i, j, poss1, poss2, dirs1, dirs2, pos1, pos2, dir1, dir2,
3471             px1, py1, px2, py2, dx1, dy1, dx2, dy2, vx, vy, c, c1, c2;
3472         if (t1[0] * (cy2 - lty1) - t1[1] * (cx2 - ltx1) > 0 &&
3473             r1[0] * (cy2 - rty1) - r1[1] * (cx2 - rtx1) > 0 &&
3474             b1[0] * (cy2 - rby1) - b1[1] * (cx2 - rbx1) > 0 &&
3475             l1[0] * (cy2 - lby1) - l1[1] * (cx2 - lbx1) > 0) {
3476             return true;
3477         } else if (t2[0] * (cy1 - lty2) - t2[1] * (cx1 - ltx2) > 0 &&
3478             r2[0] * (cy1 - rty2) - r2[1] * (cx1 - rtx2) > 0 &&
3479             b2[0] * (cy1 - rby2) - b2[1] * (cx1 - rbx2) > 0 &&
3480             l2[0] * (cy1 - lby2) - l2[1] * (cx1 - lbx2) > 0) {
3481             return true;
3482         } else {
3483             poss1 = [ lt1, rt1, rb1, lb1 ];
3484             poss2 = [ lt2, rt2, rb2, lb2 ];
3485             dirs1 = [ t1, r1, b1, l1 ];
3486             dirs2 = [ t2, r2, b2, l2 ];
3487             for (i = 0; i < 4; i++) {
3488                 pos1 = poss1[i];
3489                 px1 = pos1[0]; py1 = pos1[1];
3490                 dir1 = dirs1[i];
3491                 dx1 = dir1[0]; dy1 = dir1[1];
3492                 for (j = 0; j < 4; j++) {
3493                     pos2 = poss2[j];
3494                     px2 = pos2[0]; py2 = pos2[1];
3495                     dir2 = dirs2[j];
3496                     dx2 = dir2[0]; dy2 = dir2[1];
3497                     c = dx1 * dy2 - dy1 * dx2;
3498                     if (c !== 0) {
3499                         vx = px2 - px1;
3500                         vy = py2 - py1;
3501                         c1 = (vx * dy1 - vy * dx1) / c;
3502                         c2 = (vx * dy2 - vy * dx2) / c;
3503                         if (0 < c1 && c1 < 1 && 0 < c2 && c2 < 1) {
3504                             return true;
3505                         }
3506                     }
3507                 }
3508             }
3509             return false;
3510         }
3511     },
3512     /**
3513      [lang:ja]
3514      * Entityの中心点どうしの距離により衝突判定を行う.
3515      * @param {*} other 衝突判定を行うEntityなどx, y, width, heightプロパティを持ったObject.
3516      * @param {Number} [distance] 衝突したと見なす最大の距離. デフォルト値は二つのEntityの横幅と高さの平均.
3517      * @return {Boolean} 衝突判定の結果.
3518      [/lang]
3519      [lang:en]
3520      * Performs a collision detection based on distance from the Entity's central point.
3521      * @param {*} other An object like Entity, with properties x, y, width, height, which are used for the 
3522      * collision detection.
3523      * @param {Number} [distance] The greatest distance to be considered for a collision.
3524      * The default distance is the average of both objects width and height.
3525      * @return {Boolean} True, if a collision was detected.
3526      [/lang]
3527      [lang:de]
3528      * Führt eine Kollisionsdetektion durch, die anhand der Distanz zwischen den Objekten feststellt,
3529      * ob eine Kollision aufgetreten ist.
3530      * @param {*} other Ein Objekt wie Entity, welches x, y, width und height Variablen besitzt,
3531      * mit dem die Kollisionsdetektion durchgeführt wird.
3532      * @param {Number} [distance] Die größte Distanz die für die Kollision in betracht gezogen wird.
3533      * Der Standardwert ist der Durchschnitt der Breite und Höhe beider Objekte.
3534      * @return {Boolean} True, falls eine Kollision festgestellt wurde.
3535      [/lang]
3536      */
3537     within: function(other, distance) {
3538         if (this._dirty) {
3539             this._updateCoordinate();
3540         } if (other._dirty) {
3541             other._updateCoordinate();
3542         }
3543         if (distance == null) {
3544             distance = (this.width + this.height + other.width + other.height) / 4;
3545         }
3546         var _;
3547         return (_ = this._offsetX - other._offsetX + (this.width - other.width) / 2) * _ +
3548             (_ = this._offsetY - other._offsetY + (this.height - other.height) / 2) * _ < distance * distance;
3549     }, /**
3550      [lang:ja]
3551      * Spriteを拡大縮小する.
3552      * @param {Number} x 拡大するx軸方向の倍率.
3553      * @param {Number} [y] 拡大するy軸方向の倍率.
3554      [/lang]
3555      [lang:en]
3556      * Enlarges or shrinks this Sprite.
3557      * @param {Number} x Scaling factor on the x axis.
3558      * @param {Number} [y] Scaling factor on the y axis.
3559      [/lang]
3560      [lang:de]
3561      * Vergrößert oder verkleinert dieses Sprite.
3562      * @param {Number} x Skalierungsfaktor auf der x-Achse.
3563      * @param {Number} [y] Skalierungsfaktor auf der y-Achse.
3564      [/lang]
3565      */
3566     scale: function(x, y) {
3567         this._scaleX *= x;
3568         this._scaleY *= (y != null) ? y : x;
3569         this._dirty = true;
3570     },
3571     /**
3572      [lang:ja]
3573      * Spriteを回転する.
3574      * @param {Number} deg 回転する角度 (度数法).
3575      [/lang]
3576      [lang:en]
3577      * Rotate this Sprite.
3578      * @param {Number} deg Rotation angle (degree).
3579      [/lang]
3580      [lang:de]
3581      * Rotiert dieses Sprite.
3582      * @param {Number} deg Rotationswinkel (Grad).
3583      [/lang]
3584      */
3585     rotate: function(deg) {
3586         this._rotation += deg;
3587         this._dirty = true;
3588     },
3589     /**
3590      [lang:ja]
3591      * Spriteのx軸方向の倍率.
3592      [/lang]
3593      [lang:en]
3594      * Scaling factor on the x axis of this Sprite.
3595      [/lang]
3596      [lang:de]
3597      * Skalierungsfaktor auf der x-Achse dieses Sprites.
3598      [/lang]
3599      * @type {Number}
3600      */
3601     scaleX: {
3602         get: function() {
3603             return this._scaleX;
3604         },
3605         set: function(scaleX) {
3606             this._scaleX = scaleX;
3607             this._dirty = true;
3608         }
3609     },
3610     /**
3611      [lang:ja]
3612      * Spriteのy軸方向の倍率.
3613      [/lang]
3614      [lang:en]
3615      * Scaling factor on the y axis of this Sprite.
3616      [/lang]
3617      [lang:de]
3618      * Skalierungsfaktor auf der y-Achse dieses Sprites.
3619      [/lang]
3620      * @type {Number}
3621      */
3622     scaleY: {
3623         get: function() {
3624             return this._scaleY;
3625         },
3626         set: function(scaleY) {
3627             this._scaleY = scaleY;
3628             this._dirty = true;
3629         }
3630     },
3631     /**
3632      [lang:ja]
3633      * Spriteの回転角 (度数法).
3634      [/lang]
3635      [lang:en]
3636      * Sprite rotation angle (degree).
3637      [/lang]
3638      [lang:de]
3639      * Rotationswinkel des Sprites (Grad).
3640      [/lang]
3641      * @type {Number}
3642      */
3643     rotation: {
3644         get: function() {
3645             return this._rotation;
3646         },
3647         set: function(rotation) {
3648             this._rotation = rotation;
3649             this._dirty = true;
3650         }
3651     },
3652     /**
3653      [lang:ja]
3654      * 回転・拡大縮小の基準点のX座標
3655      [/lang]
3656      [lang:en]
3657      * The point of origin used for rotation and scaling.
3658      [/lang]
3659      [lang:de]
3660      * Ausgangspunkt für Rotation und Skalierung.
3661      [/lang]
3662      * @type {Number}
3663      */
3664     originX: {
3665         get: function() {
3666             return this._originX;
3667         },
3668         set: function(originX) {
3669             this._originX = originX;
3670             this._dirty = true;
3671         }
3672     },
3673     /**
3674      [lang:ja]
3675      * 回転・拡大縮小の基準点のY座標
3676      [/lang]
3677      [lang:en]
3678      * The point of origin used for rotation and scaling.
3679      [/lang]
3680      [lang:de]
3681      * Ausgangspunkt für Rotation und Skalierung.
3682      [/lang]
3683      * @type {Number}
3684      */
3685     originY: {
3686         get: function() {
3687             return this._originY;
3688         },
3689         set: function(originY) {
3690             this._originY = originY;
3691             this._dirty = true;
3692         }
3693     },
3694     /**
3695      [lang:ja]
3696      * インスタンスをコレクションの対象にする.
3697      * デフォルトで呼び出される.
3698      [/lang]
3699      */
3700     enableCollection: function() {
3701         this.addEventListener('addedtoscene', this._addSelfToCollection);
3702         this.addEventListener('removedfromscene', this._removeSelfFromCollection);
3703         if (this.scene) {
3704             this._addSelfToCollection();
3705         }
3706     },
3707     /**
3708      [lang:ja]
3709      * インスタンスをコレクションの対象から除外する.
3710      [/lang]
3711      */
3712     disableCollection: function() {
3713         this.removeEventListener('addedtoscene', this._addSelfToCollection);
3714         this.removeEventListener('removedfromscene', this._removeSelfFromCollection);
3715         if (this.scene) {
3716             this._removeSelfFromCollection();
3717         }
3718     },
3719     _addSelfToCollection: function() {
3720         var Constructor = this.getConstructor();
3721         Constructor._collectionTarget.forEach(function(C) {
3722             C.collection.push(this);
3723         }, this);
3724     },
3725     _removeSelfFromCollection: function() {
3726         var Constructor = this.getConstructor();
3727         Constructor._collectionTarget.forEach(function(C) {
3728             var i = C.collection.indexOf(this);
3729             if (i !== -1) {
3730                 C.collection.splice(i, 1);
3731             }
3732         }, this);
3733     },
3734     getBoundingRect: function() {
3735         var w = this.width || 0;
3736         var h = this.height || 0;
3737         var mat = this._matrix;
3738         var m11w = mat[0] * w, m12w = mat[1] * w,
3739             m21h = mat[2] * h, m22h = mat[3] * h,
3740             mdx = mat[4], mdy = mat[5];
3741         var xw = [ mdx, m11w + mdx, m21h + mdx, m11w + m21h + mdx ].sort(function(a, b) { return a - b; });
3742         var yh = [ mdy, m12w + mdy, m22h + mdy, m12w + m22h + mdy ].sort(function(a, b) { return a - b; });
3743
3744         return {
3745             left: xw[0],
3746             top: yh[0],
3747             width: xw[3] - xw[0],
3748             height: yh[3] - yh[0]
3749         };
3750     },
3751     getOrientedBoundingRect: function() {
3752         var w = this.width || 0;
3753         var h = this.height || 0;
3754         var mat = this._matrix;
3755         var m11w = mat[0] * w, m12w = mat[1] * w,
3756             m21h = mat[2] * h, m22h = mat[3] * h,
3757             mdx = mat[4], mdy = mat[5];
3758
3759         return {
3760             leftTop: [ mdx, mdy ],
3761             rightTop: [ m11w + mdx, m12w + mdy ],
3762             leftBottom: [ m21h + mdx, m22h + mdy ],
3763             rightBottom: [ m11w + m21h + mdx, m12w + m22h + mdy ]
3764         };
3765     },
3766     getConstructor: function() {
3767         return Object.getPrototypeOf(this).constructor;
3768     }
3769 });
3770
3771 var _collectizeConstructor = function(Constructor) {
3772     if (Constructor._collective) {
3773         return;
3774     }
3775     var rel = enchant.Class.getInheritanceTree(Constructor);
3776     var i = rel.indexOf(enchant.Entity);
3777     if (i !== -1) {
3778         Constructor._collectionTarget = rel.splice(0, i + 1);
3779     } else {
3780         Constructor._collectionTarget = [];
3781     }
3782     Constructor.intersect = _staticIntersect;
3783     Constructor.intersectStrict = _staticIntersectStrict;
3784     Constructor.collection = [];
3785     Constructor._collective = true;
3786 };
3787
3788 _collectizeConstructor(enchant.Entity);
3789
3790 enchant.Entity._inherited = function(subclass) {
3791     _collectizeConstructor(subclass);
3792 };
3793
3794 /**
3795  * @scope enchant.Sprite.prototype
3796  */
3797 enchant.Sprite = enchant.Class.create(enchant.Entity, {
3798     /**
3799      * @name enchant.Sprite
3800      * @class
3801      [lang:ja]
3802      * 画像表示機能を持ったクラス. Entity を継承している.
3803      *
3804      * @param {Number} [width] Spriteの横幅.
3805      * @param {Number} [height] Spriteの高さ.
3806      [/lang]
3807      [lang:en]
3808      * Class which can display images.
3809      * 
3810      * @param {Number} [width] Sprite width.
3811      * @param {Number} [height] Sprite height.
3812      [/lang]
3813      [lang:de]
3814      * Eine Klasse die Grafiken darstellen kann.
3815      * 
3816      * @param {Number} [width] Die Breite des Sprites.
3817      * @param {Number} [height] Die Höhe des Sprites.
3818      [/lang]
3819      * @example
3820      *   var bear = new Sprite(32, 32);
3821      *   bear.image = core.assets['chara1.gif'];
3822      *   
3823      * @constructs
3824      * @extends enchant.Entity
3825      */
3826     initialize: function(width, height) {
3827         enchant.Entity.call(this);
3828
3829         this.width = width;
3830         this.height = height;
3831         this._image = null;
3832         this._debugColor = '#ff0000';
3833         this._frameLeft = 0;
3834         this._frameTop = 0;
3835         this._frame = 0;
3836         this._frameSequence = [];
3837         /**
3838          [lang:ja]
3839          * frame に配列が指定されたときの処理。
3840          [/lang]
3841          */
3842         this.addEventListener('enterframe', function() {
3843             if (this._frameSequence.length !== 0) {
3844                 var nextFrame = this._frameSequence.shift();
3845                 if (nextFrame === null) {
3846                     this._frameSequence = [];
3847                 } else {
3848                     this._setFrame(nextFrame);
3849                     this._frameSequence.push(nextFrame);
3850                 }
3851             }
3852         });
3853     },
3854     /**
3855      [lang:ja]
3856      * Spriteで表示する画像.
3857      [/lang]
3858      [lang:en]
3859      * Image displayed in the Sprite.
3860      [/lang]
3861      [lang:de]
3862      * Die Grafik die im Sprite dargestellt wird.
3863      [/lang]
3864      * @type {enchant.Surface}
3865      */
3866     image: {
3867         get: function() {
3868             return this._image;
3869         },
3870         set: function(image) {
3871             if (image === undefined) {
3872                 throw new Error('Assigned value on Sprite.image is undefined. Please double-check image path, and check if the image you want to use is preload before use.');
3873             }
3874             if (image === this._image) {
3875                 return;
3876             }
3877             this._image = image;
3878             this._setFrame(this._frame);
3879         }
3880     },
3881     /**
3882      [lang:ja]
3883      * 表示するフレームのインデックス.
3884      * Spriteと同じ横幅と高さを持ったフレームが{@link enchant.Sprite#image}プロパティの画像に左上から順に
3885      * 配列されていると見て, 0から始まるインデックスを指定することでフレームを切り替える.
3886      *
3887      * 数値の配列が指定された場合、それらを毎フレーム順に切り替える。
3888      * ループするが、null値が含まれているとそこでループをストップする。
3889      [/lang]
3890      [lang:en]
3891      * Indizes of the frames to be displayed.
3892      * Frames with same width and height as Sprite will be arrayed from upper left corner of the 
3893      * {@link enchant.Sprite#image} image. When a sequence of numbers is provided, the displayed frame 
3894      * will switch automatically. At the end of the array the sequence will restart. By setting 
3895      * a value within the sequence to null, the frame switching is stopped.
3896      [/lang]
3897      [lang:de]
3898      * Die Indizes der darzustellenden Frames.
3899      * Die Frames mit der selben Größe wie das Sprite werden aus der {@link enchant.Sprite#image} image Variable,
3900      * beginnend an der oberen linken Ecke, angeordnet. Wenn eine Nummbersequenz übergeben wird, wird
3901      * der dargestellte Frame automatisch gewechselt. Am ende des Arrays der Sequenz wird diese neugestartet.
3902      * Wenn ein Wert in der Sequenz auf null gesetzt wird, wird das automatische Framewechseln gestoppt.
3903      [/lang]
3904      * @example
3905      * var sprite = new Sprite(32, 32);
3906      * sprite.frame = [0, 1, 0, 2]
3907      * //-> 0, 1, 0, 2, 0, 1, 0, 2,..
3908      * sprite.frame = [0, 1, 0, 2, null]
3909      * //-> 0, 1, 0, 2, (2, 2,.. :stop)
3910      *
3911      * @type {Number|Array}
3912      */
3913     frame: {
3914         get: function() {
3915             return this._frame;
3916         },
3917         set: function(frame) {
3918             if(this._frame === frame) {
3919                 return;
3920             }
3921             if (frame instanceof Array) {
3922                 var frameSequence = frame;
3923                 var nextFrame = frameSequence.shift();
3924                 this._setFrame(nextFrame);
3925                 frameSequence.push(nextFrame);
3926                 this._frameSequence = frameSequence;
3927             } else {
3928                 this._setFrame(frame);
3929                 this._frameSequence = [];
3930                 this._frame = frame;
3931             }
3932         }
3933     },
3934     /**
3935      * 0 <= frame
3936      [lang:ja]
3937      * 0以下の動作は未定義.
3938      [/lang]
3939      * @param frame
3940      * @private
3941      */
3942     _setFrame: function(frame) {
3943         var image = this._image;
3944         var row, col;
3945         if (image != null) {
3946             this._frame = frame;
3947             row = image.width / this._width | 0;
3948             this._frameLeft = (frame % row | 0) * this._width;
3949             this._frameTop = (frame / row | 0) * this._height % image.height;
3950         }
3951     },
3952     /**
3953      * width of Sprite
3954      * @type {Number}
3955      */
3956     width: {
3957         get: function() {
3958             return this._width;
3959         },
3960         set: function(width) {
3961             this._width = width;
3962             this._setFrame(this._frame);
3963             this._dirty = true;
3964         }
3965     },
3966     /**
3967      * height of Sprite
3968      * @type {Number}
3969      */
3970     height: {
3971         get: function() {
3972             return this._height;
3973         },
3974         set: function(height) {
3975             this._height = height;
3976             this._setFrame(this._frame);
3977             this._dirty = true;
3978         }
3979     },
3980     cvsRender: function(ctx) {
3981         var image = this._image,
3982             w = this._width, h = this._height,
3983             iw, ih, elem, sx, sy, sw, sh;
3984         if (image && w !== 0 && h !== 0) {
3985             iw = image.width, ih = image.height;
3986             if (iw < w || ih < h) {
3987                 ctx.fillStyle = enchant.Surface._getPattern(image);
3988                 ctx.fillRect(0, 0, w, h);
3989             } else {
3990                 elem = image._element;
3991                 sx = this._frameLeft;
3992                 sy = Math.min(this._frameTop, ih - h);
3993                 sw = Math.min(iw - sx, w);
3994                 sh = Math.min(ih - sy, h);
3995                 ctx.drawImage(elem, sx, sy, sw, sh, 0, 0, w, h);
3996             }
3997         }
3998     },
3999     domRender: (function() {
4000         if (enchant.ENV.VENDOR_PREFIX === 'ms') {
4001             return function(element) {
4002                 if (this._image) {
4003                     if (this._image._css) {
4004                         this._style['background-image'] = this._image._css;
4005                         this._style['background-position'] =
4006                             -this._frameLeft + 'px ' +
4007                             -this._frameTop + 'px';
4008                     } else if (this._image._element) {
4009                     }
4010                 }
4011             };
4012         } else {
4013             return function(element) {
4014                 if (this._image) {
4015                     if (this._image._css) {
4016                         this._style['background-image'] = this._image._css;
4017                         this._style['background-position'] =
4018                             -this._frameLeft + 'px ' +
4019                             -this._frameTop + 'px';
4020                     } else if (this._image._element) {
4021                     }
4022                 }
4023             };
4024         }
4025     }())
4026 });
4027
4028 /**
4029  * @scope enchant.Label.prototype
4030  */
4031 enchant.Label = enchant.Class.create(enchant.Entity, {
4032     /**
4033      * @name enchant.Label
4034      * @class
4035      [lang:ja]
4036      * Label クラス。
4037      [/lang]
4038      [lang:en]
4039      * A class for Label object.
4040      [/lang]
4041      [lang:de]
4042      * Erstellt ein Label Objekt.
4043      [/lang]
4044      * @constructs
4045      * @extends enchant.Entity
4046      */
4047     initialize: function(text) {
4048         enchant.Entity.call(this);
4049
4050         this.text = text || '';
4051         this.width = 300;
4052         this.font = '14px serif';
4053         this.textAlign = 'left';
4054
4055         this._debugColor = '#ff0000';
4056     },
4057     width: {
4058         get: function() {
4059             return this._width;
4060         },
4061         set: function(width) {
4062             this._width = width;
4063             this._dirty = true;
4064             // issue #164
4065             this.updateBoundArea();
4066         }
4067     },
4068     /**
4069      [lang:ja]
4070      * 表示するテキスト.
4071      * DOM レンダラを利用している場合 (DOMScene 以下にある場合) 改行タグ (br) も利用できるが、
4072      * ユーザから入力したり、サーバから取得した文字列を表示する場合, XSS 脆弱性などに注意してください.
4073      * Canvas レンダラを利用できる場合でも、改行タグ (br, BR) は改行に変換されます。
4074      [/lang]
4075      [lang:en]
4076      * Text to be displayed.
4077      [/lang]
4078      [lang:de]
4079      * Darzustellender Text.
4080      [/lang]
4081      * @type {String}
4082      */
4083     text: {
4084         get: function() {
4085             return this._text;
4086         },
4087         set: function(text) {
4088             text = '' + text;
4089             if(this._text === text) {
4090                 return;
4091             }
4092             this._text = text;
4093             text = text.replace(/<(br|BR) ?\/?>/g, '<br/>');
4094             this._splitText = text.split('<br/>');
4095             this.updateBoundArea();
4096             for (var i = 0, l = this._splitText.length; i < l; i++) {
4097                 text = this._splitText[i];
4098                 var metrics = this.getMetrics(text);
4099                 this._splitText[i] = {};
4100                 this._splitText[i].text = text;
4101                 this._splitText[i].height = metrics.height;
4102             }
4103         }
4104     },
4105     /**
4106      [lang:ja]
4107      * テキストの水平位置の指定.
4108      * CSSの'text-align'プロパティと同様の形式で指定できる.
4109      [/lang]
4110      [lang:en]
4111      * Specifies horizontal alignment of text.
4112      * Can be set according to the format of the CSS 'text-align' property.
4113      [/lang]
4114      [lang:de]
4115      * Spezifiziert die horizontale Ausrichtung des Textes.
4116      * Kann im gleichen Format wie die CSS 'text-align' Eigenschaft angegeben werden.
4117      [/lang]
4118      * @type {String}
4119      */
4120     textAlign: {
4121         get: function() {
4122             return this._style['text-align'];
4123         },
4124         set: function(textAlign) {
4125             this._style['text-align'] = textAlign;
4126             this.updateBoundArea();
4127         }
4128     },
4129     /**
4130      [lang:ja]
4131      * フォントの指定.
4132      * CSSの'font'プロパティと同様の形式で指定できる.
4133      [/lang]
4134      [lang:en]
4135      * Font settings.
4136      * Can be set according to the format of the CSS 'font' property.
4137      [/lang]
4138      [lang:de]
4139      * Text Eigenschaften.
4140      * Kann im gleichen Format wie die CSS 'font' Eigenschaft angegeben werden.
4141      [/lang]
4142      * @type {String}
4143      */
4144     font: {
4145         get: function() {
4146             return this._style.font;
4147         },
4148         set: function(font) {
4149             this._style.font = font;
4150             this.updateBoundArea();
4151         }
4152     },
4153     /**
4154      [lang:ja]
4155      * 文字色の指定.
4156      * CSSの'color'プロパティと同様の形式で指定できる.
4157      [/lang]
4158      [lang:en]
4159      * Text color settings.
4160      * Can be set according to the format of the CSS 'color' property.
4161      [/lang]
4162      [lang:de]
4163      * Text Farbe.
4164      * Kann im gleichen Format wie die CSS 'color' Eigenschaft angegeben werden.
4165      [/lang]
4166      * @type {String}
4167      */
4168     color: {
4169         get: function() {
4170             return this._style.color;
4171         },
4172         set: function(color) {
4173             this._style.color = color;
4174         }
4175     },
4176     cvsRender: function(ctx) {
4177         var x, y = 0;
4178         var labelWidth = this.width;
4179         var charWidth, amount, line, text, c, buf, increase, length;
4180         var bufWidth;
4181         if (this._splitText) {
4182             ctx.textBaseline = 'top';
4183             ctx.font = this.font;
4184             ctx.fillStyle = this.color || '#000000';
4185             charWidth = ctx.measureText(' ').width;
4186             amount = labelWidth / charWidth;
4187             for (var i = 0, l = this._splitText.length; i < l; i++) {
4188                 line = this._splitText[i];
4189                 text = line.text;
4190                 c = 0;
4191                 while (text.length > c + amount || ctx.measureText(text.slice(c, c + amount)).width > labelWidth) {
4192                     buf = '';
4193                     increase = amount;
4194                     length = 0;
4195                     while (increase > 0) {
4196                         if (ctx.measureText(buf).width < labelWidth) {
4197                             length += increase;
4198                             buf = text.slice(c, c + length);
4199                         } else {
4200                             length -= increase;
4201                             buf = text.slice(c, c + length);
4202                         }
4203                         increase = increase / 2 | 0;
4204                     }
4205                     ctx.fillText(buf, 0, y);
4206                     y += line.height - 1;
4207                     c += length;
4208                 }
4209                 buf = text.slice(c, c + text.length);
4210                 if (this.textAlign === 'right') {
4211                     x = labelWidth - ctx.measureText(buf).width;
4212                 } else if (this.textAlign === 'center') {
4213                     x = (labelWidth - ctx.measureText(buf).width) / 2;
4214                 } else {
4215                     x = 0;
4216                 }
4217                 ctx.fillText(buf, x, y);
4218                 y += line.height - 1;
4219             }
4220         }
4221     },
4222     domRender: function(element) {
4223         if (element.innerHTML !== this._text) {
4224             element.innerHTML = this._text;
4225         }
4226     },
4227     detectRender: function(ctx) {
4228         ctx.fillRect(this._boundOffset, 0, this._boundWidth, this._boundHeight);
4229     },
4230     updateBoundArea: function() {
4231         var metrics = this.getMetrics();
4232         this._boundWidth = metrics.width;
4233         this._boundHeight = metrics.height;
4234         if (this.textAlign === 'right') {
4235             this._boundOffset = this.width - this._boundWidth;
4236         } else if (this.textAlign === 'center') {
4237             this._boundOffset = (this.width - this._boundWidth) / 2;
4238         } else {
4239             this._boundOffset = 0;
4240         }
4241     },
4242     getMetrics: function(text) {
4243         var ret = {};
4244         var div, width, height;
4245         if (document.body) {
4246             div = document.createElement('div');
4247             for (var prop in this._style) {
4248                 if(prop !== 'width' && prop !== 'height') {
4249                     div.style[prop] = this._style[prop];
4250                 }
4251             }
4252             text = text || this._text;
4253             div.innerHTML = text.replace(/ /g, '&nbsp;');
4254             div.style.whiteSpace = 'noWrap';
4255             div.style.lineHeight = 1;
4256             document.body.appendChild(div);
4257             ret.height = parseInt(getComputedStyle(div).height, 10) + 1;
4258             div.style.position = 'absolute';
4259             ret.width = parseInt(getComputedStyle(div).width, 10) + 1;
4260             document.body.removeChild(div);
4261         } else {
4262             ret.width = this.width;
4263             ret.height = this.height;
4264         }
4265         return ret;
4266     }
4267 });
4268
4269 /**
4270  * @scope enchant.Map.prototype
4271  */
4272 enchant.Map = enchant.Class.create(enchant.Entity, {
4273     /**
4274      * @name enchant.Map
4275      * @class
4276      [lang:ja]
4277      * タイルセットからマップを生成して表示するクラス.
4278      *
4279      * @param {Number} tileWidth タイルの横幅.
4280      * @param {Number} tileHeight タイルの高さ.
4281      [/lang]
4282      [lang:en]
4283      * A class to create and display maps from a tile set.
4284      *
4285      * @param {Number} tileWidth Tile width.
4286      * @param {Number} tileHeight Tile height.
4287      [/lang]
4288      [lang:de]
4289      * Eine Klasse mit der Karten aus Kacheln (Tiles)
4290      * erstellt und angezeigt werden können.
4291      *
4292      * @param {Number} tileWidth Kachelbreite.
4293      * @param {Number} tileHeight Kachelhöhe.
4294      [/lang]
4295      * @constructs
4296      * @extends enchant.Entity
4297      */
4298     initialize: function(tileWidth, tileHeight) {
4299         var core = enchant.Core.instance;
4300
4301         enchant.Entity.call(this);
4302
4303         var surface = new enchant.Surface(core.width, core.height);
4304         this._surface = surface;
4305         var canvas = surface._element;
4306         canvas.style.position = 'absolute';
4307         if (enchant.ENV.RETINA_DISPLAY && core.scale === 2) {
4308             canvas.width = core.width * 2;
4309             canvas.height = core.height * 2;
4310             this._style.webkitTransformOrigin = '0 0';
4311             this._style.webkitTransform = 'scale(0.5)';
4312         } else {
4313             canvas.width = core.width;
4314             canvas.height = core.height;
4315         }
4316         this._context = canvas.getContext('2d');
4317
4318         this._tileWidth = tileWidth || 0;
4319         this._tileHeight = tileHeight || 0;
4320         this._image = null;
4321         this._data = [
4322             [
4323                 []
4324             ]
4325         ];
4326         this._dirty = false;
4327         this._tight = false;
4328
4329         this.touchEnabled = false;
4330
4331         /**
4332          [lang:ja]
4333          * タイルが衝突判定を持つかを表す値の二元配列.
4334          [/lang]
4335          [lang:en]
4336          * Two dimensional array to store if collision detection should be performed for a tile.
4337          [/lang]
4338          [lang:de]
4339          * Ein 2-Dimensionales Array um zu speichern, ob für eine Kachel
4340          * Kollesionsdetektion durchgeführt werden soll.
4341          [/lang]
4342          * @type {Array.<Array.<Number>>}
4343          */
4344         this.collisionData = null;
4345
4346         this._listeners['render'] = null;
4347         this.addEventListener('render', function() {
4348             if (this._dirty || this._previousOffsetX == null) {
4349                 this.redraw(0, 0, core.width, core.height);
4350             } else if (this._offsetX !== this._previousOffsetX ||
4351                 this._offsetY !== this._previousOffsetY) {
4352                 if (this._tight) {
4353                     var x = -this._offsetX;
4354                     var y = -this._offsetY;
4355                     var px = -this._previousOffsetX;
4356                     var py = -this._previousOffsetY;
4357                     var w1 = x - px + core.width;
4358                     var w2 = px - x + core.width;
4359                     var h1 = y - py + core.height;
4360                     var h2 = py - y + core.height;
4361                     if (w1 > this._tileWidth && w2 > this._tileWidth &&
4362                         h1 > this._tileHeight && h2 > this._tileHeight) {
4363                         var sx, sy, dx, dy, sw, sh;
4364                         if (w1 < w2) {
4365                             sx = 0;
4366                             dx = px - x;
4367                             sw = w1;
4368                         } else {
4369                             sx = x - px;
4370                             dx = 0;
4371                             sw = w2;
4372                         }
4373                         if (h1 < h2) {
4374                             sy = 0;
4375                             dy = py - y;
4376                             sh = h1;
4377                         } else {
4378                             sy = y - py;
4379                             dy = 0;
4380                             sh = h2;
4381                         }
4382
4383                         if (core._buffer == null) {
4384                             core._buffer = document.createElement('canvas');
4385                             core._buffer.width = this._context.canvas.width;
4386                             core._buffer.height = this._context.canvas.height;
4387                         }
4388                         var context = core._buffer.getContext('2d');
4389                         if (this._doubledImage) {
4390                             context.clearRect(0, 0, sw * 2, sh * 2);
4391                             context.drawImage(this._context.canvas,
4392                                 sx * 2, sy * 2, sw * 2, sh * 2, 0, 0, sw * 2, sh * 2);
4393                             context = this._context;
4394                             context.clearRect(dx * 2, dy * 2, sw * 2, sh * 2);
4395                             context.drawImage(core._buffer,
4396                                 0, 0, sw * 2, sh * 2, dx * 2, dy * 2, sw * 2, sh * 2);
4397                         } else {
4398                             context.clearRect(0, 0, sw, sh);
4399                             context.drawImage(this._context.canvas,
4400                                 sx, sy, sw, sh, 0, 0, sw, sh);
4401                             context = this._context;
4402                             context.clearRect(dx, dy, sw, sh);
4403                             context.drawImage(core._buffer,
4404                                 0, 0, sw, sh, dx, dy, sw, sh);
4405                         }
4406
4407                         if (dx === 0) {
4408                             this.redraw(sw, 0, core.width - sw, core.height);
4409                         } else {
4410                             this.redraw(0, 0, core.width - sw, core.height);
4411                         }
4412                         if (dy === 0) {
4413                             this.redraw(0, sh, core.width, core.height - sh);
4414                         } else {
4415                             this.redraw(0, 0, core.width, core.height - sh);
4416                         }
4417                     } else {
4418                         this.redraw(0, 0, core.width, core.height);
4419                     }
4420                 } else {
4421                     this.redraw(0, 0, core.width, core.height);
4422                 }
4423             }
4424             this._previousOffsetX = this._offsetX;
4425             this._previousOffsetY = this._offsetY;
4426         });
4427     },
4428     /**
4429      [lang:ja]
4430      * データを設定する.
4431      * タイルががimageプロパティの画像に左上から順に配列されていると見て, 0から始まる
4432      * インデックスの二元配列を設定する.複数指定された場合は後のものから順に表示される.
4433      * @param {...Array<Array.<Number>>} data タイルのインデックスの二元配列. 複数指定できる.
4434      [/lang]
4435      [lang:en]
4436      * Set map data.
4437      * Sets the tile data, whereas the data (two-dimensional array with indizes starting from 0) 
4438      * is mapped on the image starting from the upper left corner.
4439      * When more than one map data array is set, they are displayed in reverse order.
4440      * @param {...Array<Array.<Number>>} data Two-dimensional array of tile indizes. Multiple designations possible.
4441      [/lang]
4442      [lang:de]
4443      * Setzt die Kartendaten.
4444      * Setzt die Kartendaten, wobei die Daten (ein 2-Dimensionales Array bei dem die Indizes bei 0 beginnen) 
4445      * auf das Bild, beginned bei der linken oberen Ecke) projeziert werden.
4446      * Sollte mehr als ein Array übergeben worden sein, werden die Karten in invertierter Reihenfolge dargestellt. 
4447      * @param {...Array<Array.<Number>>} data 2-Dimensionales Array mit Kachel Indizes. Mehrfachangaben möglich.
4448      [/lang]
4449      */
4450     loadData: function(data) {
4451         this._data = Array.prototype.slice.apply(arguments);
4452         this._dirty = true;
4453
4454         this._tight = false;
4455         for (var i = 0, len = this._data.length; i < len; i++) {
4456             var c = 0;
4457             data = this._data[i];
4458             for (var y = 0, l = data.length; y < l; y++) {
4459                 for (var x = 0, ll = data[y].length; x < ll; x++) {
4460                     if (data[y][x] >= 0) {
4461                         c++;
4462                     }
4463                 }
4464             }
4465             if (c / (data.length * data[0].length) > 0.2) {
4466                 this._tight = true;
4467                 break;
4468             }
4469         }
4470     },
4471     /**
4472      [lang:ja]
4473      * ある座標のタイルが何か調べる.
4474      * @param {Number} x マップ上の点のx座標.
4475      * @param {Number} y マップ上の点のy座標.
4476      * @return {*} ある座標のタイルのデータ.
4477      [/lang]
4478      [lang:en]
4479      * Checks what tile is present at the given position.
4480      * @param {Number} x x coordinates of the point on the map.
4481      * @param {Number} y y coordinates of the point on the map.
4482      * @return {*} The tile data for the given position.
4483      [/lang]
4484      [lang:de]
4485      * Überprüft welche Kachel an der gegeben Position vorhanden ist.
4486      * @param {Number} x Die x Koordinataten des Punktes auf der Karte.
4487      * @param {Number} y Die y Koordinataten des Punktes auf der Karte.
4488      * @return {*} Die Kachel für die angegebene Position.
4489      [/lang]
4490      */
4491     checkTile: function(x, y) {
4492         if (x < 0 || this.width <= x || y < 0 || this.height <= y) {
4493             return false;
4494         }
4495         var width = this._image.width;
4496         var height = this._image.height;
4497         var tileWidth = this._tileWidth || width;
4498         var tileHeight = this._tileHeight || height;
4499         x = x / tileWidth | 0;
4500         y = y / tileHeight | 0;
4501         //              return this._data[y][x];
4502         var data = this._data[0];
4503         return data[y][x];
4504     },
4505     /**
4506      [lang:ja]
4507      * Map上に障害物があるかどうかを判定する.
4508      * @param {Number} x 判定を行うマップ上の点のx座標.
4509      * @param {Number} y 判定を行うマップ上の点のy座標.
4510      * @return {Boolean} 障害物があるかどうか.
4511      [/lang]
4512      [lang:en]
4513      * Judges whether or not obstacles are on top of Map.
4514      * @param {Number} x x coordinates of detection spot on map.
4515      * @param {Number} y y coordinates of detection spot on map.
4516      * @return {Boolean} True, if there are obstacles.
4517      [/lang]
4518      [lang:de]
4519      * Überprüft ob auf der Karte Hindernisse vorhanden sind.
4520      * @param {Number} x Die x Koordinataten des Punktes auf der Karte, der überprüft werden soll.
4521      * @param {Number} y Die y Koordinataten des Punktes auf der Karte, der überprüft werden soll.
4522      * @return {Boolean} True, falls Hindernisse vorhanden sind.
4523      [/lang]
4524      */
4525     hitTest: function(x, y) {
4526         if (x < 0 || this.width <= x || y < 0 || this.height <= y) {
4527             return false;
4528         }
4529         var width = this._image.width;
4530         var height = this._image.height;
4531         var tileWidth = this._tileWidth || width;
4532         var tileHeight = this._tileHeight || height;
4533         x = x / tileWidth | 0;
4534         y = y / tileHeight | 0;
4535         if (this.collisionData != null) {
4536             return this.collisionData[y] && !!this.collisionData[y][x];
4537         } else {
4538             for (var i = 0, len = this._data.length; i < len; i++) {
4539                 var data = this._data[i];
4540                 var n;
4541                 if (data[y] != null && (n = data[y][x]) != null &&
4542                     0 <= n && n < (width / tileWidth | 0) * (height / tileHeight | 0)) {
4543                     return true;
4544                 }
4545             }
4546             return false;
4547         }
4548     },
4549     /**
4550      [lang:ja]
4551      * Mapで表示するタイルセット画像.
4552      [/lang]
4553      [lang:en]
4554      * Image with which the tile set is displayed on the map.
4555      [/lang]
4556      [lang:de]
4557      * Das Bild mit dem die Kacheln auf der Karte dargestellt werden.
4558      [/lang]
4559      * @type {enchant.Surface}
4560      */
4561     image: {
4562         get: function() {
4563             return this._image;
4564         },
4565         set: function(image) {
4566             var core = enchant.Core.instance;
4567
4568             this._image = image;
4569             if (enchant.ENV.RETINA_DISPLAY && core.scale === 2) {
4570                 var img = new enchant.Surface(image.width * 2, image.height * 2);
4571                 var tileWidth = this._tileWidth || image.width;
4572                 var tileHeight = this._tileHeight || image.height;
4573                 var row = image.width / tileWidth | 0;
4574                 var col = image.height / tileHeight | 0;
4575                 for (var y = 0; y < col; y++) {
4576                     for (var x = 0; x < row; x++) {
4577                         img.draw(image, x * tileWidth, y * tileHeight, tileWidth, tileHeight,
4578                             x * tileWidth * 2, y * tileHeight * 2, tileWidth * 2, tileHeight * 2);
4579                     }
4580                 }
4581                 this._doubledImage = img;
4582             }
4583             this._dirty = true;
4584         }
4585     },
4586     /**
4587      [lang:ja]
4588      * Mapのタイルの横幅.
4589      [/lang]
4590      [lang:en]
4591      * Map tile width.
4592      [/lang]
4593      [lang:de]
4594      * Kachelbreite
4595      [/lang]
4596      * @type {Number}
4597      */
4598     tileWidth: {
4599         get: function() {
4600             return this._tileWidth;
4601         },
4602         set: function(tileWidth) {
4603             this._tileWidth = tileWidth;
4604             this._dirty = true;
4605         }
4606     },
4607     /**
4608      [lang:ja]
4609      * Mapのタイルの高さ.
4610      [/lang]
4611      [lang:en]
4612      * Map tile height.
4613      [/lang]
4614      [lang:de]
4615      * Kachelhöhe.
4616      [/lang]
4617      * @type {Number}
4618      */
4619     tileHeight: {
4620         get: function() {
4621             return this._tileHeight;
4622         },
4623         set: function(tileHeight) {
4624             this._tileHeight = tileHeight;
4625             this._dirty = true;
4626         }
4627     },
4628     /**
4629      * @private
4630      */
4631     width: {
4632         get: function() {
4633             return this._tileWidth * this._data[0][0].length;
4634         }
4635     },
4636     /**
4637      * @private
4638      */
4639     height: {
4640         get: function() {
4641             return this._tileHeight * this._data[0].length;
4642         }
4643     },
4644     /**
4645      * @private
4646      */
4647     redraw: function(x, y, width, height) {
4648         if (this._image == null) {
4649             return;
4650         }
4651
4652         var image, tileWidth, tileHeight, dx, dy;
4653         if (this._doubledImage) {
4654             image = this._doubledImage;
4655             tileWidth = this._tileWidth * 2;
4656             tileHeight = this._tileHeight * 2;
4657             dx = -this._offsetX * 2;
4658             dy = -this._offsetY * 2;
4659             x *= 2;
4660             y *= 2;
4661             width *= 2;
4662             height *= 2;
4663         } else {
4664             image = this._image;
4665             tileWidth = this._tileWidth;
4666             tileHeight = this._tileHeight;
4667             dx = -this._offsetX;
4668             dy = -this._offsetY;
4669         }
4670         var row = image.width / tileWidth | 0;
4671         var col = image.height / tileHeight | 0;
4672         var left = Math.max((x + dx) / tileWidth | 0, 0);
4673         var top = Math.max((y + dy) / tileHeight | 0, 0);
4674         var right = Math.ceil((x + dx + width) / tileWidth);
4675         var bottom = Math.ceil((y + dy + height) / tileHeight);
4676
4677         var source = image._element;
4678         var context = this._context;
4679         var canvas = context.canvas;
4680         context.clearRect(x, y, width, height);
4681         for (var i = 0, len = this._data.length; i < len; i++) {
4682             var data = this._data[i];
4683             var r = Math.min(right, data[0].length);
4684             var b = Math.min(bottom, data.length);
4685             for (y = top; y < b; y++) {
4686                 for (x = left; x < r; x++) {
4687                     var n = data[y][x];
4688                     if (0 <= n && n < row * col) {
4689                         var sx = (n % row) * tileWidth;
4690                         var sy = (n / row | 0) * tileHeight;
4691                         context.drawImage(source, sx, sy, tileWidth, tileHeight,
4692                             x * tileWidth - dx, y * tileHeight - dy, tileWidth, tileHeight);
4693                     }
4694                 }
4695             }
4696         }
4697     },
4698     cvsRender: function(ctx) {
4699         var core = enchant.Core.instance;
4700         if (this.width !== 0 && this.height !== 0) {
4701             ctx.save();
4702             ctx.setTransform(1, 0, 0, 1, 0, 0);
4703             var cvs = this._context.canvas;
4704                 ctx.drawImage(cvs, 0, 0, core.width, core.height);
4705             ctx.restore();
4706         }
4707     },
4708     domRender: function(element) {
4709         if (this._image) {
4710             this._style['background-image'] = this._surface._css;
4711             // bad performance
4712             this._style[enchant.ENV.VENDOR_PREFIX + 'Transform'] = 'matrix(1, 0, 0, 1, 0, 0)';
4713         }
4714     }
4715 });
4716
4717
4718 /**
4719  * @scope enchant.Group.prototype
4720  */
4721 enchant.Group = enchant.Class.create(enchant.Node, {
4722     /**
4723      * @name enchant.Group
4724      * @class
4725      [lang:ja]
4726      * 複数の{@link enchant.Node}を子に持つことができるクラス.
4727      *
4728      * @example
4729      *   var stage = new Group();
4730      *   stage.addChild(player);
4731      *   stage.addChild(enemy);
4732      *   stage.addChild(map);
4733      *   stage.addEventListener('enterframe', function() {
4734      *      // playerの座標に従って全体をスクロールする
4735      *      if (this.x > 64 - player.x) {
4736      *          this.x = 64 - player.x;
4737      *      }
4738      *   });
4739      *
4740      * @extends enchant.Node
4741      [/lang]
4742      [lang:en]
4743      * A class that can hold multiple {@link enchant.Node}.
4744      *
4745      * @example
4746      *   var stage = new Group();
4747      *   stage.addChild(player);
4748      *   stage.addChild(enemy);
4749      *   stage.addChild(map);
4750      *   stage.addEventListener('enterframe', function() {
4751      *      // Moves the entire frame in according to the player's coordinates.
4752      *      if (this.x > 64 - player.x) {
4753      *          this.x = 64 - player.x;
4754      *      }
4755      *   });
4756      *
4757      [/lang]
4758      [lang:de]
4759      * Eine Klasse die mehrere {@link enchant.Node} beinhalten kann.
4760      *
4761      * @example
4762      *   var stage = new Group();
4763      *   stage.addChild(player);
4764      *   stage.addChild(enemy);
4765      *   stage.addChild(map);
4766      *   stage.addEventListener('enterframe', function() {
4767      *      // Bewegt den gesamten Frame je nach der aktuelle Spielerposition.
4768      *      if (this.x > 64 - player.x) {
4769      *          this.x = 64 - player.x;
4770      *      }
4771      *   });
4772      *
4773      [/lang]
4774      * @constructs
4775      * @extends enchant.Node
4776      */
4777     initialize: function() {
4778         /**
4779          [lang:ja]
4780          * 子のNode.
4781          [/lang]
4782          [lang:en]
4783          * Child Nodes.
4784          [/lang]
4785          [lang:de]
4786          * Kind-Nodes.
4787          [/lang]
4788          * @type {Array.<enchant.Node>}
4789          */
4790         this.childNodes = [];
4791
4792         enchant.Node.call(this);
4793
4794         this._rotation = 0;
4795         this._scaleX = 1;
4796         this._scaleY = 1;
4797
4798         this._originX = null;
4799         this._originY = null;
4800
4801         this.__dirty = false;
4802
4803         [enchant.Event.ADDED_TO_SCENE, enchant.Event.REMOVED_FROM_SCENE]
4804             .forEach(function(event) {
4805                 this.addEventListener(event, function(e) {
4806                     this.childNodes.forEach(function(child) {
4807                         child.scene = this.scene;
4808                         child.dispatchEvent(e);
4809                     }, this);
4810                 });
4811             }, this);
4812     },
4813     /**
4814      [lang:ja]
4815      * GroupにNodeを追加する.
4816      * @param {enchant.Node} node 追加するNode.
4817      [/lang]
4818      [lang:en]
4819      * Adds a Node to the Group.
4820      * @param {enchant.Node} node Node to be added.
4821      [/lang]
4822      [lang:de]
4823      * Fügt einen Node zu der Gruppe hinzu.
4824      * @param {enchant.Node} node Node der hinzugeügt werden soll.
4825      [/lang]
4826      */
4827     addChild: function(node) {
4828         if (node.parentNode) {
4829             node.parentNode.removeChild(node);
4830         }
4831         this.childNodes.push(node);
4832         node.parentNode = this;
4833         var childAdded = new enchant.Event('childadded');
4834         childAdded.node = node;
4835         childAdded.next = null;
4836         this.dispatchEvent(childAdded);
4837         node.dispatchEvent(new enchant.Event('added'));
4838         if (this.scene) {
4839             node.scene = this.scene;
4840             var addedToScene = new enchant.Event('addedtoscene');
4841             node.dispatchEvent(addedToScene);
4842         }
4843     },
4844     /**
4845      [lang:ja]
4846      * GroupにNodeを挿入する.
4847      * @param {enchant.Node} node 挿入するNode.
4848      * @param {enchant.Node} reference 挿入位置の前にあるNode.
4849      [/lang]
4850      [lang:en]
4851      * Incorporates Node into Group.
4852      * @param {enchant.Node} node Node to be incorporated.
4853      * @param {enchant.Node} reference Node in position before insertion.
4854      [/lang]
4855      [lang:de]
4856      * Fügt einen Node vor einen anderen Node zu dieser Gruppe hinzu.
4857      * @param {enchant.Node} node Der Node der hinzugefügt werden soll.
4858      * @param {enchant.Node} reference Der Node der sich vor dem einzufügendem Node befindet.
4859      [/lang]
4860      */
4861     insertBefore: function(node, reference) {
4862         if (node.parentNode) {
4863             node.parentNode.removeChild(node);
4864         }
4865         var i = this.childNodes.indexOf(reference);
4866         if (i !== -1) {
4867             this.childNodes.splice(i, 0, node);
4868             node.parentNode = this;
4869             var childAdded = new enchant.Event('childadded');
4870             childAdded.node = node;
4871             childAdded.next = reference;
4872             this.dispatchEvent(childAdded);
4873             node.dispatchEvent(new enchant.Event('added'));
4874             if (this.scene) {
4875                 node.scene = this.scene;
4876                 var addedToScene = new enchant.Event('addedtoscene');
4877                 node.dispatchEvent(addedToScene);
4878             }
4879         } else {
4880             this.addChild(node);
4881         }
4882     },
4883     /**
4884      [lang:ja]
4885      * GroupからNodeを削除する.
4886      * @param {enchant.Node} node 削除するNode.
4887      [/lang]
4888      [lang:en]
4889      * Remove a Node from the Group.
4890      * @param {enchant.Node} node Node to be deleted.
4891      [/lang]
4892      [lang:de]
4893      * Entfernt einen Node aus der Gruppe.
4894      * @param {enchant.Node} node Der Node der entfernt werden soll.
4895      [/lang]
4896      */
4897     removeChild: function(node) {
4898         var i;
4899         if ((i = this.childNodes.indexOf(node)) !== -1) {
4900             this.childNodes.splice(i, 1);
4901             node.parentNode = null;
4902             var childRemoved = new enchant.Event('childremoved');
4903             childRemoved.node = node;
4904             this.dispatchEvent(childRemoved);
4905             node.dispatchEvent(new enchant.Event('removed'));
4906             if (this.scene) {
4907                 node.scene = null;
4908                 var removedFromScene = new enchant.Event('removedfromscene');
4909                 node.dispatchEvent(removedFromScene);
4910             }
4911         }
4912     },
4913     /**
4914      [lang:ja]
4915      * 最初の子Node.
4916      [/lang]
4917      [lang:en]
4918      * The Node which is the first child.
4919      [/lang]
4920      [lang:de]
4921      * Der Node, welcher das erste Kind der Gruppe darstellt.
4922      [/lang]
4923      * @type {enchant.Node}
4924      */
4925     firstChild: {
4926         get: function() {
4927             return this.childNodes[0];
4928         }
4929     },
4930     /**
4931      [lang:ja]
4932      * 最後の子Node.
4933      [/lang]
4934      [lang:en]
4935      * The Node which is the last child.
4936      [/lang]
4937      [lang:de]
4938      * Der Node, welcher das letzte Kind der Gruppe darstellt.
4939      [/lang]
4940      * @type {enchant.Node}
4941      */
4942     lastChild: {
4943         get: function() {
4944             return this.childNodes[this.childNodes.length - 1];
4945         }
4946     },
4947     /**
4948     [lang:ja]
4949     * Groupの回転角 (度数法).
4950     [/lang]
4951     [lang:en]
4952     * Group rotation angle (degree).
4953     [/lang]
4954     [lang:de]
4955     * Rotationswinkel der Gruppe (Grad).
4956     [/lang]
4957     * @type {Number}
4958     */
4959     rotation: {
4960         get: function() {
4961             return this._rotation;
4962         },
4963         set: function(rotation) {
4964             this._rotation = rotation;
4965             this._dirty = true;
4966         }
4967     },
4968     /**
4969     [lang:ja]
4970     * Groupのx軸方向の倍率.
4971     [/lang]
4972     [lang:en]
4973     * Scaling factor on the x axis of the Group.
4974     [/lang]
4975     [lang:de]
4976     * Skalierungsfaktor auf der x-Achse der Gruppe.
4977     [/lang]
4978     * @type {Number}
4979     * @see enchant.CanvasGroup.originX
4980     * @see enchant.CanvasGroup.originY
4981     */
4982     scaleX: {
4983         get: function() {
4984             return this._scaleX;
4985         },
4986         set: function(scale) {
4987             this._scaleX = scale;
4988             this._dirty = true;
4989         }
4990     },
4991     /**
4992     [lang:ja]
4993     * Groupのy軸方向の倍率.
4994     [/lang]
4995     [lang:en]
4996     * Scaling factor on the y axis of the Group.
4997     [/lang]
4998     [lang:de]
4999     * Skalierungsfaktor auf der y-Achse der Gruppe.
5000     [/lang]
5001     * @type {Number}
5002     * @see enchant.CanvasGroup.originX
5003     * @see enchant.CanvasGroup.originY
5004     */
5005     scaleY: {
5006         get: function() {
5007             return this._scaleY;
5008         },
5009         set: function(scale) {
5010             this._scaleY = scale;
5011             this._dirty = true;
5012         }
5013     },
5014     /**
5015     [lang:ja]
5016     * 回転・拡大縮小の基準点のX座標
5017     [/lang]
5018     [lang:en]
5019     * origin point of rotation, scaling
5020     [/lang]
5021     [lang:de]
5022     * Ausgangspunkt für Rotation und Skalierung.
5023     [/lang]
5024     * @type {Number}
5025     */
5026     originX: {
5027         get: function() {
5028             return this._originX;
5029         },
5030         set: function(originX) {
5031             this._originX = originX;
5032             this._dirty = true;
5033         }
5034     },
5035     /**
5036     [lang:ja]
5037     * 回転・拡大縮小の基準点のX座標
5038     [/lang]
5039     [lang:en]
5040     * origin point of rotation, scaling
5041     [/lang]
5042     [lang:de]
5043     * Ausgangspunkt für Rotation und Skalierung.
5044     [/lang]
5045     * @type {Number}
5046     */
5047     originY: {
5048         get: function() {
5049             return this._originY;
5050         },
5051         set: function(originY) {
5052             this._originY = originY;
5053             this._dirty = true;
5054         }
5055     },
5056     _dirty: {
5057         get: function() {
5058             return this.__dirty;
5059         },
5060         set: function(dirty) {
5061             dirty = !!dirty;
5062             this.__dirty = dirty;
5063             if (dirty) {
5064                 for (var i = 0, l = this.childNodes.length; i < l; i++) {
5065                     this.childNodes[i]._dirty = true;
5066                 }
5067             }
5068         }
5069     }
5070 });
5071
5072 enchant.Matrix = enchant.Class.create({
5073     initialize: function() {
5074         this.reset();
5075     },
5076     reset: function() {
5077         this.stack = [];
5078         this.stack.push([ 1, 0, 0, 1, 0, 0 ]);
5079     },
5080     makeTransformMatrix: function(node, dest) {
5081         var x = node._x;
5082         var y = node._y;
5083         var width = node.width || 0;
5084         var height = node.height || 0;
5085         var rotation = node._rotation || 0;
5086         var scaleX = (typeof node._scaleX === 'number') ? node._scaleX : 1;
5087         var scaleY = (typeof node._scaleY === 'number') ? node._scaleY : 1;
5088         var theta = rotation * Math.PI / 180;
5089         var tmpcos = Math.cos(theta);
5090         var tmpsin = Math.sin(theta);
5091         var w = (typeof node._originX === 'number') ? node._originX : width / 2;
5092         var h = (typeof node._originY === 'number') ? node._originY : height / 2;
5093         var a = scaleX * tmpcos;
5094         var b = scaleX * tmpsin;
5095         var c = scaleY * tmpsin;
5096         var d = scaleY * tmpcos;
5097         dest[0] = a;
5098         dest[1] = b;
5099         dest[2] = -c;
5100         dest[3] = d;
5101         dest[4] = (-a * w + c * h + x + w);
5102         dest[5] = (-b * w - d * h + y + h);
5103     },
5104     multiply: function(m1, m2, dest) {
5105         var a11 = m1[0], a21 = m1[2], adx = m1[4],
5106             a12 = m1[1], a22 = m1[3], ady = m1[5];
5107         var b11 = m2[0], b21 = m2[2], bdx = m2[4],
5108             b12 = m2[1], b22 = m2[3], bdy = m2[5];
5109
5110         dest[0] = a11 * b11 + a21 * b12;
5111         dest[1] = a12 * b11 + a22 * b12;
5112         dest[2] = a11 * b21 + a21 * b22;
5113         dest[3] = a12 * b21 + a22 * b22;
5114         dest[4] = a11 * bdx + a21 * bdy + adx;
5115         dest[5] = a12 * bdx + a22 * bdy + ady;
5116     },
5117     multiplyVec: function(mat, vec, dest) {
5118         var x = vec[0], y = vec[1];
5119         var m11 = mat[0], m21 = mat[2], mdx = mat[4],
5120             m12 = mat[1], m22 = mat[3], mdy = mat[5];
5121         dest[0] = m11 * x + m21 * y + mdx;
5122         dest[1] = m12 * x + m22 * y + mdy;
5123     }
5124 });
5125 enchant.Matrix.instance = new enchant.Matrix();
5126
5127 enchant.DetectColorManager = enchant.Class.create({
5128     initialize: function(reso, max) {
5129         this.reference = [];
5130         this.colorResolution = reso || 16;
5131         this.max = max || 1;
5132         this.capacity = Math.pow(this.colorResolution, 3);
5133         for (var i = 1, l = this.capacity; i < l; i++) {
5134             this.reference[i] = null;
5135         }
5136     },
5137     attachDetectColor: function(sprite) {
5138         var i = this.reference.indexOf(null);
5139         if (i === -1) {
5140             i = 1;
5141         }
5142         this.reference[i] = sprite;
5143         return this._getColor(i);
5144     },
5145     detachDetectColor: function(sprite) {
5146         var i = this.reference.indexOf(sprite);
5147         if (i !== -1) {
5148             this.reference[i] = null;
5149         }
5150     },
5151     _getColor: function(n) {
5152         var C = this.colorResolution;
5153         var d = C / this.max;
5154         return [
5155             parseInt((n / C / C) % C, 10) / d,
5156             parseInt((n / C) % C, 10) / d,
5157             parseInt(n % C, 10) / d,
5158             1.0
5159         ];
5160     },
5161     _decodeDetectColor: function(color) {
5162         var C = this.colorResolution;
5163         return ~~(color[0] * C * C * C / 256) +
5164             ~~(color[1] * C * C / 256) +
5165             ~~(color[2] * C / 256);
5166     },
5167     getSpriteByColor: function(color) {
5168         return this.reference[this._decodeDetectColor(color)];
5169     }
5170 });
5171
5172 enchant.DomManager = enchant.Class.create({
5173     initialize: function(node, elementDefinition) {
5174         var core = enchant.Core.instance;
5175         this.layer = null;
5176         this.targetNode = node;
5177         if (typeof elementDefinition === 'string') {
5178             this.element = document.createElement(elementDefinition);
5179         } else if (elementDefinition instanceof HTMLElement) {
5180             this.element = elementDefinition;
5181         }
5182         this.style = this.element.style;
5183         this.style.position = 'absolute';
5184         this.style[enchant.ENV.VENDOR_PREFIX + 'TransformOrigin'] = '0px 0px';
5185         if (core._debug) {
5186             this.style.border = '1px solid blue';
5187             this.style.margin = '-1px';
5188         }
5189
5190         var manager = this;
5191         this._setDomTarget = function() {
5192             manager.layer._touchEventTarget = manager.targetNode;
5193         };
5194         this._attachEvent();
5195     },
5196     getDomElement: function() {
5197         return this.element;
5198     },
5199     getDomElementAsNext: function() {
5200         return this.element;
5201     },
5202     getNextManager: function(manager) {
5203         var i = this.targetNode.parentNode.childNodes.indexOf(manager.targetNode);
5204         if (i !== this.targetNode.parentNode.childNodes.length - 1) {
5205             return this.targetNode.parentNode.childNodes[i + 1]._domManager;
5206         } else {
5207             return null;
5208         }
5209     },
5210     addManager: function(childManager, nextManager) {
5211         var nextElement;
5212         if (nextManager) {
5213             nextElement = nextManager.getDomElementAsNext();
5214         }
5215         var element = childManager.getDomElement();
5216         if (element instanceof Array) {
5217             element.forEach(function(child) {
5218                 if (nextElement) {
5219                     this.element.insertBefore(child, nextElement);
5220                 } else {
5221                     this.element.appendChild(child);
5222                 }
5223             }, this);
5224         } else {
5225             if (nextElement) {
5226                 this.element.insertBefore(element, nextElement);
5227             } else {
5228                 this.element.appendChild(element);
5229             }
5230         }
5231         this.setLayer(this.layer);
5232     },
5233     removeManager: function(childManager) {
5234         if (childManager instanceof enchant.DomlessManager) {
5235             childManager._domRef.forEach(function(element) {
5236                 this.element.removeChild(element);
5237             }, this);
5238         } else {
5239             this.element.removeChild(childManager.element);
5240         }
5241         this.setLayer(this.layer);
5242     },
5243     setLayer: function(layer) {
5244         this.layer = layer;
5245         var node = this.targetNode;
5246         var manager;
5247         if (node.childNodes) {
5248             for (var i = 0, l = node.childNodes.length; i < l; i++) {
5249                 manager = node.childNodes[i]._domManager;
5250                 if (manager) {
5251                     manager.setLayer(layer);
5252                 }
5253             }
5254         }
5255     },
5256     render: function(inheritMat) {
5257         var node = this.targetNode;
5258         var matrix = enchant.Matrix.instance;
5259         var stack = matrix.stack;
5260         var dest = [];
5261         matrix.makeTransformMatrix(node, dest);
5262         matrix.multiply(stack[stack.length - 1], dest, dest);
5263         matrix.multiply(inheritMat, dest, inheritMat);
5264         node._matrix = inheritMat;
5265         var ox = (typeof node._originX === 'number') ? node._originX : node.width / 2 || 0;
5266         var oy = (typeof node._originY === 'number') ? node._originY : node.height / 2 || 0;
5267         var vec = [ ox, oy ];
5268         matrix.multiplyVec(dest, vec, vec);
5269
5270         node._offsetX = vec[0] - ox;
5271         node._offsetY = vec[1] - oy;
5272         if(node.parentNode && !(node.parentNode instanceof enchant.Group)) {
5273             node._offsetX += node.parentNode._offsetX;
5274             node._offsetY += node.parentNode._offsetY;
5275         }
5276         if (node._dirty) {
5277             this.style[enchant.ENV.VENDOR_PREFIX + 'Transform'] = 'matrix(' +
5278                 dest[0].toFixed(10) + ',' +
5279                 dest[1].toFixed(10) + ',' +
5280                 dest[2].toFixed(10) + ',' +
5281                 dest[3].toFixed(10) + ',' +
5282                 dest[4].toFixed(10) + ',' +
5283                 dest[5].toFixed(10) +
5284             ')';
5285         }
5286         this.domRender();
5287     },
5288     domRender: function() {
5289         var node = this.targetNode;
5290         if(!node._style) {
5291             node._style = {};
5292         }
5293         if(!node.__styleStatus) {
5294             node.__styleStatus = {};
5295         }
5296         if (node.width !== null) {
5297             node._style.width = node.width + 'px';
5298         }
5299         if (node.height !== null) {
5300             node._style.height = node.height + 'px';
5301         }
5302         node._style.opacity = node._opacity;
5303         node._style['background-color'] = node._backgroundColor;
5304         if (typeof node._visible !== 'undefined') {
5305             node._style.display = node._visible ? 'block' : 'none';
5306         }
5307         if (typeof node.domRender === 'function') {
5308             node.domRender(this.element);
5309         }
5310         var value;
5311         for (var prop in node._style) {
5312             value = node._style[prop];
5313             if(node.__styleStatus[prop] !== value && value != null) {
5314                 this.style.setProperty(prop, '' + value);
5315                 node.__styleStatus[prop] = value;
5316             }
5317         }
5318     },
5319     _attachEvent: function() {
5320         if (enchant.ENV.TOUCH_ENABLED) {
5321             this.element.addEventListener('touchstart', this._setDomTarget, true);
5322         }
5323         this.element.addEventListener('mousedown', this._setDomTarget, true);
5324     },
5325     _detachEvent: function() {
5326         if (enchant.ENV.TOUCH_ENABLED) {
5327             this.element.removeEventListener('touchstart', this._setDomTarget, true);
5328         }
5329         this.element.removeEventListener('mousedown', this._setDomTarget, true);
5330     },
5331     remove: function() {
5332         this._detachEvent();
5333         this.element = this.style = this.targetNode = null;
5334     }
5335 });
5336
5337 enchant.DomlessManager = enchant.Class.create({
5338     initialize: function(node) {
5339         this._domRef = [];
5340         this.targetNode = node;
5341     },
5342     _register: function(element, nextElement) {
5343         var i = this._domRef.indexOf(nextElement);
5344         var childNodes;
5345         if (element instanceof Array) {
5346             if (i === -1) {
5347                 Array.prototype.push.apply(this._domRef, element);
5348             } else {
5349                 Array.prototype.splice.apply(this._domRef, [i, 0].concat(element));
5350             }
5351         } else {
5352             if (i === -1) {
5353                 this._domRef.push(element);
5354             } else {
5355                 this._domRef.splice(i, 0, element);
5356             }
5357         }
5358     },
5359     getNextManager: function(manager) {
5360         var i = this.targetNode.parentNode.childNodes.indexOf(manager.targetNode);
5361         if (i !== this.targetNode.parentNode.childNodes.length - 1) {
5362             return this.targetNode.parentNode.childNodes[i + 1]._domManager;
5363         } else {
5364             return null;
5365         }
5366     },
5367     getDomElement: function() {
5368         var ret = [];
5369         this.targetNode.childNodes.forEach(function(child) {
5370             ret = ret.concat(child._domManager.getDomElement());
5371         });
5372         return ret;
5373     },
5374     getDomElementAsNext: function() {
5375         if (this._domRef.length) {
5376             return this._domRef[0];
5377         } else {
5378             var nextManager = this.getNextManager(this);
5379             if (nextManager) {
5380                 return nextManager.element;
5381             } else {
5382                 return null;
5383             }
5384         }
5385     },
5386     addManager: function(childManager, nextManager) {
5387         var parentNode = this.targetNode.parentNode;
5388         if (parentNode) {
5389             if (nextManager === null) {
5390                 nextManager = this.getNextManager(this);
5391             }
5392             if (parentNode instanceof enchant.Scene) {
5393                 parentNode._layers.Dom._domManager.addManager(childManager, nextManager);
5394             } else {
5395                 parentNode._domManager.addManager(childManager, nextManager);
5396             }
5397         }
5398         var nextElement = nextManager ? nextManager.getDomElementAsNext() : null;
5399         this._register(childManager.getDomElement(), nextElement);
5400         this.setLayer(this.layer);
5401     },
5402     removeManager: function(childManager) {
5403         var dom;
5404         var i = this._domRef.indexOf(childManager.element);
5405         if (i !== -1) {
5406             dom = this._domRef[i];
5407             dom.parentNode.removeChild(dom);
5408             this._domRef.splice(i, 1);
5409         }
5410         this.setLayer(this.layer);
5411     },
5412     setLayer: function(layer) {
5413         this.layer = layer;
5414         var node = this.targetNode;
5415         var manager;
5416         if (node.childNodes) {
5417             for (var i = 0, l = node.childNodes.length; i < l; i++) {
5418                 manager = node.childNodes[i]._domManager;
5419                 if (manager) {
5420                     manager.setLayer(layer);
5421                 }
5422             }
5423         }
5424     },
5425     render: function(inheritMat) {
5426         var matrix = enchant.Matrix.instance;
5427         var stack = matrix.stack;
5428         var node = this.targetNode;
5429         var dest = [];
5430         matrix.makeTransformMatrix(node, dest);
5431         matrix.multiply(stack[stack.length - 1], dest, dest);
5432         matrix.multiply(inheritMat, dest, inheritMat);
5433         node._matrix = inheritMat;
5434         var ox = (typeof node._originX === 'number') ? node._originX : node.width / 2 || 0;
5435         var oy = (typeof node._originY === 'number') ? node._originY : node.height / 2 || 0;
5436         var vec = [ ox, oy ];
5437         matrix.multiplyVec(dest, vec, vec);
5438         node._offsetX = vec[0] - ox;
5439         node._offsetY = vec[1] - oy;
5440         stack.push(dest);
5441     },
5442     remove: function() {
5443         this._domRef = [];
5444         this.targetNode = null;
5445     }
5446 });
5447
5448 enchant.DomLayer = enchant.Class.create(enchant.Group, {
5449     initialize: function() {
5450         var core = enchant.Core.instance;
5451         enchant.Group.call(this);
5452
5453         this._touchEventTarget = null;
5454
5455         this._element = document.createElement('div');
5456         this._element.style.position = 'absolute';
5457
5458         this._domManager = new enchant.DomManager(this, this._element);
5459         this._domManager.layer = this;
5460
5461         this.width = core.width;
5462         this.height = core.height;
5463
5464         var touch = [
5465             enchant.Event.TOUCH_START,
5466             enchant.Event.TOUCH_MOVE,
5467             enchant.Event.TOUCH_END
5468         ];
5469
5470         touch.forEach(function(type) {
5471             this.addEventListener(type, function(e) {
5472                 if (this._scene) {
5473                     this._scene.dispatchEvent(e);
5474                 }
5475             });
5476         }, this);
5477
5478         var __onchildadded = function(e) {
5479             var child = e.node;
5480             var next = e.next;
5481             var self = e.target;
5482             var nextManager = next ? next._domManager : null;
5483             enchant.DomLayer._attachDomManager(child, __onchildadded, __onchildremoved);
5484             self._domManager.addManager(child._domManager, nextManager);
5485             var render = new enchant.Event(enchant.Event.RENDER);
5486             child._dirty = true;
5487             self._domManager.layer._rendering(child, render);
5488         };
5489
5490         var __onchildremoved = function(e) {
5491             var child = e.node;
5492             var self = e.target;
5493             self._domManager.removeManager(child._domManager);
5494             enchant.DomLayer._detachDomManager(child, __onchildadded, __onchildremoved);
5495         };
5496
5497         this.addEventListener('childremoved', __onchildremoved);
5498         this.addEventListener('childadded', __onchildadded);
5499
5500     },
5501     width: {
5502         get: function() {
5503             return this._width;
5504         },
5505         set: function(width) {
5506             this._width = width;
5507             this._element.style.width = width + 'px';
5508         }
5509     },
5510     height: {
5511         get: function() {
5512             return this._height;
5513         },
5514         set: function(height) {
5515             this._height = height;
5516             this._element.style.height = height + 'px';
5517         }
5518     },
5519     addChild: function(node) {
5520         this.childNodes.push(node);
5521         node.parentNode = this;
5522         var childAdded = new enchant.Event('childadded');
5523         childAdded.node = node;
5524         childAdded.next = null;
5525         this.dispatchEvent(childAdded);
5526         node.dispatchEvent(new enchant.Event('added'));
5527         if (this.scene) {
5528             node.scene = this.scene;
5529             var addedToScene = new enchant.Event('addedtoscene');
5530             node.dispatchEvent(addedToScene);
5531         }
5532     },
5533     insertBefore: function(node, reference) {
5534         var i = this.childNodes.indexOf(reference);
5535         if (i !== -1) {
5536             this.childNodes.splice(i, 0, node);
5537             node.parentNode = this;
5538             var childAdded = new enchant.Event('childadded');
5539             childAdded.node = node;
5540             childAdded.next = reference;
5541             this.dispatchEvent(childAdded);
5542             node.dispatchEvent(new enchant.Event('added'));
5543             if (this.scene) {
5544                 node.scene = this.scene;
5545                 var addedToScene = new enchant.Event('addedtoscene');
5546                 node.dispatchEvent(addedToScene);
5547             }
5548         } else {
5549             this.addChild(node);
5550         }
5551     },
5552     _startRendering: function() {
5553         this.addEventListener('exitframe', this._onexitframe);
5554         this._onexitframe();
5555     },
5556     _stopRendering: function() {
5557         this.removeEventListener('exitframe', this._onexitframe);
5558         this._onexitframe();
5559     },
5560     _onexitframe: function() {
5561         this._rendering(this, new enchant.Event(enchant.Event.RENDER));
5562     },
5563     _rendering: function(node, e, inheritMat) {
5564         var child;
5565         if (!inheritMat) {
5566             inheritMat = [ 1, 0, 0, 1, 0, 0 ];
5567         }
5568         node.dispatchEvent(e);
5569         node._domManager.render(inheritMat);
5570         if (node.childNodes) {
5571             for (var i = 0, l = node.childNodes.length; i < l; i++) {
5572                 child = node.childNodes[i];
5573                 this._rendering(child, e, inheritMat.slice());
5574             }
5575         }
5576         if (node._domManager instanceof enchant.DomlessManager) {
5577             enchant.Matrix.instance.stack.pop();
5578         }
5579         node._dirty = false;
5580     },
5581     _determineEventTarget: function() {
5582         var target = this._touchEventTarget;
5583         this._touchEventTarget = null;
5584         return (target === this) ? null : target;
5585     }
5586 });
5587
5588 enchant.DomLayer._attachDomManager = function(node, onchildadded, onchildremoved) {
5589     var child;
5590     if (!node._domManager) {
5591         node.addEventListener('childadded', onchildadded);
5592         node.addEventListener('childremoved', onchildremoved);
5593         if (node instanceof enchant.Group) {
5594             node._domManager = new enchant.DomlessManager(node);
5595         } else {
5596             if (node._element) {
5597                 node._domManager = new enchant.DomManager(node, node._element);
5598             } else {
5599                 node._domManager = new enchant.DomManager(node, 'div');
5600             }
5601         }
5602     }
5603     if (node.childNodes) {
5604         for (var i = 0, l = node.childNodes.length; i < l; i++) {
5605             child = node.childNodes[i];
5606             enchant.DomLayer._attachDomManager(child, onchildadded, onchildremoved);
5607             node._domManager.addManager(child._domManager, null);
5608         }
5609     }
5610 };
5611
5612 enchant.DomLayer._detachDomManager = function(node, onchildadded, onchildremoved) {
5613     var child;
5614     node.removeEventListener('childadded', onchildadded);
5615     node.removeEventListener('childremoved', onchildremoved);
5616     if (node.childNodes) {
5617         for (var i = 0, l = node.childNodes.length; i < l; i++) {
5618             child = node.childNodes[i];
5619             node._domManager.removeManager(child._domManager, null);
5620             enchant.DomLayer._detachDomManager(child, onchildadded, onchildremoved);
5621         }
5622     }
5623     node._domManager.remove();
5624     delete node._domManager;
5625 };
5626
5627 /**
5628  * @scope enchant.CanvasLayer.prototype
5629  */
5630 enchant.CanvasLayer = enchant.Class.create(enchant.Group, {
5631     /**
5632      * @name enchant.CanvasLayer
5633      * @class
5634      [lang:ja]
5635      * Canvas を用いた描画を行うクラス.
5636      * 子を Canvas を用いた描画に切り替えるクラス
5637      [/lang]
5638      [lang:en]
5639      * A class which is using HTML Canvas for the rendering.
5640      * The rendering of children will be replaced by the Canvas rendering.
5641      [/lang]
5642      [lang:de]
5643      * Eine Klasse die HTML Canvas für das Rendern nutzt.
5644      * Das Rendern der Kinder wird durch das Canvas Rendering ersetzt.
5645      [/lang]
5646      * @constructs
5647      */
5648     initialize: function() {
5649         var core = enchant.Core.instance;
5650
5651         enchant.Group.call(this);
5652
5653         this._cvsCache = {
5654             matrix: [1, 0, 0, 1, 0, 0],
5655             detectColor: '#000000'
5656         };
5657         this._cvsCache.layer = this;
5658
5659         this._element = document.createElement('canvas');
5660         this._element.style.position = 'absolute';
5661         // issue 179
5662         this._element.style.left = this._element.style.top = '0px';
5663
5664         this._detect = document.createElement('canvas');
5665         this._detect.style.position = 'absolute';
5666         this._lastDetected = 0;
5667
5668         this.context = this._element.getContext('2d');
5669         this._dctx = this._detect.getContext('2d');
5670
5671         this._colorManager = new enchant.DetectColorManager(16, 256);
5672
5673         this.width = core.width;
5674         this.height = core.height;
5675
5676         var touch = [
5677             enchant.Event.TOUCH_START,
5678             enchant.Event.TOUCH_MOVE,
5679             enchant.Event.TOUCH_END
5680         ];
5681
5682         touch.forEach(function(type) {
5683             this.addEventListener(type, function(e) {
5684                 if (this._scene) {
5685                     this._scene.dispatchEvent(e);
5686                 }
5687             });
5688         }, this);
5689
5690         var __onchildadded = function(e) {
5691             var child = e.node;
5692             var self = e.target;
5693             var layer;
5694             if (self instanceof enchant.CanvasLayer) {
5695                 layer = self._scene._layers.Canvas;
5696             } else {
5697                 layer = self.scene._layers.Canvas;
5698             }
5699             enchant.CanvasLayer._attachCache(child, layer, __onchildadded, __onchildremoved);
5700             var render = new enchant.Event(enchant.Event.RENDER);
5701             if (self._dirty) {
5702                 self._updateCoordinate();
5703             }
5704             child._dirty = true;
5705             enchant.Matrix.instance.stack.push(self._matrix);
5706             enchant.CanvasRenderer.instance.render(layer.context, child, render);
5707             enchant.Matrix.instance.stack.pop(self._matrix);
5708         };
5709
5710         var __onchildremoved = function(e) {
5711             var child = e.node;
5712             var self = e.target;
5713             var layer;
5714             if (self instanceof enchant.CanvasLayer) {
5715                 layer = self._scene._layers.Canvas;
5716             } else {
5717                 layer = self.scene._layers.Canvas;
5718             }
5719             enchant.CanvasLayer._detachCache(child, layer, __onchildadded, __onchildremoved);
5720         };
5721
5722         this.addEventListener('childremoved', __onchildremoved);
5723         this.addEventListener('childadded', __onchildadded);
5724
5725     },
5726     width: {
5727         get: function() {
5728             return this._width;
5729         },
5730         set: function(width) {
5731             this._width = width;
5732             this._element.width = this._detect.width = width;
5733         }
5734     },
5735     height: {
5736         get: function() {
5737             return this._height;
5738         },
5739         set: function(height) {
5740             this._height = height;
5741             this._element.height = this._detect.height = height;
5742         }
5743     },
5744     addChild: function(node) {
5745         this.childNodes.push(node);
5746         node.parentNode = this;
5747         var childAdded = new enchant.Event('childadded');
5748         childAdded.node = node;
5749         childAdded.next = null;
5750         this.dispatchEvent(childAdded);
5751         node.dispatchEvent(new enchant.Event('added'));
5752         if (this.scene) {
5753             node.scene = this.scene;
5754             var addedToScene = new enchant.Event('addedtoscene');
5755             node.dispatchEvent(addedToScene);
5756         }
5757     },
5758     insertBefore: function(node, reference) {
5759         var i = this.childNodes.indexOf(reference);
5760         if (i !== -1) {
5761             this.childNodes.splice(i, 0, node);
5762             node.parentNode = this;
5763             var childAdded = new enchant.Event('childadded');
5764             childAdded.node = node;
5765             childAdded.next = reference;
5766             this.dispatchEvent(childAdded);
5767             node.dispatchEvent(new enchant.Event('added'));
5768             if (this.scene) {
5769                 node.scene = this.scene;
5770                 var addedToScene = new enchant.Event('addedtoscene');
5771                 node.dispatchEvent(addedToScene);
5772             }
5773         } else {
5774             this.addChild(node);
5775         }
5776     },
5777     /**
5778      [lang:ja]
5779      * レンダリングを開始.
5780      [/lang]
5781      * @private
5782      */
5783     _startRendering: function() {
5784         this.addEventListener('exitframe', this._onexitframe);
5785         this._onexitframe(new enchant.Event(enchant.Event.RENDER));
5786     },
5787     /**
5788      [lang:ja]
5789      * レンダリングを停止.
5790      [/lang]
5791      * @private
5792      */
5793     _stopRendering: function() {
5794         this.removeEventListener('render', this._onexitframe);
5795         this._onexitframe(new enchant.Event(enchant.Event.RENDER));
5796     },
5797     _onexitframe: function() {
5798         var core = enchant.Core.instance;
5799         var ctx = this.context;
5800         ctx.clearRect(0, 0, core.width, core.height);
5801         var render = new enchant.Event(enchant.Event.RENDER);
5802         enchant.CanvasRenderer.instance.render(ctx, this, render);
5803     },
5804     _determineEventTarget: function(e) {
5805         return this._getEntityByPosition(e.x, e.y);
5806     },
5807     _getEntityByPosition: function(x, y) {
5808         var core = enchant.Core.instance;
5809         var ctx = this._dctx;
5810         if (this._lastDetected < core.frame) {
5811             ctx.clearRect(0, 0, this.width, this.height);
5812             enchant.CanvasRenderer.instance.detectRender(ctx, this);
5813             this._lastDetected = core.frame;
5814         }
5815         var color = ctx.getImageData(x, y, 1, 1).data;
5816         return this._colorManager.getSpriteByColor(color);
5817     }
5818 });
5819
5820 enchant.CanvasLayer._attachCache = function(node, layer, onchildadded, onchildremoved) {
5821     var child;
5822     if (!node._cvsCache) {
5823         node._cvsCache = {};
5824         node._cvsCache.matrix = [ 1, 0, 0, 1, 0, 0 ];
5825         node._cvsCache.detectColor = 'rgba(' + layer._colorManager.attachDetectColor(node) + ')';
5826         node.addEventListener('childadded', onchildadded);
5827         node.addEventListener('childremoved', onchildremoved);
5828     }
5829     if (node.childNodes) {
5830         for (var i = 0, l = node.childNodes.length; i < l; i++) {
5831             child = node.childNodes[i];
5832             enchant.CanvasLayer._attachCache(child, layer, onchildadded, onchildremoved);
5833         }
5834     }
5835 };
5836
5837 enchant.CanvasLayer._detachCache = function(node, layer, onchildadded, onchildremoved) {
5838     var child;
5839     if (node._cvsCache) {
5840         layer._colorManager.detachDetectColor(node);
5841         node.removeEventListener('childadded', onchildadded);
5842         node.removeEventListener('childremoved', onchildremoved);
5843         delete node._cvsCache;
5844     }
5845     if (node.childNodes) {
5846         for (var i = 0, l = node.childNodes.length; i < l; i++) {
5847             child = node.childNodes[i];
5848             enchant.CanvasLayer._detachCache(child, layer, onchildadded, onchildremoved);
5849         }
5850     }
5851 };
5852
5853 enchant.CanvasRenderer = enchant.Class.create({
5854     render: function(ctx, node, e) {
5855         var width, height, child;
5856         ctx.save();
5857         node.dispatchEvent(e);
5858         // transform
5859         this.transform(ctx, node);
5860         if (typeof node._visible === 'undefined' || node._visible) {
5861             width = node.width;
5862             height = node.height;
5863             // composite
5864             if (node.compositeOperation) {
5865                 ctx.globalCompositeOperation = node.compositeOperation;
5866             }
5867             ctx.globalAlpha = (typeof node._opacity === 'number') ? node._opacity : 1.0;
5868             // render
5869             if (node._backgroundColor) {
5870                 ctx.fillStyle = node._backgroundColor;
5871                 ctx.fillRect(0, 0, width, height);
5872             }
5873
5874             if (node.cvsRender) {
5875                 node.cvsRender(ctx);
5876             }
5877
5878             if (enchant.Core.instance._debug && node._debugColor) {
5879                 ctx.strokeStyle = node._debugColor;
5880                 ctx.strokeRect(0, 0, width, height);
5881             }
5882             if (node._clipping) {
5883                 ctx.beginPath();
5884                 ctx.rect(0, 0, width, height);
5885                 ctx.clip();
5886             }
5887             if (node.childNodes) {
5888                 for (var i = 0, l = node.childNodes.length; i < l; i++) {
5889                     child = node.childNodes[i];
5890                     this.render(ctx, child, e);
5891                 }
5892             }
5893         }
5894         ctx.restore();
5895         enchant.Matrix.instance.stack.pop();
5896     },
5897     detectRender: function(ctx, node) {
5898         var width, height, child;
5899         if (typeof node._visible === 'undefined' || node._visible) {
5900             width = node.width;
5901             height = node.height;
5902             ctx.save();
5903             this.transform(ctx, node);
5904             ctx.fillStyle = node._cvsCache.detectColor;
5905             if (node._touchEnabled) {
5906                 if (node.detectRender) {
5907                     node.detectRender(ctx);
5908                 } else {
5909                     ctx.fillRect(0, 0, width, height);
5910                 }
5911             }
5912             if (node._clipping) {
5913                 ctx.beginPath();
5914                 ctx.rect(0, 0, width, height);
5915                 ctx.clip();
5916             }
5917             if (node.childNodes) {
5918                 for (var i = 0, l = node.childNodes.length; i < l; i++) {
5919                     child = node.childNodes[i];
5920                     this.detectRender(ctx, child);
5921                 }
5922             }
5923             ctx.restore();
5924             enchant.Matrix.instance.stack.pop();
5925         }
5926     },
5927     transform: function(ctx, node) {
5928         var matrix = enchant.Matrix.instance;
5929         var stack = matrix.stack;
5930         var newmat, ox, oy, vec;
5931         if (node._dirty) {
5932             matrix.makeTransformMatrix(node, node._cvsCache.matrix);
5933             newmat = [];
5934             matrix.multiply(stack[stack.length - 1], node._cvsCache.matrix, newmat);
5935             node._matrix = newmat;
5936             ox = (typeof node._originX === 'number') ? node._originX : node._width / 2 || 0;
5937             oy = (typeof node._originY === 'number') ? node._originY : node._height / 2 || 0;
5938             vec = [ ox, oy ];
5939             matrix.multiplyVec(newmat, vec, vec);
5940             node._offsetX = vec[0] - ox;
5941             node._offsetY = vec[1] - oy;
5942             node._dirty = false;
5943         } else {
5944             newmat = node._matrix;
5945         }
5946         stack.push(newmat);
5947         ctx.setTransform.apply(ctx, newmat);
5948     }
5949 });
5950 enchant.CanvasRenderer.instance = new enchant.CanvasRenderer();
5951
5952 /**
5953  * @scope enchant.Scene.prototype
5954  * @type {*}
5955  */
5956 enchant.Scene = enchant.Class.create(enchant.Group, {
5957     /**
5958      * @name enchant.Scene
5959      * @class
5960      [lang:ja]
5961      * 表示オブジェクトツリーのルートになるクラス.
5962      * シーンはレイヤーを持っていて、子として追加されたオブジェクト (Entity) は描画方法に応じてレイヤーに振り分けられる。
5963      * Scene クラスは最も汎用的なシーンの実装で、({@link enchant.DOMLayer} と {@link enchant.CanvasLayer}) を持っており、
5964      * それぞれ DOM, Canvas を用いて描画される。描画順は DOM が手前、Canvas が奥で、
5965      * 各レイヤーの間では新しく追加されたオブジェクトほど手前に表示される。
5966      * Scene クラスを継承することで、新しい種類の Layer を持つシーンクラスを作ることができる。
5967      [/lang]
5968      [lang:en]
5969      * A Class that becomes the root of the display object tree.
5970      [/lang]
5971      [lang:de]
5972      * Eine Klasse die zur Wurzel im Darstellungsobjektbaum wird.
5973      [/lang]
5974      *
5975      * @example
5976      *   var scene = new Scene();
5977      *   scene.addChild(player);
5978      *   scene.addChild(enemy);
5979      *   core.pushScene(scene);
5980      *
5981      * @constructs
5982      * @extends enchant.Group
5983      */
5984     initialize: function() {
5985         var core = enchant.Core.instance;
5986
5987         // Call initialize method of enchant.Group
5988         enchant.Group.call(this);
5989
5990         // All nodes (entities, groups, scenes) have reference to the scene that it belongs to.
5991         this.scene = this;
5992
5993         this._backgroundColor = null;
5994
5995         // Create div tag which possesses its layers
5996         this._element = document.createElement('div');
5997         this._element.style.position = 'absolute';
5998         this._element.style.overflow = 'hidden';
5999         this._element.style[enchant.ENV.VENDOR_PREFIX + 'TransformOrigin'] = '0 0';
6000
6001         this._layers = {};
6002         this._layerPriority = [];
6003
6004         this.addEventListener(enchant.Event.CHILD_ADDED, this._onchildadded);
6005         this.addEventListener(enchant.Event.CHILD_REMOVED, this._onchildremoved);
6006         this.addEventListener(enchant.Event.ENTER, this._onenter);
6007         this.addEventListener(enchant.Event.EXIT, this._onexit);
6008
6009         var that = this;
6010         this._dispatchExitframe = function() {
6011             var layer;
6012             for (var prop in that._layers) {
6013                 layer = that._layers[prop];
6014                 layer.dispatchEvent(new enchant.Event(enchant.Event.EXIT_FRAME));
6015             }
6016         };
6017
6018         this.addEventListener(enchant.Event.CORE_RESIZE, this._oncoreresize);
6019
6020         this._oncoreresize(core);
6021     },
6022     x: {
6023         get: function() {
6024             return this._x;
6025         },
6026         set: function(x) {
6027             this._x = x;
6028             for (var type in this._layers) {
6029                 this._layers[type].x = x;
6030             }
6031         }
6032     },
6033     y: {
6034         get: function() {
6035             return this._y;
6036         },
6037         set: function(y) {
6038             this._y = y;
6039             for (var type in this._layers) {
6040                 this._layers[type].y = y;
6041             }
6042         }
6043     },
6044     width: {
6045         get: function() {
6046             return this._width;
6047         },
6048         set: function(width) {
6049             this._width = width;
6050             for (var type in this._layers) {
6051                 this._layers[type].width = width;
6052             }
6053         }
6054     },
6055     height: {
6056         get: function() {
6057             return this._height;
6058         },
6059         set: function(height) {
6060             this._height = height;
6061             for (var type in this._layers) {
6062                 this._layers[type].height = height;
6063             }
6064         }
6065     },
6066     rotation: {
6067         get: function() {
6068             return this._rotation;
6069         },
6070         set: function(rotation) {
6071             this._rotation = rotation;
6072             for (var type in this._layers) {
6073                 this._layers[type].rotation = rotation;
6074             }
6075         }
6076     },
6077     scaleX: {
6078         get: function() {
6079             return this._scaleX;
6080         },
6081         set: function(scaleX) {
6082             this._scaleX = scaleX;
6083             for (var type in this._layers) {
6084                 this._layers[type].scaleX = scaleX;
6085             }
6086         }
6087     },
6088     scaleY: {
6089         get: function() {
6090             return this._scaleY;
6091         },
6092         set: function(scaleY) {
6093             this._scaleY = scaleY;
6094             for (var type in this._layers) {
6095                 this._layers[type].scaleY = scaleY;
6096             }
6097         }
6098     },
6099     backgroundColor: {
6100         get: function() {
6101             return this._backgroundColor;
6102         },
6103         set: function(color) {
6104             this._backgroundColor = this._element.style.backgroundColor = color;
6105         }
6106     },
6107     _oncoreresize: function(e) {
6108         this._element.style.width = e.width + 'px';
6109         this.width = e.width;
6110         this._element.style.height = e.height + 'px';
6111         this.height = e.height;
6112         this._element.style[enchant.ENV.VENDOR_PREFIX + 'Transform'] = 'scale(' + e.scale + ')';
6113
6114         for (var type in this._layers) {
6115             this._layers[type].dispatchEvent(e);
6116         }
6117     },
6118     addLayer: function(type, i) {
6119         var core = enchant.Core.instance;
6120         if (this._layers[type]) {
6121             return;
6122         }
6123         var layer = new enchant[type + 'Layer']();
6124         if (core.currentScene === this) {
6125             layer._startRendering();
6126         }
6127         this._layers[type] = layer;
6128         var element = layer._element;
6129         if (typeof i === 'number') {
6130             var nextSibling = this._element.childNodes[i];
6131             if (nextSibling) {
6132                 this._element.insertBefore(element, nextSibling);
6133             } else {
6134                 this._element.appendChild(element);
6135             }
6136             this._layerPriority.splice(i, 0, type);
6137         } else {
6138             this._element.appendChild(element);
6139             this._layerPriority.push(type);
6140         }
6141         layer._scene = this;
6142     },
6143     _determineEventTarget: function(e) {
6144         var layer, target;
6145         for (var i = this._layerPriority.length - 1; i >= 0; i--) {
6146             layer = this._layers[this._layerPriority[i]];
6147             target = layer._determineEventTarget(e);
6148             if (target) {
6149                 break;
6150             }
6151         }
6152         if (!target) {
6153             target = this;
6154         }
6155         return target;
6156     },
6157     _onchildadded: function(e) {
6158         var child = e.node;
6159         var next = e.next;
6160         var target, i;
6161         if (child._element) {
6162             target = 'Dom';
6163             i = 1;
6164         } else {
6165             target = 'Canvas';
6166             i = 0;
6167         }
6168         if (!this._layers[target]) {
6169             this.addLayer(target, i);
6170         }
6171         child._layer = this._layers[target];
6172         this._layers[target].insertBefore(child, next);
6173         child.parentNode = this;
6174     },
6175     _onchildremoved: function(e) {
6176         var child = e.node;
6177         child._layer.removeChild(child);
6178         child._layer = null;
6179     },
6180     _onenter: function() {
6181         for (var type in this._layers) {
6182             this._layers[type]._startRendering();
6183         }
6184         enchant.Core.instance.addEventListener('exitframe', this._dispatchExitframe);
6185     },
6186     _onexit: function() {
6187         for (var type in this._layers) {
6188             this._layers[type]._stopRendering();
6189         }
6190         enchant.Core.instance.removeEventListener('exitframe', this._dispatchExitframe);
6191     }
6192 });
6193
6194 /**
6195  * @scope enchant.LoadingScene.prototype
6196  */
6197 enchant.LoadingScene = enchant.Class.create(enchant.Scene, {
6198     /**
6199      * @name enchant.LoadingScene.
6200      * @class
6201      * @constructs
6202      * @extends enchant.Scene
6203      * Default loading scene. If you want to use your own loading animation, overwrite (don't inherit) this class.
6204      * Referred from enchant.Core in default, as `new enchant.LoadingScene` etc.
6205      *
6206      * @usage
6207      * enchant.LoadingScene = enchant.Class.create(enchant.Scene, {
6208      *    initialize: function(){
6209      *        enchant.Scene.call(this);
6210      *        this.backgroundColor = 'red';
6211      *        // ...
6212      *        this.addEventListener('progress', function(e){
6213      *            progress = e.loaded / e.total;
6214      *        });
6215      *        this.addEventListener('enterframe', function(){
6216      *            // animation
6217      *        });
6218      *    }
6219      * });
6220      */
6221     initialize: function() {
6222         enchant.Scene.call(this);
6223         this.backgroundColor = '#000';
6224         var barWidth = this.width * 0.4 | 0;
6225         var barHeight = this.width * 0.05 | 0;
6226         var border = barWidth * 0.03 | 0;
6227         var bar = new enchant.Sprite(barWidth, barHeight);
6228         bar.disableCollection();
6229         bar.x = (this.width - barWidth) / 2;
6230         bar.y = (this.height - barHeight) / 2;
6231         var image = new enchant.Surface(barWidth, barHeight);
6232         image.context.fillStyle = '#fff';
6233         image.context.fillRect(0, 0, barWidth, barHeight);
6234         image.context.fillStyle = '#000';
6235         image.context.fillRect(border, border, barWidth - border * 2, barHeight - border * 2);
6236         bar.image = image;
6237         var progress = 0, _progress = 0;
6238         this.addEventListener('progress', function(e) {
6239             // avoid #167 https://github.com/wise9/enchant.js/issues/177
6240             progress = e.loaded / e.total * 1.0;
6241         });
6242         bar.addEventListener('enterframe', function() {
6243             _progress *= 0.9;
6244             _progress += progress * 0.1;
6245             image.context.fillStyle = '#fff';
6246             image.context.fillRect(border, 0, (barWidth - border * 2) * _progress, barHeight);
6247         });
6248         this.addChild(bar);
6249         this.addEventListener('load', function(e) {
6250             var core = enchant.Core.instance;
6251             core.removeScene(core.loadingScene);
6252             core.dispatchEvent(e);
6253         });
6254     }
6255 });
6256
6257 /**
6258  * @scope enchant.CanvasScene.prototype
6259  * @type {*}
6260  */
6261 enchant.CanvasScene = enchant.Class.create(enchant.Scene, {
6262     initialize: function() {
6263         enchant.Scene.call(this);
6264         this.addLayer('Canvas');
6265     },
6266     _determineEventTarget: function(e) {
6267         var target = this._layers.Canvas._determineEventTarget(e);
6268         if (!target) {
6269             target = this;
6270         }
6271         return target;
6272     },
6273     _onchildadded: function(e) {
6274         var child = e.node;
6275         var next = e.next;
6276         child._layer = this._layers.Canvas;
6277         this._layers.Canvas.insertBefore(child, next);
6278     },
6279     _onenter: function() {
6280         this._layers.Canvas._startRendering();
6281         enchant.Core.instance.addEventListener('exitframe', this._dispatchExitframe);
6282     },
6283     _onexit: function() {
6284         this._layers.Canvas._stopRendering();
6285         enchant.Core.instance.removeEventListener('exitframe', this._dispatchExitframe);
6286     }
6287 });
6288
6289 /**
6290  * @scope enchant.CanvasScene.prototype
6291  * @type {*}
6292  */
6293 enchant.DOMScene = enchant.Class.create(enchant.Scene, {
6294     initialize: function() {
6295         enchant.Scene.call(this);
6296         this.addLayer('Dom');
6297     },
6298     _determineEventTarget: function(e) {
6299         var target = this._layers.Dom._determineEventTarget(e);
6300         if (!target) {
6301             target = this;
6302         }
6303         return target;
6304     },
6305     _onchildadded: function(e) {
6306         var child = e.node;
6307         var next = e.next;
6308         child._layer = this._layers.Dom;
6309         this._layers.Dom.insertBefore(child, next);
6310     },
6311     _onenter: function() {
6312         this._layers.Dom._startRendering();
6313         enchant.Core.instance.addEventListener('exitframe', this._dispatchExitframe);
6314     },
6315     _onexit: function() {
6316         this._layers.Dom._stopRendering();
6317         enchant.Core.instance.removeEventListener('exitframe', this._dispatchExitframe);
6318     }
6319 });
6320
6321 /**
6322  * @scope enchant.Surface.prototype
6323  */
6324 enchant.Surface = enchant.Class.create(enchant.EventTarget, {
6325     /**
6326      * @name enchant.Surface
6327      * @class
6328      [lang:ja]
6329      * canvas要素をラップしたクラス.
6330      *
6331      * {@link enchant.Sprite}や{@link enchant.Map}のimageプロパティに設定して表示させることができる.
6332      * Canvas APIにアクセスしたいときは{@link enchant.Surface#context}プロパティを用いる.
6333      *
6334      * @example
6335      *   // 円を表示するSpriteを作成する
6336      *   var ball = new Sprite(50, 50);
6337      *   var surface = new Surface(50, 50);
6338      *   surface.context.beginPath();
6339      *   surface.context.arc(25, 25, 25, 0, Math.PI*2, true);
6340      *   surface.context.fill();
6341      *   ball.image = surface;
6342      *
6343      * @param {Number} width Surfaceの横幅.
6344      * @param {Number} height Surfaceの高さ.
6345      [/lang]
6346      [lang:en]
6347      * Class that wraps canvas elements.
6348      *
6349      * Can be used to set the {@link enchant.Sprite} and {@link enchant.Map}'s image properties to be displayed.
6350      * If you wish to access Canvas API use the {@link enchant.Surface#context} property.
6351      *
6352      * @example
6353      *   // Creates Sprite that displays a circle.
6354      *   var ball = new Sprite(50, 50);
6355      *   var surface = new Surface(50, 50);
6356      *   surface.context.beginPath();
6357      *   surface.context.arc(25, 25, 25, 0, Math.PI*2, true);
6358      *   surface.context.fill();
6359      *   ball.image = surface;
6360      *
6361      * @param {Number} width Surface width.
6362      * @param {Number} height Surface height.
6363      [/lang]
6364      [lang:de]
6365      * Diese Klasse dient als Hüllenklasse (Wrapper) für Canvas Elemente.
6366      *
6367      * Mit dieser Klasse können die image Felder der {@link enchant.Sprite} und {@link enchant.Map}'s
6368      * Klassen gesetzt werden und dadurch dargestellt werden.
6369      * Falls die Canvas API genutzt werden möchte kann dies über die
6370      * {@link enchant.Surface#context} Variable erfolgen.
6371      *
6372      * @example
6373      *   // Erstellt einen Sprite und stellt einen Kreis dar.
6374      *   var ball = new Sprite(50, 50);
6375      *   var surface = new Surface(50, 50);
6376      *   surface.context.beginPath();
6377      *   surface.context.arc(25, 25, 25, 0, Math.PI*2, true);
6378      *   surface.context.fill();
6379      *   ball.image = surface;
6380      *
6381      * @param {Number} width Die Breite der Surface.
6382      * @param {Number} height Die Höhe der Surface.
6383      [/lang]
6384      * @constructs
6385      */
6386     initialize: function(width, height) {
6387         enchant.EventTarget.call(this);
6388
6389         var core = enchant.Core.instance;
6390
6391         /**
6392          [lang:ja]
6393          * Surfaceの横幅.
6394          [/lang]
6395          [lang:en]
6396          * Surface width.
6397          [/lang]
6398          [lang:de]
6399          * Die Breite der Surface.
6400          [/lang]
6401          * @type {Number}
6402          */
6403         this.width = width;
6404         /**
6405          [lang:ja]
6406          * Surfaceの高さ.
6407          [/lang]
6408          [lang:en]
6409          * Surface height.
6410          [/lang]
6411          [lang:de]
6412          * Die Höhe der Surface.
6413          [/lang]
6414          * @type {Number}
6415          */
6416         this.height = height;
6417         /**
6418          [lang:ja]
6419          * Surfaceの描画コンテクスト.
6420          [/lang]
6421          [lang:en]
6422          * Surface drawing context.
6423          [/lang]
6424          [lang:de]
6425          * Der Surface Zeichenkontext.
6426          [/lang]
6427          * @type {CanvasRenderingContext2D}
6428          */
6429         this.context = null;
6430
6431         var id = 'enchant-surface' + core._surfaceID++;
6432         if (document.getCSSCanvasContext) {
6433             this.context = document.getCSSCanvasContext('2d', id, width, height);
6434             this._element = this.context.canvas;
6435             this._css = '-webkit-canvas(' + id + ')';
6436             var context = this.context;
6437         } else if (document.mozSetImageElement) {
6438             this._element = document.createElement('canvas');
6439             this._element.width = width;
6440             this._element.height = height;
6441             this._css = '-moz-element(#' + id + ')';
6442             this.context = this._element.getContext('2d');
6443             document.mozSetImageElement(id, this._element);
6444         } else {
6445             this._element = document.createElement('canvas');
6446             this._element.width = width;
6447             this._element.height = height;
6448             this._element.style.position = 'absolute';
6449             this.context = this._element.getContext('2d');
6450
6451             enchant.ENV.CANVAS_DRAWING_METHODS.forEach(function(name) {
6452                 var method = this.context[name];
6453                 this.context[name] = function() {
6454                     method.apply(this, arguments);
6455                     this._dirty = true;
6456                 };
6457             }, this);
6458         }
6459     },
6460     /**
6461      [lang:ja]
6462      * Surfaceから1ピクセル取得する.
6463      * @param {Number} x 取得するピクセルのx座標.
6464      * @param {Number} y 取得するピクセルのy座標.
6465      * @return {Array.<Number>} ピクセルの情報を[r, g, b, a]の形式で持つ配列.
6466      [/lang]
6467      [lang:en]
6468      * Returns 1 pixel from the Surface.
6469      * @param {Number} x The pixel's x coordinates.
6470      * @param {Number} y The pixel's y coordinates.
6471      * @return {Array.<Number>} An array that holds pixel information in [r, g, b, a] format.
6472      [/lang]
6473      [lang:de]
6474      * Liefert einen Pixel der Surface.
6475      * @param {Number} x Die x Koordinaten des Pixel.
6476      * @param {Number} y Die y Koordinaten des Pixel.
6477      * @return {Array.<Number>} Ein Array das die Pixelinformationen im [r, g, b, a] Format enthält.
6478      [/lang]
6479      */
6480     getPixel: function(x, y) {
6481         return this.context.getImageData(x, y, 1, 1).data;
6482     },
6483     /**
6484      [lang:ja]
6485      * Surfaceに1ピクセル設定する.
6486      * @param {Number} x 設定するピクセルのx座標.
6487      * @param {Number} y 設定するピクセルのy座標.
6488      * @param {Number} r 設定するピクセルのrの値.
6489      * @param {Number} g 設定するピクセルのgの値.
6490      * @param {Number} b 設定するピクセルのbの値.
6491      * @param {Number} a 設定するピクセルの透明度.
6492      [/lang]
6493      [lang:en]
6494      * Sets one pixel within the surface.
6495      * @param {Number} x The pixel's x coordinates.
6496      * @param {Number} y The pixel's y coordinates.
6497      * @param {Number} r The pixel's red level.
6498      * @param {Number} g The pixel's green level.
6499      * @param {Number} b The pixel's blue level.
6500      * @param {Number} a The pixel's transparency.
6501      [/lang]
6502      [lang:de]
6503      * Setzt einen Pixel in der Surface.
6504      * @param {Number} x Die x Koordinaten des Pixel.
6505      * @param {Number} y Die y Koordinaten des Pixel.
6506      * @param {Number} r Der Rotwert des Pixel.
6507      * @param {Number} g Der Grünwert des Pixel.
6508      * @param {Number} b Der Blauwert des Pixels.
6509      * @param {Number} a Die Transparenz des Pixels
6510      [/lang]
6511      */
6512     setPixel: function(x, y, r, g, b, a) {
6513         var pixel = this.context.createImageData(1, 1);
6514         pixel.data[0] = r;
6515         pixel.data[1] = g;
6516         pixel.data[2] = b;
6517         pixel.data[3] = a;
6518         this.context.putImageData(pixel, x, y);
6519     },
6520     /**
6521      [lang:ja]
6522      * Surfaceの全ピクセルをクリアし透明度0の黒に設定する.
6523      [/lang]
6524      [lang:en]
6525      * Clears all Surface pixels and makes the pixels transparent.
6526      [/lang]
6527      [lang:de]
6528      * Löscht alle Pixel und setzt macht die Pixel transparent.
6529      [/lang]
6530      */
6531     clear: function() {
6532         this.context.clearRect(0, 0, this.width, this.height);
6533     },
6534     /**
6535      [lang:ja]
6536      * Surfaceに対して引数で指定されたSurfaceを描画する.
6537      *
6538      * Canvas APIのdrawImageをラップしており, 描画する矩形を同様の形式で指定できる.
6539      *
6540      * @example
6541      *   var src = core.assets['src.gif'];
6542      *   var dst = new Surface(100, 100);
6543      *   dst.draw(src);         // ソースを(0, 0)に描画
6544      *   dst.draw(src, 50, 50); // ソースを(50, 50)に描画
6545      *   // ソースを(50, 50)に縦横30ピクセル分だけ描画
6546      *   dst.draw(src, 50, 50, 30, 30);
6547      *   // ソースの(10, 10)から縦横40ピクセルの領域を(50, 50)に縦横30ピクセルに縮小して描画
6548      *   dst.draw(src, 10, 10, 40, 40, 50, 50, 30, 30);
6549      *
6550      * @param {enchant.Surface} image 描画に用いるSurface.
6551      [/lang]
6552      [lang:en]
6553      * Draws the content of the given Surface onto this surface.
6554      *
6555      * Wraps Canvas API drawImage and if multiple arguments are given,
6556      * these are getting applied to the Canvas drawImage method.
6557      *
6558      * @example
6559      *   var src = core.assets['src.gif'];
6560      *   var dst = new Surface(100, 100);
6561      *   dst.draw(src);         // Draws source at (0, 0)
6562      *   dst.draw(src, 50, 50); // Draws source at (50, 50)
6563      *   // Draws just 30 horizontal and vertical pixels of source at (50, 50)
6564      *   dst.draw(src, 50, 50, 30, 30);
6565      *   // Takes the image content in src starting at (10,10) with a (Width, Height) of (40,40),
6566      *   // scales it and draws it in this surface at (50, 50) with a (Width, Height) of (30,30).
6567      *   dst.draw(src, 10, 10, 40, 40, 50, 50, 30, 30);
6568      *
6569      * @param {enchant.Surface} image Surface used in drawing.
6570      [/lang]
6571      [lang:de]
6572      * Zeichnet den Inhalt der gegebenen Surface auf diese Surface.
6573      *
6574      * Umhüllt (wraps) die Canvas drawImage Methode und sollten mehrere Argumente
6575      * übergeben werden, werden diese auf die Canvas drawImage Methode angewendet.
6576      *
6577      * @example
6578      *   var src = core.assets['src.gif'];
6579      *   var dst = new Surface(100, 100);
6580      *   dst.draw(src);         // Zeichnet src bei (0, 0)
6581      *   dst.draw(src, 50, 50); // Zeichnet src bei (50, 50)
6582      *   // Zeichnet src an der Position (50,50), jedoch nur 30x30 Pixel
6583      *   dst.draw(src, 50, 50, 30, 30);
6584      *   // Skaliert und zeichnet den Bereich mit der (Breite, Höhe) von (40, 40)
6585      *   // in src ab (10,10) in diese Surface bei (50,50) mit einer (Breite, Höhe) von (30, 30).
6586      *   dst.draw(src, 10, 10, 40, 40, 50, 50, 30, 30);
6587      *
6588      * @param {enchant.Surface} image Surface used in drawing.
6589      [/lang]
6590      */
6591     draw: function(image) {
6592         image = image._element;
6593         if (arguments.length === 1) {
6594             this.context.drawImage(image, 0, 0);
6595         } else {
6596             var args = arguments;
6597             args[0] = image;
6598             this.context.drawImage.apply(this.context, args);
6599         }
6600     },
6601     /**
6602      [lang:ja]
6603      * Surfaceを複製する.
6604      * @return {enchant.Surface} 複製されたSurface.
6605      [/lang]
6606      [lang:en]
6607      * Copies Surface.
6608      * @return {enchant.Surface} The copied Surface.
6609      [/lang]
6610      [lang:de]
6611      * Kopiert diese Surface.
6612      * @return {enchant.Surface} Die kopierte Surface.
6613      [/lang]
6614      */
6615     clone: function() {
6616         var clone = new enchant.Surface(this.width, this.height);
6617         clone.draw(this);
6618         return clone;
6619     },
6620     /**
6621      [lang:ja]
6622      * SurfaceからdataスキームのURLを生成する.
6623      * @return {String} Surfaceを表すdataスキームのURL.
6624      [/lang]
6625      [lang:en]
6626      * Creates a data URI scheme from this Surface.
6627      * @return {String} The data URI scheme that identifies this Surface and
6628      * can be used to include this Surface into a dom tree.
6629      [/lang]
6630      [lang:de]
6631      * Erstellt eine Data-URL (URI Schema) für diese Surface.
6632      * @return {String} Die Data-URL, welche diese Surface identifiziert und
6633      * welche genutzt werden kann um diese in einen DOM Baum einzubinden.
6634      [/lang]
6635      */
6636     toDataURL: function() {
6637         var src = this._element.src;
6638         if (src) {
6639             if (src.slice(0, 5) === 'data:') {
6640                 return src;
6641             } else {
6642                 return this.clone().toDataURL();
6643             }
6644         } else {
6645             return this._element.toDataURL();
6646         }
6647     }
6648 });
6649
6650 /**
6651  [lang:ja]
6652  * 画像ファイルを読み込んでSurfaceオブジェクトを作成する.
6653  *
6654  * このメソッドによって作成されたSurfaceはimg要素のラップしており{@link enchant.Surface#context}プロパティに
6655  * アクセスしたり{@link enchant.Surface#draw}, {@link enchant.Surface#clear}, {@link enchant.Surface#getPixel},
6656  * {@link enchant.Surface#setPixel}メソッドなどの呼び出しでCanvas APIを使った画像操作を行うことはできない.
6657  * ただし{@link enchant.Surface#draw}メソッドの引数とすることはでき,
6658  * ほかのSurfaceに描画した上で画像操作を行うことはできる(クロスドメインでロードした
6659  * 場合はピクセルを取得するなど画像操作の一部が制限される).
6660  *
6661  * @param {String} src ロードする画像ファイルのパス.
6662  * @param {Function} callback ロード完了時のコールバック.
6663  * @param {Function} [onerror] ロード失敗時のコールバック.
6664  [/lang]
6665  [lang:en]
6666  * Loads an image and creates a Surface object out of it.
6667  *
6668  * It is not possible to access properties or methods of the {@link enchant.Surface#context}, or to call methods using the Canvas API -
6669  * like {@link enchant.Surface#draw}, {@link enchant.Surface#clear}, {@link enchant.Surface#getPixel}, {@link enchant.Surface#setPixel}.. -
6670  * of the wrapped image created with this method.
6671  * However, it is possible to use this surface to draw it to another surface using the {@link enchant.Surface#draw} method.
6672  * The resulting surface can then be manipulated. (when loading images in a cross-origin resource sharing environment,
6673  * pixel acquisition and other image manipulation might be limited).
6674  *
6675  * @param {String} src The file path of the image to be loaded.
6676  * @param {Function} callback on load callback.
6677  * @param {Function} [onerror] on error callback.
6678  [/lang]
6679  [lang:de]
6680  * Läd eine Grafik und erstellt daraus ein Surface Objekt.
6681  *
6682  * Bei Grafiken die mit dieser Methode erstellt wurden ist es nicht möglich auf Variablen oder Methoden des {@link enchant.Surface#context}
6683  * zuzugreifen, oder Methoden die die Canvas API nutzen, wie {@link enchant.Surface#draw}, {@link enchant.Surface#clear},
6684  * {@link enchant.Surface#getPixel}, {@link enchant.Surface#setPixel}.., aufzurufen.
6685  * Jedoch ist es möglich diese Surface zu nutzen um sie in eine andere Surface mittels der {@link enchant.Surface#draw} zu zeichen.
6686  * Die daraus resultierende Surface kann dann manipuliert werden. (Wenn Bilder in einer Cross-Origin Resource Sharing Umgebung
6687  * geladen werden, kann es sein, dass die Pixelabfrage und andere Bildmanipulationen limitiert sind)
6688  *
6689  * @param {String} src Der Dateipfad der Grafik die geladen werden soll.
6690  [/lang]
6691  * @static
6692  * @return {enchant.Surface} Surface
6693  */
6694 enchant.Surface.load = function(src, callback, onerror) {
6695     var image = new Image();
6696     var surface = Object.create(enchant.Surface.prototype, {
6697         context: { value: null },
6698         _css: { value: 'url(' + src + ')' },
6699         _element: { value: image }
6700     });
6701     enchant.EventTarget.call(surface);
6702     onerror = onerror || function() {};
6703     surface.addEventListener('load', callback);
6704     surface.addEventListener('error', onerror);
6705     image.onerror = function() {
6706         var e = new enchant.Event(enchant.Event.ERROR);
6707         e.message = 'Cannot load an asset: ' + image.src;
6708         enchant.Core.instance.dispatchEvent(e);
6709         surface.dispatchEvent(e);
6710     };
6711     image.onload = function() {
6712         surface.width = image.width;
6713         surface.height = image.height;
6714         surface.dispatchEvent(new enchant.Event('load'));
6715     };
6716     image.src = src;
6717     return surface;
6718 };
6719 enchant.Surface._staticCanvas2DContext = document.createElement('canvas').getContext('2d');
6720
6721 enchant.Surface._getPattern = function(surface, force) {
6722     if (!surface._pattern || force) {
6723         surface._pattern = this._staticCanvas2DContext.createPattern(surface._element, 'repeat');
6724     }
6725     return surface._pattern;
6726 };
6727
6728 if (window.Deferred) {
6729     enchant.Deferred = window.Deferred;
6730 } else {
6731     enchant.Deferred = enchant.Class.create({
6732         initialize: function() {
6733             this._succ = this._fail = this._next = this._id = null;
6734             this._tail = this;
6735         },
6736         next: function(func) {
6737             var q = new enchant.Deferred();
6738             q._succ = func;
6739             return this._add(q);
6740         },
6741         error: function(func) {
6742             var q = new enchant.Deferred();
6743             q._fail = func;
6744             return this._add(q);
6745         },
6746         _add: function(queue) {
6747             this._tail._next = queue;
6748             this._tail = queue;
6749             return this;
6750         },
6751         call: function(arg) {
6752             var received;
6753             var queue = this;
6754             while (queue && !queue._succ) {
6755                 queue = queue._next;
6756             }
6757             if (!(queue instanceof enchant.Deferred)) {
6758                 return;
6759             }
6760             try {
6761                 received = queue._succ(arg);
6762             } catch (e) {
6763                 return queue.fail(e);
6764             }
6765             if (received instanceof enchant.Deferred) {
6766                 enchant.Deferred._insert(queue, received);
6767             } else if (queue._next instanceof enchant.Deferred) {
6768                 queue._next.call(received);
6769             }
6770         },
6771         fail: function(arg) {
6772             var result, err,
6773                 queue = this;
6774             while (queue && !queue._fail) {
6775                 queue = queue._next;
6776             }
6777             if (queue instanceof enchant.Deferred) {
6778                 result = queue._fail(arg);
6779                 queue.call(result);
6780             } else if (arg instanceof Error) {
6781                 throw arg;
6782             } else {
6783                 err = new Error('failed in Deferred');
6784                 err.arg = arg;
6785                 throw err;
6786             }
6787         }
6788     });
6789     enchant.Deferred._insert = function(queue, ins) {
6790         if (queue._next instanceof enchant.Deferred) {
6791             ins._next = queue._next;
6792         }
6793         queue._next = ins;
6794     };
6795     enchant.Deferred.next = function(func) {
6796         var q = new enchant.Deferred().next(func);
6797         q._id = setTimeout(function() { q.call(); }, 0);
6798         return q;
6799     };
6800     enchant.Deferred.parallel = function(arg) {
6801         var q = new enchant.Deferred();
6802         q._id = setTimeout(function() { q.call(); }, 0);
6803         var progress = 0;
6804         var ret = (arg instanceof Array) ? [] : {};
6805         var p = new enchant.Deferred();
6806         for (var prop in arg) {
6807             if (arg.hasOwnProperty(prop)) {
6808                 progress++;
6809                 /*jshint loopfunc:true */
6810                 (function(queue, name) {
6811                     queue.next(function(arg) {
6812                         progress--;
6813                         ret[name] = arg;
6814                         if (progress <= 0) {
6815                             p.call(ret);
6816                         }
6817                     })
6818                     .error(function(err) { p.fail(err); });
6819                     if (typeof queue._id === 'number') {
6820                         clearTimeout(queue._id);
6821                     }
6822                     queue._id = setTimeout(function() { queue.call(); }, 0);
6823                 }(arg[prop], prop));
6824             }
6825         }
6826         if (!progress) {
6827             p._id = setTimeout(function() { p.call(ret); }, 0);
6828         }
6829         return q.next(function() { return p; });
6830     };
6831 }
6832
6833 /**
6834  * @scope enchant.DOMSound.prototype
6835  * @type {*}
6836  */
6837 enchant.DOMSound = enchant.Class.create(enchant.EventTarget, {
6838     /**
6839      * @name enchant.DOMSound
6840      * @class
6841      [lang:ja]
6842      * audio要素をラップしたクラス.
6843      *
6844      * MP3ファイルの再生はSafari, Chrome, Firefox, Opera, IEが対応
6845      * (Firefox, OperaではFlashを経由して再生). WAVEファイルの再生は
6846      * Safari, Chrome, Firefox, Operaが対応している. ブラウザが音声ファイル
6847      * のコーデックに対応していない場合は再生されない.
6848      *
6849      * コンストラクタではなく{@link enchant.DOMSound.load}を通じてインスタンスを作成する.
6850      [/lang]
6851      [lang:en]
6852      * Class to wrap audio elements.
6853      *
6854      * Safari, Chrome, Firefox, Opera, and IE all play MP3 files
6855      * (Firefox and Opera play via Flash). WAVE files can be played on
6856      * Safari, Chrome, Firefox, and Opera. When the browser is not compatible with
6857      * the used codec the file will not play.
6858      *
6859      * Instances are created not via constructor but via {@link enchant.DOMSound.load}.
6860      [/lang]
6861      [lang:de]
6862      * Klasse die eine Hüllenklasse (Wrapper) für Audio Elemente darstellt.
6863      *
6864      * Safari, Chrome, Firefox, Opera, und IE können alle MP3 Dateien abspielen
6865      * (Firefox und Opera spielen diese mit Hilfe von Flash ab). WAVE Dateien können
6866      * Safari, Chrome, Firefox, and Opera abspielen. Sollte der Browser nicht mit
6867      * dem genutzten Codec kompatibel sein, wird die Datei nicht abgespielt.
6868      *
6869      * Instanzen dieser Klasse werden nicht mit Hilfe des Konstruktors, sondern mit
6870      * {@link enchant.DOMSound.load} erstellt.
6871      [/lang]
6872      * @constructs
6873      */
6874     initialize: function() {
6875         enchant.EventTarget.call(this);
6876         /**
6877          [lang:ja]
6878          * Soundの再生時間 (秒).
6879          [/lang]
6880          [lang:en]
6881          * Sound file duration (seconds).
6882          [/lang]
6883          [lang:de]
6884          * Die länge der Sounddatei in Sekunden.
6885          [/lang]
6886          * @type {Number}
6887          */
6888         this.duration = 0;
6889         throw new Error("Illegal Constructor");
6890     },
6891     /**
6892      [lang:ja]
6893      * 再生を開始する.
6894      [/lang]
6895      [lang:en]
6896      * Begin playing.
6897      [/lang]
6898      [lang:de]
6899      * Startet die Wiedergabe.
6900      [/lang]
6901      */
6902     play: function() {
6903         if (this._element) {
6904             this._element.play();
6905         }
6906     },
6907     /**
6908      [lang:ja]
6909      * 再生を中断する.
6910      [/lang]
6911      [lang:en]
6912      * Pause playback.
6913      [/lang]
6914      [lang:de]
6915      * Pausiert die Wiedergabe.
6916      [/lang]
6917      */
6918     pause: function() {
6919         if (this._element) {
6920             this._element.pause();
6921         }
6922     },
6923     /**
6924      [lang:ja]
6925      * 再生を停止する.
6926      [/lang]
6927      [lang:en]
6928      * Stop playing.
6929      [/lang]
6930      [lang:de]
6931      * Stoppt die Wiedergabe.
6932      [/lang]
6933      */
6934     stop: function() {
6935         this.pause();
6936         this.currentTime = 0;
6937     },
6938     /**
6939      [lang:ja]
6940      * Soundを複製する.
6941      * @return {enchant.DOMSound} 複製されたSound.
6942      [/lang]
6943      [lang:en]
6944      * Create a copy of this Sound object.
6945      * @return {enchant.DOMSound} Copied Sound.
6946      [/lang]
6947      [lang:de]
6948      * Erstellt eine Kopie dieses Soundobjektes.
6949      * @return {enchant.DOMSound} Kopiertes Sound Objekt.
6950      [/lang]
6951      */
6952     clone: function() {
6953         var clone;
6954         if (this._element instanceof Audio) {
6955             clone = Object.create(enchant.DOMSound.prototype, {
6956                 _element: { value: this._element.cloneNode(false) },
6957                 duration: { value: this.duration }
6958             });
6959         } else if (enchant.ENV.USE_FLASH_SOUND) {
6960             return this;
6961         } else {
6962             clone = Object.create(enchant.DOMSound.prototype);
6963         }
6964         enchant.EventTarget.call(clone);
6965         return clone;
6966     },
6967     /**
6968      [lang:ja]
6969      * 現在の再生位置 (秒).
6970      [/lang]
6971      [lang:en]
6972      * Current playback position (seconds).
6973      [/lang]
6974      [lang:de]
6975      * Aktuelle Wiedergabeposition (seconds).
6976      [/lang]
6977      * @type {Number}
6978      */
6979     currentTime: {
6980         get: function() {
6981             return this._element ? this._element.currentTime : 0;
6982         },
6983         set: function(time) {
6984             if (this._element) {
6985                 this._element.currentTime = time;
6986             }
6987         }
6988     },
6989     /**
6990      [lang:ja]
6991      * ボリューム. 0 (無音) ~ 1 (フルボリューム).
6992      [/lang]
6993      [lang:en]
6994      * Volume. 0 (muted) ~ 1 (full volume).
6995      [/lang]
6996      [lang:de]
6997      * Lautstärke. 0 (stumm) ~ 1 (volle Lautstärke).
6998      [/lang]
6999      * @type {Number}
7000      */
7001     volume: {
7002         get: function() {
7003             return this._element ? this._element.volume : 1;
7004         },
7005         set: function(volume) {
7006             if (this._element) {
7007                 this._element.volume = volume;
7008             }
7009         }
7010     }
7011 });
7012
7013 /**
7014  [lang:ja]
7015  * 音声ファイルを読み込んでSoundオブジェクトを作成する.
7016  *
7017  * @param {String} src ロードする音声ファイルのパス.
7018  * @param {String} [type] 音声ファイルのMIME Type.
7019  * @param {Function} callback ロード完了時のコールバック.
7020  * @param {Function} [onerror] ロード失敗時のコールバック.
7021  [/lang]
7022  [lang:en]
7023  * Loads an audio file and creates Sound object.
7024  *
7025  * @param {String} src Path of the audio file to be loaded.
7026  * @param {String} [type] MIME Type of the audio file.
7027  * @param {Function} callback on load callback.
7028  * @param {Function} [onerror] on error callback.
7029  [/lang]
7030  [lang:de]
7031  * Läd eine Audio Datei und erstellt ein Sound objekt.
7032  *
7033  * @param {String} src Pfad zu der zu ladenden Audiodatei.
7034  * @param {String} [type] MIME Type der Audtiodatei.
7035  [/lang]
7036  * @return {enchant.DOMSound} DOMSound
7037  * @static
7038  */
7039 enchant.DOMSound.load = function(src, type, callback, onerror) {
7040     if (type == null) {
7041         var ext = enchant.Core.findExt(src);
7042         if (ext) {
7043             type = 'audio/' + ext;
7044         } else {
7045             type = '';
7046         }
7047     }
7048     type = type.replace('mp3', 'mpeg').replace('m4a', 'mp4');
7049     onerror = onerror || function() {};
7050
7051     var sound = Object.create(enchant.DOMSound.prototype);
7052     enchant.EventTarget.call(sound);
7053     sound.addEventListener('load', callback);
7054     sound.addEventListener('error', onerror);
7055     var audio = new Audio();
7056     if (!enchant.ENV.SOUND_ENABLED_ON_MOBILE_SAFARI &&
7057         enchant.ENV.VENDOR_PREFIX === 'webkit' && enchant.ENV.TOUCH_ENABLED) {
7058         window.setTimeout(function() {
7059             sound.dispatchEvent(new enchant.Event('load'));
7060         }, 0);
7061     } else {
7062         if (!enchant.ENV.USE_FLASH_SOUND && audio.canPlayType(type)) {
7063             audio.addEventListener('canplaythrough', function() {
7064                 sound.duration = audio.duration;
7065                 sound.dispatchEvent(new enchant.Event('load'));
7066             }, false);
7067             audio.src = src;
7068             audio.load();
7069             audio.autoplay = false;
7070             audio.onerror = function() {
7071                 var e = new enchant.Event(enchant.Event.ERROR);
7072                 e.message = 'Cannot load an asset: ' + audio.src;
7073                 enchant.Core.instance.dispatchEvent(e);
7074                 sound.dispatchEvent(e);
7075             };
7076             sound._element = audio;
7077         } else if (type === 'audio/mpeg') {
7078             var embed = document.createElement('embed');
7079             var id = 'enchant-audio' + enchant.Core.instance._soundID++;
7080             embed.width = embed.height = 1;
7081             embed.name = id;
7082             embed.src = 'sound.swf?id=' + id + '&src=' + src;
7083             embed.allowscriptaccess = 'always';
7084             embed.style.position = 'absolute';
7085             embed.style.left = '-1px';
7086             sound.addEventListener('load', function() {
7087                 Object.defineProperties(embed, {
7088                     currentTime: {
7089                         get: function() {
7090                             return embed.getCurrentTime();
7091                         },
7092                         set: function(time) {
7093                             embed.setCurrentTime(time);
7094                         }
7095                     },
7096                     volume: {
7097                         get: function() {
7098                             return embed.getVolume();
7099                         },
7100                         set: function(volume) {
7101                             embed.setVolume(volume);
7102                         }
7103                     }
7104                 });
7105                 sound._element = embed;
7106                 sound.duration = embed.getDuration();
7107             });
7108             enchant.Core.instance._element.appendChild(embed);
7109             enchant.DOMSound[id] = sound;
7110         } else {
7111             window.setTimeout(function() {
7112                 sound.dispatchEvent(new enchant.Event('load'));
7113             }, 0);
7114         }
7115     }
7116     return sound;
7117 };
7118
7119
7120 window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext || window.oAudioContext;
7121
7122 /**
7123  * @scope enchant.WebAudioSound.prototype
7124  * @type {*}
7125  */
7126 enchant.WebAudioSound = enchant.Class.create(enchant.EventTarget, {
7127     /**
7128      * @name enchant.WebAudioSound
7129      * @class
7130      * Sound wrapper class for Web Audio API (supported on some webkit-based browsers)
7131      *
7132      * @constructs
7133      */
7134     initialize: function() {
7135         if(!window.webkitAudioContext){
7136             throw new Error("This browser does not support WebAudio API.");
7137         }
7138         var actx = enchant.WebAudioSound.audioContext;
7139         enchant.EventTarget.call(this);
7140         this.src = actx.createBufferSource();
7141         this.buffer = null;
7142         this._volume = 1;
7143         this._currentTime = 0;
7144         this._state = 0;
7145         this.connectTarget = enchant.WebAudioSound.destination;
7146     },
7147     play: function(dup) {
7148         var actx = enchant.WebAudioSound.audioContext;
7149         if (this._state === 2) {
7150             this.src.connect(this.connectTarget);
7151         } else {
7152             if (this._state === 1 && !dup) {
7153                 this.src.disconnect(this.connectTarget);
7154             }
7155             this.src = actx.createBufferSource();
7156             this.src.buffer = this.buffer;
7157             this.src.gain.value = this._volume;
7158             this.src.connect(this.connectTarget);
7159             this.src.noteOn(0);
7160         }
7161         this._state = 1;
7162     },
7163     pause: function() {
7164         var actx = enchant.WebAudioSound.audioContext;
7165         this.src.disconnect(this.connectTarget);
7166         this._state = 2;
7167     },
7168     stop: function() {
7169         this.src.noteOff(0);
7170         this._state = 0;
7171     },
7172     clone: function() {
7173         var sound = new enchant.WebAudioSound();
7174         sound.buffer = this.buffer;
7175         return sound;
7176     },
7177     dulation: {
7178         get: function() {
7179             if (this.buffer) {
7180                 return this.buffer.dulation;
7181             } else {
7182                 return 0;
7183             }
7184         }
7185     },
7186     volume: {
7187         get: function() {
7188             return this._volume;
7189         },
7190         set: function(volume) {
7191             volume = Math.max(0, Math.min(1, volume));
7192             this._volume = volume;
7193             if (this.src) {
7194                 this.src.gain.value = volume;
7195             }
7196         }
7197     },
7198     currentTime: {
7199         get: function() {
7200             window.console.log('currentTime is not allowed');
7201             return this._currentTime;
7202         },
7203         set: function(time) {
7204             window.console.log('currentTime is not allowed');
7205             this._currentTime = time;
7206         }
7207     }
7208 });
7209
7210 enchant.WebAudioSound.load = function(src, type, callback, onerror) {
7211     var canPlay = (new Audio()).canPlayType(type);
7212     var sound = new enchant.WebAudioSound();
7213     onerror = onerror || function() {};
7214     sound.addEventListener(enchant.Event.LOAD, callback);
7215     sound.addEventListener(enchant.Event.ERROR, onerror);
7216     var e = new enchant.Event(enchant.Event.ERROR);
7217     e.message = 'Cannot load an asset: ' + src;
7218     var actx, xhr;
7219     if (canPlay === 'maybe' || canPlay === 'probably') {
7220         actx = enchant.WebAudioSound.audioContext;
7221         xhr = new XMLHttpRequest();
7222         xhr.responseType = 'arraybuffer';
7223         xhr.open('GET', src, true);
7224         xhr.onload = function() {
7225             actx.decodeAudioData(
7226                 xhr.response,
7227                 function(buffer) {
7228                     sound.buffer = buffer;
7229                     sound.dispatchEvent(new enchant.Event(enchant.Event.LOAD));
7230                 },
7231                 function(error) {
7232                     enchant.Core.instance.dispatchEvent(e);
7233                     sound.dispatchEvent(e);
7234                 }
7235             );
7236         };
7237         xhr.send(null);
7238     } else {
7239         setTimeout(function() {
7240             sound.dispatchEvent(e);
7241         }, 50);
7242     }
7243     return sound;
7244 };
7245
7246 if(window.AudioContext){
7247     enchant.WebAudioSound.audioContext = new window.AudioContext();
7248     enchant.WebAudioSound.destination = enchant.WebAudioSound.audioContext.destination;
7249 }
7250
7251 /* jshint newcap: false */
7252
7253 enchant.Sound = window.AudioContext && enchant.ENV.USE_WEBAUDIO ? enchant.WebAudioSound : enchant.DOMSound;
7254
7255 /**
7256  * ============================================================================================
7257  * Easing Equations v2.0
7258  * September 1, 2003
7259  * (c) 2003 Robert Penner, all rights reserved.
7260  * This work is subject to the terms in http://www.robertpenner.com/easing_terms_of_use.html.
7261  * ============================================================================================
7262  */
7263
7264 /**
7265  [lang:ja]
7266  * イージング関数ライブラリ
7267  * {@link enchant.Easing} 以下にある関数は全て t(現在の時刻), b(初期値), c(変化後の値), d(値の変化にかける時間) の引数を取り、指定した時刻に取る値を返す。
7268  * ActionScript で広く使われている Robert Penner による Easing Equations を JavaScript に移植した。
7269  *
7270  * @see http://www.robertpenner.com/easing/
7271  * @see http://www.robertpenner.com/easing/penner_chapter7_tweening.pdf
7272  *
7273  [/lang]
7274  [lang:en]
7275  [/lang]
7276  * Easing function library, from "Easing Equations" by Robert Penner.
7277  * @type {Object}
7278  * @namespace
7279  * {@link enchant.Tween} クラスで用いるイージング関数のライブラリ名前空間.
7280  */
7281 enchant.Easing = {
7282     /**
7283      * @param t
7284      * @param b
7285      * @param c
7286      * @param d
7287      * @return {Number}
7288      */
7289     LINEAR: function(t, b, c, d) {
7290         return c * t / d + b;
7291     },
7292     /**
7293      * @param t
7294      * @param b
7295      * @param c
7296      * @param d
7297      * @return {Number}
7298      */
7299     SWING: function(t, b, c, d) {
7300         return c * (0.5 - Math.cos(((t / d) * Math.PI)) / 2) + b;
7301     },
7302     // quad
7303     /**
7304      * @param t
7305      * @param b
7306      * @param c
7307      * @param d
7308      * @return {Number}
7309      */
7310     QUAD_EASEIN: function(t, b, c, d) {
7311         return c * (t /= d) * t + b;
7312     },
7313     /**
7314      * @param t
7315      * @param b
7316      * @param c
7317      * @param d
7318      * @return {Number}
7319      */
7320     QUAD_EASEOUT: function(t, b, c, d) {
7321         return -c * (t /= d) * (t - 2) + b;
7322     },
7323     /**
7324      * @param t
7325      * @param b
7326      * @param c
7327      * @param d
7328      * @return {Number}
7329      */
7330     QUAD_EASEINOUT: function(t, b, c, d) {
7331         if ((t /= d / 2) < 1) {
7332             return c / 2 * t * t + b;
7333         }
7334         return -c / 2 * ((--t) * (t - 2) - 1) + b;
7335     },
7336     // cubic
7337     /**
7338      * @param t
7339      * @param b
7340      * @param c
7341      * @param d
7342      * @return {Number}
7343      */
7344     CUBIC_EASEIN: function(t, b, c, d) {
7345         return c * (t /= d) * t * t + b;
7346     },
7347     /**
7348      * @param t
7349      * @param b
7350      * @param c
7351      * @param d
7352      * @return {Number}
7353      */
7354     CUBIC_EASEOUT: function(t, b, c, d) {
7355         return c * ((t = t / d - 1) * t * t + 1) + b;
7356     },
7357     /**
7358      * @param t
7359      * @param b
7360      * @param c
7361      * @param d
7362      * @return {Number}
7363      */
7364     CUBIC_EASEINOUT: function(t, b, c, d) {
7365         if ((t /= d / 2) < 1) {
7366             return c / 2 * t * t * t + b;
7367         }
7368         return c / 2 * ((t -= 2) * t * t + 2) + b;
7369     },
7370     // quart
7371     /**
7372      * @param t
7373      * @param b
7374      * @param c
7375      * @param d
7376      * @return {Number}
7377      */
7378     QUART_EASEIN: function(t, b, c, d) {
7379         return c * (t /= d) * t * t * t + b;
7380     },
7381     /**
7382      * @param t
7383      * @param b
7384      * @param c
7385      * @param d
7386      * @return {Number}
7387      */
7388     QUART_EASEOUT: function(t, b, c, d) {
7389         return -c * ((t = t / d - 1) * t * t * t - 1) + b;
7390     },
7391     /**
7392      * @param t
7393      * @param b
7394      * @param c
7395      * @param d
7396      * @return {Number}
7397      */
7398     QUART_EASEINOUT: function(t, b, c, d) {
7399         if ((t /= d / 2) < 1) {
7400             return c / 2 * t * t * t * t + b;
7401         }
7402         return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
7403     },
7404     // quint
7405     /**
7406      * @param t
7407      * @param b
7408      * @param c
7409      * @param d
7410      * @return {Number}
7411      */
7412     QUINT_EASEIN: function(t, b, c, d) {
7413         return c * (t /= d) * t * t * t * t + b;
7414     },
7415     /**
7416      * @param t
7417      * @param b
7418      * @param c
7419      * @param d
7420      * @return {Number}
7421      */
7422     QUINT_EASEOUT: function(t, b, c, d) {
7423         return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
7424     },
7425     /**
7426      * @param t
7427      * @param b
7428      * @param c
7429      * @param d
7430      * @return {Number}
7431      */
7432     QUINT_EASEINOUT: function(t, b, c, d) {
7433         if ((t /= d / 2) < 1) {
7434             return c / 2 * t * t * t * t * t + b;
7435         }
7436         return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;
7437     },
7438     //sin
7439     /**
7440      * @param t
7441      * @param b
7442      * @param c
7443      * @param d
7444      * @return {Number}
7445      */
7446     SIN_EASEIN: function(t, b, c, d) {
7447         return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;
7448     },
7449     /**
7450      * @param t
7451      * @param b
7452      * @param c
7453      * @param d
7454      * @return {Number}
7455      */
7456     SIN_EASEOUT: function(t, b, c, d) {
7457         return c * Math.sin(t / d * (Math.PI / 2)) + b;
7458     },
7459     /**
7460      * @param t
7461      * @param b
7462      * @param c
7463      * @param d
7464      * @return {Number}
7465      */
7466     SIN_EASEINOUT: function(t, b, c, d) {
7467         return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;
7468     },
7469     // circ
7470     /**
7471      * @param t
7472      * @param b
7473      * @param c
7474      * @param d
7475      * @return {Number}
7476      */
7477     CIRC_EASEIN: function(t, b, c, d) {
7478         return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;
7479     },
7480     /**
7481      * @param t
7482      * @param b
7483      * @param c
7484      * @param d
7485      * @return {Number}
7486      */
7487     CIRC_EASEOUT: function(t, b, c, d) {
7488         return c * Math.sqrt(1 - (t = t / d - 1) * t) + b;
7489     },
7490     /**
7491      * @param t
7492      * @param b
7493      * @param c
7494      * @param d
7495      * @return {Number}
7496      */
7497     CIRC_EASEINOUT: function(t, b, c, d) {
7498         if ((t /= d / 2) < 1) {
7499             return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b;
7500         }
7501         return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;
7502     },
7503     // elastic
7504     /**
7505      * @param t
7506      * @param b
7507      * @param c
7508      * @param d
7509      * @return {Number}
7510      */
7511     ELASTIC_EASEIN: function(t, b, c, d, a, p) {
7512         if (t === 0) {
7513             return b;
7514         }
7515         if ((t /= d) === 1) {
7516             return b + c;
7517         }
7518
7519         if (!p) {
7520             p = d * 0.3;
7521         }
7522
7523         var s;
7524         if (!a || a < Math.abs(c)) {
7525             a = c;
7526             s = p / 4;
7527         } else {
7528             s = p / (2 * Math.PI) * Math.asin(c / a);
7529         }
7530         return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
7531     },
7532     /**
7533      * @param t
7534      * @param b
7535      * @param c
7536      * @param d
7537      * @return {Number}
7538      */
7539     ELASTIC_EASEOUT: function(t, b, c, d, a, p) {
7540         if (t === 0) {
7541             return b;
7542         }
7543         if ((t /= d) === 1) {
7544             return b + c;
7545         }
7546         if (!p) {
7547             p = d * 0.3;
7548         }
7549         var s;
7550         if (!a || a < Math.abs(c)) {
7551             a = c;
7552             s = p / 4;
7553         } else {
7554             s = p / (2 * Math.PI) * Math.asin(c / a);
7555         }
7556         return (a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b);
7557     },
7558     /**
7559      * @param t
7560      * @param b
7561      * @param c
7562      * @param d
7563      * @return {Number}
7564      */
7565     ELASTIC_EASEINOUT: function(t, b, c, d, a, p) {
7566         if (t === 0) {
7567             return b;
7568         }
7569         if ((t /= d / 2) === 2) {
7570             return b + c;
7571         }
7572         if (!p) {
7573             p = d * (0.3 * 1.5);
7574         }
7575         var s;
7576         if (!a || a < Math.abs(c)) {
7577             a = c;
7578             s = p / 4;
7579         } else {
7580             s = p / (2 * Math.PI) * Math.asin(c / a);
7581         }
7582         if (t < 1) {
7583             return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
7584         }
7585         return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p) * 0.5 + c + b;
7586     },
7587     // bounce
7588     /**
7589      * @param t
7590      * @param b
7591      * @param c
7592      * @param d
7593      * @return {Number}
7594      */
7595     BOUNCE_EASEOUT: function(t, b, c, d) {
7596         if ((t /= d) < (1 / 2.75)) {
7597             return c * (7.5625 * t * t) + b;
7598         } else if (t < (2 / 2.75)) {
7599             return c * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75) + b;
7600         } else if (t < (2.5 / 2.75)) {
7601             return c * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375) + b;
7602         } else {
7603             return c * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375) + b;
7604         }
7605     },
7606     /**
7607      * @param t
7608      * @param b
7609      * @param c
7610      * @param d
7611      * @return {Number}
7612      */
7613     BOUNCE_EASEIN: function(t, b, c, d) {
7614         return c - enchant.Easing.BOUNCE_EASEOUT(d - t, 0, c, d) + b;
7615     },
7616     /**
7617      * @param t
7618      * @param b
7619      * @param c
7620      * @param d
7621      * @return {Number}
7622      */
7623     BOUNCE_EASEINOUT: function(t, b, c, d) {
7624         if (t < d / 2) {
7625             return enchant.Easing.BOUNCE_EASEIN(t * 2, 0, c, d) * 0.5 + b;
7626         } else {
7627             return enchant.Easing.BOUNCE_EASEOUT(t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b;
7628         }
7629
7630     },
7631     // back
7632     /**
7633      * @param t
7634      * @param b
7635      * @param c
7636      * @param d
7637      * @return {Number}
7638      */
7639     BACK_EASEIN: function(t, b, c, d, s) {
7640         if (s === undefined) {
7641             s = 1.70158;
7642         }
7643         return c * (t /= d) * t * ((s + 1) * t - s) + b;
7644     },
7645     /**
7646      * @param t
7647      * @param b
7648      * @param c
7649      * @param d
7650      * @return {Number}
7651      */
7652     BACK_EASEOUT: function(t, b, c, d, s) {
7653         if (s === undefined) {
7654             s = 1.70158;
7655         }
7656         return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
7657     },
7658     /**
7659      * @param t
7660      * @param b
7661      * @param c
7662      * @param d
7663      * @return {Number}
7664      */
7665     BACK_EASEINOUT: function(t, b, c, d, s) {
7666         if (s === undefined) {
7667             s = 1.70158;
7668         }
7669         if ((t /= d / 2) < 1) {
7670             return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
7671         }
7672         return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
7673     },
7674     // expo
7675     /**
7676      * @param t
7677      * @param b
7678      * @param c
7679      * @param d
7680      * @return {Number}
7681      */
7682     EXPO_EASEIN: function(t, b, c, d) {
7683         return (t === 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b;
7684     },
7685     /**
7686      * @param t
7687      * @param b
7688      * @param c
7689      * @param d
7690      * @return {Number}
7691      */
7692     EXPO_EASEOUT: function(t, b, c, d) {
7693         return (t === d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;
7694     },
7695     /**
7696      * @param t
7697      * @param b
7698      * @param c
7699      * @param d
7700      * @return {Number}
7701      */
7702     EXPO_EASEINOUT: function(t, b, c, d) {
7703         if (t === 0) {
7704             return b;
7705         }
7706         if (t === d) {
7707             return b + c;
7708         }
7709         if ((t /= d / 2) < 1) {
7710             return c / 2 * Math.pow(2, 10 * (t - 1)) + b;
7711         }
7712         return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;
7713     }
7714 };
7715
7716 /**
7717  * Easing Equations v2.0
7718  */
7719
7720 /**
7721  * @scope enchant.ActionEventTarget.prototype
7722  * @type {*}
7723  */
7724 enchant.ActionEventTarget = enchant.Class.create(enchant.EventTarget, {
7725     /**
7726      * @name enchant.ActionEventTarget
7727      * @class
7728      [lang:ja]
7729      * {@link enchant.Action} クラス向けに拡張された {@link enchant.EventTarget} クラス .
7730      *
7731      [/lang]
7732      [lang:en]
7733      * EventTarget which can change the context of event listeners
7734      [/lang]
7735      * @constructs
7736      * @extends enchant.EventTarget
7737      */
7738     initialize: function() {
7739         enchant.EventTarget.apply(this, arguments);
7740     },
7741     /**
7742      * Issue event.
7743      * @param {enchant.Event} e Event issued.
7744      */
7745     dispatchEvent: function(e) {
7746         var target;
7747         if (this.node) {
7748             target = this.node;
7749             e.target = target;
7750             e.localX = e.x - target._offsetX;
7751             e.localY = e.y - target._offsetY;
7752         } else {
7753             this.node = null;
7754         }
7755
7756         if (this['on' + e.type] != null) {
7757             this['on' + e.type].call(target, e);
7758         }
7759         var listeners = this._listeners[e.type];
7760         if (listeners != null) {
7761             listeners = listeners.slice();
7762             for (var i = 0, len = listeners.length; i < len; i++) {
7763                 listeners[i].call(target, e);
7764             }
7765         }
7766     }
7767 });
7768
7769 /**
7770  * @scope enchant.Timeline.prototype
7771  */
7772 enchant.Timeline = enchant.Class.create(enchant.EventTarget, {
7773     /**
7774      * @name enchant.Timeline
7775      * @class
7776      [lang:ja]
7777      * アニメーションを管理するためのクラス.
7778      *
7779      * 操作するノードひとつに対して、必ずひとつのタイムラインが対応する。
7780      * tl.enchant.js を読み込むと、Node クラスを継承したすべてのクラス (Group, Scene, Entity, Label, Sprite)の
7781      *
7782      * tl プロパティに、タイムラインクラスのインスタンスが生成される。
7783      * タイムラインクラスは、自身に様々なアクションを追加するメソッドを持っており、
7784      * これらを使うことで簡潔にアニメーションや様々な操作をすることができる。
7785      * タイムラインクラスはフレームとタイムのアニメーションができる。
7786      * @param node 操作の対象となるノード
7787      * @param [unitialized] このパラメータがtrueならば、最初のaddメソッドが呼ばれる時nodeにenchant.Event.ENTER_FRAMEイベントリスナを追加される。
7788      [/lang]
7789      [lang:en]
7790      * Time-line class.
7791      * Class for managing the action.
7792      * For one node to manipulate the timeline of one must correspond.
7793      *
7794           * Reading a tl.enchant.js, all classes (Group, Scene, Entity, Label, Sprite) of the Node class that inherits
7795           * Tlthe property, an instance of the Timeline class is generated.
7796           * Time-line class has a method to add a variety of actions to himself,
7797           * entities can be animated and various operations by using these briefly.
7798           * You can choose time based and frame based(default) animation.
7799      *
7800      * @param node target node
7801      * @param [unitialized] if this param is true, when add method called in the first time,
7802      * enchant.Event.ENTER_FRAME event listener will be added to node (for reducing unused event listeners)
7803      [/lang]
7804      * @constructs
7805      */
7806     initialize: function(node) {
7807         enchant.EventTarget.call(this);
7808         this.node = node;
7809         this.queue = [];
7810         this.paused = false;
7811         this.looped = false;
7812         this.isFrameBased = true;
7813         this._parallel = null;
7814         this._activated = false;
7815         this.addEventListener(enchant.Event.ENTER_FRAME, this.tick);
7816     },
7817     /**
7818      * @private
7819      */
7820     _deactivateTimeline: function() {
7821         if (this._activated) {
7822             this._activated = false;
7823             this.node.removeEventListener('enterframe', this._nodeEventListener);
7824         }
7825     },
7826     /**
7827      * @private
7828      */
7829     _activateTimeline: function() {
7830         if (!this._activated && !this.paused) {
7831             this.node.addEventListener("enterframe", this._nodeEventListener);
7832             this._activated = true;
7833         }
7834     },
7835     /**
7836      [lang:ja]
7837      * 一つのenchant.Event.ENTER_FRAMEイベントはアニメーションに一つの時間単位になる。 (デフォルト)
7838      [/lang]
7839      */
7840     setFrameBased: function() {
7841         this.isFrameBased = true;
7842     },
7843     /**
7844      [lang:ja]
7845      * 一つのenchant.Event.ENTER_FRAMEイベントはアニメーションに前のフレームから経過した時間になる。
7846      [/lang]
7847      */
7848     setTimeBased: function() {
7849         this.isFrameBased = false;
7850     },
7851     /**
7852      [lang:ja]
7853      * キューの先頭にあるアクションを終了し、次のアクションへ移行する。
7854      * アクションの中から呼び出されるが、外から呼び出すこともできる。
7855      *
7856      * アクション実行中に、アクションが終了した場合、
7857      * もう一度 tick() 関数が呼ばれるため、1フレームに複数のアクションが処理される場合もある。
7858      * ex.
7859      *   sprite.tl.then(function A(){ .. }).then(function B(){ .. });
7860      * と記述した場合、最初のフレームで A・B の関数どちらも実行される
7861      [/lang]
7862      [lang:en]
7863      [/lang]
7864      */
7865     next: function(remainingTime) {
7866         var e, action = this.queue.shift();
7867         e = new enchant.Event("actionend");
7868         e.timeline = this;
7869         action.dispatchEvent(e);
7870
7871         if (this.queue.length === 0) {
7872             this._activated = false;
7873             this.node.removeEventListener('enterframe', this._nodeEventListener);
7874             return;
7875         }
7876
7877         if (this.looped) {
7878             e = new enchant.Event("removedfromtimeline");
7879             e.timeline = this;
7880             action.dispatchEvent(e);
7881             action.frame = 0;
7882
7883             this.add(action);
7884         } else {
7885             // remove after dispatching removedfromtimeline event
7886             e = new enchant.Event("removedfromtimeline");
7887             e.timeline = this;
7888             action.dispatchEvent(e);
7889         }
7890         if (remainingTime > 0 || (this.queue[0] && this.queue[0].time === 0)) {
7891             var event = new enchant.Event("enterframe");
7892             event.elapsed = remainingTime;
7893             this.dispatchEvent(event);
7894         }
7895     },
7896     /**
7897      [lang:ja]
7898      * ターゲットの enterframe イベントのリスナとして登録される関数
7899      * 1フレーム経過する際に実行する処理が書かれている。
7900      * (キューの先頭にあるアクションに対して、actionstart/actiontickイベントを発行する)
7901      [/lang]
7902      */
7903     tick: function(enterFrameEvent) {
7904         if (this.paused) {
7905             return;
7906         }
7907         if (this.queue.length > 0) {
7908             var action = this.queue[0];
7909             if (action.frame === 0) {
7910                 var f;
7911                 f = new enchant.Event("actionstart");
7912                 f.timeline = this;
7913                 action.dispatchEvent(f);
7914             }
7915
7916             var e = new enchant.Event("actiontick");
7917             e.timeline = this;
7918             if (this.isFrameBased) {
7919                 e.elapsed = 1;
7920             } else {
7921                 e.elapsed = enterFrameEvent.elapsed;
7922             }
7923             action.dispatchEvent(e);
7924         }
7925     },
7926     add: function(action) {
7927         if (!this._activated) {
7928             var tl = this;
7929             this._nodeEventListener = function(e) {
7930                 tl.dispatchEvent(e);
7931             };
7932             this.node.addEventListener("enterframe", this._nodeEventListener);
7933
7934             this._activated = true;
7935         }
7936         if (this._parallel) {
7937             this._parallel.actions.push(action);
7938             this._parallel = null;
7939         } else {
7940             this.queue.push(action);
7941         }
7942         action.frame = 0;
7943
7944         var e = new enchant.Event("addedtotimeline");
7945         e.timeline = this;
7946         action.dispatchEvent(e);
7947
7948         e = new enchant.Event("actionadded");
7949         e.action = action;
7950         this.dispatchEvent(e);
7951
7952         return this;
7953     },
7954     /**
7955      [lang:ja]
7956      * アクションを簡単に追加するためのメソッド。
7957      * 実体は add メソッドのラッパ。
7958      * @param params アクションの設定オブジェクト
7959      [/lang]
7960      */
7961     action: function(params) {
7962         return this.add(new enchant.Action(params));
7963     },
7964     /**
7965      [lang:ja]
7966      * トゥイーンを簡単に追加するためのメソッド。
7967      * 実体は add メソッドのラッパ。
7968      * @param params トゥイーンの設定オブジェクト。
7969      [/lang]
7970      */
7971     tween: function(params) {
7972         return this.add(new enchant.Tween(params));
7973     },
7974     /**
7975      [lang:ja]
7976      * タイムラインのキューをすべて破棄する。終了イベントは発行されない。
7977      [/lang]
7978      */
7979     clear: function() {
7980         var e = new enchant.Event("removedfromtimeline");
7981         e.timeline = this;
7982
7983         for (var i = 0, len = this.queue.length; i < len; i++) {
7984             this.queue[i].dispatchEvent(e);
7985         }
7986         this.queue = [];
7987         this._deactivateTimeline();
7988         return this;
7989     },
7990     /**
7991      [lang:ja]
7992      * タイムラインを早送りする。
7993      * 指定したフレーム数が経過したのと同様の処理を、瞬時に実行する。
7994      * 巻き戻しはできない。
7995      * @param frames
7996      [/lang]
7997      */
7998     skip: function(frames) {
7999         var event = new enchant.Event("enterframe");
8000         if (this.isFrameBased) {
8001             event.elapsed = 1;
8002         } else {
8003             event.elapsed = frames;
8004             frames = 1;
8005         }
8006         while (frames--) {
8007             this.dispatchEvent(event);
8008         }
8009         return this;
8010     },
8011     /**
8012      [lang:ja]
8013      * タイムラインの実行を一時停止する
8014      [/lang]
8015      */
8016     pause: function() {
8017         if (!this.paused) {
8018             this.paused = true;
8019             this._deactivateTimeline();
8020         }
8021         return this;
8022     },
8023     /**
8024      [lang:ja]
8025      * タイムラインの実行を再開する
8026      [/lang]
8027      */
8028     resume: function() {
8029         if (this.paused) {
8030             this.paused = false;
8031             this._activateTimeline();
8032         }
8033         return this;
8034     },
8035     /**
8036      [lang:ja]
8037      * タイムラインをループさせる。
8038      * ループしているときに終了したアクションは、タイムラインから取り除かれた後
8039      * 再度タイムラインに追加される。このアクションは、ループが解除されても残る。
8040      [/lang]
8041      */
8042     loop: function() {
8043         this.looped = true;
8044         return this;
8045     },
8046     /**
8047      [lang:ja]
8048      * タイムラインのループを解除する。
8049      [/lang]
8050      */
8051     unloop: function() {
8052         this.looped = false;
8053         return this;
8054     },
8055     /**
8056      [lang:ja]
8057      * 指定したフレーム数だけ待ち、何もしないアクションを追加する。
8058      * @param time
8059      [/lang]
8060      */
8061     delay: function(time) {
8062         this.add(new enchant.Action({
8063             time: time
8064         }));
8065         return this;
8066     },
8067     /**
8068      [lang:ja]
8069      * @ignore
8070      * @param time
8071      [/lang]
8072      */
8073     wait: function(time) {
8074         // reserved
8075         return this;
8076     },
8077     /**
8078      [lang:ja]
8079      * 関数を実行し、即時に次のアクションに移るアクションを追加する。
8080      * @param func
8081      [/lang]
8082      */
8083     then: function(func) {
8084         var timeline = this;
8085         this.add(new enchant.Action({
8086             onactiontick: function(evt) {
8087                 func.call(timeline.node);
8088             },
8089             // if time is 0, next action will be immediately executed
8090             time: 0
8091         }));
8092         return this;
8093     },
8094     /**
8095      [lang:ja]
8096      * then メソッドのシノニム。
8097      * 関数を実行し、即時に次のアクションに移る。
8098      * @param func
8099      [/lang]
8100      */
8101     exec: function(func) {
8102         this.then(func);
8103     },
8104     /**
8105      [lang:ja]
8106      * 実行したい関数を、フレーム数をキーとした連想配列(オブジェクト)で複数指定し追加する。
8107      * 内部的には delay, then を用いている。
8108      *
8109      * @example
8110      * sprite.tl.cue({
8111      *    10: function(){ 10フレーム経過した後に実行される関数 },
8112      *    20: function(){ 20フレーム経過した後に実行される関数 },
8113      *    30: function(){ 30フレーム経過した後に実行される関数 }
8114      * });
8115      * @param cue キューオブジェクト
8116      [/lang]
8117      */
8118     cue: function(cue) {
8119         var ptr = 0;
8120         for (var frame in cue) {
8121             if (cue.hasOwnProperty(frame)) {
8122                 this.delay(frame - ptr);
8123                 this.then(cue[frame]);
8124                 ptr = frame;
8125             }
8126         }
8127     },
8128     /**
8129      [lang:ja]
8130      * ある関数を指定したフレーム数繰り返し実行するアクションを追加する。
8131      * @param func 実行したい関数
8132      * @param time 持続フレーム数
8133      [/lang]
8134      */
8135     repeat: function(func, time) {
8136         this.add(new enchant.Action({
8137             onactiontick: function(evt) {
8138                 func.call(this);
8139             },
8140             time: time
8141         }));
8142         return this;
8143     },
8144     /**
8145      [lang:ja]
8146      * 複数のアクションを並列で実行したいときに指定する。
8147      * and で結ばれたすべてのアクションが終了するまで次のアクションには移行しない
8148      * @example
8149      * sprite.tl.fadeIn(30).and.rotateBy(360, 30);
8150      * 30フレームでフェードインしながら 360度回転する
8151      [/lang]
8152      */
8153     and: function() {
8154         var last = this.queue.pop();
8155         if (last instanceof enchant.ParallelAction) {
8156             this._parallel = last;
8157             this.queue.push(last);
8158         } else {
8159             var parallel = new enchant.ParallelAction();
8160             parallel.actions.push(last);
8161             this.queue.push(parallel);
8162             this._parallel = parallel;
8163         }
8164         return this;
8165     },
8166     /**
8167      * @ignore
8168      */
8169     or: function() {
8170         return this;
8171     },
8172     /**
8173      * @ignore
8174      */
8175     doAll: function(children) {
8176         return this;
8177     },
8178     /**
8179      * @ignore
8180      */
8181     waitAll: function() {
8182         return this;
8183     },
8184     /**
8185      [lang:ja]
8186      * true値 が返るまで、関数を毎フレーム実行するアクションを追加する。
8187      * @example
8188      * sprite.tl.waitUntil(function(){
8189      *    return this.x-- < 0
8190      * }).then(function(){ .. });
8191      * // x 座標が負になるまで毎フレーム x座標を減算し続ける
8192      *
8193      * @param func 実行したい関数
8194      [/lang]
8195      */
8196     waitUntil: function(func) {
8197         var timeline = this;
8198         this.add(new enchant.Action({
8199             onactionstart: func,
8200             onactiontick: function(evt) {
8201                 if (func.call(this)) {
8202                     timeline.next();
8203                 }
8204             }
8205         }));
8206         return this;
8207     },
8208     /**
8209      [lang:ja]
8210      * Entity の不透明度をなめらかに変えるアクションを追加する。
8211      * @param opacity 目標の不透明度
8212      * @param time フレーム数
8213      * @param [easing] イージング関数
8214      [/lang]
8215      */
8216     fadeTo: function(opacity, time, easing) {
8217         this.tween({
8218             opacity: opacity,
8219             time: time,
8220             easing: easing
8221         });
8222         return this;
8223     },
8224     /**
8225      [lang:ja]
8226      * Entity をフェードインするアクションを追加する。
8227      * fadeTo(1) のエイリアス。
8228      * @param time フレーム数
8229      * @param [easing] イージング関数
8230      [/lang]
8231      */
8232     fadeIn: function(time, easing) {
8233         return this.fadeTo(1, time, easing);
8234     },
8235     /**
8236      [lang:ja]
8237      * Entity をフェードアウトするアクションを追加する。
8238      * fadeTo(1) のエイリアス。
8239      * @param time フレーム数
8240      * @param [easing] イージング関数
8241      [/lang]
8242      */
8243     fadeOut: function(time, easing) {
8244         return this.fadeTo(0, time, easing);
8245     },
8246     /**
8247      [lang:ja]
8248      * Entity の位置をなめらかに移動させるアクションを追加する。
8249      * @param x 目標のx座標
8250      * @param y 目標のy座標
8251      * @param time フレーム数
8252      * @param [easing] イージング関数
8253      [/lang]
8254      */
8255     moveTo: function(x, y, time, easing) {
8256         return this.tween({
8257             x: x,
8258             y: y,
8259             time: time,
8260             easing: easing
8261         });
8262     },
8263     /**
8264      [lang:ja]
8265      * Entity のx座標をなめらかに変化させるアクションを追加する。
8266      * @param x
8267      * @param time
8268      * @param [easing]
8269      [/lang]
8270      */
8271     moveX: function(x, time, easing) {
8272         return this.tween({
8273             x: x,
8274             time: time,
8275             easing: easing
8276         });
8277     },
8278     /**
8279      [lang:ja]
8280      * Entity のy座標をなめらかに変化させるアクションを追加する。
8281      * @param y
8282      * @param time
8283      * @param [easing]
8284      [/lang]
8285      */
8286     moveY: function(y, time, easing) {
8287         return this.tween({
8288             y: y,
8289             time: time,
8290             easing: easing
8291         });
8292     },
8293     /**
8294      [lang:ja]
8295      * Entity の位置をなめらかに変化させるアクションを追加する。
8296      * 座標は、アクション開始時からの相対座標で指定する。
8297      * @param x
8298      * @param y
8299      * @param time
8300      * @param [easing]
8301      [/lang]
8302      */
8303     moveBy: function(x, y, time, easing) {
8304         return this.tween({
8305             x: function() {
8306                 return this.x + x;
8307             },
8308             y: function() {
8309                 return this.y + y;
8310             },
8311             time: time,
8312             easing: easing
8313         });
8314     },
8315     /**
8316      [lang:ja]
8317      * Entity の opacity を0にする (即時)
8318      [/lang]
8319      */
8320     hide: function() {
8321         return this.then(function() {
8322             this.opacity = 0;
8323         });
8324     },
8325     /**
8326      [lang:ja]
8327      * Entity の opacity を1にする (即時)
8328      [/lang]
8329      */
8330     show: function() {
8331         return this.then(function() {
8332             this.opacity = 1;
8333         });
8334     },
8335     /**
8336      [lang:ja]
8337      * Entity をシーンから削除する。
8338      * シーンから削除された場合、 enterframe イベントは呼ばれなくなるので、
8339      * タイムラインも止まることに注意。
8340      * これ以降のアクションは、再度シーンに追加されるまで実行されない。
8341      [/lang]
8342      */
8343     removeFromScene: function() {
8344         return this.then(function() {
8345             this.scene.removeChild(this);
8346         });
8347     },
8348     /**
8349      [lang:ja]
8350      * Entity をなめらかに拡大・縮小するアクションを追加する。
8351      * @param scaleX 縮尺
8352      * @param [scaleY] 縮尺。省略した場合 scaleX と同じ
8353      * @param time
8354      * @param [easing]
8355      [/lang]
8356      */
8357     scaleTo: function(scale, time, easing) {
8358         if (typeof easing === "number") {
8359             return this.tween({
8360                 scaleX: arguments[0],
8361                 scaleY: arguments[1],
8362                 time: arguments[2],
8363                 easing: arguments[3]
8364             });
8365         }
8366         return this.tween({
8367             scaleX: scale,
8368             scaleY: scale,
8369             time: time,
8370             easing: easing
8371         });
8372     },
8373     /**
8374      [lang:ja]
8375      * Entity をなめらかに拡大・縮小させるアクションを追加する。
8376      * 相対縮尺 (ex. アクション開始時の縮尺の n 倍) で指定する。
8377      * @param scaleX 相対縮尺
8378      * @param [scaleY] 相対縮尺。省略した場合 scaleX と同じ
8379      * @param time
8380      * @param [easing]
8381      [/lang]
8382      */
8383     scaleBy: function(scale, time, easing) {
8384         if (typeof easing === "number") {
8385             return this.tween({
8386                 scaleX: function() {
8387                     return this.scaleX * arguments[0];
8388                 },
8389                 scaleY: function() {
8390                     return this.scaleY * arguments[1];
8391                 },
8392                 time: arguments[2],
8393                 easing: arguments[3]
8394             });
8395         }
8396         return this.tween({
8397             scaleX: function() {
8398                 return this.scaleX * scale;
8399             },
8400             scaleY: function() {
8401                 return this.scaleY * scale;
8402             },
8403             time: time,
8404             easing: easing
8405         });
8406     },
8407     /**
8408      [lang:ja]
8409      * Entity をなめらかに回転させるアクションを追加する。
8410      * @param deg 目標の回転角度 (弧度法: 1回転を 360 とする)
8411      * @param time フレーム数
8412      * @param [easing] イージング関数
8413      [/lang]
8414      */
8415     rotateTo: function(deg, time, easing) {
8416         return this.tween({
8417             rotation: deg,
8418             time: time,
8419             easing: easing
8420         });
8421     },
8422     /**
8423      [lang:ja]
8424      * Entity をなめらかに回転させるアクションを追加する。
8425      * 角度は相対角度 (アクション開始時の角度から更に n 度) で指定する
8426      * @param deg 目標の相対角度 (弧度法: 1回転を 360 とする)
8427      * @param time フレーム数
8428      * @param [easing] イージング関数
8429      [/lang]
8430      */
8431     rotateBy: function(deg, time, easing) {
8432         return this.tween({
8433             rotation: function() {
8434                 return this.rotation + deg;
8435             },
8436             time: time,
8437             easing: easing
8438         });
8439     }
8440 });
8441
8442 /**
8443  * @scope enchant.Action.prototype
8444  * @type {*}
8445  */
8446
8447 enchant.Action = enchant.Class.create(enchant.ActionEventTarget, {
8448     /**
8449      * @name enchant.Action
8450      * @class
8451      [lang:ja]
8452      * アニメーションタイムラインを構成する、実行したい処理を指定するためのクラス.
8453      *
8454      * タイムラインに追加されたアクションは順に実行される。
8455      * アクションが開始・終了された時に actionstart, actionend イベントが発行され、
8456      * また1フレーム経過した時には actiontick イベントが発行される。
8457      * これらのイベントのリスナとして実行したい処理を指定する。
8458      *
8459      * time で指定されたフレーム数が経過すると自動的に次のアクションに移行するが、
8460      * null が指定されると、タイムラインの next メソッドが呼ばれるまで移行しない。
8461      * @constructs
8462      * @param param
8463      * @config {integer} [time] アクションが持続するフレーム数。 null が指定されると無限長
8464      * @config {function} [onactionstart] アクションが開始される時のイベントリスナ
8465      * @config {function} [onactiontick] アクションが1フレーム経過するときのイベントリスナ
8466      * @config {function} [onactionend] アクションがが終了する時のイベントリスナ
8467      [/lang]
8468      [lang:en]
8469      * Action class.
8470      * Actions are units that make up the time line,
8471      * It is a unit used to specify the action you want to perform.
8472      * Action has been added to the time line is performed in order.
8473      *
8474      * Actionstart, actiontick event is fired when the action is started and stopped,
8475      * When one frame has elapsed actiontick event is also issued.
8476      * Specify the action you want to perform as a listener for these events.
8477      * The transition to the next action automatically the number of frames that are specified in the time has elapsed.
8478      *
8479      * @constructs
8480      * @param param
8481      * @config {integer} [time] The number of frames that will last action. infinite length is specified null
8482      * @config {function} [onactionstart] Event listener for when the action is initiated
8483      * @config {function} [onactiontick] Event listener for when the action has passed one frame
8484      * @config {function} [onactionend] Event listener for when the action is finished
8485      [/lang]
8486      * @constructs
8487      */
8488     initialize: function(param) {
8489         enchant.ActionEventTarget.call(this);
8490         this.time = null;
8491         this.frame = 0;
8492         for (var key in param) {
8493             if (param.hasOwnProperty(key)) {
8494                 if (param[key] != null) {
8495                     this[key] = param[key];
8496                 }
8497             }
8498         }
8499         var action = this;
8500
8501         this.timeline = null;
8502         this.node = null;
8503
8504         this.addEventListener(enchant.Event.ADDED_TO_TIMELINE, function(evt) {
8505             action.timeline = evt.timeline;
8506             action.node = evt.timeline.node;
8507             action.frame = 0;
8508         });
8509
8510         this.addEventListener(enchant.Event.REMOVED_FROM_TIMELINE, function() {
8511             action.timeline = null;
8512             action.node = null;
8513             action.frame = 0;
8514         });
8515
8516         this.addEventListener(enchant.Event.ACTION_TICK, function(evt) {
8517             var remaining = action.time - (action.frame + evt.elapsed);
8518             if (action.time != null && remaining <= 0) {
8519                 action.frame = action.time;
8520                 evt.timeline.next(-remaining);
8521             } else {
8522                 action.frame += evt.elapsed;
8523             }
8524         });
8525
8526     }
8527 });
8528
8529 /**
8530  * @scope enchant.ParallelAction.prototype
8531  */
8532 enchant.ParallelAction = enchant.Class.create(enchant.Action, {
8533     /**
8534      * @name enchant.ParallelAction
8535      * @class
8536      [lang:ja]
8537      * アクションを並列で実行するためのアクション。
8538      * 子アクションを複数持つことができる。
8539      [/lang]
8540      * @constructs
8541      * @extends enchant.Action
8542      */
8543     initialize: function(param) {
8544         enchant.Action.call(this, param);
8545         var timeline = this.timeline;
8546         var node = this.node;
8547         /**
8548          [lang:ja]
8549          * 子アクション
8550          [/lang]
8551          [lang:en]
8552          * Children Actions
8553          [/lang]
8554          */
8555         this.actions = [];
8556         /**
8557          [lang:ja]
8558          * 実行が終了したアクション
8559          [/lang]
8560          [lang:en]
8561          * Removed actions
8562          [/lang]
8563          */
8564         this.endedActions = [];
8565         var that = this;
8566
8567         this.addEventListener(enchant.Event.ACTION_START, function(evt) {
8568             for (var i = 0, len = that.actions.length; i < len; i++) {
8569                 that.actions[i].dispatchEvent(evt);
8570             }
8571         });
8572
8573         this.addEventListener(enchant.Event.ACTION_TICK, function(evt) {
8574             var i, len, timeline = {
8575                 next: function(remaining) {
8576                     var action = that.actions[i];
8577                     that.actions.splice(i--, 1);
8578                     len = that.actions.length;
8579                     that.endedActions.push(action);
8580
8581                     var e = new enchant.Event("actionend");
8582                     e.timeline = this;
8583                     action.dispatchEvent(e);
8584
8585                     e = new enchant.Event("removedfromtimeline");
8586                     e.timeline = this;
8587                     action.dispatchEvent(e);
8588                 }
8589             };
8590
8591             var e = new enchant.Event("actiontick");
8592             e.timeline = timeline;
8593             e.elapsed = evt.elapsed;
8594             for (i = 0, len = that.actions.length; i < len; i++) {
8595                 that.actions[i].dispatchEvent(e);
8596             }
8597
8598             if (that.actions.length === 0) {
8599                 evt.timeline.next();
8600             }
8601         });
8602
8603         this.addEventListener(enchant.Event.ADDED_TO_TIMELINE, function(evt) {
8604             for (var i = 0, len = that.actions.length; i < len; i++) {
8605                 that.actions[i].dispatchEvent(evt);
8606             }
8607         });
8608
8609         this.addEventListener(enchant.Event.REMOVED_FROM_TIMELINE, function() {
8610             this.actions = this.endedActions;
8611             this.endedActions = [];
8612         });
8613
8614     }
8615 });
8616
8617 /**
8618  * @scope enchant.Tween.prototype
8619  */
8620 enchant.Tween = enchant.Class.create(enchant.Action, {
8621     /**
8622      * @name enchant.Tween
8623      * @class
8624      [lang:ja]
8625      * {@link enchant.Action} を継承した、オブジェクトの特定のプロパティを、なめらかに変更したい時に用いるためのアクションクラス.
8626      * アクションを扱いやすく拡張したクラス.
8627      *
8628      * コンストラクタに渡す設定オブジェクトに、プロパティの目標値を指定すると、
8629      * アクションが実行された時に、目標値までなめらかに値を変更するようなアクションを生成する。
8630      *
8631      * トゥイーンのイージングも、easing プロパティで指定できる。
8632      * デフォルトでは enchant.Easing.LINEAR が指定されている。
8633      *
8634      * @param params
8635      * @constructs
8636      * @config {time}
8637      * @config {easing} [function]
8638      [/lang]
8639      */
8640     initialize: function(params) {
8641         var origin = {};
8642         var target = {};
8643         enchant.Action.call(this, params);
8644
8645         if (this.easing == null) {
8646             // linear
8647             this.easing = function(t, b, c, d) {
8648                 return c * t / d + b;
8649             };
8650         }
8651
8652         var tween = this;
8653         this.addEventListener(enchant.Event.ACTION_START, function() {
8654             // excepted property
8655             var excepted = ["frame", "time", "callback", "onactiontick", "onactionstart", "onactionend"];
8656             for (var prop in params) {
8657                 if (params.hasOwnProperty(prop)) {
8658                     // if function is used instead of numerical value, evaluate it
8659                     var target_val;
8660                     if (typeof params[prop] === "function") {
8661                         target_val = params[prop].call(tween.node);
8662                     } else {
8663                         target_val = params[prop];
8664                     }
8665
8666                     if (excepted.indexOf(prop) === -1) {
8667                         origin[prop] = tween.node[prop];
8668                         target[prop] = target_val;
8669                     }
8670                 }
8671             }
8672         });
8673
8674         this.addEventListener(enchant.Event.ACTION_TICK, function(evt) {
8675             // if time is 0, set property to target value immediately
8676             var ratio = tween.time === 0 ? 1 : tween.easing(Math.min(tween.time,tween.frame + evt.elapsed), 0, 1, tween.time) - tween.easing(tween.frame, 0, 1, tween.time);
8677
8678             for (var prop in target){
8679                 if (target.hasOwnProperty(prop)) {
8680                     if (typeof this[prop] === "undefined"){
8681                         continue;
8682                     }
8683                     tween.node[prop] += (target[prop] - origin[prop]) * ratio;
8684                     if (Math.abs(tween.node[prop]) < 10e-8){
8685                         tween.node[prop] = 0;
8686                     }
8687                 }
8688             }
8689         });
8690     }
8691 });
8692
8693 /**
8694  *
8695  */
8696 }(window));