forked from: Clouds and snow + MovementMeters + (todo:SE)
forked from Clouds and snow + SE (diff: 698)
Added movement up control and speedometer reading with 1st deriative. __ It was a tricky task to scroll seamless mountains. Unfortunately the volumetric lighting effect is a bit of a CPU hog, but it looks nice if your hardware can pull it off. 繋ぎ目のない山を無限スクロールさせるのにちょっと悩みました。 クリックでどうなってるのかネタバレします。 架線柱のティアリングがひどいなあ……。 import net.hires.debug.Stats;
ActionScript3 source code
/**
* Copyright Glidias ( http://wonderfl.net/user/Glidias )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/irE6
*/
// forked from yonatan's Clouds and snow
// forked from cjcat2266's Super Express Desert Sunset + Rain (Stardust ver.)
// forked from yonatan's Super Express Desert Sunset
// forked from k0rin's Super Express
// It was a tricky task to scroll seamless mountains.
// Click to see how it works.
// Unfortunately the volumetric lighting effect is
// a bit of a CPU hog, but it looks nice if your
// hardware can pull it off.
// 繋ぎ目のない山を無限スクロールさせるのにちょっと悩みました。
// クリックでどうなってるのかネタバレします。
// 架線柱のティアリングがひどいなあ……。
package {
import flash.display.*;
import flash.events.*;
import flash.geom.*;
import com.bit101.components.*;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.media.SoundLoaderContext;
import flash.media.SoundTransform;
import flash.net.URLRequest;
import flash.text.ime.CompositionAttributeRange;
import flash.ui.Keyboard;
import flash.utils.Timer;
// import net.hires.debug.Stats;
import idv.cjcat.stardust.twoD.emitters.Emitter2D;
[SWF(width = "465", height = "465", frameRate = "40")]
public class Main extends Sprite
{
public static const WIDTH:Number = 465;
public static const HEIGHT:Number = 465;
private var debug:Boolean = false;
private var sun:SunLight;
private var entities:Vector.<Entity> = new Vector.<Entity>();
private var renderedScene:BitmapData = new BitmapData(WIDTH, HEIGHT);
private var scene:Sprite = new Sprite;
private var emitter:RainEmitter;
private var soundRun:Sound;
private var soundSL:Sound;
private var soundRunChannel:SoundChannel;
public static const CLOUD_NUM:int = 50;
public static const ERROR_SEEDS:Array = [346, 514, 1155, 1519, 1690, 1977, 2327, 2337, 2399, 2860, 2999, 3099, 4777, 4952, 5673, 6265, 7185, 7259, 7371, 7383, 7717, 7847, 8032, 8350, 8676, 8963, 8997, 9080, 9403, 9615, 9685];
public var loading:LoadingScene;
private var labelCurSpeed:Label;
private var labelMaxSpeed:Label;
/**perlinNoiseに使うとまずいシード値(画像に穴があくかもしれない)*/
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
loading = new LoadingScene();
addChild(loading);
addEventListener(Event.ENTER_FRAME, onLoading);
}
// cloud constants
public static const FOCUS:Number = 500;
public static const MAX_Z:Number = 4000;
public static const MIN_Z:Number = 250;
private function onLoading(...arg):void {
for (var i:int = 0; i < 3; i++) {
if(Clouds.bmps.length >= CLOUD_NUM){
start();
break;
}
var seed:int = Math.random() * 10000 + 1;
if (ERROR_SEEDS.indexOf(seed) >= 0) seed++;
var ct:Number = (Math.random() < 0.2)? Math.random() * 0.3 : Math.random() * 1.5;
var z:Number = MAX_Z - (MAX_Z-MIN_Z)/CLOUD_NUM*(Clouds.bmps.length);
var w:Number = 400/(z/FOCUS);
var h:Number = 200/(z/FOCUS);
var bmp:Bitmap = new Bitmap(Painter.createCloud(w, h, seed, ct, Color.cloudBase, Color.cloudLight, Color.cloudShadow));
bmp.x = Math.random() * (Main.WIDTH + bmp.width) - bmp.width;
bmp.y = HEIGHT*0.6 - HEIGHT*0.5 * FOCUS/z;
Clouds.bmps.push(bmp);
loading.setProgress(Clouds.bmps.length / CLOUD_NUM);
}
}
public function start():void
{
removeEventListener(Event.ENTER_FRAME, onLoading);
removeChild(loading);
stage.quality = StageQuality.MEDIUM;
// 空を描画
var matrix:Matrix = new Matrix();
matrix.createGradientBox(WIDTH, HEIGHT, Math.PI / 2);
graphics.beginGradientFill(GradientType.LINEAR, [0x51484A, 0x96644E], null, [0, 128], matrix);
graphics.drawRect(0, 0, WIDTH, HEIGHT);
graphics.endFill();
var clouds:Clouds = new Clouds;
entities.push(scene.addChild(clouds));
var fogR:Number = 0x40;
var fogG:Number = 0x35;
var fogB:Number = 0x2c;
var mountainR:Number = 0x17;
var mountainG:Number = 0x13;
var mountainB:Number = 0x15;
const NUMBER_OF_MOUNTAINS:int = 4;
for (var i:int = 0; i < NUMBER_OF_MOUNTAINS; i++) {
var blend:Number = i / (NUMBER_OF_MOUNTAINS - 1);
var _r:Number = lerp(fogR, mountainR, blend);
var _g:Number = lerp(fogG, mountainG, blend);
var _b:Number = lerp(fogB, mountainB, blend);
var baseHeight:Number = HEIGHT * 0.55 + i * 25;
var color:uint = (_r << 16) | (_g << 8) | _b;
var mountain:Mountain = new Mountain(-Math.pow(i + 1, 2), baseHeight, color);
entities.push(scene.addChild(mountain));
}
entities.push(scene.addChild(new PoleAndWire()));
entities.push(scene.addChild(new Tunnel()));
//insert emitter
emitter = new RainEmitter(scene);
addChild(scene);
addChild(sun = new SunLight(renderedScene));
var outline:Shape = new Shape();
var g:Graphics = outline.graphics;
g.lineStyle(1, 0x808080);
g.drawRect( -1, -1, WIDTH + 2, HEIGHT + 2);
addChild(outline);
restoreFilters(debug);
// playSound();
//stage.addEventListener(MouseEvent.CLICK, clickHandler);
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
// addChild(new Stats);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
new PushButton(this, 5, 5, "Move on..", pumpGasHandler);
var hBox:VBox = new VBox(this, 120, 10);
uiOptions = hBox;
var lbl:Label;
lbl = new Label(hBox, 0, 0, "MaxSpeed"); lbl.blendMode = "invert";
var hSlider:HSlider;
hSlider = new HSlider(hBox, 0, 0, onMaxSpeedChange);
hSlider.minimum = 1;
hSlider.maximum = 5;
hSlider.width = 15 * 5;
hSlider.value = model.getMaxSpeed();
lbl = new Label(hBox, 0,0, "AccelTimeSpan"); lbl.blendMode = "invert";
_accelTimeSpanner = hSlider = new HSlider(hBox, 0, 0, onAccelTimeSpanChange);
hSlider.minimum = 1;
hSlider.maximum = 5;
hSlider.width = 15 * 5;
hSlider.value = 1;
lbl = new Label(hBox, 0,0, "BrakeTimeSpan"); lbl.blendMode = "invert";
_accelTimeSpanner2 = hSlider = new HSlider(hBox, 0, 0, onAccelTimeSpanChange);
hSlider.minimum = 1;
hSlider.maximum = 5;
hSlider.width = 15 * 5;
hSlider.value = 1;
lbl = new Label(hBox, 0, 0, "Ease");
var cb:ComboBox = new ComboBox(hBox, 0, 0, "", ["Linear", "Quadratic", "Cubic", "Quartic", "Quintic"]);
cb.addEventListener(Event.SELECT, onComboEaseSelect);
model.setupEasingFunctions( cb.selectedIndex=2 );
model.setPickupTimespans(1, 1);
var disp:VBox = new VBox(this, 5, 20);
labelCurSpeed = new Label(disp);
new Label(disp, 0, 0, "/");
labelMaxSpeed = new Label(disp);
}
private var _accelTimeSpanner:HSlider;
private var _accelTimeSpanner2:HSlider;
private function onMaxSpeedChange(e:Event):void {
var hSlider:HSlider = e.target as HSlider;
model.setMaxSpeed( hSlider.value);
}
private function onAccelTimeSpanChange(e:Event):void {
model.setPickupTimespans(_accelTimeSpanner.value, _accelTimeSpanner2.value);
}
private function onComboEaseSelect(e:Event):void {
var targ:ComboBox = e.target as ComboBox;
model.setupEasingFunctions( targ.selectedIndex );
}
private function pumpGasHandler(e:Event=null):void {
model.travelTo( int(model.targetDest + 1 ) );
}
private function onKeyDown(e:KeyboardEvent):void
{
if (e.keyCode == Keyboard.G) {
model.travelTo( int(model.targetDest + 1 ) );
}
}
private function clickHandler(e:MouseEvent):void
{
debug = !debug;
var matrix:Matrix = new Matrix();
if (debug) {
// transformで表示領域外を確認。お手軽でいいと思う。
matrix.scale(0.2, 0.2);
matrix.translate(WIDTH * 0.4, HEIGHT * 0.4);
}
transform.matrix = matrix;
restoreFilters(debug);
}
private function restoreFilters(debug:Boolean):void
{
for each (var entity:Entity in entities)
{
entity.restoreFilter(debug);
}
}
private var model:SceneModel = new SceneModel();
private var _needToRender:Boolean = false;
private var _curLoc:Number = 0;
private var unitTimeLength:Number = GameSettings.SHARED_FPS;
private var uiOptions:Sprite;
private function enterFrameHandler(e:Event):void
{
model.update();
if (model.movingState != BGTrainState.STOPPED) {
uiOptions.mouseChildren = false;
uiOptions.visible = false;
}
else {
uiOptions.mouseChildren = true;
uiOptions.visible = true;
}
// if (_needToRender || model.movingState != BGTrainState.STOPPED) { // perform necessary render updates
_needToRender = model.movingState != BGTrainState.STOPPED;
var tarLoc:Number = model.currentPosition;
var diff:Number = (tarLoc - _curLoc)*unitTimeLength;
for each (var entity:Entity in entities)
{
entity.update(diff);
}
renderedScene.fillRect(renderedScene.rect, 0);
renderedScene.draw(scene);
sun.update(diff);
/*
if (soundRunChannel && soundRunChannel.position >= 14025)
{
soundRunChannel.stop();
soundRunChannel = soundRun.play(3169);
trace(soundRunChannel.position);
}
*/
labelCurSpeed.text = "" + model.getCurrentVelocity();
labelMaxSpeed.text = "" + model.getMaxSpeed();
emitter.steppedBasedOnSpeeds(model.getCurrentVelocity(), model.getMaxSpeed() );
sun.update(diff);
_curLoc = tarLoc;
// else {
// _needToRender = false;
// sun.update(0);
// emitter.step();
// }
}
private function playSound():void
{
var context:SoundLoaderContext = new SoundLoaderContext(1000, true);
soundRun = new Sound(new URLRequest("http://paq.s346.xrea.com/wonderfl/sound/sl_run.mp3"), context);
soundSL = new Sound(new URLRequest("http://paq.s346.xrea.com/wonderfl/sound/sl.mp3"), context);
soundRun.addEventListener(Event.COMPLETE, function():void {
soundRun.removeEventListener(Event.COMPLETE, arguments.callee);
soundRunChannel = soundRun.play(0);
});
soundSL.addEventListener(Event.COMPLETE, function():void {
soundSL.removeEventListener(Event.COMPLETE, arguments.callee);
var timer:Timer = new Timer(3000);
timer.addEventListener(TimerEvent.TIMER, function():void {
timer.removeEventListener(TimerEvent.TIMER, arguments.callee);
timer = null;
soundSL.play();
});
timer.start();
});
}
}
}
import flash.display.*;
import flash.filters.*;
import flash.geom.*;
import idv.cjcat.stardust.common.actions.Die;
import idv.cjcat.stardust.common.actions.triggers.ActionTrigger;
import idv.cjcat.stardust.common.clocks.SteadyClock;
import idv.cjcat.stardust.common.initializers.Scale;
import idv.cjcat.stardust.common.math.UniformRandom;
import idv.cjcat.stardust.twoD.actions.Gravity;
import idv.cjcat.stardust.twoD.actions.Move;
import idv.cjcat.stardust.twoD.actions.Oriented;
import idv.cjcat.stardust.twoD.actions.RandomDrift;
import idv.cjcat.stardust.twoD.actions.triggers.ZoneTrigger;
import idv.cjcat.stardust.twoD.emitters.Emitter2D;
import idv.cjcat.stardust.twoD.fields.UniformField;
import idv.cjcat.stardust.twoD.handlers.DisplayObjectHandler;
import idv.cjcat.stardust.twoD.initializers.DisplayObjectClass;
import idv.cjcat.stardust.twoD.initializers.Position;
import idv.cjcat.stardust.twoD.initializers.Velocity;
import idv.cjcat.stardust.twoD.zones.LazySectorZone;
import idv.cjcat.stardust.twoD.zones.RectZone;
import idv.cjcat.stardust.twoD.zones.Zone;
class Rain extends Shape {
public function Rain() {
graphics.beginFill(0x303030);
graphics.drawRect( -1, -15, 2, 30);
blendMode = BlendMode.ADD;
filters = [new BlurFilter(20, 0)];
}
}
class RainEmitter extends Emitter2D {
public var uniField:UniformField;
public function RainEmitter(container:DisplayObjectContainer) {
super(new SteadyClock(2));
//initializers
addInitializer(new DisplayObjectClass(Rain));
addInitializer(new Position(new RectZone(500, -50, 1, 500)));
addInitializer(new Scale(new UniformRandom(1, 0.7)));
var lazyRectZone:LazySectorZone = new LazySectorZone();
lazyRectZone.direction.set(-1, 0);
lazyRectZone.directionVar = 20;
lazyRectZone.radius = 25;
lazyRectZone.radiusVar = 15;
addInitializer(new Velocity(lazyRectZone));
//actions
addAction(new Move());
addAction(new Oriented());
addAction(new RandomDrift(4, 4));
//gravity
var gravity:Gravity = new Gravity();
gravity.addField(uniField = new UniformField(0, 1));
addAction(gravity);
//death zone
var deathZone:Zone = new RectZone( -50, -50, 600, 600);
var zoneTrigger:ActionTrigger = new ZoneTrigger(deathZone);
zoneTrigger.inverted = true;
zoneTrigger.addAction(new Die());
addAction(zoneTrigger);
//particle handler
particleHandler = new DisplayObjectHandler(container);
}
public function steppedBasedOnSpeeds(speed:Number, maxSpeed:Number):void {
uniField.x = -speed;
step();
}
}
class Entity extends Sprite
{
public function update(dt:Number):void { };
public function restoreFilter(debug:Boolean):void { };
}
class SunLight extends Entity {
public static const FXW:int = 0x100;
public static const FXH:int = 0x100;
private var src:BitmapData = new BitmapData(FXW, FXH, true, 0);
private var dst:BitmapData = new BitmapData(FXW, FXH, true, 0);
private var sun:Shape = new Shape;
private var obstruction:Bitmap;
private var scaleDown:Matrix = new Matrix;
private var scaleUp:Matrix = new Matrix;
private var mtx:Matrix = new Matrix;
private var canvas:Bitmap = new Bitmap(dst);
private var blur:BlurFilter = new BlurFilter(5, 5, 1);
public function SunLight(obstruction:BitmapData) {
this.blendMode = "add";
this.obstruction = new Bitmap(obstruction);
var m:Matrix = new Matrix;
m.createGradientBox(FXW, FXH, 0, 0, 0);
sun.graphics.beginGradientFill("radial", [0x0C0a08, 0x0a0806, 0x060504, 0x020201, 0], [1, 1, 1, 1, 1], [0, 10, 34, 64, 255], m);
sun.graphics.drawRect(0, 0, FXW, FXH);
sun.graphics.endFill();
sun.cacheAsBitmap = true;
scaleDown.scale(FXW/Main.WIDTH, FXH/Main.HEIGHT);
scaleUp.scale(Main.WIDTH/FXW, Main.HEIGHT/FXH);
addChild(canvas);
transform.matrix = scaleUp;
}
public override function update(dt:Number):void {
src.lock();
dst.lock();
src.fillRect(src.rect, 0);
src.draw(sun);
src.draw(obstruction, scaleDown, null, "erase");
canvas.bitmapData = process(src);
src.unlock();
dst.unlock();
}
private function process(src:BitmapData):BitmapData {
var dst:BitmapData = this.dst;
mtx.identity();
mtx.translate(-FXW/34, -FXH/34);
mtx.scale(17/16, 17/16);
var cnt:int = 5;
var tmp:BitmapData;
while(cnt--) {
mtx.concat(mtx);
dst.copyPixels(src, src.rect, src.rect.topLeft);
dst.draw(src, mtx, null, "add");
dst.applyFilter(dst, dst.rect, dst.rect.topLeft, blur);
tmp = src;
src = dst;
dst = tmp;
}
return src;
}
}
class Mountain extends Entity
{
private var heightMap:Vector.<Number> = new Vector.<Number>();
private const SEGMENT_LENGTH:Number = 10;
private var baseHeight:Number;
private var color:uint;
private var speed:Number;
function Mountain(speed:Number, baseHeight:Number, color:uint)
{
this.baseHeight = baseHeight;
this.color = color;
this.speed = speed;
generateHeightMap();
createShape();
}
public override function update(dt:Number):void
{
x += speed*dt;
if (x < -(width - Main.WIDTH)) {
var removeSegmentNumber:int = (width - Main.WIDTH) / SEGMENT_LENGTH;
heightMap.splice(0, removeSegmentNumber);
x += removeSegmentNumber * SEGMENT_LENGTH;
generateHeightMap();
createShape();
}
}
private function generateHeightMap():void
{
// 再帰で分割していく
divide(baseHeight, baseHeight, 0, 200);
function divide(left:Number, right:Number, depth:int, offset:Number):void
{
if (depth < 6) {
var half:Number = (left + right) / 2 + rnd( -offset / 2, offset / 2);
divide(left, half, depth + 1, offset / 2);
divide(half, right, depth + 1, offset / 2);
} else {
// 十分に分割したら順番に書き出し
heightMap.push(left);
}
}
}
private function createShape():void
{
var g:Graphics = graphics;
g.clear();
g.beginFill(color);
g.moveTo(0, Main.HEIGHT);
for (var i:int = 0; i < heightMap.length; i++) {
g.lineTo(i * SEGMENT_LENGTH, heightMap[i]);
}
g.lineTo((i - 1) * SEGMENT_LENGTH, Main.HEIGHT);
g.endFill();
// デバッグ表示
g.lineStyle(1, color);
g.moveTo(0, heightMap[0]);
g.lineTo(0, Main.HEIGHT * 2);
}
}
class Clouds extends Entity {
public static var bmps:Array = [];
public function Clouds() {
for each(var bmp:Bitmap in bmps) addChild(bmp);
}
public override function update(dt:Number):void {
for each(var bmp:Bitmap in bmps) {
bmp.x -= bmp.width * 0.001*dt;
if(bmp.x + bmp.width < 0) {
bmp.x = Main.WIDTH;
}
}
}
}
const SPEED:Number = 80;
class PoleAndWire extends Entity
{
private const SPACING:Number = Main.WIDTH * 5;
private const POLE_THICK:Number = 40;
private const WIRE_TOP:Number = 20;
private const WIRE_BOTTOM:Number = 100;
function PoleAndWire()
{
var g:Graphics = graphics;
g.beginFill(0x332222);
g.drawRect(-POLE_THICK / 2, 0, POLE_THICK, Main.HEIGHT);
g.endFill();
g.lineStyle(1, 0x221111);
g.moveTo(POLE_THICK / 2, WIRE_TOP);
g.curveTo(SPACING / 2, WIRE_BOTTOM, SPACING - POLE_THICK, WIRE_TOP);
g.moveTo(-POLE_THICK / 2, WIRE_TOP);
g.curveTo(-SPACING / 2, WIRE_BOTTOM, -SPACING + POLE_THICK, WIRE_TOP);
x = (SPACING + Main.WIDTH) / 2;
}
public override function update(dt:Number):void
{
x -= SPEED*dt;
if (x < (-SPACING + Main.WIDTH) / 2) {
x += SPACING;
}
}
public override function restoreFilter(debug:Boolean):void
{
filters = debug ? null : [ new BlurFilter(80, 0, 1) ];
}
}
class Tunnel extends Entity
{
// |ENTRANCE|SPACE|LIGHT|SPACE|ENTRANCE|
// ^ origin
private const LIGHT:Number = 100;
private const SPACE:Number = Main.WIDTH * 1.4;
private const ENTRANCE:Number = Main.WIDTH * 1.5;
private const WIDTH:Number = LIGHT + SPACE * 2 + ENTRANCE * 2;
private const ENTRANCE_COLOR:uint = 0x896857 >>> 1 & 0x7f7f7f;
private const DARKNESS_COLOR:uint = 0x0A0908;
private const LIGHT_COLOR:uint = 0xFFF0E0;
private var lightCount:int;
private var light:Shape;
function Tunnel()
{
var g:Graphics = graphics;
var matrix:Matrix = new Matrix();
matrix.createGradientBox(ENTRANCE, Main.HEIGHT);
g.beginGradientFill(GradientType.LINEAR, [ENTRANCE_COLOR, DARKNESS_COLOR], null, [0, 255], matrix);
g.drawRect(0, 0, ENTRANCE, Main.HEIGHT);
matrix.createGradientBox(ENTRANCE, Main.HEIGHT, 0, WIDTH - ENTRANCE, 0);
g.beginGradientFill(GradientType.LINEAR, [DARKNESS_COLOR, ENTRANCE_COLOR], null, [0, 255], matrix);
g.drawRect(WIDTH - ENTRANCE, 0, ENTRANCE, Main.HEIGHT);
g.endFill();
g.beginFill(DARKNESS_COLOR);
g.drawRect(ENTRANCE, 0, LIGHT + SPACE * 2, Main.HEIGHT);
g.endFill();
light = new Shape();
light.graphics.beginFill(LIGHT_COLOR);
light.graphics.drawRect(WIDTH / 2, Main.HEIGHT * 0.55, LIGHT, 20);
light.graphics.endFill();
addChild(light);
prepareNextTunnel();
// 最初のトンネルまでは定距離にする。 - distance to 1st tunnel
x = SPEED * 1800;
}
public override function update(dt:Number):void
{
x -= SPEED*dt;
if (x < -(WIDTH - ENTRANCE - Main.WIDTH)) {
if (--lightCount >= 0) {
// ライトをループ
x += SPACE * 2 + LIGHT - Main.WIDTH;
trace(length);
}
}
if (x < -WIDTH * 2) {
prepareNextTunnel();
}
}
public override function restoreFilter(debug:Boolean):void
{
filters = debug ? null : [ new BlurFilter(80, 0, 1) ];
light.filters = debug ? null : [ new GlowFilter(0xFF8000, 1, 50, 50, 3, 4) ];
}
private function prepareNextTunnel():void
{
x = SPEED * rnd(1300, 4000);
lightCount = rnd(6, 50);
}
}
// 線形補間
function lerp(n0:Number, n1:Number, p:Number):Number
{
return n0 * (1 - p) + n1 * p;
}
// [min, max)の乱数を取得
function rnd(min:Number, max:Number):Number
{
return min + Math.random() * (max - min);
// return lerp(min, max, Math.random());
}
// copy-pasta from tencho's Sea of Clouds...
class Color {
/**雲の色*/
static public var cloudBase:uint = 0x725040;
/**雲のハイライト色*/
static public var cloudLight:uint = 0xFDDFC9;
/**雲の影の色*/
static public var cloudShadow:uint = 0x38231E;
}
class LoadingScene extends Sprite {
private var _lineWidth:Number = 200;
private var _loadedLine:Sprite;
public function LoadingScene() {
var bg:Sprite = addChild(Painter.createGradientRect(Main.WIDTH, Main.HEIGHT, [0x000000], [1])) as Sprite;
var baseLine:Sprite = addChild(Painter.createGradientRect(_lineWidth, 2, [0x444444], [1])) as Sprite;
_loadedLine = addChild(Painter.createGradientRect(_lineWidth, 2, [0x7DA3C8], [1])) as Sprite;
baseLine.x = _loadedLine.x = int((Main.WIDTH - _lineWidth) / 2);
baseLine.y = _loadedLine.y = int((Main.HEIGHT - baseLine.height) / 2);
setProgress(0);
}
public function setProgress(per:Number):void {
_loadedLine.width = _lineWidth * per;
}
}
class Painter {
/**
* 雲画像生成
* @param width 幅
* @param height 高さ
* @param seed ランダムシード値
* @param contrast コントラスト0~
* @param color ベースの色
* @param light 明るい色
* @param shadow 暗い色
*/
static public function createCloud(width:int, height:int, seed:int, contrast:Number = 1, color:uint = 0xFFFFFF, light:uint = 0xFFFFFF, shadow:uint = 0xDDDDDD):BitmapData {
var gradiation:Sprite = new Sprite();
var drawMatrix:Matrix = new Matrix();
drawMatrix.createGradientBox(width, height);
gradiation.graphics.beginGradientFill("radial", [0x000000, 0x000000], [0, 1], [0, 255], drawMatrix);
gradiation.graphics.drawRect(0, 0, width, height);
gradiation.graphics.endFill();
var alphaBmp:BitmapData = new BitmapData(width, height);
alphaBmp.perlinNoise(width / 3, height / 2.5, 5, seed, false, true, 1|2|4, true);
var zoom:Number = 1 + (contrast - 0.1) / (contrast + 0.9);
if (contrast < 0.1) zoom = 1;
if (contrast > 2.0) zoom = 2;
var ctMatrix:Array = [contrast + 1, 0, 0, 0, -128 * contrast, 0, contrast + 1, 0, 0, -128 * contrast, 0, 0, contrast + 1, 0, -128 * contrast, 0, 0, 0, 1, 0];
alphaBmp.draw(gradiation, new Matrix(zoom, 0, 0, zoom, -(zoom - 1) / 2 * width, -(zoom - 1) / 2 * height));
alphaBmp.applyFilter(alphaBmp, alphaBmp.rect, new Point(), new ColorMatrixFilter(ctMatrix));
var image:BitmapData = new BitmapData(width, height, true, 0xFF << 24 | color);
image.copyChannel(alphaBmp, alphaBmp.rect, new Point(), 4, 8);
image.applyFilter(image, image.rect, new Point(), new GlowFilter(light, 1, 4, 4, 1, 3, true));
var bevelSize:Number = Math.min(width, height) / 30;
image.applyFilter(image, image.rect, new Point(), new BevelFilter(bevelSize, 45, light, 1, shadow, 1, bevelSize/5, bevelSize/5, 1, 3));
var image2:BitmapData = new BitmapData(width, height, true, 0);
image2.draw(Painter.createGradientRect(width, height, [light, color, shadow], [1, 0.2, 1], null, 90), null, null, BlendMode.MULTIPLY);
image2.copyChannel(alphaBmp, alphaBmp.rect, new Point(), 4, 8);
image.draw(image2, null, null, BlendMode.MULTIPLY);
alphaBmp.dispose();
return image;
}
/**
* グラデーションスプライト生成
*/
static public function createGradientRect(width:Number, height:Number, colors:Array, alphas:Array, ratios:Array = null, rotation:Number = 0):Sprite {
var i:int, rts:Array = new Array();
if(ratios == null) for (i = 0; i < colors.length; i++) rts.push(int(255 * i / (colors.length - 1)));
else for (i = 0; i < ratios.length; i++) rts[i] = Math.round(ratios[i] * 255);
var sp:Sprite = new Sprite();
var mtx:Matrix = new Matrix();
mtx.createGradientBox(width, height, Math.PI / 180 * rotation, 0, 0);
if (colors.length == 1 && alphas.length == 1) sp.graphics.beginFill(colors[0], alphas[0]);
else sp.graphics.beginGradientFill("linear", colors, alphas, rts, mtx);
sp.graphics.drawRect(0, 0, width, height);
sp.graphics.endFill();
return sp;
}
}
import flash.utils.getTimer;
class Std {
static public function _is(v : *,t : *) : Boolean {
try {
if(t == Object) return true;
return v is t;
}
catch( e : * ){
};
return false;
}
static public function instance(value : *,c : Class) : * {
return value as c;
}
static public function string(s : *) : String {
return ""+s;
}
static public function _int(x : Number) : int {
return int(x);
}
static public function _parseInt(x : String) : * {
var v : * = parseInt(x);
if(isNaN(v)) return null;
return v;
}
static public function _parseFloat(x : String) : Number {
return parseFloat(x);
}
static public function random(x : int) : int {
if(x <= 0) return 0;
else return Math.floor(Math.random() * x);
return 0;
}
}
class enum {
public var tag : String;
public var index : int;
public var params : Array;
public function toString() : String { return enum_to_string(this); }
static protected var IN_E : int = 0;
static public function enum_to_string(e : *) : String {
if(e.params == null) return e.tag;
var pstr : Array = [];
if(IN_E > 15) pstr.push("...");
else {
IN_E++;
{
var _g : int = 0;
var _g1 : Array = e.params;
while(_g < _g1.length) {
var p : * = _g1[_g];
++_g;
pstr.push(""+p);
}
};
IN_E--;
};
return e.tag + "(" + pstr.join(",") + ")";
}
}
final class BGTrainState extends enum {
public static const __isenum : Boolean = true;
public function BGTrainState( t : String, index : int, p : Array = null ) : void { this.tag = t; this.index = index; this.params = p; }
public static function ACCEL(wontSpeed : Boolean) : BGTrainState { return new BGTrainState("ACCEL",1,[wontSpeed]); }
public static function BRAKING(wontSpeed : Boolean) : BGTrainState { return new BGTrainState("BRAKING",3,[wontSpeed]); }
public static var SPEEDING : BGTrainState = new BGTrainState("SPEEDING",2);
public static var STOPPED : BGTrainState = new BGTrainState("STOPPED",0);
public static var __constructs__ : Array = ["STOPPED","ACCEL","SPEEDING","BRAKING"];
}
interface IBGTrain {
function get_currentPosition() : Number ;
function get_targetDest() : Number ;
function resetTo(index : int) : void ;
function travelTo(index : int) : void ;
function stopAt(index : int) : void ;
function missStopAt(index : int) : void ;
function setMaxSpeed(maxSpeed : Number) : void ;
function setPickupTimespans(accelSpan : Number,brakeSpan : Number) : void ;
function setupEasingFunctions(powerIndex : int) : void ;
function update() : void ;
function setCruisingSpeed(speed : Number) : void ;
function getCurrentVelocity():Number;
function getMaxSpeed():Number;
}
class SceneModel implements IBGTrain{
public function SceneModel() : void {
this.calcPickupTime();
this.setPickupTimespans(3,3);
}
public function getCurrentVelocity():Number {
return _curVelocity;
}
protected var _curLoc : Number = 0;
protected var _targetDest : Number = 0;
public function get targetDest() : Number { return get_targetDest(); }
public function set targetDest( __v : Number ) : void { $targetDest = __v; }
protected var $targetDest : Number;
public function get_targetDest() : Number {
return this._targetDest;
}
public function getMaxSpeed():Number {
return _maxSpeed;
}
protected var _reseting : Boolean = true;
protected var _cruisingSpeed : Number = 1;
protected var _maxSpeed : Number = 3;
protected var _isStarted : Boolean = false;
protected var _startIndex : Number = -1;
protected var _tweenProgress : Number = 0;
protected var _tweenDuration : Number = 0;
protected var _pickupTime : Number;
protected var _pickupTimeDiff : Number;
protected var _pickupTimeDistCovered : Number;
protected function calcPickupTime() : void {
this._pickupTime = (this.easeFuncs.deriativeGetX)(this._maxSpeed);
this._pickupTimeDistCovered = (this.easeFuncs.distCovered)(this._pickupTime);
this._pickupTimeDiff = this._pickupTime - this._pickupTimeDistCovered / this._maxSpeed;
}
public var easeFuncs : EaseFunctions = EaseFunctions.create(2);
public function setupEasingFunctions(powerIndex : int) : void {
this.easeFuncs = EaseFunctions.create(powerIndex);
this.calcPickupTime();
}
protected var pickupTimeSpan : Number = 1;
protected var pickdownTimeSpan : Number = 1;
protected var pickupAndDownMidpointRatio : Number = .5;
public function setPickupTimespans(accelSpan : Number,brakeSpan : Number) : void {
this.pickupTimeSpan = accelSpan;
this.pickdownTimeSpan = brakeSpan;
this.pickupAndDownMidpointRatio = this.pickupTimeSpan / (this.pickupTimeSpan + this.pickdownTimeSpan);
}
protected function get pickupUnitTimeLength() : Number { return get_pickupUnitTimeLength(); }
protected function set pickupUnitTimeLength( __v : Number ) : void { $pickupUnitTimeLength = __v; }
protected var $pickupUnitTimeLength : Number;
public function get_pickupUnitTimeLength() : Number {
return this.pickupTimeSpan * 60;
}
protected function get pickdownUnitTimeLength() : Number { return get_pickdownUnitTimeLength(); }
protected function set pickdownUnitTimeLength( __v : Number ) : void { $pickdownUnitTimeLength = __v; }
protected var $pickdownUnitTimeLength : Number;
public function get_pickdownUnitTimeLength() : Number {
return this.pickdownTimeSpan * 60;
}
protected function get pickupTimeDur() : Number { return get_pickupTimeDur(); }
protected function set pickupTimeDur( __v : Number ) : void { $pickupTimeDur = __v; }
protected var $pickupTimeDur : Number;
public function get_pickupTimeDur() : Number {
return this._pickupTime * 60 * this.pickupTimeSpan;
}
protected function get pickdownTimeDur() : Number { return get_pickdownTimeDur(); }
protected function set pickdownTimeDur( __v : Number ) : void { $pickdownTimeDur = __v; }
protected var $pickdownTimeDur : Number;
public function get_pickdownTimeDur() : Number {
return this._pickupTime * 60 * this.pickdownTimeSpan;
}
protected function get totalPickupAndDownTimeDur() : Number { return get_totalPickupAndDownTimeDur(); }
protected function set totalPickupAndDownTimeDur( __v : Number ) : void { $totalPickupAndDownTimeDur = __v; }
protected var $totalPickupAndDownTimeDur : Number;
public function get_totalPickupAndDownTimeDur() : Number {
return this.get_pickupTimeDur() + this.get_pickdownTimeDur();
}
public function isBlendAccelBrake() : Boolean {
return this._pickupTimeDistCovered * this.pickupTimeSpan + this._pickupTimeDistCovered * this.pickdownTimeSpan >= this._targetDest - this._startIndex;
}
public function isBlendAccelBrake2() : Boolean {
return this.get_totalPickupAndDownTimeDur() >= this._tweenDuration;
}
public function resetTo(index : int) : void {
this._reseting = true;
this._targetDest = index;
}
protected var _forceStop : Boolean = false;
protected var _curVelocity:Number;
public function get currentPosition() : Number { return get_currentPosition(); }
public function set currentPosition( __v : Number ) : void { $currentPosition = __v; }
protected var $currentPosition : Number;
public function get_currentPosition() : Number {
return this._curLoc;
}
protected var _startTime : Number = -1;
public function travelTo(index : int) : void {
if(!this._isStarted) {
this._targetDest = index;
this._isStarted = true;
var tarIndex : Number = Std._int(this._curLoc);
this._startTime = getTimer() / 1000;
this._startIndex = tarIndex;
this._tweenProgress = 0;
this._tweenDuration = (index - this._startIndex) * 60 / this._maxSpeed + this._pickupTimeDiff * this.pickupTimeSpan * 60 + this._pickupTimeDiff * this.pickdownTimeSpan * 60;
}
else {
if(this._braking) {
var tarLoc : Number = this._tweenProgress - this._tweenDuration + this.get_pickdownUnitTimeLength();
var xRatio : Number = tarLoc /= this.get_pickdownUnitTimeLength();
tarLoc = (this.easeFuncs.distCovered_Out)(tarLoc);
tarLoc *= this.pickdownTimeSpan;
tarLoc += this._targetDest - this.pickdownTimeSpan;
this._curLoc = tarLoc;
xRatio = 1 - xRatio;
var tarIndex1 : Number = tarLoc -= (this.easeFuncs.distCovered)(xRatio) * this.pickupTimeSpan;
this._startIndex = tarLoc;
this._tweenProgress = xRatio * this.get_pickupUnitTimeLength();
this._startTime = getTimer()/1000 - this._tweenProgress / 60;
this._targetDest = index;
}
else {
this._targetDest = index;
};
this._tweenDuration = (index - this._startIndex) * 60 / this._maxSpeed + this._pickupTimeDiff * this.pickupTimeSpan * 60 + this._pickupTimeDiff * this.pickdownTimeSpan * 60;
};
if(this.isBlendAccelBrake()) {
var y : Number = this._targetDest - this._startIndex;
this._tweenDuration = (this.easeFuncs.distCoveredGetX)(y / this.pickupTimeSpan * this.pickupAndDownMidpointRatio) * 60 * this.pickupTimeSpan + (this.easeFuncs.distCoveredGetX)(y / this.pickdownTimeSpan * (1 - this.pickupAndDownMidpointRatio)) * 60 * this.pickdownTimeSpan;
}
}
public function stopAt(index : int) : void {
this._targetDest = index;
}
public function missStopAt(index : int) : void {
if(this._curLoc <= index + .75) this._targetDest = index + .75;
else this._targetDest = index;
}
public function setMaxSpeed(maxSpeed : Number) : void {
this._maxSpeed = maxSpeed;
this.calcPickupTime();
}
public function setCruisingSpeed(speed : Number) : void {
this._cruisingSpeed = speed;
}
public var movingState : BGTrainState = BGTrainState.STOPPED;
protected var _braking : Boolean = true;
public function update() : void {
if(this._isStarted) {
this._tweenProgress = (getTimer()/1000 - this._startTime) * 60;
if(this._tweenProgress > this._tweenDuration) this._tweenProgress = this._tweenDuration;
this._braking = false;
var tarLoc : Number = 0;
var exceed : Boolean = this.isBlendAccelBrake();
var exceed2 : Boolean = this.isBlendAccelBrake2();
var exceedBreaking : Boolean = false;
if(exceed) exceedBreaking = this._tweenProgress >= this._tweenDuration * this.pickupAndDownMidpointRatio;
if(exceed && !exceedBreaking || !exceed && this._tweenProgress < this.get_pickupTimeDur()) {
tarLoc = this._tweenProgress / this.get_pickupUnitTimeLength();
_curVelocity = this.easeFuncs.deriative(tarLoc);
tarLoc = (this.easeFuncs.distCovered)(tarLoc);
tarLoc *= this.pickupTimeSpan;
tarLoc += this._startIndex;
this.movingState = BGTrainState.ACCEL(exceed);
}
else if(exceed && exceedBreaking || !exceed && this._tweenProgress >= this._tweenDuration - this.get_pickdownTimeDur()) {
this._braking = true;
tarLoc = this._tweenProgress - this._tweenDuration + this.get_pickdownUnitTimeLength();
tarLoc /= this.get_pickdownUnitTimeLength();
_curVelocity = easeFuncs.deriative_Out(tarLoc);
tarLoc = (this.easeFuncs.distCovered_Out)(tarLoc);
tarLoc *= this.pickdownTimeSpan;
tarLoc += this._targetDest - this.pickdownTimeSpan;
this.movingState = BGTrainState.BRAKING(exceed);
}
else if(!exceed) {
tarLoc = CSMath.lerp(this._startIndex + this._pickupTimeDistCovered * this.pickupTimeSpan,this._targetDest - this._pickupTimeDistCovered * this.pickdownTimeSpan,(this._tweenProgress - this.get_pickupTimeDur()) / (this._tweenDuration - this.get_totalPickupAndDownTimeDur()));
this.movingState = BGTrainState.SPEEDING;
this._curVelocity = this._maxSpeed;
}
this._curLoc = tarLoc;
if(this._tweenProgress >= this._tweenDuration) {
this._tweenProgress = this._tweenDuration;
this._isStarted = false;
}
}
else {
this.movingState = BGTrainState.STOPPED;
this._curVelocity = 0;
}
if(this._forceStop) {
this._forceStop = false;
this._isStarted = false;
this._curVelocity = 0;
this.movingState = BGTrainState.STOPPED;
}
}
static protected var PUSH_FORWARD_ERROR : Number = .75;
static public function main() : void {
}
static protected var unitTimeLength : Number = 60;
}
class CSMath {
static public function lerp(n0 : Number,n1 : Number,p : Number) : Number {
return n0 * (1 - p) + n1 * p;
}
static public function rnd(min : Number,max : Number) : Number {
return min + Math.random() * (max - min);
}
}
class EaseFunctions {
public function EaseFunctions() : void {
}
public var distCovered : Function;
public var distCovered_Out : Function;
public var distCoveredGetX : Function;
public var deriative : Function;
public var deriative_Out : Function;
public var deriativeGetX : Function;
static public function linearDistCovered(t : Number) : Number {
return t;
}
static public function linearDistCoveredGetX(offset : Number) : Number {
return offset;
}
static public function linearDeriative(x : Number) : Number {
return 1;
}
static public function linearDeriativeGetX(v : Number) : Number {
return 0;
}
static public function quadraticDistCovered(t : Number) : Number {
return t * t;
}
static public function quadraticDistCovered_Out(t : Number) : Number {
return t * (2 - t);
}
static public function quadraticDistCoveredGetX(offset : Number) : Number {
return Math.sqrt(offset);
}
static public function quadraticDeriative(x : Number) : Number {
return 2 * x;
}
static public function quadraticDeriative_Out(x : Number) : Number {
return 2 - 2 * x;
}
static public function quadraticDeriativeGetX(v : Number) : Number {
return v / 2;
}
static public function cubicDistCovered(t : Number) : Number {
return t * t * t;
}
static public function cubicDistCovered_Out(t : Number) : Number {
return --t * t * t + 1;
}
static public function cubicDistCoveredGetX(offset : Number) : Number {
return Math.pow(offset,0.33333333333333331);
}
static public function cubicDeriative(x : Number) : Number {
return 3 * x * x;
}
static public function cubicDeriative_Out(x : Number) : Number {
return 3 * x * x - 6 * x + 3;
}
static public function cubicDeriativeGetX(v : Number) : Number {
return Math.sqrt(v / 3);
}
static public function quarticDistCovered(t : Number) : Number {
return t * t * t * t;
}
static public function quarticDistCovered_Out(t : Number) : Number {
return 1 - --t * t * t * t;
}
static public function quarticDistCoveredGetX(offset : Number) : Number {
return Math.pow(offset,0.25);
}
static public function quarticDeriative(x : Number) : Number {
return 4 * x * x * x;
}
static public function quarticDeriative_Out(x : Number) : Number {
return -4 * x * x * x + 12 * x * x - 12 * x + 4 * x;
}
static public function quarticDeriativeGetX(v : Number) : Number {
return Math.pow(v / 4,0.33333333333333331);
}
static public function quinticDistCovered(t : Number) : Number {
return t * t * t * t * t;
}
static public function quinticDistCovered_Out(t : Number) : Number {
return 1 + --t * t * t * t * t;
}
static public function quinticDistCoveredGetX(offset : Number) : Number {
return Math.pow(offset,0.2);
}
static public function quinticDeriative(x : Number) : Number {
return 5 * x * x * x * x;
}
static public function quinticDeriative_Out(x : Number) : Number {
return 5 * x * x * x * x - 20 * x * x * x + 30 * x * x - 20 * x + 5;
}
static public function quinticDeriativeGetX(v : Number) : Number {
return Math.pow(v / 5,0.25);
}
static public var LINEAR : int = 0;
static public var QUADRATIC : int = 1;
static public var CUBIC : int = 2;
static public var QUARTIC : int = 3;
static public var QUINTIC : int = 4;
static public function create(powerIndex : int) : EaseFunctions {
var me : EaseFunctions = new EaseFunctions();
switch(powerIndex) {
case 0:
{
me.distCovered = EaseFunctions.linearDistCovered;
me.distCovered_Out = EaseFunctions.linearDistCovered;
me.distCoveredGetX = EaseFunctions.linearDistCoveredGetX;
me.deriative = EaseFunctions.linearDeriative;
me.deriative_Out = EaseFunctions.linearDeriative;
me.deriativeGetX = EaseFunctions.linearDeriativeGetX;
}
break;
case 1:
{
me.distCovered = EaseFunctions.quadraticDistCovered;
me.distCovered_Out = EaseFunctions.quadraticDistCovered_Out;
me.distCoveredGetX = EaseFunctions.quadraticDistCoveredGetX;
me.deriative = EaseFunctions.quadraticDeriative;
me.deriative_Out = EaseFunctions.quadraticDeriative_Out;
me.deriativeGetX = EaseFunctions.quadraticDeriativeGetX;
}
break;
case 2:
{
me.distCovered = EaseFunctions.cubicDistCovered;
me.distCovered_Out = EaseFunctions.cubicDistCovered_Out;
me.distCoveredGetX = EaseFunctions.cubicDistCoveredGetX;
me.deriative = EaseFunctions.cubicDeriative;
me.deriative_Out = EaseFunctions.cubicDeriative_Out;
me.deriativeGetX = EaseFunctions.cubicDeriativeGetX;
}
break;
case 3:
{
me.distCovered = EaseFunctions.quarticDistCovered;
me.distCovered_Out = EaseFunctions.quarticDistCovered_Out;
me.distCoveredGetX = EaseFunctions.quarticDistCoveredGetX;
me.deriative = EaseFunctions.quarticDeriative;
me.deriative_Out = EaseFunctions.quarticDeriative_Out;
me.deriativeGetX = EaseFunctions.quarticDeriativeGetX;
}
break;
case 4:
{
me.distCovered = EaseFunctions.quinticDistCovered;
me.distCovered_Out = EaseFunctions.quinticDistCovered_Out;
me.distCoveredGetX = EaseFunctions.quinticDistCoveredGetX;
me.deriative = EaseFunctions.quinticDeriative;
me.deriative_Out = EaseFunctions.quinticDistCovered_Out;
me.deriativeGetX = EaseFunctions.quinticDeriativeGetX;
}
break;
default:
// if(powerIndex > 0) (haxe.Log._trace)("Warning:: no easing functions case found",{ fileName : "EaseFunctions.hx", lineNumber : 193, className : "EaseFunctions", methodName : "create"});
break;
};
return me;
}
}
class GameSettings {
public function GameSettings() : void {
}
public var minTurnTime : Number = 1;
public var penaltyDelayMs : Number = 0;
static public var SHARED_FPS : int = 60;
static protected function delayInSeconds(ms : Number) : Number {
return ms / 1000;
}
}