5 * Copyright Ubiquitous Entertainment Inc.
6 * Released under the MIT license.
9 (function(window, undefined){
12 * ECMA-262 5th edition Functions
14 if (typeof Object.defineProperty !== 'function') {
15 Object.defineProperty = function(obj, prop, desc) {
16 if ('value' in desc) {
17 obj[prop] = desc.value;
20 obj.__defineGetter__(prop, desc.get);
23 obj.__defineSetter__(prop, desc.set);
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]);
38 if (typeof Object.create !== 'function') {
39 Object.create = function(prototype, descs) {
43 F.prototype = prototype;
46 Object.defineProperties(obj, descs);
51 if (typeof Object.getPrototypeOf !== 'function') {
52 Object.getPrototypeOf = function(obj) {
57 if (typeof Function.prototype.bind !== 'function') {
58 Function.prototype.bind = function(thisObject) {
60 var args = Array.prototype.slice.call(arguments, 1);
61 var Nop = function() {
63 var bound = function() {
64 var a = args.concat(Array.prototype.slice.call(arguments));
66 this instanceof Nop ? this : thisObject || window, a);
68 Nop.prototype = func.prototype;
69 bound.prototype = new Nop();
74 window.getTime = (function() {
76 if (window.performance && window.performance.now) {
79 return origin + window.performance.now();
81 } else if (window.performance && window.performance.webkitNow) {
84 return origin + window.performance.webkitNow();
92 * define requestAnimationFrame
94 window.requestAnimationFrame =
95 window.requestAnimationFrame ||
96 window.mozRequestAnimationFrame ||
97 window.webkitRequestAnimationFrame ||
98 window.msRequestAnimationFrame ||
100 var lastTime = window.getTime();
101 var frame = 1000 / 60;
102 return function(func) {
103 var _id = setTimeout(function() {
104 lastTime = window.getTime();
106 }, Math.max(0, lastTime + frame - window.getTime()));
113 * グローバルにライブラリのクラスをエクスポートする.
115 * 引数に何も渡さない場合enchant.jsで定義されたクラス及びプラグインで定義されたクラス
116 * 全てがエクスポートされる. 引数が一つ以上の場合はenchant.jsで定義されたクラスのみ
117 * がデフォルトでエクスポートされ, プラグインのクラスをエクスポートしたい場合は明示的に
118 * プラグインの識別子を引数として渡す必要がある.
121 * enchant(); // 全てのクラスがエクスポートされる
122 * enchant(''); // enchant.js本体のクラスのみがエクスポートされる
123 * enchant('ui'); // enchant.js本体のクラスとui.enchant.jsのクラスがエクスポートされる
125 * @param {...String} [modules] エクスポートするモジュール. 複数指定できる.
128 * Export the library classes globally.
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.
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.
140 * @param {...String} [modules] Export module. Multiple designations possible.
143 * Globaler Export der Programmbibliotheken.
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.
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.
155 * @param {...String} [modules] Module die exportiert werden sollen.
161 var enchant = function(modules) {
162 if (modules != null) {
163 if (!(modules instanceof Array)) {
164 modules = Array.prototype.slice.call(arguments);
166 modules = modules.filter(function(module) {
167 return [module].join();
170 (function include(module, prefix) {
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);
181 i = modules.indexOf(prefix + prop);
183 submodules.push(prop);
184 modules.splice(i, 1);
191 for (i = 0, len = submodules.length; i < len; i++) {
192 include(module[submodules[i]], prefix + submodules[i] + '.');
197 if (enchant.Class.getInheritanceTree(window.Game).length <= enchant.Class.getInheritanceTree(window.Core).length) {
198 window.Game = window.Core;
201 if (modules != null && modules.length) {
202 throw new Error('Cannot load module: ' + modules.join(', '));
209 window.enchant = enchant;
211 window.addEventListener("message", function(msg, origin) {
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) {
219 enchant.Core.instance.start();
222 enchant.Core.instance.pause();
225 enchant.Core.instance.resume();
228 enchant.Core.instance._tick();
240 * @name enchant.Class
245 * @param {Function} [superclass] 継承するクラス.
246 * @param {*} definition クラス定義.
249 * A Class representing a class which supports inheritance.
251 * @param {Function} [superclass] The class from which the
252 * new class will inherit the class definition.
253 * @param {*} definition Class definition.
256 * Eine Klasse für Klassen, die Vererbung unterstützen.
258 * @param {Function} [superclass] Die Klasse, deren Klassendefinition
259 * die neue Klasse erben wird.
260 * @param {*} definition Klassendefinition.
264 enchant.Class = function(superclass, definition) {
265 return enchant.Class.create(superclass, definition);
272 * ほかのクラスを継承したクラスを作成する場合, コンストラクタはデフォルトで
273 * 継承元のクラスのものが使われる. コンストラクタをオーバーライドする場合継承元の
274 * コンストラクタを適用するには明示的に呼び出す必要がある.
277 * var Ball = Class.create({ // 何も継承しないクラスを作成する
278 * initialize: function(radius) { ... }, // メソッド定義
279 * fall: function() { ... }
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'];
290 * @param {Function} [superclass] 継承するクラス.
291 * @param {*} [definition] クラス定義.
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.
301 * var Ball = Class.create({ // Creates independent class.
302 * initialize: function(radius) { ... }, // Method definition.
303 * fall: function() { ... }
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'];
314 * @param {Function} [superclass] The class from which the
315 * new class will inherit the class definition.
316 * @param {*} [definition] Class definition.
319 * Erstellt eine neue Klasse
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.
327 * var Ball = Class.create({ // definiert eine unabhängige Klasse.
328 * initialize: function(radius) { ... }, // Methodendefinitionen
329 * fall: function() { ... }
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'];
340 * @param {Function} [superclass] The class from which the
341 * new class will inherit the class definition.
342 * @param {*} [definition] Class definition.
345 * Erstellt eine neue Klasse
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.
353 * var Ball = Class.create({ // definiert eine unabhängige Klasse.
354 * initialize: function(radius) { ... }, // Methodendefinitionen
355 * fall: function() { ... }
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'];
366 * @param {Function} [superclass] Die Klasse, deren Klassendefinition
367 * die neue Klasse erben wird.
368 * @param {*} definition Klassendefinition.
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)");
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]);
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;
392 definition[prop] = { value: definition[prop], enumerable: true, writable: true };
396 var Constructor = function() {
397 if (this instanceof Constructor) {
398 Constructor.prototype.initialize.apply(this, arguments);
400 return new Constructor();
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);
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);
427 * Get the inheritance tree of this class.
429 * @param {ConstructorFunction}
430 * @return {...ConstructorFunction}
432 enchant.Class.getInheritanceTree = function(Constructor) {
435 var proto = C.prototype;
436 while (C !== Object) {
438 proto = Object.getPrototypeOf(proto);
439 C = proto.constructor;
448 * new Core() を呼ぶ前に変更することで変更することで, 動作設定を変えることができる.
451 * enchant.js environment variables.
452 * Execution settings can be changed by modifying these before calling new Core().
466 * Version of enchant.js
470 * Version of enchant.js
476 * The CSS vendor prefix of the current browser.
479 VENDOR_PREFIX: (function() {
480 var ua = navigator.userAgent;
481 if (ua.indexOf('Opera') !== -1) {
483 } else if (ua.indexOf('MSIE') !== -1) {
485 } else if (ua.indexOf('WebKit') !== -1) {
487 } else if (navigator.product === 'Gecko') {
494 * Determines if the current browser supports touch.
495 * @type {Boolean} True, if touch is enabled.
497 TOUCH_ENABLED: (function() {
498 var div = document.createElement('div');
499 div.setAttribute('ontouchstart', 'return');
500 return typeof div.ontouchstart === 'function';
503 * Determines if the current browser is an iPhone with a retina display.
504 * @return {Boolean} True, if this display is a retina display
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);
513 viewport.setAttribute('content', 'width=640');
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.
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);
531 * If click/touch event occurs for these tags the setPreventDefault() method will not be called.
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'
540 * You can use 'left', 'up', 'right', 'down', 'a', or 'b' for preset events.
542 * enchant.ENV.KEY_BIND_TABLE = {
547 * 32: 'a', //-> use 'space' key as 'a button'
549 * The default key bindings only bind 'left', 'up', 'right', and 'down' to the arrow keys.
557 PREVENT_DEFAULT_KEY_CODES: [37, 38, 39, 40, 32],
561 SOUND_ENABLED_ON_MOBILE_SAFARI: false,
563 * Determines if WebAudioAPI is enabled.
564 * (true: use WebAudioAPI instead of Audio element if possible)
566 USE_WEBAUDIO: (function(){
567 return location.protocol !== 'file:';
570 * Determines if animation feature is enabled.
571 * (true: Timeline instance will be generated for every new Node)
577 * @scope enchant.Event.prototype
579 enchant.Event = enchant.Class.create({
581 * @name enchant.Event
584 * DOM Event風味の独自イベント実装を行ったクラス.
586 * @param {String} type Eventのタイプ
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.
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.
601 initialize: function(type) {
607 * The type of the event.
620 * The target of the event.
633 * The x-coordinate of the event's occurrence.
636 * X Koordinate des Auftretens des Ereignis.
646 * The y-coordinate of the event's occurrence.
649 * Y Koordinate des Auftretens des Ereignis.
656 * イベントを発行したオブジェクトを基準とするイベント発生位置のx座標.
659 * The x-coordinate of the event's occurrence relative to the object
660 * which issued the event.
663 * X Koordinate des lokalen Koordinatensystems des Auftretens des Ereignis.
670 * イベントを発行したオブジェクトを基準とするイベント発生位置のy座標.
673 * The y-coordinate of the event's occurrence relative to the object
674 * which issued the event.
677 * Y Koordinate des lokalen Koordinatensystems des Auftretens des Ereignis.
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;
692 * Coreのロード完了時に発生するイベント.
694 * 画像のプリロードを行う場合ロードが完了するのを待ってゲーム開始時の処理を行う必要がある.
695 * 発行するオブジェクト: {@link enchant.Core}
698 * var core = new Core(320, 320);
699 * core.preload('player.gif');
700 * core.onload = function() {
701 * ... // ゲーム開始時の処理を記述
707 * An event dispatched once the core has finished loading.
709 * When preloading images, it is necessary to wait until preloading is complete
710 * before starting the game.
711 * Issued by: {@link enchant.Core}
714 * var core = new Core(320, 320);
715 * core.preload('player.gif');
716 * core.onload = function() {
717 * ... // Description of initial core processing
723 * Ereignis, dass auftritt wenn das Laden des Spieles abgeschlossen wurde.
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}
730 * var core = new Core(320, 320);
731 * core.preload('player.gif');
732 * core.onload = function() {
733 * ... // initialisierung des Spieles
740 enchant.Event.LOAD = 'load';
744 * エラーの発生をCoreに伝える際に発生するイベント.
745 * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Surface}, {@link enchant.WebAudioSound}, {@link enchant.DOMSound}
748 * An event dispatched when an error occurs.
749 * Issued by: {@link enchant.Core}, {@link enchant.Surface}, {@link enchant.WebAudioSound}, {@link enchant.DOMSound}
752 enchant.Event.ERROR = 'error';
756 * 表示サイズが変わったときに発生するイベント.
757 * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
760 * An event dispatched when the display size is changed.
761 * Issued by: {@link enchant.Core}, {@link enchant.Scene}
765 enchant.Event.CORE_RESIZE = 'coreresize';
769 * Coreのロード進行中に発生するイベント.
770 * プリロードする画像が一枚ロードされる度に発行される. 発行するオブジェクト: {@link enchant.LoadingScene}
773 * An event dispatched while the core is loading.
774 * Dispatched each time an image is preloaded. Issued by: {@link enchant.LoadingScene}
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}
783 enchant.Event.PROGRESS = 'progress';
788 * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Node}
791 * An event dispatched when a new frame is being processed.
792 * Issued by: {@link enchant.Core}, {@link enchant.Node}
795 * Ereignis, welches auftritt wenn ein neuer Frame bearbeitet wird.
796 * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Node}
800 enchant.Event.ENTER_FRAME = 'enterframe';
805 * 発行するオブジェクト: {@link enchant.Core}
808 * An event dispatched when frame processing is about to end.
809 * Issued by: {@link enchant.Core}
812 * Ereignis, welches auftritt wenn ein Frame beendet wird.
813 * Objekt des Auftretens: {@link enchant.Core}
817 enchant.Event.EXIT_FRAME = 'exitframe';
821 * Sceneが開始したとき発生するイベント.
822 * 発行するオブジェクト: {@link enchant.Scene}
825 * An event dispatched when a Scene begins.
826 * Issued by: {@link enchant.Scene}
829 * Ereignis, dass auftritt wenn eine neue Szene
830 * ({@link enchant.Scene}) beginnt.
831 * Objekt des Auftretens: {@link enchant.Scene}
835 enchant.Event.ENTER = 'enter';
839 * Sceneが終了したとき発生するイベント.
840 * 発行するオブジェクト: {@link enchant.Scene}
843 * An event dispatched when a Scene ends.
844 * Issued by: {@link enchant.Scene}
847 * Ereignis, dass auftritt wenn eine Szene
848 * ({@link enchant.Scene}) endet.
849 * Objekt des Auftretens: {@link enchant.Scene}
853 enchant.Event.EXIT = 'exit';
857 * Nodeに子が追加されたとき発生するイベント.
858 * 発行するオブジェクト: {@link enchant.Group}, {@link enchant.Scene}
861 * An event dispatched when a Child has been added to a Node.
862 * Issued by: {@link enchant.Group}, {@link enchant.Scene}
865 * Ereignis, welchses auftritt wenn ein Kindelement zu einem Node
867 * Objekt des Auftretens: {@link enchant.Group}, {@link enchant.Scene}
871 enchant.Event.CHILD_ADDED = 'childadded';
875 * NodeがGroupに追加されたとき発生するイベント.
876 * 発行するオブジェクト: {@link enchant.Node}
879 * An event dispatched when a Node has been added to a Group.
880 * Issued by: {@link enchant.Node}
883 * Ereignis, welchses auftritt wenn der Node zu einer Gruppe
885 * Objekt des Auftretens: {@link enchant.Node}
889 enchant.Event.ADDED = 'added';
893 * NodeがSceneに追加されたとき発生するイベント.
894 * 発行するオブジェクト: {@link enchant.Node}
897 * An event dispatched when a Node has been added to a Scene.
898 * Issued by: {@link enchant.Node}
901 * Ereignis, welchses auftritt wenn der Node zu einer Szene
903 * Objekt des Auftretens: {@link enchant.Node}
907 enchant.Event.ADDED_TO_SCENE = 'addedtoscene';
911 * Nodeから子が削除されたとき発生するイベント.
912 * 発行するオブジェクト: {@link enchant.Group}, {@link enchant.Scene}
916 * An event dispatched when a Child has been removed from a Node.
917 * Issued by: {@link enchant.Group}, {@link enchant.Scene}
921 * Ereignis, welchses auftritt wenn ein Kindelement von einem Node
923 * Objekt des Auftretens: {@link enchant.Group}, {@link enchant.Scene}
927 enchant.Event.CHILD_REMOVED = 'childremoved';
931 * NodeがGroupから削除されたとき発生するイベント.
932 * 発行するオブジェクト: {@link enchant.Node}
935 * An event dispatched when a Node has been deleted from a Group.
936 * Issued by: {@link enchant.Node}
939 * Ereignis, welchses auftritt wenn der Node aus einer Gruppe
941 * Objekt des Auftretens: {@link enchant.Node}
945 enchant.Event.REMOVED = 'removed';
949 * NodeがSceneから削除されたとき発生するイベント.
950 * 発行するオブジェクト: {@link enchant.Node}
953 * An event dispatched when a Node has been deleted from a Scene.
954 * Issued by: {@link enchant.Node}
957 * Ereignis, welchses auftritt wenn der Node aus einer Szene
959 * Objekt des Auftretens: {@link enchant.Node}
963 enchant.Event.REMOVED_FROM_SCENE = 'removedfromscene';
967 * Nodeに対するタッチが始まったとき発生するイベント.
968 * クリックもタッチとして扱われる. 発行するオブジェクト: {@link enchant.Node}
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}
975 * Ereignis, welchses auftritt wenn ein Touch auf einen Node
976 * beginnt. Klicks werden als Touch behandelt.
977 * Objekt des Auftretens: {@link enchant.Node}
981 enchant.Event.TOUCH_START = 'touchstart';
985 * Nodeに対するタッチが移動したとき発生するイベント.
986 * クリックもタッチとして扱われる. 発行するオブジェクト: {@link enchant.Node}
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}
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}
999 enchant.Event.TOUCH_MOVE = 'touchmove';
1003 * Nodeに対するタッチが終了したとき発生するイベント.
1004 * クリックもタッチとして扱われる. 発行するオブジェクト: {@link enchant.Node}
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}
1011 * Ereignis, welchses auftritt wenn ein Touch auf einen Node
1012 * endet. Klicks werden als Touch behandelt.
1013 * Objekt des Auftretens: {@link enchant.Node}
1017 enchant.Event.TOUCH_END = 'touchend';
1021 * Entityがレンダリングされるときに発生するイベント.
1022 * 発行するオブジェクト: {@link enchant.Entity}
1025 * An event dispatched when an Entity has been rendered.
1026 * Issued by: {@link enchant.Entity}
1029 * Ereignis, welchses auftritt wenn eine Entity
1031 * Objekt des Auftretens: {@link enchant.Entity}
1035 enchant.Event.RENDER = 'render';
1039 * ボタン入力が始まったとき発生するイベント.
1040 * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1043 * An event dispatched when any button has been pressed.
1044 * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1047 * Ereignis, welchses auftritt wenn ein Knopf gedückt wird.
1048 * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1052 enchant.Event.INPUT_START = 'inputstart';
1056 * ボタン入力が変化したとき発生するイベント.
1057 * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1060 * An event dispatched when button inputs have changed.
1061 * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1064 * Ereignis, welchses auftritt wenn eine Knopfeingabe verändert wird.
1065 * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1069 enchant.Event.INPUT_CHANGE = 'inputchange';
1073 * ボタン入力が終了したとき発生するイベント.
1074 * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1077 * An event dispatched when all button inputs have ended.
1078 * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1081 * Ereignis, welchses auftritt wenn eine Knopf losgelassen wird.
1082 * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1086 enchant.Event.INPUT_END = 'inputend';
1090 * leftボタンが押された発生するイベント.
1091 * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1094 * An event dispatched when the 'left' button is pressed.
1095 * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1098 * Ereignis, welchses auftritt wenn der "Nach Links"-Knopf gedrückt wird.
1099 * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1103 enchant.Event.LEFT_BUTTON_DOWN = 'leftbuttondown';
1107 * leftボタンが離された発生するイベント.
1108 * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1111 * An event dispatched when the 'left' button is released.
1112 * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1115 * Ereignis, welchses auftritt wenn der "Nach Links"-Knopf losgelassen wird.
1116 * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1120 enchant.Event.LEFT_BUTTON_UP = 'leftbuttonup';
1124 * rightボタンが押された発生するイベント.
1125 * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1128 * An event dispatched when the 'right' button is pressed.
1129 * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1132 * Ereignis, welchses auftritt wenn der "Nach Rechts"-Knopf gedrückt wird.
1133 * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1137 enchant.Event.RIGHT_BUTTON_DOWN = 'rightbuttondown';
1141 * rightボタンが離された発生するイベント.
1142 * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1145 * An event dispatched when the 'right' button is released.
1146 * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1149 * Ereignis, welchses auftritt wenn der "Nach Rechts"-Knopf losgelassen wird.
1150 * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1154 enchant.Event.RIGHT_BUTTON_UP = 'rightbuttonup';
1158 * upボタンが押された発生するイベント.
1159 * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1162 * An event dispatched when the 'up' button is pressed.
1163 * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1166 * Ereignis, welchses auftritt wenn der "Nach Oben"-Knopf gedrückt wird.
1167 * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1171 enchant.Event.UP_BUTTON_DOWN = 'upbuttondown';
1175 * upボタンが離された発生するイベント.
1176 * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1179 * An event dispatched when the 'up' button is released.
1180 * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1183 * Ereignis, welchses auftritt wenn der "Nach Oben"-Knopf losgelassen wird.
1184 * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1188 enchant.Event.UP_BUTTON_UP = 'upbuttonup';
1192 * downボタンが離された発生するイベント.
1193 * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1196 * An event dispatched when the 'down' button is pressed.
1197 * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1200 * Ereignis, welchses auftritt wenn der "Nach Unten"-Knopf gedrückt wird.
1201 * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1205 enchant.Event.DOWN_BUTTON_DOWN = 'downbuttondown';
1209 * downボタンが離された発生するイベント.
1210 * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1213 * An event dispatched when the 'down' button is released.
1214 * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1217 * Ereignis, welchses auftritt wenn der "Nach Unten"-Knopf losgelassen wird.
1218 * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1222 enchant.Event.DOWN_BUTTON_UP = 'downbuttonup';
1226 * aボタンが押された発生するイベント.
1227 * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1230 * An event dispatched when the 'a' button is pressed.
1231 * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1234 * Ereignis, welchses auftritt wenn der "A"-Knopf gedrückt wird.
1235 * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1239 enchant.Event.A_BUTTON_DOWN = 'abuttondown';
1243 * aボタンが離された発生するイベント.
1244 * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1247 * An event dispatched when the 'a' button is released.
1248 * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1251 * Ereignis, welchses auftritt wenn der "A"-Knopf losgelassen wird.
1252 * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1256 enchant.Event.A_BUTTON_UP = 'abuttonup';
1260 * bボタンが押された発生するイベント.
1261 * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1264 * An event dispatched when the 'b' button is pressed.
1265 * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1268 * Ereignis, welchses auftritt wenn der "B"-Knopf gedrückt wird.
1269 * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1273 enchant.Event.B_BUTTON_DOWN = 'bbuttondown';
1277 * bボタンが離された発生するイベント.
1278 * 発行するオブジェクト: {@link enchant.Core}, {@link enchant.Scene}
1281 * An event dispatched when the 'b' button is released.
1282 * Issued by: {@link enchant.Core}, {@link enchant.Scene}
1285 * Ereignis, welchses auftritt wenn der "B"-Knopf losgelassen wird.
1286 * Objekt des Auftretens: {@link enchant.Core}, {@link enchant.Scene}
1290 enchant.Event.B_BUTTON_UP = 'bbuttonup';
1294 * アクションがタイムラインに追加された時に発行されるイベント
1295 * looped が設定されている時も、アクションは一度タイムラインから削除されもう一度追加される
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.
1304 enchant.Event.ADDED_TO_TIMELINE = "addedtotimeline";
1308 * アクションがタイムラインから削除された時に発行されるイベント
1309 * looped が設定されている時も、アクションは一度タイムラインから削除されもう一度追加される
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.
1317 enchant.Event.REMOVED_FROM_TIMELINE = "removedfromtimeline";
1321 * アクションが開始された時に発行されるイベント
1324 * An event dispatched when an Action begins.
1328 enchant.Event.ACTION_START = "actionstart";
1332 * アクションが終了するときに発行されるイベント
1335 * An event dispatched when an Action finishes.
1339 enchant.Event.ACTION_END = "actionend";
1343 * アクションが1フレーム経過するときに発行されるイベント
1346 * An event dispatched when an Action has gone through one frame.
1350 enchant.Event.ACTION_TICK = "actiontick";
1354 * アクションが追加された時に、タイムラインに対して発行されるイベント
1357 * An event dispatched to the Timeline when an Action is added.
1361 enchant.Event.ACTION_ADDED = "actionadded";
1365 * アクションが削除された時に、タイムラインに対して発行されるイベント
1368 * An event dispatched to the Timeline when an Action is removed.
1372 enchant.Event.ACTION_REMOVED = "actionremoved";
1375 * @scope enchant.EventTarget.prototype
1377 enchant.EventTarget = enchant.Class.create({
1379 * @name enchant.EventTarget
1382 * DOM Event風味の独自イベント実装を行ったクラス.
1386 * A class for implementation of events similar to DOM Events.
1387 * However, it does not include the concept of phases.
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.
1394 * @extends {enchant.Event}
1397 initialize: function() {
1398 this._listeners = {};
1403 * @param {String} type イベントのタイプ.
1404 * @param {function(e:enchant.Event)} listener 追加するイベントリスナ.
1407 * Add a new event listener which will be executed when the event
1409 * @param {String} type Type of the events.
1410 * @param {function(e:enchant.Event)} listener Event listener to be added.
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.
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);
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.
1436 this.addEventListener.apply(this, arguments);
1441 * @param {String} type イベントのタイプ.
1442 * @param {function(e:enchant.Event)} listener 削除するイベントリスナ.
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.
1450 * Entfernt einen Ereignisbeobachter.
1451 * @param {String} type Ereignis Typ.
1452 * @param {function(e:enchant.Event)} listener Der Ereignisbeobachter
1453 * der entfernt wird.
1456 removeEventListener: function(type, listener) {
1457 var listeners = this._listeners[type];
1458 if (listeners != null) {
1459 var i = listeners.indexOf(listener);
1461 listeners.splice(i, 1);
1468 * @param [String] type イベントのタイプ.
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.
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.
1482 clearEventListener: function(type) {
1484 delete this._listeners[type];
1486 this._listeners = {};
1492 * @param {enchant.Event} e 発行するイベント.
1496 * @param {enchant.Event} e Event to be issued.
1499 * Löst ein Ereignis aus.
1500 * @param {enchant.Event} e Ereignis das ausgelöst werden soll.
1503 dispatchEvent: function(e) {
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);
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);
1521 * @scope enchant.Core.prototype
1526 * @scope enchant.Core.prototype
1528 enchant.Core = enchant.Class.create(enchant.EventTarget, {
1530 * @name enchant.Core
1533 * アプリケーションのメインループ, シーンを管理するクラス.
1535 * インスタンスは一つしか存在することができず, すでにインスタンスが存在する状態で
1536 * コンストラクタを実行した場合既存のものが上書きされる. 存在するインスタンスには
1537 * enchant.Core.instanceからアクセスできる.
1539 * @param {Number} width 画面の横幅.
1540 * @param {Number} height 画面の高さ.
1543 * A class for controlling the core’s main loop and scenes.
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}.
1550 * @param {Number} width The width of the core viewport.
1551 * @param {Number} height The height of the core viewport.
1554 * Klasse, welche die Spielschleife und Szenen kontrolliert.
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.
1561 * @param {Number} width Die Breite des Spieles.
1562 * @param {Number} height Die Höhe des Spieles.
1565 * @extends enchant.EventTarget
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.");
1573 enchant.EventTarget.call(this);
1579 core = enchant.Core.instance = this;
1581 this._calledTime = 0;
1582 this._mousedownID = 0;
1583 this._surfaceID = 0;
1588 width = width || 320;
1589 height = height || 320;
1591 var stage = document.getElementById('enchant-stage');
1592 var scale, sWidth, sHeight;
1594 stage = document.createElement('div');
1595 stage.id = 'enchant-stage';
1596 stage.style.position = 'absolute';
1598 if (document.body.firstChild) {
1599 document.body.insertBefore(stage, document.body.firstChild);
1601 document.body.appendChild(stage);
1604 window.innerWidth / width,
1605 window.innerHeight / height
1610 var style = window.getComputedStyle(stage);
1611 sWidth = parseInt(style.width, 10);
1612 sHeight = parseInt(style.height, 10);
1613 if (sWidth && sHeight) {
1621 while (stage.firstChild) {
1622 stage.removeChild(stage.firstChild);
1624 stage.style.position = 'relative';
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);
1630 stage.style.fontSize = '12px';
1631 stage.style.webkitTextSizeAdjust = 'none';
1632 stage.style.webkitTapHighlightColor = 'rgba(0, 0, 0, 0)';
1633 this._element = stage;
1635 this.addEventListener('coreresize', this._oncoreresize);
1637 this._width = width;
1638 this._height = height;
1646 * The frame rate of the core.
1649 * Frame Rate des Spieles.
1659 * The number of frames processed since the core was started.
1662 * Anzahl der Frames seit dem Spielestart.
1672 * Indicates whether or not the core can be executed.
1675 * Zeigt an ob das Spiel ausgeführt werden kann.
1685 * Indicates whether or not the core is currently running.
1688 * Zeigt an ob das Spiel derzeit ausgeführt wird.
1692 this.running = false;
1695 * ロードされた画像をパスをキーとして保存するオブジェクト.
1698 * Object which stores loaded assets using the path as a key.
1701 * Geladene Objekte werden unter dem Pfad als Schlüssel in diesem Objekt abgelegt.
1703 * @type {Object.<String, Surface>}
1706 var assets = this._assets = [];
1707 (function detectAssets(module) {
1708 if (module.assets) {
1709 enchant.Core.instance.preload(module.assets);
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]);
1722 * 現在のScene. Sceneスタック中の一番上のScene.
1725 * The Scene which is currently displayed. This Scene is on top of Scene stack.
1728 * Die aktuell dargestellte Szene.
1729 * Diese Szene befindet sich oben auf dem Stapelspeicher.
1731 * @type {enchant.Scene}
1733 this.currentScene = null;
1736 * ルートScene. Sceneスタック中の一番下のScene.
1739 * The root Scene. The Scene at bottom of the Scene stack.
1742 * Die Ursprungsszene.
1743 * Diese Szene befindet sich unten auf dem Stapelspeicher.
1745 * @type {enchant.Scene}
1747 this.rootScene = new enchant.Scene();
1748 this.pushScene(this.rootScene);
1751 * ローディング時に表示されるScene.
1754 * The Scene to be displayed during loading.
1757 * Die Szene, welche während des Ladevorgangs dargestellt wird.
1759 * @type {enchant.Scene}
1761 this.loadingScene = new enchant.LoadingScene();
1765 * 一度でも game.start() が呼ばれたことがあるかどうか。
1768 * Indicates whether or not game.start() has been called.
1773 this._activated = false;
1780 * アプリに対する入力状態を保存するオブジェクト.
1783 * Object that saves the current input state for the core.
1786 * Objekt, welches den aktuellen Eingabestatus des Spieles speichert.
1788 * @type {Object.<String, Boolean>}
1791 if (!enchant.ENV.KEY_BIND_TABLE) {
1792 enchant.ENV.KEY_BIND_TABLE = {};
1794 this._keybind = enchant.ENV.KEY_BIND_TABLE;
1795 this.pressedKeysNum = 0;
1796 this._internalButtondownListeners = {};
1797 this._internalButtonupListeners = {};
1799 for (var prop in this._keybind) {
1800 this.keybind(prop, this._keybind[prop]);
1804 stage = enchant.Core.instance._element;
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) {
1810 e.stopPropagation();
1813 if (!core.running) {
1816 var button = core._keybind[e.keyCode];
1818 evt = new enchant.Event(button + 'buttondown');
1819 core.dispatchEvent(evt);
1822 document.addEventListener('keyup', function(e) {
1823 if (!core.running) {
1826 var button = core._keybind[e.keyCode];
1828 evt = new enchant.Event(button + 'buttonup');
1829 core.dispatchEvent(evt);
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) {
1838 if (!core.running) {
1839 e.stopPropagation();
1843 stage.addEventListener('touchmove', function(e) {
1844 var tagName = (e.target.tagName).toLowerCase();
1845 if (enchant.ENV.USE_DEFAULT_EVENT_TAGS.indexOf(tagName) === -1) {
1847 if (!core.running) {
1848 e.stopPropagation();
1852 stage.addEventListener('touchend', function(e) {
1853 var tagName = (e.target.tagName).toLowerCase();
1854 if (enchant.ENV.USE_DEFAULT_EVENT_TAGS.indexOf(tagName) === -1) {
1856 if (!core.running) {
1857 e.stopPropagation();
1862 stage.addEventListener('mousedown', function(e) {
1863 var tagName = (e.target.tagName).toLowerCase();
1864 if (enchant.ENV.USE_DEFAULT_EVENT_TAGS.indexOf(tagName) === -1) {
1866 core._mousedownID++;
1867 if (!core.running) {
1868 e.stopPropagation();
1872 stage.addEventListener('mousemove', function(e) {
1873 var tagName = (e.target.tagName).toLowerCase();
1874 if (enchant.ENV.USE_DEFAULT_EVENT_TAGS.indexOf(tagName) === -1) {
1876 if (!core.running) {
1877 e.stopPropagation();
1881 stage.addEventListener('mouseup', function(e) {
1882 var tagName = (e.target.tagName).toLowerCase();
1883 if (enchant.ENV.USE_DEFAULT_EVENT_TAGS.indexOf(tagName) === -1) {
1885 if (!core.running) {
1886 e.stopPropagation();
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;
1897 for (var i = 0, l = touches.length; i < l; i++) {
1899 evt._initPosition(touch.pageX, touch.pageY);
1900 target = core.currentScene._determineEventTarget(evt);
1901 core._touchEventTarget[touch.identifier] = target;
1902 target.dispatchEvent(evt);
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;
1910 for (var i = 0, l = touches.length; i < l; i++) {
1912 target = core._touchEventTarget[touch.identifier];
1914 evt._initPosition(touch.pageX, touch.pageY);
1915 target.dispatchEvent(evt);
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;
1924 for (var i = 0, l = touches.length; i < l; i++) {
1926 target = core._touchEventTarget[touch.identifier];
1928 evt._initPosition(touch.pageX, touch.pageY);
1929 target.dispatchEvent(evt);
1930 delete core._touchEventTarget[touch.identifier];
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);
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];
1949 target.dispatchEvent(evt);
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];
1958 target.dispatchEvent(evt);
1960 delete core._touchEventTarget[core._mousedownID];
1969 * The width of the core screen.
1972 * Breite des Spieles.
1982 this._dispatchCoreResizeEvent();
1990 * The height of the core screen.
1999 return this._height;
2003 this._dispatchCoreResizeEvent();
2011 * The scaling of the core rendering.
2014 * Skalierung der Spieldarstellung.
2024 this._dispatchCoreResizeEvent();
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);
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';
2038 for (var i = 0, l = this._scenes.length; i < l; i++) {
2039 scene = this._scenes[i];
2040 scene.dispatchEvent(e);
2047 * プリロードを行うよう設定されたファイルは{@link enchant.Core#start}が実行されるとき
2048 * ロードが行われる. 全てのファイルのロードが完了したときはCoreオブジェクトからload
2049 * イベントが発行され, Coreオブジェクトのassetsプロパティから画像ファイルの場合は
2050 * Surfaceオブジェクトとして, 音声ファイルの場合はSoundオブジェクトとして,
2051 * その他の場合は文字列としてアクセスできるようになる.
2053 * なおこのSurfaceオブジェクトは{@link enchant.Surface.load}を使って作成されたものである
2054 * ため直接画像操作を行うことはできない. enchant.Surface.loadの項を参照.
2057 * core.preload('player.gif');
2058 * core.onload = function() {
2059 * var sprite = new Sprite(32, 32);
2060 * sprite.image = core.assets['player.gif']; // パス名でアクセス
2065 * @param {...String} assets プリロードするファイルのパス. 複数指定できる.
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.
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
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.
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
2096 * @param {...String} assets Path of images to be preloaded.
2097 * Multiple settings possible.
2100 * Lässt Dateien im voraus laden.
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.
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.
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
2123 * @param {...String} assets Pfade zu den Dateien die im voraus geladen werden sollen.
2124 * Mehrfachangaben möglich.
2126 * @return {enchant.Core} this
2128 preload: function(assets) {
2130 if (!(assets instanceof Array)) {
2131 if (typeof assets === 'object') {
2133 for (var name in assets) {
2134 if (assets.hasOwnProperty(name)) {
2135 a.push([ assets[name], name ]);
2140 assets = Array.prototype.slice.call(arguments);
2143 Array.prototype.push.apply(this._assets, assets);
2150 * @param {String} [src] asset ロードするファイルのパス.
2151 * @param {String} [alias] ロードするファイルに設定したい名前.
2152 * @param {Function} [callback] ファイルのロードが完了したときに呼び出される関数.
2153 * @param {Function} [onerror] ファイルのロードに失敗したときに呼び出される関数.
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.
2164 * Laden von Dateien.
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.
2170 load: function(src, alias, callback, onerror) {
2171 var assetName, offset;
2172 if (typeof arguments[1] === 'string') {
2179 callback = arguments[1 + offset] || function() {};
2180 onerror = arguments[2 + offset] || function() {};
2182 var ext = enchant.Core.findExt(src);
2184 return enchant.Deferred.next(function() {
2185 var d = new enchant.Deferred();
2186 var _callback = function(e) {
2188 callback.call(this, e);
2190 var _onerror = function(e) {
2192 onerror.call(this, e);
2194 if (enchant.Core._loadFuncs[ext]) {
2195 enchant.Core.instance.assets[assetName] = enchant.Core._loadFuncs[ext](src, ext, _callback, _onerror);
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);
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);
2214 core.assets[assetName] = req.responseText;
2215 _callback.call(enchant.Core.instance, new enchant.Event('laod'));
2228 * enchant.Core#fpsで設定されたフレームレートに従ってenchant.Core#currentSceneの
2229 * フレームの更新が行われるようになる. プリロードする画像が存在する場合はロードが
2230 * 始まりローディング画面が表示される.
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.
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.
2247 * @return {enchant.Deferred} Deferred
2249 start: function(deferred) {
2250 var onloadTimeSetter = function() {
2252 this.removeEventListener('load', onloadTimeSetter);
2254 this.addEventListener('load', onloadTimeSetter);
2256 this.currentTime = window.getTime();
2257 this.running = true;
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);
2283 core.pushScene(scene);
2288 this._requestNextFrame(0);
2290 var ret = this._requestPreload()
2292 enchant.Core.instance.loadingScene.dispatchEvent(new enchant.Event(enchant.Event.LOAD));
2296 ret.next(function(arg) {
2299 .error(function(arg) {
2306 _requestPreload: function() {
2310 loadFunc = function() {
2311 var e = new enchant.Event('progress');
2312 e.loaded = ++loaded;
2314 core.loadingScene.dispatchEvent(e);
2318 .forEach(function(asset) {
2320 if (asset instanceof Array) {
2327 o[name] = this.load(src, name, loadFunc);
2332 this.pushScene(this.loadingScene);
2333 return enchant.Deferred.parallel(o);
2339 * enchant.Core.instance._debug フラグを true にすることでもデバッグモードをオンにすることができる
2342 * Start application in debug mode.
2344 * Core debug mode can be turned on even if the
2345 * enchant.Core.instance._debug flag is already set to true.
2348 * Startet den Debug-Modus des Spieles.
2350 * Auch wenn die enchant.Core.instance._debug Variable gesetzt ist,
2351 * kann der Debug-Modus gestartet werden.
2353 * @return {enchant.Deferred} Deferred
2357 return this.start();
2361 return this._actualFps || this.fps;
2367 * @param {Number} requestAnimationFrameを呼び出すまでの遅延時間.
2370 * Requests the next frame.
2371 * @param {Number} Amount of time to delay before calling requestAnimationFrame.
2375 _requestNextFrame: function(delay) {
2379 if (this.fps >= 60 || delay <= 16) {
2380 this._calledTime = window.getTime();
2381 window.requestAnimationFrame(this._callTick);
2383 setTimeout(function() {
2384 var core = enchant.Core.instance;
2385 core._calledTime = window.getTime();
2386 window.requestAnimationFrame(core._callTick);
2387 }, Math.max(0, delay));
2392 * {@link enchant.Core#_tick}を呼び出す.
2395 * Calls {@link enchant.Core#_tick}.
2397 * @param {Number} [time]
2400 _callTick: function(time) {
2401 enchant.Core.instance._tick(time);
2403 _tick: function(time) {
2404 var e = new enchant.Event('enterframe');
2405 var now = window.getTime();
2406 var elapsed = e.elapsed = now - this.currentTime;
2408 this._actualFps = elapsed > 0 ? (1000 / elapsed) : 0;
2410 var nodes = this.currentScene.childNodes.slice();
2411 var push = Array.prototype.push;
2412 while (nodes.length) {
2413 var node = nodes.pop();
2415 node.dispatchEvent(e);
2416 if (node.childNodes) {
2417 push.apply(nodes, node.childNodes);
2421 this.currentScene.age++;
2422 this.currentScene.dispatchEvent(e);
2423 this.dispatchEvent(e);
2425 this.dispatchEvent(new enchant.Event('exitframe'));
2427 now = window.getTime();
2428 this.currentTime = now;
2429 this._requestNextFrame(1000 / this.fps - (now - this._calledTime));
2431 getTime: function() {
2432 return window.getTime();
2438 * フレームは更新されず, ユーザの入力も受け付けなくなる.
2439 * enchant.Core#startで再開できる.
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}.
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.
2457 this.running = false;
2463 * フレームは更新されず, ユーザの入力は受け付ける.
2464 * enchant.Core#startで再開できる.
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}.
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.
2491 * Setzt die Ausführung des Spieles fort.
2494 resume: function() {
2498 this.currentTime = window.getTime();
2500 this.running = true;
2501 this._requestNextFrame(0);
2508 * Sceneはスタック状に管理されており, 表示順序もスタックに積み上げられた順に従う.
2509 * enchant.Core#pushSceneを行うとSceneをスタックの一番上に積むことができる. スタックの
2510 * 一番上のSceneに対してはフレームの更新が行われる.
2512 * @param {enchant.Scene} scene 移行する新しいScene.
2513 * @return {enchant.Scene} 新しいScene.
2516 * Switch to a new Scene.
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.
2522 * @param {enchant.Scene} scene The new scene to be switched to.
2523 * @return {enchant.Scene} The new Scene.
2526 * Wechselt zu einer neuen Szene.
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
2534 * @param {enchant.Scene} scene Die neue Szene zu der gewechselt werden soll.
2535 * @return {enchant.Scene} Die neue Szene.
2538 pushScene: function(scene) {
2539 this._element.appendChild(scene._element);
2540 if (this.currentScene) {
2541 this.currentScene.dispatchEvent(new enchant.Event('exit'));
2543 this.currentScene = scene;
2544 this.currentScene.dispatchEvent(new enchant.Event('enter'));
2545 return this._scenes.push(scene);
2549 * 現在のSceneを終了させ前のSceneに戻る.
2551 * Sceneはスタック状に管理されており, 表示順序もスタックに積み上げられた順に従う.
2552 * enchant.Core#popSceneを行うとスタックの一番上のSceneを取り出すことができる.
2554 * @return {enchant.Scene} 終了させたScene.
2557 * Ends the current Scene, return to the previous Scene.
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.
2563 * @return {enchant.Scene} Ended Scene.
2566 * Beendet die aktuelle Szene und wechselt zu der vorherigen Szene.
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.
2573 * @return {enchant.Scene} Die Szene, die beendet wurde.
2576 popScene: function() {
2577 if (this.currentScene === this.rootScene) {
2578 return this.currentScene;
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();
2588 * 現在のSceneを別のSceneにおきかえる.
2590 * enchant.Core#popScene, enchant.Core#pushSceneを同時に行う.
2592 * @param {enchant.Scene} scene おきかえるScene.
2593 * @return {enchant.Scene} 新しいScene.
2596 * Overwrites the current Scene with a new Scene.
2598 * {@link enchant.Core#popScene}, {@link enchant.Core#pushScene} are executed after
2599 * each other to replace to current scene with the new scene.
2601 * @param {enchant.Scene} scene The new scene which will replace the previous scene.
2602 * @return {enchant.Scene} The new Scene.
2605 * Ersetzt die aktuelle Szene durch eine neue Szene.
2607 * {@link enchant.Core#popScene}, {@link enchant.Core#pushScene} werden nacheinander
2608 * ausgeführt um die aktuelle Szene durch die neue zu ersetzen.
2610 * @param {enchant.Scene} scene Die neue Szene, welche die aktuelle Szene ersetzen wird.
2611 * @return {enchant.Scene} Die neue Szene.
2614 replaceScene: function(scene) {
2616 return this.pushScene(scene);
2622 * Sceneスタック中からSceneを削除する.
2624 * @param {enchant.Scene} scene 削除するScene.
2625 * @return {enchant.Scene} 削除したScene.
2630 * Removes a Scene from the Scene stack.
2632 * @param {enchant.Scene} scene Scene to be removed.
2633 * @return {enchant.Scene} The deleted Scene.
2636 * Entfernt eine Szene.
2638 * Entfernt eine Szene aus dem Szenen-Stapelspeicher.
2640 * @param {enchant.Scene} scene Die Szene die entfernt werden soll.
2641 * @return {enchant.Scene} Die entfernte Szene.
2644 removeScene: function(scene) {
2645 if (this.currentScene === scene) {
2646 return this.popScene();
2648 var i = this._scenes.indexOf(scene);
2650 this._scenes.splice(i, 1);
2651 this._element.removeChild(scene._element);
2662 * @param {Number} key キーバインドを設定するキーコード.
2663 * @param {String} button 割り当てるボタン.
2666 * Set a key binding.
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).
2672 * Bindet eine Taste.
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).
2677 * @return {enchant.Core} this
2679 keybind: function(key, button) {
2680 this._keybind[key] = button;
2681 var onxbuttondown = function(e) {
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);
2689 this.currentScene.dispatchEvent(e);
2691 var onxbuttonup = function(e) {
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);
2699 this.currentScene.dispatchEvent(e);
2702 this.addEventListener(button + 'buttondown', onxbuttondown);
2703 this.addEventListener(button + 'buttonup', onxbuttonup);
2705 this._internalButtondownListeners[key] = onxbuttondown;
2706 this._internalButtonupListeners[key] = onxbuttonup;
2712 * @param {Number} key 削除するキーコード.
2715 * Delete a key binding.
2717 * @param {Number} key Key code that want to delete.
2720 * Entbindet eine Taste.
2722 * @param {Number} key Der Tastencode der entfernt werden soll.
2724 * @return {enchant.Core} this
2726 keyunbind: function(key) {
2727 if (!this._keybind[key]) {
2730 var buttondowns = this._internalButtondownListeners;
2731 var buttonups = this._internalButtonupListeners;
2733 this.removeEventListener(key + 'buttondown', buttondowns);
2734 this.removeEventListener(key + 'buttonup', buttonups);
2736 delete buttondowns[key];
2737 delete buttonups[key];
2739 delete this._keybind[key];
2745 * Core#start が呼ばれてから経過した時間を取得する
2746 * @return {Number} 経過した時間 (秒)
2749 * Get the elapsed core time (not actual) from when core.start was called.
2750 * @return {Number} The elapsed time (seconds)
2753 * Liefert die vergange Spielzeit (keine reale) die seit dem Aufruf von core.start
2755 * @return {Number} Die vergangene Zeit (Sekunden)
2758 getElapsedTime: function() {
2759 return this.frame / this.fps;
2765 * 拡張子に対応したアセットのロード関数.
2766 * ロード関数はファイルのパス, 拡張子, コールバックを引数に取り,
2767 * 対応したクラスのインスタンスを返す必要がある.
2768 * コールバックはEvent.LOADとEvent.ERRORでハンドルする.
2772 * @type {Object.<String, Function>}
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);
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);
2791 * Get the file extension from a path
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();
2802 if (path.indexOf('data:') === 0) {
2803 return path.split(/[\/;]/)[1].toLowerCase();
2813 * The Current Core instance.
2816 * Die aktuelle Instanz des Spieles.
2818 * @type {enchant.Core}
2821 enchant.Core.instance = null;
2825 * enchant.Core is moved to enchant.Core from v0.6
2828 enchant.Game = enchant.Core;
2830 * @scope enchant.Node.prototype
2832 enchant.Node = enchant.Class.create(enchant.EventTarget, {
2834 * @name enchant.Node
2837 * Sceneをルートとした表示オブジェクトツリーに属するオブジェクトの基底クラス.
2841 * Base class for objects in the display tree which is rooted at a Scene.
2842 * Not to be used directly.
2845 * Basisklasse für Objekte die im Darstellungsbaum,
2846 * dessen Wurzel eine Szene ist, enthalten sind.
2847 * Sollte nicht direkt verwendet werden.
2850 * @extends enchant.EventTarget
2852 initialize: function() {
2853 enchant.EventTarget.call(this);
2855 this._dirty = false;
2857 this._matrix = [ 1, 0, 0, 1, 0, 0 ];
2866 * Node が画面に表示されてから経過したフレーム数。
2867 * {@link enchant.Event.ENTER_FRAME} イベントを受け取る前にインクリメントされる。
2868 * (ENTER_FRAME イベントのリスナが初めて実行される時に 1 となる。)
2871 * The age (frames) of this node which will be increased before this node receives {@link enchant.Event.ENTER_FRAME} event.
2874 * Das Alter (Frames) dieses Nodes welches vor dem {@link enchant.Event.ENTER_FRAME} Ereignis erhöht wird.
2885 * Parent Node of this Node.
2888 * Der Eltern-Node dieses Node.
2890 * @type {enchant.Group}
2892 this.parentNode = null;
2898 * Scene to which Node belongs.
2901 * Die Szene, zu welcher dieser Node gehört.
2903 * @type {enchant.Scene}
2907 this.addEventListener('touchstart', function(e) {
2908 if (this.parentNode) {
2909 this.parentNode.dispatchEvent(e);
2912 this.addEventListener('touchmove', function(e) {
2913 if (this.parentNode) {
2914 this.parentNode.dispatchEvent(e);
2917 this.addEventListener('touchend', function(e) {
2918 if (this.parentNode) {
2919 this.parentNode.dispatchEvent(e);
2925 * Node が生成される際に、tl プロパティに Timeline オブジェクトを追加している
2928 if(enchant.ENV.USE_ANIMATION){
2929 var tl = this.tl = new enchant.Timeline(this);
2935 * @param {Number} x 移動先のx座標.
2936 * @param {Number} y 移動先のy座標.
2939 * Move the Node to the given target location.
2940 * @param {Number} x Target x coordinates.
2941 * @param {Number} y Target y coordinates.
2944 * Bewegt diesen Node zu den gegebenen Ziel Koordinaten.
2945 * @param {Number} x Ziel x Koordinaten.
2946 * @param {Number} y Ziel y Koordinaten.
2949 moveTo: function(x, y) {
2957 * @param {Number} x 移動するx軸方向の距離.
2958 * @param {Number} y 移動するy軸方向の距離.
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.
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.
2971 moveBy: function(x, y) {
2981 * x coordinates of the Node.
2984 * Die x Koordinaten des Nodes.
3002 * y coordinates of the Node.
3005 * Die y Koordinaten des Nodes.
3018 _updateCoordinate: function() {
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;
3028 var matrix = enchant.Matrix.instance;
3029 var stack = matrix.stack;
3032 stack.push(tree[0]._matrix);
3033 for (var i = 1, l = tree.length; i < l; i++) {
3036 matrix.makeTransformMatrix(node, mat);
3037 matrix.multiply(stack[stack.length - 1], mat, newmat);
3038 node._matrix = 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;
3050 remove: function() {
3051 if (this._listener) {
3052 this.clearEventListener();
3054 if (this.parentNode) {
3055 this.parentNode.removeChild(this);
3060 var _intersectBetweenClassAndInstance = function(Class, instance) {
3063 for (var i = 0, l = Class.collection.length; i < l; i++) {
3064 c = Class.collection[i];
3065 if (instance._intersectOne(c)) {
3072 var _intersectBetweenClassAndClass = function(Class1, Class2) {
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 ]);
3087 var _intersectStrictBetweenClassAndInstance = function(Class, instance) {
3090 for (var i = 0, l = Class.collection.length; i < l; i++) {
3091 c = Class.collection[i];
3092 if (instance._intersectStrictOne(c)) {
3099 var _intersectStrictBetweenClassAndClass = function(Class1, Class2) {
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 ]);
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);
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);
3133 * @scope enchant.Entity.prototype
3135 enchant.Entity = enchant.Class.create(enchant.Node, {
3137 * @name enchant.Entity
3140 * DOM上で表示する実体を持ったクラス. 直接使用することはない.
3143 * A class with objects displayed as DOM elements. Not to be used directly.
3146 * Eine Klasse die Objekte mit Hilfe von DOM Elementen darstellt.
3147 * Sollte nicht direkt verwendet werden.
3150 * @extends enchant.Node
3152 initialize: function() {
3153 var core = enchant.Core.instance;
3154 enchant.Node.call(this);
3160 this._touchEnabled = true;
3161 this._clipping = false;
3163 this._originX = null;
3164 this._originY = null;
3168 this._backgroundColor = null;
3169 this._debugColor = '#0000ff';
3171 this._visible = true;
3172 this._buttonMode = null;
3175 this.__styleStatus = {};
3179 * Entityを描画する際の合成処理を設定する.
3180 * Canvas上に描画する際のみ有効.
3181 * CanvasのコンテキストのglobalCompositeOperationにセットされる.
3184 this.compositeOperation = null;
3188 * Entityにボタンの機能を設定する.
3189 * Entityに対するタッチ, クリックをleft, right, up, down, a, bいずれかの
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.
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.
3205 this.buttonMode = null;
3208 * Entityが押されているかどうか.
3209 * {@link enchant.Entity.buttonMode}が設定されているときだけ機能する.
3212 * Indicates if this Entity is being clicked.
3213 * Only works when {@link enchant.Entity.buttonMode} is set.
3216 * Zeigt an, ob auf die Entity geklickt wurde.
3217 * Funktioniert nur wenn {@link enchant.Entity.buttonMode} gesetzt ist.
3221 this.buttonPressed = false;
3222 this.addEventListener('touchstart', function() {
3223 if (!this.buttonMode) {
3226 this.buttonPressed = true;
3227 var e = new enchant.Event(this.buttonMode + 'buttondown');
3228 this.dispatchEvent(e);
3229 core.dispatchEvent(e);
3231 this.addEventListener('touchend', function() {
3232 if (!this.buttonMode) {
3235 this.buttonPressed = false;
3236 var e = new enchant.Event(this.buttonMode + 'buttonup');
3237 this.dispatchEvent(e);
3238 core.dispatchEvent(e);
3241 this.enableCollection();
3248 * The width of the Entity.
3251 * Die Breite der Entity.
3259 set: function(width) {
3260 this._width = width;
3269 * The height of the Entity.
3272 * Die Höhe der Entity.
3278 return this._height;
3280 set: function(height) {
3281 this._height = height;
3288 * CSSの'color'プロパティと同様の形式で指定できる.
3291 * The Entity background color.
3292 * Must be provided in the same format as the CSS 'color' property.
3295 * Die Hintergrundfarbe der Entity.
3296 * Muss im gleichen Format definiert werden wie das CSS 'color' Attribut.
3302 return this._backgroundColor;
3304 set: function(color) {
3305 this._backgroundColor = color;
3311 * CSSの'color'プロパティと同様の形式で指定できる.
3314 * The Entity debug color.
3315 * Must be provided in the same format as the CSS 'color' property.
3321 return this._debugColor;
3323 set: function(color) {
3324 this._debugColor = color;
3330 * 0から1までの値を設定する(0が完全な透明, 1が完全な不透明).
3333 * The transparency of this entity.
3334 * Defines the transparency level from 0 to 1
3335 * (0 is completely transparent, 1 is completely opaque).
3338 * Transparenz der Entity.
3339 * Definiert den Level der Transparenz von 0 bis 1
3340 * (0 ist komplett transparent, 1 ist vollständig deckend).
3346 return this._opacity;
3348 set: function(opacity) {
3349 this._opacity = parseFloat(opacity);
3354 * Entityを表示するかどうかを指定する.
3357 * Indicates whether or not to display this Entity.
3360 * Zeigt an, ob die Entity dargestellt werden soll oder nicht.
3366 return this._visible;
3368 set: function(visible) {
3369 this._visible = visible;
3374 * Entityのタッチを有効にするかどうかを指定する.
3377 * Indicates whether or not this Entity can be touched.
3380 * Definiert ob auf die Entity geklickt werden kann.
3386 return this._touchEnabled;
3388 set: function(enabled) {
3389 this._touchEnabled = enabled;
3391 this._style.pointerEvents = 'all';
3393 this._style.pointerEvents = 'none';
3399 * Entityの矩形が交差しているかどうかにより衝突判定を行う.
3400 * @param {*} other 衝突判定を行うEntityなどx, y, width, heightプロパティを持ったObject.
3401 * @return {Boolean} 衝突判定の結果.
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.
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.
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);
3425 _intersectOne: function(other) {
3427 this._updateCoordinate();
3428 } if (other._dirty) {
3429 other._updateCoordinate();
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;
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);
3442 _intersectStrictOne: function(other) {
3444 this._updateCoordinate();
3445 } if (other._dirty) {
3446 other._updateCoordinate();
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) {
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) {
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++) {
3489 px1 = pos1[0]; py1 = pos1[1];
3491 dx1 = dir1[0]; dy1 = dir1[1];
3492 for (j = 0; j < 4; j++) {
3494 px2 = pos2[0]; py2 = pos2[1];
3496 dx2 = dir2[0]; dy2 = dir2[1];
3497 c = dx1 * dy2 - dy1 * dx2;
3501 c1 = (vx * dy1 - vy * dx1) / c;
3502 c2 = (vx * dy2 - vy * dx2) / c;
3503 if (0 < c1 && c1 < 1 && 0 < c2 && c2 < 1) {
3514 * Entityの中心点どうしの距離により衝突判定を行う.
3515 * @param {*} other 衝突判定を行うEntityなどx, y, width, heightプロパティを持ったObject.
3516 * @param {Number} [distance] 衝突したと見なす最大の距離. デフォルト値は二つのEntityの横幅と高さの平均.
3517 * @return {Boolean} 衝突判定の結果.
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.
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.
3537 within: function(other, distance) {
3539 this._updateCoordinate();
3540 } if (other._dirty) {
3541 other._updateCoordinate();
3543 if (distance == null) {
3544 distance = (this.width + this.height + other.width + other.height) / 4;
3547 return (_ = this._offsetX - other._offsetX + (this.width - other.width) / 2) * _ +
3548 (_ = this._offsetY - other._offsetY + (this.height - other.height) / 2) * _ < distance * distance;
3552 * @param {Number} x 拡大するx軸方向の倍率.
3553 * @param {Number} [y] 拡大するy軸方向の倍率.
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.
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.
3566 scale: function(x, y) {
3568 this._scaleY *= (y != null) ? y : x;
3574 * @param {Number} deg 回転する角度 (度数法).
3577 * Rotate this Sprite.
3578 * @param {Number} deg Rotation angle (degree).
3581 * Rotiert dieses Sprite.
3582 * @param {Number} deg Rotationswinkel (Grad).
3585 rotate: function(deg) {
3586 this._rotation += deg;
3594 * Scaling factor on the x axis of this Sprite.
3597 * Skalierungsfaktor auf der x-Achse dieses Sprites.
3603 return this._scaleX;
3605 set: function(scaleX) {
3606 this._scaleX = scaleX;
3615 * Scaling factor on the y axis of this Sprite.
3618 * Skalierungsfaktor auf der y-Achse dieses Sprites.
3624 return this._scaleY;
3626 set: function(scaleY) {
3627 this._scaleY = scaleY;
3636 * Sprite rotation angle (degree).
3639 * Rotationswinkel des Sprites (Grad).
3645 return this._rotation;
3647 set: function(rotation) {
3648 this._rotation = rotation;
3657 * The point of origin used for rotation and scaling.
3660 * Ausgangspunkt für Rotation und Skalierung.
3666 return this._originX;
3668 set: function(originX) {
3669 this._originX = originX;
3678 * The point of origin used for rotation and scaling.
3681 * Ausgangspunkt für Rotation und Skalierung.
3687 return this._originY;
3689 set: function(originY) {
3690 this._originY = originY;
3696 * インスタンスをコレクションの対象にする.
3700 enableCollection: function() {
3701 this.addEventListener('addedtoscene', this._addSelfToCollection);
3702 this.addEventListener('removedfromscene', this._removeSelfFromCollection);
3704 this._addSelfToCollection();
3709 * インスタンスをコレクションの対象から除外する.
3712 disableCollection: function() {
3713 this.removeEventListener('addedtoscene', this._addSelfToCollection);
3714 this.removeEventListener('removedfromscene', this._removeSelfFromCollection);
3716 this._removeSelfFromCollection();
3719 _addSelfToCollection: function() {
3720 var Constructor = this.getConstructor();
3721 Constructor._collectionTarget.forEach(function(C) {
3722 C.collection.push(this);
3725 _removeSelfFromCollection: function() {
3726 var Constructor = this.getConstructor();
3727 Constructor._collectionTarget.forEach(function(C) {
3728 var i = C.collection.indexOf(this);
3730 C.collection.splice(i, 1);
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; });
3747 width: xw[3] - xw[0],
3748 height: yh[3] - yh[0]
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];
3760 leftTop: [ mdx, mdy ],
3761 rightTop: [ m11w + mdx, m12w + mdy ],
3762 leftBottom: [ m21h + mdx, m22h + mdy ],
3763 rightBottom: [ m11w + m21h + mdx, m12w + m22h + mdy ]
3766 getConstructor: function() {
3767 return Object.getPrototypeOf(this).constructor;
3771 var _collectizeConstructor = function(Constructor) {
3772 if (Constructor._collective) {
3775 var rel = enchant.Class.getInheritanceTree(Constructor);
3776 var i = rel.indexOf(enchant.Entity);
3778 Constructor._collectionTarget = rel.splice(0, i + 1);
3780 Constructor._collectionTarget = [];
3782 Constructor.intersect = _staticIntersect;
3783 Constructor.intersectStrict = _staticIntersectStrict;
3784 Constructor.collection = [];
3785 Constructor._collective = true;
3788 _collectizeConstructor(enchant.Entity);
3790 enchant.Entity._inherited = function(subclass) {
3791 _collectizeConstructor(subclass);
3795 * @scope enchant.Sprite.prototype
3797 enchant.Sprite = enchant.Class.create(enchant.Entity, {
3799 * @name enchant.Sprite
3802 * 画像表示機能を持ったクラス. Entity を継承している.
3804 * @param {Number} [width] Spriteの横幅.
3805 * @param {Number} [height] Spriteの高さ.
3808 * Class which can display images.
3810 * @param {Number} [width] Sprite width.
3811 * @param {Number} [height] Sprite height.
3814 * Eine Klasse die Grafiken darstellen kann.
3816 * @param {Number} [width] Die Breite des Sprites.
3817 * @param {Number} [height] Die Höhe des Sprites.
3820 * var bear = new Sprite(32, 32);
3821 * bear.image = core.assets['chara1.gif'];
3824 * @extends enchant.Entity
3826 initialize: function(width, height) {
3827 enchant.Entity.call(this);
3830 this.height = height;
3832 this._debugColor = '#ff0000';
3833 this._frameLeft = 0;
3836 this._frameSequence = [];
3839 * frame に配列が指定されたときの処理。
3842 this.addEventListener('enterframe', function() {
3843 if (this._frameSequence.length !== 0) {
3844 var nextFrame = this._frameSequence.shift();
3845 if (nextFrame === null) {
3846 this._frameSequence = [];
3848 this._setFrame(nextFrame);
3849 this._frameSequence.push(nextFrame);
3859 * Image displayed in the Sprite.
3862 * Die Grafik die im Sprite dargestellt wird.
3864 * @type {enchant.Surface}
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.');
3874 if (image === this._image) {
3877 this._image = image;
3878 this._setFrame(this._frame);
3884 * Spriteと同じ横幅と高さを持ったフレームが{@link enchant.Sprite#image}プロパティの画像に左上から順に
3885 * 配列されていると見て, 0から始まるインデックスを指定することでフレームを切り替える.
3887 * 数値の配列が指定された場合、それらを毎フレーム順に切り替える。
3888 * ループするが、null値が含まれているとそこでループをストップする。
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.
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.
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)
3911 * @type {Number|Array}
3917 set: function(frame) {
3918 if(this._frame === frame) {
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;
3928 this._setFrame(frame);
3929 this._frameSequence = [];
3930 this._frame = frame;
3942 _setFrame: function(frame) {
3943 var image = this._image;
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;
3960 set: function(width) {
3961 this._width = width;
3962 this._setFrame(this._frame);
3972 return this._height;
3974 set: function(height) {
3975 this._height = height;
3976 this._setFrame(this._frame);
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);
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);
3999 domRender: (function() {
4000 if (enchant.ENV.VENDOR_PREFIX === 'ms') {
4001 return function(element) {
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) {
4013 return function(element) {
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) {
4029 * @scope enchant.Label.prototype
4031 enchant.Label = enchant.Class.create(enchant.Entity, {
4033 * @name enchant.Label
4039 * A class for Label object.
4042 * Erstellt ein Label Objekt.
4045 * @extends enchant.Entity
4047 initialize: function(text) {
4048 enchant.Entity.call(this);
4050 this.text = text || '';
4052 this.font = '14px serif';
4053 this.textAlign = 'left';
4055 this._debugColor = '#ff0000';
4061 set: function(width) {
4062 this._width = width;
4065 this.updateBoundArea();
4071 * DOM レンダラを利用している場合 (DOMScene 以下にある場合) 改行タグ (br) も利用できるが、
4072 * ユーザから入力したり、サーバから取得した文字列を表示する場合, XSS 脆弱性などに注意してください.
4073 * Canvas レンダラを利用できる場合でも、改行タグ (br, BR) は改行に変換されます。
4076 * Text to be displayed.
4079 * Darzustellender Text.
4087 set: function(text) {
4089 if(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;
4108 * CSSの'text-align'プロパティと同様の形式で指定できる.
4111 * Specifies horizontal alignment of text.
4112 * Can be set according to the format of the CSS 'text-align' property.
4115 * Spezifiziert die horizontale Ausrichtung des Textes.
4116 * Kann im gleichen Format wie die CSS 'text-align' Eigenschaft angegeben werden.
4122 return this._style['text-align'];
4124 set: function(textAlign) {
4125 this._style['text-align'] = textAlign;
4126 this.updateBoundArea();
4132 * CSSの'font'プロパティと同様の形式で指定できる.
4136 * Can be set according to the format of the CSS 'font' property.
4139 * Text Eigenschaften.
4140 * Kann im gleichen Format wie die CSS 'font' Eigenschaft angegeben werden.
4146 return this._style.font;
4148 set: function(font) {
4149 this._style.font = font;
4150 this.updateBoundArea();
4156 * CSSの'color'プロパティと同様の形式で指定できる.
4159 * Text color settings.
4160 * Can be set according to the format of the CSS 'color' property.
4164 * Kann im gleichen Format wie die CSS 'color' Eigenschaft angegeben werden.
4170 return this._style.color;
4172 set: function(color) {
4173 this._style.color = color;
4176 cvsRender: function(ctx) {
4178 var labelWidth = this.width;
4179 var charWidth, amount, line, text, c, buf, increase, length;
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];
4191 while (text.length > c + amount || ctx.measureText(text.slice(c, c + amount)).width > labelWidth) {
4195 while (increase > 0) {
4196 if (ctx.measureText(buf).width < labelWidth) {
4198 buf = text.slice(c, c + length);
4201 buf = text.slice(c, c + length);
4203 increase = increase / 2 | 0;
4205 ctx.fillText(buf, 0, y);
4206 y += line.height - 1;
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;
4217 ctx.fillText(buf, x, y);
4218 y += line.height - 1;
4222 domRender: function(element) {
4223 if (element.innerHTML !== this._text) {
4224 element.innerHTML = this._text;
4227 detectRender: function(ctx) {
4228 ctx.fillRect(this._boundOffset, 0, this._boundWidth, this._boundHeight);
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;
4239 this._boundOffset = 0;
4242 getMetrics: function(text) {
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];
4252 text = text || this._text;
4253 div.innerHTML = text.replace(/ /g, ' ');
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);
4262 ret.width = this.width;
4263 ret.height = this.height;
4270 * @scope enchant.Map.prototype
4272 enchant.Map = enchant.Class.create(enchant.Entity, {
4277 * タイルセットからマップを生成して表示するクラス.
4279 * @param {Number} tileWidth タイルの横幅.
4280 * @param {Number} tileHeight タイルの高さ.
4283 * A class to create and display maps from a tile set.
4285 * @param {Number} tileWidth Tile width.
4286 * @param {Number} tileHeight Tile height.
4289 * Eine Klasse mit der Karten aus Kacheln (Tiles)
4290 * erstellt und angezeigt werden können.
4292 * @param {Number} tileWidth Kachelbreite.
4293 * @param {Number} tileHeight Kachelhöhe.
4296 * @extends enchant.Entity
4298 initialize: function(tileWidth, tileHeight) {
4299 var core = enchant.Core.instance;
4301 enchant.Entity.call(this);
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)';
4313 canvas.width = core.width;
4314 canvas.height = core.height;
4316 this._context = canvas.getContext('2d');
4318 this._tileWidth = tileWidth || 0;
4319 this._tileHeight = tileHeight || 0;
4326 this._dirty = false;
4327 this._tight = false;
4329 this.touchEnabled = false;
4333 * タイルが衝突判定を持つかを表す値の二元配列.
4336 * Two dimensional array to store if collision detection should be performed for a tile.
4339 * Ein 2-Dimensionales Array um zu speichern, ob für eine Kachel
4340 * Kollesionsdetektion durchgeführt werden soll.
4342 * @type {Array.<Array.<Number>>}
4344 this.collisionData = null;
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) {
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;
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;
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);
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);
4408 this.redraw(sw, 0, core.width - sw, core.height);
4410 this.redraw(0, 0, core.width - sw, core.height);
4413 this.redraw(0, sh, core.width, core.height - sh);
4415 this.redraw(0, 0, core.width, core.height - sh);
4418 this.redraw(0, 0, core.width, core.height);
4421 this.redraw(0, 0, core.width, core.height);
4424 this._previousOffsetX = this._offsetX;
4425 this._previousOffsetY = this._offsetY;
4431 * タイルががimageプロパティの画像に左上から順に配列されていると見て, 0から始まる
4432 * インデックスの二元配列を設定する.複数指定された場合は後のものから順に表示される.
4433 * @param {...Array<Array.<Number>>} 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.
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.
4450 loadData: function(data) {
4451 this._data = Array.prototype.slice.apply(arguments);
4454 this._tight = false;
4455 for (var i = 0, len = this._data.length; i < len; i++) {
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) {
4465 if (c / (data.length * data[0].length) > 0.2) {
4474 * @param {Number} x マップ上の点のx座標.
4475 * @param {Number} y マップ上の点のy座標.
4476 * @return {*} ある座標のタイルのデータ.
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.
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.
4491 checkTile: function(x, y) {
4492 if (x < 0 || this.width <= x || y < 0 || this.height <= y) {
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];
4507 * Map上に障害物があるかどうかを判定する.
4508 * @param {Number} x 判定を行うマップ上の点のx座標.
4509 * @param {Number} y 判定を行うマップ上の点のy座標.
4510 * @return {Boolean} 障害物があるかどうか.
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.
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.
4525 hitTest: function(x, y) {
4526 if (x < 0 || this.width <= x || y < 0 || this.height <= y) {
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];
4538 for (var i = 0, len = this._data.length; i < len; i++) {
4539 var data = this._data[i];
4541 if (data[y] != null && (n = data[y][x]) != null &&
4542 0 <= n && n < (width / tileWidth | 0) * (height / tileHeight | 0)) {
4554 * Image with which the tile set is displayed on the map.
4557 * Das Bild mit dem die Kacheln auf der Karte dargestellt werden.
4559 * @type {enchant.Surface}
4565 set: function(image) {
4566 var core = enchant.Core.instance;
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);
4581 this._doubledImage = img;
4600 return this._tileWidth;
4602 set: function(tileWidth) {
4603 this._tileWidth = tileWidth;
4621 return this._tileHeight;
4623 set: function(tileHeight) {
4624 this._tileHeight = tileHeight;
4633 return this._tileWidth * this._data[0][0].length;
4641 return this._tileHeight * this._data[0].length;
4647 redraw: function(x, y, width, height) {
4648 if (this._image == null) {
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;
4664 image = this._image;
4665 tileWidth = this._tileWidth;
4666 tileHeight = this._tileHeight;
4667 dx = -this._offsetX;
4668 dy = -this._offsetY;
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);
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++) {
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);
4698 cvsRender: function(ctx) {
4699 var core = enchant.Core.instance;
4700 if (this.width !== 0 && this.height !== 0) {
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);
4708 domRender: function(element) {
4710 this._style['background-image'] = this._surface._css;
4712 this._style[enchant.ENV.VENDOR_PREFIX + 'Transform'] = 'matrix(1, 0, 0, 1, 0, 0)';
4719 * @scope enchant.Group.prototype
4721 enchant.Group = enchant.Class.create(enchant.Node, {
4723 * @name enchant.Group
4726 * 複数の{@link enchant.Node}を子に持つことができるクラス.
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;
4740 * @extends enchant.Node
4743 * A class that can hold multiple {@link enchant.Node}.
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;
4759 * Eine Klasse die mehrere {@link enchant.Node} beinhalten kann.
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;
4775 * @extends enchant.Node
4777 initialize: function() {
4788 * @type {Array.<enchant.Node>}
4790 this.childNodes = [];
4792 enchant.Node.call(this);
4798 this._originX = null;
4799 this._originY = null;
4801 this.__dirty = false;
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);
4816 * @param {enchant.Node} node 追加するNode.
4819 * Adds a Node to the Group.
4820 * @param {enchant.Node} node Node to be added.
4823 * Fügt einen Node zu der Gruppe hinzu.
4824 * @param {enchant.Node} node Node der hinzugeügt werden soll.
4827 addChild: function(node) {
4828 if (node.parentNode) {
4829 node.parentNode.removeChild(node);
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'));
4839 node.scene = this.scene;
4840 var addedToScene = new enchant.Event('addedtoscene');
4841 node.dispatchEvent(addedToScene);
4847 * @param {enchant.Node} node 挿入するNode.
4848 * @param {enchant.Node} reference 挿入位置の前にあるNode.
4851 * Incorporates Node into Group.
4852 * @param {enchant.Node} node Node to be incorporated.
4853 * @param {enchant.Node} reference Node in position before insertion.
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.
4861 insertBefore: function(node, reference) {
4862 if (node.parentNode) {
4863 node.parentNode.removeChild(node);
4865 var i = this.childNodes.indexOf(reference);
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'));
4875 node.scene = this.scene;
4876 var addedToScene = new enchant.Event('addedtoscene');
4877 node.dispatchEvent(addedToScene);
4880 this.addChild(node);
4886 * @param {enchant.Node} node 削除するNode.
4889 * Remove a Node from the Group.
4890 * @param {enchant.Node} node Node to be deleted.
4893 * Entfernt einen Node aus der Gruppe.
4894 * @param {enchant.Node} node Der Node der entfernt werden soll.
4897 removeChild: function(node) {
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'));
4908 var removedFromScene = new enchant.Event('removedfromscene');
4909 node.dispatchEvent(removedFromScene);
4918 * The Node which is the first child.
4921 * Der Node, welcher das erste Kind der Gruppe darstellt.
4923 * @type {enchant.Node}
4927 return this.childNodes[0];
4935 * The Node which is the last child.
4938 * Der Node, welcher das letzte Kind der Gruppe darstellt.
4940 * @type {enchant.Node}
4944 return this.childNodes[this.childNodes.length - 1];
4952 * Group rotation angle (degree).
4955 * Rotationswinkel der Gruppe (Grad).
4961 return this._rotation;
4963 set: function(rotation) {
4964 this._rotation = rotation;
4973 * Scaling factor on the x axis of the Group.
4976 * Skalierungsfaktor auf der x-Achse der Gruppe.
4979 * @see enchant.CanvasGroup.originX
4980 * @see enchant.CanvasGroup.originY
4984 return this._scaleX;
4986 set: function(scale) {
4987 this._scaleX = scale;
4996 * Scaling factor on the y axis of the Group.
4999 * Skalierungsfaktor auf der y-Achse der Gruppe.
5002 * @see enchant.CanvasGroup.originX
5003 * @see enchant.CanvasGroup.originY
5007 return this._scaleY;
5009 set: function(scale) {
5010 this._scaleY = scale;
5019 * origin point of rotation, scaling
5022 * Ausgangspunkt für Rotation und Skalierung.
5028 return this._originX;
5030 set: function(originX) {
5031 this._originX = originX;
5040 * origin point of rotation, scaling
5043 * Ausgangspunkt für Rotation und Skalierung.
5049 return this._originY;
5051 set: function(originY) {
5052 this._originY = originY;
5058 return this.__dirty;
5060 set: function(dirty) {
5062 this.__dirty = dirty;
5064 for (var i = 0, l = this.childNodes.length; i < l; i++) {
5065 this.childNodes[i]._dirty = true;
5072 enchant.Matrix = enchant.Class.create({
5073 initialize: function() {
5078 this.stack.push([ 1, 0, 0, 1, 0, 0 ]);
5080 makeTransformMatrix: function(node, dest) {
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;
5101 dest[4] = (-a * w + c * h + x + w);
5102 dest[5] = (-b * w - d * h + y + h);
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];
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;
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;
5125 enchant.Matrix.instance = new enchant.Matrix();
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;
5137 attachDetectColor: function(sprite) {
5138 var i = this.reference.indexOf(null);
5142 this.reference[i] = sprite;
5143 return this._getColor(i);
5145 detachDetectColor: function(sprite) {
5146 var i = this.reference.indexOf(sprite);
5148 this.reference[i] = null;
5151 _getColor: function(n) {
5152 var C = this.colorResolution;
5153 var d = C / this.max;
5155 parseInt((n / C / C) % C, 10) / d,
5156 parseInt((n / C) % C, 10) / d,
5157 parseInt(n % C, 10) / d,
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);
5167 getSpriteByColor: function(color) {
5168 return this.reference[this._decodeDetectColor(color)];
5172 enchant.DomManager = enchant.Class.create({
5173 initialize: function(node, elementDefinition) {
5174 var core = enchant.Core.instance;
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;
5182 this.style = this.element.style;
5183 this.style.position = 'absolute';
5184 this.style[enchant.ENV.VENDOR_PREFIX + 'TransformOrigin'] = '0px 0px';
5186 this.style.border = '1px solid blue';
5187 this.style.margin = '-1px';
5191 this._setDomTarget = function() {
5192 manager.layer._touchEventTarget = manager.targetNode;
5194 this._attachEvent();
5196 getDomElement: function() {
5197 return this.element;
5199 getDomElementAsNext: function() {
5200 return this.element;
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;
5210 addManager: function(childManager, nextManager) {
5213 nextElement = nextManager.getDomElementAsNext();
5215 var element = childManager.getDomElement();
5216 if (element instanceof Array) {
5217 element.forEach(function(child) {
5219 this.element.insertBefore(child, nextElement);
5221 this.element.appendChild(child);
5226 this.element.insertBefore(element, nextElement);
5228 this.element.appendChild(element);
5231 this.setLayer(this.layer);
5233 removeManager: function(childManager) {
5234 if (childManager instanceof enchant.DomlessManager) {
5235 childManager._domRef.forEach(function(element) {
5236 this.element.removeChild(element);
5239 this.element.removeChild(childManager.element);
5241 this.setLayer(this.layer);
5243 setLayer: function(layer) {
5245 var node = this.targetNode;
5247 if (node.childNodes) {
5248 for (var i = 0, l = node.childNodes.length; i < l; i++) {
5249 manager = node.childNodes[i]._domManager;
5251 manager.setLayer(layer);
5256 render: function(inheritMat) {
5257 var node = this.targetNode;
5258 var matrix = enchant.Matrix.instance;
5259 var stack = matrix.stack;
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);
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;
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) +
5288 domRender: function() {
5289 var node = this.targetNode;
5293 if(!node.__styleStatus) {
5294 node.__styleStatus = {};
5296 if (node.width !== null) {
5297 node._style.width = node.width + 'px';
5299 if (node.height !== null) {
5300 node._style.height = node.height + 'px';
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';
5307 if (typeof node.domRender === 'function') {
5308 node.domRender(this.element);
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;
5319 _attachEvent: function() {
5320 if (enchant.ENV.TOUCH_ENABLED) {
5321 this.element.addEventListener('touchstart', this._setDomTarget, true);
5323 this.element.addEventListener('mousedown', this._setDomTarget, true);
5325 _detachEvent: function() {
5326 if (enchant.ENV.TOUCH_ENABLED) {
5327 this.element.removeEventListener('touchstart', this._setDomTarget, true);
5329 this.element.removeEventListener('mousedown', this._setDomTarget, true);
5331 remove: function() {
5332 this._detachEvent();
5333 this.element = this.style = this.targetNode = null;
5337 enchant.DomlessManager = enchant.Class.create({
5338 initialize: function(node) {
5340 this.targetNode = node;
5342 _register: function(element, nextElement) {
5343 var i = this._domRef.indexOf(nextElement);
5345 if (element instanceof Array) {
5347 Array.prototype.push.apply(this._domRef, element);
5349 Array.prototype.splice.apply(this._domRef, [i, 0].concat(element));
5353 this._domRef.push(element);
5355 this._domRef.splice(i, 0, element);
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;
5367 getDomElement: function() {
5369 this.targetNode.childNodes.forEach(function(child) {
5370 ret = ret.concat(child._domManager.getDomElement());
5374 getDomElementAsNext: function() {
5375 if (this._domRef.length) {
5376 return this._domRef[0];
5378 var nextManager = this.getNextManager(this);
5380 return nextManager.element;
5386 addManager: function(childManager, nextManager) {
5387 var parentNode = this.targetNode.parentNode;
5389 if (nextManager === null) {
5390 nextManager = this.getNextManager(this);
5392 if (parentNode instanceof enchant.Scene) {
5393 parentNode._layers.Dom._domManager.addManager(childManager, nextManager);
5395 parentNode._domManager.addManager(childManager, nextManager);
5398 var nextElement = nextManager ? nextManager.getDomElementAsNext() : null;
5399 this._register(childManager.getDomElement(), nextElement);
5400 this.setLayer(this.layer);
5402 removeManager: function(childManager) {
5404 var i = this._domRef.indexOf(childManager.element);
5406 dom = this._domRef[i];
5407 dom.parentNode.removeChild(dom);
5408 this._domRef.splice(i, 1);
5410 this.setLayer(this.layer);
5412 setLayer: function(layer) {
5414 var node = this.targetNode;
5416 if (node.childNodes) {
5417 for (var i = 0, l = node.childNodes.length; i < l; i++) {
5418 manager = node.childNodes[i]._domManager;
5420 manager.setLayer(layer);
5425 render: function(inheritMat) {
5426 var matrix = enchant.Matrix.instance;
5427 var stack = matrix.stack;
5428 var node = this.targetNode;
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;
5442 remove: function() {
5444 this.targetNode = null;
5448 enchant.DomLayer = enchant.Class.create(enchant.Group, {
5449 initialize: function() {
5450 var core = enchant.Core.instance;
5451 enchant.Group.call(this);
5453 this._touchEventTarget = null;
5455 this._element = document.createElement('div');
5456 this._element.style.position = 'absolute';
5458 this._domManager = new enchant.DomManager(this, this._element);
5459 this._domManager.layer = this;
5461 this.width = core.width;
5462 this.height = core.height;
5465 enchant.Event.TOUCH_START,
5466 enchant.Event.TOUCH_MOVE,
5467 enchant.Event.TOUCH_END
5470 touch.forEach(function(type) {
5471 this.addEventListener(type, function(e) {
5473 this._scene.dispatchEvent(e);
5478 var __onchildadded = function(e) {
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);
5490 var __onchildremoved = function(e) {
5492 var self = e.target;
5493 self._domManager.removeManager(child._domManager);
5494 enchant.DomLayer._detachDomManager(child, __onchildadded, __onchildremoved);
5497 this.addEventListener('childremoved', __onchildremoved);
5498 this.addEventListener('childadded', __onchildadded);
5505 set: function(width) {
5506 this._width = width;
5507 this._element.style.width = width + 'px';
5512 return this._height;
5514 set: function(height) {
5515 this._height = height;
5516 this._element.style.height = height + 'px';
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'));
5528 node.scene = this.scene;
5529 var addedToScene = new enchant.Event('addedtoscene');
5530 node.dispatchEvent(addedToScene);
5533 insertBefore: function(node, reference) {
5534 var i = this.childNodes.indexOf(reference);
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'));
5544 node.scene = this.scene;
5545 var addedToScene = new enchant.Event('addedtoscene');
5546 node.dispatchEvent(addedToScene);
5549 this.addChild(node);
5552 _startRendering: function() {
5553 this.addEventListener('exitframe', this._onexitframe);
5554 this._onexitframe();
5556 _stopRendering: function() {
5557 this.removeEventListener('exitframe', this._onexitframe);
5558 this._onexitframe();
5560 _onexitframe: function() {
5561 this._rendering(this, new enchant.Event(enchant.Event.RENDER));
5563 _rendering: function(node, e, inheritMat) {
5566 inheritMat = [ 1, 0, 0, 1, 0, 0 ];
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());
5576 if (node._domManager instanceof enchant.DomlessManager) {
5577 enchant.Matrix.instance.stack.pop();
5579 node._dirty = false;
5581 _determineEventTarget: function() {
5582 var target = this._touchEventTarget;
5583 this._touchEventTarget = null;
5584 return (target === this) ? null : target;
5588 enchant.DomLayer._attachDomManager = function(node, onchildadded, onchildremoved) {
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);
5596 if (node._element) {
5597 node._domManager = new enchant.DomManager(node, node._element);
5599 node._domManager = new enchant.DomManager(node, 'div');
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);
5612 enchant.DomLayer._detachDomManager = function(node, onchildadded, onchildremoved) {
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);
5623 node._domManager.remove();
5624 delete node._domManager;
5628 * @scope enchant.CanvasLayer.prototype
5630 enchant.CanvasLayer = enchant.Class.create(enchant.Group, {
5632 * @name enchant.CanvasLayer
5635 * Canvas を用いた描画を行うクラス.
5636 * 子を Canvas を用いた描画に切り替えるクラス
5639 * A class which is using HTML Canvas for the rendering.
5640 * The rendering of children will be replaced by the Canvas rendering.
5643 * Eine Klasse die HTML Canvas für das Rendern nutzt.
5644 * Das Rendern der Kinder wird durch das Canvas Rendering ersetzt.
5648 initialize: function() {
5649 var core = enchant.Core.instance;
5651 enchant.Group.call(this);
5654 matrix: [1, 0, 0, 1, 0, 0],
5655 detectColor: '#000000'
5657 this._cvsCache.layer = this;
5659 this._element = document.createElement('canvas');
5660 this._element.style.position = 'absolute';
5662 this._element.style.left = this._element.style.top = '0px';
5664 this._detect = document.createElement('canvas');
5665 this._detect.style.position = 'absolute';
5666 this._lastDetected = 0;
5668 this.context = this._element.getContext('2d');
5669 this._dctx = this._detect.getContext('2d');
5671 this._colorManager = new enchant.DetectColorManager(16, 256);
5673 this.width = core.width;
5674 this.height = core.height;
5677 enchant.Event.TOUCH_START,
5678 enchant.Event.TOUCH_MOVE,
5679 enchant.Event.TOUCH_END
5682 touch.forEach(function(type) {
5683 this.addEventListener(type, function(e) {
5685 this._scene.dispatchEvent(e);
5690 var __onchildadded = function(e) {
5692 var self = e.target;
5694 if (self instanceof enchant.CanvasLayer) {
5695 layer = self._scene._layers.Canvas;
5697 layer = self.scene._layers.Canvas;
5699 enchant.CanvasLayer._attachCache(child, layer, __onchildadded, __onchildremoved);
5700 var render = new enchant.Event(enchant.Event.RENDER);
5702 self._updateCoordinate();
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);
5710 var __onchildremoved = function(e) {
5712 var self = e.target;
5714 if (self instanceof enchant.CanvasLayer) {
5715 layer = self._scene._layers.Canvas;
5717 layer = self.scene._layers.Canvas;
5719 enchant.CanvasLayer._detachCache(child, layer, __onchildadded, __onchildremoved);
5722 this.addEventListener('childremoved', __onchildremoved);
5723 this.addEventListener('childadded', __onchildadded);
5730 set: function(width) {
5731 this._width = width;
5732 this._element.width = this._detect.width = width;
5737 return this._height;
5739 set: function(height) {
5740 this._height = height;
5741 this._element.height = this._detect.height = height;
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'));
5753 node.scene = this.scene;
5754 var addedToScene = new enchant.Event('addedtoscene');
5755 node.dispatchEvent(addedToScene);
5758 insertBefore: function(node, reference) {
5759 var i = this.childNodes.indexOf(reference);
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'));
5769 node.scene = this.scene;
5770 var addedToScene = new enchant.Event('addedtoscene');
5771 node.dispatchEvent(addedToScene);
5774 this.addChild(node);
5783 _startRendering: function() {
5784 this.addEventListener('exitframe', this._onexitframe);
5785 this._onexitframe(new enchant.Event(enchant.Event.RENDER));
5793 _stopRendering: function() {
5794 this.removeEventListener('render', this._onexitframe);
5795 this._onexitframe(new enchant.Event(enchant.Event.RENDER));
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);
5804 _determineEventTarget: function(e) {
5805 return this._getEntityByPosition(e.x, e.y);
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;
5815 var color = ctx.getImageData(x, y, 1, 1).data;
5816 return this._colorManager.getSpriteByColor(color);
5820 enchant.CanvasLayer._attachCache = function(node, layer, onchildadded, onchildremoved) {
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);
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);
5837 enchant.CanvasLayer._detachCache = function(node, layer, onchildadded, onchildremoved) {
5839 if (node._cvsCache) {
5840 layer._colorManager.detachDetectColor(node);
5841 node.removeEventListener('childadded', onchildadded);
5842 node.removeEventListener('childremoved', onchildremoved);
5843 delete node._cvsCache;
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);
5853 enchant.CanvasRenderer = enchant.Class.create({
5854 render: function(ctx, node, e) {
5855 var width, height, child;
5857 node.dispatchEvent(e);
5859 this.transform(ctx, node);
5860 if (typeof node._visible === 'undefined' || node._visible) {
5862 height = node.height;
5864 if (node.compositeOperation) {
5865 ctx.globalCompositeOperation = node.compositeOperation;
5867 ctx.globalAlpha = (typeof node._opacity === 'number') ? node._opacity : 1.0;
5869 if (node._backgroundColor) {
5870 ctx.fillStyle = node._backgroundColor;
5871 ctx.fillRect(0, 0, width, height);
5874 if (node.cvsRender) {
5875 node.cvsRender(ctx);
5878 if (enchant.Core.instance._debug && node._debugColor) {
5879 ctx.strokeStyle = node._debugColor;
5880 ctx.strokeRect(0, 0, width, height);
5882 if (node._clipping) {
5884 ctx.rect(0, 0, width, height);
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);
5895 enchant.Matrix.instance.stack.pop();
5897 detectRender: function(ctx, node) {
5898 var width, height, child;
5899 if (typeof node._visible === 'undefined' || node._visible) {
5901 height = node.height;
5903 this.transform(ctx, node);
5904 ctx.fillStyle = node._cvsCache.detectColor;
5905 if (node._touchEnabled) {
5906 if (node.detectRender) {
5907 node.detectRender(ctx);
5909 ctx.fillRect(0, 0, width, height);
5912 if (node._clipping) {
5914 ctx.rect(0, 0, width, height);
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);
5924 enchant.Matrix.instance.stack.pop();
5927 transform: function(ctx, node) {
5928 var matrix = enchant.Matrix.instance;
5929 var stack = matrix.stack;
5930 var newmat, ox, oy, vec;
5932 matrix.makeTransformMatrix(node, node._cvsCache.matrix);
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;
5939 matrix.multiplyVec(newmat, vec, vec);
5940 node._offsetX = vec[0] - ox;
5941 node._offsetY = vec[1] - oy;
5942 node._dirty = false;
5944 newmat = node._matrix;
5947 ctx.setTransform.apply(ctx, newmat);
5950 enchant.CanvasRenderer.instance = new enchant.CanvasRenderer();
5953 * @scope enchant.Scene.prototype
5956 enchant.Scene = enchant.Class.create(enchant.Group, {
5958 * @name enchant.Scene
5961 * 表示オブジェクトツリーのルートになるクラス.
5962 * シーンはレイヤーを持っていて、子として追加されたオブジェクト (Entity) は描画方法に応じてレイヤーに振り分けられる。
5963 * Scene クラスは最も汎用的なシーンの実装で、({@link enchant.DOMLayer} と {@link enchant.CanvasLayer}) を持っており、
5964 * それぞれ DOM, Canvas を用いて描画される。描画順は DOM が手前、Canvas が奥で、
5965 * 各レイヤーの間では新しく追加されたオブジェクトほど手前に表示される。
5966 * Scene クラスを継承することで、新しい種類の Layer を持つシーンクラスを作ることができる。
5969 * A Class that becomes the root of the display object tree.
5972 * Eine Klasse die zur Wurzel im Darstellungsobjektbaum wird.
5976 * var scene = new Scene();
5977 * scene.addChild(player);
5978 * scene.addChild(enemy);
5979 * core.pushScene(scene);
5982 * @extends enchant.Group
5984 initialize: function() {
5985 var core = enchant.Core.instance;
5987 // Call initialize method of enchant.Group
5988 enchant.Group.call(this);
5990 // All nodes (entities, groups, scenes) have reference to the scene that it belongs to.
5993 this._backgroundColor = null;
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';
6002 this._layerPriority = [];
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);
6010 this._dispatchExitframe = function() {
6012 for (var prop in that._layers) {
6013 layer = that._layers[prop];
6014 layer.dispatchEvent(new enchant.Event(enchant.Event.EXIT_FRAME));
6018 this.addEventListener(enchant.Event.CORE_RESIZE, this._oncoreresize);
6020 this._oncoreresize(core);
6028 for (var type in this._layers) {
6029 this._layers[type].x = x;
6039 for (var type in this._layers) {
6040 this._layers[type].y = y;
6048 set: function(width) {
6049 this._width = width;
6050 for (var type in this._layers) {
6051 this._layers[type].width = width;
6057 return this._height;
6059 set: function(height) {
6060 this._height = height;
6061 for (var type in this._layers) {
6062 this._layers[type].height = height;
6068 return this._rotation;
6070 set: function(rotation) {
6071 this._rotation = rotation;
6072 for (var type in this._layers) {
6073 this._layers[type].rotation = rotation;
6079 return this._scaleX;
6081 set: function(scaleX) {
6082 this._scaleX = scaleX;
6083 for (var type in this._layers) {
6084 this._layers[type].scaleX = scaleX;
6090 return this._scaleY;
6092 set: function(scaleY) {
6093 this._scaleY = scaleY;
6094 for (var type in this._layers) {
6095 this._layers[type].scaleY = scaleY;
6101 return this._backgroundColor;
6103 set: function(color) {
6104 this._backgroundColor = this._element.style.backgroundColor = color;
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 + ')';
6114 for (var type in this._layers) {
6115 this._layers[type].dispatchEvent(e);
6118 addLayer: function(type, i) {
6119 var core = enchant.Core.instance;
6120 if (this._layers[type]) {
6123 var layer = new enchant[type + 'Layer']();
6124 if (core.currentScene === this) {
6125 layer._startRendering();
6127 this._layers[type] = layer;
6128 var element = layer._element;
6129 if (typeof i === 'number') {
6130 var nextSibling = this._element.childNodes[i];
6132 this._element.insertBefore(element, nextSibling);
6134 this._element.appendChild(element);
6136 this._layerPriority.splice(i, 0, type);
6138 this._element.appendChild(element);
6139 this._layerPriority.push(type);
6141 layer._scene = this;
6143 _determineEventTarget: function(e) {
6145 for (var i = this._layerPriority.length - 1; i >= 0; i--) {
6146 layer = this._layers[this._layerPriority[i]];
6147 target = layer._determineEventTarget(e);
6157 _onchildadded: function(e) {
6161 if (child._element) {
6168 if (!this._layers[target]) {
6169 this.addLayer(target, i);
6171 child._layer = this._layers[target];
6172 this._layers[target].insertBefore(child, next);
6173 child.parentNode = this;
6175 _onchildremoved: function(e) {
6177 child._layer.removeChild(child);
6178 child._layer = null;
6180 _onenter: function() {
6181 for (var type in this._layers) {
6182 this._layers[type]._startRendering();
6184 enchant.Core.instance.addEventListener('exitframe', this._dispatchExitframe);
6186 _onexit: function() {
6187 for (var type in this._layers) {
6188 this._layers[type]._stopRendering();
6190 enchant.Core.instance.removeEventListener('exitframe', this._dispatchExitframe);
6195 * @scope enchant.LoadingScene.prototype
6197 enchant.LoadingScene = enchant.Class.create(enchant.Scene, {
6199 * @name enchant.LoadingScene.
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.
6207 * enchant.LoadingScene = enchant.Class.create(enchant.Scene, {
6208 * initialize: function(){
6209 * enchant.Scene.call(this);
6210 * this.backgroundColor = 'red';
6212 * this.addEventListener('progress', function(e){
6213 * progress = e.loaded / e.total;
6215 * this.addEventListener('enterframe', function(){
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);
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;
6242 bar.addEventListener('enterframe', function() {
6244 _progress += progress * 0.1;
6245 image.context.fillStyle = '#fff';
6246 image.context.fillRect(border, 0, (barWidth - border * 2) * _progress, barHeight);
6249 this.addEventListener('load', function(e) {
6250 var core = enchant.Core.instance;
6251 core.removeScene(core.loadingScene);
6252 core.dispatchEvent(e);
6258 * @scope enchant.CanvasScene.prototype
6261 enchant.CanvasScene = enchant.Class.create(enchant.Scene, {
6262 initialize: function() {
6263 enchant.Scene.call(this);
6264 this.addLayer('Canvas');
6266 _determineEventTarget: function(e) {
6267 var target = this._layers.Canvas._determineEventTarget(e);
6273 _onchildadded: function(e) {
6276 child._layer = this._layers.Canvas;
6277 this._layers.Canvas.insertBefore(child, next);
6279 _onenter: function() {
6280 this._layers.Canvas._startRendering();
6281 enchant.Core.instance.addEventListener('exitframe', this._dispatchExitframe);
6283 _onexit: function() {
6284 this._layers.Canvas._stopRendering();
6285 enchant.Core.instance.removeEventListener('exitframe', this._dispatchExitframe);
6290 * @scope enchant.CanvasScene.prototype
6293 enchant.DOMScene = enchant.Class.create(enchant.Scene, {
6294 initialize: function() {
6295 enchant.Scene.call(this);
6296 this.addLayer('Dom');
6298 _determineEventTarget: function(e) {
6299 var target = this._layers.Dom._determineEventTarget(e);
6305 _onchildadded: function(e) {
6308 child._layer = this._layers.Dom;
6309 this._layers.Dom.insertBefore(child, next);
6311 _onenter: function() {
6312 this._layers.Dom._startRendering();
6313 enchant.Core.instance.addEventListener('exitframe', this._dispatchExitframe);
6315 _onexit: function() {
6316 this._layers.Dom._stopRendering();
6317 enchant.Core.instance.removeEventListener('exitframe', this._dispatchExitframe);
6322 * @scope enchant.Surface.prototype
6324 enchant.Surface = enchant.Class.create(enchant.EventTarget, {
6326 * @name enchant.Surface
6329 * canvas要素をラップしたクラス.
6331 * {@link enchant.Sprite}や{@link enchant.Map}のimageプロパティに設定して表示させることができる.
6332 * Canvas APIにアクセスしたいときは{@link enchant.Surface#context}プロパティを用いる.
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;
6343 * @param {Number} width Surfaceの横幅.
6344 * @param {Number} height Surfaceの高さ.
6347 * Class that wraps canvas elements.
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.
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;
6361 * @param {Number} width Surface width.
6362 * @param {Number} height Surface height.
6365 * Diese Klasse dient als Hüllenklasse (Wrapper) für Canvas Elemente.
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.
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;
6381 * @param {Number} width Die Breite der Surface.
6382 * @param {Number} height Die Höhe der Surface.
6386 initialize: function(width, height) {
6387 enchant.EventTarget.call(this);
6389 var core = enchant.Core.instance;
6399 * Die Breite der Surface.
6412 * Die Höhe der Surface.
6416 this.height = height;
6422 * Surface drawing context.
6425 * Der Surface Zeichenkontext.
6427 * @type {CanvasRenderingContext2D}
6429 this.context = null;
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);
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');
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);
6462 * Surfaceから1ピクセル取得する.
6463 * @param {Number} x 取得するピクセルのx座標.
6464 * @param {Number} y 取得するピクセルのy座標.
6465 * @return {Array.<Number>} ピクセルの情報を[r, g, b, a]の形式で持つ配列.
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.
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.
6480 getPixel: function(x, y) {
6481 return this.context.getImageData(x, y, 1, 1).data;
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 設定するピクセルの透明度.
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.
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
6512 setPixel: function(x, y, r, g, b, a) {
6513 var pixel = this.context.createImageData(1, 1);
6518 this.context.putImageData(pixel, x, y);
6522 * Surfaceの全ピクセルをクリアし透明度0の黒に設定する.
6525 * Clears all Surface pixels and makes the pixels transparent.
6528 * Löscht alle Pixel und setzt macht die Pixel transparent.
6532 this.context.clearRect(0, 0, this.width, this.height);
6536 * Surfaceに対して引数で指定されたSurfaceを描画する.
6538 * Canvas APIのdrawImageをラップしており, 描画する矩形を同様の形式で指定できる.
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);
6550 * @param {enchant.Surface} image 描画に用いるSurface.
6553 * Draws the content of the given Surface onto this surface.
6555 * Wraps Canvas API drawImage and if multiple arguments are given,
6556 * these are getting applied to the Canvas drawImage method.
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);
6569 * @param {enchant.Surface} image Surface used in drawing.
6572 * Zeichnet den Inhalt der gegebenen Surface auf diese Surface.
6574 * Umhüllt (wraps) die Canvas drawImage Methode und sollten mehrere Argumente
6575 * übergeben werden, werden diese auf die Canvas drawImage Methode angewendet.
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);
6588 * @param {enchant.Surface} image Surface used in drawing.
6591 draw: function(image) {
6592 image = image._element;
6593 if (arguments.length === 1) {
6594 this.context.drawImage(image, 0, 0);
6596 var args = arguments;
6598 this.context.drawImage.apply(this.context, args);
6604 * @return {enchant.Surface} 複製されたSurface.
6608 * @return {enchant.Surface} The copied Surface.
6611 * Kopiert diese Surface.
6612 * @return {enchant.Surface} Die kopierte Surface.
6616 var clone = new enchant.Surface(this.width, this.height);
6622 * SurfaceからdataスキームのURLを生成する.
6623 * @return {String} Surfaceを表すdataスキームのURL.
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.
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.
6636 toDataURL: function() {
6637 var src = this._element.src;
6639 if (src.slice(0, 5) === 'data:') {
6642 return this.clone().toDataURL();
6645 return this._element.toDataURL();
6652 * 画像ファイルを読み込んでSurfaceオブジェクトを作成する.
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 * 場合はピクセルを取得するなど画像操作の一部が制限される).
6661 * @param {String} src ロードする画像ファイルのパス.
6662 * @param {Function} callback ロード完了時のコールバック.
6663 * @param {Function} [onerror] ロード失敗時のコールバック.
6666 * Loads an image and creates a Surface object out of it.
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).
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.
6680 * Läd eine Grafik und erstellt daraus ein Surface Objekt.
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)
6689 * @param {String} src Der Dateipfad der Grafik die geladen werden soll.
6692 * @return {enchant.Surface} Surface
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 }
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);
6711 image.onload = function() {
6712 surface.width = image.width;
6713 surface.height = image.height;
6714 surface.dispatchEvent(new enchant.Event('load'));
6719 enchant.Surface._staticCanvas2DContext = document.createElement('canvas').getContext('2d');
6721 enchant.Surface._getPattern = function(surface, force) {
6722 if (!surface._pattern || force) {
6723 surface._pattern = this._staticCanvas2DContext.createPattern(surface._element, 'repeat');
6725 return surface._pattern;
6728 if (window.Deferred) {
6729 enchant.Deferred = window.Deferred;
6731 enchant.Deferred = enchant.Class.create({
6732 initialize: function() {
6733 this._succ = this._fail = this._next = this._id = null;
6736 next: function(func) {
6737 var q = new enchant.Deferred();
6739 return this._add(q);
6741 error: function(func) {
6742 var q = new enchant.Deferred();
6744 return this._add(q);
6746 _add: function(queue) {
6747 this._tail._next = queue;
6751 call: function(arg) {
6754 while (queue && !queue._succ) {
6755 queue = queue._next;
6757 if (!(queue instanceof enchant.Deferred)) {
6761 received = queue._succ(arg);
6763 return queue.fail(e);
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);
6771 fail: function(arg) {
6774 while (queue && !queue._fail) {
6775 queue = queue._next;
6777 if (queue instanceof enchant.Deferred) {
6778 result = queue._fail(arg);
6780 } else if (arg instanceof Error) {
6783 err = new Error('failed in Deferred');
6789 enchant.Deferred._insert = function(queue, ins) {
6790 if (queue._next instanceof enchant.Deferred) {
6791 ins._next = queue._next;
6795 enchant.Deferred.next = function(func) {
6796 var q = new enchant.Deferred().next(func);
6797 q._id = setTimeout(function() { q.call(); }, 0);
6800 enchant.Deferred.parallel = function(arg) {
6801 var q = new enchant.Deferred();
6802 q._id = setTimeout(function() { q.call(); }, 0);
6804 var ret = (arg instanceof Array) ? [] : {};
6805 var p = new enchant.Deferred();
6806 for (var prop in arg) {
6807 if (arg.hasOwnProperty(prop)) {
6809 /*jshint loopfunc:true */
6810 (function(queue, name) {
6811 queue.next(function(arg) {
6814 if (progress <= 0) {
6818 .error(function(err) { p.fail(err); });
6819 if (typeof queue._id === 'number') {
6820 clearTimeout(queue._id);
6822 queue._id = setTimeout(function() { queue.call(); }, 0);
6823 }(arg[prop], prop));
6827 p._id = setTimeout(function() { p.call(ret); }, 0);
6829 return q.next(function() { return p; });
6834 * @scope enchant.DOMSound.prototype
6837 enchant.DOMSound = enchant.Class.create(enchant.EventTarget, {
6839 * @name enchant.DOMSound
6844 * MP3ファイルの再生はSafari, Chrome, Firefox, Opera, IEが対応
6845 * (Firefox, OperaではFlashを経由して再生). WAVEファイルの再生は
6846 * Safari, Chrome, Firefox, Operaが対応している. ブラウザが音声ファイル
6847 * のコーデックに対応していない場合は再生されない.
6849 * コンストラクタではなく{@link enchant.DOMSound.load}を通じてインスタンスを作成する.
6852 * Class to wrap audio elements.
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.
6859 * Instances are created not via constructor but via {@link enchant.DOMSound.load}.
6862 * Klasse die eine Hüllenklasse (Wrapper) für Audio Elemente darstellt.
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.
6869 * Instanzen dieser Klasse werden nicht mit Hilfe des Konstruktors, sondern mit
6870 * {@link enchant.DOMSound.load} erstellt.
6874 initialize: function() {
6875 enchant.EventTarget.call(this);
6881 * Sound file duration (seconds).
6884 * Die länge der Sounddatei in Sekunden.
6889 throw new Error("Illegal Constructor");
6899 * Startet die Wiedergabe.
6903 if (this._element) {
6904 this._element.play();
6915 * Pausiert die Wiedergabe.
6919 if (this._element) {
6920 this._element.pause();
6931 * Stoppt die Wiedergabe.
6936 this.currentTime = 0;
6941 * @return {enchant.DOMSound} 複製されたSound.
6944 * Create a copy of this Sound object.
6945 * @return {enchant.DOMSound} Copied Sound.
6948 * Erstellt eine Kopie dieses Soundobjektes.
6949 * @return {enchant.DOMSound} Kopiertes Sound Objekt.
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 }
6959 } else if (enchant.ENV.USE_FLASH_SOUND) {
6962 clone = Object.create(enchant.DOMSound.prototype);
6964 enchant.EventTarget.call(clone);
6972 * Current playback position (seconds).
6975 * Aktuelle Wiedergabeposition (seconds).
6981 return this._element ? this._element.currentTime : 0;
6983 set: function(time) {
6984 if (this._element) {
6985 this._element.currentTime = time;
6991 * ボリューム. 0 (無音) ~ 1 (フルボリューム).
6994 * Volume. 0 (muted) ~ 1 (full volume).
6997 * Lautstärke. 0 (stumm) ~ 1 (volle Lautstärke).
7003 return this._element ? this._element.volume : 1;
7005 set: function(volume) {
7006 if (this._element) {
7007 this._element.volume = volume;
7015 * 音声ファイルを読み込んでSoundオブジェクトを作成する.
7017 * @param {String} src ロードする音声ファイルのパス.
7018 * @param {String} [type] 音声ファイルのMIME Type.
7019 * @param {Function} callback ロード完了時のコールバック.
7020 * @param {Function} [onerror] ロード失敗時のコールバック.
7023 * Loads an audio file and creates Sound object.
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.
7031 * Läd eine Audio Datei und erstellt ein Sound objekt.
7033 * @param {String} src Pfad zu der zu ladenden Audiodatei.
7034 * @param {String} [type] MIME Type der Audtiodatei.
7036 * @return {enchant.DOMSound} DOMSound
7039 enchant.DOMSound.load = function(src, type, callback, onerror) {
7041 var ext = enchant.Core.findExt(src);
7043 type = 'audio/' + ext;
7048 type = type.replace('mp3', 'mpeg').replace('m4a', 'mp4');
7049 onerror = onerror || function() {};
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'));
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'));
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);
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;
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, {
7090 return embed.getCurrentTime();
7092 set: function(time) {
7093 embed.setCurrentTime(time);
7098 return embed.getVolume();
7100 set: function(volume) {
7101 embed.setVolume(volume);
7105 sound._element = embed;
7106 sound.duration = embed.getDuration();
7108 enchant.Core.instance._element.appendChild(embed);
7109 enchant.DOMSound[id] = sound;
7111 window.setTimeout(function() {
7112 sound.dispatchEvent(new enchant.Event('load'));
7120 window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext || window.oAudioContext;
7123 * @scope enchant.WebAudioSound.prototype
7126 enchant.WebAudioSound = enchant.Class.create(enchant.EventTarget, {
7128 * @name enchant.WebAudioSound
7130 * Sound wrapper class for Web Audio API (supported on some webkit-based browsers)
7134 initialize: function() {
7135 if(!window.webkitAudioContext){
7136 throw new Error("This browser does not support WebAudio API.");
7138 var actx = enchant.WebAudioSound.audioContext;
7139 enchant.EventTarget.call(this);
7140 this.src = actx.createBufferSource();
7143 this._currentTime = 0;
7145 this.connectTarget = enchant.WebAudioSound.destination;
7147 play: function(dup) {
7148 var actx = enchant.WebAudioSound.audioContext;
7149 if (this._state === 2) {
7150 this.src.connect(this.connectTarget);
7152 if (this._state === 1 && !dup) {
7153 this.src.disconnect(this.connectTarget);
7155 this.src = actx.createBufferSource();
7156 this.src.buffer = this.buffer;
7157 this.src.gain.value = this._volume;
7158 this.src.connect(this.connectTarget);
7164 var actx = enchant.WebAudioSound.audioContext;
7165 this.src.disconnect(this.connectTarget);
7169 this.src.noteOff(0);
7173 var sound = new enchant.WebAudioSound();
7174 sound.buffer = this.buffer;
7180 return this.buffer.dulation;
7188 return this._volume;
7190 set: function(volume) {
7191 volume = Math.max(0, Math.min(1, volume));
7192 this._volume = volume;
7194 this.src.gain.value = volume;
7200 window.console.log('currentTime is not allowed');
7201 return this._currentTime;
7203 set: function(time) {
7204 window.console.log('currentTime is not allowed');
7205 this._currentTime = time;
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;
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(
7228 sound.buffer = buffer;
7229 sound.dispatchEvent(new enchant.Event(enchant.Event.LOAD));
7232 enchant.Core.instance.dispatchEvent(e);
7233 sound.dispatchEvent(e);
7239 setTimeout(function() {
7240 sound.dispatchEvent(e);
7246 if(window.AudioContext){
7247 enchant.WebAudioSound.audioContext = new window.AudioContext();
7248 enchant.WebAudioSound.destination = enchant.WebAudioSound.audioContext.destination;
7251 /* jshint newcap: false */
7253 enchant.Sound = window.AudioContext && enchant.ENV.USE_WEBAUDIO ? enchant.WebAudioSound : enchant.DOMSound;
7256 * ============================================================================================
7257 * Easing Equations v2.0
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 * ============================================================================================
7267 * {@link enchant.Easing} 以下にある関数は全て t(現在の時刻), b(初期値), c(変化後の値), d(値の変化にかける時間) の引数を取り、指定した時刻に取る値を返す。
7268 * ActionScript で広く使われている Robert Penner による Easing Equations を JavaScript に移植した。
7270 * @see http://www.robertpenner.com/easing/
7271 * @see http://www.robertpenner.com/easing/penner_chapter7_tweening.pdf
7276 * Easing function library, from "Easing Equations" by Robert Penner.
7279 * {@link enchant.Tween} クラスで用いるイージング関数のライブラリ名前空間.
7289 LINEAR: function(t, b, c, d) {
7290 return c * t / d + b;
7299 SWING: function(t, b, c, d) {
7300 return c * (0.5 - Math.cos(((t / d) * Math.PI)) / 2) + b;
7310 QUAD_EASEIN: function(t, b, c, d) {
7311 return c * (t /= d) * t + b;
7320 QUAD_EASEOUT: function(t, b, c, d) {
7321 return -c * (t /= d) * (t - 2) + b;
7330 QUAD_EASEINOUT: function(t, b, c, d) {
7331 if ((t /= d / 2) < 1) {
7332 return c / 2 * t * t + b;
7334 return -c / 2 * ((--t) * (t - 2) - 1) + b;
7344 CUBIC_EASEIN: function(t, b, c, d) {
7345 return c * (t /= d) * t * t + b;
7354 CUBIC_EASEOUT: function(t, b, c, d) {
7355 return c * ((t = t / d - 1) * t * t + 1) + b;
7364 CUBIC_EASEINOUT: function(t, b, c, d) {
7365 if ((t /= d / 2) < 1) {
7366 return c / 2 * t * t * t + b;
7368 return c / 2 * ((t -= 2) * t * t + 2) + b;
7378 QUART_EASEIN: function(t, b, c, d) {
7379 return c * (t /= d) * t * t * t + b;
7388 QUART_EASEOUT: function(t, b, c, d) {
7389 return -c * ((t = t / d - 1) * t * t * t - 1) + b;
7398 QUART_EASEINOUT: function(t, b, c, d) {
7399 if ((t /= d / 2) < 1) {
7400 return c / 2 * t * t * t * t + b;
7402 return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
7412 QUINT_EASEIN: function(t, b, c, d) {
7413 return c * (t /= d) * t * t * t * t + b;
7422 QUINT_EASEOUT: function(t, b, c, d) {
7423 return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
7432 QUINT_EASEINOUT: function(t, b, c, d) {
7433 if ((t /= d / 2) < 1) {
7434 return c / 2 * t * t * t * t * t + b;
7436 return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;
7446 SIN_EASEIN: function(t, b, c, d) {
7447 return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;
7456 SIN_EASEOUT: function(t, b, c, d) {
7457 return c * Math.sin(t / d * (Math.PI / 2)) + b;
7466 SIN_EASEINOUT: function(t, b, c, d) {
7467 return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;
7477 CIRC_EASEIN: function(t, b, c, d) {
7478 return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;
7487 CIRC_EASEOUT: function(t, b, c, d) {
7488 return c * Math.sqrt(1 - (t = t / d - 1) * t) + b;
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;
7501 return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;
7511 ELASTIC_EASEIN: function(t, b, c, d, a, p) {
7515 if ((t /= d) === 1) {
7524 if (!a || a < Math.abs(c)) {
7528 s = p / (2 * Math.PI) * Math.asin(c / a);
7530 return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
7539 ELASTIC_EASEOUT: function(t, b, c, d, a, p) {
7543 if ((t /= d) === 1) {
7550 if (!a || a < Math.abs(c)) {
7554 s = p / (2 * Math.PI) * Math.asin(c / a);
7556 return (a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b);
7565 ELASTIC_EASEINOUT: function(t, b, c, d, a, p) {
7569 if ((t /= d / 2) === 2) {
7573 p = d * (0.3 * 1.5);
7576 if (!a || a < Math.abs(c)) {
7580 s = p / (2 * Math.PI) * Math.asin(c / a);
7583 return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
7585 return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p) * 0.5 + c + b;
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;
7603 return c * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375) + b;
7613 BOUNCE_EASEIN: function(t, b, c, d) {
7614 return c - enchant.Easing.BOUNCE_EASEOUT(d - t, 0, c, d) + b;
7623 BOUNCE_EASEINOUT: function(t, b, c, d) {
7625 return enchant.Easing.BOUNCE_EASEIN(t * 2, 0, c, d) * 0.5 + b;
7627 return enchant.Easing.BOUNCE_EASEOUT(t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b;
7639 BACK_EASEIN: function(t, b, c, d, s) {
7640 if (s === undefined) {
7643 return c * (t /= d) * t * ((s + 1) * t - s) + b;
7652 BACK_EASEOUT: function(t, b, c, d, s) {
7653 if (s === undefined) {
7656 return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
7665 BACK_EASEINOUT: function(t, b, c, d, s) {
7666 if (s === undefined) {
7669 if ((t /= d / 2) < 1) {
7670 return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
7672 return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
7682 EXPO_EASEIN: function(t, b, c, d) {
7683 return (t === 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b;
7692 EXPO_EASEOUT: function(t, b, c, d) {
7693 return (t === d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;
7702 EXPO_EASEINOUT: function(t, b, c, d) {
7709 if ((t /= d / 2) < 1) {
7710 return c / 2 * Math.pow(2, 10 * (t - 1)) + b;
7712 return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;
7717 * Easing Equations v2.0
7721 * @scope enchant.ActionEventTarget.prototype
7724 enchant.ActionEventTarget = enchant.Class.create(enchant.EventTarget, {
7726 * @name enchant.ActionEventTarget
7729 * {@link enchant.Action} クラス向けに拡張された {@link enchant.EventTarget} クラス .
7733 * EventTarget which can change the context of event listeners
7736 * @extends enchant.EventTarget
7738 initialize: function() {
7739 enchant.EventTarget.apply(this, arguments);
7743 * @param {enchant.Event} e Event issued.
7745 dispatchEvent: function(e) {
7750 e.localX = e.x - target._offsetX;
7751 e.localY = e.y - target._offsetY;
7756 if (this['on' + e.type] != null) {
7757 this['on' + e.type].call(target, e);
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);
7770 * @scope enchant.Timeline.prototype
7772 enchant.Timeline = enchant.Class.create(enchant.EventTarget, {
7774 * @name enchant.Timeline
7777 * アニメーションを管理するためのクラス.
7779 * 操作するノードひとつに対して、必ずひとつのタイムラインが対応する。
7780 * tl.enchant.js を読み込むと、Node クラスを継承したすべてのクラス (Group, Scene, Entity, Label, Sprite)の
7782 * tl プロパティに、タイムラインクラスのインスタンスが生成される。
7783 * タイムラインクラスは、自身に様々なアクションを追加するメソッドを持っており、
7784 * これらを使うことで簡潔にアニメーションや様々な操作をすることができる。
7785 * タイムラインクラスはフレームとタイムのアニメーションができる。
7786 * @param node 操作の対象となるノード
7787 * @param [unitialized] このパラメータがtrueならば、最初のaddメソッドが呼ばれる時nodeにenchant.Event.ENTER_FRAMEイベントリスナを追加される。
7791 * Class for managing the action.
7792 * For one node to manipulate the timeline of one must correspond.
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.
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)
7806 initialize: function(node) {
7807 enchant.EventTarget.call(this);
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);
7820 _deactivateTimeline: function() {
7821 if (this._activated) {
7822 this._activated = false;
7823 this.node.removeEventListener('enterframe', this._nodeEventListener);
7829 _activateTimeline: function() {
7830 if (!this._activated && !this.paused) {
7831 this.node.addEventListener("enterframe", this._nodeEventListener);
7832 this._activated = true;
7837 * 一つのenchant.Event.ENTER_FRAMEイベントはアニメーションに一つの時間単位になる。 (デフォルト)
7840 setFrameBased: function() {
7841 this.isFrameBased = true;
7845 * 一つのenchant.Event.ENTER_FRAMEイベントはアニメーションに前のフレームから経過した時間になる。
7848 setTimeBased: function() {
7849 this.isFrameBased = false;
7853 * キューの先頭にあるアクションを終了し、次のアクションへ移行する。
7854 * アクションの中から呼び出されるが、外から呼び出すこともできる。
7856 * アクション実行中に、アクションが終了した場合、
7857 * もう一度 tick() 関数が呼ばれるため、1フレームに複数のアクションが処理される場合もある。
7859 * sprite.tl.then(function A(){ .. }).then(function B(){ .. });
7860 * と記述した場合、最初のフレームで A・B の関数どちらも実行される
7865 next: function(remainingTime) {
7866 var e, action = this.queue.shift();
7867 e = new enchant.Event("actionend");
7869 action.dispatchEvent(e);
7871 if (this.queue.length === 0) {
7872 this._activated = false;
7873 this.node.removeEventListener('enterframe', this._nodeEventListener);
7878 e = new enchant.Event("removedfromtimeline");
7880 action.dispatchEvent(e);
7885 // remove after dispatching removedfromtimeline event
7886 e = new enchant.Event("removedfromtimeline");
7888 action.dispatchEvent(e);
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);
7898 * ターゲットの enterframe イベントのリスナとして登録される関数
7899 * 1フレーム経過する際に実行する処理が書かれている。
7900 * (キューの先頭にあるアクションに対して、actionstart/actiontickイベントを発行する)
7903 tick: function(enterFrameEvent) {
7907 if (this.queue.length > 0) {
7908 var action = this.queue[0];
7909 if (action.frame === 0) {
7911 f = new enchant.Event("actionstart");
7913 action.dispatchEvent(f);
7916 var e = new enchant.Event("actiontick");
7918 if (this.isFrameBased) {
7921 e.elapsed = enterFrameEvent.elapsed;
7923 action.dispatchEvent(e);
7926 add: function(action) {
7927 if (!this._activated) {
7929 this._nodeEventListener = function(e) {
7930 tl.dispatchEvent(e);
7932 this.node.addEventListener("enterframe", this._nodeEventListener);
7934 this._activated = true;
7936 if (this._parallel) {
7937 this._parallel.actions.push(action);
7938 this._parallel = null;
7940 this.queue.push(action);
7944 var e = new enchant.Event("addedtotimeline");
7946 action.dispatchEvent(e);
7948 e = new enchant.Event("actionadded");
7950 this.dispatchEvent(e);
7956 * アクションを簡単に追加するためのメソッド。
7958 * @param params アクションの設定オブジェクト
7961 action: function(params) {
7962 return this.add(new enchant.Action(params));
7966 * トゥイーンを簡単に追加するためのメソッド。
7968 * @param params トゥイーンの設定オブジェクト。
7971 tween: function(params) {
7972 return this.add(new enchant.Tween(params));
7976 * タイムラインのキューをすべて破棄する。終了イベントは発行されない。
7980 var e = new enchant.Event("removedfromtimeline");
7983 for (var i = 0, len = this.queue.length; i < len; i++) {
7984 this.queue[i].dispatchEvent(e);
7987 this._deactivateTimeline();
7993 * 指定したフレーム数が経過したのと同様の処理を、瞬時に実行する。
7998 skip: function(frames) {
7999 var event = new enchant.Event("enterframe");
8000 if (this.isFrameBased) {
8003 event.elapsed = frames;
8007 this.dispatchEvent(event);
8019 this._deactivateTimeline();
8028 resume: function() {
8030 this.paused = false;
8031 this._activateTimeline();
8038 * ループしているときに終了したアクションは、タイムラインから取り除かれた後
8039 * 再度タイムラインに追加される。このアクションは、ループが解除されても残る。
8051 unloop: function() {
8052 this.looped = false;
8057 * 指定したフレーム数だけ待ち、何もしないアクションを追加する。
8061 delay: function(time) {
8062 this.add(new enchant.Action({
8073 wait: function(time) {
8079 * 関数を実行し、即時に次のアクションに移るアクションを追加する。
8083 then: function(func) {
8084 var timeline = this;
8085 this.add(new enchant.Action({
8086 onactiontick: function(evt) {
8087 func.call(timeline.node);
8089 // if time is 0, next action will be immediately executed
8097 * 関数を実行し、即時に次のアクションに移る。
8101 exec: function(func) {
8106 * 実行したい関数を、フレーム数をキーとした連想配列(オブジェクト)で複数指定し追加する。
8107 * 内部的には delay, then を用いている。
8111 * 10: function(){ 10フレーム経過した後に実行される関数 },
8112 * 20: function(){ 20フレーム経過した後に実行される関数 },
8113 * 30: function(){ 30フレーム経過した後に実行される関数 }
8115 * @param cue キューオブジェクト
8118 cue: function(cue) {
8120 for (var frame in cue) {
8121 if (cue.hasOwnProperty(frame)) {
8122 this.delay(frame - ptr);
8123 this.then(cue[frame]);
8130 * ある関数を指定したフレーム数繰り返し実行するアクションを追加する。
8131 * @param func 実行したい関数
8132 * @param time 持続フレーム数
8135 repeat: function(func, time) {
8136 this.add(new enchant.Action({
8137 onactiontick: function(evt) {
8146 * 複数のアクションを並列で実行したいときに指定する。
8147 * and で結ばれたすべてのアクションが終了するまで次のアクションには移行しない
8149 * sprite.tl.fadeIn(30).and.rotateBy(360, 30);
8150 * 30フレームでフェードインしながら 360度回転する
8154 var last = this.queue.pop();
8155 if (last instanceof enchant.ParallelAction) {
8156 this._parallel = last;
8157 this.queue.push(last);
8159 var parallel = new enchant.ParallelAction();
8160 parallel.actions.push(last);
8161 this.queue.push(parallel);
8162 this._parallel = parallel;
8175 doAll: function(children) {
8181 waitAll: function() {
8186 * true値 が返るまで、関数を毎フレーム実行するアクションを追加する。
8188 * sprite.tl.waitUntil(function(){
8189 * return this.x-- < 0
8190 * }).then(function(){ .. });
8191 * // x 座標が負になるまで毎フレーム x座標を減算し続ける
8193 * @param func 実行したい関数
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)) {
8210 * Entity の不透明度をなめらかに変えるアクションを追加する。
8211 * @param opacity 目標の不透明度
8213 * @param [easing] イージング関数
8216 fadeTo: function(opacity, time, easing) {
8226 * Entity をフェードインするアクションを追加する。
8229 * @param [easing] イージング関数
8232 fadeIn: function(time, easing) {
8233 return this.fadeTo(1, time, easing);
8237 * Entity をフェードアウトするアクションを追加する。
8240 * @param [easing] イージング関数
8243 fadeOut: function(time, easing) {
8244 return this.fadeTo(0, time, easing);
8248 * Entity の位置をなめらかに移動させるアクションを追加する。
8252 * @param [easing] イージング関数
8255 moveTo: function(x, y, time, easing) {
8265 * Entity のx座標をなめらかに変化させるアクションを追加する。
8271 moveX: function(x, time, easing) {
8280 * Entity のy座標をなめらかに変化させるアクションを追加する。
8286 moveY: function(y, time, easing) {
8295 * Entity の位置をなめらかに変化させるアクションを追加する。
8296 * 座標は、アクション開始時からの相対座標で指定する。
8303 moveBy: function(x, y, time, easing) {
8317 * Entity の opacity を0にする (即時)
8321 return this.then(function() {
8327 * Entity の opacity を1にする (即時)
8331 return this.then(function() {
8337 * Entity をシーンから削除する。
8338 * シーンから削除された場合、 enterframe イベントは呼ばれなくなるので、
8340 * これ以降のアクションは、再度シーンに追加されるまで実行されない。
8343 removeFromScene: function() {
8344 return this.then(function() {
8345 this.scene.removeChild(this);
8350 * Entity をなめらかに拡大・縮小するアクションを追加する。
8352 * @param [scaleY] 縮尺。省略した場合 scaleX と同じ
8357 scaleTo: function(scale, time, easing) {
8358 if (typeof easing === "number") {
8360 scaleX: arguments[0],
8361 scaleY: arguments[1],
8363 easing: arguments[3]
8375 * Entity をなめらかに拡大・縮小させるアクションを追加する。
8376 * 相対縮尺 (ex. アクション開始時の縮尺の n 倍) で指定する。
8377 * @param scaleX 相対縮尺
8378 * @param [scaleY] 相対縮尺。省略した場合 scaleX と同じ
8383 scaleBy: function(scale, time, easing) {
8384 if (typeof easing === "number") {
8386 scaleX: function() {
8387 return this.scaleX * arguments[0];
8389 scaleY: function() {
8390 return this.scaleY * arguments[1];
8393 easing: arguments[3]
8397 scaleX: function() {
8398 return this.scaleX * scale;
8400 scaleY: function() {
8401 return this.scaleY * scale;
8409 * Entity をなめらかに回転させるアクションを追加する。
8410 * @param deg 目標の回転角度 (弧度法: 1回転を 360 とする)
8412 * @param [easing] イージング関数
8415 rotateTo: function(deg, time, easing) {
8424 * Entity をなめらかに回転させるアクションを追加する。
8425 * 角度は相対角度 (アクション開始時の角度から更に n 度) で指定する
8426 * @param deg 目標の相対角度 (弧度法: 1回転を 360 とする)
8428 * @param [easing] イージング関数
8431 rotateBy: function(deg, time, easing) {
8433 rotation: function() {
8434 return this.rotation + deg;
8443 * @scope enchant.Action.prototype
8447 enchant.Action = enchant.Class.create(enchant.ActionEventTarget, {
8449 * @name enchant.Action
8452 * アニメーションタイムラインを構成する、実行したい処理を指定するためのクラス.
8454 * タイムラインに追加されたアクションは順に実行される。
8455 * アクションが開始・終了された時に actionstart, actionend イベントが発行され、
8456 * また1フレーム経過した時には actiontick イベントが発行される。
8457 * これらのイベントのリスナとして実行したい処理を指定する。
8459 * time で指定されたフレーム数が経過すると自動的に次のアクションに移行するが、
8460 * null が指定されると、タイムラインの next メソッドが呼ばれるまで移行しない。
8463 * @config {integer} [time] アクションが持続するフレーム数。 null が指定されると無限長
8464 * @config {function} [onactionstart] アクションが開始される時のイベントリスナ
8465 * @config {function} [onactiontick] アクションが1フレーム経過するときのイベントリスナ
8466 * @config {function} [onactionend] アクションがが終了する時のイベントリスナ
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.
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.
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
8488 initialize: function(param) {
8489 enchant.ActionEventTarget.call(this);
8492 for (var key in param) {
8493 if (param.hasOwnProperty(key)) {
8494 if (param[key] != null) {
8495 this[key] = param[key];
8501 this.timeline = null;
8504 this.addEventListener(enchant.Event.ADDED_TO_TIMELINE, function(evt) {
8505 action.timeline = evt.timeline;
8506 action.node = evt.timeline.node;
8510 this.addEventListener(enchant.Event.REMOVED_FROM_TIMELINE, function() {
8511 action.timeline = null;
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);
8522 action.frame += evt.elapsed;
8530 * @scope enchant.ParallelAction.prototype
8532 enchant.ParallelAction = enchant.Class.create(enchant.Action, {
8534 * @name enchant.ParallelAction
8537 * アクションを並列で実行するためのアクション。
8538 * 子アクションを複数持つことができる。
8541 * @extends enchant.Action
8543 initialize: function(param) {
8544 enchant.Action.call(this, param);
8545 var timeline = this.timeline;
8546 var node = this.node;
8564 this.endedActions = [];
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);
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);
8581 var e = new enchant.Event("actionend");
8583 action.dispatchEvent(e);
8585 e = new enchant.Event("removedfromtimeline");
8587 action.dispatchEvent(e);
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);
8598 if (that.actions.length === 0) {
8599 evt.timeline.next();
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);
8609 this.addEventListener(enchant.Event.REMOVED_FROM_TIMELINE, function() {
8610 this.actions = this.endedActions;
8611 this.endedActions = [];
8618 * @scope enchant.Tween.prototype
8620 enchant.Tween = enchant.Class.create(enchant.Action, {
8622 * @name enchant.Tween
8625 * {@link enchant.Action} を継承した、オブジェクトの特定のプロパティを、なめらかに変更したい時に用いるためのアクションクラス.
8626 * アクションを扱いやすく拡張したクラス.
8628 * コンストラクタに渡す設定オブジェクトに、プロパティの目標値を指定すると、
8629 * アクションが実行された時に、目標値までなめらかに値を変更するようなアクションを生成する。
8631 * トゥイーンのイージングも、easing プロパティで指定できる。
8632 * デフォルトでは enchant.Easing.LINEAR が指定されている。
8637 * @config {easing} [function]
8640 initialize: function(params) {
8643 enchant.Action.call(this, params);
8645 if (this.easing == null) {
8647 this.easing = function(t, b, c, d) {
8648 return c * t / d + b;
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
8660 if (typeof params[prop] === "function") {
8661 target_val = params[prop].call(tween.node);
8663 target_val = params[prop];
8666 if (excepted.indexOf(prop) === -1) {
8667 origin[prop] = tween.node[prop];
8668 target[prop] = target_val;
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);
8678 for (var prop in target){
8679 if (target.hasOwnProperty(prop)) {
8680 if (typeof this[prop] === "undefined"){
8683 tween.node[prop] += (target[prop] - origin[prop]) * ratio;
8684 if (Math.abs(tween.node[prop]) < 10e-8){
8685 tween.node[prop] = 0;