// DefaultMover.tjs - レイヤ自動移動のデフォルトのハンドラ // Copyright (C)2001-2003, W.Dee 改変・配布は自由です class LinearMover { // 直線補間 var layer; // レイヤ var path; // 点配列 var time; // 点を通過するのに必要な時間 var accel; // 加速度的な動きをするかどうか var pointCount; // path.count -1 var finalFunction; // 移動終了時に呼ぶ関数 var startTick; // 移動開始をしたティック var totalTime; // 全体の時間 var delayTimer; // 動作開始時まで待つためのタイマ var moving = false; // 移動中か var first = true; // 初回のハンドラ呼び出しか var nextStop = false; // 次のハンドラ呼び出しで停止するか function LinearMover(layer, path, time, accel, finalfunction) { this.layer = layer; this.path = path; this.time = time; this.accel = accel; this.finalFunction = finalfunction; totalTime = (pointCount = (path.count \ 3 - 1)) * time; } function finalize() { stopMove(); if(delayTimer !== void) invalidate delayTimer; } function startMove(delay) { // 移動を開始する if(delay != 0) { delayTimer = new Timer(onDelayTimer, ''); delayTimer.interval = delay; delayTimer.enabled = true; moving = true; } else { System.addContinuousHandler(handler); // ContinuousHandlers に追加 moving = true; } } function onDelayTimer() { // delayTimer が発動した delayTimer.enabled = false; System.addContinuousHandler(handler); } function stopMove() { // 移動を終わる if(moving) { // 最終位置に移動 if(layer isvalid) { var idx = int(pointCount*3); var p = path; layer.setPos(p[idx], p[idx+1]); layer.opacity = p[idx+2]; } System.removeContinuousHandler(handler); moving = false; finalFunction(); } } function handler(tick) { // 移動中に呼ばれる if(nextStop || !(layer isvalid)) { stopMove(); return; } if(first) startTick = tick, first = false; tick -= startTick; if(tick >= totalTime) { nextStop = true; var idx = int(pointCount*3); var p = path; layer.setPos(p[idx], p[idx+1]); layer.opacity = p[idx+2]; return; } if(accel < 0) { // 上弦 ( 最初が動きが早く、徐々に遅くなる ) tick = 1.0 - tick / totalTime; tick = Math.pow(tick, -accel); tick = int ( (1.0 - tick) * totalTime ); } else if(accel > 0) { // 下弦 ( 最初は動きが遅く、徐々に早くなる ) tick = tick / totalTime; tick = Math.pow(tick, accel); tick = int ( tick * totalTime ); } move(tick); } function move(tick) { var index = tick \ time * 3; var ratio = tick % time / time; var p = path; var sx = p[index]; var sy = p[index+1]; var so = p[index+2]; var ex = p[index+3]; var ey = p[index+4]; var eo = p[index+5]; var l = int((ex-sx)*ratio + sx); var t = int((ey-sy)*ratio + sy); var o = eo >= 256 ? so : int((eo-so)*ratio + so); layer.setPos(l, t); layer.opacity = o; } } class SplineMover extends LinearMover { // スプライン補間 var zx = []; // スプラインワーク var zy = []; // スプラインワーク function SplineMover(layer, path, time, accel, finalfunction) { super.LinearMover(...); if(path.count < 9) { // 3 点以下 ( 指定するのはそのうちの2点 ) は補完できない throw new Exception("2 点以上を指定してください"); } // スプライン補間に必要なワークを計算 var points = path.count \ 3; var tmpx = [], tmpy = []; var tx = zx, ty = zy; tx[0] = 0; ty[0] = 0; tx[points-1] = 0; ty[points-1] = 0; for(var i = points-2, pi = path.count-6; i >= 0; i--, pi -= 3) { tmpx[i+1] = (path[pi + 3] - path[pi ]); tmpy[i+1] = (path[pi + 4] - path[pi+1]); } tx[1] = tmpx[2] - tmpx[1] - tx[0]; ty[1] = tmpy[2] - tmpy[1] - ty[0]; tmpx[1] = 4; tmpy[1] = 4; var lim = points - 2; for(var i = 1, pi = 3; i < lim; i++, pi += 3) { var x = 1 / tmpx[i]; var y = 1 / tmpy[i]; tx[i+1] = tmpx[i+2] - tmpx[i+1] - path[pi ] * x; ty[i+1] = tmpy[i+2] - tmpy[i+1] - path[pi+1] * y; tmpx[i+1] = 4 - x; tmpy[i+1] = 4 - y; } tx[points-2] -= tx[points-1]; ty[points-2] -= ty[points-1]; for(var i = points-2, pi = path.count-6; i>0; i--, pi -= 3) { tx[i] = (tx[i] - tx[i+1]) / tmpx[i]; ty[i] = (ty[i] - ty[i+1]) / tmpx[i]; } } function move(tick) { var index; var pindex = (index = tick \ time) * 3; var d = tick % time / time; var p = path; var l = (((zx[index+1] - zx[index])*d + zx[index]*3)*d + ((p[pindex + 3] - p[pindex]) - (zx[index]*2 + zx[index+1]))) * d + p[pindex]; var t = (((zy[index+1] - zy[index])*d + zy[index]*3)*d + ((p[pindex + 4] - p[pindex+1]) - (zy[index]*2 + zy[index+1]))) * d + p[pindex+1]; var so = p[pindex+2]; var eo = p[pindex+5]; var o = eo >= 256 ? so : int((eo-so)*d + so); layer.setPos(l, t); layer.opacity = o; } }