/* * tmlib.js 0.2.0 * http://github.com/phi-jp/tmlib.js * MIT Licensed * * Copyright (C) 2010 phi, http://tmlife.net */ (function() { "use strict"; })(); /* * tm namespace */ var tm = tm || {}; tm.global = window || global || this; // node.js if (typeof module !== 'undefined' && module.exports) { module.exports = tm; } (function() { /** * バージョン */ tm.VERSION = "0.2.0"; /** * tmlib.js のルートパス */ tm.LIB_ROOT = (function(){ if (!window.document) return ; var scripts = document.getElementsByTagName("script"); for (var i=0, len=scripts.length; i 0 || ua.indexOf("iPad") > 0 || ua.indexOf("Android") > 0); })(); /** * クラス定義 */ tm.createClass = function(prop) { // デフォルト値 prop.init = prop.init || function() {}; prop.superClass = prop.superClass || null; // クラス作成 var tm_class = function() { var temp = new tm_class.prototype.creator(); tm_class.prototype.init.apply(temp, arguments); return temp }; // 継承 if (prop.superClass) { prop.init.owner = tm_class; tm_class.prototype = Object.create(prop.superClass.prototype); tm_class.prototype.superInit = function() { var caller = this.superInit.caller; // 呼び出しもと var subclass = caller.owner; // 呼び出しもとを持っているクラス var superclass= subclass.prototype.superClass; // 呼び出しもとクラスの親クラス var superInit = superclass.prototype.init; // 呼び出しもとクラスの親クラスの init // var superMethod = this.superInit.caller.owner.prototype.superClass.prototype.init; superInit.apply(this, arguments); }; tm_class.prototype.constructor = tm_class; } tm_class.prototype.selfClass = tm_class; // プロパティを追加 for (var key in prop) { tm_class.prototype[key] = prop[key]; } // クリエイタの生成 tm_class.prototype.creator = function() { return this; }; // クリエイタの継承 tm_class.prototype.creator.prototype = tm_class.prototype; tm_class._class = true; return tm_class; }; tm.classes = {}; var _calssDefinedCallback = {}; /** * クラス定義 * phi クラス定義 * new と apply を同時に使う */ tm.define = function(path, prop) { var index = path.lastIndexOf("."); var nsName = path.substring(0, index); var ns = (nsName) ? tm.using(nsName) : tm.global; var className = (nsName) ? path.substring(index+1) : path; var bind = Function.prototype.bind; var unshift = Array.prototype.unshift; prop._path = path; prop._className = className; var _class = null; var superClass = prop.superClass; if (superClass && typeof superClass == "string") { var superClassName = superClass; superClass = tm.using(superClass); if (superClass._class) { prop.superClass = superClass; _class = tm.createClass(prop); } else { // 親クラスが呼ばれた際に再度実行する if (!_calssDefinedCallback[superClassName]) { _calssDefinedCallback[superClassName] = []; } _calssDefinedCallback[superClassName].push(function() { tm.define(path, prop); }); return ; } } else { _class = tm.createClass(prop); } // キャッシュしておく ns[className] = tm.classes[path] = _class; if (_calssDefinedCallback[path]) { var list = _calssDefinedCallback[path]; for (var i=0,len=list.length; i 0) ? newDelay : 0; // 次回呼び出し登録 setTimeout(arguments.callee, newDelay); }; setTimeout(temp, delay); }; tm.inform = function(parent){ parent = parent || document.body; var eInfo = document.createElement("div"); eInfo.setAttribute("class", "tm-info"); eInfo.addEventListener("mouseover", function(){ this.style.opacity = 0.9; }, false); eInfo.addEventListener("mouseout", function(){ this.style.opacity = 0.25; }, false); with(eInfo.style) { position = "absolute"; width = "100%"; // top = "0px"; bottom = "0px"; left = "0px"; right = "0px"; margin = "0px"; padding = "10px 0px"; zIndex = "0"; textAlign = "center"; fontFamily = '"Meiryo", "メイリオ", "ヒラギノ角ゴ Pro W3", sans-serif'; fontSize = "13px"; opacity = "0.25"; backgroundColor = "rgb(230,230,255)"; background = "-webkit-linear-gradient(top, hsla(0, 100%, 100%, 0.8) 0%, hsla(0, 100%, 100%, 0.3) 50%, hsla(0, 100%, 100%, 0.1) 51%, hsla(0, 100%, 100%, 0.2) 100%), rgb(190,190,210)"; background = "-moz-linear-gradient(top, hsla(0, 100%, 100%, 0.8) 0%, hsla(0, 100%, 100%, 0.3) 50%, hsla(0, 100%, 100%, 0.1) 51%, hsla(0, 100%, 100%, 0.2) 100%), rgb(190,190,210)"; WebkitTransition = "1s"; MozTransition = "1s"; } /* eInfo.innerHTML = "このプログラムで利用している JavaScript ライブラリ 『tmlib.js』 はこちらからダウンロードできます. 詳しくはBlogに書いています.".format({ "tmlibLink": "http://code.google.com/p/tmlib-js/downloads/list", "blogLink" : "http://tmlife.net/tmlib" }); */ eInfo.innerHTML = "このプログラムで利用している JavaScript ライブラリ 『tmlib.js』 についてはこちら.".format({ "projectLink" : "https://github.com/phi1618/tmlib.js" }); parent.appendChild(eInfo); }; })(); (function() { if (!window) return ; if (!window.requestAnimationFrame) { window.requestAnimationFrame = window[tm.VENDER_PREFIX + "RequestAnimationFrame"] || function(callback) { window.setTimeout(callback, 1000/60); }; } if (!window.cancelRequestAnimationFrame) { window.cancelRequestAnimationFrame = window[tm.VENDER_PREFIX + "CancelRequestAnimationFrame"] || window.clearTimeout; } })(); (function() { if (!window.document) return ; _loadCheckList = []; tm.addLoadCheckList = function(obj) { console.assert(obj.isLoaded !== undefined, "isLoaded が定義されていません!!"); _loadCheckList.push(obj); }; _preloadListners = []; _mainListners = []; tm.preload = function(fn) { _preloadListners.push(fn); }; tm.main = function(fn) { _mainListners.push(fn); }; var _preload = function() { for (var i=0,len=_preloadListners.length; i $extend としました */ Object.defineInstanceMethod("$extend", function() { Array.prototype.forEach.call(arguments, function(source) { for (var property in source) { this[property] = source[property]; } }, this); return this; }); /** * @method $safe * 安全拡張 * 上書きしない */ Object.defineInstanceMethod("$safe", function(source) { Array.prototype.forEach.call(arguments, function(source) { for (var property in source) { if (!this[property]) this[property] = source[property]; } }, this); return this; }); /** * @method $strict * 厳格拡張 * すでにあった場合は警告 */ Object.defineInstanceMethod("$strict", function(source) { Array.prototype.forEach.call(arguments, function(source) { for (var property in source) { console.assert(!this[property], "tm error: {0} is Already".format(property)); this[property] = source[property]; } }, this); return this; }); /** * @method $pick * text */ Object.defineInstanceMethod("$pick", function() { var temp = {}; Array.prototype.forEach.call(arguments, function(key) { if (key in this) temp[key] = this[key]; }, this); return temp; }); /** * @method $omit * text */ Object.defineInstanceMethod("$omit", function() { var temp = {}; for (var key in this) { if (Array.prototype.indexOf.call(arguments, key) == -1) { temp[key] = this[key]; } } return temp; }); /** * @method using * 使う */ Object.defineInstanceMethod("$using", function(source) { // TODO: return this; }); /** * @method globalize * グローバル化 */ Object.defineInstanceMethod("$globalize", function(key) { if (key) { tm.global[key] = this[key]; } else { tm.global.$strict(this); } return this; }); })(); /* * array.js */ (function() { /** * @class global.Array * Arrayの拡張 * * @example display * [1, 2, 3].first; */ /** * @property first * 最初の要素 */ Array.prototype.accessor("first", { "get": function() { return this[0]; }, "set": function(v) { this[0] = v; } }); /** * @property last * 最後の要素 */ Array.prototype.accessor("last", { "get": function() { return this[this.length-1]; }, "set": function(v) { this[this.length-1] = v; } }); /** * @method equals * 渡された配列と等しいかどうかをチェック */ Array.defineInstanceMethod("equals", function(arr) { // 長さチェック if (this.length !== arr.length) return false; for (var i=0,len=this.length; i= 0) { this.splice(index, 1); } return this; }); /** * @method eraseAll * elm と一致する要素を全て削除 */ Array.defineInstanceMethod("eraseAll", function(elm) { for (var i=0,len=this.length; iend; i+=step, ++index) { this[index] = i; } } return this; }); /** * @method shuffle * シャッフル */ Array.defineInstanceMethod("shuffle", function() { for (var i=0,len=this.length; i b) ? b : x ); }; /** * @property DEG_TO_RAD * Degree to Radian. */ Math.DEG_TO_RAD = Math.PI/180; /** * @property RAD_TO_DEG * Radian to Degree. */ Math.RAD_TO_DEG = 180/Math.PI; /** * @method * Degree を Radian に変換 */ Math.degToRad = function(deg) { return deg * Math.DEG_TO_RAD; }; /** * @method * Radian を Degree に変換 */ Math.radToDeg = function(rad) { return rad * Math.RAD_TO_DEG; }; /** * @method * ランダムな値を指定された範囲内で生成 */ Math.rand = function(min, max) { return window.Math.floor( Math.random()*(max-min+1) ) + min; }; /** * @method * ランダムな値を指定された範囲内で生成 */ Math.randf= function(min, max) { return window.Math.random()*(max-min)+min; }; /** * @method * 長さを取得 */ Math.magnitude = function() { return Math.sqrt(Math.magnitudeSq.apply(null, arguments)); }; /** * @method * 長さの2乗を取得 */ Math.magnitudeSq = function() { var n = 0; for (var i=0,len=arguments.length; i= a) && (x) <= b; }; })(); /* * number.js */ (function() { /** * @class global.Number * Numberの拡張 */ /** * @method round * 四捨五入 * 桁数指定版 */ Number.defineInstanceMethod("round", function(figure) { figure = figure || 0; var base = Math.pow(10, figure); var temp = this * base; temp = Math.round(temp); return temp/base; }); /** * @method ceil * 切り上げ. * 桁数指定版 */ Number.defineInstanceMethod("ceil", function(figure) { figure = figure || 0; var base = Math.pow(10, figure); var temp = this * base; temp = Math.ceil(temp); return temp/base; }); /** * @method floor * 切り捨て * 桁数指定版 */ Number.defineInstanceMethod("floor", function(figure) { figure = figure || 0; var base = Math.pow(10, figure); var temp = this * base; temp = Math.floor(temp); // ~~this // this|0 return temp/base; }); /** * @method toInt * integer 型に変換する */ Number.defineInstanceMethod("toInt", function() { return (this | 0); }); /** * @method toHex * 16進数化 */ Number.defineInstanceMethod("toHex", function() { return this.toString(16); }); /** * @method toBin * 2進数化 */ Number.defineInstanceMethod("toBin", function() { return this.toString(2); }); /** * @method toUnsigned * unsigned 型に変換する */ Number.defineInstanceMethod("toUnsigned", function() { return this >>> 0; }); /** * @method padding * 文字埋め */ Number.defineInstanceMethod("padding", function(n, ch) { var str = this+''; n = n-str.length; ch = ch || '0'; while(n-- > 0) { str = ch + str; } return str; }); })(); /* * string.js */ (function() { /** * @class global.String * Stringの拡張 * `String` is a global object that may be used to construct String instances. */ /** * @method format * * フォーマット * * ## example * * document.write("{0} + {1} = {2}".format(5, 10, 5+10)); // "5 + 10 = 15" * document.write("rgb({r}, {g}, {b})".format({ // "rgb(128, 0, 255)" * r: 128, * g: 0, * b: 255 * })); */ String.defineInstanceMethod("format", function(arg) { // 置換ファンク var rep_fn = undefined; // オブジェクトの場合 if (typeof arg == "object") { /** @ignore */ rep_fn = function(m, k) { return arg[k]; } } // 複数引数だった場合 else { var args = arguments; /** @ignore */ rep_fn = function(m, k) { return args[ parseInt(k) ]; } } return this.replace( /\{(\w+)\}/g, rep_fn ); }); /** * @method trim * トリム * * Reference * */ String.defineInstanceMethod("trim", function() { return this.replace(/^\s+|\s+$/g, ""); }); /** * @method capitalize * キャピタライズ * * ## Reference * * - [キャピタライズ(単語の先頭の大文字化)を行う - oct inaodu](http://d.hatena.ne.jp/brazil/20051212/1134369083) * - [デザインとプログラムの狭間で: javascriptでキャピタライズ(一文字目を大文字にする)](http://design-program.blogspot.com/2011/02/javascript.html) * */ String.defineInstanceMethod("capitalize", function() { return this.replace(/\w+/g, function(word){ return word.capitalizeFirstLetter(); }); }); /** * @method capitalizeFirstLetter * 先頭文字のみキャピタライズ */ String.defineInstanceMethod("capitalizeFirstLetter", function() { return this.charAt(0).toUpperCase() + this.substr(1).toLowerCase(); }); /** * @method toDash * ダッシュ */ String.defineInstanceMethod("toDash", function() { return this.replace(/([A-Z])/g, function(m){ return '-'+m.toLowerCase(); }); }); /** * @method toHash * ハッシュ値に変換 */ String.defineInstanceMethod("toHash", function() { return this.toCRC32(); }); /** * @method padding * 左側に指定された文字を詰めて右寄せにする */ String.defineInstanceMethod("padding", function(n, ch) { var str = this.toString(); n = n-str.length; ch = ch || ' '; while(n-- > 0) { str = ch + str; } return str; }); /** * @method paddingLeft * 左側に指定された文字を詰めて右寄せにする */ String.defineInstanceMethod("paddingLeft", function(n, ch) { var str = this.toString(); n = n-str.length; ch = ch || ' '; while(n-- > 0) { str = ch + str; } return str; }); /** * @method paddingRight * 右側に指定された文字を詰めて左寄せにする */ String.defineInstanceMethod("paddingRight", function(n, ch) { var str = this.toString(); n = n-str.length; ch = ch || ' '; while(n-- > 0) { str = str + ch; } return str; }); /** * @method quotemeta * メタ文字をクォート */ String.defineInstanceMethod("quotemeta", function(n) { return this.replace(/([^0-9A-Za-z_])/g, '\\$1'); }); /** * @method repeat * リピート */ String.defineInstanceMethod("repeat", function(n) { // TODO: 確認する var arr = Array(n); for (var i=0; i>> 8) ^ x; } return (crc ^ (-1)) >>> 0; }); })(); /* * list.js */ (function() { /** * @class tm.Item * Item クラス */ tm.Item = tm.createClass({ /** prev */ prev: null, /** next */ next: null, /** data */ data: null, /** * @constructor */ init: function() { } }); /** * @class tm.List * List クラス * ### Reference * - * - * - * - * - * - */ tm.List = tm.createClass({ /** * @constructor */ init: function() { this._length = 0; this._head = tm.Item(); this._tail = tm.Item(); this._head.next = this._tail; this._tail.prev = this._head; }, /** * 追加 */ add: function(data) { var item = tm.Item(); item.data = data; item.prev = this._tail.prev; item.next = this._tail; this._tail.prev.next = item; this._tail.prev = item; ++this._length; return this; }, /** * 削除 */ remove: function(index) { var current = this.getItem(index); current.prev.next = current.next; current.next.prev = current.prev; --this._length; return current; }, /** * ゲット */ get: function(index) { return this.getItem(index).data; }, /** * アイテムを取得 */ getItem: function(index) { var current = this._head.next; var i=0; while (i++ < index) { current = current.next; } return current; }, /** * 繰り返し */ forEach: function(fn) { // TODO: }, /** * クリア */ clear: function() { // TODO: }, /** * クローン */ clone: function() { // TODO: }, /** * 最初の要素を取得 */ getFirst: function() { // TODO: }, /** * 最後の要素を取得 */ getLast: function() { // TODO: }, /** * 最初に一致した位置のインデックスを取得 */ indexOf: function(obj) { // TODO: }, /** * 最後に一致した位置のインデックスを取得 */ lastIndexOf: function(obj) { // TODO: }, /** * 配列に変換 */ toArray: function() { if (this._length <= 0) return []; var current = this._head.next; var arr = []; while (current.data != null) { arr.push(current.data); current = current.next; } return arr; }, /** * 文字列に変換 */ toString: function() { var arr = this.toArray(); for (var i=0,len=arr.length; i * - * - * - * - */ tm.util.Random = { /** * Dummy */ randint: function(min, max) { return window.Math.floor( Math.random()*(max-min+1) ) + min; }, /** * Dummy */ randfloat: function(min, max) { return window.Math.random()*(max-min)+min; }, /** * Dummy */ randbool: function() { return this.randint(0, 1) === 1; }, }; })(); /* * ajax.js */ tm.util = tm.util || {}; (function() { /* * @enum * @TODO ? * @private */ var AJAX_DEFAULT_SETTINGS = { /* @property type */ type :"GET", /* @property async */ async: true, /* @property data */ data: null, /* @property contentType */ contentType: 'application/x-www-form-urlencoded', /* @property dataType */ dataType: 'text', /* @property username */ username: null, /* @property password */ password: null, /* @property success */ success : function(data){ alert("success!!\n"+data); }, /* @property error */ error : function(data){ alert("error!!"); }, /* @property beforeSend */ beforeSend: null, }; /** * @class tm.util.Ajax * @TODO ? */ tm.util.Ajax = { /** * load */ load: function(params) { for (var key in AJAX_DEFAULT_SETTINGS) { params[key] = params[key] || AJAX_DEFAULT_SETTINGS[key]; } var httpRequest = new XMLHttpRequest(); var ajax_params = ""; var conv_func = tm.util.Ajax.DATA_CONVERTE_TABLE[params.dataType]; var url = params.url; if (params.data) { var query = ""; if (typeof params.data == 'string') { query = params.data; // query = encodeURIComponent(params.data); } else { query = tm.util.QueryString.stringify(params.data); } if (params.type == 'GET') { params.url += '?' + query; params.data = null; } else if (params.type == 'POST') { params.data = query; } } // httpRequest.withCredentials = true; // コールバック httpRequest.onreadystatechange = function() { if (httpRequest.readyState == 4) { // 成功 if (httpRequest.status === 200) { // タイプ別に変換をかける var data = conv_func(httpRequest.responseText); params.success(data); } // status === 0 はローカルファイル用 else if (httpRequest.status === 0) { // タイプ別に変換をかける var data = conv_func(httpRequest.responseText); params.success(data); } else { params.error(httpRequest.responseText); } } else { //console.log("通信中"); } }; httpRequest.open(params.type, params.url, params.async, params.username, params.password); // オープン if (params.type === "POST") { httpRequest.setRequestHeader('Content-Type', params.contentType); // ヘッダをセット } if (params.beforeSend) { params.beforeSend(httpRequest); } httpRequest.send(params.data); }, /** * loadJSONP */ loadJSONP: function(url, callback) { var g = tm.global; g.tmlib_js_dummy_func_count = tm.global.tmlib_js_dummy_func || 0; var dummy_func_name = "tmlib_js_dummy_func" + (g.tmlib_js_dummy_func_count++); g[dummy_func_name] = callback; var elm = document.createElement("script"); elm.type = "text/javascript"; elm.charset = "UTF-8"; elm.src = url + "&callback=" + dummy_func_name; elm.setAttribute("defer", true); document.getElementsByTagName("head")[0].appendChild(elm); } }; /* * @enum tm.util.Ajax.DATA_CONVERTE_TABLE * データコンバータテーブル */ tm.util.Ajax.DATA_CONVERTE_TABLE = { /* @method */ undefined: function(data) { return data; }, /* @method */ text: function(data) { return data; }, /* @method */ xml: function(data) { var div = document.createElement("div"); div.innerHTML = data; return div; }, /* @method */ dom: function(data) { var div = document.createElement("div"); div.innerHTML = data; return tm.dom.Element(div); }, /* @method */ json: function(data) { try { return JSON.parse(data); } catch(e) { console.dir(e); console.dir(data); } }, /* @method */ script: function(data) { eval(data); return data; }, /* * @method * ### Reference * - * @param {Object} data */ bin: function(data) { var bytearray = []; for (var i=0, len=data.length; i 0) { for (var i=0,len=this.tasks.length; i= 2) { this.args[key] = value; } this._check(); }, /** * 終了チェック */ isFinish: function() { return (this.counter === this.waits); }, _check: function() { if (this.isFinish()) { var args = this.args; if (this.callback) { this.callback(args); this.args = null; this.callback = null; } var e = tm.event.Event("flowfinish"); e.args = args; this.fire(e); } } }); /* * vector2.js */ /* * 幾何学 */ tm.geom = tm.geom || {}; (function() { /** * @class tm.geom.Vector2 * 2次元ベクトル */ tm.geom.Vector2 = tm.createClass({ /** x座標 */ x: 0, /** y座標 */ y: 0, /** * @constructor */ init: function(x, y) { this.set(x, y); }, /** * 複製 */ clone: function() { return tm.geom.Vector2(this.x, this.y); }, /** * 等しいかどうかをチェック * @param {tm.geom.Vector2} v 比較対象となる2次元ベクトル */ equals: function(v) { return (this.x === v.x && this.y === v.y) ? true : false; }, /** * 数値と等しいかどうかをチェック * @param {Number} x 比較対象となる x 値 * @param {Number} y 比較対象となる y 値 */ equalsNumber: function(x, y) { return (this.x === x && this.y === y) ? true : false; }, /** * 配列と等しいかどうかをチェック * @param {Number} arr 比較対象となる配列 */ equalsArray: function(arr) { return (this.x === arr[0] && this.y === arr[1]) ? true : false; }, /** * セッター */ set: function(x, y) { this.x = x; this.y = y; }, /** * 数値からセット */ setNumber: function(x, y) { this.x = x; this.y = y; return this; }, /** * 配列からセット */ setArray: function(arr) { this.x = arr[0]; this.y = arr[1]; return this; }, /** * オブジェクトからセット */ setObject: function(obj) { this.x = obj.x; this.y = obj.y; return this; }, /** * 文字列からセット */ setString: function(str) { var m = str.match(/(-?\d+(\.{1}\d+)?),\s*(-?\d+(\.{1}\d+)?)/); this.x = parseFloat(m[1]); this.y = parseFloat(m[3]); return this; }, /** * 賢いセット */ setSmart: function(x, y) { var v = arguments[0]; // xyz if (arguments.length === 2) { this.x = x; this.y = y; } // Array else if (v instanceof Array) { this.x = v[0]; this.y = v[1]; } // Object else if (v instanceof Object) { this.x = v.x; this.y = v.y; } // String else if (typeof(v) == "string") { var m = v.match(/(-?\d+(\.{1}\d+)?),\s*(-?\d+(\.{1}\d+)?)/); this.x = parseFloat(m[1]); this.y = parseFloat(m[3]); } return this; }, /** * 角度と長さでベクトルをセット * Angle は Degree 値で指定 */ setAngle: function(angle, len) { var rad = angle*Math.DEG_TO_RAD; len = len || 1; this.x = Math.cos(rad)*len; this.y = Math.sin(rad)*len; return this; }, /** * 角度(radian)と長さでベクトルをセット */ setRadian: function(radian, len) { len = len || 1; this.x = Math.cos(radian)*len; this.y = Math.sin(radian)*len; return this; }, /** * 角度(degree)と長さでベクトルをセット */ setDegree: function(degree, len) { var rad = degree*Math.DEG_TO_RAD; len = len || 1; this.x = Math.cos(rad)*len; this.y = Math.sin(rad)*len; return this; }, /** * ランダムベクトルをセット */ setRandom: function(min, max, len) { min = min || 0; max = max || 360; len = len || 1; this.setDegree(Math.randf(min, max), len); return this; }, /** * 加算 */ add: function(v) { this.x += v.x; this.y += v.y; return this; }, /** * 減算 */ sub: function(v) { this.x -= v.x; this.y -= v.y; return this; }, /** * 乗算 */ mul: function(n) { this.x *= n; this.y *= n; return this; }, /** * 除算 */ div: function(n) { //console.assert(n != 0, "0 division!!"); n = n || 0.01; this.x /= n; this.y /= n; return this; }, /** * 反転 */ negate: function() { this.x = -this.x; this.y = -this.y; return this; }, /** * @method * 内積. * 投影ベクトルを求めたり, 類似度に使ったり. */ dot: function(v) { return this.x * v.x + this.y * v.y; }, /** * @method * 外積 */ cross: function(v) { return (this.x*v.y) - (this.y*v.x); }, /** * 長さを取得 * ### memo * magnitude って名前の方が良いかも. 検討中. */ length: function() { return Math.sqrt(this.x*this.x + this.y*this.y); }, /** * 2乗された長さを取得 * C# の名前を引用 * or lengthSquare or lengthSqrt */ lengthSquared: function() { return this.x*this.x + this.y*this.y; }, /** * 2点間の距離を返す */ distance: function(v) { return Math.sqrt( Math.pow(this.x-v.x, 2) + Math.pow(this.y-v.y, 2) ); }, /** * 2点間の距離を返す */ distanceSquared: function(v) { return Math.pow(this.x-v.x, 2) + Math.pow(this.y-v.y, 2); }, /** * 正規化 */ normalize: function() { var length = this.length(); this.div(length); return this; }, /** * 角度(radian)に変換 */ toAngle: function() { return Math.atan2(this.y, this.x); }, /** * @TODO ? */ toStyleString: function() { return "{x:{x}, y:{y}}".format(this); }, /** * @TODO ? */ toString: function() { return "{x:{x}, y:{y}}".format(this); }, /** * X値をセット * チェーンメソッド用セッター */ setX: function(x) { this.x = x; return this; }, /** * Y値をセット * チェーンメソッド用セッター */ setY: function(y) { this.y = y; return this; }, }); /** * @method * @static * min */ tm.geom.Vector2.min = function(lhs, rhs) { return tm.geom.Vector2( (lhs.x < rhs.x) ? lhs.x : rhs.x, (lhs.y < rhs.y) ? lhs.y : rhs.y ); }; /** * @method * @static * max */ tm.geom.Vector2.max = function(lhs, rhs) { return tm.geom.Vector2( (lhs.x > rhs.x) ? lhs.x : rhs.x, (lhs.y > rhs.y) ? lhs.y : rhs.y ); }; /** * @method * @static * 加算 */ tm.geom.Vector2.add = function(lhs, rhs) { return tm.geom.Vector2(lhs.x+rhs.x, lhs.y+rhs.y); }; /** * @method * @static * 減算 */ tm.geom.Vector2.sub = function(lhs, rhs) { return tm.geom.Vector2(lhs.x-rhs.x, lhs.y-rhs.y); }; /** * @method * @static * 乗算 */ tm.geom.Vector2.mul = function(v, n) { return tm.geom.Vector2(v.x*n, v.y*n); }; /** * @method * @static * 割算 */ tm.geom.Vector2.div = function(v, n) { return tm.geom.Vector2(v.x/n, v.y/n); }; /** * @method * @static * 反転 */ tm.geom.Vector2.negate = function(v) { return tm.geom.Vector2(-v.x, -v.y); }; /** * @method * @static * 内積. * 投影ベクトルを求めたり, 類似度に使ったり. */ tm.geom.Vector2.dot = function(lhs, rhs) { return lhs.x * rhs.x + lhs.y * rhs.y; }; /** * @method * @static * 外積 */ tm.geom.Vector2.cross = function(lhs, rhs) { return (lhs.x*rhs.y) - (lhs.y*rhs.x); }; /** * @method * @static * 2点間の距離を返す */ tm.geom.Vector2.distance = function(lhs, rhs) { return Math.sqrt( Math.pow(lhs.x-rhs.x, 2) + Math.pow(lhs.y-rhs.y, 2) ); }; /** * @method * @static * 2点間の距離を返す */ tm.geom.Vector2.distanceSquared = function(lhs, rhs) { return Math.pow(lhs.x-rhs.x, 2) + Math.pow(lhs.y-rhs.y, 2); }; /** * @method * @static * マンハッタン距離 */ tm.geom.Vector2.manhattanDistance = function(lhs, rhs) { return Math.abs(lhs.x-rhs.x) + Math.abs(lhs.y-rhs.y); }; /** * @method * @static * 反射ベクトル */ tm.geom.Vector2.reflect = function(v, normal) { var len = Vector2.dot(v, normal); var temp= Vector2.mul(normal, 2*len); return tm.geom.Vector2.sub(v, temp); }; /** * @method * @static * 補間. * 0.5 で lhs と rhs の中間ベクトルを求めることができます. */ tm.geom.Vector2.lerp = function(lhs, rhs, t) { // TODO: return tm.geom.Vector2( lhs.x + (rhs.x-lhs.x)*t, lhs.y + (rhs.y-lhs.y)*t ); }; /** * @method * @static * 補間 */ tm.geom.Vector2.slerp = function(lhs, rhs, t) { // TODO: // cos... }; /** * @method * @static * min ~ max の間でランダムな方向のベクトルを生成する. len で長さ指定. */ tm.geom.Vector2.random = function(min, max, len) { min = min || 0; max = max || 360; len = len || 1; return tm.geom.Vector2().setDegree(Math.randf(min, max), len); }; /** * @property * @static * zero */ tm.geom.Vector2.ZERO = tm.geom.Vector2( 0, 0); /** * @property * @static * left */ tm.geom.Vector2.LEFT = tm.geom.Vector2(-1, 0); /** * @property * @static * right */ tm.geom.Vector2.RIGHT = tm.geom.Vector2( 1, 0); /** * @property * @static * up */ tm.geom.Vector2.UP = tm.geom.Vector2( 0, 1); /** * @property * @static * down */ tm.geom.Vector2.DOWN = tm.geom.Vector2( 0,-1); })(); /* * vector3.js */ /* * 幾何学 */ tm.geom = tm.geom || {}; (function() { /** * @class tm.geom.Vector3 * 3次元ベクトル */ tm.geom.Vector3 = tm.createClass({ /** x 座標 */ x: 0, /** y 座標 */ y: 0, /** z 座標 */ z: 0, /** * @constructor * - [Test Program](http://tmlib-js.googlecode.com/svn/trunk/test/geom/vector-test.html) */ init: function(x, y, z) { this.set(x, y, z); }, /** * セット */ set: function(x, y, z) { this.x = x; this.y = y; this.z = z; return this; }, /** * 数値からセット */ setNumber: function(x, y, z) { this.x = x; this.y = y; this.z = z; return this; }, /** * 配列からセット */ setArray: function(arr) { this.x = arr[0]; this.y = arr[1]; this.z = arr[2]; return this; }, /** * オブジェクトからセット */ setObject: function(obj) { this.x = obj.x; this.y = obj.y; this.z = obj.z; return this; }, /** * 文字列からセット */ setString: function(str) { var m = str.match(/(-?\d+(\.{1}\d+)?),\s*(-?\d+(\.{1}\d+)?),\s*(-?\d+(\.{1}\d+)?)/); this.x = parseFloat(m[1]); this.y = parseFloat(m[3]); this.z = parseFloat(m[5]); return this; }, /** * 角度(radian)と長さでベクトルをセット */ setAngle: function(thetaRad, phiRad, len) { len = len || 1; this.x = len * Math.cos(thetaRad) * Math.sin(phiRad); this.y = len * Math.sin(thetaRad); this.z = len * Math.cos(thetaRad) * Math.cos(phiRad); return this; }, /** * 角度(radian)と長さでベクトルをセット */ setRadian: function(thetaRad, phiRad, len) { return this.setAngle(thetaRad, phiRad, len); }, /** * 角度(degree)と長さでベクトルをセット */ setDegree: function(thetaDegree, phiDegree, len) { return this.setAngle(thetaDegree*Math.DEG_TO_RAD, phiDegree*Math.DEG_TO_RAD, len); }, /** * 賢いセット */ setSmart: function(x, y, z) { var v = arguments[0]; // xyz if (arguments.length === 3) { this.x = x; this.y = y; this.z = z; } // Array else if (v instanceof Array) { this.x = v[0]; this.y = v[1]; this.z = v[2]; } // Object else if (v instanceof Object) { this.x = v.x; this.y = v.y; this.z = v.z; } // String else if (typeof(v) == "string") { var m = v.match(/(-?\d+(\.{1}\d+)?),\s*(-?\d+(\.{1}\d+)?),\s*(-?\d+(\.{1}\d+)?)/); this.x = parseFloat(m[1]); this.y = parseFloat(m[3]); this.z = parseFloat(m[5]); } return this; }, /** * 加算 */ add: function(v) { this.x += v.x; this.y += v.y; this.z += v.z; return this; }, /** * 減算 */ sub: function(v) { this.x -= v.x; this.y -= v.y; this.z -= v.z; return this; }, /** * 乗算 */ mul: function(n) { this.x *= n; this.y *= n; this.z *= n; return this; }, /** * 除算 */ div: function(n) { console.assert(n != 0, "0 division!!"); this.x /= n; this.y /= n; this.z /= n; return this; }, /** * 反転 */ negate: function() { this.x = -this.x; this.y = -this.y; this.z = -this.z; return this; }, /** * 内積. * 投影ベクトルを求めたり, 類似度に使ったり. */ dot: function(v) { return this.x * v.x + this.y * v.y + this.z * v.z; }, /** * 外積 */ cross: function(v) { var x = this.y*v.z - this.z*v.y; var y = this.z*v.x - this.x*v.z; var z = this.x*v.y - this.y*v.x; this.set(x, y, z); return this; }, /** * 長さを取得 * or magnitude */ length: function() { return Math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z); }, /** * 2乗された長さを取得 * C# の名前を引用 * or lengthSquare or lengthSqrt */ lengthSquared: function() { return this.x*this.x + this.y*this.y + this.z*this.z; }, /** * 正規化 */ normalize: function() { var length = this.length(); this.div(length); return this; }, /** * @TODO ? */ toVector2: function() { // TODO: }, /** * 角度(radian)に変換 */ toAngleXY: function() { return Math.atan2(this.y, this.x); }, /** * 3D化する */ to3D: function() { // TODO: 3d化する }, /** * 等しいか */ equals: function(x, y, z) { return ( (this.x === x) && (this.y === y) && (this.z === z) ); }, // equals: function(obj) { // return this.equals(obj.x, obj.y, obj.z); // }, /** * 配列と等しいか */ equalsArray: function(arr) { return this.equals(arr[0], arr[1], arr[2]); }, /** * オブジェクトと等しいか */ equalsObject: function(obj) { return this.equals(obj.x, obj.y, obj.z); }, /** * 賢い比較 */ equalsSmart: function() { // TODO: }, /** * @TODO ? */ toStyleString: function() { return "{x:{x}, y:{y}, z:{z}}".format(this); }, /** * @TODO ? */ toString: function() { return "{x:{x}, y:{y}, z:{z}}".format(this); }, /** * X値をセット * チェーンメソッド用セッター */ setX: function(x) { this.x = x; return this; }, /** * Y値をセット * チェーンメソッド用セッター */ setY: function(y) { this.y = y; return this; }, /** * Z値をセット * チェーンメソッド用セッター */ setZ: function(z) { this.z = z; return this; } }); /** * @method * @static * min */ tm.geom.Vector3.min = function(lhs, rhs) { return Vector3( (lhs.x < rhs.x) ? lhs.x : rhs.x, (lhs.y < rhs.y) ? lhs.y : rhs.y, (lhs.z < rhs.z) ? lhs.z : rhs.z ); }; /** * @method * @static * max */ tm.geom.Vector3.max = function(lhs, rhs) { return Vector3( (lhs.x > rhs.x) ? lhs.x : rhs.x, (lhs.y > rhs.y) ? lhs.y : rhs.y, (lhs.z > rhs.z) ? lhs.z : rhs.z ); }; /** * @method * @static * 加算 */ tm.geom.Vector3.add = function(lhs, rhs) { return tm.geom.Vector3(lhs.x+rhs.x, lhs.y+rhs.y, lhs.z+rhs.z); }; /** * @method * @static * 減算 */ tm.geom.Vector3.sub = function(lhs, rhs) { return tm.geom.Vector3(lhs.x-rhs.x, lhs.y-rhs.y, lhs.z-rhs.z); }; /** * @method * @static * 乗算 */ tm.geom.Vector3.mul = function(v, n) { return tm.geom.Vector3(v.x*n, v.y*n, v.z*n); }; /** * @method * @static * 割算 */ tm.geom.Vector3.div = function(v, n) { return tm.geom.Vector3(v.x/n, v.y/n, v.z/n); }; /** * @method * @static * 内積. * 投影ベクトルを求めたり, 類似度に使ったり. */ tm.geom.Vector3.dot = function(lhs, rhs) { return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z; }; /** * @method * @static * 外積 */ tm.geom.Vector3.cross = function(lhs, rhs) { return tm.geom.Vector3( lhs.y*rhs.z - lhs.z*rhs.y, lhs.z*rhs.x - lhs.x*rhs.z, lhs.x*rhs.y - lhs.y*rhs.x ); }; /** * @method * @static * 反転 */ tm.geom.Vector3.negate = function(v) { return tm.geom.Vector3(-v.x, -v.y, -v.z); }; /** * @method * @static * 2点間の距離を返す */ tm.geom.Vector3.distance = function(lhs, rhs) { return Math.sqrt( Math.pow(lhs.x-rhs.x, 2) + Math.pow(lhs.y-rhs.y, 2) + Math.pow(lhs.z-rhs.z, 2) ); }; /** * @method * @static * 2点間の距離を返す */ tm.geom.Vector3.distanceSquared = function(lhs, rhs) { return Math.pow(lhs.x-rhs.x, 2) + Math.pow(lhs.y-rhs.y, 2) + Math.pow(lhs.z-rhs.z, 2); }; /** * @method * @static * マンハッタン距離 */ tm.geom.Vector3.manhattanDistance = function(lhs, rhs) { return Math.abs(lhs.x-rhs.x) + Math.abs(lhs.y-rhs.y) + Math.abs(lhs.z-rhs.z); }; /** * @method * @static * 反射ベクトル */ tm.geom.Vector3.reflect = function(v, normal) { var len = Vector3.dot(v, normal); var temp= Vector3.mul(normal, 2*len); return Vector3.sub(v, temp); }; /** * @method * @static * 補間. * 0.5 で lhs と rhs の中間ベクトルを求めることができます. */ tm.geom.Vector3.lerp = function(lhs, rhs, t) { return tm.geom.Vector3( lhs.x + (rhs.x-lhs.x)*t, lhs.y + (rhs.y-lhs.y)*t, lhs.z + (rhs.z-lhs.z)*t ); }; /** * @method * @static * 補間 */ tm.geom.Vector3.slerp = function(lhs, rhs, t) { // TODO: // cos... }; /** * @method * @static * min ~ max の間でランダムな方向のベクトルを生成する. len で長さ指定. */ tm.geom.Vector3.random = function(thetaMin, thetaMax, phiMin, phiMax, len) { thetaMin= thetaMin || 0; thetaMax= thetaMax || 360; phiMin = phiMin || 0; phiMax = phiMax || 360; len = len || 1; return TM.Geom.Vector3().setFromDegree(TM.randomf(thetaMin, thetaMax), TM.randomf(phiMin, phiMax), len); }; /* Vector3.prototype.accessor("length", { "get": function() { return this.length(); }, "set": function(len) { this.normalize().mul(len); } }); */ /** * @property * @static * zero */ tm.geom.Vector3.ZERO = tm.geom.Vector3( 0, 0, 0); /** * @property * @static * left */ tm.geom.Vector3.LEFT = tm.geom.Vector3(-1, 0, 0); /** * @property * @static * right */ tm.geom.Vector3.RIGHT = tm.geom.Vector3( 1, 0, 0); /** * @property * @static * up */ tm.geom.Vector3.UP = tm.geom.Vector3( 0, 1, 0); /** * @property * @static * down */ tm.geom.Vector3.DOWN = tm.geom.Vector3( 0,-1, 0); /** * @property * @static * forward */ tm.geom.Vector3.FORWARD = tm.geom.Vector3( 0, 0,-1); /** * @property * @static * backward */ tm.geom.Vector3.BACKWARD= tm.geom.Vector3( 0, 0, 1); })(); /* * matrix33.js */ tm.geom = tm.geom || {}; (function() { /** * @class tm.geom.Matrix33 * 3*3 マトリックスクラス */ tm.define("tm.geom.Matrix33", { /** * 要素 */ m: null, /** * @constructor */ init: function() { this.m = []; if (arguments.length >= 9) { this.set.apply(this, arguments); } else { this.identity(); } }, /** * クローン */ clone: function() { var m = this.m; return tm.geom.Matrix33( m[0], m[3], m[6], m[1], m[4], m[7], m[2], m[5], m[8] ); }, /** * セッター */ set: function(m00, m01, m02, m10, m11, m12, m20, m21, m22) { console.assert(arguments.length>=9, ""); // |m00, m01, m02| // |m10, m11, m12| // |m20, m21, m22| // |m[0], m[3], m[6]| // |m[1], m[4], m[7]| // |m[2], m[5], m[8]| // |a, b, tx| // |c, d, ty| // |0, 0, 1| this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m20 = m20; this.m21 = m21; this.m22 = m22; return this; }, /** * 配列からセット */ setArray: function(arr) { this.set( arr[0], arr[3], arr[6], arr[1], arr[4], arr[7], arr[2], arr[5], arr[8] ); return this; }, /** * オブジェクトからセット */ setObject: function(obj) { this.set( obj.m00, obj.m01, obj.m02, obj.m10, obj.m11, obj.m12, obj.m20, obj.m21, obj.m22 ); return this; }, /** * 単位行列 */ identity: function() { var m = this.m; m[0] = 1; m[3] = 0; m[6] = 0; m[1] = 0; m[4] = 1; m[7] = 0; m[2] = 0; m[5] = 0; m[8] = 1; return this; }, /** * 転置 */ transpose: function() { this.m.swap(1, 3); this.m.swap(2, 6); this.m.swap(5, 7); return this; }, /** * 逆行列 */ invert: function() { var m = this.m; var m00 = m[0], m01 = m[3], m02 = m[6]; var m10 = m[1], m11 = m[4], m12 = m[7]; var m20 = m[2], m21 = m[5], m22 = m[8]; var det = this.determinant(); // |m00, m01, m02| // |m10, m11, m12| // |m20, m21, m22| this.m00 = (m11*m22-m12*m21)/det; this.m01 = (m10*m22-m12*m20)/det*-1; this.m02 = (m10*m21-m11*m20)/det; this.m10 = (m01*m22-m02*m21)/det*-1; this.m11 = (m00*m22-m02*m20)/det; this.m12 = (m00*m21-m01*m20)/det*-1; this.m20 = (m01*m12-m02*m11)/det; this.m21 = (m00*m12-m02*m10)/det*-1; this.m22 = (m00*m11-m01*m10)/det; this.transpose(); return this; }, /** * @TODO ? */ determinant: function() { var m = this.m; var m00 = m[0], m01 = m[3], m02 = m[6]; var m10 = m[1], m11 = m[4], m12 = m[7]; var m20 = m[2], m21 = m[5], m22 = m[8]; return m00*m11*m22 + m10*m21*m02 + m01*m12*m20 - m02*m11*m20 - m01*m10*m22 - m12*m21*m00; }, /** * ゼロクリア */ zero: function() { this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0 ); return this; }, /** * 移動 */ translate: function(x, y) { var m = this.m; m[6] = m[0] * x + m[3] * y + m[6]; m[7] = m[1] * x + m[4] * y + m[7]; m[8] = m[2] * x + m[5] * y + m[8]; return this; return this.multiply( tm.geom.Matrix33.translate(x, y) ); }, /** * X軸回転 */ rotateX: function(rad) { return this.multiply( tm.geom.Matrix33.rotateX(rad) ); }, /** * Y軸回転 */ rotateY: function(rad) { return this.multiply( tm.geom.Matrix33.rotateY(rad) ); }, /** * Z軸回転 */ rotateZ: function(rad) { var s = Math.sin(rad); var c = Math.cos(rad); var m = this.m; var m00 = m[0]; var m10 = m[1]; var m20 = m[2]; var m01 = m[3]; var m11 = m[4]; var m21 = m[5]; return this.multiply( tm.geom.Matrix33.rotateZ(rad) ); }, /** * スケーリング */ scale: function(x, y) { var m = this.m; m[0] *= x; m[3] *= y; m[1] *= x; m[4] *= y; m[2] *= x; m[5] *= y; return this; return this.multiply( tm.geom.Matrix33.scale(x, y) ); }, /** * 掛け算 */ multiply: function(mat) { var tm = this.m; var om = mat.m; var a00 = tm[0], a01 = tm[3], a02 = tm[6]; var a10 = tm[1], a11 = tm[4], a12 = tm[7]; var a20 = tm[2], a21 = tm[5], a22 = tm[8]; var b00 = om[0], b01 = om[3], b02 = om[6]; var b10 = om[1], b11 = om[4], b12 = om[7]; var b20 = om[2], b21 = om[5], b22 = om[8]; tm[0] = a00*b00 + a01*b10 + a02*b20; tm[3] = a00*b01 + a01*b11 + a02*b21; tm[6] = a00*b02 + a01*b12 + a02*b22; tm[1] = a10*b00 + a11*b10 + a12*b20; tm[4] = a10*b01 + a11*b11 + a12*b21; tm[7] = a10*b02 + a11*b12 + a12*b22; tm[2] = a20*b00 + a21*b10 + a22*b20; tm[5] = a20*b01 + a21*b11 + a22*b21; tm[8] = a20*b02 + a21*b12 + a22*b22; return this; }, /** * ベクトルとの掛け算 */ multiplyVector2: function(v) { var vx = this.m00*v.x + this.m01*v.y + this.m02; var vy = this.m10*v.x + this.m11*v.y + this.m12; return tm.geom.Vector2(vx, vy); }, /** * ベクトルとの掛け算 */ multiplyVector3: function(v) { var vx = this.m00*v.x + this.m01*v.y + this.m02*v.z; var vy = this.m10*v.x + this.m11*v.y + this.m12*v.z; var vz = this.m20*v.x + this.m21*v.y + this.m22*v.z; return tm.geom.Vector3(vx, vy, vz); }, /** * 配列に変換 */ toArray: function() { return this.m.slice(); }, /** * 文字列化 */ toString: function() { return "|{m00}, {m01}, {m02}|\n|{m10}, {m11}, {m12}|\n|{m20}, {m21}, {m22}|".format(this); }, }); /** * @property m00 * 要素 */ tm.geom.Matrix33.prototype.accessor("m00", { "get": function() { return this.m[0]; }, "set": function(v) { this.m[0] = v; } }); /** * @property m10 * 要素 */ tm.geom.Matrix33.prototype.accessor("m10", { "get": function() { return this.m[1]; }, "set": function(v) { this.m[1] = v; } }); /** * @property m20 * 要素 */ tm.geom.Matrix33.prototype.accessor("m20", { "get": function() { return this.m[2]; }, "set": function(v) { this.m[2] = v; } }); /** * @property m01 * 要素 */ tm.geom.Matrix33.prototype.accessor("m01", { "get": function() { return this.m[3]; }, "set": function(v) { this.m[3] = v; } }); /** * @property m11 * 要素 */ tm.geom.Matrix33.prototype.accessor("m11", { "get": function() { return this.m[4]; }, "set": function(v) { this.m[4] = v; } }); /** * @property m21 * 要素 */ tm.geom.Matrix33.prototype.accessor("m21", { "get": function() { return this.m[5]; }, "set": function(v) { this.m[5] = v; } }); /** * @property m02 * 要素 */ tm.geom.Matrix33.prototype.accessor("m02", { "get": function() { return this.m[6]; }, "set": function(v) { this.m[6] = v; } }); /** * @property m12 * 要素 */ tm.geom.Matrix33.prototype.accessor("m12", { "get": function() { return this.m[7]; }, "set": function(v) { this.m[7] = v; } }); /** * @property m22 * 要素 */ tm.geom.Matrix33.prototype.accessor("m22", { "get": function() { return this.m[8]; }, "set": function(v) { this.m[8] = v; } }); /** * @property a * 要素 */ tm.geom.Matrix33.prototype.accessor("a", { "get": function() { return this.m[0]; }, "set": function(v) { this.m[0] = v; } }); /** * @property b * 要素 */ tm.geom.Matrix33.prototype.accessor("b", { "get": function() { return this.m[3]; }, "set": function(v) { this.m[3] = v; } }); /** * @property c * 要素 */ tm.geom.Matrix33.prototype.accessor("c", { "get": function() { return this.m[1]; }, "set": function(v) { this.m[1] = v; } }); /** * @property d * 要素 */ tm.geom.Matrix33.prototype.accessor("d", { "get": function() { return this.m[4]; }, "set": function(v) { this.m[4] = v; } }); /** * @property tx * 要素 */ tm.geom.Matrix33.prototype.accessor("tx", { "get": function() { return this.m[6]; }, "set": function(v) { this.m[6] = v; } }); /** * @property ty * 要素 */ tm.geom.Matrix33.prototype.accessor("ty", { "get": function() { return this.m[7]; }, "set": function(v) { this.m[7] = v; } }); /** * @static * @method * 移動 */ tm.geom.Matrix33.translate = function(x, y) { return tm.geom.Matrix33( 1, 0, x, 0, 1, y, 0, 0, 1 ); }; /** * @static * @method * X軸回転 */ tm.geom.Matrix33.rotateX = function(rad) { var c = Math.cos(rad); var s = Math.sin(rad); return tm.geom.Matrix33( 1, 0, 0, 0, c,-s, 0, s, c ); }; /** * @static * @method * Y軸回転 */ tm.geom.Matrix33.rotateY = function(rad) { var c = Math.cos(rad); var s = Math.sin(rad); return tm.geom.Matrix33( c, 0, s, 0, 1, 0, -s, 0, c ); }; /** * @static * @method * Z軸回転 */ tm.geom.Matrix33.rotateZ = function(rad) { var c = Math.cos(rad); var s = Math.sin(rad); return tm.geom.Matrix33( c,-s, 0, s, c, 0, 0, 0, 1 ); }; /** * @static * @method * スケーリング */ tm.geom.Matrix33.scale = function(x, y) { var mat = tm.geom.Matrix33(); if (y == undefined) y = x; mat.set( x, 0, 0, 0, y, 0, 0, 0, 1 ); return mat; }; })(); /* * matrix44.js */ tm.geom = tm.geom || {}; (function() { /** * @class * 4*4 マトリックスクラス */ tm.geom.Matrix44 = tm.createClass({ /** 要素 */ m: null, /** * @constructor */ init: function() { this.m = []; if (arguments.length >= 16) { this.set.apply(this, arguments); } else { this.identity(); } }, /** * セット */ set: function(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) { console.assert(arguments.length>=16, ""); // |m00, m01, m02, m03| // |m10, m11, m12, m13| // |m20, m21, m22, m23| // |m30, m31, m32, m33| this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m03 = m03; this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m13 = m13; this.m20 = m20; this.m21 = m21; this.m22 = m22; this.m23 = m23; this.m30 = m30; this.m31 = m31; this.m32 = m32; this.m33 = m33; return this; }, /** * 配列からセット */ setArray: function(arr) { this.set( arr[0], arr[4], arr[8], arr[12], arr[1], arr[5], arr[9], arr[13], arr[2], arr[6], arr[10], arr[14], arr[3], arr[7], arr[11], arr[15] ); return this; }, /** * オブジェクトからセット. * Matrix44 もこいつでいける!! */ setObject: function(obj) { this.set( obj.m00, obj.m01, obj.m02, obj.m03, obj.m10, obj.m11, obj.m12, obj.m13, obj.m20, obj.m21, obj.m22, obj.m23, obj.m30, obj.m31, obj.m32, obj.m33 ); return this; }, /** * 単位行列 */ identity: function() { this.set( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ); return this; }, /** * 転置 */ transpose: function() { this.m.swap(1, 4); this.m.swap(2, 8); this.m.swap(3, 12); this.m.swap(6, 9); this.m.swap(7, 13); this.m.swap(11, 14); return this; }, /** * 移動 */ translate: function(x, y, z) { return this.multiply( tm.geom.Matrix44.translate(x, y, z) ); }, /** * 回転 */ rotate: function(angle) { // TODO: いつか実装する console.error("Unimplemented"); }, /** * X軸を基軸に回転する */ rotateX: function(rad) { return this.multiply( tm.geom.Matrix44.rotateX(rad) ); }, /** * Y軸を基軸に回転する */ rotateY: function(rad) { return this.multiply( tm.geom.Matrix44.rotateY(rad) ); }, /** * Z軸を基軸に回転する */ rotateZ: function(rad) { return this.multiply( tm.geom.Matrix44.rotateZ(rad) ); }, /** * スケーリング */ scale: function(x, y, z) { return this.multiply( tm.geom.Matrix44.scale(x, y, z) ); }, /** * ゼロ */ zero: function() { this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); return this; }, /** * 乗算 * this * mat */ multiply: function(mat) { var m00 = this.m00*mat.m00 + this.m01*mat.m10 + this.m02*mat.m20 + this.m03*mat.m30; var m01 = this.m00*mat.m01 + this.m01*mat.m11 + this.m02*mat.m21 + this.m03*mat.m31; var m02 = this.m00*mat.m02 + this.m01*mat.m12 + this.m02*mat.m22 + this.m03*mat.m32; var m03 = this.m00*mat.m03 + this.m01*mat.m13 + this.m02*mat.m23 + this.m03*mat.m33; var m10 = this.m10*mat.m00 + this.m11*mat.m10 + this.m12*mat.m20 + this.m13*mat.m30; var m11 = this.m10*mat.m01 + this.m11*mat.m11 + this.m12*mat.m21 + this.m13*mat.m31; var m12 = this.m10*mat.m02 + this.m11*mat.m12 + this.m12*mat.m22 + this.m13*mat.m32; var m13 = this.m10*mat.m03 + this.m11*mat.m13 + this.m12*mat.m23 + this.m13*mat.m33; var m20 = this.m20*mat.m00 + this.m21*mat.m10 + this.m22*mat.m20 + this.m23*mat.m30; var m21 = this.m20*mat.m01 + this.m21*mat.m11 + this.m22*mat.m21 + this.m23*mat.m31; var m22 = this.m20*mat.m02 + this.m21*mat.m12 + this.m22*mat.m22 + this.m23*mat.m32; var m23 = this.m20*mat.m03 + this.m21*mat.m13 + this.m22*mat.m23 + this.m23*mat.m33; var m30 = this.m30*mat.m00 + this.m31*mat.m10 + this.m32*mat.m20 + this.m33*mat.m30; var m31 = this.m30*mat.m01 + this.m31*mat.m11 + this.m32*mat.m21 + this.m33*mat.m31; var m32 = this.m30*mat.m02 + this.m31*mat.m12 + this.m32*mat.m22 + this.m33*mat.m32; var m33 = this.m30*mat.m03 + this.m31*mat.m13 + this.m32*mat.m23 + this.m33*mat.m33; return this.set( m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33 ); }, /* getAxisX: function() { return TM.Geom.Vector3(this.m00, this.m10, this.m20); }, getAxisY: function() { return TM.Geom.Vector3(this.m01, this.m11, this.m21); }, getAxisZ: function() { return TM.Geom.Vector3(this.m02, this.m12, this.m22); }, */ /** * @TODO ? */ getAxisX: function() { return TM.Geom.Vector3(this.m00, this.m01, this.m02); }, /** * @TODO ? */ getAxisY: function() { return TM.Geom.Vector3(this.m10, this.m11, this.m12); }, /** * @TODO ? */ getAxisZ: function() { return TM.Geom.Vector3(this.m20, this.m21, this.m22); }, /** * @TODO ? */ setAxisX: function(v) { this.m00=v.x, this.m01=v.y, this.m02=v.z; }, /** * @TODO ? */ setAxisY: function(v) { this.m10=v.x, this.m11=v.y, this.m12=v.z; }, /** * @TODO ? */ setAxisZ: function(v) { this.m20=v.x, this.m21=v.y, this.m22=v.z; }, /** * Matrix33 に変換 */ toMatrix33: function() { // TODO: }, /** * 配列に変換 */ toArray: function() { return this.m.slice(); }, /** * 文字列化 */ toString: function() { return "|{m00}, {m01}, {m02}, {m03}|\n|{m10}, {m11}, {m12}, {m13}|\n|{m20}, {m21}, {m22}, {m23}|\n|{m30}, {m31}, {m32}, {m33}|".format(this); } }); /** * @property m00 * 要素 */ tm.geom.Matrix44.prototype.accessor("m00", { "get": function() { return this.m[0]; }, "set": function(v) { this.m[0] = v; } }); /** * @property m01 * 要素 */ tm.geom.Matrix44.prototype.accessor("m10", { "get": function() { return this.m[1]; }, "set": function(v) { this.m[1] = v; } }); /** * @property m02 * 要素 */ tm.geom.Matrix44.prototype.accessor("m20", { "get": function() { return this.m[2]; }, "set": function(v) { this.m[2] = v; } }); /** * @property m03 * 要素 */ tm.geom.Matrix44.prototype.accessor("m30", { "get": function() { return this.m[3]; }, "set": function(v) { this.m[3] = v; } }); /** * @property m10 * 要素 */ tm.geom.Matrix44.prototype.accessor("m01", { "get": function() { return this.m[4]; }, "set": function(v) { this.m[4] = v; } }); /** * @property m11 * 要素 */ tm.geom.Matrix44.prototype.accessor("m11", { "get": function() { return this.m[5]; }, "set": function(v) { this.m[5] = v; } }); /** * @property m12 * 要素 */ tm.geom.Matrix44.prototype.accessor("m21", { "get": function() { return this.m[6]; }, "set": function(v) { this.m[6] = v; } }); /** * @property m13 * 要素 */ tm.geom.Matrix44.prototype.accessor("m31", { "get": function() { return this.m[7]; }, "set": function(v) { this.m[7] = v; } }); /** * @property m20 * 要素 */ tm.geom.Matrix44.prototype.accessor("m02", { "get": function() { return this.m[8]; }, "set": function(v) { this.m[8] = v; } }); /** * @property m21 * 要素 */ tm.geom.Matrix44.prototype.accessor("m12", { "get": function() { return this.m[9]; }, "set": function(v) { this.m[9] = v; } }); /** * @property m22 * 要素 */ tm.geom.Matrix44.prototype.accessor("m22", { "get": function() { return this.m[10]; }, "set": function(v) { this.m[10] = v; } }); /** * @property m23 * 要素 */ tm.geom.Matrix44.prototype.accessor("m32", { "get": function() { return this.m[11]; }, "set": function(v) { this.m[11] = v; } }); /** * @property m30 * 要素 */ tm.geom.Matrix44.prototype.accessor("m03", { "get": function() { return this.m[12]; }, "set": function(v) { this.m[12] = v; } }); /** * @property m31 * 要素 */ tm.geom.Matrix44.prototype.accessor("m13", { "get": function() { return this.m[13]; }, "set": function(v) { this.m[13] = v; } }); /** * @property m32 * 要素 */ tm.geom.Matrix44.prototype.accessor("m23", { "get": function() { return this.m[14]; }, "set": function(v) { this.m[14] = v; } }); /** * @property m33 * 要素 */ tm.geom.Matrix44.prototype.accessor("m33", { "get": function() { return this.m[15]; }, "set": function(v) { this.m[15] = v; } }); /** * @static * @method * 移動 */ tm.geom.Matrix44.translate = function(x, y, z) { return tm.geom.Matrix44( 1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z, 0, 0, 0, 1 ); }; /** * @static * @method * X軸回転 */ tm.geom.Matrix44.rotateX = function(rad) { var c = Math.cos(rad); var s = Math.sin(rad); return tm.geom.Matrix44( 1, 0, 0, 0, 0, c,-s, 0, 0, s, c, 0, 0, 0, 0, 1 ); }; /** * @static * @method * Y軸回転 */ tm.geom.Matrix44.rotateY = function(rad) { var c = Math.cos(rad); var s = Math.sin(rad); return tm.geom.Matrix44( c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1 ); }; /** * @static * @method * Z軸回転 */ tm.geom.Matrix44.rotateZ = function(rad) { var c = Math.cos(rad); var s = Math.sin(rad); return tm.geom.Matrix44( c,-s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ); }; /** * @static * @method * スケーリング */ tm.geom.Matrix44.scale = function(x, y, z) { var mat = tm.geom.Matrix44(); if (y == undefined) y = x; if (z == undefined) z = x; mat.set( x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1 ); return mat; }; /** * @static * @method * perspective */ tm.geom.Matrix44.perspective = function(fovy, aspect, znear, zfar) { var yscale = 1.0 / Math.tan(0.5*fovy*Math.PI/180); var xscale = yscale / aspect; return tm.geom.Matrix44( xscale, 0.0, 0.0, 0.0, 0.0, yscale, 0.0, 0.0, 0.0, 0.0, zfar/(zfar-znear), znear*zfar/(znear-zfar), 0.0, 0.0, 1.0, 0.0 ); }; /** * @static * @method * ortho */ tm.geom.Matrix44.ortho = function(left, right, bottom, top, near, far) { /* var lr = 1 / (left - right), bt = 1 / (bottom - top), nf = 1 / (near - far); return tm.geom.Matrix44( -2*lr, 0, 0, 0, 0, -2*bt, 0, 0, 0, 0, 2*nf, 0, (left+right)*lr, (top+bottom)*bt, (far+near)*nf, 1 ); */ var rl = (right - left), tb = (top - bottom), fn = (far - near); return tm.geom.Matrix44( 2.0/rl, 0, 0, 0, 0.0, 2.0/tb, 0, 0, 0, 0, -2.0/fn, 0, -(left+right)/rl, -(top+bottom)/tb, -(far+near)/fn, 1 ).transpose(); }; /** * @static * @method * lookAt */ tm.geom.Matrix44.lookAt = function(eye, target, up) { var axis_z = tm.geom.Vector3.sub(eye, target).normalize(); var axis_x = tm.geom.Vector3.cross(up, axis_z).normalize(); var axis_y = tm.geom.Vector3.cross(axis_z, axis_x).normalize(); /* return tm.geom.Matrix44( axis_x.x, axis_x.y, axis_x.z, -tm.geom.Vector3.dot(eye, axis_x), axis_y.x, axis_y.y, axis_y.z, -tm.geom.Vector3.dot(eye, axis_y), axis_z.x, axis_z.y, axis_z.z, -tm.geom.Vector3.dot(eye, axis_z), 0, 0, 0, 1 ); */ /* return tm.geom.Matrix44( axis_x.x, axis_y.x, axis_z.x, 0, axis_x.y, axis_y.y, axis_z.y, 0, axis_x.z, axis_y.z, axis_z.z, 0, -tm.geom.Vector3.dot(eye, axis_x), -tm.geom.Vector3.dot(eye, axis_y), -tm.geom.Vector3.dot(eye, axis_z), 1 ); */ var orientation = tm.geom.Matrix44( axis_x.x, axis_y.x, axis_z.x, 0, axis_x.y, axis_y.y, axis_z.y, 0, axis_x.z, axis_y.z, axis_z.z, 0, 0, 0, 0, 1 ); var translation = tm.geom.Matrix44( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -eye.x, -eye.y, -eye.z, 1 ); return translation.multiply(orientation); }; })(); /* * rect.js */ tm.geom = tm.geom || {}; (function() { /** * @class tm.geom.Rect * 四角形クラス */ tm.geom.Rect = tm.createClass({ /** x */ x: 0, /** y */ y: 0, /** 幅 */ width: 0, /** 高さ */ height: 0, /** * @constructor */ init: function(x, y, width, height) { this.set(x, y, width, height); }, /** * セッター */ set: function(x, y, width, height) { this.x = x; this.y = y; this.width = width; this.height = height; return this; }, /** * 移動 */ move: function(x, y) { this.x = x; this.y = y; return this; }, /** * 現在位置を基準に移動 */ moveBy: function(x, y) { this.x += x; this.y += y; return this; }, /** * リサイズ */ resize: function(w, h) { this.width = w; this.height= h; return this; }, /** * 現在のサイズを基準にリサイズ */ resizeBy: function(w, h) { this.width += w; this.height+= h; return this; }, /** * パディング. * 縮めたりなど. 画面ハミ出しチェック時などに便利 * ## example * var circle = TM.$Circle(10, 10, 10); * var windowRect = TM.$Rect(0, 0, window.innerWidth, window.innerHiehgt); * windowRect.padding(circle.radius); * if (circle.x < windowRect.left) { * // 左にはみ出した時の処理 * } */ padding: function(top, right, bottom, left) { // css の padding に合わせて時計回りにパラメータ調整 switch (arguments.length) { case 1: top = right = bottom = left = arguments[0]; break; case 2: top = bottom = arguments[0]; right = left = arguments[1]; break; case 3: top = arguments[0]; right = left = arguments[1]; bottom = arguments[2]; break; } this.x += left; this.y += top; this.width -= left+right; this.height-= top +bottom; return this; }, /** * クローン */ clone: function() { return tm.geom.Rect(this.x, this.y, this.width, this.height); }, /** * @TODO ? */ toCircle: function() { return tm.geom.Circle( this.centerX, this.centerY, ((this.width < this.height) ? this.width : this.height)/2 ); }, /** * @TODO ? */ toArray: function() { return [this.x, this.y, this.width, this.height]; }, }); /** * @property left * left */ tm.geom.Rect.prototype.accessor("left", { "get": function() { return this.x; }, "set": function(v) { this.width -= v-this.x; this.x = v; } }); /** * @property top * top */ tm.geom.Rect.prototype.accessor("top", { "get": function() { return this.y; }, "set": function(v) { this.height -= v-this.y; this.y = v; } }); /** * @property right * right */ tm.geom.Rect.prototype.accessor("right", { "get": function() { return this.x + this.width; }, "set": function(v) { this.width += v-this.right; } }); /** * @property bottom * bottom */ tm.geom.Rect.prototype.accessor("bottom", { "get": function() { return this.y + this.height; }, "set": function(v) { this.height += v-this.bottom; } }); /** * @property centerX * centerX */ tm.geom.Rect.prototype.accessor("centerX", { "get": function() { return this.x + this.width/2; }, "set": function(v) { // TODO: どうしようかな?? } }); /** * @property centerY * centerY */ tm.geom.Rect.prototype.accessor("centerY", { "get": function() { return this.y + this.height/2; }, "set": function(v) { // TODO: どうしようかな?? } }); })(); /* * circle.js */ tm.geom = tm.geom || {}; (function() { /** * @class tm.geom.Circle * 円クラス */ tm.define("tm.geom.Circle", { /** x */ x: 0, /** y */ y: 0, /** 半径 */ radius: 0, /** * @constructor */ init: function(x, y, radius) { this.set(x, y, radius); }, /** * セッター */ set: function(x, y, radius) { this.x = x; this.y = y; this.radius = radius; return this; }, /** * 移動 */ move: function(x, y) { this.x = x; this.y = y; return this; }, /** * 現在位置を基準に移動 */ moveBy: function(x, y) { this.x += x; this.y += y; return this; }, /** * リサイズ */ resize: function(size) { this.radius = size; return this; }, /** * 現在のサイズを基準にリサイズ */ resizeBy: function(size) { this.radius += size; return this; }, /** * クローン作成 */ clone: function() { return tm.geom.Circle(this.x, this.y, this.radius); }, /** * 四角形に変換 */ toRect: function() { return tm.geom.Rect( this.x - this.radius, this.y - this.radius, this.radius*2, this.radius*2 ); }, /** * 配列に変換 */ toArray: function() { return [this.x, this.y, this.radius]; } }); /** * @property left * left */ tm.geom.Circle.prototype.getter("left", function() { return this.x - this.radius; }); /** * @property top * top */ tm.geom.Circle.prototype.getter("top", function() { return this.y - this.radius; }); /** * @property right * right */ tm.geom.Circle.prototype.getter("right", function() { return this.x + this.radius; }); /** * @property bottom * bottom */ tm.geom.Circle.prototype.getter("bottom", function() { return this.y + this.radius; }); })(); /* * collision.js */ tm.collision = tm.collision || {}; (function() { /** * @class tm.collision * 衝突判定 */ tm.collision; /** * @method testCircleCircle * 円同士の衝突判定 */ tm.collision.testCircleCircle = function(circle0, circle1) { var distanceSquared = tm.geom.Vector2.distanceSquared(circle0, circle1); return distanceSquared <= Math.pow(circle0.radius + circle1.radius, 2); } /** * @method testRectRect * 矩形同士の衝突判定 */ tm.collision.testRectRect = function(rect0, rect1) { return (rect0.left < rect1.right) && (rect0.right > rect1.left) && (rect0.top < rect1.bottom) && (rect0.bottom > rect1.top); } })(); /* * element.js */ tm.dom = tm.dom || {}; (function() { /** * @class * Element クラス */ tm.dom.Element = tm.createClass({ /** エレメント */ element: null, /** * @constructor */ init: function() { this.set.apply(this, arguments); }, /** * セッター */ set: function(q) { if (typeof q === "string") { this.element = document.querySelector(q); } else if (q != undefined) { this.element = q; } else { // デフォルトはドキュメント this.element = document; } }, /** * 子供の最後尾に追加 */ append: function(child) { this.element.appendChild(child.element); return this; }, /** * 子供の先頭に追加 */ prepend: function(child) { this.element.insertBefore(child.element, this.element.firstChild); return this; }, /** * 自分の後に追加 */ after: function(child) { this.element.parentNode.insertBefore(child.element, this.element.nextSibling); return this; }, /** * 自分の前に追加 */ before: function(child) { this.element.parentNode.insertBefore(child.element, this.element); return this; }, /** * 引数に渡された要素に自分を append */ appendTo: function(parent) { parent.append(this); return this; }, /** * 引数に渡された要素に自分を prepend */ prependTo: function(parent) { parent.prepend(this); return this; }, /** * 複製 */ clone: function() { return tm.dom.Element(this.element.cloneNode(true)); }, /** * 親から自分を引っぺがす */ remove: function() { this.element.parentNode.removeChild(this.element); return this; }, /** * 要素生成 */ create: function(tag, addFuncName) { // 要素を生成 var element = tm.dom.Element(document.createElement(tag)); // デフォルトの追加方法は append if (!addFuncName) { addFuncName="append"; } // 自分の子供として追加 this[addFuncName](element); return element; }, /** * query */ query: function(query, index) { var elm = (index) ? this.element.querySelectorAll(query)[index] : this.element.querySelector(query); return tm.dom.Element(elm); }, /** * queryAll */ queryAll: function(query) { var list = this.element.querySelectorAll(query); return tm.dom.ElementList(list); }, /** * 固定化 */ fixed: function(x, y, width, height) { this.style.set("position", "fixed"); if (x) this.x = x; if (y) this.y = y; if (width) this.width = width; if (height) this.height = height; return this; }, /** * absolute 化 */ absolute: function(x, y, width, height) { this.style.set("position", "absolute"); if (x) this.x = x; if (y) this.y = y; if (width) this.width = width; if (height) this.height = height; return this; }, /** * フルスクリーン化 */ fullScreen: function() { this.element.webkitRequestFullScreen(); }, /** * @TODO ? */ show: function() { this.visible = true; }, /** * @TODO ? */ hide: function() { this.visible = false; }, /** * @TODO ? */ toString: function() { return "tm.dom.element"; }, /** * @TODO ? */ getElement: function() { return this.element; }, }); /** @property html html の値 */ tm.dom.Element.prototype.accessor("html", { "get": function() { return this.element.innerHTML; }, "set": function(html) { this.element.innerHTML = html; } }); /** @property value value の値 */ tm.dom.Element.prototype.accessor("value", { "get": function() { return this.element.value; }, "set": function(value) { this.element.value = value; } }); /** @property x x値 */ tm.dom.Element.prototype.accessor("x", { "get": function() { return Number( this.element.style.left.replace("px", '') ); }, "set": function(x) { this.element.style.left = x+"px"; } }); /** @property y y値 */ tm.dom.Element.prototype.accessor("y", { "get": function() { return Number( this.element.style.top.replace("px", '') ); }, "set": function(y) { this.element.style.top = y+"px"; } }); /** @property width 幅 */ tm.dom.Element.prototype.accessor("width", { "get": function() { return Number( this.element.style.width.replace("px", '') ); }, "set": function(w) { this.element.style.width = w+"px"; } }); /** @property height 高さ */ tm.dom.Element.prototype.accessor("height", { "get": function() { return Number( this.element.style.height.replace("px", '') ); }, "set": function(h) { this.element.style.height = h+"px"; } }); /** @property color 色 */ tm.dom.Element.prototype.accessor("color", { "get": function() { return this.element.style.color; }, "set": function(color) { this.element.style.color = color; } }); /** @property backgroundColor 背景色 */ tm.dom.Element.prototype.accessor("backgroundColor", { "get": function() { return this.element.style.backgroundColor; }, "set": function(color) { this.element.style.backgroundColor = color; } }); /** @property visible 表示/非表示 */ tm.dom.Element.prototype.accessor("visible", { "get": function() { return this.element.style.visibility != "hidden"; }, "set": function(v) { this.element.style.visibility = (v==true) ? "visible" : "hidden"; } }); /** @property text テキスト */ tm.dom.Element.prototype.accessor("text", { "get": function() { return this.element.innerText || this.element.textContent; }, "set": function(v) { if (this.element.innerText) { this.element.innerText = v; } else { this.element.textContent = v; } } }); /** @property classList クラスリスト */ tm.dom.Element.prototype.getter("classList", function() { return this.element.classList; }); /** @property parent */ tm.dom.Element.prototype.getter("parent", function(){ return (this.element.parentNode != undefined) ? tm.dom.Element(this.element.parentNode) : null; }); /** @property prev */ tm.dom.Element.prototype.getter("prev", function(){ return (this.element.previousSibling != undefined) ? tm.dom.Element(this.element.previousSibling) : null; }); /** @property next */ tm.dom.Element.prototype.getter("next", function(){ return (this.element.nextSibling != undefined) ? tm.dom.Element(this.element.nextSibling) : null; }); /** @property children */ tm.dom.Element.prototype.getter("children", function(){ return tm.dom.ElementList(this.element.children); }); })(); (function(){ /** * @class tm.dom.ElementList * エレメントリスト * @extends global.Array */ tm.dom.ElementList = tm.createClass({ superClass: Array, /** * @constructor * TM.DOM.Element 用配列 */ init: function(arr) { if (typeof arguments[0] == "string") { var query = arguments[0]; arr = document.querySelectorAll(query); } else if (arr == undefined) { return ; } for (var i=0,len=arr.length; i -1; } return false; }, /** * @TODO ? */ toggle: function(name, value) { if (this.contains(name, value)) { this.remove(name, value); } else { this.add(name, value); } return this; } }); /** * Attr クラス * @property attr */ tm.dom.Element.prototype.getter("attr", function(){ return this._attr || ( this._attr = tm.dom.Attr(this.element) ); }); })(); /* * style.js */ tm.dom = tm.dom || {}; (function(){ /** * @class tm.dom.Style * スタイル */ tm.dom.Style = tm.createClass({ /** エレメント */ element: null, /** * @constructor */ init: function(element) { this.element = element; }, /** * セット */ set: function(name, value) { this.element.style[name] = value; return this; }, /** * 削除 */ remove: function(name) { this.element.style.removeProperty(name); // delete this.element.style[name]; return this; }, /** * クリア */ clear: function(name) { return this; }, /** * 取得 */ get: function(name) { return this.element.style[name]; }, /** * CSS の値も考慮した上での値を取得 */ getPropValue: function(prop_name) { return document.defaultView.getComputedStyle(this.element, '').getPropertyValue(prop_name); }, }); /** * スタイルクラス * @member tm.dom.Element * @property style */ tm.dom.Element.prototype.getter("style", function(){ return this._style || ( this._style = tm.dom.Style(this.element) ); }); })(); /* * anim.js */ tm.dom = tm.dom || {}; (function() { var prefix = tm.VENDER_PREFIX; var ANIMATION = prefix + "Animation"; var ANIMATION_END = prefix + "AnimationEnd"; var ANIMATION_PLAY_STATE = prefix + "AnimationPlayState"; var ANIMATION_NAME = prefix + "AnimationName"; var ANIMATION_DURATION = prefix + "AnimationDuration"; var ANIMATION_TIMING_FUNCTION = prefix + "AnimationTimingFunction"; var ANIMATION_DELAY = prefix + "AnimationDelay"; var ANIMATION_DIRECTION = prefix + "AnimationDirection"; var ANIMATION_ITERATION_COUNT = prefix + "AnimationIterationCount"; /** * @class tm.dom.Anim * アニメーションクラス */ tm.dom.Anim = tm.createClass({ /** @property element */ /** * @constructor */ init: function(element) { this.element = element; // アニメーションが終了したらステートを "paused" にする(何度も再生できるようにする為) var self = this; this.element.addEventListener(ANIMATION_END, function() { self.stop(); }, false); }, /** * アニメーション開始 */ start: function() { this.element.style[ANIMATION_PLAY_STATE] = "running"; return this; }, /** * アニメーション終了 */ stop: function() { this.element.style[ANIMATION_PLAY_STATE] = "paused"; return this; }, /** * プロパティをセット */ setProperty: function(prop) { if (typeof prop == "string") { this.element.style[ANIMATION] = prop; } else { for (var key in prop) { var fn = ANIM_SETTER_FUNC_NAME_MAP[key]; var value = prop[key]; fn.call(this, value); } } return this; }, /** * 名前をセット */ setName: function(name) { this.element.style[ANIMATION_NAME] = name; return this; }, /** * アニメーション時間の長さをセット */ setDuration: function(s) { this.element.style[ANIMATION_DURATION] = s; return this; }, /** * 補間関数をセット */ setTimingFunction: function(func) { this.element.style[ANIMATION_TIMING_FUNCTION] = func; return this; }, /** * イテレータカウントをセット */ setIterationCount: function(n) { this.element.style[ANIMATION_ITERATION_COUNT] = n; return this; }, /** * アニメーション開始待ち時間をセット */ setDelay: function(s) { this.element.style[ANIMATION_DELAY] = s; return this; }, /** * 判定再生させるかどうかを指定 * "normal" or "alternate" */ setDirection: function(t) { this.element.style[ANIMATION_DURATION] = t; return this; }, }); var ANIM_SETTER_FUNC_NAME_MAP = { // 小文字対応 "name" : tm.dom.Anim.prototype.setName, "duration" : tm.dom.Anim.prototype.setDuration, "timingFunction": tm.dom.Anim.prototype.setTimingFunction, "iterationCount": tm.dom.Anim.prototype.setIterationCount, "delay" : tm.dom.Anim.prototype.setDelay, // 大文字対応 "Name" : tm.dom.Anim.prototype.setName, "Duration" : tm.dom.Anim.prototype.setDuration, "TimingFunction": tm.dom.Anim.prototype.setTimingFunction, "IterationCount": tm.dom.Anim.prototype.setIterationCount, "Delay" : tm.dom.Anim.prototype.setDelay, }; /** * @property anim */ tm.dom.Element.prototype.getter("anim", function() { return this._anim || (this._anim = tm.dom.Anim(this.element)); }); })(); (function(){ /** * @class tm.dom.Trans * @TODO ? */ tm.dom.Trans = tm.createClass({ /** エレメント */ element: null, /** * @constructor */ init: function(element) { this.element = element; }, /** * @TODO ? */ to: function(props, t) { this.set(props).duration(t||1000); return this; }, /** * @TODO ? */ set: function(props) { var style = this.element.style; var names = []; for (var key in props) { var name = _checkStyleProperty(key); names.push( name.toDash() ); style[name] = props[key] + ""; } style[tm.dom.Trans.PROPERTY] = names.join(', '); // none; return this; }, /** * @TODO ? */ duration: function(t) { var style = this.element.style; if (typeof t == "number") t = t + "ms"; style[tm.dom.Trans.DURATION] = t; return this; }, /** * @TODO ? */ easing: function(ease) { var style = this.element.style; style[tm.dom.Trans.TIMING_FUNCTION] = func; return this; }, /** * @TODO ? */ end: function(fn) { var elm = tm.dom.Element(this.element); elm.event.add(tm.dom.Trans.END_EVENT, fn); return this; }, /** * @TODO ? */ reset: function() { var style = this.element.style; style[tm.dom.Trans.PROPERTY] = "none"; return this; }, /** * @TODO ? */ translate: function(x, y, t) { this.to({"transform": "translate({0}px,{1}px)".format(x, y)}, t); return this; }, /** * @TODO ? */ translate3d: function(x, y, z, t) { this.to({"transform": "translate3d({0}px,{1}px,{2}px)".format(x, y, z)}, t); return this; }, /** * @TODO ? */ rotate: function(deg, t) { this.to({"transform": "rotate({0}deg)".format(deg)}, t); return this; }, /** * @TODO ? */ rotate3d: function(x, y, z, deg, t) { this.to({"transform": "rotate3d({0},{1},{2},{3}deg)".format(x, y, z, deg)}, t); return this; }, /** * @TODO ? */ scale: function(x, y, t) { this.to({"transform": "scale({0},{1})".format(x, y)}, t); return this; }, /** * @TODO ? */ transform: function() { // TODO: 実装する }, // ------------------------------------- /** * @TODO ? */ setProp: function(prop) { var style = this.element.style; var prop_list = []; for (var key in prop) { var name = _checkStyleProperty(key); prop_list.push( name.toDash() ); style[name] = prop[key]; } style[tm.dom.Trans.PROPERTY] = prop_list.join(', '); // none; return this; }, /** * @TODO ? */ setDuration: function(t) { var style = this.element.style; style[tm.dom.Trans.DURATION] = t; return this; }, /** * @TODO ? */ setTimingFunction: function(func) { var style = this.element.style; style[tm.dom.Trans.TIMING_FUNCTION] = func; return this; }, /** * @TODO ? */ resetProp: function() { var style = this.element.style; style[tm.dom.Trans.PROPERTY] = "none"; return this; }, /** * @TODO ? */ setEndFunction: function(fn) { var elm = tm.dom.Element(this.element); elm.event.add(tm.dom.Trans.END_EVENT, fn); return this; }, }); /** @static @property */ tm.dom.Trans.PROPERTY = tm.VENDER_PREFIX + "TransitionProperty"; /** @static @property */ tm.dom.Trans.DURATION = tm.VENDER_PREFIX + "TransitionDuration"; /** @static @property */ tm.dom.Trans.TIMING_FUNCTION = tm.VENDER_PREFIX + "TransitionTimingFunction"; /** @static @property */ tm.dom.Trans.DELAY = tm.VENDER_PREFIX + "TransitionDelay"; /** @static @method @member tm.dom.Trans */ tm.dom.Trans.END_EVENT = (function(){ return { "webkit": "webkitTransitionEnd", "moz" : "transitionend", "o" : "oTransitionEnd", }[tm.VENDER_PREFIX]; })(); /** * @property trans */ tm.dom.Element.prototype.getter("trans", function(){ return this._trans || ( this._trans = tm.dom.Trans(this.element) ); }); var _styleList = { "transform": true, }; var _checkStyleProperty = function(name) { if (_styleList[name] === true) { return '-'+tm.VENDER_PREFIX + name.capitalizeFirstLetter(); } return name; }; })(); /* * dom/data.js */ (function(){ /** * @class tm.dom.Data */ tm.define("tm.dom.Data", { /** エレメント */ element: null, /** * @constructor */ init: function(element) { this.element = element; }, /** * 属性をセット */ set: function(name, value) { var key = "data-" + name.toDash(); this.element.setAttribute(key, value); return this; }, /** * 属性をゲット */ get: function(name, value) { var key = "data-" + name.toDash(); return this.element.attributes[key].value; }, }); /** * Attr クラス * @property data */ tm.dom.Element.prototype.getter("data", function(){ return this._data || ( this._data = tm.dom.Data(this.element) ); }); })(); /* * manager.js */ (function() { tm.asset = tm.asset || {}; tm.asset.Manager = { assets: {}, /** * アセットのゲット * @param {Object} key */ get: function(key) { return this.assets[key]; }, /** * アセットのセット * @param {Object} key * @param {Object} asset */ set: function(key, asset) { this.assets[key] = asset; return this; }, /** * @TODO ? * @param {Object} key */ contains: function(key) { return (this.assets[key]) ? true : false; }, }; })(); (function() { tm.define("tm.asset.Loader", { superClass: "tm.event.EventDispatcher", init: function() { this.superInit(); this.assets = {}; }, contains: function(key) { return (this.assets[key]) ? true : false; }, load: function(arg) { if (tm.util.Type.isObject(arg)) { this._loadByObject(arg); } else { this._loadString(arguments[0], arguments[1], arguments[2]); } return this; }, /** * アセットのゲット * @param {Object} key */ get: function(key) { return this.assets[key]; }, /** * アセットのセット * @param {Object} key * @param {Object} asset */ set: function(key, asset) { this.assets[key] = asset; // manager の方にもセットする tm.asset.Manager.set(key, asset); return this; }, _load: function(key, path, type) { // if (tm.asset.Manager.contains(key)) { // return tm.asset.Manager.get(key); // } path = path || key; // type が省略されている場合は拡張子から判定する type = type || path.split('.').last; var asset = tm.asset.Loader._funcs[type](path); this.set(key, asset); return asset; }, _loadString: function(key, path, type) { var hash = {}; hash[key] = { url: path, type: type, }; this._loadByObject(hash); }, _loadByObject: function(hash) { var flow = tm.util.Flow(Object.keys(hash).length, function() { var e = tm.event.Event("load"); this.dispatchEvent(e); }.bind(this)); var loadAsset = function(asset) { flow.pass(); var e = tm.event.Event("progress"); e.asset = asset; e.progress = flow.counter/flow.waits; // todo this.dispatchEvent(e); }.bind(this); Object.keys(hash).each(function(key) { var value = hash[key]; var asset = null; if (typeof value == 'string') { asset = this._load(key, value); } else { asset = this._load(key, value['url'] || value['src'] || value['path'], value['type']); } if (asset.loaded) { loadAsset(asset); } else { asset.on("load", function() { loadAsset(asset); }); } }.bind(this)); }, }); tm.asset.Loader._funcs = []; tm.asset.Loader.defineFunction("register", function(type, func) { this._funcs[type] = func; }); var _textureFunc = function(path) { var texture = tm.asset.Texture(path); return texture; }; var _soundFunc = function(path) { var audio = tm.sound.WebAudio(path); return audio; }; var _tmxFunc = function(path) { var mapSheet = tm.asset.MapSheet(path); return mapSheet; }; var _tmssFunc = function(path) { var ss = tm.asset.SpriteSheet(path); return ss; }; var _jsonFunc = function(path) { var file = tm.util.File(); if (typeof path == 'string') { file.load({ url: path, dataType: 'json', }); } else { var data = path; file.setData(path); file.loaded = true; } return file; }; // image tm.asset.Loader.register("png", _textureFunc); tm.asset.Loader.register("gif", _textureFunc); tm.asset.Loader.register("jpg", _textureFunc); tm.asset.Loader.register("jpeg", _textureFunc); // sound tm.asset.Loader.register("wav", _soundFunc); tm.asset.Loader.register("mp3", _soundFunc); tm.asset.Loader.register("ogg", _soundFunc); tm.asset.Loader.register("m4a", _soundFunc); // json tm.asset.Loader.register("json", _jsonFunc); // map data tm.asset.Loader.register("tmx", _tmxFunc); // spritesheet for tmlib.js tm.asset.Loader.register("tmss", _tmssFunc); })(); /* * texture.js */ (function() { /** * @class tm.asset.Texture * テクスチャクラス * @extends tm.event.EventDispatcher */ tm.define("tm.asset.Texture", { superClass: "tm.event.EventDispatcher", /** window.document.Image */ element: null, /** ロード済みかどうか */ loaded: false, /** * @constructor */ init: function(src) { this.superInit(); this.element = new Image(); this.element.src = src; var self = this; this.element.onload = function() { self.loaded = true; var e = tm.event.Event("load"); self.dispatchEvent( e ); }; }, /** * window.document.Image クラスのインスタンスを返す */ getElement: function() { return this.element; }, }); /** * @property width * 幅 */ tm.asset.Texture.prototype.getter("width", function() { return this.element.width; }); /** * @property height * 高さ */ tm.asset.Texture.prototype.getter("height", function() { return this.element.height; }); })(); (function(){ /* * @static * @method * ### ref * http://dummyimage.com/ */ /* tm.graphics.TextureManager.loadDummy = function(key, param) { param = param || {}; var paths = ["http://dummyimage.com"]; paths.push(param.size || 256); paths.push(param.bgColor || "aaa"); paths.push(param.color || "000"); paths.push(param.format || "png"); var src = paths.join('/'); if (param.text) { src += '&text=' + param.text; } this.textures[key] = tm.graphics.Texture(src); this.loaded = false; }; */ })(); /* * spritesheet.js */ (function() { /** * @class tm.asset.SpriteSheet * マップシート * @extends tm.event.EventDispatcher */ tm.define("tm.asset.SpriteSheet", { superClass: "tm.event.EventDispatcher", /** loaded */ loaded: false, /** * @constructor */ init: function(src) { this.superInit(); this.loaded = false; if (typeof src == "string") { this.load(src); } else { this.parse(src); this.loaded = true; this.dispatchEvent(tm.event.Event("load")); } }, /** * @TODO ? */ load: function(path) { tm.util.Ajax.load({ url: path, dataType: "json", success: function(d) { this.parse(d); this.loaded = true; }.bind(this), }); }, /** * @TODO ? */ parse: function(param) { this.frame = param.frame; if (typeof param.image == "string") { if (!tm.asset.Manager.contains(param.image)) { var loader = tm.asset.Loader(); loader.load(param.image); } this.image = tm.asset.Manager.get(param.image); } else { this.image = param.image; } if (this.image.loaded === false) { this.image.addEventListener("load", function() { this._calcFrames(param.frame); var e = tm.event.Event("load"); this.dispatchEvent(e); }.bind(this), false); } else { this._calcFrames(param.frame); var e = tm.event.Event("load"); this.dispatchEvent(e); } this._calcAnim(param.animations); }, /** * @TODO ? */ getFrame: function(index) { return this.frames[index]; }, /** * @TODO ? */ getAnimation: function(name) { return this.animations[name]; }, /** * @TODO ? * @private */ _calcFrames: function(frame) { var frames = this.frames = []; var w = frame.width; var h = frame.height; var row = ~~(this.image.width / w); var col = ~~(this.image.height/ h); if (!frame.count) frame.count = row*col; for (var i=0,len=frame.count; iTest Program. * ### Example * TM.loadScript("input", "keyboard"); * * TM.main(function() { * var k = TM.$Key(document); * k.run(); * TM.setLoop(function(){ * if (k.getKey('a')) { console.log("press 'a'!!"); } * }); * }); */ init: function(element) { this.element = element || document; this.key = {}; this.press = {}; this.down = {}; this.up = {}; this.last = {}; var self = this; this.element.addEventListener("keydown", function(e){ self.key[e.keyCode] = true; }); this.element.addEventListener("keyup", function(e){ // delete self.key[e.keyCode]; self.key[e.keyCode] = false; // self.button |= 1<Test Program. */ init: function(element) { this.element = element || window.document; this.position = tm.geom.Vector2(0, 0); this.deltaPosition = tm.geom.Vector2(0, 0); this.prevPosition = tm.geom.Vector2(0, 0); this._x = 0; this._y = 0; var self = this; this.element.addEventListener("touchstart", function(e){ self.touched = true; self._touchmove(e); // 最初だけセット self.position.set(self._x, self._y); self.prevPosition.set(self._x, self._y); // prevPostion をリセット }); this.element.addEventListener("touchend", function(e){ self.touched = false; }); this.element.addEventListener("touchmove", function(e){ self._touchmove(e); // 画面移動を止める e.stop(); }); // var self = this; // this.element.addEventListener("touchstart", function(e) { // if (self._touch) return ; // self._touch = e.changedTouches[0]; // // changedTouches; // // targetTouches; // self._touchmove(e); // self.prevPosition.setObject(self.position); // self.touched = true; // }); // this.element.addEventListener("touchend", function(e){ // if (self._touch == e.changedTouches[0]) { // self.touched = false; // } // }); // this.element.addEventListener("touchmove", function(e){ // self._touchmove(e); // // 画面移動を止める // e.stop(); // }); }, /** * run. * 自動でマウス情報を更新したい際に使用する */ run: function(fps) { var self = this; fps = fps || 30; tm.setLoop(function() { self.update(); }, 1000/fps); return this; }, /** * 情報更新処理 * マイフレーム呼んで下さい. */ update: function() { this.last = this.now; this.now = Number(this.touched); this.start = (this.now ^ this.last) & this.now; this.end = (this.now ^ this.last) & this.last; // 変化値を更新 this.deltaPosition.x = this._x - this.prevPosition.x; this.deltaPosition.y = this._y - this.prevPosition.y; // 前回の座標を更新 this.prevPosition.setObject(this.position); // 現在の位置を更新 this.position.set(this._x, this._y); }, /** * タッチしているかを判定 */ getTouch: function() { return this.touched != 0; }, /** * タッチ開始時に true */ getTouchStart: function() { return this.start != 0; }, /** * タッチ終了時に true */ getTouchEnd: function() { return this.end != 0; }, /** * @TODO ? * @private */ _touchmove: function(e) { var t = e.touches[0]; var r = e.target.getBoundingClientRect(); this._x = t.clientX - r.left; this._y = t.clientY - r.top; }, /** * @TODO ? * @private */ _touchmoveScale: function(e) { var t = e.touches[0]; var r = e.target.getBoundingClientRect(); this._x = t.clientX - r.left; this._y = t.clientY - r.top; if (e.target.style.width) { this._x *= e.target.width / parseInt(e.target.style.width); } if (e.target.style.height) { this._y *= e.target.height / parseInt(e.target.style.height); } }, }); /** * @property x * x座標値 */ tm.input.Touch.prototype.accessor("x", { "get": function() { return this.position.x; }, "set": function(v) { this.position.x = v; } }); /** * @property y * y座標値 */ tm.input.Touch.prototype.accessor("y", { "get": function() { return this.position.y; }, "set": function(v) { this.position.y = v; } }); /** * @property dx * dx値 */ tm.input.Touch.prototype.accessor("dx", { "get": function() { return this.deltaPosition.x; }, "set": function(v) { this.deltaPosition.x = v; } }); /** * @property dy * dy値 */ tm.input.Touch.prototype.accessor("dy", { "get": function() { return this.deltaPosition.y; }, "set": function(v) { this.deltaPosition.y = v; } }); /** * @method * ポインティング状態取得(mouse との差異対策) */ tm.input.Touch.prototype.getPointing = tm.input.Touch.prototype.getTouch; /** * @method * ポインティングを開始したかを取得(mouse との差異対策) */ tm.input.Touch.prototype.getPointingStart = tm.input.Touch.prototype.getTouchStart; /** * @method * ポインティングを終了したかを取得(mouse との差異対策) */ tm.input.Touch.prototype.getPointingEnd = tm.input.Touch.prototype.getTouchEnd; })(); (function() { return ; /** * @class tm.input.Touches * マルチタッチ対応クラス * @extends global.Array */ tm.define("tm.input.Touches", { superClass: Array, /** * @constructor */ init: function(elm, length) { this.element = elm; for (var i=0; iTest Program. * * ### Reference * - * - * - * - */ init: function(element) { this.gravity = tm.geom.Vector3(0, 0, 0); this.acceleration = tm.geom.Vector3(0, 0, 0); this.rotation = tm.geom.Vector3(0, 0, 0); this.orientation = tm.geom.Vector3(0, 0, 0); var self = this; window.addEventListener("devicemotion", function(e) { var acceleration = self.acceleration; var gravity = self.gravity; var rotation = self.rotation; if (e.acceleration) { acceleration.x = e.acceleration.x; acceleration.y = e.acceleration.y; acceleration.z = e.acceleration.z; } if (e.accelerationIncludingGravity) { gravity.x = e.accelerationIncludingGravity.x; gravity.y = e.accelerationIncludingGravity.y; gravity.z = e.accelerationIncludingGravity.z; } if (e.rotationRate) { rotation.x = rotation.beta = e.rotationRate.beta; rotation.y = rotation.gamma = e.rotationRate.gamma; rotation.z = rotation.alpha = e.rotationRate.alpha; } }); window.addEventListener("deviceorientation", function(e) { var orientation = self.orientation; orientation.alpha = e.alpha; // z(0~360) orientation.beta = e.beta; // x(-180~180) orientation.gamma = e.gamma; // y(-90~90) }); }, }); })(); /* * color.js */ tm.graphics = tm.graphics || {}; (function() { /** * @class tm.graphics.Color * カラークラス */ tm.graphics.Color = tm.createClass({ /** R値 */ r: 255, /** G値 */ g: 255, /** B値 */ b: 255, /** A値 */ a: 1.0, /** * @constructor */ init: function(r, g, b, a) { this.set.apply(this, arguments); }, /** * セッター. */ set: function(r, g, b, a) { this.r = r; this.g = g; this.b = b; this.a = (a !== undefined) ? a : 1.0; return this; }, /** * 数値によるセッター. */ setFromNumber: function(r, g, b, a) { this.r = r; this.g = g; this.b = b; this.a = (a !== undefined) ? a : 1.0; return this; }, /** * 配列によるセッター */ setFromArray: function(arr) { return this.set.apply(this, arr); }, /** * オブジェクトによるセッター */ setFromObject: function(obj) { return this.set(obj.r, obj.g, obj.b, obj.a); }, /** * 文字列によるセッター */ setFromString: function(str) { var color = tm.graphics.Color.stringToNumber(str); return this.set(color[0], color[1], color[2], color[3]); }, /** * 賢いセッター */ setSmart: function() { var arg = arguments[0]; if (arguments.length >= 3) { this.set(arguments.r, arguments.g, arguments.b, arguments.a); } else if (arg instanceof Array) { this.setFromArray(arg); } else if (arg instanceof Object) { this.setFromObject(arg); } else if (typeof(arg) == "string") { this.setFromString(arg); } return this; }, /** * CSS 用 16進数文字列に変換 */ toStyleAsHex: function() { return "#{0}{1}{2}".format( this.r.toString(16).padding(2, '0'), this.g.toString(16).padding(2, '0'), this.b.toString(16).padding(2, '0') ); }, /** * CSS 用 RGB文字列に変換 */ toStyleAsRGB: function() { return "rgb({r},{g},{b})".format({ r: ~~this.r, g: ~~this.g, b: ~~this.b }); }, /** * CSS 用 RGBA文字列に変換 */ toStyleAsRGBA: function() { return "rgba({r},{g},{b},{a})".format({ r: ~~this.r, g: ~~this.g, b: ~~this.b, a: this.a }); }, /** * CSS 用 RGBA 文字列に変換 */ toStyle: function() { return "rgba({r},{g},{b},{a})".format({ r: ~~this.r, g: ~~this.g, b: ~~this.b, a: this.a }); }, }); var MATCH_SET_LIST = { "hex111": { reg: /^#(\w{1})(\w{1})(\w{1})$/, exec: function(m) { return [ parseInt(m[1]+m[1], 16), parseInt(m[2]+m[2], 16), parseInt(m[3]+m[3], 16) ]; } }, "hex222": { reg: /^#(\w{2})(\w{2})(\w{2})$/, exec: function(m) { return [ parseInt(m[1], 16), parseInt(m[2], 16), parseInt(m[3], 16) ]; } }, "rgb": { reg: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, exec: function(m) { return [ parseInt(m[1]), parseInt(m[2]), parseInt(m[3]) ]; } }, "rgba": { reg: /^rgba\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*(\d{1}(\.{1}\d+)?)\)$/, exec: function(m) { return [ parseInt(m[1]), parseInt(m[2]), parseInt(m[3]), parseFloat(m[4]) ]; } }, "hsl": { reg: /^hsl\((\d{1,3}),\s*(\d{1,3})%,\s*(\d{1,3})%\)$/, exec: function(m) { return tm.graphics.Color.HSLtoRGB(m[1], m[2], m[3]); } }, "hsla": { reg: /^rgba\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*(\d{1}(\.{1}\d+)?)\)$/, exec: function(m) { return Color.HSLAtoRGBA(m[1], m[2], m[3], m[4]); } }, }; /** * @static * @TODO ? */ tm.graphics.Color.COLOR_LIST = { /** @property black */ "black" : [0x00, 0x00, 0x00], /** @property silver */ "silver" : [0xc0, 0xc0, 0xc0], /** @property gray */ "gray" : [0x80, 0x80, 0x80], /** @property white */ "white" : [0xff, 0xff, 0xff], /** @property maroon */ "maroon" : [0x80, 0x00, 0x00], /** @property red */ "red" : [0xff, 0x00, 0x00], /** @property purple */ "purple" : [0x80, 0x00, 0x80], /** @property fuchsia */ "fuchsia" : [0xff, 0x00, 0xff], /** @property green */ "green" : [0x00, 0x80, 0x00], /** @property lime */ "lime" : [0x00, 0xff, 0x00], /** @property olive */ "olive" : [0x80, 0x80, 0x00], /** @property yellow */ "yellow" : [0xff, 0xff, 0x00], /** @property navy */ "navy" : [0x00, 0x00, 0x80], /** @property blue */ "blue" : [0x00, 0x00, 0xff], /** @property teal */ "teal" : [0x00, 0x80, 0x80], /** @property aqua */ "aqua" : [0x00, 0xff, 0xff], }; /** * @static * @member tm.graphics.Color * @method strToNum * @TODO ? */ /** * @static * @member tm.graphics.Color * @method stringToNumber * @TODO ? */ tm.graphics.Color.strToNum = tm.graphics.Color.stringToNumber = function(str){ var vlaue = null; var type = null; if (str[0] === '#') { type = (str.length == 4) ? "hex111" : "hex222"; } else if (str[0] === 'r' && str[1] === 'g' && str[2] === 'b') { type = (str[3] == 'a') ? "rgba" : "rgb"; } else if (str[0] === 'h' && str[1] === 's' && str[2] === 'l') { type = (str[3] == 'a') ? "hsla" : "hsl"; } if (type) { var match_set = MATCH_SET_LIST[type]; var m = str.match( match_set.reg ); value = match_set.exec(m); } else if (Color.COLOR_LIST[str]){ value = Color.COLOR_LIST[str]; } return value; }; /** * @static * @method * @TODO ? */ tm.graphics.Color.HSLtoRGB = function(h, s, l) { var r, g, b; h%=360; h+=360; h%=360; s *= 0.01; l *= 0.01; if (s == 0) { var l = Math.round(l * 255); return [l, l, l]; } var m2 = (l < 0.5) ? l * (1+s) : l + s - l*s; var m1 = l*2 - m2; // red var temp = (h + 120)%360; if (temp < 60) { r = m1 + (m2-m1) * temp/60; } else if (temp < 180){ r = m2; } else { r = m1; } // green temp = h; if (temp < 60) { g = m1 + (m2-m1) * temp/60; } else if (temp < 180){ g = m2; } else if (temp < 240){ g = m1 + (m2-m1) * (240-temp)/60; } else { g = m1; } // blue temp = ((h-120)+360)%360; if (temp < 60) { b = m1 + (m2-m1) * temp/60; } else if (temp < 180){ b = m2; } else if (temp < 240){ b = m1 + (m2-m1) * (240-temp)/60; } else { b = m1; } return [ parseInt(r*255), parseInt(g*255), parseInt(b*255) ]; }; /** * @static * @method * @TODO ? */ tm.graphics.Color.HSLAtoRGBA = function(h, s, l, a) { var temp = Color.HSLtoRGB(h, s, l); temp[3] = a; return rgb; }; /** * @static * @method * rgb 値を作成 */ tm.graphics.Color.createStyleRGB = function(r, g, b) { return "rgba(" + r + "," + g + "," + b + ")"; }; /** * @static * @method * rgba 値を作成 */ tm.graphics.Color.createStyleRGBA = function(r, g, b, a) { return "rgba(" + r + "," + g + "," + b + "," + a + ")"; }; /** * @static * @method * hsl 値を作成 */ tm.graphics.Color.createStyleHSL = function(h, s, l) { return "hsl(" + h + "," + s + "%," + l + "%)"; }; /** * @static * @method * hsla 値を作成 */ tm.graphics.Color.createStyleHSLA = function(h, s, l, a) { return "hsla(" + h + "," + s + "%," + l + "%," + a + ")"; }; })(); /* * canvas.js */ tm.graphics = tm.graphics || {}; (function() { /** * @class tm.graphics.Canvas * キャンバス */ tm.graphics.Canvas = tm.createClass({ /** 要素 */ element: null, /** キャンバス */ canvas: null, /** コンテキスト */ context: null, /** * @constructor */ init: function(canvas) { this.canvas = null; if (typeof canvas == "string") { this.canvas = document.querySelector(canvas); } else { this.canvas = canvas || document.createElement("canvas"); } this.element = this.canvas; this.context = this.canvas.getContext("2d"); this.context.lineCap = "round"; this.context.lineJoin = "round"; }, /** * リサイズする */ resize: function(width, height) { this.canvas.width = width; this.canvas.height = height; return this; }, /** * リサイズウィンドウ */ resizeWindow: function() { this.canvas.style.position = "fixed"; this.canvas.style.margin = "0px"; this.canvas.style.padding = "0px"; this.canvas.style.left = "0px"; this.canvas.style.top = "0px"; return this.resize(window.innerWidth, window.innerHeight); }, /** * フィット */ resizeToFitScreen: function() { this.canvas.style.position = "fixed"; this.canvas.style.margin = "0px"; this.canvas.style.padding = "0px"; this.canvas.style.left = "0px"; this.canvas.style.top = "0px"; return this.resize(window.innerWidth, window.innerHeight); }, /** * 拡縮で画面にフィットさせる * 名前は仮. 検討する */ fitWindow: function(everFlag) { var _fitFunc = function() { everFlag = everFlag === undefined ? true : everFlag; var e = this.element; var s = e.style; s.position = "absolute"; s.margin = "auto"; s.left = "0px"; s.top = "0px"; s.bottom = "0px"; s.right = "0px"; var rateWidth = e.width/window.innerWidth; var rateHeight= e.height/window.innerHeight; var rate = e.height/e.width; if (rateWidth > rateHeight) { s.width = innerWidth+"px"; s.height = innerWidth*rate+"px"; } else { s.width = innerHeight/rate+"px"; s.height = innerHeight+"px"; } }.bind(this); // 一度実行しておく _fitFunc(); // リサイズ時のリスナとして登録しておく if (everFlag) { window.addEventListener("resize", _fitFunc, false); } }, /** * クリア */ clear: function(x, y, width, height) { x = x || 0; y = y || 0; width = width || this.width; height= height|| this.height; this.context.clearRect(x, y, width, height); return this; }, /** * 色指定クリア * @param {String} fillStyle * @param {Number} [x=0] * @param {Number} [y=0] * @param {Number} [width=this.width] * @param {Number} [height=this.height] */ clearColor: function(fillStyle, x, y, width, height) { x = x || 0; y = y || 0; width = width || this.width; height= height|| this.height; this.save(); this.resetTransform(); // 行列初期化 this.fillStyle = fillStyle; // 塗りつぶしスタイルセット this.context.fillRect(x, y, width, height); this.restore(); return this; }, /** * パスを開始(リセット) */ beginPath: function() { this.context.beginPath(); return this; }, /** * パスを閉じる */ closePath: function() { this.context.closePath(); return this; }, /** * 新規パス生成 */ moveTo: function(x, y) { this.context.moveTo(x, y); return this; }, /** * パスに追加 */ lineTo: function(x, y) { this.context.lineTo(x, y); return this; }, /** * パス内を塗りつぶす */ fill: function() { this.context.fill(); return this; }, /** * パス上にラインを引く */ stroke: function() { this.context.stroke(); return this; }, /** * クリップ */ clip: function() { this.context.clip(); return this; }, /** * 点描画 */ drawPoint: function(x, y) { return this.strokeRect(x, y, 1, 1); // return this.beginPath().moveTo(x-0.5, y-0.5).lineTo(x+0.5, y+0.5).stroke(); }, /** * ラインパスを作成 */ line: function(x0, y0, x1, y1) { return this.moveTo(x0, y0).lineTo(x1, y1); }, /** * ラインを描画 */ drawLine: function(x0, y0, x1, y1) { return this.beginPath().line(x0, y0, x1, y1).stroke(); }, /** * ダッシュラインを描画 */ drawDashLine: function(x0, y0, x1, y1, pattern) { var patternTable = null; if (typeof(pattern) == "string") { patternTable = pattern; } else { pattern = pattern || 0xf0f0; patternTable = pattern.toString(2); } patternTable = patternTable.padding(16, '1'); var vx = x1-x0; var vy = y1-y0; var len = Math.sqrt(vx*vx + vy*vy); vx/=len; vy/=len; var x = x0; var y = y0; for (var i=0; ihttp://www.w3.org/TR/2010/WD-2dcontext-20100624/#colors-and-styles */ setColorStyle: function(stroke, fill) { fill = fill || stroke; this.context.strokeStyle = stroke; this.context.fillStyle = fill; return this; }, /** * テキストをセット */ setText: function(font, align, baseline) { var c = this.context; c.font = font; c.textAlign = align; c.textBaseline = baseline; }, /** * ラインスタイルを一括セット * http://www.w3.org/TR/2010/WD-2dcontext-20100624/#line-styles */ setLineStyle: function(width, cap, join, miter) { with(this.context) { lineWidth = width || 1; lineCap = cap || "round"; lineJoin = join || "round"; miterLimit = miter || 10.0; } return this; }, /** * 影をセット * - * - */ setShadow: function(color, offsetX, offsetY, blur) { var ctx = this.context; ctx.shadowColor = color || "black"; ctx.shadowOffsetX = offsetX || 0; ctx.shadowOffsetY = offsetY || 0; ctx.shadowBlur = blur || 0; return this; }, /** * エレメント取得 */ getElement: function() { return this.element; }, }); /** @static @property */ tm.graphics.Canvas.MIME_TYPE_PNG = "image/png"; /** @static @property */ tm.graphics.Canvas.MIME_TYPE_JPG = "image/jpeg"; /** @static @property */ tm.graphics.Canvas.MIME_TYPE_SVG = "image/svg+xml"; /** * @property width * 幅 */ tm.graphics.Canvas.prototype.accessor("width", { "get": function() { return this.canvas.width; }, "set": function(v) { this.canvas.width = v; } }); /** * @property height * 高さ */ tm.graphics.Canvas.prototype.accessor("height", { "get": function() { return this.canvas.height; }, "set": function(v) { this.canvas.height = v; } }); /** * @property fillStyle * 塗りつぶしスタイル */ tm.graphics.Canvas.prototype.accessor("fillStyle", { "get": function() { return this.context.fillStyle; }, "set": function(v) { this.context.fillStyle = v; } }); /** * @property strokeStyle * ストロークスタイル */ tm.graphics.Canvas.prototype.accessor("strokeStyle", { "get": function() { return this.context.strokeStyle; }, "set": function(v) { this.context.strokeStyle = v; } }); /** * @property globalAlpha * アルファ指定 */ tm.graphics.Canvas.prototype.accessor("globalAlpha", { "get": function() { return this.context.globalAlpha; }, "set": function(v) { this.context.globalAlpha = v; } }); /** * @property globalCompositeOperation * ブレンド指定 */ tm.graphics.Canvas.prototype.accessor("globalCompositeOperation", { "get": function() { return this.context.globalCompositeOperation; }, "set": function(v) { this.context.globalCompositeOperation = v; } }); /** * @property shadowBlur * シャドウブラー */ tm.graphics.Canvas.prototype.accessor("shadowBlur", { "get": function() { return this.context.shadowBlur; }, "set": function(v) { this.context.shadowBlur = v; } }); /** * @property shadowColor * シャドウブラーカラー */ tm.graphics.Canvas.prototype.accessor("shadowColor", { "get": function() { return this.context.shadowColor; }, "set": function(v) { this.context.shadowColor = v; } }); /** * @property shadowOffsetX * シャドウオフセット X */ tm.graphics.Canvas.prototype.accessor("shadowOffsetX", { "get": function() { return this.context.shadowOffsetX; }, "set": function(v) { this.context.shadowOffsetX = v; } }); /** * @property shadowOffsetY * シャドウオフセット Y */ tm.graphics.Canvas.prototype.accessor("shadowOffsetY", { "get": function() { return this.context.shadowOffsetY; }, "set": function(v) { this.context.shadowOffsetY = v; } }); /** * @property lineCap * ライン終端の描画方法 */ tm.graphics.Canvas.prototype.accessor("lineCap", { "get": function() { return this.context.lineCap; }, "set": function(v) { this.context.lineCap = v; } }); /** * @property lineJoin * ラインつなぎ目の描画方法 */ tm.graphics.Canvas.prototype.accessor("lineJoin", { "get": function() { return this.context.lineJoin; }, "set": function(v) { this.context.lineJoin = v; } }); /** * @property miterLimit * マイターリミット */ tm.graphics.Canvas.prototype.accessor("miterLimit", { "get": function() { return this.context.miterLimit; }, "set": function(v) { this.context.miterLimit = v; } }); /** * @property lineWidth * ライン幅設定 */ tm.graphics.Canvas.prototype.accessor("lineWidth", { "get": function() { return this.context.lineWidth; }, "set": function(v) { this.context.lineWidth = v; } }); /** * @property font * フォント */ tm.graphics.Canvas.prototype.accessor("font", { "get": function() { return this.context.font; }, "set": function(v) { this.context.font = v; } }); /** * @property textAlign * テキストのアラインメント */ tm.graphics.Canvas.prototype.accessor("textAlign", { "get": function() { return this.context.textAlign; }, "set": function(v) { this.context.textAlign = v; } }); /** * @property textBaseline * テキストのベースライン */ tm.graphics.Canvas.prototype.accessor("textBaseline", { "get": function() { return this.context.textBaseline; }, "set": function(v) { this.context.textBaseline = v; } }); /** * @property centerX * センターX */ tm.graphics.Canvas.prototype.getter("centerX", function() { return this.canvas.width/2; }); /** * @property centerY * センターY */ tm.graphics.Canvas.prototype.getter("centerY", function(){ return this.canvas.height/2; }); /** * @property imageSmoothingEnabled * 画像スムージング設定 */ tm.graphics.Canvas.prototype.accessor("imageSmoothingEnabled", { "get": function() { return this.context.imageSmoothingEnabled; }, "set": function(v) { this.context.imageSmoothingEnabled = v; this.context.webkitImageSmoothingEnabled = v; this.context.mozImageSmoothingEnabled = v; } }); })(); /* * bitmap.js */ tm.graphics = tm.graphics || {}; (function() { /** * @class tm.graphics.Bitmap * ビットマップクラス */ tm.graphics.Bitmap = tm.createClass({ /** イメージデータ */ imageData: null, /** * @constructor */ init: function(imageData) { if (!dummyCanvas) { dummyCanvas = document.createElement("canvas"); dummyContext= dummyCanvas.getContext("2d"); } this._init.apply(this, arguments); this.init = this._init; }, /** * @TODO ? * @private */ _init: function(imageData) { if (arguments.length == 1) { this.imageData = imageData; this.data = imageData.data; } else if (arguments.length == 2) { var w = arguments[0]; var h = arguments[1]; this.imageData = dummyContext.createImageData(w, h); this.data = this.imageData.data; } }, /** * index 指定でピクセル値を取得 * 最も高速 */ getPixelIndex: function(index) { var i = index*4; return [ this.data[i+0], this.data[i+1], this.data[i+2], this.data[i+3] ]; }, /** * x, y 指定でピクセル値を取得 */ getPixelXY: function(x, y) { return this.getPixelIndex( this.posToIndex(x, y) ); }, /** * ピクセル値を取得 * ### Memo * - index 指定か x, y 指定にするか検討中 * - 配列で返すか数値で返すか検討中. 速度の早いやつを採用する */ getPixel: function(x, y) { return this.getPixelIndex( this.posToIndex(x, y) ); }, /** * @TODO ? */ getPixelAsNumber: function(index) { var i = index*4; return (this.data[i+3] << 24) | (this.data[i+0] << 16) | (this.data[i+1] << 8) | this.data[i+2]; }, /** * @TODO ? */ getPixelAsObject: function(index) { var i = index*4; return { r: this.data[i+0], g: this.data[i+1], b: this.data[i+2], a: this.data[i+3] }; }, /** * @TODO ? */ getPixelAsArray: function(index) { var i = index*4; return [ this.data[i+0], this.data[i+1], this.data[i+2], this.data[i+3] ]; }, /** * 指定した範囲内のピクセル平均値を取得 */ getPixelAverage: function(x, y, width, height) { var rgba = [0, 0, 0, 0]; // 範囲 var l = x; var r = x+width; var t = y; var b = y+height; // ハミ出し調整 if (l < 0) { l = 0; } if (r > this.width) { r = this.width; } if (t < 0) { t = 0; } if (b > this.height) { b = this.height; } // 範囲内のピクセル全てを取得 var temp = []; var bitmapWidth = this.width; for (var i=t; i>>16, (pixel & 0x0000ff00)>>>8, (pixel & 0x000000ff)>>>0); }, /** * argb */ setPixel32FromNumber: function(index, pixel) { return this.setPixel32(index, (pixel & 0x00ff0000)>>>16, (pixel & 0x0000ff00)>>>8, (pixel & 0x000000ff)>>>0, (pixel & 0xff000000)>>>24); }, /** * object */ setPixelFromObject: function(index, pixel) { return this.setPixel(pixel.r, pixel.g, pixel.b); }, /** * @TODO ? */ setPixel32FromObject: function(index, pixel) { return this.setPixel32(pixel.r, pixel.g, pixel.b, pixel.a); }, /** * string * rgb, hsl, #... #...... などに対応予定 */ setPixelFromString: function(index, pixel) { // TODO }, /** * 位置をインデックスに変換 */ posToIndex: function(x, y) { return y*this.imageData.width + x; }, // filter: function(rect, filter) /** * @TODO ? */ filter: function(filter) { for (var i=0; i * - */ tm.graphics.BlurFilter = tm.createClass({ /** @property blurX */ /** @property blurY */ /** @property quality */ /** * @constructor */ init: function(blurX, blurY, quality) { this.blurX = blurX || 4; this.blurY = blurY || 4; this.quality = quality || 1; }, /** * apply */ apply: function(src, dst) { var halfX = Math.floor(this.blurX/2); var halfY = Math.floor(this.blurY/2); var rangeX = this.blurX; var rangeY = this.blurY; var srcWidth = src.width; var srcHeight = src.height; var len = src.length; // ブラー処理 var _apply = function(src, dst) { for (var i=0; i * - * - * - * - */ tm.graphics.ColorMatrixFilter = tm.createClass({ /** @property colorMatrix */ /** * @constructor */ init: function(colorMatrix) { this.colorMatrix = colorMatrix; }, /** * @property * apply */ apply: function(src, dst) { var cm = this.colorMatrix; for (var i=0,len=src.length; i 0) { this.to.apply(this, arguments); } }, /** * 指定した値までアニメーション * @param {Object} target * @param {Object} finishProps * @param {Object} duration * @param {Function} func */ to: function(target, finishProps, duration, func) { var beginProps = {}; for (var key in finishProps) { beginProps[key] = target[key]; } this.fromTo(target, beginProps, finishProps, duration, func); return this; }, /** * 指定した値を足した値までアニメーション * @param {Object} target * @param {Object} props * @param {Object} duration * @param {Function} func */ by: function(target, props, duration, func) { var beginProps = {}; var finishProps = {}; for (var key in props) { beginProps[key] = target[key]; finishProps[key] = target[key] + props[key]; } this.fromTo(target, beginProps, finishProps, duration, func); return this; }, /** * 開始の値から終了の値までアニメーション * @param {Object} target * @param {Object} beginProps * @param {Object} finishProps * @param {Object} duration * @param {Function} func */ fromTo: function(target, beginProps, finishProps, duration, func) { this.target = target; this.beginProps = beginProps; this.finishProps = finishProps; this.duration = duration; // setup this.changeProps = {}; for (var key in beginProps) { this.changeProps[key] = finishProps[key] - beginProps[key]; } this.setTransition(func); return this; }, /** * @TODO ? * @param {Object} target * @param {Object} beginProps * @param {Object} duration * @param {Function} func */ from: function(target, beginProps, duration, func) { var finishProps = {}; for (var key in beginProps) { finishProps[key] = target[key]; } this.fromTo(target, beginProps, finishProps, duration, func); return this; }, /** * easingの指定か、コールバックの指定か調べる * @param {Function} func */ setTransition: function(func) { if (typeof func == 'function') { this.func = func; } else if (typeof func == 'string'){ this.func = tm.anim.easing[func]; } else { this.func = tm.anim.easing["default"]; } return this; }, /** * アニメーションの再開 */ resume: function() { this.isPlaying = true; this._resumeTime(); this._updateTime(); this.dispatchEvent(tm.event.TweenEvent("resume", this.time, this.nowProps)); }, /** * アニメーションの開始 */ start: function() { this.isPlaying = true; this._startTime(); this._updateTime(); this.dispatchEvent(tm.event.TweenEvent("start", this.time, this.nowProps)); }, /** * アニメーションのストップ */ stop: function() { this.isPlaying = false; this.dispatchEvent(tm.event.TweenEvent("stop", this.time, this.nowProps)); }, /** * 開始位置まで戻る */ rewind: function() { this.time = 0; this.update(); }, /** * 最後位置まで早送り */ fforward: function() { this.time = this.duration; this.update(); }, /** * ヨーヨーのアニメーション */ yoyo: function() { var temp = this.finishProps; this.finishProps = this.beginProps; this.beginProps = temp; for (var key in this.beginProps) { this.changeProps[key] = this.finishProps[key] - this.beginProps[key]; } this.start(); }, /** * 更新 */ update: function() { for (var key in this.changeProps) { this.nowProps[key] = this.func(this.time, this.beginProps[key], this.changeProps[key], this.duration); this.target[key] = this.nowProps[key]; } this.dispatchEvent(tm.event.TweenEvent("change", this.time, this.nowProps)); }, /** * 時間を巻き戻す * @private */ _resumeTime: function() { this.startTime = (new Date()).getTime() - this.time; }, /** * スタート時間を設定 * @private */ _startTime: function() { this.startTime = (new Date()).getTime(); }, /** * 時間を進める * @private */ _updateTime: function() { if (this.isPlaying) { this._setTime((new Date()).getTime() - this.startTime); setTimeout(arguments.callee.bind(this), 1000/this.fps); } }, /** * 時間を設定する * @param {Object} t * @private */ _setTime: function(t) { var time = t; // モーション終了 if (time > this.duration) { // ループ if (this.isLooping) { this.rewind(); // 座標を更新 this.update(); // イベント開始 this.dispatchEvent(tm.event.TweenEvent("loop", this.time, this.nowProps)); } // 終了 else { this.time = this.duration; // 座標を更新 this.update(); // 停止 this.stop(); // イベント this.dispatchEvent(tm.event.TweenEvent("finish", this.time, this.nowProps)); } } // 更新 else { this.time = time; // 座標を更新 this.update(); } } }); })(); /* * easing */ (function() { /** * @class tm.anim.easing * イージング * ### Reference * - * - * - * - */ tm.anim.easing = { /** default */ "default": function(t, b, c, d) { return c*t/d + b; }, /** linear */ linear: function(t, b, c, d) { return c*t/d + b; }, /** swing */ swing: function(t, b, c, d) { return -c *(t/=d)*(t-2) + b; }, /** easeInQuad */ easeInQuad: function(t, b, c, d) { return c*(t/=d)*t + b; }, /** easeOutQuad */ easeOutQuad: function(t, b, c, d) { return -c *(t/=d)*(t-2) + b; }, /** easeInOutQuad */ easeInOutQuad: function(t, b, c, d) { if((t/=d/2) < 1) return c/2*t*t + b; return -c/2 *((--t)*(t-2) - 1) + b; }, /** defeInCubic */ easeInCubic: function(t, b, c, d) { return c*(t/=d)*t*t + b; }, /** easeOutCubic */ easeOutCubic: function(t, b, c, d) { return c*((t=t/d-1)*t*t + 1) + b; }, /** easeInOutCubic */ easeInOutCubic: function(t, b, c, d) { if((t/=d/2) < 1) return c/2*t*t*t + b; return c/2*((t-=2)*t*t + 2) + b; }, /** easeOutInCubic */ easeOutInCubic: function(t, b, c, d) { if(t < d/2) return tm.anim.easing.easeOutCubic(t*2, b, c/2, d); return tm.anim.easing.easeInCubic((t*2)-d, b+c/2, c/2, d); }, /** easeInQuart */ easeInQuart: function(t, b, c, d) { return c*(t/=d)*t*t*t + b; }, /** easeOutQuart */ easeOutQuart: function(t, b, c, d) { return -c *((t=t/d-1)*t*t*t - 1) + b; }, /** easeInOutQuart */ easeInOutQuart: function(t, b, c, d) { if((t/=d/2) < 1) return c/2*t*t*t*t + b; return -c/2 *((t-=2)*t*t*t - 2) + b; }, /** easeOutInQuart */ easeOutInQuart: function(t, b, c, d) { if(t < d/2) return tm.anim.easing.easeOutQuart(t*2, b, c/2, d); return tm.anim.easing.easeInQuart((t*2)-d, b+c/2, c/2, d); }, /** easeInQuint */ easeInQuint: function(t, b, c, d) { return c*(t/=d)*t*t*t*t + b; }, /** easeOutQuint */ easeOutQuint: function(t, b, c, d) { return c*((t=t/d-1)*t*t*t*t + 1) + b; }, /** easeInOutQuint */ easeInOutQuint: function(t, b, c, d) { if((t/=d/2) < 1) return c/2*t*t*t*t*t + b; return c/2*((t-=2)*t*t*t*t + 2) + b; }, /** easeOutInQuint */ easeOutInQuint: function(t, b, c, d) { if(t < d/2) return tm.anim.easing.easeOutQuint(t*2, b, c/2, d); return tm.anim.easing.easeInQuint((t*2)-d, b+c/2, c/2, d); }, /** easeInSine */ easeInSine: function(t, b, c, d) { return -c * Math.cos(t/d *(Math.PI/2)) + c + b; }, /** easeOutSine */ easeOutSine: function(t, b, c, d) { return c * Math.sin(t/d *(Math.PI/2)) + b; }, /** easeInOutSine */ easeInOutSine: function(t, b, c, d) { return -c/2 *(Math.cos(Math.PI*t/d) - 1) + b; }, /** easeOutInSine */ easeOutInSine: function(t, b, c, d) { if(t < d/2) return tm.anim.easing.easeOutSine(t*2, b, c/2, d); return tm.anim.easing.easeInSine((t*2)-d, b+c/2, c/2, d); }, /** easeInExpo */ easeInExpo: function(t, b, c, d) { return(t==0) ? b : c * Math.pow(2, 10 *(t/d - 1)) + b - c * 0.001; }, /** easeOutExpo */ easeOutExpo: function(t, b, c, d) { return(t==d) ? b+c : c * 1.001 *(-Math.pow(2, -10 * t/d) + 1) + b; }, /** easeInOutExpo */ easeInOutExpo: function(t, b, c, d) { if(t==0) return b; if(t==d) return b+c; if((t/=d/2) < 1) return c/2 * Math.pow(2, 10 *(t - 1)) + b - c * 0.0005; return c/2 * 1.0005 *(-Math.pow(2, -10 * --t) + 2) + b; }, /** easeOutInExpo */ easeOutInExpo: function(t, b, c, d) { if(t < d/2) return tm.anim.easing.easeOutExpo(t*2, b, c/2, d); return tm.anim.easing.easeInExpo((t*2)-d, b+c/2, c/2, d); }, /** easeInCirc */ easeInCirc: function(t, b, c, d) { return -c *(Math.sqrt(1 -(t/=d)*t) - 1) + b; }, /** easeOutCirc */ easeOutCirc: function(t, b, c, d) { return c * Math.sqrt(1 -(t=t/d-1)*t) + b; }, /** easeInOutCirc */ easeInOutCirc: function(t, b, c, d) { if((t/=d/2) < 1) return -c/2 *(Math.sqrt(1 - t*t) - 1) + b; return c/2 *(Math.sqrt(1 -(t-=2)*t) + 1) + b; }, /** easeOutInCirc */ easeOutInCirc: function(t, b, c, d) { if(t < d/2) return tm.anim.easing.easeOutCirc(t*2, b, c/2, d); return tm.anim.easing.easeInCirc((t*2)-d, b+c/2, c/2, d); }, /** easeInElastic */ easeInElastic: function(t, b, c, d, a, p) { var s; if(t==0) return b; if((t/=d)==1) return b+c; if(!p) p=d*.3; if(!a || a < Math.abs(c)) { a=c; s=p/4; } else s = p/(2*Math.PI) * Math.asin(c/a); return -(a*Math.pow(2,10*(t-=1)) * Math.sin((t*d-s)*(2*Math.PI)/p )) + b; }, /** easeOutElastic */ easeOutElastic: function(t, b, c, d, a, p) { var s; if(t==0) return b; if((t/=d)==1) return b+c; if(!p) p=d*.3; if(!a || a < Math.abs(c)) { a=c; s=p/4; } else s = p/(2*Math.PI) * Math.asin(c/a); return(a*Math.pow(2,-10*t) * Math.sin((t*d-s)*(2*Math.PI)/p ) + c + b); }, /** easeInOutElastic */ easeInOutElastic: function(t, b, c, d, a, p) { var s; if(t==0) return b; if((t/=d/2)==2) return b+c; if(!p) p=d*(.3*1.5); if(!a || a < Math.abs(c)) { a=c; s=p/4; } else s = p/(2*Math.PI) * Math.asin(c/a); if(t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin((t*d-s)*(2*Math.PI)/p )) + b; return a*Math.pow(2,-10*(t-=1)) * Math.sin((t*d-s)*(2*Math.PI)/p )*.5 + c + b; }, /** easeOutInElastic */ easeOutInElastic: function(t, b, c, d, a, p) { if(t < d/2) return tm.anim.easing.easeOutElastic(t*2, b, c/2, d, a, p); return tm.anim.easing.easeInElastic((t*2)-d, b+c/2, c/2, d, a, p); }, /** easeInBack */ easeInBack: function(t, b, c, d, s) { if(s == undefined) s = 1.70158; return c*(t/=d)*t*((s+1)*t - s) + b; }, /** easeOutBack */ easeOutBack: function(t, b, c, d, s) { if(s == undefined) s = 1.70158; return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; }, /** easeInOutBack */ easeInOutBack: function(t, b, c, d, s) { if(s == undefined) s = 1.70158; if((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; }, /** easeOutInBack */ easeOutInBack: function(t, b, c, d, s) { if(t < d/2) return tm.anim.easing.easeOutBack(t*2, b, c/2, d, s); return tm.anim.easing.easeInBack((t*2)-d, b+c/2, c/2, d, s); }, /** easeInBounce */ easeInBounce: function(t, b, c, d) { return c - tm.anim.easing.easeOutBounce(d-t, 0, c, d) + b; }, /** easeOutBounce */ easeOutBounce: function(t, b, c, d) { if((t/=d) <(1/2.75)) { return c*(7.5625*t*t) + b; } else if(t <(2/2.75)) { return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; } else if(t <(2.5/2.75)) { return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; } else { return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; } }, /** easeInOutBounce */ easeInOutBounce: function(t, b, c, d) { if(t < d/2) return tm.anim.easing.easeInBounce(t*2, 0, c, d) * .5 + b; else return tm.anim.easing.easeOutBounce(t*2-d, 0, c, d) * .5 + c*.5 + b; }, /** easeOutInBounce */ easeOutInBounce: function(t, b, c, d) { if(t < d/2) return tm.anim.easing.easeOutBounce(t*2, b, c/2, d); return tm.anim.easing.easeInBounce((t*2)-d, b+c/2, c/2, d); } }; })(); /* * baseapp.js */ tm.app = tm.app || {}; (function() { /** * @class tm.app.BaseApp * ベースアプリケーション */ tm.app.BaseApp = tm.createClass({ /** エレメント */ element : null, /** マウスクラス */ mouse : null, /** タッチクラス */ touch : null, /** マウスクラス + タッチクラス */ pointing : null, /** キーボードクラス */ keyboard : null, /** 加速度センサー */ accelerometer : null, /** statsライブラリ */ stats : null, /** フレーム */ frame : 0, /** フレームレート */ fps : 30, /** 現在更新中か */ isPlaying : null, /** @private シーン情報の管理 */ _scenes : null, /** @private シーンのインデックス */ _sceneIndex : 0, /** * @constructor * @param {Object} elm */ init: function(elm) { this.element = elm; // マウスを生成 this.mouse = tm.input.Mouse(this.element); // タッチを生成 this.touch = tm.input.Touch(this.element, 0); // キーボードを生成 this.keyboard = tm.input.Keyboard(); // ポインティングをセット(PC では Mouse, Mobile では Touch) this.pointing = (tm.isMobile) ? this.touch : this.mouse; // 加速度センサーを生成 this.accelerometer = tm.input.Accelerometer(); // 再生フラグ this.isPlaying = true; // シーン周り this._scenes = [ tm.app.Scene() ]; this._sceneIndex = 0; // 決定時の処理をオフにする(iPhone 時のちらつき対策) this.element.addEventListener("touchstart", function(e) { e.stop(); }); // ウィンドウフォーカス時イベントリスナを登録 window.addEventListener("focus", function() { this.currentScene.dispatchEvent(tm.event.Event("focus")); }.bind(this)); // ウィンドウブラー時イベントリスナを登録 window.addEventListener("blur", function() { this.currentScene.dispatchEvent(tm.event.Event("blur")); }.bind(this)); // クリック this.element.addEventListener((tm.isMobile) ? "touchstart" : "mousedown", this._onclick.bind(this)); }, /** * 実行 */ run: function() { var self = this; // // requestAnimationFrame version // var fn = function() { // self._loop(); // requestAnimationFrame(fn); // } // fn(); tm.setLoop(function(){ self._loop(); }, 1000/this.fps); return ; if (true) { setTimeout(arguments.callee.bind(this), 1000/this.fps); this._loop(); } return ; var self = this; // setInterval(function(){ self._loop(); }, 1000/self.fps); tm.setLoop(function(){ self._loop(); }, 1000/self.fps); }, /* * ループ処理 * @private */ _loop: function() { // update if (this.update) this.update(); this._update(); // draw if (this.draw) this.draw(); this._draw(); // stats update if (this.stats) this.stats.update(); }, /** * シーンを切り替える * @param {Object} scene * ## Reference * - */ replaceScene: function(scene) { var e = null; if (this.currentScene) { e = tm.event.Event("exit"); e.app = this; this.currentScene.dispatchEvent(e); this.currentScene.app = null; } e = tm.event.Event("enter"); e.app = this; this.currentScene = scene; this.currentScene.app = this; this.currentScene.dispatchEvent(e); return this; }, /** * シーンをプッシュする(ポーズやオブション画面などで使用) * @param {Object} scene */ pushScene: function(scene) { e = tm.event.Event("exit"); e.app = this; this.currentScene.dispatchEvent(e); this._scenes.push(scene); ++this._sceneIndex; e = tm.event.Event("enter"); e.app = this; scene.app = this; scene.dispatchEvent(e); return this; }, /** * シーンをポップする(ポーズやオブション画面などで使用) */ popScene: function() { var scene = this._scenes.pop(); --this._sceneIndex; e = tm.event.Event("exit"); e.app = this; scene.dispatchEvent(e); scene.app = null; // e = tm.event.Event("enter"); e.app = this; this.currentScene.dispatchEvent(e); return scene; }, /** * 外部のFPS表示ライブラリ Stats を生成、配置する * ## Reference * - */ enableStats: function() { if (window["Stats"]) { // Stats this.stats = new Stats(); // 右上に設定 this.stats.domElement.style.position = "fixed"; this.stats.domElement.style.left = "5px"; this.stats.domElement.style.top = "20px"; document.body.appendChild(this.stats.domElement); } else { console.warn("not defined stats."); } return this; }, /** * dat gui を有効化 */ enableDatGUI: function() { if (window.dat) { var gui = new dat.GUI(); return gui; } }, /** * シーンのupdateを実行するようにする */ start: function() { this.isPlaying = true; return this; }, /** * シーンのupdateを実行しないようにする */ stop: function() { this.isPlaying = false; return this; }, /** * デバイスやシーンのアップデート呼び出し処理 * @private */ _update: function() { // デバイス系 Update this.mouse.update(); this.keyboard._update(); this.touch.update(); // this.touches.update(); if (this.isPlaying) { this.currentScene._update(this); ++this.frame; } }, /** * @TODO ? オーバーライド予定? * @private */ _draw: function() {}, /** * elementの取得 */ getElement: function() { return this.element; }, /** * クリックイベント登録 * @private * @param {Object} e */ _onclick: function(e) { var px = e.pointX; var py = e.pointY; if (this.element.style.width) { px *= this.element.width / parseInt(this.element.style.width); } if (this.element.style.height) { py *= this.element.height / parseInt(this.element.style.height); } var _fn = function(elm) { if (elm.children.length > 0) { elm.children.each(function(elm) { if (elm.hasEventListener("click")) { if (elm.isHitPoint && elm.isHitPoint(px, py)) { elm.dispatchEvent(tm.event.Event("click")); } } }); } }; _fn(this.currentScene); }, }); /** * @property currentScene * カレントシーン * @TODO どうしよう? */ tm.app.BaseApp.prototype.accessor("currentScene", { "get": function() { return this._scenes[this._sceneIndex]; }, "set": function(v){ this._scenes[this._sceneIndex] = v; } }); })(); /* * element.js */ tm.app = tm.app || {}; (function() { /** * @class tm.app.Element * アプリケーション用オブジェクトの基底となるクラス * 親子関係の情報を管理する * @extends tm.event.EventDispatcher */ tm.app.Element = tm.createClass({ superClass: tm.event.EventDispatcher, /** 親 */ parent: null, /** 子 */ children: null, /** @private */ _listeners: null, /** * @constructor */ init: function() { this.superInit(); this.children = []; this._listeners = {}; }, /** * 親から離す */ remove: function() { console.assert(this.parent); this.parent.removeChild(this); this.parent = null; return this; }, /** * 子供を追加 * @param {Object} child */ addChild: function(child) { if (child.parent) child.remove(); child.parent = this; this.children.push(child); var e = tm.event.Event("added"); child.dispatchEvent(e); return child; }, /** * parent に自分を子供として追加 * @param {Object} parent */ addChildTo: function(parent) { parent.addChild(this); // if (this.parent) this.remove(); // this.parent = parent; // parent.children.push(child); return this; }, /** * まとめて追加 * scene 遷移時に子供をごっそり移譲するときなどに使用 * まだ動作確認していない * @param {Object} children */ addChildren: function(children) { var tempChildren = children.slice(); for (var i=beginIndex,len=tempChildren.length; i 0) { var tempChildren = this.children.slice(); for (var i=0,len=tempChildren.length; i 0) { tween.delay -= 1000/app.fps; continue; } var time = tween.time + 1000/app.fps; tween._setTime(time); if (tween.time >= tween.duration) { // 削除 this.tweens.erase(tween); // 全てのアニメーション終了チェック if (this.tweens.length <= 0) { this.isAnimation = false; var e = tm.event.Event("animationend"); this.element.dispatchEvent(e); this.dispatchEvent(e); } } else { tween.update(); } } }, /** * タスクの更新 * @private * @param {Object} app */ _updateTask: function(app) { if (!this.isPlaying) return ; var task = this._tasks[this._index]; if (!task) { if (this.loop === true) { this._index = 0; } else { this.isPlaying = false; } return ; } this._index++; if (task.type == "tween") { var data = task.data; var fnStr= task.data.type; var args = task.data.args; this._tween = tm.anim.Tween(); this._tween[fnStr].apply(this._tween, args); this._func = this._updateTween; this._func(app); } else if (task.type == "wait") { this._wait = task.data; this._wait.time = 0; this._func = this._updateWait; this._func(app); } else if (task.type == "call") { task.data.func.apply(null, task.data.args); // 1フレーム消費しないよう再帰 this._updateTask(app); } else if (task.type == "set") { this.element.$extend(task.data.values); // 1フレーム消費しないよう再帰 this._updateTask(app); } }, /** * Tween の更新 * @private * @param {Object} elm */ _updateTween: function(app) { var tween = this._tween; var time = tween.time + 1000/app.fps; tween._setTime(time); if (tween.time >= tween.duration) { // 削除 delete this._tween; this._tween = null; this._func = this._updateTask; } else { tween.update(); } }, /** * 時間の更新 * @private * @param {Object} elm */ _updateWait: function(app) { var wait = this._wait; wait.time += 1000/app.fps; if (wait.time >= wait.limit) { delete this._wait; this._wait = null; this._func = this._updateTask; } }, /** * @TODO ? * @param {Object} param */ add: function(param) { if (!param.target) param.target = this.element; this._tasks.push({ type: "tween", data: param }); if (this.isAnimation == false) { this.isAnimation = true; var e = tm.event.Event("animationstart"); this.element.dispatchEvent(e); } return this; }, /** * 指定した値を足した値までアニメーション * @param {Object} props * @param {Object} duration * @param {Function} fn */ by: function(props, duration, fn) { this._addTweenTask({ props: props, duration: duration, fn: fn, type: "by" }); return this; }, /** * 指定した値までアニメーション * @param {Object} props * @param {Object} duration * @param {Function} fn */ to: function(props, duration, fn) { this._addTweenTask({ props: props, duration: duration, fn: fn, type: "to" }); return this; }, /** * 移動アニメーション * @param {Number} x * @param {Number} y * @param {Object} duration * @param {Function} fn */ move: function(x, y, duration, fn) { return this.to({x:x, y:y}, duration, fn); }, /** * 指定した値を足した座標までアニメーション * @param {Number} x * @param {Number} y * @param {Object} duration * @param {Function} fn */ moveBy: function(x, y, duration, fn) { return this.by({x:x, y:y}, duration, fn); }, /** * 回転アニメーション * @param {Number} rotation * @param {Object} duration * @param {Function} fn */ rotate: function(rotation, duration, fn) { return this.to({rotation:rotation}, duration, fn); }, /** * 拡縮アニメーション * @param {Number} scale * @param {Object} duration * @param {Function} fn */ scale: function(scale, duration, fn) { return this.to({scaleX:scale, scaleY:scale}, duration, fn); }, /** * フェードアニメーション * @param {Object} value * @param {Object} duration */ fade: function(value, duration) { this.to({"alpha":value}, duration); return this; }, /** * フェードイン * @param {Object} duration */ fadeIn: function(duration) { this.fade(1.0, duration); return this; }, /** * フェードアウト * @param {Object} duration */ fadeOut: function(duration) { this.fade(0.0, duration); return this; }, /** * Tween のタスクを追加 * @private * @param {Object} param */ _addTweenTask: function(param) { param.target = (param.target !== undefined) ? param.target : this.element; param.duration = (param.duration !== undefined) ? param.duration : 1000; this._tasks.push({ type: "tween", data: { args: [param.target, param.props, param.duration, param.fn], type: param.type } }); if (this.isAnimation == false) { this.isAnimation = true; var e = tm.event.Event("animationstart"); this.element.dispatchEvent(e); } return this; }, /** * 待ち時間 * @param {Object} time */ wait: function(time) { this._tasks.push({ type: "wait", data: { limit: time } }); return this; }, /** * コールバックを登録 * @param {Function} fn * @param {Object} args */ call: function(fn, args) { this._tasks.push({ type: "call", data: { func: fn, args: args, }, }); return this; }, /** * プロパティをセット * @param {Object} key * @param {Object} value */ set: function(key, value) { var values = null; if (arguments.length == 2) { values = {}; values[key] = value; } else { values = key; } this._tasks.push({ type: "set", data: { values: values } }); return this; }, /** * アニメーション開始 */ play: function() { this.isPlaying = true; return this; }, /** * アニメーションを一時停止 */ pause: function() { this.isPlaying = false; return this; }, /** * アニメーションを巻き戻す */ rewind: function() { this._func = this._updateTask; this._index = 0; this.play(); return this; }, /** * アニメーションループ設定 * @param {Boolean} flag */ setLoop: function(flag) { this.loop = flag; return this; }, /** * アニメーションをクリア */ clear: function() { this._init(); return this; } }); /** * @member tm.app.Element * @property tweener * トゥイーンアニメーション */ tm.app.Element.prototype.getter("tweener", function() { if (!this._tweener) { this._tweener = tm.app.Tweener(this); } return this._tweener; }); })(); /* * timeline.js */ tm.namespace("tm.app", function() { /** * @class tm.app.Timeline * タイムラインクラス * @extends tm.event.EventDispatcher */ tm.define("tm.app.Timeline", { superClass: "tm.event.EventDispatcher", /** * @constructor * @param {Object} elm */ init: function(elm) { this.superInit(); this.setTarget(elm); this.fps = 30; this.currentFrame = 0; this.duration = 0; this.isPlay = true; this._tweens = []; this._actions = []; }, /** * 更新 * @param {Object} app */ update: function(app) { if (!this.isPlay) return ; if (this.currentFrame > this.duration) { // this.gotoAndPlay(0); } else { this._updateTween(); this._updateAction(); } this.currentFrame++; }, /** * @TODO ? * @private */ _updateTween: function() { var tweens = this._tweens; for (var i=0,len=tweens.length; i this.currentFrame) { continue ; } var time = this.currentFrame - tween.delay; tween._setTime(time); if (tween.time >= tween.duration) { } else { tween.update(); } } }, /** * @TODO ? * @private */ _updateAction: function() { var actions = this._actions; for (var i=0,len=actions.length; i 0) { var tempChildren = obj.children.slice(); for (var i=0,len=tempChildren.length; i 40) len = 40; this.angle = Math.radToDeg(v.toAngle()); this.circle.position.set(v.x*len, v.y*len); // 大きさ this.distance = len/40.0; // 向きベクトル this.direction = v.mul(this.distance); } }); })(); /* * button.js */ tm.ui = tm.ui || {}; (function() { /** * @class tm.ui.LabelButton * LabelButton * @extends tm.display.Label */ tm.ui.LabelButton = tm.createClass({ superClass: tm.display.Label, /** * @constructor */ init: function(text) { this.superInit(text); this.alpha = tm.ui.LabelButton.DEFAULT_ALPHA; this.setAlign("center").setBaseline("middle"); this.setInteractive(true); this.boundingType = "rect"; this.addEventListener("pointingover", function() { this.tweener.clear(); this.tweener.fadeIn(250); }.bind(this)); this.addEventListener("pointingout", function() { this.tweener.clear(); this.tweener.fade(tm.ui.LabelButton.DEFAULT_ALPHA, 250); }.bind(this)); /* var d = this.draw; this.draw = function(canvas) { d.call(this, canvas); this.drawBoundingRect(canvas); } /* */ } }); /** * @static * @property * デフォルトとなるアルファ値 */ tm.ui.LabelButton.DEFAULT_ALPHA = 0.5; })(); (function() { /** * @class tm.ui.IconButton * IconButton * @extends tm.display.Sprite */ tm.ui.IconButton = tm.createClass({ superClass: tm.display.Sprite, /** * @constructor */ init: function(texture) { if (texture) { this.superInit(texture, texture.width, texture.height); } else { this.superInit(); } this.alpha = tm.ui.IconButton.DEFAULT_ALPHA; this.setInteractive(true); this.boundingType = "rect"; this.addEventListener("pointingover", function() { this.tweener.clear(); this.tweener.fade(1, 250); }); this.addEventListener("pointingout", function() { this.tweener.clear(); this.tweener.fade(tm.ui.LabelButton.DEFAULT_ALPHA, 250); }); }, }); /** * @static * @property * デフォルトとなるアルファ値 */ tm.ui.IconButton.DEFAULT_ALPHA = 0.5; })(); (function() { /** * @class tm.ui.GlossyButton * glossy button * @extends tm.display.Shape */ tm.ui.GlossyButton = tm.createClass({ superClass: tm.display.Shape, /** * @constructor */ init: function(width, height, backgroundColor, text) { this.superInit(width, height); text = text || "Button"; this.backgroundColor = backgroundColor || "black"; this.alpha = tm.ui.GlossyButton.DEFAULT_ALPHA; this.setInteractive(true); this.boundingType = "rect"; this.addEventListener("pointingover", function() { this.tweener.clear(); this.tweener.fade(1.0, 250); }); this.addEventListener("pointingout", function() { this.tweener.clear(); this.tweener.fade(tm.ui.GlossyButton.DEFAULT_ALPHA, 250); }); // ラベル this.label = tm.display.Label(text || "").addChildTo(this); this.label.setAlign("center").setBaseline("middle"); this._refresh(); }, /** * @TODO ? */ setBackgroundColor: function(backgroundColor) { this.backgroundColor = backgroundColor; this._refresh(); return this; }, /** * @TODO ? * @private */ _refresh: function() { // ボタン描画 var c = this.canvas; c.resize(this.width, this.height); c.fillStyle = this.backgroundColor; c.fillRoundRect(2, 2, this.width-4, this.height-4, 10); c.strokeStyle = "rgba(100,100,100,0.75)"; c.lineWidth = 2; c.strokeRoundRect(2, 2, this.width-4, this.height-4, 10); // テカリ c.roundRect(2, 2, this.width-4, this.height-4, 10); c.clip(); var grad = tm.graphics.LinearGradient(0, 0, 0, this.height); // grad.addColorStop(0.0, "hsl( 0, 75%, 50%)"); // grad.addColorStop(0.5, "hsl(120, 75%, 50%)"); // grad.addColorStop(1.0, "hsl(240, 75%, 50%)"); grad.addColorStop(0.0, "rgba(255,255,255,0.9)"); grad.addColorStop(0.5, "rgba(255,255,255,0.5)"); grad.addColorStop(0.51, "rgba(255,255,255,0.2)"); grad.addColorStop(1.0, "rgba(255,255,255,0.0)"); c.setGradient(grad); c.fillRect(2, 2, this.width-4, this.height-4, 10); // ラベルのサイズをリセット this.label.setSize(this.width, this.height); }, }); /** * @static * @property * デフォルトとなるアルファ値 */ tm.ui.GlossyButton.DEFAULT_ALPHA = 0.5; })(); (function() { /** * @class tm.ui.FlatButton * フラットデザインのボタン * @extends tm.display.Shape */ tm.define("tm.ui.FlatButton", { superClass: tm.display.Shape, /** * @constructor */ init: function(param) { param.$safe({ width: 300, height: 100, bgColor: "rgb(180, 180, 180)", text: "ABC", fontSize: 50, fontFamily: "'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', 'メイリオ', 'Meiryo', 'MS Pゴシック', 'MS PGothic', sans-serif", }); this.superInit(param.width, param.height); this.canvas.clearColor(param.bgColor); this.setInteractive(true); this.setBoundingType("rect"); this.label = tm.display.Label(param.text).addChildTo(this); this.label.setFontSize(param.fontSize).setFontFamily(param.fontFamily).setAlign("center").setBaseline("middle"); }, }); })(); /* * menudialog.js */ (function() { /** * @class tm.ui.MenuDialog * メニューダイアログ * @extends tm.app.Scene */ tm.define("tm.ui.MenuDialog", { superClass: tm.app.Scene, /** @type {string} タイトル */ titleText: null, /** @type {Array.} メニュー名リスト */ menu: null, /** @type {Array.} メニュー詳細リスト */ descriptions: null, /** @type {boolean} exit の表示/非表示 */ showExit: false, /** @type {tm.display.Label} dummy */ title: null, /** @type {Array.} dummy */ selections: [], /** @type {tm.display.Label} dummy */ description: null, /** @type {tm.display.RectangleShape} dummy */ box: null, /** @type {tm.display.RectangleShape} dummy */ cursor: null, /** @private */ _selected: 0, /** @private */ _opened: false, /** @private */ _finished: false, /** @private */ _screenWidth: 0, /** @private */ _screenHeight: 0, /** * @constructor * @param {Object} params */ init: function(params) { this.superInit(); this._screenWidth = params.screenWidth; this._screenHeight = params.screenHeight; this.titleText = params.title; this.menu = [].concat(params.menu); this._selected = ~~params.defaultSelected; this.showExit = !!params.showExit; if (params.menuDesctiptions) { this.descriptions = params.menuDesctiptions; } else { this.descriptions = [].concat(params.menu); } if (this.showExit) { this.menu.push("exit"); this.descriptions.push("前の画面へ戻ります"); } var height = Math.max((1+this.menu.length)*50, 50) + 40; this.box = tm.display.RectangleShape(this._screenWidth * 0.8, height, { strokeStyle: "rgba(0,0,0,0)", fillStyle: "rgba(43,156,255, 0.8)", }).setPosition(this._screenWidth*0.5, this._screenHeight*0.5); this.box.width = 1; this.box.height = 1; this.box.setBoundingType("rect"); this.box.tweener .to({ width: this._screenWidth*0.8, height: height }, 200, "easeOutExpo") .call(this._onOpen.bind(this)); this.box.addChildTo(this); this.description = tm.display.Label("", 14) .setAlign("center") .setBaseline("middle") .setPosition(this._screenWidth*0.5, this._screenHeight-10) .addChildTo(this); }, /** * @TODO ? * @private */ _onOpen: function() { var self = this; var y = this._screenHeight*0.5 - this.menu.length * 25; this.title = tm.display.Label(this.titleText, 30) .setAlign("center") .setBaseline("middle") .setPosition(this._screenWidth*0.5, y) .addChildTo(this); this.cursor = this._createCursor(); this.selections = this.menu.map(function(text, i) { var self = this; y += 50; var selection = tm.ui.LabelButton(text) .setPosition(this._screenWidth*0.5, y) .addChildTo(this); selection.interactive = true; selection.addEventListener("click", function() { if (self._selected === i) { self.closeDialog(self._selected); } else { self._selected = i; var e = tm.event.Event("menuselect"); e.selectValue = self.menu[self._selected]; e.selectIndex = i; self.dispatchEvent(e); } }); selection.width = this._screenWidth * 0.7; return selection; }.bind(this)); this.cursor.y = this.selections[this._selected].y; this._opened = true; // close window when touch bg outside this.addEventListener("pointingend", function(e) { var p = e.app.pointing; if (!self.box.isHitPoint(p.x, p.y)) { self.closeDialog(self._selected); } }); // dispatch opened event var e = tm.event.Event("menuopened"); this.dispatchEvent(e); }, /** * @TODO ? * @private */ _createCursor: function() { var cursor = tm.display.RectangleShape(this._screenWidth*0.7, 30, { strokeStyle: "rgba(0,0,0,0)", fillStyle: "rgba(12,79,138,1)" }).addChildTo(this); cursor.x = this._screenWidth*0.5; cursor.target = this._selected; cursor.update = function() { if (this.target !== this.parent._selected) { this.target = this.parent._selected; this.tweener.clear(); this.tweener.to({ y: this.parent.selections[this.parent._selected].y }, 200, "easeOutExpo"); } }; return cursor; }, /** * @TODO ? */ update: function(app) { this.description.text = this.descriptions[this._selected]; }, /** * @TODO ? */ closeDialog: function(result) { this._finished = true; var e = tm.event.Event("menuselected"); e.selectIndex = result; this.dispatchEvent(e); this.tweener .clear() .wait(200) .call(function() { this.cursor.remove(); this.title.remove(); this.selections.each(function(sel) { sel.remove(); }); this.box.tweener.clear(); this.box.tweener .to({ width: 1, height: 1 }, 200, "easeInExpo") .call(function() { this.app.popScene(); var e = tm.event.Event("menuclosed"); e.selectIndex = result; this.dispatchEvent(e); }.bind(this)); }.bind(this)); this.cursor.tweener .clear() .call(function() { this.visible = !this.visible; }.bind(this.cursor)) .setLoop(true); }, /** * @TODO ? */ draw: function(canvas) { canvas.fillStyle = "rgba(0,0,0,0.8)"; canvas.fillRect(0,0,this._screenWidth,this._screenHeight); }, }); })(); /* * sketch.js */ ;(function() { var DEFAULT_PARAM = { bgColor: "rgba(255, 255, 255, 1.0)", penColor: "rgba(0, 0, 0, 1.0)", lineWidth: 16, }; /** * @class tm.ui.Sketch * Sketch * @extends tm.display.Shape */ tm.define("tm.ui.Sketch", { superClass: "tm.display.Shape", /** * @constructor */ init: function(width, height, param) { this.superInit(width, height); param = param || {}; param.$safe(DEFAULT_PARAM); this._setup(param); }, _setup: function(param) { var self = this; // setup this this.boundingType = "rect"; this.setInteractive(true); // setup canvas var c = this.canvas.context; c.lineCap = "round"; c.lineJoin = "round"; c.miterLimit = 10.0; this.bgColor = param.bgColor; this.penColor = param.penColor; this.lineWidth = param.lineWidth; // setup event this.on("pointingstart", function(e) { var p = e.app.pointing; self._drawPoint(p.position); }); this.on("pointingmove", function(e) { var p = e.app.pointing; self._drawLine(p.prevPosition, p.position); }); }, /** * 画面をbgColor色でクリアする */ clear: function() { this.canvas.clear(); this.canvas.clearColor(this.bgColor); return this; }, _drawPoint: function(p) { this.canvas.drawPoint(p.x-this.left, p.y-this.top); }, _drawLine: function(p, prev) { this.canvas.drawLine( p.x-this.left, p.y-this.top, prev.x-this.left, prev.y-this.top ); }, }); /** * @property penColor * penColor */ tm.ui.Sketch.prototype.accessor("penColor", { "get": function() { return this._penColor; }, "set": function(v) { this._penColor = v; this.canvas.strokeStyle = v; } }); /** * @property bgColor * bgColor */ tm.ui.Sketch.prototype.accessor("bgColor", { "get": function() { return this._bgColor; }, "set": function(v) { this._bgColor = v; this.clear(); } }); /** * @property lineWidth * lineWidth */ tm.ui.Sketch.prototype.accessor("lineWidth", { "get": function() { return this._lineWidth; }, "set": function(v) { this._lineWidth = v; this.canvas.lineWidth = v; } }); })(); /* * gauge.js */ (function() { /** * @class tm.ui.Gauge * ゲーム用ゲージクラス * @extends tm.display.CanvasElement */ tm.ui.Gauge = tm.createClass({ superClass: tm.display.CanvasElement, /** * アニメーションさせるかどうかのフラグ */ animationFlag: true, /** * 0~100 に変化する際にかかる時間 * つまり10*1000 だった場合は, 0~10に変化するさいに 1秒かかる */ animationTime: 10*1000, // 10 秒 /** * @constructor */ init: function(param) { this.superInit(); param = param || {}; param.$safe({ width: 300, height: 25, color: "hsl(220, 100%, 50%)", bgColor: "#444", borderColor: "white", borderWidth: 4, }); this.$extend(param); this._reset(); }, /** * @TODO ? */ isFull: function() { return this.targetProp === this._maxValue; }, /** * @TODO ? */ isEmpty: function() { return this.targetProp == 0; }, /** * @TODO ? * @private */ _reset: function(direction) { this.originX = 0; this._value = 100; this._value = this._maxValue = 100; }, /** * @TODO ? */ setValue: function(value) { value= Math.clamp(value, 0, this._maxValue); this._realValue = value; // end when now value equal value of argument if (this._value === value) return ; // fire value change event this.fire(tm.event.Event("change")); if (this.isAnimation()) { this.tweener.clear(); var time = (Math.abs(this._value-value)/100)*this.animationTime; this.tweener.clear() .to({ "_value":value }, time) .call(function() { this.fire(tm.event.Event("changed")); }.bind(this)); } else { this._value = value; this.fire(tm.event.Event("change")); this.fire(tm.event.Event("changed")); } return this; }, /** * @TODO ? */ getValue: function() { return this.value; }, /** * @TODO ? */ setPercent: function(percent) { return this.setValue(this._maxValue*percent*0.01); }, /** * @TODO ? */ getPercent: function() { return (this._value/this._maxValue)*100; }, /** * @TODO ? */ setRatio: function(ratio) { return this.setValue(this._maxValue*percent); }, /** * @TODO ? */ getRatio: function() { return this._value/this._maxValue; }, isAnimation: function() { return this.animationFlag; }, draw: function(canvas) { canvas.save(); // bg canvas.fillStyle = this.bgColor; canvas.fillRect(0, 0, this.width, this.height); // bar canvas.fillStyle = this.color; canvas.fillRect(0, 0, this.width*this.getRatio(), this.height); // border canvas.strokeStyle = this.borderColor; canvas.lineWidth = this.borderWidth; canvas.strokeRect(0, 0, this.width, this.height); canvas.restore(); } }); /** * @property value * 値 */ tm.ui.Gauge.prototype.accessor("value", { get: function() { return this._value; }, set: function(v) { this.setValue(v); }, }); /** * @property percent * パーセント */ tm.ui.Gauge.prototype.accessor("percent", { get: function() { return this.getPercent(); }, set: function(v) { this.setPercent(v); }, }); /** * @property ratio * 比率 */ tm.ui.Gauge.prototype.accessor("ratio", { get: function() { return this.getRatio(); }, set: function(v) { this.setRatio(v); }, }); })(); ;(function() { /** * @class tm.ui.FlatGauge * ゲーム用ゲージクラス * @extends tm.ui.Gauge */ tm.define("tm.ui.FlatGauge", { superClass: "tm.ui.Gauge", /** * @constructor */ init: function(param) { this.superInit(param); }, draw: function(canvas) { canvas.save(); canvas.save(); canvas.roundRect(0, 0, this.width, this.height, this.height/2); canvas.clip(); // bg canvas.fillStyle = this.bgColor; canvas.fillRect(0, 0, this.width, this.height); // bar canvas.fillStyle = this.color; canvas.fillRect(0, 0, this.width*this.getRatio(), this.height); canvas.restore(); // border canvas.strokeStyle = this.borderColor; canvas.lineWidth = this.borderWidth; canvas.strokeRoundRect(0, 0, this.width, this.height, this.height/2); canvas.restore(); }, }); })(); ;(function() { /** * @class tm.ui.GlossyGauge * ゲーム用ゲージクラス * @extends tm.ui.Gauge */ tm.define("tm.ui.GlossyGauge", { superClass: "tm.ui.Gauge", init: function(param) { param = param || {}; param.borderWidth = param.borderWidth || 2; this.superInit(param); }, /** * @constructor */ draw: function(c) { c.save(); // clip c.roundRect(0, 0, this.width, this.height, this.height/2); c.clip(); // bg c.fillStyle = this.bgColor; c.fillRect(0, 0, this.width, this.height); // bar c.fillStyle = this.color; c.fillRect(0, 0, this.width*this.getRatio(), this.height); var grad = tm.graphics.LinearGradient(0, 0, 0, this.height); grad.addColorStop(0.0, "rgba(255,255,255,0.9)"); grad.addColorStop(0.5, "rgba(255,255,255,0.5)"); grad.addColorStop(0.51, "rgba(255,255,255,0.2)"); grad.addColorStop(1.0, "rgba(255,255,255,0.0)"); c.setGradient(grad); c.fillRect(0, 0, this.width*this.getRatio(), this.height); c.restore(); // border c.lineWidth = this.borderWidth; c.strokeStyle = this.borderColor; c.strokeRoundRect(0, 0, this.width, this.height, this.height/2); }, }); })(); /* * loadingscene.js */ ;(function() { var DEFAULT_PARAM = { width: 465, height: 465, }; tm.define("tm.ui.LoadingScene", { superClass: "tm.app.Scene", init: function(param) { this.superInit(); param = {}.$extend(DEFAULT_PARAM, param); this.bg = tm.display.Shape(param.width, param.height).addChildTo(this); this.bg.canvas.clearColor("hsla(200, 80%, 70%, 1.0)"); this.bg.setOrigin(0, 0); var label = tm.display.Label("Loading"); label.x = param.width/2; label.y = param.height/2; label.width = param.width; label.align = "center"; label.baseline = "middle"; label.fontSize = 32; label.counter = 0; label.update = function(app) { if (app.frame % 30 == 0) { this.text += "."; this.counter += 1; if (this.counter > 3) { this.counter = 0; this.text = "Loading"; } } }; label.addChildTo(this.bg); // ひよこさん var piyo = tm.display.Shape(84, 84); piyo.setPosition(param.width, param.height - 80); piyo.canvas.setColorStyle("white", "yellow").fillCircle(42, 42, 32); piyo.canvas.setColorStyle("white", "black").fillCircle(27, 27, 2); piyo.canvas.setColorStyle("white", "brown").fillRect(40, 70, 4, 15).fillTriangle(0, 40, 11, 35, 11, 45); piyo.update = function(app) { piyo.x -= 4; if (piyo.x < -80) piyo.x = param.width; piyo.rotation -= 7; }; piyo.addChildTo(this.bg); this.alpha = 0.0; this.bg.tweener.clear().fadeIn(100).call(function() { if (param.assets) { var loader = tm.asset.Loader(); loader.onload = function() { this.bg.tweener.clear().wait(200).fadeOut(200).call(function() { if (param.nextScene) { this.app.replaceScene(param.nextScene()); } var e = tm.event.Event("load"); this.fire(e); }.bind(this)); }.bind(this); loader.onprogress = function(e) { var event = tm.event.Event("progress"); event.progress = e.progress; this.fire(event); }.bind(this); loader.load(param.assets); } }.bind(this)); }, }); })(); /* * three.js */ tm.three = tm.three || {}; (function() { if (!tm.global.THREE) return ; /** * @class tm.three.ThreeApp * 3Dライブラリ - Three.jsをtmlib.jsで対応 * @extends tm.app.BaseApp */ tm.three.ThreeApp = tm.createClass({ superClass: tm.app.BaseApp, /** canvas */ canvas : null, /** canvas */ background : null, /** @private canvas */ _scenes : null, /** @private canvas */ _sceneIndex : 0, /** * @constructor */ init: function(canvas) { if (canvas instanceof HTMLCanvasElement) { this.element = canvas; } else if (typeof canvas == "string") { this.element = document.querySelector(canvas); } else { this.element = document.createElement("canvas"); document.body.appendChild(this.element); } // 親の初期化 this.superInit(this.element); // レンダラーを生成 // this.renderer = new THREE.CanvasRenderer({ canvas: this.element }); this.renderer = new THREE.WebGLRenderer({ canvas: this.element, clearColor: 0x222222, clearAlpha: 1.0 }); this.renderer.setSize(this.element.width, this.element.height); // シーン周り this._scenes = [ tm.three.Scene() ]; }, /** * @TODO ? */ resize: function(width, height) { this.width = width; this.height= height; this.renderer.setSize(this.width, this.height); return this; }, /** * @TODO ? */ resizeWindow: function() { this.width = innerWidth; this.height= innerHeight; this.renderer.setSize(this.width, this.height); return this; }, /** * 画面にフィットさせる */ fitWindow: function(everFlag) { // 画面にフィット var _fitFunc = function() { everFlag = everFlag === undefined ? true : everFlag; var e = this.element; var s = e.style; s.position = "absolute"; s.left = "0px"; s.top = "0px"; var rateWidth = e.width/window.innerWidth; var rateHeight= e.height/window.innerHeight; var rate = e.height/e.width; if (rateWidth > rateHeight) { s.width = innerWidth+"px"; s.height = innerWidth*rate+"px"; } else { s.width = innerHeight/rate+"px"; s.height = innerHeight+"px"; } }.bind(this); // 一度実行しておく _fitFunc(); // リサイズ時のリスナとして登録しておく if (everFlag) { window.addEventListener("resize", _fitFunc, false); } // マウスとタッチの座標更新関数をパワーアップ this.mouse._mousemove = this.mouse._mousemoveScale; this.touch._touchmove = this.touch._touchmoveScale; }, /** * @TODO ? * @private */ _draw: function() { // 描画は全てのシーン行う for (var i=0, len=this._scenes.length; i 0) { var tempChildren = this.children.slice(); for (var i=0,len=tempChildren.length; i * ### Example * tm.social.Twitter.createURL({ * type : "tweet", // タイプ(tweet/retweet/favorite/user) * tweet_id : "210219483959263232", // 対象となる Tweet * in_reply_to : "210219483959263232", // 返信する対象となる Tweet * text : "Test", // テキスト * screen_name : "phi_jp", // スクリーンネーム * hashtags : "javascript,tmlibjs", // ハッシュタグ * url : "http://tmlife.net", // url * via : "phi_jp", // ~から * related : "tmlib.js tmlife", // 関連ワード * }); */ tm.social.Twitter.createURL = function(prop) { var param_string_list = []; for (var key in prop) { if (key == "type") continue; var value = encodeURIComponent(prop[key]); var param_string = key+"="+value; param_string_list.push(param_string); } var url = "{baseURL}/{type}?{param}".format({ baseURL : BASE_URL, type : prop.type, param : param_string_list.join('&'), }); return url; }; })(); (function() { var BASE_URL = "http://api.twitter.com/1/{type}/{kind}.json"; /** * @member tm.social.Twitter */ tm.social.Twitter.api = function(type, kind, param, callback) { var url = BASE_URL.format({ type:type, kind:kind }); var qs = tm.util.QueryString.stringify(param); tm.util.Ajax.loadJSONP(url + "?" + qs, callback); }; })(); (function() { var BASE_URL = "http://search.twitter.com/search.json"; /** * @member tm.social.Twitter */ tm.social.Twitter.search = function(param, callback) { var url = BASE_URL; var qs = tm.util.QueryString.stringify(param); tm.util.Ajax.loadJSONP(url + "?" + qs, callback); }; })(); (function() { /* * format = xml or json */ var BASE_URL = "http://api.twitter.com/1/statuses/followers.json"; //http://api.twitter.com/1/statuses/followers.json?id=tmlife_jp /** * @member tm.social.Twitter * * user_id ユーザーID * screen_name screen_name * cursor -1 を指定すると先頭から 100 * include_entities true を指定すると entities を取得できる * */ tm.social.Twitter.getFollowers = function(param, callback) { tm.social.Twitter.api("statuses", "followers", param, callback); /* tm.social.Twitter.api("statuses", "public_timeline", param, callback); tm.social.Twitter.api("statuses", "home_timeline", param, callback); tm.social.Twitter.api("statuses", "friends_timeline", param, callback); tm.social.Twitter.api("statuses", "user_timeline", param, callback); tm.social.Twitter.api("statuses", "replies", param, callback); tm.social.Twitter.api("statuses", "mentions", param, callback); */ }; })(); /* * nineleap.js */ tm.social = tm.social || {}; (function() { /** * @class tm.social.NineLeap * 9leap ネームスペース */ tm.social.Nineleap = tm.social.Nineleap || {}; var BASE_URL = "http://9leap.net/games/{id}/result?score={score}&result={result}"; /** * @member tm.social.Nineleap * @method createURL * 9leap 用の URL を生成 */ tm.social.Nineleap.createURL = function(id, score, result) { return BASE_URL.format({ id : id, score : score, result : result }); }; /** * @member tm.social.Nineleap * @method postRanking * 9leap でランキングを POST */ tm.social.Nineleap.postRanking = function(score, result) { if (location.hostname == 'r.jsgames.jp') { var id = location.pathname.match(/^\/games\/(\d+)/)[1]; location.replace( this.createURL(id, score, result) ); } else { console.warn("9leap に投稿されていません!"); } }; })(); /* * chart.js */ tm.google = tm.google || {}; (function() { /** * @class tm.google.Chart * チャートネームスペース */ tm.google.Chart = tm.google.Chart || {}; var DYNAMIC_ICONS_BASE_URL = "https://chart.googleapis.com/chart?chst={type}&chld={data}"; var QR_CODE_BASE_URL = "https://chart.googleapis.com/chart?chs={size}&cht={type}&chl={text}&chco={color}"; /** * @static * ダイナミックアイコン * @param {string} type d_bubble_text_small OR d_fnote_title OR chst=d_fnote etc... * @param {string} data * ### Example * tm.google.Chart.createDynamicIcons("d_bubble_icon_text_small", "ski|bb|Hello, world!|FFFFFF|000000"); * tm.google.Chart.createDynamicIcons("d_fnote", "balloon|1|000000|l|Hello, world!"); * tm.google.Chart.createDynamicIcons("d_fnote", "pinned_c|1|000000|l|Hello, world!"); * tm.google.Chart.createDynamicIcons("d_weather", "taped_y|sunny|Barcelona|max+25°C|min+15°C"); * tm.google.Chart.createDynamicIcons("d_simple_text_icon_left", "flag_jp|14|000|flag_jp|24|000|FFF"); */ tm.google.Chart.createDynamicIcons = function(type, data) { // data = encodeURIComponent(data); return DYNAMIC_ICONS_BASE_URL.format({ type:type, data:data }); }; /** * @static * QRCode 生成 * @param {Object} prop * ### Reference * - * - * - * ### Example * tm.google.Chart.createQRCode("160x160", "http://tmlife.net"); * tm.google.Chart.createQRCode("160x160", "Hello, world"); */ tm.google.Chart.createQRCode = function(size, text, color) { text = encodeURIComponent(text); return QR_CODE_BASE_URL.format({ type:"qr", size:size, text:text, }); }; /** * @static * Tex 生成 */ tm.google.Chart.createTeX = function() { //&chco=ff0000ff }; })(); ;(function() { /** * @member tm.app.Element * @property interaction * インタラクション */ tm.app.Element.prototype.getter("interaction", function() { console.assert(false, "interaction は Object2d に統合されました. obj.setInteractive(true); とすればタッチ判定が有効になります."); }); var dirtyClass = { "display": [ "Sprite", "Shape", "CircleShape", "TriangleShape", "RectangleShape", "StarShape", "PolygonShape", "HeartShape", "TextShape", "CanvasRenderer", "BoundingRectRenderer", "Label", "MapSprite", "CanvasElement", "CanvasApp", "AnimationSprite", "SpriteSheet", ], "ui": [ "LabelButton", "IconButton", "GlossyButton", "FlatButton", "LoadingScene", ], }; for (var key in dirtyClass) { var namespace = dirtyClass[key]; namespace.each(function(className) { tm.app[className] = tm[key][className]; }); } tm.asset.AssetManager = tm.asset.Manager; })();