enterFrameアニメをそーめんで。 1
Threadで物理シミュっぽいenterFrameアニメを制御してってみる。
物理でいう「仕事」をいろんな軸毎に分けて、それぞれを別スレッドとして実行すれば、
管理も変更もやりやすいんじゃなかろうか、という予想を試す。
1では、垂直方向のみの自由落下と跳ね返りを別スレッドで動かしてみてます。
/*
Threadで物理シミュっぽいenterFrameアニメを制御してってみる。
物理でいう「仕事」をいろんな軸毎に分けて、それぞれを別スレッドとして実行すれば、
管理も変更もやりやすいんじゃなかろうか、という予想を試す。
1では、垂直方向のみの自由落下と跳ね返りを別スレッドで動かしてみてます。
*/
package {
import flash.display.Sprite;
import flash.display.Stage;
import org.libspark.thread.EnterFrameThreadExecutor;
import org.libspark.thread.Thread;
[SWF(frameRate = "48", backgroundColor = "#eeeeee")]
public class FlashTest extends Sprite {
public static var myStage:Stage;
public function FlashTest() {
// write as3 code here..
myStage = stage;
Thread.initialize(new EnterFrameThreadExecutor());
new MainThread().start();
}
};
};
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Shape;
import flash.display.Stage;
import flash.utils.getTimer;
import flash.utils.Timer;
import org.libspark.thread.Thread;
class MainThread extends Thread
{
private var _ball:Shape;
private var _stage:Stage;
private var _worldTime:WorldTime;
private var _fallThread:FallThread;
private var _throwUpThread:Thread;
private var _startTime:Number;
private var _prevY:Number;
public function MainThread()
{
_ball = new Shape();
_ball.graphics.beginFill(0xff0000);
_ball.graphics.drawCircle(0, 0, 10);
_ball.graphics.endFill();
_stage = FlashTest.myStage;
_ball.x = _stage.stageWidth * 0.5;
_ball.y = 200;
_prevY = _ball.y;
_stage.addChild(_ball);
var bmd:BitmapData = new BitmapData(_stage.stageWidth, _stage.stageHeight, true, 0x00000000);
bmd.draw(_stage);
var startPhoto:Bitmap = new Bitmap(bmd);
_stage.addChild(startPhoto);
startPhoto.alpha = 0.4
_worldTime = new WorldTime();
};
override protected function run():void
{
_fallThread = new FallThread(_ball, _worldTime);
_fallThread.start();
_startTime = getTimer();
next(_worldTick);
};
private function _worldTick():void
{
_worldTime.tick();
//地面に当たったら、一旦計算系統をリセットするために世界時間をリセット。
if ((_ball.y + _ball.height * 0.5) >= _stage.stageHeight && (_prevY + _ball.height * 0.5) < _stage.stageHeight) {
_worldTime.reset();
if (_throwUpThread) _throwUpThread.interrupt();
var hanpatsu:Number = 0.9;
var throwUp_V0:Number = (_ball.y - _prevY) * hanpatsu;
_ball.y = _stage.stageHeight - _ball.height * 0.5;
//hanpatsu(反発係数のつもり)と, _ball.y の位置補正をしてるものの、代入する値によっては上手くいかない。
if ( throwUp_V0 <= hanpatsu*0.5) {
_fallThread.interrupt();
_throwUpThread.interrupt();
_ball.y = _stage.stageHeight - _ball.height * 0.5;
next(null);
return;
};
_throwUpThread = new ThrowUpThread(_ball, throwUp_V0, _worldTime);
_throwUpThread.start();
};
_prevY = _ball.y;
next(_worldTick);
}
}
import flash.display.DisplayObject;
import org.libspark.thread.Thread;
class ThrowUpThread extends Thread
{
private var _ball:DisplayObject;
private var _worldTime:WorldTime;
public function ThrowUpThread(ball:DisplayObject, firstVelocity:Number, worldTime:WorldTime)
{
_ball = ball;
_worldTime = worldTime;
_firstVelocity = firstVelocity;
};
private var _firstVelocity:Number;
override protected function run():void
{
if (isInterrupted) {
next(null);
}else {
_ball.y = _ball.y - _firstVelocity;
next(run);
}
}
}
import flash.display.DisplayObject;
import org.libspark.thread.Thread;
class FallThread extends Thread
{
private var _ball:DisplayObject;
private var _worldTime:WorldTime;
public function FallThread(ball:DisplayObject, worldTime:WorldTime)
{
super();
_ball = ball;
_worldTime = worldTime;
};
private const g:Number = 9.80665;
override protected function run():void
{
if (isInterrupted) {
next(null);
}else {
var prevY:Number = _ball.y;
_ball.y = _ball.y + g * _worldTime.time;
next(run);
};
};
override protected function finalize():void
{
trace("finalize")
}
};
class WorldTime
{
private var _time:Number;
public function WorldTime()
{
_time = 0;
};
public function get time():Number { return _time; };
public function tick():void
{
_time += 1 / 48;
};
public function reset():void
{
_time = 0;
}
}