MojaGrandPrix(play with WebCam)
stolen from @makc3d, see http://makc3d.wordpress.com/2010/10/08/hough-transform-part-2/
/* How to play */
Get a pen, ruler, any banknote, etc. Steer it in front of webcam. see http://nullurban.appspot.com/moja-HOW-TO.swf
[T] - show estimator (for adjustment)
[W] - show/hide wheel
[UP/W] - auto acceleration
[Down/S] - auto reverse
/**
* Copyright zob ( http://wonderfl.net/user/zob )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/dOOl
*/
/**
* Copyright tencho ( http://wonderfl.net/user/tencho )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/t5IZ
*/
/**
* [Arrow Keys] : Steer / Move Menu Cursor
* [Z] : Accelerate / Select
* [X] : Brake, Reverse / Cancel
* [C] : Change Camera
* [CTRL] : Pause Menu
*
* 最初だけマウスでクリックして、あとはキーボードで操作します。
* ドリフトはスピードつけてカーブ中にアクセルを離してまたすぐ押す感じ。
* Z、Xの代わりにメニューではEnter、SHIFT、運転は上下キーでも代用できるけど、ドリフトがしにくくなるかもしれないです。
* タイムトライアルモードではゴーストが10台まで一時的に残ります。(一時的なのでSWFをリセットすると消えちゃう)
* セーブデータはSharedObjectで保存してるけど、Fileのエクスポート/インポートを使うとデータが移せます。
* ちなみに全部クリアしても特別な事は起こりません・・・気が向いたら何か追加するかも。
*/
package {
import com.bit101.components.ProgressBar;
import com.bit101.components.Style;
import flash.display.Sprite;
import flash.display.StageQuality;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
public class MojaGrandPrix extends Sprite {
private var progress:ProgressBar;
public var keyEnabled:Boolean = true;
private var de:DistanceEstimator;
private var wheel:Wheel = new Wheel(stage);
public function MojaGrandPrix() {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void {
addChild(Create.box((Display.width - 4000) / 2, (Display.height - 4000) / 2, 4000, 4000, 0, 1));
Display.stage = stage;
Display.setSize(465, 465);
transform.perspectiveProjection.fieldOfView = 78;
transform.perspectiveProjection.projectionCenter = Display.center;
stage.frameRate = 30;
stage.quality = StageQuality.LOW;
$.moja = this;
$.howto = new HowTo();
$.replay = new ReplayManager();
$.thumb = new Thumb();
$.race = new Race();
$.game = new Game(de = new DistanceEstimator(wheel));
$.user = new UserData();
$.selector = new TrackSelector();
$.world = new World();
$.top = new TopMenu();
$.setting = new SettingMenu();
$.transition = new FadeTransition();
$.tape = new TickerTape();
$.complete = new Complete();
$.user.setDefaultData();
$.user.load();
Dot.init();
$.complete.init();
$.transition.init();
$.game.init();
$.setting.init();
$.top.init();
$.selector.init();
ScoreWindow.title = "Moja Grand Prix";
ScoreWindow.init(loaderInfo, start, onErrorScore);
}
private function onErrorScore():void {
$.top.setNoConnection();
start();
}
private function start():void {
$.world.checkRankIn($.user);
$.world.checkComplete($.user);
$.game.sprite.scrollRect = Display.size;
addChild($.game.sprite);
addChild($.selector.sprite);
addChild($.game.display.backSprite);
addChild($.top.sprite);
addChild($.setting.sprite);
addChild($.complete.sprite);
addChild($.howto.sprite);
addChild($.tape.sprite);
addChild(ScoreWindow.sprite);
addChild($.transition.sprite);
addChild(wheel);
Style.PROGRESS_BAR = 0xDE472D;
progress = new ProgressBar(this, (Display.width - 80) / 2, (Display.height - 4) / 2);
progress.setSize(80, 4);
SE.init();
SE.mute = $.user.mute;
$.thumb.create(onComplete, onProgress);
}
private function onProgress(per:Number):void {
progress.value = per;
}
private function onComplete():void {
removeChild(progress);
$.game.createStage($.world.demo);
$.game.isDemo = true;
$.game.startRace();
$.transition.fadeIn();
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyUpDown);
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUpDown);
}
private function onKeyUpDown(e:KeyboardEvent):void {
if (!keyEnabled) return;
$.game.keyUpDown(e);
$.howto.keyUpDown(e);
if (e.type == KeyboardEvent.KEY_DOWN) return;
switch(e.keyCode) {
case 90: case Keyboard.ENTER://Z,ENTER
if ($.top.scene == TopMenu.SCENE_CLICK) $.top.gotoTop();
break;
case 81://Q
$.user.groundQuality = ++$.user.groundQuality % 2;
$.game.updateGround();
$.setting.update();
$.user.save();
break;
case 80://P
$.user.showParticles = !$.user.showParticles;
$.setting.update();
$.user.save();
break;
case 86://V
$.user.viewDistance = ++$.user.viewDistance % 5;
$.game.updateDisplay();
$.setting.update();
$.user.save();
break;
case 76://L
$.user.showLight = !$.user.showLight;
$.game.updateDisplay();
$.setting.update();
$.user.save();
break;
case 77://M
$.user.showMirror = !$.user.showMirror;
$.game.updateDisplay();
$.setting.update();
$.user.save();
break;
case 71://G
$.user.showGhost = !$.user.showGhost;
$.game.updateGhostVisible();
$.setting.update();
$.user.save();
break;
case 83://S
$.user.mute = SE.mute = !SE.mute;
$.setting.update();
$.user.save();
break;
case 84://T
de.visible = !de.visible;
if(de.visible)
addChild(de.show());
else
removeChild(de.hide());
break;
case 87://W
wheel.visible = !wheel.visible;
break;
}
}
}
}
import Box2D.Collision.Shapes.b2FilterData;
import Box2D.Common.Math.b2Vec2;
import Box2D.Dynamics.b2Body;
import com.actionsnippet.qbox.objects.GroupObject;
import com.actionsnippet.qbox.QuickBox2D;
import com.actionsnippet.qbox.QuickContacts;
import com.actionsnippet.qbox.QuickObject;
import com.bit101.components.Label;
import com.bit101.components.PushButton;
import com.bit101.components.Style;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BitmapDataChannel;
import flash.display.BlendMode;
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.GradientType;
import flash.display.Graphics;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.display.MovieClip;
import flash.display.Shape;
import flash.display.Sprite;
import flash.display.Stage;
import flash.display.StageQuality;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.events.SecurityErrorEvent;
import flash.filters.DropShadowFilter;
import flash.filters.GlowFilter;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.geom.Vector3D;
import flash.net.FileReference;
import flash.net.SharedObject;
import flash.net.URLRequest;
import flash.system.LoaderContext;
import flash.text.TextFormat;
import flash.ui.Keyboard;
import flash.utils.ByteArray;
import flash.utils.describeType;
import net.wonderfl.utils.WonderflAPI;
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.easing.Cubic;
import org.libspark.betweenas3.tweens.ITween;
import org.si.sion.SiONDriver;
import org.si.sion.utils.SiONPresetVoice;
/**
* 全データ
*/
class $ {
static public var moja:MojaGrandPrix;
static public var tape:TickerTape;
static public var howto:HowTo;
static public var replay:ReplayManager;
static public var thumb:Thumb;
static public var race:Race;
static public var world:World;
static public var game:Game;
static public var user:UserData;
static public var selector:TrackSelector;
static public var top:TopMenu;
static public var setting:SettingMenu;
static public var transition:FadeTransition;
static public var complete:Complete;
}
/**
* おめでとう
*/
class Complete {
public var sprite:Sprite = new Sprite();
private var _message:Label;
private var _congra:Bitmap;
public function Complete() {
}
public function init():void {
var sp:Sprite = new Sprite();
UI.createLabel(sp, 0, 0, "CONGRATULATIONS!", 32);
_congra = Create.gradientLabel(sp, 0xF8F044, 0xE98A0A);
_congra.x = 50;
_congra.y = 100;
sprite.addChild(_congra);
_message = UI.createLabel(sprite, 60, 150, "", 16, 0xF8F044);
_message.filters = UI.TEXT_FILTERS;
hide();
}
public function show(lv:int):void {
$.game.destroyStage();
switch(lv) {
case Race.NORMAL:
$.world.complete.light = Light.DAY;
$.world.complete.setPlace(Track.FOREST);
break;
case Race.HARD:
$.world.complete.light = Light.DAWN;
$.world.complete.setPlace(Track.CIRCUIT);
break;
case Race.EXTREME:
$.world.complete.light = Light.NIGHT;
$.world.complete.setPlace(Track.SNOWFIELD);
break;
}
$.game.createStage($.world.complete);
SE.stopAll();
SE.setVolume(1);
SE.effect(SE.SND_FINISH);
$.game.startRace();
var f:Point = $.game.player.front.clone();
f.normalize(300);
$.game.player.addForce(f);
_message.text = "You Completed All '" + Text.LEVELS[lv] + "' Tracks!";
sprite.visible = true;
}
public function hide():void {
sprite.visible = false;
}
}
/**
* コース情報
*/
class Track {
static public const CIRCUIT:int = 0;
static public const FOREST:int = 1;
static public const SNOWFIELD:int = 2;
static public const WINTERCIRCUIT:int = 3;
public var name:String = "Demo Course";
public var id:int = -1;
public var level:int = 0;
public var unlock:int = 0;
public var handicap:Number = 1;
public var light:int = 0;
public var place:int = CIRCUIT;
public var lapsNum:int = 3;
public var enemiesNum:int = 7;
public var fenceHeight:Number = 0.8;
public var fenceMapSize:int = 6;
public var fenceMap:BitmapData = null;
public var dirtFriction:Number = 0.02;
public var lakeColor:Number = 0x2D488C;
public var edgeColor:uint = 0xD9C364;
public var roadColor:uint = 0x4A4A4A;
public var lineColor:uint = 0xFFFFFF;
public var pathColor:uint = roadColor;
public var dirtColor:uint = 0x73900B;
public var lakeEdge:uint = 0x8598A6;
public var roadSize:Number = 25;
public var pathSize:Number = 20;
public var lakes:Array = [];
public var points:Array = [];
public var path:Array = [];
public var objectS:Array = [];
public var objectL:Array = [];
public var lamps:Array = [];
public var trees:Array = [];
public var fences:Array = [];
public var planes:Array = [];
public var plants:Array = [];
public var seatsXY:Array = [75, 11];
public var wancoXY:Array = [0, 0];
public var checkPoints:Array = [[0, 0, 100, 0], [0, 0, -100, 0]];
public var particleColors:Array = [];
public var gazeXY:Array = [];
public var cameraXY:Array = [];
public function Track(param:Object = null) {
if (!param) return;
if (param.course != null) setCourse(param.course);
if (param.lv != null) level = param.lv;
if (param.light != null) light = param.light;
if (param.place != null) setPlace(param.place);
if (param.unlock != null) unlock = param.unlock;
if (param.reverse) reverse();
}
public function reverse():void {
name += "(R)";
points.reverse();
for each (var p:Array in points) {
if (p.length < 6) continue;
var tmp:Number = p[4];
p[4] = p[2];
p[2] = tmp;
tmp = p[5]
p[5] = p[3];
p[3] = tmp;
}
var start:Array = points.splice(-2, 2);
points = start.concat(points);
for (var i:int = 0; i < checkPoints.length; i++)
checkPoints[i] = [checkPoints[i][2], checkPoints[i][3], checkPoints[i][0], checkPoints[i][1]];
checkPoints.reverse();
checkPoints.unshift(checkPoints.pop());
}
/**
* 指定の場所にコース図を描画する
*/
public function draw(g:Graphics, thickness:Number = 1, color:uint = 0xFFFFFF, alpha:Number = 1, scale:Number = 1):void {
g.lineStyle(thickness, color, alpha);
for (var i:int = 0; i < points.length; i++) {
var a:Array = points[i];
var b:Array = points[(i+1) % points.length];
CurveUtil.drawBezierXY(g, a[0], a[1], b[0], b[1], a[2], a[3], b[4], b[5], 4, scale);
}
}
/**
* コース形状を決める
*/
public function setCourse(num:int):void {
switch(num) {
case -1:
name = "How To Drift";
roadSize = 60;
pathSize = 130;
cameraXY = [-14.42,-25.85];
gazeXY = [-7.52,-36.52];
seatsXY = [-46.18,-1.77];
trees = [[3.49,26.99],[10.74,24.49],[18.37,27.24],[-0.37,34.49],[-51.13,52.99],[-46.75,58.62],[-37.25,56.24],[-32.5,47.99],[-46.5,47.99],[-50.25,40.74],[-75.37,39.12],[-74.75,55.49],[-73.37,68.24],[-21.37,71.49],[-14.88,62.62],[-9,52.61],[-26.5,36.25],[-20.75,27.24],[43.99,31.99],[47.99,39.24],[59.24,38.75],[62.5,28.49],[60.5,-33.75],[63.62,-38.12],[77.37,-35.12],[71.24,-14.37],[64.62,-12.75],[71.62,-8.88],[42.99,-19],[40.49,-27.5],[41.99,-38],[43.37,-43.75],[22.24,-53.25],[5.5,-55.63],[7.75,-79.12],[26.62,-80.25],[57.5,-83.62],[74.74,-65.37],[74.74,-52.75],[48.24,-88.25],[86.37,-31.5],[88.5,15],[76.49,60.5],[72.25,71.25],[58.75,82.5],[43.5,79.25],[31.25,63.24],[-69.5,-73],[-75,-66.75],[-77.25,-54],[-72.87,-42],[-57,-76],[-57.63,-54.12],[-47.62,-54.87],[-53.62,-47.75],[-50.62,-37.75],[-36.13,-54.63],[-71.37,-32.38],[67.87,-34.75],[45.61,-49.63],[52.62,-13.25],[68.24,-78.5],[-48.37,-25.25],[-70.25,81],[-60,90.24],[-45.75,91],[-27.25,82.62],[54,42.49]];
checkPoints = [[-78.25,-20.75,-43.25,-20.25],[86.99,4.25,55.73,3.75]];
path = [[[35.49,44.73],[56.98,71.48],[68.73,43.73]],[[-4.25,23.24],[15.49,-1.25],[37.75,23.49]],[[-61,56.25],[-60,76.75],[-32.25,73.24],[-28,61.49]],[[54.48,-36.25],[65,-65.01],[54.75,-68.25],[21.23,-64.53]]];
points = [[-63.2,-45.35,8.38,10.58,-25.26,-31.89],[-62.7,29.09,-1.25,52.24,0.24,-10.4],[-41.25,72.74,9.09,-2.72,-14.26,4.27],[-15.27,41.48,6.68,-14.52,-6.77,14.72],[10.25,7.99,15.7,-6.79,-12.4,5.36],[39.23,51.23,5.93,16.51,-6.67,-18.58],[65.47,52.98,13.59,-40.57,-4.08,12.17],[80.99,-20.25,-2.24,-11.43,2.53,12.93],[50.23,-25,-4.52,-8.34,4.18,7.72],[43.98,-68.26,-58.25,3.92,29.46,-1.98]];
wancoXY = [-36.25,-0.77];
break;
case 11:
name = "Moja Circuit+";
roadSize = 37;
pathSize = 33;
cameraXY = [-30.91,59.05];
gazeXY = [-39.18,10.74];
seatsXY = [-65.81,-14.73];
lakes = [[-50.27,-52.14,18],[52.22,29.49,14],[63.05,-58.25,12]];
objectS = [[63.74,12.45],[66.54,13.76],[63.09,9.89],[8.35,-63.66],[10.94,-64],[13.7,-64.84],[15.95,-65.71],[18.51,-66.4],[21.32,-67.27],[60.78,0.7],[61.82,3.75],[62.47,6.69],[-54.36,-71.8],[-60.69,-69.58],[-65.74,-64.94],[-69.22,-59.53],[-70.27,-52.69]];
objectL = [[-5.26,67.43],[-6.95,66.03],[-7.7,67.86],[-69.83,20.94],[-71.65,21.69],[-71.44,20.01]];
lamps = [[-53.58,22.1],[-48.53,25.33],[-44.5,28.15],[-40.25,30.98],[-36.02,34.4],[-31.58,37.44],[-27.34,40.26],[-23.3,42.68],[-88.29,-36.22],[-88.7,-30.37],[-88.29,-23.7],[-88.29,-18.66],[-88.7,-13.82],[-88.29,-9.18],[-17.75,-19],[-10.25,-13.75],[-0.25,-8.5],[7.24,-4.25],[15,0.74],[-39,9.74],[-34,13],[68.99,-44.75],[-13.25,26.99],[-18.75,23.49],[53.24,-69.26],[13,-75],[27.75,-68.25],[28.5,-87],[36.5,-87],[43.49,-87.25]];
trees = [[-88.29,-53.38],[-88.09,-60.85],[-86.27,-71.95],[-71.73,-89.7],[-62.86,-91.51],[-53.77,-91.52],[-43.69,-91.11],[-35.61,-90.71],[-27.14,-89.5],[-19.67,-87.89],[-12,-86.68],[-1.12,-83.25],[14.87,-84.24],[5.38,-81.02],[35.83,-68.58],[39.61,-65.7],[30.78,-68.72],[46.72,-60.44],[10.19,-79],[8.77,-84.65],[3.13,-86.47],[81.04,10.52],[79.17,6.15],[82.91,14.21],[59.23,-16.45],[55.8,-21.49],[91.78,26.02],[92.53,30.91],[93.86,36.53],[67.09,61.65],[61.65,66.29],[56.2,71.34],[54.19,76.39],[51.56,81.23],[47.14,89.21],[15.44,59.23],[23.51,61.45],[28.96,61.25],[35.82,59.84],[41.88,56.2],[45.48,52.38],[25.99,28.24],[25.25,35.99],[17.24,39.49],[7.75,38.75],[-44.75,4.49],[-44.5,-5.25],[-39.75,-13.25],[-33.25,-18.75],[-24.5,-21.25],[87.24,-79],[82.24,-83.75],[39.75,4.74],[26.99,-15.5],[17.75,-20.25],[22.75,-23.75],[9.49,-27.75],[-57,-20.5],[-54.25,-27.25],[-60,-27],[-62.25,2.75],[91.49,-48.75],[94.49,-38.5],[79.25,-27.25],[72.5,-23.75],[75.99,-25],[31.74,90.5],[18,89.25],[14.49,83.75],[-83.75,31.5],[-77.5,41.74],[-66.25,52.75],[-53.75,61],[-40.5,71.25],[-25,78],[-7,83.75],[24.24,-91.75],[41.25,-92.5],[53.5,-94],[65.24,-92],[74.75,-91]];
checkPoints = [[-37,30.74,-56.5,58.24],[-46.25,25,-65.75,51.25],[-66.75,2.5,-89.5,6.75],[-64.75,-53.25,-92.25,-55.25],[-43.75,-66,-38,-94.5],[7.5,-53.75,5.99,-94],[23.75,-28.25,93.5,-82.5],[25.74,-22.5,98,-37.25],[44.24,6.99,95.5,10.25],[43.24,53.75,95,92.74],[34.24,61.99,38.5,95.24],[17.75,59,-8.5,93.99],[-26.25,38.75,-46.25,67.99]];
planes = [[[[-45.75,62.74],[-29,36.5]],3,3,".title",true,1,1],[[[-0.25,0.24],[7.74,5.74]],4,2,".wonderfl",true,1,1],[[[50.74,-87.25],[59.48,-87.5]],5,0,".flash",false,1,1],[[[28.5,-65.75],[10,-59]],3,0,".title",false,1,1]];
fences = [[[-67.34,-46.98],[-72.14,-33.6],[-72.34,-5.35],[-67.9,7.97],[-57.4,22.48],[-21.29,47.32],[-6.54,52.98],[7.94,58.83],[31.59,67.98],[39.79,65.26],[52.49,51.2],[56.4,42.08]],[[41.03,11.06],[49.1,9.88],[48.3,4.88],[34.04,-7.35],[29.78,-24.33],[31.79,-40.28],[25.51,-52.16],[8,-60.64],[1.87,-60.91],[-18.7,-67.95],[-30.23,-75.39],[-42,-73.7],[-49,-69.65]],[[-70.12,22.9],[-64.88,31.38],[-27.14,58.22],[-9.55,66.28]],[[10.17,73.56],[17.62,76.37],[24.09,82.84],[33.61,87.9],[45.71,85.47],[51.75,71.54],[62.43,61.66],[76.59,52.95],[83.65,42.66],[88.86,32.83],[87.18,18.63]],[[57.98,-5.68],[57.28,-10.69],[52.96,-17.04],[50.74,-28.52],[53.35,-41.25],[51.35,-51.57],[42.06,-59.22],[25.74,-66.93]],[[10,-75.39],[-12.2,-83.46],[-32.79,-87.3],[-54.38,-88.5],[-69.33,-86.67],[-79.8,-79.4],[-84.46,-66.65],[-86.07,-43.69],[-85.85,-6.15],[-84.66,16.84],[-74.56,38.43],[-53.36,55.39],[-32.79,69.92],[-14.23,77.98],[-1.11,77.79],[10.17,73.56]],[[87.1,17.73],[88.79,13.12],[85.67,-17.05],[83.72,-29.37],[87.07,-41.21]],[[87.07,-41.21],[88.75,-64.26],[82.99,-78],[65.98,-86],[21.75,-83.75],[10,-75.39]],[[44,39.75],[40.25,49.24],[24.25,55.74],[4.74,54.24],[-57.5,14.25],[-58.25,-10.75],[-42.75,-32.5],[-19.25,-38],[31.25,-6.25],[41.03,11.06]]];
path = [[[-78.65,-49.77],[-75.53,-69.25],[-66.5,-79.09],[-52.88,-82.85],[-34,-82.05],[-21.14,-79.03]],[[9.65,68.22],[-3.29,70.98],[-12.54,70.39],[-28.68,63.7],[-47.81,50.02],[-69.51,34.02],[-78.22,15.45],[-78.4,-5.35]],[[39.85,79.16],[32.79,79.2],[24.54,74.79],[15.66,69.75]],[[50,13.49],[41,17.24],[33.75,24.25],[34.49,32.99],[32.25,44],[18,50.25],[5.5,50],[-53,12.5],[-53.25,-9.5],[-39.75,-27.25],[-21.25,-32.5],[26.75,-2.25],[33.75,24.25]],[[-31,23.24],[-15,1.99],[4.25,14.74]],[[5.99,-68.25],[30.49,-57.25],[41.24,-45.75],[41.74,-30.75],[38.5,-20.75],[43.75,-8.75],[75.11,17.24]]];
points = [[-60.69,27.1,-10.37,-8.62,36.65,30.48],[-78.79,-24.8,-0.33,-10.75,-1.05,35.78],[-62.69,-75.34,22.51,-9.25,-19.3,8.3],[-9.88,-75.56,5.16,2.27,-15.09,-6.65],[8.28,-68.15,8.85,3.67,-6.22,-2.58],[31.23,-76.25,19.5,-0.75,-10.2,0.39],[78.98,-68,7.61,10.94,-8.67,-12.46],[67.48,-32.75,-10.54,3.76,13.46,-4.8],[67.66,7.73,2.54,6.44,-3.41,-8.66],[81.9,31.17,-0.38,9.03,0.56,-13.3],[51.4,61.04,-9.33,10.61,14.75,-16.78],[18.75,70.85,-12.37,-6.37,27.98,14.42]];
wancoXY = [25.74,-59.01];
break;
case 0:
name = "Clear";
roadSize = 36;
pathSize = 15;
cameraXY = [-24.25,52.23];
gazeXY = [10.24,4.74];
seatsXY = [34.23,45.94];
lamps = [[-42.5,40.98],[-37.75,36.74],[-32.25,32.99],[-26.5,27.5],[-21.25,23.49],[-16.5,19.49],[-10.5,15],[-5.5,10.5],[-0.75,6.5],[3.74,2.74],[8.24,-1.25],[-32.75,54],[-28.25,50.49],[-22.75,45.74],[-18.5,41.99],[-13.25,38.5],[-8.5,34.24],[-3.25,29.75],[1.75,25.99],[6.75,22.5],[11.25,18.24],[15,15],[18.75,12.24]];
trees = [[43.75,-32.5],[36.99,-27.25],[31,-22.5],[24.74,-17.5],[18.24,-13],[29.74,4.25],[35.99,-1],[42.99,-7],[48.24,-12],[55.25,-17.75]];
checkPoints = [[46.74,-46,96.48,6.49],[-67.5,45.49,-97.5,71.99],[-5,-10.5,-81.25,-92.5],[59.24,-59.25,92.25,-89.25]];
fences = [[[63,-56.5],[-65.75,50.49],[-71.25,43.5],[57.5,-63.75],[63,-56.5]]];
path = [[[25,0.5],[25,16.99],[-29.25,62.49],[-54,63.49]],[[25,13.49],[24.25,59.99],[28.75,66.75],[64.23,66.72]]];
points = [[79.04,-49.37,0,0,0,0],[-60.19,67.59,0,0,0,0],[-83.5,60.22,0,0,0,0],[-85.25,33.5,0,0,0,0],[50.74,-80.5,0,0,0,0],[79.49,-77.25,0,0,0,0]];
wancoXY = [80,-17.5];
break;
case 1:
name = "Moja Circuit";
handicap = 0.85;
roadSize = 37;
pathSize = 33;
cameraXY = [-30.91,59.05];
gazeXY = [-39.18,10.74];
seatsXY = [-65.81,-14.73];
lakes = [[-50.27,-52.14,18],[52.22,29.49,14],[63.07,-60,12]];
objectS = [[53.11,11.58],[54.04,14.01],[61.49,-6.35],[11.6,-74.16],[13.32,-73.25],[15.09,-72.45],[16.95,-71.34],[18.77,-70.53],[20.32,-69.52],[52.28,9.83],[65.58,-1.24],[63.47,-3.92],[-54.36,-71.8],[-60.69,-69.58],[-65.74,-64.94],[-69.22,-59.53],[-70.27,-52.69]];
objectL = [[-8.01,67.7],[-7.45,65.79],[-6.2,67.38],[-69.83,20.94],[-71.65,21.69],[-71.44,20.01]];
lamps = [[-53.58,22.1],[-48.53,25.33],[-44.5,28.15],[-40.25,30.98],[-36.02,34.4],[-31.58,37.44],[-27.34,40.26],[-23.3,42.68],[-88.29,-36.22],[-88.7,-30.37],[-88.29,-23.7],[-88.29,-18.66],[-88.7,-13.82],[-88.29,-9.18],[-17.75,-19],[-10.25,-13.75],[-0.25,-8.5],[7.24,-4.25],[15,0.74],[-39,9.74],[-34,13],[68.5,-46.25],[-13.25,26.99],[-18.75,23.49],[52.49,-69.75],[53.24,6.5],[57.75,11.75],[62.5,16.75],[66.25,21.25],[67.5,27.75],[80,12.5],[83.24,16.5],[49.24,-49],[49.49,-40.5],[48.5,-32.5],[48.24,-24.75],[-70,46.74],[-62.25,52.75],[-53,60],[-44,66.49],[-36.5,71.75],[-27.5,75.74],[-20.5,78.75],[37.99,89.25],[43.49,89.25],[-3.75,-34.5],[4.25,-29.75],[66.99,-18.5],[26.5,-87.75],[33.99,-87.25]];
trees = [[-88.29,-53.38],[-88.09,-60.85],[-86.27,-71.95],[-71.73,-89.7],[-62.86,-91.51],[-53.77,-91.52],[-43.69,-91.11],[-35.61,-90.71],[-27.14,-89.5],[-19.67,-87.89],[-12,-86.68],[-1.12,-83.25],[14.87,-84.24],[5.38,-81.02],[26.34,-70.33],[37.61,-65.7],[30.78,-68.72],[46.72,-60.44],[11.18,-81.25],[19.02,-88.9],[-4.12,-90.47],[74.54,4.27],[71.42,0.9],[77.18,7.71],[59.23,-16.45],[55.8,-21.49],[87.29,25.53],[87.29,35.42],[85.87,43.29],[67.09,61.65],[61.65,66.29],[56.2,71.34],[54.19,76.39],[51.56,81.23],[50.15,85.47],[15.44,59.23],[23.51,61.45],[28.96,61.25],[35.82,59.84],[41.88,56.2],[45.48,52.38],[25.99,28.24],[25.25,35.99],[17.24,39.49],[7.75,38.75],[-44.75,4.49],[-44.5,-5.25],[-39.75,-13.25],[-33.25,-18.75],[-24.5,-21.25],[82.74,-79],[77.74,-82],[39.75,4.74],[26.99,-15.5],[17.75,-20.25],[22.75,-23.75],[9.49,-27.75],[-57,-20.5],[-54.25,-27.25],[-60,-27],[-62.25,2.75],[5.25,21.75],[-1,20.99],[11.99,18.75],[10.74,9.49],[-31.75,-70.75],[-23.5,-65.5],[-11,-60],[1.75,-56.25],[13,-55],[19.74,-49.75],[-75.75,44],[-67.25,51.5],[-59.25,56.74],[-49,66.99],[-39,73.24],[-27.5,78.75],[-15.25,81.75],[-5.25,30.74],[-8.75,-40.25],[-23.5,-43.25],[-31.75,-40],[-89,6.5],[-88.5,22.75],[-94.5,-29.5],[-94,-18],[88.75,-29.5],[90,-20.25],[91.49,-4],[92.74,-42.5],[10.74,83.5],[23.24,88.75]];
checkPoints = [[-52.5,21.25,-91.75,75.24],[-61.25,11.99,-98,59.75],[-65.75,-1.5,-92.75,-1.75],[-66.75,-40.25,-94.25,-40.25],[-60.25,-60.75,-83.75,-83.5],[-44.25,-65.75,-37.5,-96],[4.74,-45.75,36.74,-95.25],[23.24,-29.25,94.49,-64.75],[44.24,6.99,93.5,-15],[57.75,31.25,94.74,40],[45,54.75,89.25,92.25],[32.75,62.5,34,94.49],[10.99,57.75,-9,93.75],[-38,31.99,-77,91.99]];
planes = [[[[-45.75,62.74],[-29,36.5]],3,3,".title",true,1,1],[[[-0.25,0.24],[7.74,5.74]],4,2,".wonderfl",true,1,1],[[[53.24,-86],[62.24,-85.25]],5,0,".flash",false,1,1]];
fences = [[[-67.34,-46.98],[-72.14,-33.6],[-72.34,-5.35],[-67.9,7.97],[-57.4,22.48],[-21.29,47.32],[-6.54,52.98],[7.94,58.83],[31.59,67.98],[39.79,65.26],[52.49,51.2],[56.4,42.08]],[[41.03,11.06],[49.1,9.88],[48.3,4.88],[34.04,-7.35],[29.78,-24.33],[31.79,-40.28],[25.51,-52.16],[13,-61.64],[1.87,-60.91],[-18.7,-67.95],[-30.23,-75.39],[-42,-73.7],[-49,-69.65]],[[-70.12,22.9],[-64.88,31.38],[-27.14,58.22],[-9.55,66.28]],[[10.17,73.56],[17.62,76.37],[24.09,82.84],[33.61,87.9],[45.71,85.47],[51.75,71.54],[62.43,61.66],[76.59,52.95],[83.65,42.66],[84.87,33.34],[84.44,22.89]],[[69.75,-13.68],[60.03,-10.69],[52.96,-17.04],[50.74,-28.52],[53.35,-41.25],[51.35,-51.57],[42.06,-59.22],[22.75,-68.91]],[[10,-75.39],[-12.2,-83.46],[-32.79,-87.3],[-54.38,-88.5],[-69.33,-86.67],[-79.8,-79.4],[-84.46,-66.65],[-86.07,-43.69],[-85.85,-6.15],[-84.66,16.84],[-74.56,38.43],[-53.36,55.39],[-32.79,69.92],[-14.23,77.98],[-1.11,77.79],[10.17,73.56]],[[84.36,22.48],[88.79,13.12],[85.67,-17.05],[81.23,-30.37],[87.07,-41.21]],[[22.76,-68.31],[22.77,-72.36]],[[87.07,-41.21],[85.5,-60],[79.49,-76.25],[67.24,-82.5],[21.75,-83.75],[10,-75.39]],[[44,39.75],[40.25,49.24],[24.25,55.74],[4.74,54.24],[-57.5,14.25],[-58.25,-10.75],[-42.75,-32.5],[-19.25,-38],[31.25,-6.25],[41.03,11.06]]];
path = [[[72.02,14.85],[79.83,27.56],[78.61,37.86],[73.37,45.93],[58.05,54.79]],[[-78.65,-49.77],[-75.53,-69.25],[-66.5,-79.09],[-52.88,-82.85],[-34,-82.05],[-21.14,-79.03]],[[9.65,68.22],[-3.29,70.98],[-12.54,70.39],[-28.68,63.7],[-47.81,50.02],[-69.51,34.02],[-78.22,15.45],[-78.4,-5.35]],[[39.85,79.16],[32.79,79.2],[24.54,74.79],[15.66,69.75]],[[10.43,-69.95],[23.99,-78.78],[41.15,-78.36],[66.06,-76.7],[76.09,-72.36],[80.73,-59.71],[75.81,-48.21],[72.95,-29.93],[77.45,-18.95],[78.79,-8.72],[59.01,-2.82]],[[50,13.49],[41,17.24],[33.75,24.25],[34.49,32.99],[32.25,44],[18,50.25],[5.5,50],[-53,12.5],[-53.25,-9.5],[-39.75,-27.25],[-21.25,-32.5],[26.75,-2.25],[33.75,24.25]],[[-31,23.24],[-15,1.99],[4.25,14.74]]];
points = [[-60.69,27.1,-10.37,-8.62,36.65,30.48],[-78.79,-24.8,-0.33,-10.75,-1.05,35.78],[-62.69,-75.34,22.51,-9.25,-19.3,8.3],[-9.88,-75.29,12.33,4.38,-19.56,-6.95],[36.04,-54.4,14.02,10.34,-12.26,-9.04],[44.93,-11.76,4.62,4.14,-16.48,-14.77],[76.65,27.43,-0.39,9.03,0.57,-13.3],[51.4,61.04,-9.7,10.28,16.76,-17.77],[18.75,70.85,-12.37,-6.37,27.98,14.42]];
plants = [[9.49,14.74,0,4,1],[11.25,14.49,0,4,1],[10.5,16.99,0,4,1],[11.99,15.74,0,4,1]];
wancoXY = [10.61,15.73];
break;
case 2:
name = "Outlying Hoge";
roadSize = 35;
pathSize = 89;
cameraXY = [-14.99,-71.83];
gazeXY = [-44.63,-54.42];
seatsXY = [85.52,5.98];
lakes = [[-41.64,50.02,15],[72.25,72.24,15],[45.74,10,15],[-28.75,14.25,6]];
objectS = [[-9,-63.75],[-5.25,-63.5],[-1.25,-63.5],[2.75,-64.25],[-46.25,-29.5],[-46.25,-25.75],[-46.25,-21.5]];
objectL = [[-13.25,-30.25],[-13.5,-34.5],[-10.25,-32.25]];
lamps = [[-36.25,5.25],[-30.25,1.49],[-22.5,3.24],[-17.25,10.25],[-17.25,19],[-23.75,24.25],[-32.5,24.74],[-38.25,21.5],[-40.25,10.25],[4,-45.25],[4.25,-38.5],[1.99,-30.25],[-15.75,-14.75],[-23.5,-14.5],[-32.5,-16.5]];
trees = [[79.49,26.75],[77.74,34],[75.5,40],[73,47.5],[68,53.5],[-40.5,70.74],[-35.25,73],[-26.75,72.5],[-17.25,72.5],[-12.25,69.49],[-2.25,70],[6.75,68.99],[12.24,65.24],[19.49,62.5],[30.25,60.5],[35.74,56],[43.75,53.75],[46,47.99],[52.99,43.5],[55,36.99],[59.75,32.25],[59.24,24.74],[60.5,20.99],[55.25,-6.25],[59.49,-3],[-67.25,-27],[-67.25,-21.25],[-65.75,-16],[-67.75,-9.75],[-66,-4.75],[-65,3.24],[-65,9.74],[-47.5,-15.01],[-45.5,-8.25],[-43.75,0.25],[-43.5,10],[-46.5,20],[-49.75,24.25],[-52,31.99],[-56.25,36.74],[-68.5,-33.75],[-48.25,-33.75],[-52.25,-41],[-58.5,-48.75],[-57.25,-56.5],[-55.25,-62.75],[-48.5,-66.5],[-42.5,-69.75],[-62.75,-88.25],[-70,-85],[-82.25,-66.5],[-16,-82.75],[-2.5,-81.5],[11.5,-83.5],[65.5,-84.25],[71,-79.75],[73.75,-71.75],[75,-63.5],[74.49,-54.5],[66.25,-48.75],[6.5,-65],[13.24,-64.25],[-12.5,-64.25],[-19.25,-64.5],[-26.75,-67],[-4.25,-18],[-1.5,-21.75],[-15.25,-39],[-9.25,-15],[-18.75,-33.25],[-12.25,-55],[-12.5,-50],[-24.75,-30.25]];
checkPoints = [[5.5,49,18.49,95],[-9.5,52.75,-2.5,97.99],[-41.5,55.25,-61.25,91],[-46.75,45.74,-86.25,40.74],[5.5,18.24,-95,-0.75],[5.74,4.25,-95.25,-53.75],[4.25,-18.5,-56.25,-95],[8.24,-51.25,-3.5,-95],[30.49,-65.5,32.25,-95.5],[38.5,-67,93.24,-72.75],[16.99,-26.5,93.23,-34],[36.99,10.5,96.75,9.49],[39.49,32.25,81.73,57.23],[23,44.49,39.74,87.99]];
planes = [[[[-10.75,5.5],[-10.75,20.74]],5,1,".moja",true,1,1],[[[-69.75,84.24],[-78.75,73.98]],5,1,".wonderfl",true,1,1],[[[63,-45.25],[52.5,-44]],5,1,".wonderfl",true,1,1],[[[-83.25,-71.5],[-75.75,-82]],5,1,".flash",true,1,1],[[[-39.5,-41.5],[-27.75,-40.25],[-22,-48.25],[-24.75,-56.75],[-35.5,-58.5],[-42.5,-51.5],[-39.5,-41.5]],8,0,"bldg",false,4,3]];
fences = [[[58.75,67.73],[32.99,80],[-3.25,88.99],[-34.5,89.49],[-61.25,82.5],[-75.5,68.73],[-79.25,50.74],[-76.5,31.5],[-69,18.49],[-72,-40.75],[-79.25,-54],[-78.5,-67.5],[-69,-81.25],[-52.25,-88.75],[-5.75,-84.25],[42.25,-88.5],[59.74,-86.75],[70.74,-74.75],[72.25,-57.75],[61.24,-49.5],[49.74,-47]],[[-50.75,-49.5],[-47.75,-59.25],[-35.5,-65.75],[-17.5,-60],[-15.75,-45],[-26,-31.75],[-43.5,-33],[-50.5,-49.5]],[[-32.5,-13.27],[-17.25,-10.5],[-0.75,-12],[8.75,-39.25],[4.25,-51.75],[11.5,-61],[24.74,-66],[46,-68.25],[27.24,-63],[21.99,-57],[16.99,-40],[21.75,-18.5],[38.24,-3]],[[56.25,20.25],[43.74,44.24],[17.24,56.5],[-8.5,62.5],[-29.5,57.25]],[[73.75,57.75],[82.49,34.23],[76.98,28.24],[76.98,-15.75],[66.25,-28],[78.99,-37.5],[86.49,-53.5],[85,-71.25],[74.49,-88],[59.49,-86.75]],[[-32.5,-13.27],[-40.75,-10.5],[-24,-2.75],[2.99,2.24],[3.99,25.48],[-24.75,29],[-42,32.25],[-48.75,37.24]]];
path = [[[-44.5,-25.75],[-29.75,-20.75],[-7.5,-24.25],[-3.5,-36.75],[-4.5,-55.5],[-1,-60.75]],[[51.74,-77.75],[63.73,-68.5],[55,-56.5],[33.75,-45.5],[30.24,-34.5],[61.25,-12.75],[72.5,11.99]],[[-41.5,-79.75],[-67.25,-70.25],[-67.5,-49.5]],[[-29,5],[-23,16.75],[-40,14.74]]];
points = [[33.8,68.64,-27.96,11.55,17.58,-7.26],[-34.5,80.73,-21.25,-3.73,17.08,3],[-69.71,52.34,-0.42,-23.9,0.29,16.42],[-52.5,12.24,3.75,-5.99,-4.08,6.53],[-55.75,-23.75,4.9,-10.44,-4.52,9.64],[-64.01,-65.76,20.77,-23.18,-15.19,16.96],[-10.25,-72.01,28.16,3.18,-25.6,-2.89],[61.23,-72.76,9.29,12.52,-14.71,-19.83],[39.23,-54.25,-9.38,0.64,8.3,-0.57],[31.73,-27.5,0.22,6.51,-0.55,-16.42],[54.73,-16,9.99,-4.97,-8.57,4.26],[70.74,17.5,-1.62,24.32,1.73,-25.88]];
wancoXY = [-1.5,13.98];
break;
case 3:
name = "Mojaspeed";
roadSize = 30;
pathSize = 120;
cameraXY = [-63,-22.64];
gazeXY = [-50.8,10.99];
seatsXY = [-35.93,30.99];
lakes = [[3.63,2.03,19],[-44.55,-49.79,11],[76.15,-75.94,13],[-78.84,1.7,18],[30.25,-68,5]];
objectS = [[-6.16,35.63],[-13.78,27.96],[-10.25,32.63],[29.9,73.9],[24.25,74.44],[35.25,72.94],[-64.37,45.2],[-62.43,41.91],[-60.69,37.65],[-58.95,33.98]];
lamps = [[-40.36,15.97],[-39.97,9.77],[-39.59,1.64],[-39.97,-5.9],[-22.93,-37.08],[-24.1,-32.26],[-26.04,-26.66],[-28.16,-21.06],[44.04,-1.84],[41.92,-7.45],[39.2,-14.61],[36.11,-21.97],[87.8,39.59],[86.84,44.43],[86.06,48.5],[78.7,-57.01],[81.22,-51.01],[82.38,-44.43],[83.35,-36.88],[-63.01,-13.84],[-60.5,-6.67],[-51.01,-63.21],[-56.43,-59.53],[47.94,-86.03],[53.04,-83.96]];
trees = [[7.24,29.49],[11.5,-22.5],[3.75,-24.75],[-3.75,-24.25],[-9,-23.75],[-6.25,-29.5],[-2.5,25.5],[-12,22.75],[-10.25,-19.25],[-14.75,17.73],[1.49,31.25],[-6.5,-35.75],[-7,24.24],[-73,-88],[-80.25,-84.25],[-87.75,-74.25],[-87,-59.5],[-85.75,-44.5],[-83.25,-36.25],[-56.75,15.25],[-55.75,7.24],[-55.5,0],[-54.75,-8],[-57.75,-17.5],[-67.25,-23],[-61.5,-64.75],[-61.5,-58.25],[-57.5,-68.25],[16.98,-42.5],[31.99,-67.25],[37.99,-63.25],[44,-59.5],[49.24,-56],[53.5,-48.25],[54.49,-42],[71.25,-38.25],[71.75,-34.25],[75.23,-30.5],[72.25,-43.75],[61.99,-77],[57.98,-79.76],[65.29,59.84],[69.36,53.69],[54,65.23],[48.24,66.25],[39.75,67.73],[32.5,68.75],[24,70],[16.25,70],[8.24,70.5],[1.25,70.5],[-10.75,70.73],[-18,71.98],[-23.79,69.85],[-33.56,71.58],[-43.1,69.8],[-30.7,67.5],[-33.64,63.1],[-44.75,59.49],[-43,52.99],[-42.25,44.24],[-47.55,64.91],[-38.5,67.73],[-42.34,64.07],[10.25,35.74],[21.75,-37.5],[24.49,28.74],[32.99,28],[45.25,21.75],[46.49,7.75],[34.49,15.74],[70.41,45.6],[59.49,46.25],[47.75,50.25],[34.49,55.74],[20.25,62.25],[62.25,-82.25],[75.74,-59.75],[72.5,-62],[78.5,76.48],[71.98,82.25],[63.24,85],[-1.25,-80],[0.25,-67.75],[0.74,-55.75],[-33.75,-86.5],[-26.75,-84.25],[-21.25,-81.25],[-75,69.75],[-74.5,62.25],[-74.5,82.25],[-69.9,21.29],[-69.59,27.2],[-68.24,32.62],[-39.78,92.44],[-23.9,92.44],[-8.8,93.61],[-1.05,93.41],[8.61,93.61],[25.07,93.99],[37.85,93.22]];
checkPoints = [[-35.5,26.73,-80.25,24.49],[-30.5,9,-81.5,5.25],[-52.5,-42.25,-86,-39.75],[-57.75,-70.25,-69,-94],[-28.38,-56.37,-3,-88.62],[-26.62,-45,7.75,-47.75],[-35.75,0.5,29.49,-4.25],[6.24,64.24,15.99,30],[44.24,51.74,36.5,28.24],[75,20.99,50.74,18.24],[56.25,-23.25,22.5,-12.25],[28,-67,2.24,-66.75],[29.49,-70.75,24.25,-93],[33.5,-69.25,56.5,-91.25],[50,-31,90.24,-41.75],[71.75,14.25,92.23,12.75],[50.49,44,84.25,69.49],[26.99,53.75,30.49,91.25],[-16,54.75,-20.5,94.75],[-23.5,47.99,-69.25,87.25],[-35.75,39.49,-81.25,37.74]];
planes = [[[[10.6,-83.8],[22.45,-86.55]],5,0,".wonderfl",false,1,1],[[[34.23,-58],[41.48,-50.5]],5,0,".moja",false,1,1],[[[-64.76,-10.5],[-34.75,-19.75]],3,3,".title",true,1,1],[[[-67.5,85.48],[-72.25,75.72]],5,1,".flash",true,1,1],[[[-32,-23.75],[-27.75,-36]],5,1,".moja",true,2,1]];
fences = [[[-32,21.5],[-32.5,0],[-29.25,-15.25],[-35.25,-25.75],[-53.25,-35.5],[-63.25,-48.5],[-67,-62.5],[-61,-72.5],[-45,-73],[-25,-57],[-22.75,-44.75],[-31.98,-34.82]],[[30.12,-64.19],[30.25,-57.75],[46.25,-41.75],[60,-13.5],[71.75,8.24],[74.48,24.25],[70,38.74],[10,63.24],[-17.25,57.99],[-32,40.49]],[[2.24,-85.5],[4.49,-52.25],[8.49,-32.75],[21.74,-19.75],[32.75,10.25],[19,22.75],[14,29.98],[18.48,35.24],[47.75,27.24],[52.23,22.75],[52.5,15.25],[32.75,10.25]],[[-31.75,-88.75],[-67.5,-88.25],[-81,-80],[-83.5,-54.75],[-80.25,-16]],[[88.5,-34],[83.99,-22.25],[85.5,-9.5],[88,25.74],[82.25,56.25],[80.5,69.75],[68.5,79.75],[48.24,83.5],[24.25,89.75],[-2.25,88.24],[-27.25,88.24],[-55.25,88.24],[-66,80],[-70.5,66.25],[-67.5,51.5],[-70,36.74],[-77,19]],[[69.28,-86.5],[26.99,-90],[2.24,-85.5]],[[81.99,-64.75],[88.5,-34]],[[-31.75,-88.75],[2.23,-85.5]],[[-31.98,-34.82],[-29,-53.25],[-45,-73]]];
path = [[[-51.27,32.47],[-47,6.75],[-44.75,-8.75],[-69.75,-36],[-71.5,-79],[-38,-70.75],[-15,-61.75],[-16.25,-26.5],[-27.25,9.25],[-15.75,42.5],[6.75,53.5],[66.75,28.75],[31.99,-49.25],[8.8,-74.11],[30.71,-83.3],[60.5,-66.75],[64.54,-30.78],[78.23,-16.5],[82.31,20.99],[71.09,69.14],[17.49,79.06],[-60.25,78.5],[-63.25,60.5],[-52,34.99]]];
points = [[-51.51,49.67,2.56,-7.5,-2.22,6.51],[-48.88,16.42,2.37,-13.04,-2.54,13.96],[-56.75,-27,-6.02,-4.63,14.14,10.88],[-73.82,-66.58,1.5,-9.21,-2.77,16.97],[-36.47,-77.08,13.71,4.8,-24.89,-8.71],[-15.75,-36.14,-1.53,9.79,2.56,-16.38],[-23.76,17.75,0.17,14.2,0.52,-19.29],[14,51.25,13.89,-1.02,-17.51,1.29],[55.54,34.14,9.36,-6.37,-12.78,8.69],[49.44,-15.86,-4.23,-11.53,7.22,19.68],[20.19,-59.73,-10.87,-14.25,15.24,19.97],[49.69,-69.51,11.58,9.16,-21,-16.62],[72.63,-22.21,6.59,9.02,-10.99,-15.05],[80,24.82,-0.67,10.23,0.97,-14.85],[63.99,71.25,-7.47,3.59,14.84,-7.13],[9.66,79.03,-12.1,-1.5,19.47,2.42],[-52.51,75.06,-9.81,-5.4,16.94,9.31]];
wancoXY = [-56.25,-63.26];
break;
case 5:
name = "Hoge Town";
handicap = 0.95;
roadSize = 33;
pathSize = 15;
cameraXY = [-2.5,49.06];
gazeXY = [22.96,22.34];
seatsXY = [35.56,14.49];
lakes = [[0.73,-0.3,15]];
objectS = [[-29.56,-57.61],[-25.12,-59.03],[-20.28,-60.85],[-34.4,-56.4],[-69.83,29.92],[-65.08,31.53],[-73.98,27.24]];
objectL = [[-66.9,17.64],[-62.86,19.27],[-63.66,14.83],[-34.01,-50.43],[49.79,68.64],[48.36,67.89],[-1.1,-69.32],[0.89,-69.79],[-21.13,44.85],[-23.49,44.93],[-19,45.02]];
lamps = [[14,20.56],[13.64,26.69],[12.08,33.82],[3.32,42.54],[-3.54,42.84],[-10.07,43.1],[-21.5,83.99],[-10,84.25],[0,84.49],[-72.75,-62.25],[-68.5,-70.5],[-59.5,-75.75],[70.73,-24.25],[70,-17.5],[69.25,-10.25],[42.6,-6.38],[45.24,-17],[-32,-19],[-43.32,-17.5],[-34.5,-30.5],[-28.75,64.37],[-50.2,-77.65],[-5.72,-52.33],[58.45,31.68],[-82.55,21.62],[-78.49,28.38],[-83.49,11.84],[-22.73,6.48],[-26.88,10.8],[-30.85,14.95],[-35,18.93],[-39.33,23.59],[-34.15,-4.92],[-38.11,-0.6],[-41.57,4.07],[-45.72,8.21],[-50.91,13.23],[-72.69,33.1],[-65.94,35.85],[-59.02,36.21],[58.84,17.54],[8.36,38.99],[7.69,-40.01],[17.71,-37.6],[25.5,-35],[32.75,-32.58],[30.64,-26.35],[42.99,-22.95],[-43.25,-53],[9.49,-55.25],[28.5,-64],[36.5,-63.25],[44.49,-61.75],[21.5,84.49],[-2,69.25],[9,68.99],[20,68.5],[31,68.5],[-67.25,-19.5],[-72,-11.5],[-76.75,-3.75]];
trees = [[-3.32,-76.38],[1.27,-76.63],[-16.79,-61.28],[18.35,-64.75],[12.37,-60.45],[-13.09,-59.17],[42.23,-1.3],[24.92,-64.48],[32.39,-63.26],[40.06,-62.25],[47.5,-60.61],[53.04,-57.07],[56.09,-51.15],[65.02,-73.79],[71.74,-66.75],[73.95,-60.44],[75.38,-52.77],[29.97,-14.83],[27.14,-21.9],[21.5,-31.58],[13.01,-35.61],[1.91,-38.04],[-6.55,-37.43],[-16.04,-36.22],[12.73,12.55],[6.71,16.76],[-1.5,17.55],[-17.18,3.43],[-14.83,8.64],[-16.15,-3.46],[-51.35,63.06],[-51.15,55.8],[-47.09,50.55],[-42.65,45.91],[-51.55,74.77],[-44.7,81.03],[-43.49,85.47],[-34.6,86.88],[-25.93,88.5],[-15.64,86.68],[-4.33,88.09],[8.36,84.66],[17.25,86.68],[27.48,85.47],[-52.98,83.57],[73.06,86.25],[34.65,85.17],[58.93,81.18],[59.64,7.76],[58.43,24.31],[58.45,38.88],[63.1,52.14],[66.44,61.18],[63.47,-7.89],[67.09,-20.67],[70.74,-33],[-57.61,3.33],[-57.41,13.21],[-64.27,7.56],[-83.35,-5.8],[-79.62,-13.25],[-75.35,-19.9],[-70.85,-25.73],[-47.04,-51.14],[-39.45,-53.93],[-67.55,-32.04],[-64.27,-68.45],[-55.64,-72.28],[-47.52,-74.36],[-40.45,-77.19],[-33.19,-78],[-66.11,-49.27],[-65.34,-43.85],[35.34,29.64],[35,36.21],[34.31,43.99],[-68.75,55.25],[-79,50.49],[-80.25,44],[-88,37.75],[-92.25,22.75],[-92.25,7.5],[-89.25,-54.75],[-85,-67.75],[-81,-82.75],[-69,-91.25],[-57,-92.25],[-38.25,-93.75],[-24.75,-95.5],[-5.5,-94.5],[35,-93.75],[45,-94.25],[62.25,-92],[70,-86.25],[88.5,-79.25],[92.25,-68],[95.24,-50]];
checkPoints = [[35.23,9.25,7.49,8.75],[35.98,0.24,7.49,0.24],[8.24,-34,3.24,-11.75],[-28.5,-23,-8.75,-5.5],[-53.25,5,-27.75,28.5],[-58.75,6.75,-91.5,45.74],[-57.5,-1,-92.5,-26.75],[3,-47.25,-1.25,-98],[41.37,-42.81,65.5,-95.25],[48.87,-35.38,92.36,-33.5],[37.25,40.49,91.75,42.25],[42.25,61.99,78.99,96],[25.74,64.25,26.5,93.5],[-19.25,65,-20,91.99],[-20.75,65.74,-91.5,63.99],[-20.25,64.24,-37.75,32.75],[17.75,59,-27.25,20.99],[32.5,18.49,-20.5,17.75]];
planes = [[[[13,-30.57],[21.08,-26.95]],4,1,".moja",true,1,1],[[[99.23,-42.25],[80.13,-29.81],[78.86,-0.75],[70.04,5.89],[68.64,41.16],[76.66,51.35],[75.19,97.32]],8,0,"bldg",false,15,3]];
fences = [[[31,24.09],[30.44,39.61],[19.43,56.38],[4.25,63.24],[-22.5,63.99],[-22.75,67.25],[46.58,66.47],[39.49,45.74],[39.59,24.09]],[[30.97,4.73],[29.36,-8.38],[20.89,-23.72],[2.94,-31.8],[-18.86,-27.37],[-30.16,-15.23],[-50.7,8.38],[-60.64,9.48],[-60.64,-0.5],[-46.1,-23.7],[-47.32,-39.25],[6.35,-51.76],[45.74,-43.68],[52.98,-39.85],[46.32,-21.29]],[[-10.11,9.78],[-58.62,56.4],[-59.63,89.45]],[[-68.31,-63.51],[-21.24,-78.38],[-10.59,-77.19],[-2.27,-71.5],[1.11,-71.73],[7.77,-79.28],[20,-81.67],[51.86,-77.61],[67.7,-68.31],[72.14,-50.55],[70.94,-41.47],[62.26,-17.64],[55.6,8.57],[54.79,40.46],[66.7,72.34],[62.66,80.62]],[[-38.6,37.32],[-16.62,37.6]],[[-64.95,-37],[-63.84,-30.95],[-87.25,6.75]],[[89.22,-63.25],[73.5,-81],[54.49,-89],[21.99,-90.5],[-27,-90],[-64.25,-85.25],[-76.25,-79.25],[-83,-63.75],[-84.55,-42.85]],[[46.31,-21.29],[43.34,-36.73],[37.67,-45.32]],[[89.22,-63.25],[88.99,-35.25]],[[-59.64,89.44],[75.49,90]],[[-84.55,-42.85],[-64.96,-37]],[[-87.25,6.75],[-86.25,31.5],[-58.62,56.39]]];
path = [[[-46.08,-44.87],[-28.21,-50.06],[-12.95,-53.95]],[[-69.56,-56.44],[-77.69,-56.6],[-78.25,-64.25],[-73,-74.5],[-62.25,-81.5],[-25.25,-85.75],[21.5,-87],[53.75,-84],[69.25,-78.5],[77.73,-67],[81,-57.5],[79.73,-47.25],[76.48,-33.5],[74.98,-4.25],[66,3.49],[63.99,43.5],[72.23,54.24],[71.75,74.48],[66.25,85],[57.5,87.25],[49.75,85],[34.99,77.73]],[[50.74,-10],[38.75,-13],[35.25,-18],[39.24,-31.5],[36.74,-37],[7.75,-45.75],[-40,-35],[-36.75,-16.5]],[[-33.75,50.74],[-41.25,54.49],[-45,61.49],[-44.75,69.48],[-39.5,75.73],[-28.5,78.75]]];
points = [[22.41,-0.8,-0.58,-19.41,0.2,6.7],[-18.59,-11.47,-5.72,7.89,14.61,-20.17],[-53.81,25.67,-11.71,8.03,12.44,-8.53],[-73.97,5.21,7.46,-10.17,-8.66,11.81],[-54.1,-25.48,2.26,-3.25,-2.85,4.08],[-57,-57.18,5.54,-2.69,-3.42,1.66],[-21.1,-69.39,9.65,-2.87,-5.94,1.76],[0.56,-61.2,4.21,-0.19,-4.83,0.22],[19.77,-74.61,7.66,1.5,-8.32,-1.62],[49.36,-69.49,15.96,3.82,-9.44,-2.26],[63.47,-42.7,-2.87,7.86,2.59,-7.1],[50.29,-1,-3.31,15.34,2.88,-13.32],[47.79,45.96,18.92,35.99,-3.39,-6.45],[41.14,75.98,-13.69,0.84,11.18,-0.69],[-23.56,76.67,-19.2,0.95,14.16,-0.7],[-28.23,52.41,8.65,0.13,-17.12,-0.27],[3.66,52.31,22.99,0,-12.8,0]];
plants = [[-41.85,-12.97,0,4,1],[-40.55,-14.01,0,4,1],[-39.08,-13.04,0,3,1],[-38.88,-11.21,0,4,1],[-41.35,-10.86,0,4,1],[-42.26,-14.52,0,3,1],[-38,-12.22,0,3,1],[-41.18,-15.77,0,3,1],[-65.5,-53.75,0,3,1],[-66.12,-54.75,0,4,1],[-66.25,-56.12,0,3,1],[-66,-58.75,0,3,1],[-65.5,-57.13,0,4,1]];
wancoXY = [-40.5,-12.26];
break;
case 4:
name = "Hoge & Moja";
handicap = 0.93;
roadSize = 40;
pathSize = 132;
cameraXY = [69.06,29.37];
gazeXY = [82.23,7.1];
seatsXY = [43.13,-44.45];
objectS = [[23.54,7.96],[24.98,10.47],[25.87,13.15],[20.86,24.08],[23.01,22.45],[25.15,21.04]];
objectL = [[-66.87,-7.07],[-65.97,-4.38],[-65.25,-0.8],[59.16,-15.45],[57.21,-12.44],[55.94,-9.57],[66.34,-63.11],[68.67,-60.25],[62.35,49.49],[60.88,48.8],[63.81,50.22]];
lamps = [[-17.62,49],[-6,41.87],[1.99,54.36],[-10,61.24],[-19.25,46.62],[-20.25,50.49],[-8,39.24],[-3.5,40.74],[4.49,52.74],[3.75,56.99],[-8.25,63.36],[-12.38,62.87],[-83.16,-11.9],[-81.73,-6.53],[-80.3,-1.51],[-78.86,4.03],[-78.33,10.65],[-79.05,16.74],[-80.65,23.36],[-83.16,29.09],[-84.77,35.18],[-86.39,41.27],[-66.51,-28.91],[-61.67,-34.28],[-55.4,-36.79],[-48.96,-37.33],[-43.05,-36.79],[-37.32,-33.75],[17.28,-67.95],[20.82,-73.8],[26.77,-78.69],[32.68,-82.27],[38.95,-84.78],[44.85,-86.39],[50.39,-86.57],[56.85,-85.67],[62.76,-83.88],[68.84,-81.55],[74.22,-79.05],[77.98,-74.75],[82.45,-68.3],[78.34,19.42],[80.84,27.12],[77.98,-11.36],[81.74,-18.35],[40.25,79.94],[44.51,76.59],[49.35,74.98],[62.04,39.65],[63.65,44.49],[57.21,53.8]];
trees = [[7.61,-57.74],[5.82,-48.43],[7.79,-41.26],[5.28,-29.63],[6.71,-22.65],[6.71,-13.15],[10.65,-4.2],[12.26,5.28],[11.73,17.64],[8.5,23.9],[-5.1,31.78],[-1.87,26.59],[-9.57,22.83],[-17.09,17.45],[-19.6,10.65],[-17.99,-4.74],[-12.79,-11],[-8.31,-24.08],[-8.85,-36.97],[-13.51,-48.43],[-16.2,-54.7],[-23.71,-59.71],[-36.43,-65.8],[-47.89,-61.68],[-58.81,-65.44],[-70.27,-61.32],[-81.55,-57.74],[-86.92,-48.43],[-91.4,-35.9],[-91.94,-24.25],[-90.15,-12.79],[-92.47,-3.85],[-90.86,12.09],[-91.94,22.29],[-93.37,28.91],[-91.94,36.44],[-93.73,48.79],[-89.79,66.51],[-87.81,73.14],[-83.34,79.4],[-79.22,79.94],[-71.16,87.29],[-63.46,88.18],[-55.05,86.39],[-45.38,87.29],[-38.94,84.96],[-31.95,79.94],[-26.94,78.87],[-19.06,72.42],[-13.87,70.81],[-11.36,76.36],[-6.7,76.9],[-5.21,83.04],[2.7,87.84],[7.46,91.55],[21.34,94.26],[29.09,91.4],[34.11,89.44],[44.32,89.25],[48.61,86.03],[55.42,86.39],[65.09,84.78],[72.6,84.78],[76.01,81.74],[84.96,77.98],[88.72,69.38],[57.56,44.91],[51.65,50.25],[51.65,44.49],[56.1,38.01],[41.63,49.69],[13.7,54.69],[17.1,58.81],[21.75,53.8],[27.66,59.89],[-34.46,37.15],[-34.81,42.52],[-41.09,48.97],[-32.49,48.97],[-43.77,57.56],[-39.47,30.53],[-58.81,-22.29],[-52.72,-28.01],[-44.66,-24.44],[-48.42,-17.27],[-57.2,-14.4],[-52.9,-9.4]];
checkPoints = [[9.4,-39.84,41.67,-39.46],[9.4,-24.61,40.73,-24.8],[13.16,14.59,49.1,21.65],[7.25,27.66,22.11,48.06],[-41.26,55.77,-25.65,79.41],[-60.75,55.25,-85,74.01],[-59.65,24.56,-90.68,19.42],[-50.93,-30.88,-50.57,-66.87],[-40.01,-24.97,-9.75,-25.15],[-48.42,20.5,-21.05,4.22],[-6.89,75.11,15.67,59.89],[57.03,84.42,37.51,54.16],[91.23,-38.89,62.32,-43.17],[58.07,-91.09,53.24,-60.84],[9.65,-55.77,39.05,-55.02]];
planes = [[[[-10.35,29.9],[-28.81,41.69]],3,3,".title2",true,1,1],[[[-7.38,73.07],[11.9,60.45]],3,3,".title2",true,1,1],[[[17.82,49.49],[4.37,29.09]],3,3,".title",true,1,1],[[[-35.9,52.68],[-22.79,74.35]],3,3,".title",true,1,1],[[[-82.98,-37.15],[-75.34,-46.75],[-65.28,-52.18],[-54.18,-54.86],[-42.87,-54.51],[-31.45,-51.68],[-22.32,-44.89]],5,1,".moja",true,1,1],[[[81.43,-5.74],[72.64,3.26],[80.85,12.07]],5,1,".wonderfl",true,1,1]];
fences = [[[-23.81,43.24],[-26.45,52.2],[-46.2,62.75],[-57.56,62.04],[-65.89,54.79],[-67.5,42.61],[-54.4,0.61],[-23.82,43.23]],[[-54.4,0.61],[-64.46,-15.43],[-65.7,-23.27],[-61.95,-30.08],[-53,-34.1],[-42.52,-33.12],[-38.58,-27.57],[-39.75,-18.53],[-54.4,0.61]],[[30.25,37.33],[7.07,51.29],[7.04,58.1],[16.21,69.84],[26.5,70.05],[46.19,56.05],[46.37,41.52],[56.29,28.68],[51.53,9.45],[52.25,-11.43],[65.97,-39.61],[67.74,-53.45],[59.86,-63.85],[44.49,-66],[34.83,-57.83],[35.24,-28.45],[45.74,1.88],[44.84,18.75],[39.26,30.04],[30.25,37.32]],[[86.21,56.84],[88,-64.73],[75.97,-82.06],[51.41,-89.55],[28,-84.78],[13.02,-69.17],[12.12,-11.21],[18.54,5.19],[16.03,25.34],[-1.15,37.69],[-9.03,35.89],[-26.76,10.29],[-25.15,-1.95],[-15.55,-17.87],[-13.42,-34.68],[-20.94,-49.12],[-34.33,-56.64],[-57.04,-58.95],[-75.61,-53.02],[-87.78,-34.99],[-88.15,50.57],[-83.09,71.71],[-66.84,83.29],[-43.47,82.43],[-15.97,66.2],[-7.61,67.91],[-0.61,77.98],[10.64,87.53],[18.96,90.22],[67.79,78.55],[81.35,71.32],[86.21,56.84]]];
path = [[[73.24,43.24],[76.49,59.49],[69.25,66.49],[55.25,66.75]],[[-75.25,-12.25],[-67,3.75],[-69.75,15.99],[-75.25,30]],[[-72.5,62.74],[-56.25,71],[-46.75,68.99]],[[24.74,-14.25],[32.75,-6.25],[37.24,20.99]]];
points = [[24.29,-58.93,-0.03,26.74,0.02,-16.85],[35.22,12.74,7.8,11.03,-17.33,-24.5],[-41.25,69.74,-22.38,12.69,60.23,-34.15],[-69.5,65.49,-5.15,-7.86,6.44,9.83],[-73,27.23,9.54,-25.74,-7.76,20.93],[-72.75,-34.5,19.94,-14.25,-13.65,9.75],[-25.5,-35.75,8.55,12.98,-7.79,-11.84],[-37.75,9.24,7.19,10.55,-8.52,-12.5],[-2.1,60.23,13.61,22,-10.39,-16.79],[31.65,75.83,27.04,-23.69,-9.52,8.34],[73.69,46.81,-7.93,-24.33,11.77,36.1],[66.97,-16.75,11.37,-14.84,-16.55,21.61],[73.23,-68,-19.82,-18.69,12.61,11.89]];
wancoXY = [80.99,3.71];
break;
case 6:
name = "Hoge Circuit";
roadSize = 40;
pathSize = 32;
cameraXY = [57.07,45.64];
gazeXY = [92.72,65.97];
seatsXY = [84.07,-4.75];
lakes = [[0.24,-0.25,9]];
objectS = [[-56,14.02],[-51.96,4.34],[-47.32,0.9],[-41.46,-0.9],[-58.22,-18.66],[-57.05,-15.98]];
objectL = [[70,51.69],[72.8,61.83],[57.08,65.5],[-28.75,68.92],[71.11,20.28],[68.18,23.07],[64.61,25.78],[-60.07,-16.45],[-61.05,-17.85],[-59.63,-14.63]];
lamps = [[36.74,17.5],[42.25,17.5],[48.24,16.99],[54.49,15.74],[59.75,13.75],[50.49,-58.5],[50.74,-52.75],[50.25,-46.25],[49,-40.25],[49.24,-33],[50,-26.25],[-69.75,-41.5],[-88.25,-29],[-70.5,-29.5],[-54.75,44.24],[-72.25,48.24],[45.74,65.24],[45.25,82.25],[-82,14.74],[-65,11.99],[-87.25,-15],[-70.25,-17.25],[-88,-45.75],[-60,31.5],[52.75,65.24],[52.5,83],[15.5,41.99],[22.5,41.5],[29,40.74],[-53.25,29.75],[-55.75,24.24],[-49.75,35],[-53.75,-2.75],[-47.5,-6],[-41.75,-7],[-7,-9.5],[-11.25,-1.5],[-9,5.74],[-2.5,10.5],[6.5,8],[10,1.25],[8.24,-7.5],[0.99,-12]];
trees = [[-10.95,1.9],[-9.99,-6.2],[-2.94,-11.6],[4.87,-11.09],[10.59,-3.32],[10.13,5.14],[2.12,10.19],[-6.95,7.91],[54.39,-12.4],[53.79,-5.54],[54.39,3.33],[51.97,9.99],[65.69,57.21],[-31.58,20.69],[-62.25,-28.55],[-57.81,-25.73],[-59.02,-37.43],[-54.99,-31.38],[-43.89,-17.85],[-34,-14.02],[-67.9,-27.14],[-67.7,-5.75],[-65.89,4.13],[-63.66,15.64],[36.43,-64.27],[38.84,-67.5],[42.69,-61.65],[47.93,-62.66],[63.07,-80.42],[69.83,-65.4],[70.09,-56.05],[68.59,-46.96],[68.72,-37.64],[-31.17,62.86],[-36.82,63.87],[-38.85,59.43],[-45.5,59.03],[-48.53,50.75],[-66.7,67.91],[-70.73,57.62],[-75.56,42.48],[-79,25.73],[-84.65,9.59],[-87.08,-6.95],[-87.68,-20.48],[-88.67,-37.21],[-86.45,-63.45],[-78.2,-68.2],[-68.62,-69.76],[-57.45,-64.33],[-48.7,-56.36],[-41.32,-46.76],[-33.4,-37.03],[-24.71,-36.42],[-17.25,-38.85],[-9.77,-40.46],[26.25,-87.25],[16.99,-81],[13.49,-71.75],[8.49,-67.5],[5,-59.75],[2.5,-53],[-8.5,81.99],[2.24,83.5],[10.25,85],[16.99,85],[26.25,85.74],[84.49,32.5],[83.99,76.25],[-22.5,31.74],[-17,34]];
checkPoints = [[16.75,38.73,21.99,9.49],[48.24,35.99,51.74,11.5],[80.24,7.5,56.5,4.74],[73.24,-51.25,41.99,-53.5],[44.24,-91.75,39.24,-54.5],[12.75,-67.26,32.5,-54.5],[-9.25,-50.25,0.49,-16.25],[-76,-85.5,-55.75,-12.5],[-92.5,6.75,-58.25,0.99],[-86,62.25,-43.75,45.74],[-45.5,86,-35.25,51.5],[70,88.75,66.49,59.24],[92.25,52.75,68.5,56.25],[61.25,29.24,63.75,56.74],[-33,21.99,-51.25,43.5],[-33.5,19,-67.25,-3.25],[-29,22.75,-21.5,-14.75]];
planes = [[[[-16.01,-12.5],[-20.77,-38.54]],3,3,".title",true,1,1],[[[-74.5,35.73],[-82.5,33.99]],5,0,".moja",false,1,1],[[[-6.75,42.5],[-3,35.97]],5,1,".hoge",true,1,1],[[[80.73,34.23],[88,46.25],[88.73,60.74],[84.75,73.5]],4,1,".wonderfl",true,1,1],[[[-48.1,-17.27],[-51.28,-23.29]],4,1,".wonderfl",true,1,1]];
fences = [[[71.75,56.81],[66.7,63.47],[59.44,58.63],[64.68,51.96],[71.75,56.81]],[[59.44,58.62],[30.55,64.88],[-21.69,58.02],[-42.88,54.59],[-59.43,25.12],[-65.26,-10.39],[-48.72,-16.84],[-30.77,-9.18],[3.53,-20.88],[31.99,-58.82],[44.09,-56.6],[44.29,15.03],[32.99,14.83],[13.62,10.99],[17.45,-4.34],[3.53,-20.88]],[[-66.09,-17.05],[-51.98,-22.52],[-65.34,-43.52],[-66.09,-17.05]],[[87.01,30.93],[9.25,37.64],[-25.12,25.12],[-34.36,24.96],[-35.93,17.24],[-28.75,17.23],[-25.12,25.12]],[[76.91,7.03],[77.19,-25.06],[65.77,-33.83],[67.56,-69.81],[55.87,-84.97],[36.85,-87.64],[22.28,-78.84],[4.03,-46.19]],[[43.87,-26.37],[58.82,-15.25],[58.39,10.83],[44.29,15.03]],[[89.33,77.6],[57.01,85.87],[-14.22,77.4],[-26.26,86.41],[-61.09,78.57],[-78.94,67.92]],[[4.03,-46.19],[-36.25,-43.5],[-55.25,-69.25],[-77.25,-73.75],[-89.5,-65.5],[-89.25,13.75],[-86.5,34.75],[-79,67.48]],[[76.9,7.02],[87.01,30.93],[89.73,42.73],[89.32,77.6]]];
path = [[[58.5,-40.5],[61.25,-71.25],[52.74,-81.75],[37.74,-83.75],[26.24,-76.5],[12.75,-50.25]],[[-47.75,24.98],[-52.5,12.5],[-48.75,3.75],[-37.75,0.74],[-28.5,2.75],[-18.25,11.25]],[[-53,-47.75],[-65.76,-60],[-73.75,-58.25],[-79.75,-55],[-81,-45.25],[-78.5,-8.75]],[[83,63],[81.25,47.75],[76.48,41],[66,36.99],[52.25,40.25],[38.5,48.5]]];
points = [[-7.5,18.22,38.5,7.74,-7.38,-1.48],[67.91,13.33,0.98,-6.75,-2.69,18.46],[67.54,-20.75,-2.5,-1,3.62,1.45],[57.68,-30.15,0.75,-4.79,-0.5,3.26],[59.8,-63.46,0,-12,0,6.56],[23.69,-67.48,-3.45,5.52,13.84,-22.11],[1.48,-33.36,-7.5,6.24,5.16,-4.29],[-38.79,-26.07,-4,-4,7.19,7.19],[-62.16,-57,-5.42,-4.9,13.82,12.51],[-78,-11,1.14,6.18,-9.25,-49.8],[-53.98,70.33,1.16,2.59,-17.08,-37.87],[-27.79,77.53,4.4,0.72,-5.76,-0.95],[-13.89,67.44,4.22,0.86,-3.95,-0.8],[60.54,73.86,4.47,-0.56,-20.53,2.58],[81.49,62.6,2.24,-11.25,-1.2,6.05],[67.54,42.04,-12.92,-1.8,8.65,1.2],[30.49,51.32,-13.75,1.99,6.3,-0.91],[-23.7,44.43,-26.49,-16,13.23,7.99],[-43.94,6.03,13.74,-8.25,-12.26,7.36]];
wancoXY = [-81,38.97];
break;
case 7:
name = "Hoge Canyon";
handicap = 1.1;
roadSize = 40;
pathSize = 113;
cameraXY = [-72.53,15.29];
gazeXY = [-34.73,-0.71];
seatsXY = [32.99,17.22];
lakes = [[42.99,54,10],[83.99,21.5,9],[88.24,-37,10],[38.75,-11.75,12],[40.24,-50.5,10]];
objectL = [[18.24,-71],[18.24,-72.75],[18.24,-74.25],[38.75,-78.5],[38.5,-76.5],[-60.75,-74.25],[-60,-76.75]];
lamps = [[-43.5,66.25],[-38,67.24],[-32.75,66.75],[-26,64.25],[-18.25,62.5],[-10.75,61.99],[-4.25,61.49],[3.49,61.49],[12.5,61.99],[17.5,63],[-47.25,62.74],[-50.5,59.24],[-55.75,78],[-51.25,80.24],[-45.75,82.74],[-39,84.25],[-32.5,83.5],[-26,82.25],[-20.5,80.5],[-13.25,79.75],[-7.25,78],[-0.5,78.24],[5,78.75]];
trees = [[56.25,49],[79.23,78.75],[61,50.25],[63.49,55.25],[60.24,63.5],[54,62.74],[56.74,68.24],[47.99,68.5],[52.25,71],[41.99,72.25],[80.74,49.75],[81,58.24],[77.74,66.75],[77.74,72.25],[71,80.5],[65.74,85],[57.99,87.74],[73.24,86.25],[25.74,90.24],[9.74,89.25],[76.99,38.75],[71.99,29.24],[66.25,23.75],[67.74,16.99],[72.24,21.99],[73.75,16.5],[72.74,10.5],[76,6.25],[79.25,10.99],[47.25,10.25],[53.75,8],[48.5,19.25],[45.48,28.5],[49.99,29.24],[78.99,30],[51.5,37.99],[55,41.74],[82.25,44],[83.99,65.5],[59.99,-6.75],[31,64.75],[36.99,69.74],[63.49,-10.25],[57.74,-18],[61.49,-14],[57.24,-63.5],[58.5,-0.25],[83,-18.25],[83.75,-9.5],[81.25,-0.75],[80.74,-25],[73.24,-31.75],[67.99,-40.75],[69.25,-45],[71.25,-36],[73.24,-43],[76.25,-34.5],[48.75,-36.5],[49.75,-45.25],[84.49,-64.25],[41.99,-35],[48.5,-29.75],[48.5,0.99],[52.5,-21.75],[54,-12.75],[83.74,-73.75],[52.49,-55.75],[76,-48.5],[80.24,-58.5],[80.74,-48.5],[83.24,-53],[81.25,-63.25],[80.49,-74.25],[33.75,94.25],[46.74,95],[56.5,93.5],[15.74,86.75],[7.5,83.99],[21.99,62.74],[-14.5,46],[-6.25,46.74],[-3.5,42.25],[7.75,39],[13.49,33.75],[19.49,33.75],[24,29.24],[26.75,-2.5],[24,-10.25],[23.75,-20.75],[17.5,-23],[16.75,-29.75],[7.5,-30],[11.25,-34.75],[-18.25,23.24],[-24,19.25],[-35,51.74],[-91.75,-70.5],[-26.75,53.75],[-23.5,46],[-84.5,62.74],[-82.75,54.75],[-78.75,59.49],[-73.5,62.5],[-68.5,67.25],[-62.5,-85.25],[-68.5,-82.75],[-75,-77.25],[-78.5,-69.25],[-78.75,-90.26],[-83.25,-65.5],[-86.5,-82.75]];
checkPoints = [[4.49,88.24,7.24,43.5],[32.73,98.24,36.25,52.99],[92.25,59,49.74,55],[98.5,-44.25,43.75,-44.25],[37.25,-92.5,36.5,-53.25],[-49.75,-94.5,-48.5,-59],[-99.75,-47.25,-55.25,-47.75],[-60.25,-18.5,-50.75,-46.5],[0.5,3.75,29.75,-10.5],[-8.5,10.5,-0.75,52.5],[-38.5,-6.25,-55.5,19],[-88.25,14.25,-63.75,21.5],[-79.25,66.99,-60,41.74],[-12.75,92.74,-9.5,45.24]];
planes = [[[[-63.17,-107.33],[-55.84,-87.89],[-36.91,-79.09],[-19.35,-76.31],[-2.97,-81.31],[9.27,-86.22],[25.15,-78.78],[37.98,-81],[52.98,-84.75],[74.25,-83.48],[90.31,-101.07]],6,0,"rock",false,10,1],[[[-99,61.25],[-89.75,50.99],[-88.25,32.75],[-84,13.49],[-77.25,-6.5],[-58,-13.5],[-41.75,-5.5],[-29.75,7.24],[-21.75,16.75],[-5.75,20.5],[5.25,10.74],[3,-2.75],[-11.75,-13],[-32,-14.5],[-51.75,-19],[-69,-25.25],[-81,-37.75],[-84.25,-54.75],[-97.5,-64.75],[-115,-63.5]],6,0,"rock",false,10,1],[[[-63,12.24],[-68,26.99],[-65.75,42.5],[-51.5,51.49],[-38,45.73],[-47.25,33.24],[-49.5,18.24],[-63,12.24]],6,0,"rock",false,10,1],[[[-3.25,-35.5],[10,-46.75],[1.75,-60.76],[-11.5,-56.01],[-33.5,-55.75],[-48.75,-64.25],[-61.01,-58.25],[-57,-44.5],[-40.75,-39.75],[-23,-37],[-3.25,-35.5]],4,0,"rock",false,10,1]];
fences = [[[-90.75,52.99],[-60.25,79.75],[-37.5,88],[3,82.25],[34,90],[78.49,88.75],[88.75,64.75],[85.74,29.24]],[[85.24,13.24],[86.49,-28]],[[88.5,-47],[88.75,-71.5],[78.5,-88.5]],[[-57,-90.25],[-74,-86.25],[-85.5,-73.75],[-88.5,-58.25]],[[3.75,-41.5],[17.24,-39],[27.5,-31.5],[31.49,-21]],[[33.5,55.74],[13.24,48.24],[-13.25,51.99],[-38,45.74]],[[53.99,-61.25],[48.49,-56.25]],[[32.25,-45],[17.24,-39]],[[40.49,0],[40,45.49]]];
path = [[[68.5,-59.25],[53.99,-39.75],[75.24,-10.25],[53.49,22.24],[71.49,49.49]],[[-62,-75.25],[-73.5,-68],[-72.25,-51.25],[-68.25,-38],[-57,-33.25]],[[6.99,-15],[17.75,6.25],[13.24,25.25],[0.99,33.24]],[[-49.5,2.24],[-65.5,1.75],[-77.5,14]],[[-13.25,-73.25],[10.74,-63.76],[24,-62.25],[41.5,-67.51]],[[52.99,-72.5],[65.49,-69.75]]];
points = [[3.55,69.84,17.21,0.29,-23.41,-0.4],[38.74,81.99,6.93,3.15,-8.93,-4.05],[71.99,56.5,-0.5,-20.25,0.5,20.25],[57.24,22.24,-0.06,-11.6,0.04,7.95],[72.98,-11.75,0,-8.02,-0.01,11.41],[58.48,-40,-0.41,-10.25,0.43,10.65],[61.72,-75.39,-9.33,-3.15,18.71,6.33],[17.17,-72.28,-12.43,-6.29,22.64,11.47],[-43.91,-71.53,-15.17,-9.54,24.55,15.44],[-71.5,-57.25,-7.87,27.59,5.16,-18.09],[-27,-26.25,26.49,6.77,-15.42,-3.94],[13.24,-5.5,14.51,22.31,-14.86,-22.84],[-17,34.24,-28.65,9.67,39.92,-13.47],[-44.77,5.49,-27,-18.01,17.02,11.36],[-77.75,23.49,-3.71,11.45,7.73,-23.82],[-65.75,55.73,16.58,9.21,-10.96,-6.09],[-34.75,75.24,6.04,0.44,-25.99,-1.9]];
plants = [[72.98,-87.25,6.1,30,0],[65.49,-87.5,6.1,30,0],[55.73,-88.25,6.1,30,0],[77.73,-93.5,6.1,30,0],[46.49,-87.25,6.1,30,0],[37.99,-85.5,6.1,30,0],[29.49,-84,6.1,30,0],[20.5,-86.75,6.1,30,0],[12.75,-90.5,6.1,30,0],[4,-89.25,6.1,30,0],[-4.5,-86,6.1,30,0],[-13,-83,6.1,30,0],[-22.25,-81.75,6.1,30,0],[-31,-84,6.1,30,0],[-40,-86,6.1,30,0],[-48.25,-88.5,6.1,30,0],[-54,-94.25,6.1,30,0],[-1.25,-0.25,6.1,30,0],[0.5,9.74,6.1,30,0],[-6.75,15.5,6.1,30,0],[-20.75,11.99,6.1,30,0],[-22.25,-0.75,6.29,30,0],[-12,-8.25,6.1,30,0],[-21,-10,6.1,30,0],[-28,2.24,6.1,30,0],[-42.75,-10.5,6.1,30,0],[-52.25,-16.75,6.1,30,0],[-63.5,-15.5,6.1,30,0],[-70,-22.5,6.1,30,0],[-73.75,-15.25,6.1,30,0],[-79,-20.5,6.29,30,0],[-76,-28.25,6.1,30,0],[-85,-33.5,6.1,30,0],[-85,-43.25,6.1,30,0],[-87.5,-53.25,6.1,30,0],[-82.75,-8,6.1,30,0],[-85.25,1.5,6.1,30,0],[-84.75,-17.75,6.29,30,0],[-87.5,11.75,6.1,30,0],[-90,23.24,6.1,30,0],[-93,37.99,6.1,30,0],[-94.25,49,6.1,30,0],[-12.5,10.5,6.29,30,0],[-30,-8,6.1,30,0],[-89.5,-6,6.1,30,0],[-85.75,-26,6.1,30,0],[-96.75,-59.25,6.1,30,0],[-92.25,-49.25,6.29,30,0],[-91.25,5.74,6.29,30,0],[-95.75,28.5,6.29,30,0],[-97.75,42.25,6.29,30,0],[-9.5,0,6.29,30,0],[-89.75,-37.25,6.29,30,0],[-61,17.24,6.1,30,0],[-52.5,21.25,6.1,30,0],[-42.75,44.24,6.1,30,0],[-49.25,35.49,6.1,30,0],[-64,25.99,6.1,30,0],[-63,36.25,6.1,30,0],[-52.75,47.24,5.09,30,0],[-57.25,25.99,6.29,30,0],[-55.25,39.24,6.29,30,0],[-0.75,-53.75,4.09,30,0],[-4.5,-41.5,4.09,30,0],[4.49,-47.75,4.09,30,0],[-10.25,-51,4.09,30,0],[-14.75,-40.75,4.09,30,0],[-21,-50.5,4.09,30,0],[-26,-41.25,4.09,30,0],[-30.5,-50.25,4.09,30,0],[-38,-42.5,4.09,30,0],[-42.75,-56.25,4.09,30,0],[-56.75,-57,4.09,30,0],[-49.25,-51.75,4.09,30,0],[-53.5,-47,4.09,30,0],[-44,-46,4.09,30,0]];
wancoXY = [9.74,-42.54];
break;
case 8:
name = "Moja Racers";
handicap = 0.92;
enemiesNum = 14;
roadSize = 45;
pathSize = 18;
cameraXY = [-59.39,3.33];
gazeXY = [-36.05,-32.68];
seatsXY = [-37.68,-16.25];
lakes = [[4.74,-35.75,12],[31.25,43.24,10],[79.49,-65.5,10],[-72.25,-73,10],[-34,42.99,10]];
objectS = [[57.75,42.25],[57.75,37.99],[57.75,32.25],[59,27.75],[61.49,23.49],[68.75,39.49],[68.5,34.49],[70,30.25],[72.5,25.99]];
objectL = [[-29.75,-81.75],[-27,-84],[-23.75,-85],[-19.75,-84.5],[-15.5,-84.75],[44.75,-66.75],[47.99,-64.75],[52.25,-61.75],[56,-57.75],[-62.5,76],[-59.25,79.49],[-55.5,81.25]];
lamps = [[-42,-29.75],[-42.25,-33.75],[-42,-38],[-41,-40.75],[4.74,-62.5],[-5.5,-66.75],[-0.25,-64.5],[-57.5,-42],[-58.75,-36.25],[-59.5,-30.5],[-60,-24.25],[-60.5,-17.5],[-61,-12],[-61,-7],[-61,-1.25],[10.25,-60.25],[-26.25,-65],[-23.5,-67.25],[-35.5,-80.25],[-37.5,-77.75],[-40.5,-75]];
trees = [[-79.25,38.75],[-79.25,43.75],[-78.5,48.75],[-79,54.49],[-78.5,60.74],[-77.5,66.49],[-77.5,70.24],[-47.75,58.5],[-48.75,53.24],[-48.75,47.5],[-49,41.25],[-49.25,34],[-45.75,28],[-80.25,32.5],[-77.25,26.25],[-76,19.74],[27.5,-53],[32.75,-50.5],[38.24,-48],[42.99,-44.5],[53.75,-31.5],[55.74,-27.5],[60.5,-19.5],[61.24,-14],[63.5,-62.5],[67.74,-57.5],[72.74,-51.75],[76.99,-45],[78.99,-38.25],[80.5,-32],[81,-25.75],[81.49,-20.25],[83.5,-16.25],[41.25,-39.25],[39,-36.5],[45.25,-28.75],[49,-30.5],[-8.25,-43.25],[-3.25,-49],[5.74,-51],[-7.5,-24.5],[0,-20.75],[39.75,32.5],[43.75,37.25],[44.24,45.25],[16.75,46.74],[20.74,52.75],[-27.5,30.25],[-21.25,33.75],[-19.75,40.74],[-56.25,-78.25],[-55,-70.5],[-59.25,-61.75],[-67.75,-58],[-76.25,-58]];
checkPoints = [[-17.5,-12.25,-73,-12.5],[-15.25,-34.5,-73.25,-35.5],[-13.5,-46.75,-54.5,-91.75],[-0.5,-56.75,8.75,-92.25],[26.25,-43.5,58.75,-76.25],[43.5,-14.25,91,-26.75],[41.5,23.75,93,39.24],[34.24,46.25,59.49,90.74],[11.99,47.99,6.99,85.74],[-32,53.5,-23,86],[-44,54.49,-66.75,88.75],[-46,41.5,-85.25,41.5],[-15,5.25,-79.25,6.75]];
planes = [[[[86.49,8.75],[56.99,8.24]],3,3,".title2",true,1,1],[[[-33.75,-29.75],[-68.25,-30.5]],3,3,".title",true,1,1],[[[-68,-3.5],[-33.5,-3.5]],3,3,".title",true,1,1],[[[-34.25,82.74],[-45,86.49],[-56.5,84.49],[-66.25,80.5],[-71.25,71.25],[-72.75,61.75]],5,1,".wonderfl",true,1,1],[[[63,68.49],[57.23,75.74],[51,80.5],[44.49,84.25],[35.98,85.74]],5,1,".flash",true,1,1]];
fences = [[[-18.75,-37],[-28.25,-58],[-18.5,-66.25],[-11.5,-66],[8,-57.5],[32.99,-46.5]],[[55.73,-22],[60.5,-7.25],[61.98,12.5],[56.24,17.5],[51.74,28.49],[52.98,50.48],[34.74,64.97],[-6.5,53.74],[-20,53.99],[-44.5,64.72],[-52,59.23],[-53,31.74],[-47,23.24],[-19.25,4.99],[-18.76,-37]],[[-62.01,-38.5],[-56,-60.75],[-31.75,-88.25],[-13,-89],[12.24,-79.75],[53.74,-70.25],[73.99,-42.75],[84.75,-0.5],[81.75,25],[73.99,35.23],[75.24,57.99],[57.49,85.24],[34.73,89.74],[-5,79.25],[-17.5,79.49],[-44.75,90.49],[-68.26,85.24],[-75.25,73.48],[-76.5,30.99],[-71.5,15],[-63.5,2.24],[-62.01,-38.5]],[[32.99,-46.5],[29.24,-35.75],[43.75,-21.75],[55.73,-22]]];
path = [[[-54.75,17.75],[-27.25,-0.75],[-27,-32.75],[-37,-43.75],[-37,-65.25]],[[56.24,-43],[43.24,-33.75]]];
points = [[-51.44,-10.86,-0.15,-31.51,0.24,49.95],[-35,-68.5,9.94,-12.81,-15.43,19.89],[-2.75,-75,26.26,14.81,-11.65,-6.57],[55.73,-50,20.97,27.13,-17,-22],[69.73,22.24,-20.05,19.14,7.15,-6.83],[45.98,73.98,-12.54,11.65,37.75,-35.06],[-17.75,66.25,-11.24,3.26,18.38,-5.33],[-64.25,57.5,-7.25,-60.25,4.53,37.68]];
wancoXY = [39.74,-30.02];
break;
case 9:
name = "Moja Forest";
handicap = 0.94;
roadSize = 45;
pathSize = 30;
cameraXY = [67.85,24.59];
gazeXY = [83.6,5.83];
seatsXY = [85.72,19.47];
objectS = [[65.37,14.87],[65.24,16.99],[65.12,19.37],[65.12,21.62],[76.62,15],[76.62,17.12],[76.25,19.37],[76.12,21.75],[-75.09,17.85],[-73.34,15.53],[-71.59,13.13],[-10.05,-56.08],[-10.28,-52.63],[-9.42,-59.1]];
lamps = [[-37.25,64.49],[-30.75,64.25],[-22,65.24],[-15.75,65.5],[-8.25,65],[0.5,65],[8,65],[14.25,63.99],[-41.25,85],[-34.25,85.74],[-28.75,85.74],[-22,86.25],[-16.5,86.49],[-10.25,85.74],[-4.5,85.5],[3,85.24],[10.5,85.74],[15.99,85]];
trees = [[-78,17.5],[-80.5,21.75],[-83,26.25],[-84.75,31.5],[-87,36.74],[-88,41.74],[-66,1.99],[-60.25,-2.5],[-53.75,-5.25],[-48.25,-6.25],[-1.5,4.49],[-5.5,4.99],[-84.25,-42.75],[-81.5,-32.75],[-82.75,-27.75],[-83.25,-21.25],[-13.25,-61],[-11.5,-69],[-9,-74],[-5.5,-77.25],[-1.75,-81],[5,-82],[11.5,-82.5],[-10.25,-39.25],[-10.25,-35.25],[-7.25,-31.25],[-3.75,-27.75],[22.75,61.99],[30.25,58.5],[36.74,55.25],[42.75,51.5],[48.49,45.99],[54.49,42.5],[25.25,82.74],[32.24,78.75],[40.74,75],[47.75,70.24],[54.75,66.25],[61.25,63.99],[67.74,59.75],[72.5,54.24],[58.24,35.74],[-42.25,61.99],[-47.5,61],[-52.75,61],[-58,58.75],[-64,55.49],[-65.75,50.74],[-50.5,85],[-58.25,84.25],[-64.25,82.25],[-69.75,81.25],[-72,78.24],[-75.25,76.75],[-80,71],[-84.75,68.5],[-86,64.75],[-87.75,60.74],[55.74,-87.5],[65.24,-86.25],[68.74,-71.25],[72.49,-68],[76,-60.75],[79.24,-56.25],[82.5,-51.75],[88,-48.5],[-25.75,-70],[-31.5,-80.5],[-37,-83],[-40,-87.75],[-49.75,-87.75],[-77.25,-88],[-84.5,-84.75],[-90.25,-75.5],[-92,-64.5],[-94,-56.75],[-93.75,-44.5],[60.74,-26],[56.74,-29.25],[64.49,-23.75],[45.74,-42.75],[44.24,-48.5],[-31,19.25],[-22.5,24],[-17.5,28.75],[-7.75,29.75],[-1.75,32.75],[6.25,32.75],[11.99,25.5],[23.75,19.74],[19,16.5],[27.5,14.49],[30,7.5],[32.75,0.25],[36.25,-8],[33.24,13.49],[34,-20.5],[30.25,-26.75],[19,25.5],[-58.75,-50.5],[-55.75,-44.5],[-50,-40],[-43,-35.75],[-15.5,-28],[-12.5,-19],[-18.25,-8],[-26.75,-11.75],[-35.25,-13.5],[-44.25,-13.5],[-57.5,-13.5],[-49.75,-16],[1.75,-13],[-45.5,22.75],[-52.75,24.74],[-59.5,33.75],[-61.5,41.25],[-52,32.25],[-33.75,-66],[-15.25,-39.5],[-81.5,18.24],[-61.76,2.24],[-20.26,-60],[67.74,-78.75],[68.99,-54],[-26,-60.75],[59.49,-3.5],[62.74,-13],[65.24,-18.75],[37.99,-62],[40.25,-58.25],[32.25,-62.25],[23.24,-59.75],[17.24,-58.75],[15,-55.75],[13.24,-47.5],[18.49,-42.75],[-20.25,-37.25],[-13.25,-46],[-78.12,12.24],[-69.5,5.99],[-85.75,-50.75],[-85.75,-57.25],[-85.5,-62.75],[-43,-74.25],[-39.5,-68.5],[-66,-43.25],[-64.75,-39],[-64.5,-31.25],[-65,-24],[-66,-18],[-81.5,-14.5],[-83.5,-8.25],[-83.25,0]];
checkPoints = [[-6.75,57.25,-7.5,93.73],[-29.25,57.74,-30.75,93.24],[-57,48.49,-92.75,88.5],[-61.75,37.75,-94.75,32.25],[-46.75,19,-97.5,-62.25],[26.99,38.24,-90.5,-91.5],[11.25,-55.75,-17.25,-68.5],[29.49,-58.75,24.25,-96],[40.74,-36.25,96.75,-80],[51.5,-12.5,94.75,-6.75],[39.49,30.74,70.24,78.75],[15,54.99,15,93.75]];
planes = [[[[-26.5,88.49],[-26,63.23]],3,3,".title",true,1,1],[[[59.23,66.49],[44.74,45.74]],3,3,".title2",true,1,1],[[[-82.25,-70.75],[-78,-76],[-70.5,-79.25],[-63.75,-80.25],[-57.25,-79.5],[-50.75,-76.75]],5,1,".wonderfl",true,1,1],[[[-87.5,57.74],[-87.5,46]],6,1,".moja",true,1,1],[[[1.5,0.25],[19.25,19]],3,3,".flash",true,5,1],[[[83.99,-1.25],[60.5,-9]],3,3,".hoge",true,4,1],[[[34.24,-85.5],[41.74,-85.5],[47.5,-83.5],[53.5,-80.25],[59.49,-76.75],[63.99,-71.5]],5,1,".moja",true,1,1],[[[-78.45,8.84],[-69.9,2.99]],5,1,".moja",true,1,1],[[[-15.83,-47.3],[-15.57,-57.55]],5,1,".moja",true,1,1]];
fences = [[[-64.75,34.75],[-65.25,44.49],[-57.75,52.99],[-35.5,59.75],[-10,60.74],[18,57.25],[50,28.99],[54.49,-3.25],[60.49,-19.25],[51.25,-30.75],[39.49,-44.75],[44.24,-59.75],[39,-65.75],[15.5,-61],[6.99,-57.5],[10,-51.5],[9.24,-44],[20.25,-37],[29.49,-37.5],[37.75,-23],[39.49,-6.75],[35.74,21.25],[23.24,38.74],[3.24,44.99],[-17,41],[-35.75,30.99],[-39.25,18.24],[-47,14.25],[-54.75,19.25],[-64.76,34.75]],[[41.5,-88.75],[61.75,-83],[72.49,-57.5],[88.5,-38.75],[88.24,-4.5],[80,7.24],[80.24,41.5],[72.5,62.74],[50.74,78],[23.75,89.75],[-36.75,89.73],[-62,87.25],[-77,82.5],[-89.75,68.99],[-89.5,38.5],[-84.75,20.25],[-89.75,3.24],[-90,-20.75],[-89,-58.25],[-84.25,-80.25],[-63.75,-88.5],[-47.25,-83],[-34.75,-76],[-26.75,-64.75],[-16.51,-64.01],[-13.25,-79.25],[-2.75,-89.25],[20.5,-86],[41.5,-88.75]],[[-64,-3.75],[-48,-9.5],[-26,-6.75],[-9.75,3],[-1,0.99],[6.5,-8.75],[6.5,-16.02],[-9,-28],[-14.5,-34],[-17.75,-32],[-34.5,-34],[-49.25,-44.25],[-55.75,-56],[-61,-56.25],[-63.75,-51.5],[-60.5,-40],[-42,-30.75],[-20.25,-25.5],[-17.25,-14.5]],[[-17.25,-14.5],[-45,-22.25],[-63,-19.75],[-64,-3.75]]];
path = [[[-73.76,0.74],[-73.75,-24.5],[-72.76,-36.75],[-77.25,-50.25],[-77.75,-59],[-75.75,-67.75],[-67,-73],[-55,-72],[-48,-67.25],[-44.75,-58.5],[-37.75,-53.25],[-29,-48.25],[-20,-50.25]],[[-22.25,-20.5],[-42,-25.5],[-57.75,-27.25]],[[-45.5,-60.75],[-60.25,-68.5],[-71.5,-64],[-74.25,-44.5]],[[68.75,3.75],[61.25,9.49],[60.49,26.99],[68.24,31.98]]];
points = [[-76.56,33.73,2.84,-7.71,-6.73,18.29],[-53.07,5.85,15.5,-5.45,-12.1,4.25],[-22.25,10.24,16.24,10.25,-9.9,-6.24],[10.74,8.24,2.8,-4.58,-10.55,17.25],[17.75,-10.75,2.56,-14.88,-0.94,5.47],[-1.75,-40.75,-3.55,-10.01,3.74,10.56],[-0.5,-66.03,8.3,-9.5,-5.44,6.23],[26.5,-73.25,6.06,-3.58,-10.85,6.4],[50.48,-72.25,14.18,9.37,-11.35,-7.5],[54.23,-54.26,0.41,19.77,-0.12,-5.73],[77.23,-34.5,8.81,19.86,-5.16,-11.64],[71.73,2.73,0.23,10.27,-0.2,-8.93],[71.23,37.23,0.31,11.1,-0.23,-8.12],[18.49,75.49,-5.96,0.83,7.1,-0.99],[-35,74.98,-44.65,-0.81,23.2,0.42]];
wancoXY = [-25.26,-21.53];
break;
case 10:
name = "Moja Moja Road";
lapsNum = 2;
handicap = 1.1;
roadSize = 45;
pathSize = 106;
cameraXY = [29.16,-21];
gazeXY = [7.19,1.19];
seatsXY = [73.73,4.48];
objectS = [[84.49,51],[83.99,46.99],[83,42.75],[84.25,54.49],[27.62,49.87],[30.87,50.99],[31.74,68.12],[26.36,65.37],[29,66.37],[23.86,64.37],[33.75,52.36],[36.62,53.75],[-44.62,70.62],[-40.75,69.25],[-36.75,67.74]];
lamps = [[-42.75,-57],[-38.25,-52.75],[-35.5,-47.5],[-33.25,-41.5],[-31.25,-34.5],[-30,-28],[-29.75,-21],[-29.75,-14],[-31.25,-8],[-33.25,-2.25],[-35.25,4],[-36.5,10.5],[-37.75,15.99],[-40.75,20],[52.75,-12.75],[50.74,-7],[49.49,6.5],[49.49,10.99],[-72.75,43.5],[-72.25,49],[-70,53.75],[-65.75,55.74],[-61.25,56.74],[-57.5,56.25],[-84.25,-3],[-83.5,2.75],[-85,19.25],[-86.25,24.49],[69.75,-56.25],[69.49,-51.5],[68.24,-46.5]];
trees = [[-4.5,-52],[0,-55.25],[0.74,-50.5],[9.25,-44.25],[28.75,-46.25],[32.5,-51.5],[38.24,-49.5],[43.24,-46.5],[4.49,-48],[45,-42],[-6,40.74],[0.99,42.5],[8.49,41.25],[14,43.75],[19.74,43.5],[22.75,33.5],[40.49,50.49],[42.25,55.25],[34.75,73.99],[24.74,46],[31,77.49],[27.24,82.24],[12.5,64.25],[5.74,63.24],[-2.25,62.5],[-7.25,62.5],[-13.5,61.75],[-17.75,63.24],[-22.5,65.74],[-29.5,66.49],[-10.75,41.49],[35.74,80.24],[63.24,86.25],[74.75,85],[78.5,81.25],[82.74,77.74],[89.75,69.25],[49.49,-3],[49.24,1.99],[70.74,-9],[73.75,-15.25],[77.5,-21],[81,-27.75],[84.25,-32.75],[70.74,18.24],[73.75,21.25],[76,25.5],[79.25,28.5],[83,32.75],[88.24,-40.5],[-8.75,-92.5],[-16,-93.75],[-26.25,-91],[-38,-91.75],[-48,-91.25],[-57.75,-86.25],[-65.5,-82.75],[-71.75,-76.75],[-73.75,-66.75],[88.5,-45.75],[89.75,-54.5]];
checkPoints = [[91.75,5.5,33.48,1.99],[93.49,-38,61.49,-40.25],[67.25,-95.5,56.5,-60],[-31.5,-94.25,-30,-71.25],[-73.5,-69.5,-46.25,-65.25],[-52.75,3.24,-30.5,8.49],[-46,36.74,-33,13.24],[-17.75,29.49,-28.75,10.25],[9.49,-13.25,-14.75,-12.5],[-9.25,-50.5,-35.75,-57.75],[16.25,-38.25,22.5,-75],[35.99,-42,63.75,-62],[30.25,-38,47.5,-16],[-33.25,30,-28.75,49.24],[-50,30.74,-66.5,51],[-51.25,18,-70.75,13],[-47.25,-39.25,-65,-27.5],[-87,-46.5,-71.25,-28],[-89.75,-16.75,-69.25,-19.5],[-88.25,66,-62.25,50],[-41.25,92.25,-42.25,49.49],[4.25,91.99,39,3.24],[23.49,91,49,61.25],[78.99,92.74,60.24,56.99],[92.74,65.74,65,52.99],[91.73,36.48,49.23,34]];
planes = [[[[20.99,-29.5],[16.5,-9.5],[6.5,9.25],[-7.75,22.24],[-27.5,33.49],[-50.5,35.49]],6,1,".wonderfl",true,1,1],[[[-53.25,74.23],[-66.26,73.99],[-77,71],[-84.25,64.49],[-89.25,54.75]],6,1,".moja",true,1,1],[[[47.48,-84.75],[50.23,-91.5]],5,1,".flash",true,1,1],[[[26.75,-87.25],[29.24,-93.75]],5,1,".wonderfl",true,1,1],[[[5,-90.75],[7.24,-96.75]],5,1,".moja",true,1,1],[[[-63.75,-17.75],[-26.25,-8.5]],3,3,".title",true,1,1],[[[-86.75,5.74],[-92.5,0.25]],5,1,".moja",true,1,1]];
fences = [[[-26.25,-73],[-4.5,-74],[46.49,-67],[63.75,-58.25],[65.24,-40.5],[54.24,-19.25],[39,-15],[32.48,-0.75],[50.49,14.74],[53.24,29.24],[68.5,48.5],[70,56.5],[55,67.74],[50.74,63.99],[43.75,46.25],[47.74,31.49],[53.24,29.24]],[[32.48,-0.75],[5.99,25.74],[-21,45.74],[-45.25,53.75],[-59.5,53.74],[-69,46.24],[-71.25,31.74],[-66.5,3],[-71.5,-17.75],[-72.5,-29.75],[-62.5,-30.5],[-60.5,-19.75],[-66.5,3]],[[4,9.74],[8.75,-8.25],[3.49,-29.75],[-12.5,-47.5],[-10,-53.75],[6.5,-40.25],[22.24,-39.75],[36.74,-43.75],[41.25,-38.25],[23,-28.75],[16.25,-5.25],[4,9.74],[-16.25,27.5],[-41.5,36],[-52.5,32.5],[-56.25,21.5],[-46,-10.5],[-45,-31.75],[-56,-47.25],[-81,-68.25],[-77.5,-84],[-59.5,-90.75],[0.99,-89.25],[72.5,-78.5],[87.23,-67.5],[86,-42.25],[66.99,-9],[66.25,18.24],[85.74,39.24],[89.49,55.49],[81.25,74.24],[51.24,88.99],[37.98,82.49],[30.49,89.24]],[[-26.25,-73],[-35,-54.75],[-28.25,-32.5],[-11.25,-15.5],[-15.25,2.75],[-35.5,17.5],[-26.75,-13.75],[-28.25,-32.5]],[[-26.25,-73],[-47.5,-68.75],[-49.75,-63.25],[-35,-54.75]],[[-56,-47.25],[-68,-52.5],[-84,-48],[-90.75,-33],[-84.5,5.99],[-91,43.24],[-89.5,67.5],[-71.51,84.24],[-45.75,84.49],[-35.25,88.99]],[[-35.25,88.99],[30.49,89.24]]];
path = [[[-47.25,72.24],[-25.25,80.74],[-5,77.48],[13.24,80.24],[30,70.74],[34.24,40.74],[26.99,18.49],[34.49,13.49],[42.25,24.25]],[[4.49,-59.5],[16.75,-47.25],[32.5,-58]],[[-38.75,-82.25],[-69.25,-74.25],[-66.5,-60.5]]];
points = [[52.75,-35.25,-5.51,6.01,20.95,-22.85],[26.99,-18.25,-2.11,25.75,0.77,-9.47],[-22.75,38.48,-30.05,13.84,14.97,-6.89],[-59.76,11.75,11.92,-25.35,-10.99,23.36],[-70,-42.75,-17.84,1.6,25.64,-2.31],[-75.5,-2.5,6.5,19.25,-6.5,-19.25],[-70,64.23,13.61,6.27,-27.53,-12.68],[-11.25,50.98,5.55,-1.1,-11.84,2.34],[22.99,56,21.06,4.37,-6.9,-1.43],[51.74,80.49,20.04,-10.91,-5.5,3],[78.99,46.74,-5.24,-11.74,5.24,11.74],[60,18.75,-1,-5.99,1,5.99],[60.5,-6.5,0.5,-17.42,-0.26,8.91],[66.25,-70.25,-44.49,-10.79,33.99,8.24],[-48.25,-78.5,-30.62,15.34,16.25,-8.14],[-45,-46.75,24.99,34.99,-10.26,-14.37],[-45,29.48,30.31,1.94,-19.21,-1.23],[-11.25,-31.5,-14.97,-9.09,33.74,20.49],[-10,-65.25,42.49,0.75,-26.02,-0.45]];
wancoXY = [15.74,28.72];
break;
}
}
public function setPlace(type:int):void {
place = type;
switch(type) {
case CIRCUIT:
fenceMap = Dot.moja;
dirtFriction = 0.02;
roadColor = pathColor = 0x505050;
lineColor = 0xffffff;
dirtColor = 0x73900b;
edgeColor = 0xd9c364;
particleColors = [0x6d8a15, 0xb6e034];
break;
case FOREST:
dirtFriction = 0.025;
fenceMapSize = 4;
fenceHeight = 2;
fenceMap = Dot.grass;
edgeColor = 0xA47B4E;
dirtColor = 0x5A6130;
roadColor = pathColor = lineColor = 0xC0AE57;
particleColors = [0x6d8a15, 0xb6e034];
break;
case SNOWFIELD:
dirtFriction = 0.03;
fenceMapSize = 2;
fenceHeight = 1;
fenceMap = Dot.brick;
dirtColor = 0xeaeaea;
edgeColor = 0xd9c364;
roadColor = pathColor = lineColor = 0x877B49;
particleColors = [0xF2F2F2, 0xFFFFFF];
break;
case WINTERCIRCUIT:
dirtFriction = 0.03;
fenceMapSize = 2;
fenceHeight = 1;
fenceMap = Dot.brick;
dirtColor = 0xeaeaea;
edgeColor = 0xd9c364;
roadColor = pathColor = 0x505050;
lineColor = 0xffffff;
particleColors = [0xF2F2F2, 0xFFFFFF];
break;
}
}
public function random(place:int = 0):void {
var hasInFence:Boolean = true;
var hasOutFence:Boolean = true;
var hasCone:Boolean = true;
var hasDrum:Boolean = true;
var treeInRange:Array = [0.88, 0.88];
var treeOutRange:Array = [1.12, 1.12];
var treeNum:int = 3;
var lampNum:int = 2;
this.place = place;
roadSize = 30;
switch(place) {
case CIRCUIT:
roadSize = 40;
treeNum = 3;
treeInRange = [0.76, 0.79];
treeOutRange = [1.22, 1.26];
break;
case FOREST:
roadSize = 30;
hasDrum = false;
treeInRange = [0.5, 0.9];
treeOutRange = [1.1, 1.4];
treeNum = 6;
fenceMapSize = 4;
fenceHeight = 2;
fenceMap = Dot.grass;
break;
case SNOWFIELD:
roadSize = 35;
treeNum = 1;
break;
case WINTERCIRCUIT:
roadSize = 40;
treeNum = 3;
treeInRange = [0.76, 0.79];
treeOutRange = [1.22, 1.26];
break;
}
var i:int, n:Number, tx:Number, ty:Number, angle:Number, p1:Point, p2:Point, tp:Point, rad:Number;
checkPoints.length = points.length = objectS.length = objectL.length = trees.length = 0;
for (i = 0; i < 20; i ++) {
rad = (i <= 2 || i == 19)? 55 : (Math.random() * 25 + 55);
angle = Angle.RAD360 * i / 20;
tx = Math.cos(angle + Angle.RAD90) * 5;
ty = Math.sin(angle + Angle.RAD90) * 5;
points.push([Math.cos(angle) * rad, Math.sin(angle) * rad, tx,ty,-tx,-ty]);
}
for (i = 0; i < 20; i ++) {
rad = Angle.toRAD * (i / 20 * 360 + 10);
checkPoints.push([0, 0, Math.cos(rad) * 200, Math.sin(rad) * 200]);
}
var leng:int = points.length;
fences = [[], []];
for (i = 0; i <= leng; i++) {
p1 = new Point(points[i % leng][0], points[i % leng][1]);
p2 = new Point(points[(i+1)%leng][0], points[(i+1)%leng][1]);
fences[0].push([p1.x * 0.8, p1.y * 0.8]);
fences[1].push([p1.x * 1.2, p1.y * 1.2]);
}
fences[0].reverse();
if (!hasInFence) fences.splice(0, 1);
if (!hasOutFence) fences.splice(-1, 1);
for (i = 1; i < leng; i++) {
p1 = new Point(points[i][0], points[i][1]);
p2 = new Point(points[i - 1][0], points[i - 1][1]);
for (n = 1; n <= lampNum; n++) {
tp = Point.interpolate(p1, p2, n / lampNum);
lamps.push([tp.x * 0.86, tp.y * 0.86]);
lamps.push([tp.x * 1.14, tp.y * 1.14]);
}
if (i % 4 && i != 1) {
for (n = 1; n <= treeNum; n++) {
tp = Point.interpolate(p1, p2, n / treeNum);
if (treeInRange.length) {
var perIn:Number = treeInRange[0] + (treeInRange[1] - treeInRange[0]) * Math.random();
trees.push([tp.x * perIn, tp.y * perIn]);
}
if (treeOutRange.length) {
var perOut:Number = treeOutRange[0] + (treeOutRange[1] - treeOutRange[0]) * Math.random();
trees.push([tp.x * perOut, tp.y * perOut]);
}
}
} else {
tp = Point.interpolate(p1, p2, 0.4);
if (hasDrum) for (n = 1; n <= 1; n++)
objectL.push([tp.x * 1.08 + Math.random() * 1.2, tp.y * 1.08 + Math.random() * 1.2]);
if (hasCone) for (n = 0.8; n <= 1; n += 0.1) {
tp = Point.interpolate(p1, p2, n);
objectS.push([tp.x * 0.93, tp.y * 0.93]);
}
}
}
}
}
/**
* トラックデータとか
*/
class World {
public var wonderfl:Track;
public var demo:Track;
public var complete:Track;
public var howto:Track;
public var tracks:Vector.<Track> = new Vector.<Track>();
public function World() {
tracks.push( new Track({ lv:0 ,course:1 ,unlock:0 ,light:Light.DAY ,place:Track.CIRCUIT ,reverse:false }));
tracks.push( new Track({ lv:0 ,course:2 ,unlock:1 ,light:Light.DAY ,place:Track.SNOWFIELD ,reverse:false }));
tracks.push( new Track({ lv:0 ,course:3 ,unlock:2 ,light:Light.DAWN ,place:Track.CIRCUIT ,reverse:false }));
tracks.push( new Track({ lv:0 ,course:4 ,unlock:3 ,light:Light.SUNSET ,place:Track.FOREST ,reverse:false }));
tracks.push( new Track({ lv:0 ,course:5 ,unlock:4 ,light:Light.NIGHT ,place:Track.CIRCUIT ,reverse:false }));
tracks.push( new Track({ lv:1 ,course:6 ,unlock:0 ,light:Light.DAY ,place:Track.WINTERCIRCUIT ,reverse:false }));
tracks.push( new Track({ lv:1 ,course:7 ,unlock:1 ,light:Light.SUNSET ,place:Track.FOREST ,reverse:false }));
tracks.push( new Track({ lv:1 ,course:8 ,unlock:2 ,light:Light.DAY ,place:Track.CIRCUIT ,reverse:false }));
tracks.push( new Track({ lv:1 ,course:9 ,unlock:3 ,light:Light.DAY ,place:Track.FOREST ,reverse:false }));
tracks.push( new Track({ lv:1 ,course:10 ,unlock:4 ,light:Light.NIGHT ,place:Track.CIRCUIT ,reverse:false }));
tracks.push( new Track({ lv:2 ,course:1 ,unlock:0 ,light:Light.NIGHT ,place:Track.WINTERCIRCUIT ,reverse:true }));
tracks.push( new Track({ lv:2 ,course:2 ,unlock:0 ,light:Light.DAWN ,place:Track.CIRCUIT ,reverse:true }));
tracks.push( new Track({ lv:2 ,course:3 ,unlock:0 ,light:Light.DAY ,place:Track.FOREST ,reverse:true }));
tracks.push( new Track({ lv:2 ,course:4 ,unlock:0 ,light:Light.DAY ,place:Track.CIRCUIT ,reverse:true }));
tracks.push( new Track({ lv:2 ,course:5 ,unlock:2 ,light:Light.SUNSET ,place:Track.WINTERCIRCUIT ,reverse:true }));
tracks.push( new Track({ lv:2 ,course:6 ,unlock:3 ,light:Light.NIGHT ,place:Track.CIRCUIT ,reverse:true }));
tracks.push( new Track({ lv:2 ,course:7 ,unlock:4 ,light:Light.DAY ,place:Track.CIRCUIT ,reverse:true }));
tracks.push( new Track({ lv:2 ,course:8 ,unlock:5 ,light:Light.SUNSET ,place:Track.CIRCUIT ,reverse:true }));
tracks.push( new Track({ lv:2 ,course:9 ,unlock:6 ,light:Light.DAWN ,place:Track.CIRCUIT ,reverse:true }));
tracks.push( new Track({ lv:2 ,course:10 ,unlock:7 ,light:Light.DAY ,place:Track.SNOWFIELD ,reverse:true }));
tracks.push( new Track({ lv:3 ,course:11 ,unlock:0 ,light:Light.DAY ,place:Track.WINTERCIRCUIT ,reverse:false }));
demo = new Track({ course:6 ,light:Light.NIGHT ,place:Track.WINTERCIRCUIT ,reverse:false });
howto = new Track({ course:-1 ,light:Light.DAY ,place:Track.CIRCUIT });
complete = new Track({ course:0 ,light:Light.NIGHT ,place:Track.WINTERCIRCUIT });
wonderfl = getTracksByLevel(3)[0];
demo.enemiesNum = 4;
howto.enemiesNum = 0;
complete.enemiesNum = 0;
wonderfl.enemiesNum = 0;
for (var i:int = 0; i < tracks.length; i++) tracks[i].id = i;
}
/**
* アンロック済みの難易度の全トラックデータを配列で取得する
*/
public function getUnlockedTracks(user:UserData):Vector.<Track> {
var items:Vector.<Track> = getTracksByLevel(Race.NORMAL);
if (user.rankIn[Race.NORMAL]) items = items.concat(getTracksByLevel(Race.HARD));
if (user.rankIn[Race.HARD]) items = items.concat(getTracksByLevel(Race.EXTREME));
return items;
}
/**
* 指定レベルのトラックデータを配列で取得する
*/
public function getTracksByLevel(lv:int):Vector.<Track> {
var items:Vector.<Track> = new Vector.<Track>();
for each (var tk:Track in tracks) if (tk.level == lv) items.push(tk);
return items;
}
/**
* ユーザーデータを渡してアンロック済みのトラック数を調べる
*/
public function getUnlockedNum(user:UserData):int {
var cnt:int = 0;
for each (var lv:int in Race.LEVELS) {
if (lv >= 1 && !user.rankIn[lv-1]) continue;
var items:Vector.<Track> = getTracksByLevel(lv);
var num:int = user.getClearNum(items, 3);
items.forEach(function(...arg):void { cnt += int(arg[0].unlock <= num) } );
}
return cnt;
}
/**
* ユーザーデータを渡して全コース1位になったかチェックする
*/
public function checkComplete(user:UserData):int {
var complete:int = -1;
for each (var lv:int in Race.LEVELS) {
var items:Vector.<Track> = getTracksByLevel(lv);
if (!user.complete[lv] && user.getClearNum(items, 1) == items.length) {
user.complete[lv] = true;
complete = lv;
}
}
return complete;
}
/**
* ユーザーデータを渡して全コース入賞したかチェックする
*/
public function checkRankIn(user:UserData):int {
var rankIn:int = -1;
for each (var lv:int in Race.LEVELS) {
var items:Vector.<Track> = getTracksByLevel(lv);
if (!user.rankIn[lv] && user.getClearNum(items, 3) == items.length) {
user.rankIn[lv] = true;
rankIn = lv;
}
}
return rankIn;
}
}
/**
* 設定メニュー
*/
class SettingMenu {
public var sprite:Sprite = new Sprite();
private var _menu:LabelMenu;
private var _cancelFunc:Function;
public function SettingMenu() {
}
public function init():void {
var texts:Array = ["Mirror(M): {OFF,ON}", "Headlight(L): {OFF,ON}", "Sound(S): {OFF,ON}", "View Distance(V): {1,2,3,4,5}", "Particles(P): {OFF,ON}", "Quality(Q): {LOW,HIGH}", "Ghost Car(G): {OFF,ON}"];
_menu = new LabelMenu(sprite, UI.menuX, UI.menuY, texts, null, onCancel, onChange, onSwitch);
setEnabled(false);
}
public function setEnabled(enabled:Boolean, cancel:Function = null):void {
_cancelFunc = cancel;
_menu.enabled = _menu.visible = enabled;
if (enabled) {
update();
_menu.select(0);
}
}
private function onChange(index:int):void {
if (!$.game.isDemo) return;
if (index <= 3) $.game.setCamera(SceneCamera.DRIVERS);
else $.game.setCamera(SceneCamera.AROUND);
}
private function onSwitch(index:int, option:int):void {
$.user.showMirror = !!_menu.options[0];
$.user.showLight = !!_menu.options[1];
$.user.mute = SE.mute = !_menu.options[2];
$.user.viewDistance = _menu.options[3];
$.user.showParticles = !!_menu.options[4];
$.user.showGhost = !!_menu.options[6];
$.user.groundQuality = _menu.options[5];
$.user.save();
$.game.updateDisplay();
if (index == 5) $.game.updateGround();
if (index == 6) $.game.updateGhostVisible();
$.game.scene.render();
}
private function onCancel():void {
_cancelFunc();
setEnabled(false);
}
public function update():void {
_menu.setOption(0, int($.user.showMirror));
_menu.setOption(1, int($.user.showLight));
_menu.setOption(2, int(!$.user.mute));
_menu.setOption(3, $.user.viewDistance);
_menu.setOption(4, int($.user.showParticles));
_menu.setOption(5, $.user.groundQuality);
_menu.setOption(6, int($.user.showGhost));
}
}
/**
* タイトル画面
*/
class TopMenu {
static public const SCENE_HIDE:int = 0;
static public const SCENE_TOP:int = 1;
static public const SCENE_LEVEL:int = 2;
static public const SCENE_SETTING:int = 3;
static public const SCENE_CLICK:int = 4;
static public const SCENE_FILE:int = 5;
public var sprite:Sprite = new Sprite();
private var _noConnection:Boolean = false;
private var _scene:int = SCENE_CLICK;
private var _logo:Bitmap;
private var _click:Sprite;
private var _titleMenu:LabelMenu;
private var _levelMenu:LabelMenu;
private var _fileMenu:LabelMenu;
public function get scene():int { return _scene; }
public function TopMenu() {
}
public function init():void {
var sp:Sprite = new Sprite();
UI.createLabel(sp, 0, 0, Text.TITLE_MAIN, 8 * 7);
UI.createLabel(sp, 6, 75, Text.TITLE_SUB, 8 * 3);
_logo = Create.gradientLabel(sp, 0xFFFA19, 0xFF9411, 0, 0xA0);
_logo.x = (Display.width - _logo.width)/2 | 0;
_logo.y = 70;
sprite.addChild(_logo);
var items:Array = [Text.RACE_SINGLE, Text.RACE_TIMETRIAL, Text.RACE_WONDERFL, Text.RACE_RANDOM, Text.MENU_SETTINGS, Text.HOWTO, Text.FILE];
_titleMenu = new LabelMenu(sprite, UI.menuX, UI.menuY, items, onSelectTitle);
_levelMenu = new LabelMenu(sprite, UI.menuX, UI.menuY, Text.LEVELS, onSelectLevel, onCancelLevel);
_fileMenu = new LabelMenu(sprite, UI.menuX, UI.menuY, [Text.EXPORT, Text.IMPORT], onSelectFile, onCancelLevel);
_click = Create.box(0, 0, Display.width, Display.height, 0, 0);
UI.createLabel(_click, (Display.width - 140)/2|0, 300, Text.MSG_CLICK, 8 * 2, UI.HIGHLIGHT).filters = UI.TEXT_FILTERS;
_click.buttonMode = true;
_click.mouseChildren = false;
_click.addEventListener(MouseEvent.CLICK, gotoTop);
sprite.addChild(_click);
setScene(SCENE_CLICK);
}
public function setNoConnection():void {
_noConnection = true;
_titleMenu.items[2].setText("--------");
_titleMenu.items[2].enabled = false;
}
private function onSelectFile(index:int):void{
if (index == 0) $.user.exportFile();
if (index == 1) $.user.importFile(onCompleteImport);
}
private function onCompleteImport():void{
setScene(SCENE_TOP);
}
public function gotoTop(e:MouseEvent = null):void {
SE.note(SE.OMP_SELECT);
setScene(SCENE_TOP);
}
public function updateLevel():void {
_levelMenu.items[1].setText($.user.rankIn[Race.NORMAL]? Text.LEVELS[Race.HARD] : "-----");
_levelMenu.items[2].setText($.user.rankIn[Race.HARD]? Text.LEVELS[Race.EXTREME] : "-----");
_levelMenu.items[1].setEnabled($.user.rankIn[Race.NORMAL]);
_levelMenu.items[2].setEnabled($.user.rankIn[Race.HARD]);
}
public function setScene(value:int):void {
_scene = value;
switch(_scene) {
case SCENE_FILE: case SCENE_LEVEL: case SCENE_SETTING: $.game.display.showBack(Text.LABEL_BACK); break;
default: $.game.display.hideBack();
}
sprite.visible = (_scene != SCENE_HIDE);
_click.visible = (_scene == SCENE_CLICK);
_fileMenu.enabled = _fileMenu.visible = (_scene == SCENE_FILE);
_titleMenu.enabled = _titleMenu.visible = (_scene == SCENE_TOP);
_levelMenu.enabled = _levelMenu.visible = (_scene == SCENE_LEVEL);
if (_scene == SCENE_SETTING) $.setting.setEnabled(true, onCancelSettings);
$.game.updateDisplay();
updateLevel();
}
private function onCancelLevel():void {
setScene(SCENE_TOP);
}
private function onCancelSettings():void {
$.game.setCamera(SceneCamera.DEMO);
setScene(SCENE_TOP);
}
private function onSelectLevel(index:int):void {
if (index > 0 && !_levelMenu.items[index].enabled) return;
startSelectTrack(Race.SINGLE, index);
}
private function onSelectTitle(index:int):void {
if (index == 0) {
setScene(SCENE_LEVEL);
return;
}
if (index <= 3) startSelectTrack(index);
if (index == 4) setScene(SCENE_SETTING);
if (index == 5) $.transition.fadeOutIn($.game.howto);
if (index == 6) {
_fileMenu.select(0);
setScene(SCENE_FILE);
}
}
private function startSelectTrack(mode:int, level:int = 0):void {
setScene(SCENE_HIDE);
$.selector.create(mode, level);
}
}
/**
* 表示テキスト
*/
class Text {
static public const TITLE_MAIN:String = "MOJA";
static public const TITLE_SUB:String = "GRAND PRIX";
static public const LEVEL:String = "Difficulty";
static public const RESULT:String = "Race Result";
static public const HOWTO:String = "How To Drift";
static public const FILE:String = "File";
static public const LABEL_BACK:String = "Back";
static public const LABEL_QUIT:String = "Quit";
static public const EXPORT:String = "Export Save Data";
static public const IMPORT:String = "Import Save Data";
static public const DEMO:String = "DEMONSTRATION";
static public const FINISH:String = "FINISH";
static public const WINNER:String = "WINNER";
static public const RACE_SINGLE:String = "Single Race";
static public const RACE_TIMETRIAL:String = "Time Trial";
static public const RACE_RANDOM:String = "Random Race";
static public const RACE_WONDERFL:String = "Wonderfl Challenge";
static public const MENU_SETTINGS:String = "Settings";
static public const MENU_RETRY:String = "Try Again";
static public const MENU_QUIT:String = "Quit";
static public const MENU_RESUME:String = "Resume";
static public const MENU_REPLAY:String = "Replay Video";
static public const RACES:Array = [RACE_SINGLE, RACE_TIMETRIAL, RACE_WONDERFL, RACE_RANDOM];
static public const LEVELS:Array = ["NORMAL", "HARD", "MOJA"];
static public const PLACES:Array = ["CIRCUIT", "FOREST", "SNOWFIELD", "WINTER CIRCUIT"];
static public const UNLOCK_TRACK:String = "New Track is Unlocked!";
static public const MSG_CLICK:String = "CLICK TO PLAY";
static public function getRankString(rank:int):String {
if (rank >= 4) return rank + "th";
return ["1st", "2nd", "3rd"][rank - 1];
}
static public function getTimeString(time:int):String {
var sec:Number = time / 1000;
if (time < 0) return "--:--:--";
return String(sec / 60 | 0) + ":" + String("00").substr(String(sec % 60 | 0).length) + (sec % 60).toFixed(3).replace(".", ":");
}
}
/**
* UIの色とか
*/
class UI {
static public const menuX:Number = 155;
static public const menuY:Number = 230;
static public const PALE:uint = 0xDDDDD0;
static public const HIGHLIGHT:uint = 0xFFE01A;
static public const WINNER:uint = 0xFFCC00;
static public const BASE:uint = 0x857E56;
static public const DARK:uint = 0x302E1F;
static public const TEXT_FILTERS:Array = [new DropShadowFilter(1, 45, 0, 1, 3, 3, 200, 1)];
static public function createLabel(parent:DisplayObjectContainer = null, x:Number = 0, y:Number = 0, text:String = "", size:Number = 16, rgb:uint = 0xFFFFFF):Label {
var saveSize:Number = Style.fontSize;
var saveRgb:uint = Style.LABEL_TEXT;
Style.fontSize = size;
Style.LABEL_TEXT = rgb;
var label:Label = new Label(parent, x, y, text);
Style.fontSize = saveSize;
Style.LABEL_TEXT = saveRgb;
return label;
}
static public function createDarkBox(alpha:Number = 0.4):Sprite {
return Create.box(0, 0, Display.width, Display.height, DARK, alpha);
}
static public function createHeader(title:String = ""):Sprite {
var sprite:Sprite = Create.gradientBox(0, 0, Display.width, 40, true, 90, [0x333333, 0x000000], [1, 1], [0, 0xFF]);
createLabel(sprite, 5, 3, title);
return sprite;
}
}
/**
* 保存するデータ
*/
class UserData {
public var viewDistance:int;
public var groundQuality:int;
public var randomEnemiesNum:int;
public var randomPlace:int;
public var randomTime:int;
public var randomLevel:int;
public var unlock:int;
public var showParticles:Boolean;
public var showMirror:Boolean;
public var showLight:Boolean;
public var showGhost:Boolean;
public var mute:Boolean;
public var bestRank:Array = [];
public var bestTotals:Array = [];
public var bestLaps:Array = [];
public var rankIn:Array = [];
public var complete:Array = [];
private var _so:SharedObject = SharedObject.getLocal("mojagp");
private var _fr:FileReference = new FileReference();
private var _error:Function;
private var _complete:Function;
public function UserData() {
}
/**
* 指定ランク以上に入賞したトラック数を調べる
*/
public function getClearNum(tracks:Vector.<Track>, unlockRank:int = 3):int {
var unlock:int = 0;
for each (var track:Track in tracks) {
var rank:int = bestRank[track.id];
if (rank > 0 && rank <= unlockRank) unlock++;
}
return unlock;
}
/**
* アンロックしたトラック数を設定しつつ数が増えたらtrueを返す
*/
public function setUnlockedNum(num:int):Boolean {
var isUpdate:Boolean = (unlock < num);
unlock = num;
return isUpdate;
}
public function setDefaultData():void {
var i:int, n:int;
for (n = 0; n < $.world.tracks.length; n++) {
bestRank[n] = -1;
bestTotals[n] = -1;
bestLaps[n] = -1;
}
mute = false;
showParticles = true;
showGhost = true;
showLight = true;
showMirror = false;
viewDistance = 2;
groundQuality = 1;
randomEnemiesNum = 6;
unlock = randomPlace = randomLevel = randomTime = 0;
setUnlockedNum($.world.getUnlockedNum(this));
complete = [false, false, false];
rankIn = [false, false, false];
}
public function importFile(complete:Function = null, error:Function = null):void {
_complete = complete;
_error = error;
_fr.addEventListener(Event.SELECT, onSelectFile);
_fr.addEventListener(Event.CANCEL, removeFileListeners);
_fr.browse();
}
private function removeFileListeners(...arg):void {
_fr.removeEventListener(Event.SELECT, onSelectFile);
_fr.removeEventListener(Event.CANCEL, removeFileListeners);
_fr.removeEventListener(Event.COMPLETE, onLoadFile);
}
private function onSelectFile(e:Event):void {
removeFileListeners();
_fr.addEventListener(Event.COMPLETE, onLoadFile);
_fr.load();
}
private function onLoadFile(e:Event):void {
removeFileListeners();
try {
_fr.data.uncompress();
var obj:Object = _fr.data.readObject();
for each(var node:XML in describeType(this).variable) {
var name:String = node.@name;
if(obj[name] != null) this[name] = obj[name];
}
save();
SE.effect(SE.SND_NEWRECORD);
if (_complete != null)_complete();
} catch (e:Error) {
SE.note(SE.OMP_BOO);
if (_error != null) _error();
}
}
public function exportFile():void {
var ba:ByteArray = new ByteArray();
ba.writeObject(_so.data);
ba.compress();
_fr.save(ba, "mojadata.dat");
}
public function save():void {
for each(var node:XML in describeType(this).variable) {
var name:String = node.@name;
_so.data[name] = this[name];
}
}
public function load():void {
for each(var node:XML in describeType(this).variable) {
var name:String = node.@name;
if (_so.data[name] != null) this[name] = _so.data[name];
}
}
public function destroy():void {
_so.clear();
setDefaultData();
save();
}
}
/**
* 画面サイズ
*/
class Display {
static public var stage:Stage;
static public var width:int;
static public var height:int;
static public var size:Rectangle = new Rectangle();
static public var center:Point = new Point();
static private var _lastQuality:String = "";
static public function setSize(width:Number, height:Number):void {
center.x = (Display.width = size.width = width) / 2;
center.y = (Display.height = size.height = height) / 2;
}
static public function cacheQuality(quality:String = ""):void {
_lastQuality = Display.stage.quality;
if (quality) Display.stage.quality = quality;
}
static public function restoreQuality():void {
Display.stage.quality = _lastQuality;
}
}
/**
* レース結果画面
*/
class ResultMenu {
private var _menu:LabelMenu;
private var _labels:Label;
private var _times:Label;
private var _message:Label;
private var _starts:Vector.<Bitmap> = new Vector.<Bitmap>();
private var _trophy:Bitmap = new Bitmap();
private var _continue:PushButton;
public var onSelect:Function;
public var sprite:Sprite = new Sprite();
public function ResultMenu() {
}
public function init():void {
sprite.addChild(UI.createDarkBox());
sprite.addChild(UI.createHeader(Text.RESULT));
sprite.addChild(_trophy);
_trophy.scaleX = _trophy.scaleY = 5;
for (var i:int = 0; i < 3; i++) {
var star:Bitmap = sprite.addChild(new Bitmap(Dot.star)) as Bitmap;
star.scaleX = star.scaleY = 2;
star.x = UI.menuX + 60;
star.y = 87 + i * 26;
_starts.push(star);
}
_labels = UI.createLabel(sprite, UI.menuX, 80);
_times = UI.createLabel(sprite, UI.menuX + 80, 80);
_message = UI.createLabel(sprite, UI.menuX, 180, "", 16, 0xFFFF00);
_message.filters = _times.filters = _labels.filters = UI.TEXT_FILTERS;
_labels.text = "RANK\rRACE\rLAP";
_menu = new LabelMenu(sprite, UI.menuX, UI.menuY, [Text.MENU_REPLAY, Text.MENU_RETRY, Text.MENU_QUIT], onSelectMenu);
_continue = new PushButton(sprite, 182, 222, "CONTINUE", showMenu);
_continue.visible = false;
sprite.visible = _menu.enabled = _menu.visible = false;
}
private function onSelectMenu(index:int):void {
sprite.visible = _menu.enabled = _menu.visible = false;
if (onSelect != null) onSelect(index);
}
public function setMessgae(str:String):void {
_message.text = str;
}
public function setResult(race:Race):void {
sprite.visible = true;
var noRank:Boolean = !race.track.enemiesNum || race.mode == Race.TIMETRIAL;
if (race.rank <= 3 && !noRank) {
_trophy.bitmapData = Dot["trophy" + race.rank];
_trophy.x = 96 - _trophy.bitmapData.width * _trophy.scaleX / 2 | 0;
_trophy.y = 122 - _trophy.bitmapData.height * _trophy.scaleY / 2 | 0;
} else _trophy.bitmapData = null;
race.lapsTime.sort(Array.NUMERIC);
var str:String = "";
str += (noRank? "---" : Text.getRankString(race.rank)) + "\r";
str += Text.getTimeString(race.raceTime) + "\r";
str += Text.getTimeString(race.lapsTime[0]) + "\r";
_times.text = str;
_starts[0].visible = race.newRankRecord;
_starts[1].visible = race.newRaceRecord;
_starts[2].visible = race.newLapRecord;
if (!race.isWonderfl) {
showMenu();
return;
}
$.moja.keyEnabled = false;
FrameTimer.setTimer(5, function():void {
_continue.visible = true;
}, null, "continue");
ScoreWindow.show(race.raceTime, showMenu, "Time", "sec", 3, 99, true, true);
}
private function showMenu(...arg):void {
FrameTimer.clearTimer("continue");
_continue.visible = false;
$.moja.keyEnabled = true;
_menu.select(0);
_menu.enabled = _menu.visible = true;
}
}
/**
* 一時停止メニュー
*/
class PauseMenu {
public var sprite:Sprite = new Sprite();
public var onSelect:Function;
private var _menu:LabelMenu;
public function PauseMenu() {
}
public function init():void {
sprite.addChild(Create.box(0, 0, Display.width, Display.height, UI.DARK, 0.8));
sprite.addChild(Create.gradientBox(0, 0, Display.width, 40, true, 90, [0x333333, 0x000000], [1, 1], [0, 0xFF]));
UI.createLabel(sprite, 5, 3, "PAUSE");
_menu = new LabelMenu(sprite, UI.menuX, UI.menuY, [Text.MENU_RESUME, Text.MENU_RETRY, Text.MENU_SETTINGS, Text.MENU_QUIT], onSelectMenu);
sprite.visible = _menu.enabled = false;
}
public function active():void {
sprite.visible = _menu.enabled = _menu.visible = true;
$.setting.setEnabled(false);
_menu.select(0);
}
private function onSelectMenu(index:int):void {
_menu.enabled = false;
sprite.visible = !(_menu.visible = onSelect(index));
}
}
/**
* サムネイル生成
*/
class Thumb {
public var images:Vector.<BitmapData> = new Vector.<BitmapData>();
private var _complete:Function;
private var _progress:Function;
private var _sprite:Sprite = new Sprite();
private var _cnt:int = 0;
private var _save:int;
public function Thumb():void {
}
public function create(complete:Function, progress:Function):void {
_complete = complete;
_progress = progress;
_save = $.user.viewDistance;
$.user.viewDistance = 0;
$.game.updateDisplay();
$.game.setGroundScale(5, false);
_sprite.addEventListener(Event.ENTER_FRAME, onTick);
}
private function onTick(e:Event):void {
var track:Track = $.world.tracks[_cnt++];
$.game.createStage(track, true);
$.game.scene.camera.setGazeXYZ(track.gazeXY[0], track.gazeXY[1], 0);
$.game.scene.camera.setPositionXYZ(track.cameraXY[0], track.cameraXY[1], 1.5);
$.game.scene.render();
var bmd:BitmapData = new BitmapData(90, 90, false, 0);
bmd.draw($.game.scene.display, new Matrix(bmd.width / Display.width, 0, 0, bmd.height / Display.height, 0, 0), null, null, null, true);
var shape:Shape = new Shape();
track.draw(shape.graphics, 3, 0xFFFFFF, 1, 0.5);
shape.filters = [new GlowFilter(0x000000, 1.5, 1.5, 1, 10, 3)];
bmd.draw(shape, new Matrix(1, 0, 0, 1, bmd.width/2, bmd.height/2));
images.push(bmd);
_progress(_cnt / $.world.tracks.length);
if (_cnt >= $.world.tracks.length) {
$.user.viewDistance = _save;
$.game.updateGround(false);
_sprite.removeEventListener(Event.ENTER_FRAME, onTick);
_complete();
}
}
}
/**
* コース選択画面
*/
class TrackSelector {
public var sprite:Sprite = new Sprite();
private var _bg:Sprite;
private var _items:Vector.<SelectorItem> = new Vector.<SelectorItem>();
private var _menu:LabelMenu;
private var _header:Sprite;
private var _itemContainer:Sprite = new Sprite();
private var _itemH:Number = 100;
private var _headerH:Number = 40;
private var _title:Label;
private var _level:int;
private var _tracks:Vector.<Track>;
public function TrackSelector() {
sprite.visible = false;
}
public function init():void {
_header = Create.gradientBox(0, 0, Display.width, _headerH, true, 90, [0x333333, 0x000000], [1, 1], [0, 0xFF]);
_bg = UI.createDarkBox()
sprite.addChild(_bg);
sprite.addChild(_itemContainer);
sprite.addChild(_header);
_title = UI.createLabel(_header, 5, 3, "");
}
public function create(mode:int, level:int):void {
$.game.display.showBack(Text.LABEL_BACK);
$.race.mode = mode;
var i:int;
if ($.race.isWonderfl) _tracks = Vector.<Track>([$.world.wonderfl]);
else if ($.race.isTimeTrial) _tracks = $.world.getUnlockedTracks($.user);
else _tracks = $.world.getTracksByLevel(level);
_level = level;
_itemContainer.y = 0;
_title.text = Text.RACES[mode];
if ($.race.isSingle) _title.text += ": " + Text.LEVELS[level];
if (_menu) _menu.dispose();
var labels:Array = [];
for (i = 0; i < _tracks.length; i++) labels.push("");
if (!$.race.isRandom) {
_menu = new LabelMenu(null, 0, 0, labels, onSelect, onCancel, onChange);
} else {
var enemiesNum:Array = [];
for (i = 1; i <= 30; i++) enemiesNum.push(i);
_menu = new LabelMenu(sprite, UI.menuX, UI.menuY, ["{#,#}", "Place: {" + Text.PLACES.join(",") + "}", "Time : {"+Light.LABELS.join(",")+"}", "Enemies: {" + enemiesNum.join(",") + "}", "Start"], onSelectRandom, onCancel, null, null, 30);
_menu.setOption(0, $.user.randomLevel);
_menu.setOption(1, $.user.randomPlace);
_menu.setOption(2, $.user.randomTime);
_menu.setOption(3, $.user.randomEnemiesNum);
var list:Array = [];
var lv:int = !$.user.rankIn[0] ? 1 : !$.user.rankIn[1]? 2 : 3;
for (i = 0; i < lv; i++) list.push(Text.LEVEL + ": " + Text.LEVELS[i]);
_menu.setLabelsAt(0, list);
}
while (_itemContainer.numChildren) _itemContainer.removeChildAt(0);
_items.length = 0;
var unlock:int = $.user.getClearNum(_tracks, 3);
var leng:int = $.race.isRandom? 1 : _tracks.length;
for (i = 0; i < leng; i++) {
var item:SelectorItem = new SelectorItem();
if (!$.race.isRandom) {
var thumb:BitmapData = (_tracks[i].id >=0 && $.thumb.images[_tracks[i].id])? $.thumb.images[_tracks[i].id] : null;
item.initNormal(mode, _tracks[i], thumb);
var isUnlock:Boolean = ($.race.isTimeTrial)? $.user.bestRank[_tracks[i].id] > 0 : unlock >= _tracks[i].unlock;
item.setUnlock(isUnlock);
if ($.race.isTimeTrial) {
item.setGhostNum($.replay.getDataByID(_tracks[i].id).length);
}
} else {
item.initRandom();
}
item.setRecord($.user);
_items.push(item);
_itemContainer.addChild(item);
item.y = _itemH * i;
}
_bg.visible = $.race.isRandom;
sprite.visible = true;
onChange(0);
}
private function onSelectRandom(index:int):void {
if (index != 4) return;
sprite.visible = _menu.enabled = false;
$.user.randomLevel = _menu.options[0];
$.user.randomPlace = _menu.options[1];
$.user.randomTime = _menu.options[2];
$.user.randomEnemiesNum = _menu.options[3];
$.user.save();
var track:Track = new Track();
track.random(_menu.options[1]);
track.level = _menu.options[0];
track.lapsNum = 4;
track.enemiesNum = _menu.options[3] + 1;
track.light = Light.LIST[_menu.options[2]];
track.setPlace(_menu.options[1]);
$.transition.fadeOutIn(function():void {
$.game.isDemo = false;
$.game.destroyStage();
$.game.createStage(track, false);
$.game.startRace();
});
}
private function onChange(index:int):void {
for (var i:int = 0; i < _items.length; i++) _items[i].setSelect(i == index);
var min:Number = (index) * _itemH + _itemContainer.y;
var max:Number = (index + 1) * _itemH + _itemContainer.y;
if (max > Display.height) BetweenAS3.to(_itemContainer, { y:Display.height - _itemH*(index+1) }, 0.3, Cubic.easeOut).play();
if (min < _headerH) BetweenAS3.to(_itemContainer, { y:_headerH - index * _itemH }, 0.3, Cubic.easeOut).play();
}
private function onCancel():void{
sprite.visible = _menu.enabled = false;
$.top.setScene($.race.isSingle? TopMenu.SCENE_LEVEL : TopMenu.SCENE_TOP);
}
private function onSelect(index:int):void {
if (!_items[index].isUnlocked) return;
sprite.visible = _menu.enabled = false;
$.transition.fadeOutIn(function():void {
$.game.isDemo = false;
$.game.destroyStage();
$.game.createStage(_tracks[index]);
$.game.startRace();
});
}
}
/**
* コースセレクタ用アイテム
*/
class SelectorItem extends Sprite {
public var isUnlocked:Boolean = false;
private var _mode:int = 0;
private var _base:Sprite;
private var _thumb:Sprite;
private var _lock:Sprite;
private var _bestLap:Label;
private var _bestRace:Label;
private var _courseName:Label;
private var _track:Track;
public function SelectorItem() {
_base = Create.gradientBox(0, 0, Display.width, 100, true, 90, [UI.BASE, UI.DARK], [1, 1], [0, 0xFF]);
_thumb = Create.box(0, 0, 90, 90, 0, 0.5, 5, 5);
_lock = Create.box(0, 0, 90, 90, 0x111111, 1, 5, 5);
_lock.addChild(Create.spriteBmp(Dot.lock, 3, -Dot.lock.width/2, -Dot.lock.height/2, 45, 45));
_base.alpha = 0;
addChild(_base);
addChild(_thumb);
addChild(_lock);
_courseName = UI.createLabel(this, 105, 1, "");
UI.createLabel(this, 105, 40, "BEST RACE", 16, UI.PALE);
UI.createLabel(this, 105, 62, "BEST LAP", 16, UI.PALE);
_bestRace = UI.createLabel(this, 220, 40, "??:??:??", 16, UI.PALE);
_bestLap = UI.createLabel(this, 220, 62, "??:??:??", 16, UI.PALE);
}
public function initRandom():void {
_mode = Race.RANDOM;
_courseName.text = "??????";
_bestRace.text = _bestLap.text = "??:??:??";
setUnlock(true);
}
public function initNormal(mode:int, track:Track, bmd:BitmapData):void {
_track = track;
_mode = mode;
_thumb.addChild(new Bitmap(bmd));
_courseName.text = ((mode == Race.WONDERFL)? "" : String(_track.id+1) + ". ") + track.name;
}
public function setGhostNum(value:int):void {
if (!value) return;
addChild(Create.spriteBmp(Dot.ghost, 4, 0, 0, 355, 25));
UI.createLabel(this, 394, 30, "x" + value, 8*3);
}
public function setUnlock(unlock:Boolean):void {
isUnlocked = unlock
_lock.visible = !isUnlocked;
}
public function setRecord(user:UserData):void {
if (_mode == Race.RANDOM) return;
if (user.bestRank[_track.id] == null) return;
_bestRace.text = Text.getTimeString(user.bestTotals[_track.id] || -1);
_bestLap.text = Text.getTimeString(user.bestLaps[_track.id] || -1);
if (_mode > Race.SINGLE) return;
if (user.bestRank[_track.id] > 3 || user.bestRank[_track.id] == -1) return;
var bmd:BitmapData = Dot["trophy" + user.bestRank[_track.id]];
var icon:Sprite = addChild(Create.spriteBmp(bmd, 3, -bmd.width / 2 | 0, -bmd.height / 2 | 0)) as Sprite;
icon.x = 400;
icon.y = 50;
}
public function setSelect(select:Boolean):void {
if(select) BetweenAS3.to(_base, { alpha:1 }, 0.2, Cubic.easeOut).play();
else BetweenAS3.to(_base, { alpha:0.4 }, 0.2, Cubic.easeOut).play();
}
}
/**
* ゲーム画面に表示する数値やマップ
*/
class DisplayInfo extends Sprite {
public var replay:Label;
public var map:Sprite = new Sprite();
public var display:Sprite = new Sprite();
public var markContainer:Sprite = new Sprite();
public var backSprite:Sprite = new Sprite();
private var _backLabel:Label;
private var _labelContainer:Sprite = new Sprite();
private var _messageContainer:Sprite = new Sprite();
private var _rank:Label;
private var _speed:Label;
private var _lapNum:Label;
private var _messageL:Label;
private var _messageS:Label;
private var _enemyNum:Label;
private var _totalTime:Label;
private var _lapTimes:Label;
private var _currentLapTime:Label;
private var _laps:Vector.<int> = new Vector.<int>();
private var _mapImage:BitmapData;
private var _lapMax:int = 1;
public function DisplayInfo() {
}
public function init():void {
replay = UI.createLabel(null, Display.width - 85, 7, "REPLAY");
replay.visible = false;
addChild(display);
addChild(replay);
display.addChild(markContainer);
display.addChild(_labelContainer);
display.addChild(_messageContainer);
display.addChild(map);
_lapNum = UI.createLabel(_labelContainer, Display.width - 95, 10);
_rank = UI.createLabel(_labelContainer, 370, 370);
_speed = UI.createLabel(_labelContainer, 200, 10);
_messageL = UI.createLabel(_messageContainer, 0, 120);
_messageS = UI.createLabel(_messageContainer, 0, 230);
_messageContainer.filters = UI.TEXT_FILTERS;
_rank.scaleX = _rank.scaleY = 3;
_enemyNum = UI.createLabel(_labelContainer, 420, 430);
UI.createLabel(_labelContainer, 10, 10, "RACE");
_totalTime = UI.createLabel(_labelContainer, 10, 30);
UI.createLabel(_labelContainer, 10, 50, "LAP");
_lapTimes = UI.createLabel(_labelContainer, 10, 70);
var tfm:TextFormat = new TextFormat();
tfm.leading = -6;
_lapTimes.textField.defaultTextFormat = tfm;
_currentLapTime = UI.createLabel(_labelContainer, 10, 70);
_mapImage = new BitmapData(S.QtoM(S.QRECT.right), S.QtoM(S.QRECT.bottom), true, 0);
map.addChild(new Bitmap(_mapImage)).alpha = 0.8;
map.x = 0;
map.y = Display.height - map.height;
backSprite.addChild(Create.spriteBmp(Dot.X, 2));
backSprite.x = Display.width - 80;
backSprite.y = 9;
_backLabel = UI.createLabel(backSprite, 26, -6, "");
hideBack();
}
public function hideBack():void {
backSprite.visible = false;
}
public function showBack(text:String = ""):void {
if (text) _backLabel.text = text;
backSprite.visible = true;
}
public function setCourseData(data:Track):void {
_lapMax = data.lapsNum;
setLapNum(1);
_rank.text = "";
_enemyNum.text = "/ " + ($.race.mode == Race.TIMETRIAL? 1 : data.enemiesNum + 1);
_laps.length = 0;
_lapTimes.text = "";
_currentLapTime.y = 70;
setTotalTime(0);
setLapTime(0);
//マップにコースを描画する
_mapImage.fillRect(_mapImage.rect, 0);
var shape:Shape = new Shape();
data.draw(shape.graphics, 13 * S.MAP, 0x444444, 1, S.MAP);
shape.filters = [new GlowFilter(0xFFFFFF, 1, 2, 2, 5, 3)];
Display.cacheQuality(StageQuality.BEST);
_mapImage.draw(shape, new Matrix(1, 0, 0, 1, S.QtoM(0), S.QtoM(0)));
Display.restoreQuality();
}
public function addLapTime(time:int, finish:Boolean = false):void {
_currentLapTime.y += 20;
_laps.push(time);
_lapTimes.text = "";
_laps.forEach(function(...arg):void { _lapTimes.text += Text.getTimeString(arg[0]) + "\r"; }, null);
if (finish) _currentLapTime.text = "";
}
public function setLapTime(time:int):void {
_currentLapTime.text = Text.getTimeString(time);
}
public function setTotalTime(time:int):void {
_totalTime.text = Text.getTimeString(time);
}
public function setSpeed(speed:Number):void {
_speed.text = String(speed * S.QtoKPH | 0) + " kph";
_speed.x = 260 - _speed.width;
}
public function setLapNum(lap:int):void {
_lapNum.text = "LAP: " + Math.min(_lapMax, lap) + "/" + _lapMax;
if (lap >= _lapMax) _lapNum.transform.colorTransform = Palette.getColorTransform(UI.HIGHLIGHT);
else _lapNum.transform.colorTransform = Palette.getColorTransform(0xFFFFFF);
}
public function setRank(rank:int):void {
_rank.text = String(rank);
}
public function setMessage(isLarge:Boolean, str:String, scale:Number = 1, interval:int = 4000, color:uint = 0xFFFFFF):void {
var msg:Label = (isLarge)? _messageL : _messageS;
msg.transform.colorTransform = Palette.getColorTransform(color);
msg.scaleX = msg.scaleY = scale;
msg.text = str;
msg.visible = false;
FrameTimer.setTimer(2, onShow, [msg]);
if (interval > 0) FrameTimer.setTimer(Math.max(3, interval / 1000 * 30), onHide, [msg]);
}
private function onHide(target:Label):void {
target.visible = false;
}
private function onShow(target:Label):void {
target.visible = true;
target.x = ((Display.width - target.getRect(target.parent).width) / 2) | 0;
}
}
/**
* レース部分のメインクラス
*/
class Game {
public var sprite:Sprite = new Sprite();
private var _sceneTime:int = 0;
private var _isDemo:Boolean = false;
private var _isPlaying:Boolean = false;
private var _inResultView:Boolean = false;
private var _isRunning:Boolean = false;
private var _isFinish:Boolean = false;
private var _isRecording:Boolean = false;
private var _isReplay:Boolean = false;
private var _isComplete:Boolean = false;
private var _isHowTo:Boolean = false;
private var _mirror:Bitmap;
private var _boxContainer:MovieClip = new MovieClip();
private var _display:DisplayInfo = new DisplayInfo();
private var _pause:PauseMenu;
private var _result:ResultMenu;
private var _sceneCam:SceneCamera = new SceneCamera();
private var _scene:Scene3D = new Scene3D();
private var _sim:QuickBox2D;
private var _contacts:QuickContacts;
private var _race:Race;
private var _player:Car;
private var _keyUD:uint = 0x0000;
private var _lap:Number = 1;
private var _time:Number = 0;
private var _collideTime:int = 0;
private var _mirrorCnt:int = -1;
private var _startTime:int = 0;
private var _countDown:int = 0;
private var _countNum:int = 3;
private var _countInterval:int = 30;
private var _complete:int = -1;
private var _completeTimer:int;
private var _lines:Sprite;
private var _lines2:Shape;
private var _lines1:Shape;
private var _circles:Shape;
private var _lakes:Shape;
private var _shadowContainer:Sprite = new Sprite();
private var _lightContainer:Sprite = new Sprite();
private var _noise:BitmapData = new BitmapData(50, 50, false, 0);
private var _wanco:Wanco;
private var _distanceEstimator:DistanceEstimator;
/**シーンの経過フレーム時間*/
public function get sceneTime():int { return _sceneTime; }
public function get display():DisplayInfo { return _display; }
public function get scene():Scene3D { return _scene; }
public function get player():Car { return _player; }
public function get isFinish():Boolean { return _isFinish; }
public function get isReplay():Boolean { return _isReplay; }
public function get isDemo():Boolean { return _isDemo; }
public function set isDemo(value:Boolean):void { _isDemo = value; }
public function Game(de:DistanceEstimator = null) {
_lines = new Sprite();
_lines2 = _lines.addChild(new Shape()) as Shape;
_lines1 = _lines.addChild(new Shape()) as Shape;
_circles = _lines.addChild(new Shape()) as Shape;
_lakes = new Shape();
_noise.noise(123, 0x4, 0x24, 7, true);
_distanceEstimator = de;
}
/*
public function saveReplay():void {
if (!$.replay.data.length) return;
var fr:FileReference = new FileReference();
var ba:ByteArray = new ByteArray();
ba.writeObject($.replay.data[0].toObject());
ba.compress();
fr.save(ba, "replay" + new Date().time + ".dat");
}
*/
public function init():void {
_race = $.race;
_display.init();
_mirror = new Bitmap(new BitmapData(465/2, 75, false, 0));
_mirror.x = (Display.width - _mirror.width)/2;
_mirror.y = 35;
_pause = new PauseMenu();
_pause.init();
_pause.onSelect = onSelectPauseMenu;
_scene.setSize(Display.width, Display.height);
_result = new ResultMenu();
_result.init();
_result.onSelect = onSelectResultMenu;
sprite.addChild(_boxContainer);
sprite.addChild(_scene.display);
sprite.addChild(_mirror);
sprite.addChild(_display);
sprite.addChild(_pause.sprite);
sprite.addChild(_result.sprite);
setGroundScale(1);
}
public function updateGround(draw:Boolean = true):void {
setGroundScale([2, 1][$.user.groundQuality], draw);
}
public function setGroundScale(scale:Number = 1, draw:Boolean = false):void {
S.setScale(scale);
if (_scene.groundMap) _scene.groundMap.dispose();
if (_race.dirtMap) _race.dirtMap.dispose();
_scene.groundMap = new BitmapData(S.QtoG(S.QRECT.right), S.QtoG(S.QRECT.bottom), true, 0);
_race.dirtMap = new BitmapData(S.QtoD(S.QRECT.right), S.QtoD(S.QRECT.bottom), false);
if (!draw) return;
drawGround(_race.track, false);
}
private function onSelectPauseMenu(index:int):Boolean {
switch (index) {
case 0: play(); break;
case 1: $.transition.fadeOutIn(reset); break;
case 2: $.setting.setEnabled(true, function():void { _pause.active(); } ); break;
case 3: $.transition.fadeOutIn(gotoTop); break;
}
return index != 2;
}
/**
* 操作説明デモ
*/
public function howto():void {
_isHowTo = true;
_isDemo = true;
destroyStage();
createStage($.world.howto);
SE.stopAll();
SE.setVolume(1);
startRace();
$.howto.onFinish = function():void {
$.transition.fadeOutIn(function():void {
_isHowTo = false;
$.howto.sprite.visible = false;
quitAndReset();
});
}
$.top.setScene(TopMenu.SCENE_HIDE);
$.howto.start();
}
/**
* 現在の難易度での全コースを1位でクリア
*/
public function complete():void {
_isComplete = true;
_isDemo = true;
_completeTimer = 30 * 7;
$.tape.start();
$.complete.show(_race.track.level);
$.top.setScene(TopMenu.SCENE_HIDE);
}
/**
* TOPへ戻る
*/
private function quit():void {
isDemo = true;
destroyCars();
_scene.destroyParticles();
_scene.destroyGhosts();
SE.stopAll();
SE.setVolume(1);
startRace();
$.top.setScene(TopMenu.SCENE_TOP);
}
/**
* バックミラーレンダリング
*/
public function drawMirror():void {
_scene.camera.horizon >> 1;
_scene.camera.view >> 1;
_scene.camera.setGazeXYZ(_player.position.x - _player.front.x, _player.position.y - _player.front.y, _player.position.z + 0.1);
_scene.camera.setPositionXYZ(_player.position.x, _player.position.y, _player.position.z + 0.5);
_scene.render();
_scene.camera.horizon << 1;
_scene.camera.view << 1;
_mirror.bitmapData.draw(_scene.display, new Matrix(-0.5, 0, 0, 0.5, _mirror.width, -20), null, null);
}
private function pause():void {
_isPlaying = false;
_sim.stop();
sprite.removeEventListener(Event.EXIT_FRAME, onTickSimurate);
}
private function play():void {
_isPlaying = true;
_sim.start();
sprite.addEventListener(Event.EXIT_FRAME, onTickSimurate);
}
private function reset():void {
destroyStage();
createStage(_race.track);
startRace();
}
private function destroyCars():void {
_player = null;
_scene.destroyCars();
}
public function destroyStage():void {
if (!_sim) return;
pause();
_race.reset();
_sim.destroy();
_contacts.removeEventListener(QuickContacts.ADD, onCollide);
while (_boxContainer.numChildren) _boxContainer.removeChildAt(0);
_scene.destroyAll();
_player = null;
}
/**
* シーン生成
* @param course コースデータ
* @param captureMode サムネイル生成モード(Box2Dは生成しない)
*/
public function createStage(track:Track, captureMode:Boolean = false):void {
var i:int, n:Number, p:Point, tp:Point, list:Array, cnt:int, leng:int, num:Number, obj:Sprite3D, qobj:QuickObject;
//コースデータを元に必要データを計算する
_race.calculate(track, captureMode);
var light:Light = new Light(track.light);
_scene.setLight(light);
_scene.destroyAll();
if (!captureMode) {
Dot.setParticleColor.apply(null, track.particleColors);
_sim = new QuickBox2D(_boxContainer, { frim:false, timeStep:1 / 30, gravityY:0, bounds:[S.QRECT.x, S.QRECT.y, S.QRECT.right, S.QRECT.bottom] } );
_contacts = _sim.addContactListener();
_contacts.addEventListener(QuickContacts.ADD, onCollide);
_sim.setDefault( { lineAlpha:0 } );
}
//ワールドの壁
for (i = 0; i < 4; i++)
addBox( { density:0, x:[ -95, 95, 0, 0][i], y:[0, 0, -95, 95][i], width:[10, 10, 180, 180][i], height:[200, 200, 10, 10][i], fillAlpha:0.5, fillColor:0x000000 }, captureMode);
//観客席
createSeats(track.seatsXY[0], track.seatsXY[1], 20, 4, captureMode);
//フェンス
var fp1:Point, fp2:Point, distance:Number;
for each(list in track.fences) {
for (i = 0; i < list.length - 1; i++) {
fp1 = new Point(list[i][0], list[i][1]);
fp2 = new Point(list[i + 1][0], list[i + 1][1]);
distance = Point.distance(fp1, fp2);
createPlaneXY(fp1.x, fp1.y, fp2.x, fp2.y, 0, track.fenceHeight, Math.ceil(distance / 8), track.fenceMap, Math.ceil(distance / track.fenceMapSize), 1, true, false, captureMode);
}
}
//板ポリゴン
for each(list in track.planes) {
for (i = 0; i < list[0].length - 1; i++) {
fp1 = new Point(list[0][i][0], list[0][i][1]);
fp2 = new Point(list[0][i + 1][0], list[0][i + 1][1]);
distance = Point.distance(fp1, fp2);
var map:BitmapData = (list[3].indexOf(".") != -1)? Dot.ads[list[3].substr(1)] : Dot[list[3]];
createPlaneXY(fp1.x, fp1.y, fp2.x, fp2.y, list[2], list[1], Math.ceil(distance / 8), map, list[5], list[6], true, false, captureMode || list[2] > 0);
if (list[4]) {
//両サイドに柱をつける
var pp:Point = fp2.subtract(fp1);
pp.normalize(0.2);
createPlaneXY(fp1.x, fp1.y, fp1.x + pp.x, fp1.y + pp.y, 0, list[2], 1, 0x404040, 1, 1, true, false, true);
pp.normalize(-0.2);
createPlaneXY(fp2.x, fp2.y, fp2.x + pp.x, fp2.y + pp.y, 0, list[2], 1, 0x404040, 1, 1, true, false, true);
}
}
}
//木・ドラム缶・コーンetc
cnt = -1;
var trees:Array = Dot.trees;
switch(track.place) {
case Track.SNOWFIELD: case Track.WINTERCIRCUIT: trees = Dot.treesSnow; break;
}
for each(list in track.lamps) createObject(list[0], list[1], 0, light.isLightUp? Dot.lampOn : Dot.lampOff, 3, true, true, true, 0.3, 0, 0.2).isEmit = light.isLightUp;
for each(list in track.trees) createObject(list[0], list[1], 0, trees[++cnt % trees.length], 10, true, true, captureMode, 0.5, 0, 0.2);
for each(list in track.objectL) createObject(list[0], list[1], 0, Dot.drum, 3, true, true, captureMode, 0.3, 0.7, 0.2);
for each(list in track.objectS) createObject(list[0], list[1], 0, Dot.cone, 3, true, true, captureMode, 0.2, 0.05, 0.2);
for each(list in track.plants) createObject(list[0], list[1], list[2], Dot.plantL, list[3], !!list[4], !!list[4], true);
for each(list in track.lakes) addCircle( { density:0, x:list[0], y:list[1], radius:list[2], fillColor:track.lakeColor }, captureMode);
if (!captureMode) {
qobj = _sim.addCircle( { density:0.02, restitution:1, radius:0.5, skin:"none" } );
_wanco = new Wanco(qobj, Create.spriteBmp(Dot.wanco, 2, -Dot.wanco.width / 2, -Dot.wanco.height), true, true, track.wancoXY[0], track.wancoXY[1], 0)
_scene.addSprite(_wanco);
}
drawGround(track, captureMode);
}
/**
* 地面テクスチャ描画
* @param track
* @param captureMode
*/
public function drawGround(track:Track, capture:Boolean):void {
var i:int, p:Point, list:Array, leng:int, num:int
_scene.groundMap.lock();
Display.cacheQuality(StageQuality.HIGH);
_race.dirtMap.fillRect(_race.dirtMap.rect, 0xFF808080);
_scene.groundMap.fillRect(_scene.groundMap.rect, 0xFF<<24 | track.dirtColor);
//コースを描画
drawLine(track, true);
//破線
if (!capture) {
leng = (_race.totalDistance / 10) | 0;
num = Math.min(track.roadSize - 6, 10) * S.DRAW;
for (i = 0; i < leng; i++) {
p = _race.getStartPos(_race.totalDistance / leng * i)[0];
Draw.circle(_circles.graphics, S.QtoG(p.x), S.QtoG(p.y), num, num, track.roadColor);
}
}
//テクスチャにコースを貼りつけ
_scene.groundMap.draw(_lines, null, null, null, null, true);
_circles.graphics.clear();
//コースアウト判定マップ
if (!capture) {
drawLine(track, false);
_race.dirtMap.draw(_lines, null, Palette.getColorTransform(0xFFFFFF), null, null, true);
}
//スタートライン
var mtx:Matrix = new Matrix();
mtx.rotate(Math.atan2(_race.checkPoints[0][0].y - _race.checkPoints[0][1].y, _race.checkPoints[0][0].x - _race.checkPoints[0][1].x));
mtx.scale(track.roadSize / 23 * S.DRAW, track.roadSize / 23 * S.DRAW);
mtx.translate(S.QtoG(_race.startingPoint.x), S.QtoG(_race.startingPoint.y));
_scene.groundMap.draw(Create.spriteBmp(Dot.startingLine, 2.8, -7, -2), mtx, null, null, null, true);
//テクスチャにノイズを焼き込む
if (!capture) _scene.groundMap.draw(Create.bitmapFillBox(0, 0, _scene.groundMap.width, _scene.groundMap.height, _noise, 1, 1), null, null, BlendMode.SUBTRACT, null, true);
_lakes.filters = [new GlowFilter(track.lakeEdge, 1, 10 * S.DRAW, 10 * S.DRAW, 2, 2, true), new GlowFilter(track.edgeColor, 1, 30 * S.DRAW, 30 * S.DRAW, 3, 1)];
for each(list in track.lakes) Draw.circle(_lakes.graphics, S.QtoG(list[0]), S.QtoG(list[1]), list[2]*S.QtoF*S.TEXTURE, list[2]*S.QtoF*S.TEXTURE, track.lakeColor);
_scene.groundMap.draw(_lakes, null, null, null, null, true);
_scene.groundMap.colorTransform(_scene.groundMap.rect, _scene.camera.light.ambientColor);
if (!capture) {
//光と影を地面に描画する
for each(list in track.trees) Draw.gradientCircle(_shadowContainer.graphics, S.QtoG(list[0]), S.QtoG(list[1]), 20 * S.DRAW, 20 * S.DRAW, [0, 0], [0.2, 0], [100, 255]);
_scene.groundMap.draw(_shadowContainer, null, null, BlendMode.NORMAL, null, true);
if (_scene.camera.light.isLightUp) {
for each(list in track.lamps) Draw.gradientCircle(_lightContainer.graphics, S.QtoG(list[0]), S.QtoG(list[1]), 25 * S.DRAW, 25 * S.DRAW, [0xffffff, 0xffffff], [1, 0], [0, 255]);
_scene.groundMap.draw(_lightContainer, null, null, BlendMode.OVERLAY, null, true);
}
//地面の元画像をストックしておく
if (_scene.rawMap) _scene.rawMap.dispose();
_scene.rawMap = _scene.groundMap.clone();
_scene.rawMap.colorTransform(_scene.rawMap.rect, Palette.getColorTransform(0, 0, 0.1));
_scene.splitRawImage();
}
_lines1.graphics.clear();
_lines2.graphics.clear();
_lakes.graphics.clear();
_lightContainer.graphics.clear();
_shadowContainer.graphics.clear();
Display.restoreQuality();
_scene.groundMap.unlock();
}
private function drawLine(track:Track, texture:Boolean = true):void {
var scale:Number = texture? S.DRAW : S.DRAW_DIRT;
var i:int, px:Number, py:Number, p:Point, list:Array;
_lines1.graphics.clear();
_lines2.graphics.clear();
_lines1.graphics.lineStyle(2 * scale, track.lineColor, 1);
_lines2.graphics.lineStyle(2 * scale, track.pathColor, 1);
for (i = 0; i <= _race.course.length; i++) {
p = _race.course[i % _race.course.length];
px = texture? S.QtoG(p.x) : S.QtoD(p.x);
py = texture? S.QtoG(p.y) : S.QtoD(p.y);
if (!i) _lines1.graphics.moveTo(px, py);
else _lines1.graphics.lineTo(px, py);
}
for each(list in track.path) {
for (i = 0; i < list.length; i++) {
px = texture? S.QtoG(list[i][0]) : S.QtoD(list[i][0]);
py = texture? S.QtoG(list[i][1]) : S.QtoD(list[i][1]);
if (!i) _lines2.graphics.moveTo(px, py);
else _lines2.graphics.lineTo(px, py);
}
}
_lines1.filters = [new GlowFilter(track.roadColor, 1, track.roadSize * scale, track.roadSize * scale, 100, 2)];
_lines2.filters = [new GlowFilter(track.pathColor, 1, track.pathSize * scale, track.pathSize * scale, 100, 2)];
_lines.filters = texture? [new GlowFilter(track.edgeColor, 1, 15 * scale, 15 * scale, 3, 2)] : [];
}
/**
* 車生成
*/
public function createCars():void {
_player = createCar(true, 0xFF4400, 2.3, 0.05);
var data:Array = _race.getStartPos(0.1);
_player.setStartPosition(data[0].x, data[0].y, data[1], _race);
createGhost();
if (_race.mode == Race.TIMETRIAL) return;
var accel:Number = [3.4 * 0.9, 4.0 * 0.9, 4.1 * 0.9][_race.track.level];
var densities:Array = [2, 0.6, 0.45, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3];
for (var i:int = 0; i < _race.track.enemiesNum; i++) {
var per:Number = (i + 1) / _race.track.enemiesNum;
var index:int = Math.min(densities.length - 1, _race.track.enemiesNum - i - 1 + 2 - _race.track.level);
var enemy:Car = createCar(false, getCarColor(index), densities[index], 0.8);
enemy.steerSpeed = (1 - Math.random() * (1 - per)) * 0.5 + 0.2;//0.2/0.5
enemy.accelFirst = enemy.accel = (accel - (1 - per)) * _race.track.handicap;
data = _race.getStartPos(200 * per);
enemy.setStartPosition(data[0].x + (Math.random() - 0.5) * 0 , data[0].y + (Math.random() - 0.5) * 0, data[1], _race);
enemy.proactiveRate = Math.random() * 0.7 + 0.6;
}
}
private function getCarColor(index:int):uint {
var colors:Array = [0x222222, 0xFFFFFF, 0x8F27BC, 0x0088FF, 0x2FE6CF, 0x33CC33, 0xFFE31A, 0xFF9411, 0x936300, 0];
var rgb:uint = colors[Math.min(index, colors.length - 1)];
if (!rgb) rgb = Math.random() * 0xFFFFFF;
return rgb;
}
public function createGhost(skipLast:Boolean = false, offset:int = 0):void {
var cars:Vector.<Car> = new Vector.<Car>();
for (var i:int = 0; i < $.replay.data.length; i++) {
var data:ReplayData = $.replay.data[i];
if (data.trackID != _race.track.id || (skipLast && $.replay.last === data)) continue;
var car:Car = createCar(false, getCarColor(i));
car.setGhost(data.clone());
car.replay.startReplay(true, offset);
}
updateGhostVisible();
}
public function updateGhostVisible():void {
for each(var c:Car in _scene.cars) {
if (c.isGhost) c.ghostVisible = $.user.showGhost;
}
}
private function addCircle(param:Object, noBody:Boolean = false):Sprite {
if (noBody) return null;
var qobj:QuickObject = _sim.addCircle(param);
return qobj.userData;
}
private function addBox(param:Object, noBody:Boolean = false):Sprite {
if (noBody) return null;
var qobj:QuickObject = _sim.addBox(param);
return qobj.userData;
}
//観客席を作る
private function createSeats(x:Number, y:Number, height:Number = 20, segments:int = 3, noBody:Boolean = false):void {
var width:Number = 10;
var p:Point = new Point(x - width / 2, y - height / 2);
createPlaneXY(p.x, p.y, p.x + width, p.y, 0, 5, 1, Dot.audienceSide, -1, 1, true, false, true);
createPlaneXY(p.x, p.y + height, p.x + width, p.y + height, 0, 5, 1, Dot.audienceSide, -1, 1, true, false, true);
createPlaneXY(p.x + width - 0.1, p.y, p.x + width - 0.1, p.y + height, 4.2, 7, segments, Dot.audienceRoof, -20, 1, true, false, true).forEach(function(...arg):void { arg[0].sprite.rotationX = 172; }, null);
createPlaneXY(p.x + 0.1, p.y, p.x + 0.1, p.y + height, 0.5, 9, segments, Dot.audienceSeats, -10, 4, true, false, true).forEach(function(...arg):void { arg[0].sprite.rotationX = 15; }, null);
createPlaneXY(p.x + width, p.y, p.x + width, p.y + height, 0, 3.5, segments, 0x808080, 1, 1, false, true, true);
createPlaneXY(p.x + width, p.y, p.x + width, p.y + height, 2.9, 0.6, segments, 0x666666, 1, 1, false, false, true);
createPlaneXY(p.x, p.y, p.x, p.y + height, 0, 0.5, segments, 0xDDDDDD, 1, 1, false, false, true);
addBox( { density:0, x:x, y:y, width:width, height:height, fillColor:0x444444 }, noBody)
}
private function onCollide(e:Event):void {
if (_isDemo || !_contacts.inCurrentContact(_player.qobject)) return;
if (!_wanco.active && _contacts.inCurrentContact(_wanco.qobject)) _wanco.love(_player);
if (_sceneTime - _collideTime <= 1) return;
_collideTime = _sceneTime;
var v:Number = _contacts.currentPoint.velocity.Length();
if (v<1.5) return;
var i:int = v < 4? 0 : v < 8? 1 : v < 15? 2 : 3;
SE.note(SE.OMP_COLLISIONS[i]);
}
private function createCar(isPlayer:Boolean = true, rgb:uint = 0xC80000, density:Number = 0.3, restitution:Number = 0.8):Car {
var car:Car = new Car(_sim, isPlayer, rgb, density, restitution, _distanceEstimator);
car.qobject.angle = Math.PI;
car.sprite.graphics.clear();
var p:Point = new Point( -Dot.carBase.width / 2, -Dot.carBase.height / 2);
var scale:Number = 1.6;
var carFrame:BitmapData = Dot.carFrame(Palette.mix(rgb, 0xFFFFFF, 0.5), rgb, Palette.mix(rgb, 0, 0.2));
var carWing:BitmapData = Dot.carWing(Palette.mix(rgb, 0xFFFFFF, 0.5), rgb, Palette.mix(rgb, 0, 0.2));
car.sprite.addChild(Create.bitmap(Dot.carBase, scale, p.x, p.y)).z = -1;
car.sprite.addChild(Create.bitmap(carFrame, scale, p.x + 1, p.y)).z = -2.5;
car.sprite.addChild(Create.bitmap(carWing, scale, p.x + 1, p.y + 21)).z = -6;
car.shredder.addData(carFrame, carWing);
_scene.addSprite(car);
_scene.addLight(car.light3D);
_display.map.addChild(car.mapMark);
_display.markContainer.addChild(car.rankMark);
return car;
}
private function createPlaneXY(x1:Number, y1:Number, x2:Number, y2:Number, z:Number, height:Number, segments:int = 1, material:* = 0x808080, loopW:Number = 1, loopH:Number = 1, two:Boolean = true, reverse:Boolean = false, noBody:Boolean = false):Vector.<Sprite3D> {
return createPlane(new Point(x1, y1), new Point(x2, y2), z, height, segments, material, loopW, loopH, two, reverse, noBody);
}
private function createPlane(p1:Point, p2:Point, z:Number, height:Number, segments:int = 1, material:* = 0x808080, loopW:Number = 1, loopH:Number = 1, two:Boolean = true, reverse:Boolean = false, noBody:Boolean = false):Vector.<Sprite3D> {
var i:int, pts:Array = [], width:Number = Point.distance(p1, p2), angle:Number = Math.atan2(p2.y - p1.y, p2.x - p1.x);
var list:Vector.<Sprite3D> = new Vector.<Sprite3D>();
for (i = 0; i < segments; i++) {
var dp1:Point = Point.interpolate(p1, p2, i / segments);
var dp2:Point = Point.interpolate(p1, p2, (i + 1) / segments);
var w:Number = width / segments;
var sp:Sprite = new Sprite();
if (material is uint) sp.graphics.beginFill(material, 1);
if (material is BitmapData) sp.graphics.beginBitmapFill(material, new Matrix(w / loopW * segments * S.QtoF / material.width, 0, 0, height * S.QtoF / material.height / loopH, w * S.QtoF * (0.5 + i), 0));
if(height) sp.graphics.drawRect( -w / 2 * S.QtoF, -height * S.QtoF, w * S.QtoF, height * S.QtoF);
sp.graphics.endFill();
list.push(_scene.addSprite(new Sprite3D(sp, false, true, (dp1.x + dp2.x) / 2, (dp1.y + dp2.y) / 2, z, angle * Angle.toROT, two, reverse)));
}
addBox( { density:0, restitution:0.1, x:(p1.x + p2.x) / 2, y:(p1.y + p2.y) / 2, width:width, height:0.5, angle:angle, skin:"none", bullet:false }, noBody);
return list;
}
private function createObject(xp:Number, yp:Number, zp:Number, bmd:BitmapData, scale:Number = 1, lookAt:Boolean = true, stand:Boolean = true, noBody:Boolean = false, radius:Number = 0.3, density:Number = 1, restitution:Number = 0.2):Sprite3D {
var sp:Sprite3D;
if (noBody) {
var slideH:Number = (!lookAt && !stand)? -bmd.height / 2 : -bmd.height;
sp = _scene.addSprite(new Sprite3D(Create.spriteBmp(bmd, scale, -bmd.width / 2, slideH), lookAt, stand, xp, yp, zp));
} else {
var qobj:QuickObject = _sim.addCircle( { density:density, restitution:restitution, x:xp, y:yp, radius:radius, skin:"none" } );
sp = _scene.addSprite(new QuickBox3D(qobj, Create.spriteBmp(bmd, scale, -bmd.width / 2, -bmd.height), lookAt, stand, xp, yp, zp));
}
return sp;
}
/**
* カウントダウン開始
*/
public function startRace():void {
$.game.display.hideBack();
createCars();
_race.key = _keyUD = 0;
_sceneCam.setStartingPos();
_countDown = _countInterval * (_countNum + 1);
_isRecording = _isRunning = _isFinish = false;
_lap = 1;
_sim.start();
if (_isHowTo) {
setCamera(SceneCamera.BEHIND);
_player.autoSteer = false;
startRun();
} else if (_isComplete) {
setCamera(SceneCamera.COMPLETE);
_player.autoSteer = true;
startRun();
} else if (_isDemo) {
setCamera(SceneCamera.DEMO);
_player.autoSteer = true;
startRun();
} else {
setCamera(SceneCamera.BEHIND);
_display.setCourseData(_race.track);
_display.setMessage(true, "");
_display.setMessage(false, "");
}
updateDisplay();
_scene.render();
play();
}
public function setCamera(type:int):void {
_sceneCam.cameraType = type;
updateDisplay();
}
public function startRun():void {
_sceneTime = _collideTime = 0;
_time = _startTime = getSceneTime();
_isReplay = _inResultView = false;
_isRecording = _isRunning = true;
if(!_isDemo) _scene.startRecord();
}
/**
* キー入力
*/
public function keyUpDown(e:KeyboardEvent):void {
if (_isDemo) return;
var isDown:Boolean = (e.type == KeyboardEvent.KEY_DOWN);
switch(e.keyCode) {
case 38: _keyUD = (isDown)? _keyUD | 0xF000 : _keyUD & 0x0FFF; break;
case 90: _keyUD = (isDown)? _keyUD | 0x0F00 : _keyUD & 0xF0FF; break;
case 40: _keyUD = (isDown)? _keyUD | 0x00F0 : _keyUD & 0xFF0F; break;
case 88: _keyUD = (isDown)? _keyUD | 0x000F : _keyUD & 0xFFF0; break;
case Keyboard.LEFT: _race.key = (isDown)? _race.key | 0x00F00 : _race.key & 0xFF0FF; break;
case Keyboard.RIGHT: _race.key = (isDown)? _race.key | 0x000F0 : _race.key & 0xFFF0F; break;
}
if(isDown)
{
_race.reverse = !(_keyUD & 0xFF00);
_race.reverse = (_keyUD & 0x00FF);
}
_race.key = (_keyUD & 0xFF00)? _race.key | 0xF0000 : _race.key & 0x0FFFF;
_race.key = (_keyUD & 0x00FF)? _race.key | 0x0F000 : _race.key & 0xF0FFF;
if (!isDown) switch(e.keyCode) {
case 88: case Keyboard.SHIFT: case 90: case Keyboard.ENTER://Z,Enter,X,SHIFT
if (_isReplay && !$.transition.isFading) endReplay();
break;
case 67://C
changeCamera();
updateDisplay();
_scene.render();
break;
case Keyboard.CONTROL:
if (!_isFinish && !$.transition.isFading) {
pause();
_pause.active();
SE.stopAll();
}
break;
}
}
private function changeCamera():void {
if (_isReplay || _isDemo) return;
_sceneCam.swap();
updateDisplay();
}
private function endReplay():void {
$.transition.fadeOutIn(function():void {
_isReplay = _isRecording = false;
_display.replay.visible = false;
_scene.destroyGhosts();
gotoTop();
});
}
public function startReplay():void {
updateGround();
_sceneTime = 0;
_sceneCam.startReplay();
_display.replay.visible = true;
_isReplay = _isRecording = true;
_sim.stop();
setCamera(SceneCamera.REPLAY);
_scene.startReplay();
_scene.destroyGhosts();
if(_race.isTimeTrial) createGhost(true, -$.replay.last.timeCount);
}
/**
* シーンやカメラが変化した時に画面の表示を更新する
*/
public function updateDisplay():void {
if (_player) {
_player.isAlwaysLight = _sceneCam.cameraType == SceneCamera.DRIVERS;
_player.visible = (_isDemo || _isReplay || _sceneCam.cameraType == SceneCamera.BEHIND);
}
_scene.camera.ground = 900 + 300 * $.user.viewDistance;
_scene.camera.view = 1100 + 300 * $.user.viewDistance;
_scene.updateLight();
_scene.updateFog();
_mirrorCnt = -1;
_mirror.visible = _sceneCam.cameraType == SceneCamera.DRIVERS && $.user.showMirror;
_display.display.visible = !isDemo && !_inResultView && !_isReplay;
}
///===========================================================
/// ゲームのメイン処理
///===========================================================
private function onTickSimurate(e:Event = null):void {
_scene.groundMap.lock();
var i:int, qobj:QuickObject, car:Car;
_sceneTime++;
if ((!_isDemo || _isHowTo) && (!_isFinish || _isReplay)) SE.update(_player);
if (!_isDemo && _countDown > 0) tickCountDown();
if (_isHowTo) {
$.howto.tick();
_race.key = $.howto.key;
}
_race.key = _race.reverse?(_race.key | 0x0F000):(_race.key | 0xF0000);
/*cheat*/
if (_isComplete && --_completeTimer<=0) {
_isComplete = false;
$.transition.fadeOutIn(onFinishCompleteScene);
}
if (_wanco.active && _sceneTime % 10 == 0) _scene.addParticle(Dot.heart, 1, 1.5, 2, 30, _wanco.point.x + (Math.random() - 0.5), _wanco.point.y + (Math.random() - 0.5), 1, 2);
for each (car in _scene.cars) car.stockPrev();
if (_mirror.visible && ++_mirrorCnt % 2 == 0) drawMirror();
//リプレイ処理
if (_isRecording && _isReplay) {
_scene.tickRecord();
if (_player.replay.isFinish) repeatReplay();
}
_sceneCam.update(_sceneTime);
_scene.camera.setPosition(_sceneCam.vector.position);
_scene.camera.setGaze(_sceneCam.vector.gaze);
//レンダリング
_scene.render();
_scene.fadeTireTrack();
for each (car in _scene.cars) car.updateMark();
if (_isRecording && !_isReplay && !_inResultView) _scene.tickRecord();
if (_isRunning) {
var layRubber:Number = $.user.groundQuality? 0.7 : 0.75;
//車の処理
for each (car in _scene.cars) {
car.simulate(_race);
if (car.speedRate > 0.2) {
//パーティクル
if ($.user.showParticles && (car.visible || car.isAlwaysLight) && _sceneTime % 3 == 0) {
if (car.slip > 0.8) _scene.addParticle(Math.random() > 0.5? Dot.smoke1 : Dot.smoke2, 0.6, 3, 8, Math.random()*30+15, car.position.x, car.position.y, car.position.z, car.position.z + 1);
if (car.dirtRate > 0.2) _scene.addParticle(Dot.grassParticle, 1, 2.5, 2.5, 20, car.position.x + (Math.random() - 0.5), car.position.y + (Math.random() - 0.5), car.position.z, car.position.z + 0.5);
}
//タイヤの跡
if (car.slip > 0.8 || car.dirtRate > 0.2) {
Pixel.drawDarkLine(_scene.groundMap, S.QtoG(car.tireL.x), S.QtoG(car.tireL.y), S.QtoG(car.tireLprev.x), S.QtoG(car.tireLprev.y), layRubber, true);
Pixel.drawDarkLine(_scene.groundMap, S.QtoG(car.tireR.x), S.QtoG(car.tireR.y), S.QtoG(car.tireRprev.x), S.QtoG(car.tireRprev.y), layRubber, true);
}
}
}
if (!_isFinish && !_isDemo && !_isReplay) {
var lapTime:int = getSceneTime() - _time;
_race.raceTime = getSceneTime() - _startTime;
_display.setTotalTime(_race.raceTime);
_display.setLapTime(lapTime);
//順位チェック
_scene.cars.sort(function(a:Car, b:Car):int { return int(a.lap < b.lap) - int(a.lap > b.lap) } );
for (i = 0; i < _scene.cars.length; i++) {
_scene.cars[i].setRank(i + 1);
if (_race.track.level == Race.EXTREME && !_scene.cars[i].isPlayer && _scene.cars[i].lap < _player.lap && _scene.cars[i].nitro == 0) _scene.cars[i].chargeNitro();
}
_display.setRank(_player.rank);
//周回チェック
if (_player.lap >= _lap) {
_race.lapsTime.push(lapTime);
_display.setLapNum((_player.lap | 0)+1);
var newLapRecord:Boolean = checkLapRecord(lapTime);
if (newLapRecord) _race.newLapRecord = true;
_display.setMessage(false, Text.getTimeString(lapTime), 1, 3000, (newLapRecord)? UI.HIGHLIGHT : 0xFFFFFF);
if (_race.track.lapsNum - _lap == 1) _display.setMessage(true, "FINAL LAP", 1, 3000, UI.HIGHLIGHT);
//FINISH
if (_isFinish = (_lap++ == _race.track.lapsNum)) {
_race.rank = _player.rank;
_player.replay.setFinish(_race);
checkTotalRecord();
onFinish();
}
_display.addLapTime(lapTime, _isFinish);
SE.effect((_isFinish)? SE.SND_FINISH : (_lap == _race.track.lapsNum)? SE.SND_FINAL : (newLapRecord)?SE.SND_NEWRECORD : SE.SND_LAP);
_time = getSceneTime();
}
}
_display.setSpeed(_player.speed);
}
//BOX2D摩擦
if (!_isReplay) _scene.updateQuickBox();
//画面の揺れ
if (!_isDemo && !_isReplay) {
_scene.display.x = _player.dirtRate * _player.speedRate * Math.random() * 8;
_scene.display.y = _player.dirtRate * _player.speedRate * Math.random() * 8;
}
_scene.groundMap.unlock();
}
private function onFinishCompleteScene():void {
$.tape.stop();
$.complete.hide();
quitAndReset();
}
public function quitAndReset():void {
destroyStage();
createStage($.world.demo);
quit();
}
public function getSceneTime():int {
return _sceneTime * 33;
}
private function repeatReplay():void {
$.transition.fadeOutIn(startReplay);
}
//ハイスコアチェック
private function checkTotalRecord():void {
if (_race.isRandom) return;
var bestRace:int = $.user.bestTotals[_race.track.id];
var bestRank:int = $.user.bestRank[_race.track.id];
if (!_race.isTimeTrial && !_race.isWonderfl && (_race.rank < bestRank || bestRank < 0)) {
_race.newRankRecord = true;
$.user.bestRank[_race.track.id] = _race.rank;
}
if (_race.raceTime < bestRace || bestRace < 0) {
_race.newRaceRecord = true;
$.user.bestTotals[_race.track.id] = _race.raceTime;
}
$.user.save();
}
//LAPタイムチェック
private function checkLapRecord(time:int):Boolean {
if (_race.isRandom) return false;
var record:int = $.user.bestLaps[_race.track.id];
if (time < record || record < 0) {
_race.newLapRecord = true;
_race.fastLapTime = time;
$.user.bestLaps[_race.track.id] = time;
$.user.save();
return true;
} else return false;
}
//カウントダウン
private function tickCountDown():void {
if (--_countDown / _countInterval <= _countNum && _countDown % _countInterval == 0) {
if (!_countDown) {
_display.setMessage(true, "GO", 3, 1500, UI.HIGHLIGHT);
startRun();
} else _display.setMessage(true, String(_countDown / _countInterval), 3, 0);
SE.effect((_countDown)? SE.SND_COUNT : SE.SND_GO);
}
}
//ゴール
private function onFinish():void {
if (_player.rank == 1 && !_race.isTimeTrial && _race.track.enemiesNum > 0) _display.setMessage(true, Text.WINNER, 3, 4000, UI.WINNER);
else _display.setMessage(true, Text.FINISH, 3, 4000, UI.HIGHLIGHT);
_player.autoSteer = true;
FrameTimer.setTimer(30 * 3, showResult, null);
}
//結果画面
private function showResult():void {
_isRecording = false;
SE.stopAll();
_scene.stopRecord();
if(_race.mode == Race.TIMETRIAL) $.replay.add(_player.replay.clone());
_inResultView = true;
_result.setResult(_race);
updateDisplay();
//アンロック確認
$.world.checkRankIn($.user);
_result.setMessgae($.user.setUnlockedNum($.world.getUnlockedNum($.user))? Text.UNLOCK_TRACK : "");
_complete = $.world.checkComplete($.user);
$.user.save();
}
private function onSelectResultMenu(index:int):void {
_inResultView = false;
switch(index) {
case 0: $.transition.fadeOutIn(startReplay); break;
case 1: $.transition.fadeOutIn(reset); break;
case 2: $.transition.fadeOutIn(gotoTop); break;
}
}
private function gotoTop():void {
if (_complete == -1) {
quit();
return;
}
complete();
}
}
/**
* 紙吹雪エフェクト
*/
class TickerTape {
public var sprite:Sprite = new Sprite();
public var tapes:Vector.<Tape> = new Vector.<Tape>();
public function TickerTape() {
for (var i:int = 0; i < 30; i++) addTape();
}
public function start():void {
sprite.visible = true;
for each(var tape:Tape in tapes) tape.reset();
sprite.addEventListener(Event.ENTER_FRAME, onTick);
}
public function addTape():Tape {
var tape:Tape = new Tape();
tape.reset();
sprite.addChild(tape);
tapes.push(tape);
return tape;
}
public function stop():void {
sprite.visible = false;
sprite.removeEventListener(Event.ENTER_FRAME, onTick);
}
private function onTick(e:Event):void {
for each(var tape:Tape in tapes) {
tape.tick();
tape.x += tape.vx;
tape.y += tape.vy;
if (tape.x > Display.width || tape.y > Display.height) tape.reset();
}
}
}
/**
* 紙吹雪用テープ
*/
class Tape extends Bitmap {
public var vx:Number = 1;
public var vy:Number = 1;
private var _frame:int = 0;
private var _images:Array = [];
private var _limit:int = 20;
public function Tape() {
super();
vx = Math.random() * 1 + 1;
vy = Math.random() * 2 + 1;
_frame = Math.random() * 20;
_images = [Dot.papers[0], Dot.papers[1], Dot.papers[2], Dot.papers[1]];
}
public function tick():void {
_frame = ++_frame % _limit;
bitmapData = _images[_frame / 5 | 0];
}
public function reset():void {
x = Math.random() * 465 - 100;
y = Math.random() * 30 - 50;
}
}
/**
* ドリフト解説
*/
class HowTo {
public var sprite:Sprite = new Sprite();
public var key:uint = 0x000000;
private var _active:Boolean = false;
private var _lastKey:uint = 0;
private var _time:int = 0;
private var _step:int = 0;
private var _isFinish:Boolean = false;
private var _message:Label;
private var _press:Object = {};
private var _keys:Array = [
[72, 0xf0000], [233, 0xf0f00], [255, 0xf00], [259, 0xf0f00, true], [293, 0xf0000, false], [388, 0xf00f0], [412, 0xf0],
[421, 0xf00f0, true], [447, 0xf0000, false], [456, 0xf0f00], [464, 0xf0000], [501, 0xf0f00], [530, 0xf00], [536, 0xf0f00, true],
[554, 0xf0000, false], [577, 0xf00f0], [580, 0xf0000], [636, 0xf0f00], [660, 0xf00], [667, 0xf0f00, true], [683, 0xf0000],
[695, 0xf00f0], [731, 0xf0000, false], [745, 0xf0f00], [755, 0xf00], [760, 0xf0f00, true], [779, 0xf0000, false], [789, 0xf00f0],
[793, 0xf0000], [906, 0xf0f00], [925, 0xf00], [932, 0xf0f00, true], [957, 0xf0000, false], [987, 0xf00f0], [995, 0xff000], [1100, 0xff000]
];
public var onFinish:Function;
public function HowTo() {
_press.Z = sprite.addChild(Create.spriteBmp(Dot.Z, 6, 0, 0, 60, 100));
_press.X = sprite.addChild(Create.spriteBmp(Dot.X, 6, 0, 0, 130, 100));
_press.L = sprite.addChild(Create.spriteBmp(Dot.L, 6, 0, 0, 260, 100));
_press.R = sprite.addChild(Create.spriteBmp(Dot.R, 6, 0, 0, 330, 100));
_message = UI.createLabel(sprite, 190, 200, "DRIFT", 8 * 3, UI.HIGHLIGHT);
_message.filters = UI.TEXT_FILTERS;
UI.createLabel(sprite, 150, 45, Text.DEMO).filters = UI.TEXT_FILTERS;
sprite.visible = false;
}
/*
public function record(key:uint):void {
_time++;
if (_lastKey == key) return;
_lastKey = key;
trace("[" + _time + ", " + "0x"+key.toString(16) + "],");
}
*/
public function keyUpDown(e:KeyboardEvent):void {
if (!_active || $.transition.isFading || e.type == KeyboardEvent.KEY_DOWN || _time < 30) return;
switch(e.keyCode) {
case Keyboard.SHIFT: case 88:
end();
break;
}
}
public function start():void {
$.game.display.showBack(Text.LABEL_QUIT);
_time = _step = key = 0;
sprite.visible = true;
_isFinish = false;
_message.visible = false;
_active = true;
for (var k:String in _press) _press[k].transform.colorTransform = Palette.getColorTransform(0, 0.6, 1);
}
public function end():void {
if (_isFinish) return;
_isFinish = true;
_active = false;
if (onFinish != null) onFinish();
}
public function tick():void {
if (_step >= _keys.length) return;
_time++;
if (_keys[_step][0] == _time) {
key = _keys[_step][1];
if(_keys[_step][2] != null) _message.visible = _keys[_step][2];
_press.Z.transform.colorTransform = Palette.getColorTransform(0, 0.6 * int(!(key & 0xF0000)), 1);
_press.X.transform.colorTransform = Palette.getColorTransform(0, 0.6 * int(!(key & 0x0F000)), 1);
_press.L.transform.colorTransform = Palette.getColorTransform(0, 0.6 * int(!(key & 0x00F00)), 1);
_press.R.transform.colorTransform = Palette.getColorTransform(0, 0.6 * int(!(key & 0x000F0)), 1);
_step++;
if (_step >= _keys.length) end();
}
}
}
class SceneCamera {
static public const DRIVERS:int = 0;
static public const BEHIND:int = 1;
static public const REPLAY:int = 2;
static public const DEMO:int = 3;
static public const AROUND:int = 4;
static public const COMPLETE:int = 5;
public var vector:CameraVector = new CameraVector();
public var cameraType:int = DEMO;
private var _replayCameraTime:int = 0;
private var _replayCameraCount:int = 0;
private var _replayCameraType:int = 0;
private var _replayCameraPos:Vector3D = new Vector3D();
private var _replayTargetCar:Car;
private var _trackingSpeed:Number = 0.25;
private var _cameraSpeed:Number = 0;
public function SceneCamera() {
}
public function swap():void {
cameraType = cameraType == BEHIND? DRIVERS : BEHIND;
}
public function startReplay():void {
_replayCameraTime = 0;
_replayCameraCount = -1;
}
public function setStartingPos():void {
_cameraSpeed = 0;
vector.moveOffsetXYZ(1, 15, -0.4, 1);
}
public function update(time:int):void {
var t:Number;
var player:Car = $.game.player;
_cameraSpeed += (_trackingSpeed - _cameraSpeed) * 0.01;
switch(cameraType) {
case AROUND:
t = time / 100;
vector.movePosition(player.position.add(new Vector3D(Math.cos(t) * 5, Math.sin(t) * 5, 2)), 1);
vector.moveGaze(player.position, 1);
break;
case DEMO:
t = time / 180;
var per:Number = (Math.sin(t / 1.5) + 1) * 0.5;
vector.movePosition(Vector3DUtil.mix(player.position.add(new Vector3D(Math.cos(t * 2.5) * 4, Math.sin(t * 2.5) * 4, 3)), new Vector3D(Math.cos(t) * 70, Math.sin(t) * 70, 8), per), 1);
vector.moveGaze(player.position, 1);
break;
case COMPLETE:
t = -time / 50;
vector.movePosition(player.position.add(new Vector3D(Math.cos(t) * 4, Math.sin(t) * 4, 2)), 1);
vector.moveGaze(player.position.add(new Vector3D(0, 0, 2)), 1);
break;
case BEHIND:
vector.moveGazeXYZ(player.qobject.x, player.qobject.y, 1.2, 1);
if (!$.game.isFinish || $.game.isReplay) vector.moveOffsetXYZ(player.front.x * -2.6, player.front.y * -2.6, 0.4, _cameraSpeed);
break;
case DRIVERS:
vector.moveGazeXYZ(player.qobject.x + player.front.x * 2.5, player.qobject.y + player.front.y * 2.5, 0.8, 1);
vector.moveOffsetXYZ(player.front.x * -2.5, player.front.y * -2.5, 0.05, 1);
break;
case REPLAY:
updateReplayCamera();
break;
}
vector.tick();
}
//リプレイ用カメラ
private function updateReplayCamera():void {
var rnd:int, c:Car, min:Number, d:Number;
var player:Car = $.game.player;
var cars:Vector.<Car> = $.game.scene.cars;
if (_replayCameraCount > 0) _replayCameraCount--;
if (_replayCameraCount <= 0) {
_replayCameraTime = 0;
rnd = Math.random() * 3;
if (_replayCameraCount == -1) rnd = 1;
if (rnd == 2) {
_replayCameraType = 2;
_replayCameraCount = 30 * 7;
min = Number.MAX_VALUE;
for each (c in cars) {
if (!c.isPlayer) {
d = Point.distance(c.point, player.point)
if (min > d) {
min = d;
_replayTargetCar = c;
}
}
}
if (min > 25) rnd = Math.random() * 2;
}
if (rnd ==0) {
if (player.speed > 10) {
_replayCameraPos.x = player.point.x + player.velocity.x * 30 * 1 + (Math.random() - 0.5) * 10;
_replayCameraPos.y = player.point.y + player.velocity.y * 30 * 1 + (Math.random() - 0.5) * 10;
_replayCameraPos.z = Math.random() * 3 + 1;
_replayCameraType = 0;
_replayCameraCount = 30 * 2.5;
} else rnd = 1;
}
if (rnd == 1) {
_replayCameraType = 1;
_replayCameraCount = 30 * 14;
}
}
_replayCameraTime++;
if (_replayCameraType == 1) {
var time:Number = _replayCameraTime / 100;
var per:Number = (Math.cos(time*1.2) + 1) * 0.5;
var rad:Number = Math.atan2(player.point.y, player.point.x) + Angle.toRAD * 38 - _replayCameraTime / 300;
var pos:Vector3D = new Vector3D(Math.cos(rad) * 70, Math.sin(rad) * 70, 12);
_replayCameraPos = Vector3DUtil.mix(player.position.add(new Vector3D(Math.cos(time) * 7, Math.sin(time) * 7, 3)), pos, per);
}
var speed:Number = 1;
if (_replayCameraType == 2) {
var v:Point = player.point.subtract(_replayTargetCar.point);
v.normalize(4 + _replayCameraTime/100);
_replayCameraPos = player.position.add(new Vector3D(v.x, v.y, 1.5 + _replayCameraTime / 70));
if (_replayCameraTime == 1) speed = 1;
else speed = 0.1;
}
vector.movePosition(_replayCameraPos, speed);
vector.moveGaze(player.position, 1);
SE.setVolume(Math.max(0, 1 - player.position.subtract($.game.scene.camera.position).length / 30));
}
}
/**
* 背景画像
*/
class BackGround extends Sprite {
private var _zoom:int = 2;
private var _mtx:Matrix = new Matrix(_zoom, 0, 0, _zoom);
private var _bmd:BitmapData = new BitmapData(1900 / _zoom, 170 / _zoom);
private var _clouds:Vector.<BitmapData> = new Vector.<BitmapData>();
private var _fogBox:Sprite;
public function BackGround() {
}
public function init():void {
_fogBox = Create.box(0, 0, Display.width, 100, 0, 1, 0, -5);
addChild(_fogBox);
var i:int, n:int, h:Number, c:BitmapData;
for (n = 0; n < 3; n++) {
_clouds[n] = new BitmapData(_bmd.width, 55 / _zoom, true, 0);
for (i = 0; i < 13; i++) {
h = (i % 2 * 15 + 40);
c = Create.smoke(250 / _zoom, h / _zoom, i + 50, 0.7 - n * 0.2, 0);
_clouds[n].copyPixels(c, c.rect, new Point((i * 140 + i % 3 * 20) / _zoom, _clouds[n].height - h / _zoom), null, null, true);
c.dispose();
}
}
}
public function draw(light:Light):void {
_bmd.draw(Create.gradientBox(0, 0, _bmd.width, _bmd.height, true, 90, [light.sky, light.horizon, light.fog], [1, 1, 1], [0, light.horizonPer* 200, 200]));
if (light.hasStars) for (i = 0; i < 100; i++) _bmd.setPixel(Math.random() * _bmd.width, Math.random() * _bmd.height / 2, Palette.mix(light.sky, 0xFFE033, i / 100 * 0.7 + 0.3));
var i:int, rgb:uint, cloudDark:uint = Palette.mix(light.horizon, light.sky, 0.2);
for (i = 0; i < 3; i++) {
rgb = Palette.mix(light.cloud, cloudDark, 1 - i / 2);
_clouds[i].colorTransform(_clouds[i].rect, Palette.getColorTransform(rgb));
_bmd.copyPixels(_clouds[i], _clouds[i].rect, new Point(0, _bmd.height - 55 / _zoom - _clouds[i].height), null, null, true);
}
slide(0);
_fogBox.transform.colorTransform = Palette.getColorTransform(light.fog, 1);
}
public function slide(per:Number):void {
_mtx.tx = _bmd.width * _zoom * per;
graphics.clear();
graphics.beginBitmapFill(_bmd, _mtx, true, false);
graphics.drawRect(0, -_bmd.height * _zoom, 465, _bmd.height * _zoom);
}
}
/**
* プレイ中に必要な情報色々
*/
class Race {
static public var SINGLE:int = 0;
static public var TIMETRIAL:int = 1;
static public var WONDERFL:int = 2;
static public var RANDOM:int = 3;
static public var NORMAL:int = 0;
static public var HARD:int = 1;
static public var EXTREME:int = 2;
static public var LEVELS:Array = [NORMAL, HARD, EXTREME];
/**現在のトラックデータ*/
public var track:Track;
/**ゲームモード*/
public var mode:int;
/**キー入力データ*/
public var key:uint = 0x00000;
/**減速するエリア*/
public var dirtMap:BitmapData;
/**コース形状*/
public var course:Vector.<Point> = new Vector.<Point>();
/**各区画における対応チェックポイント番号*/
public var lineID:Vector.<int> = new Vector.<int>();
/**チェックポイントリスト*/
public var checkPoints:Vector.<Vector.<Point>> = new Vector.<Vector.<Point>>();
/**次のコーナーまでの長さ*/
public var distances:Vector.<Number> = new Vector.<Number>();
public var totalDistance:Number = 0;
public var startingPoint:Point;
public var startingOffsetPer:Number = 0.5;
public var rank:int = 0;
public var fastLapTime:int = 0;
public var raceTime:int = 0;
public var lapsTime:Array = [];
public var newRankRecord:Boolean = false;
public var newRaceRecord:Boolean = false;
public var newLapRecord:Boolean = false;
public var reverse:Boolean = false;
public function get isRandom():Boolean { return mode == RANDOM; }
public function get isSingle():Boolean { return mode == SINGLE; }
public function get isTimeTrial():Boolean { return mode == TIMETRIAL; }
public function get isWonderfl():Boolean { return mode == WONDERFL; }
public function Race() {
}
public function calculate(data:Track, rough:Boolean = false):void {
var i:int, cnt:int, list:Array, p1:Array, p2:Array, bezList:Vector.<Point>, pointList:Array = [];
reset();
track = data;
course.length = checkPoints.length = 0;
for each (list in data.points) {
if (list.length < 6) {
list[2] = list[4] = 0;
list[3] = list[5] = 0;
}
pointList.push([new Point(list[0], list[1]), new Point(list[0] + list[2], list[1] + list[3]), new Point(list[0] + list[4], list[1] + list[5])]);
}
var segments:int = rough? 3 : 10;
for (i = 0; i < pointList.length; i++) {
p1 = pointList[i % pointList.length];
p2 = pointList[(i+1) % pointList.length];
bezList = CurveUtil.getBezierList(p1[0], p2[0], p1[1], p2[2], segments);
bezList.pop();
course = course.concat(bezList);
}
//チェックポイント
for each (list in data.checkPoints) checkPoints.push(Vector.<Point>([new Point(list[0], list[1]), new Point(list[2], list[3])]));
//長さ計算
totalDistance = distances.length = 0;
var d:Number, leng:int = course.length;
for (i = 0; i < leng; i++) {
d = course[i].subtract(course[(i + 1 + leng) % leng]).length;
distances.push(d);
totalDistance += d;
}
//スタートライン
startingPoint = null;
var startIndex:int = -1;
if (checkPoints.length > 0) {
for (i = 0; i < course.length; i++) {
var cross:Point = LineUtil.crossSegment(course[i], course[(i + 1) % course.length], checkPoints[0][0], checkPoints[0][1]);
if (cross) {
startingPoint = cross;
startIndex = i;
break;
}
}
}
if (startIndex > 0) {
course = course.concat(course.splice(0, startIndex));
distances = distances.concat(distances.splice(0, startIndex));
}
if (!startingPoint) startingPoint = Point.interpolate(course[0], course[1], 0.5);
//スタート位置のライン上の割合
startingOffsetPer = Point.distance(startingPoint, course[0]) / distances[0];
var cp:Vector.<Point>;
cnt = 0;
for (i = 0; i < course.length - 1 && cnt < checkPoints.length; i++) {
cp = checkPoints[cnt];
lineID[i] = cnt;
if (LineUtil.isCrossXY(course[i].x, course[i].y, course[i + 1].x, course[i + 1].y, cp[0].x, cp[0].y, cp[1].x, cp[1].y)) cnt++;
}
}
//チェックポイントのどっち側にいるか
public function checkSide(id:int, car:Car):Boolean {
var p0:Point = checkPoints[id][0];
var p1:Point = checkPoints[id][1];
return VectorUtil.crossXY(p0.x - p1.x, p0.y - p1.y, car.point.x - p1.x, car.point.y - p1.y) <= 0;
}
//チェックポイントを通過したか
public function checkCross(id:int, car:Car):Boolean {
var p0:Point = checkPoints[id][0];
var p1:Point = checkPoints[id][1];
return LineUtil.isCross(p0, p1, car.point, car.prevPoint);
}
//チェックポイントまでの距離
public function getDistance(id:int, car:Car):Number {
var p0:Point = checkPoints[id][0];
var p1:Point = checkPoints[id][1];
return LineUtil.getNearDistance(p0, p1, car.point);
}
public function getStartPos(leng:Number):Array {
leng += distances[0] * startingOffsetPer;
var index:int = 0, per:Number = 0;
while (1) {
if (leng < distances[index]) {
per = (!distances[index])? 0 : leng / distances[index];
break;
} else {
leng -= distances[index];
index = ++index % course.length;
}
}
var index2:int = (index + 1) % course.length;
return [Point.interpolate(course[index2], course[index], per), index2];
}
public function reset():void {
checkPoints.length = course.length = distances.length = lapsTime.length = 0;
dirtMap.fillRect(dirtMap.rect, 0);
rank = raceTime = 0;
newRankRecord = newRaceRecord = newLapRecord = false;
}
}
/**
* 各種スケール
*/
class S {
static public const QtoF:Number = 30;
static public const QtoKPH:Number = 5;
static public const FtoQ:Number = 1 / QtoF;
static public var TEXTURE:Number = 1 / 5;
static public var DRAW:Number = 5 * TEXTURE;
static public const DIRT:Number = 1 / 15;
static public const DRAW_DIRT:Number = 5 * DIRT;
static public const MAP:Number = 0.8;
static public const QRECT:Rectangle = new Rectangle(-100, -100, 200, 200);
static public function QtoP(x:Number, y:Number):Point { return new Point(x * QtoF, y * QtoF); }
static public function QtoG(num:Number):Number { return (num + QRECT.width / 2) * QtoF * TEXTURE; }
static public function QtoD(num:Number):Number { return (num + QRECT.width / 2) * QtoF * DIRT; }
static public function QtoM(num:Number):Number { return (num + QRECT.width / 2) * MAP }
static public function setScale(scale:Number):void {
TEXTURE = 1 / 5 / scale;
DRAW = 5 * TEXTURE;
}
}
/**
* ドットグラフィック
*/
class Dot {
static public var grassParticle:BitmapData;
static public var lampOn:BitmapData;
static public var lampOff:BitmapData = image(6, 31, "'00.21,11@',',,,1222.1233.13443113443101331001,10'.''.''.''.''.''.''.''.''.''.''.''.''.''.''.''.''.''.''.''.''.''.''.'", [0x000000, 0x333333, 0x666666, 0xcccccc]);
static public var lamp:BitmapData = image(6, 31, "'00.21,43:34;11@';';22;234432:55,:66,:66,034430023320'22''.''.''.''.''.''.''.''.''.''.''.''.''.''.''.''.''.''.''.''.''.''.'", [0x000000,0x3f371f,0x686236,0x8c8713,0xffff00,0xffffff]);
static public var smoke1:BitmapData = image(9, 8, "'12.00,21:11;23!20@.:'..'';!':,;01::1332,',;,'31;!02323331.0233!.", [0xcccccc,0x999999,0x666666]);
static public var smoke2:BitmapData = image(8, 9, "'21.11,22:12;00!20@;.!;02.'10.::''..,::,3231',33',2332031323!;02!;", [0xcccccc,0x999999,0x666666]);
static public var heart:BitmapData = image(7, 6, "'10.12,22:00@01'1101,.21.,,'.,':.'::':", [0x990033,0xff3399]);
static public var star:BitmapData = image(9, 10, "'00.01,10:12;21!44I32|33@'',''':,'.:I11.|!|31:!!I,:!I,.23|;'13;23,.;.;'11'.,", [0x000000,0xae8300,0xffcc00,0xffffcc]);
static public var LR:BitmapData = image(10, 8, "'00.11,10:01;22@':.,''12.21':;.;,13;.;311432.2341:43.34,'14.41'':.,'", [0x000000,0xf2f2f2,0xcccccc,0x999999]);
static public var Z:BitmapData = image(11, 11, "'11.33,34:13;22!41I12|44?23-01@-''''-;;;;31I...,'?'':!I..:,'?.:.!I.:.,'?'':!I...,',|||!-''''0", [0x000000,0xf2f2f2,0xcccccc,0x999999]);
static public var X:BitmapData = image(11, 11, "'11.33,13:34;41!22I12|31?44-23*01@*''''*!!!!|I...:'-'|,;I.',:'-.,.;I.',:'-'|,;I...:':???;*''''0", [0x000000,0xf2f2f2,0xcccccc,0x999999]);
static public var L:BitmapData = image(11, 11, "'11.33,34:13;22!41I12|44?23-01@-''''-;;;;31I...,'?.:.!I.:.,'?'':!I.:.,'?.:.!I...,',|||!-''''0", [0x000000,0xf2f2f2,0xcccccc,0x999999]);
static public var R:BitmapData = image(11, 11, "'11.33,34:13;22!41I12|44?23-01@-''''-;;;;31I...,'?.:.!I..:,'?'':!I..:,'?.:.!I...,',|||!-''''0", [0x000000,0xf2f2f2,0xcccccc,0x999999]);
static public var U:BitmapData = image(11, 11, "'33.11,13:34;22!41I12|44?23-01@-....-;;;;31I''':.?','!I'.,:.?,,,!I'31':.?','!I''':.:|||!-....0", [0x000000, 0xf2f2f2, 0xcccccc, 0x999999]);
static public var D:BitmapData = image(11, 11, "'33.11,13:34;22!41I12|44?23-01@-....-;;;;31I''':.?','!I'31':.?,,,!I'.,:.?','!I''':.:|||!-....0", [0x000000, 0xf2f2f2, 0xcccccc, 0x999999]);
static public var bldg:BitmapData = image(10, 13, "'11.22,44:34;43@'''''''''''''''.....:,;,,:,;,,:,;,,:,;,,.....'''''''''''''''.....", [0xb4b4aa,0x75756f,0x131313,0x5a7189]);
static public var carBase:BitmapData = image(15, 25, "'11.00,10:21;33!02I01|31?13@...',..I'.'',I'',!''.'?;''''?;;|'''';|'!'''I'',:'',',.'''',..''''',.!'''''..:'''',.!'''''..:'''',.!'''''..:'''',.!'''''..:'''',.!:''':...:'',.I'.:',I'',!''.'?;''''?;;|'''';|'.2222,I'',....'1", [0x000000,0x000001,0x272727]);
static public var grass:BitmapData = image(16, 9, "'00.44,34:10;22!33I43|24?42-23*01^02@'':'''''*':':'':^:;'20*':03;32^31^*2112,!--13;;!?,,!-!?,,III.,,...|..|.|.,..,.?", [0x6c8319,0x515c24,0x434920,0x2b3205]);
static public var brick:BitmapData = image(15, 6, "'55.44,11:45@,,,,,,,1223.322223.33'''3335'''.:.:.:.'''''''54:.:.:.:", [0xffffff,0xe0e0e0,0xbdbdbd,0x5b472c,0x3d2714]);
static public var trophy1:BitmapData = image(15, 15, "'00.11,01:41;55!10I32|34?23-13*33^44@',....'',12I*^.',21??|:31,2112I*^.:-.??|:14!-:I|:^!'.,*:,!''',31''''',-.'''',I|:''',....'''15;;;!'',56666651'''15;;;!'',....'0", [0x000000,0xffffcc,0xffcc00,0xae8300,0x765038,0xd6cdb1]);
static public var trophy2:BitmapData = image(9, 14, "'11.01,00:55;41!24I44@'''''23!42;1232I!'23!42;.32I21,.!21,,.;,,.14',.22I;.''''15:::'5666665115:::'''''", [0x000000,0xcccccc,0xf2f2f2,0x999999,0x765038,0xd6cdb1]);
static public var trophy3:BitmapData = image(7, 12, "'11.55,00:41@''''2322:123224'2322:0132:,0121,,1210,132410''''..5115..''''", [0x000000,0xbd8000,0xffad02,0x845900,0x765038]);
static public var arrow:BitmapData = image(10, 7, "'11.00,22@'''''12,,,'13,,23'0132,3110.1323'..013110...'..", [0x000000,0xffcc00,0xae8300]);
static public var audienceRoof:BitmapData = image(4, 4, "'12@''''''''", [0x494949,0x333333]);
static public var audienceSeats:BitmapData = image(8, 6, "'11@''''23456325''''65354562''''52465236", [0x494949,0xffcc00,0x336699,0xff9933,0xcc3300,0x006633]);
static public var audienceSide:BitmapData = image(18, 27, "'00.14,33:10;12!23I13|32?20-01*31@''''':'''''''':'''''-'':'''''-'':''':'-'':''';'-'':'''I?-'':'''I|-'':'''I,21'':'''!,*'':''';,*?':'''.!*|':'''.;*,?:'''..21,|:'''..;,,:'''...!,;'''...;,I?''....!I|''....;I,?'.....!,|'.....;,,?......!,|......;,,.......!,.......;,........!........;", [0x666666,0x999999,0xcccccc,0x545454]);
static public var moja:BitmapData = image(42, 6, "'22.12,11:21@,,,,,,,,,,.''''''''''.,..':.:''..'.,,',:,..:'.,:,::..,:..:'::'.....,:,:''.....:'::,..,..':'::...'.,,:,:'.,,,,,,,,,,.''''''''''", [0x333333,0xcccccc]);
static public var drum:BitmapData = image(6, 8, "'41.11,12:21@01.10:.,3222:33'.13',31,:33'.03'10", [0x5a7a85,0x415c5d,0x91b7cc,0x7497a6]);
static public var cone:BitmapData = image(5, 7, "'00.01@'10'02'.13'2240.33.244311333", [0xff3333,0xffff00,0x990000,0xcc9900]);
static public var startingLine:BitmapData = image(14, 4, "'11.10,01@'''''''.......,,,,,,,'''''''", [0xffffff]);
static public var plantS:BitmapData = image(10, 10, "'00.02,43:13;10!21I31|20@'01||''!:11'|1211I..!I,;:33341422!I,,41.::44;!1441,;.443432''01.;'", [0x515c24,0x6c8319,0x434920,0x2b3205]);
static public var plantL:BitmapData = image(14, 14, "'00.13,31:12;21!10I32|43?20-01*23^44~34/14@'''-''''?!?:''02:;,;!'';,**?!:.;..,'-*.|,I':I~,|.!*.33~/22!03;,||41-!I^/^.?-;/41|,'02.^~II''?,I11'''':':''", [0x515c24,0x6c8319,0x434920,0x2b3205]);
static public var rock:BitmapData = image(8, 24, "'65.56,87:55;76!88I58|68?67-75*45^34@123213322343^43^:***:::....?'''!-;.,',I,I!I;I!I'',57I;:'';.;86:|!86'!!;85!,|-78,?:?;'?::'85-|I,.!|,.,66;.;425344^", [0x6c8319,0x515c24,0x434920,0x2b3205,0x4c402c,0x7b6647,0x9c825a,0xbea467]);
static public var lock:BitmapData = image(9, 12, "'11.24,00:12;21!33I41|01@,|',,|22;,|;';,:10:10'''''233242I:!..'233242I:!..';''I:!..'''''", [0x000000,0xcccccc,0xf2f2f2,0x999999]);
static public var ghost:BitmapData = image(8, 11, "'22.25,42:24;23@0111111002333320'''':;31,'533612.32;61.32;61'533621:.62,:.62,07''70", [0x010101,0x000000,0xff3300,0x666666,0x990000,0xff8b6e,0x000001]);
static public var wanco:BitmapData = image(16, 16, "'00.44,11:14;10!21I41|01?13-31*42^12~24@''',;''''''^-''''''?.;'''',~*,'''|~.43:;''?32.!34!''^....!'|.....-;|~:.:*?I?......!^.I:I..!::..I.*-|I,,:*33;|-5155?33,'',5551,,'''',;''''", [0x000000,0xb1582c,0x934824,0xcc6633,0xcc3333]);
static public var pattern1:BitmapData = image(2, 2, "@1001", [0x000000]);
static public var papers:Array = [
image(7, 7, "'22.10,00:21;01@,;.,11'.12':;'':;''.12:.,11,0", [0x000000, 0xffcc00]),
image(8, 7, "'22.00,12:01;21!10@.:!.:,;.,''!,'';:'';.,'!.:11.", [0x000000, 0xffaf00]),
image(10, 6, "'00.22,10:21;01@';,'';12:,'12..:,;...:'11.:,''11,'", [0x000000,0xff9900])
];
static public var trees:Array = [
image(12, 24, "'00.12,30:43;34!11I21|13?33-50*06^14~31/01(22)41{02}03@''/10''''/I''''.!,''/.|40'''I44,''{.):''.^);''/(^;,{.I.:,'(.||'}I!I;40I!(|;?{.!~44,23(.^|:!I!~:;:.~)~?!;^;?,}|:?::04?35?,,'}*-''''*-''''*-''''*-''''*-''", [0x73900b,0x8cb10d,0x3e5a1d,0x577314,0x694e1f,0x755f2b]),
image(10, 23, "'00.31,12:13;65!44I24|40?01-33*20^41~21/22@'','''?.*''..~'03:11,'?.11I'..,/|:.~/*?:,I!:..^*-.32,^.-,/!.-.,|?:,!I:.!^!.:I,|03~!I|'422542''04;|''';'''';'''';'''';'''';''", [0x73900b,0x577314,0x8cb10d,0x3e5a1d,0x694e1f,0x755f2b]),
image(12, 23, "'00.12,23:32;43!21I34|22?06-50*40^11~44/30(01@''(20''''../''(.31,''.^.!''^^!|/02^|.,*'..31|/(!,|I*,|..,;::::~2003!!24:I!.:|,;.!!,24I,,:I;~;33,;:/0433;~;*';III''0445~*'''?-''''?-''''?-''''?-''''?-''", [0x8cb10d, 0x73900b, 0x577314, 0x3e5a1d, 0x694e1f, 0x755f2b])
];
static public var treesSnow:Array = [
image(12, 23, "'00.11,80:76;09!12I67|21?22-70*55^44~54/33(60)77{23}01@''}10''''.!10''}!|{''42{42/''^^~35(05^*4556-'.4564*(}..15I-|.?!56:63?/25)5006~~5762..1565*|!|.51..{32?13/?37:6326:65(076636):-':III''0778)-''';,'''';,'''';,'''';,'''';,''", [0xffffff, 0xe0e0e0, 0xbdbdbd, 0x848e23, 0x636a14, 0x465013, 0x2e3b13, 0x4c321a, 0x5b472c]),
image(10, 23, "'00.11,98:12;44!21I24|77?70-46*22@''.'''01.10''.!23'02!3232'0342:I'5354;-103553636120.15416442....60*!!..*:::4754;*-?01;-|61:43|73.I456741I0563|;?'766876''07,?''','''','''','''','''',''", [0xffffff, 0xe0e0e0, 0x636a14, 0xbdbdbd, 0x848e23, 0x465013, 0x2e3b13, 0x4c321a, 0x5b472c]),
image(12, 24, "'00.13,11:35;80!44I40|64?09-55*22^01~05/52(04@''^10''''^12''''..I''^,1560''03,36I''~./|''31:6243''.3721,10~33/23.50~-272134'(72*.:6072*,335114^,:-,3015.572653:--*45:-|274262/!*462646!I(24|!||06!48!II'(?;''''?;''''?;''''?;''''?;''", [0xffffff, 0x636a14, 0xe0e0e0, 0x2e3b13, 0xbdbdbd, 0x465013, 0x848e23, 0x4c321a, 0x5b472c])
];
static public function carWing(color1:uint, color2:uint, color3:uint):BitmapData {
return image(13, 4, "'22.11@12'''''31'''''2312'''''31.....13", [color1, color2, color3]);
}
static public function carFrame(color1:uint, color2:uint, color3:uint):BitmapData {
return image(13, 24, "'22.33,00:11;30!23I44|01?12-42*02^24~20@,,|:,,,,,'~,,,,?';,*~|'!,':,?';|:10|'!,:',?';*!;:'!;.,:''!;,:'I-!;:?^I'.31:^II!.:?II-.31:^II!.41--'-43I14'''^34:?'''.;|'''!,,*''',*~...;':03...|:10...;:'03...*!;...;.", [color1,color2,color3,0x000000]);
}
static public var ads:Object = { };
static public function init():void {
var radius:int = 10;
lampOn = new BitmapData(radius*2, lamp.height + radius - 3, true, 0);
lampOn.draw(Create.gradientCircle(radius, radius, radius, radius, [0xFFFF00, 0xFFF7B2], [1, 0], [0, 255]));
lampOn.copyPixels(lamp, lamp.rect, new Point((lampOn.width - lamp.width) / 2, (lampOn.height - lamp.height)), null, null, true);
var data:Array = [
["title", 160, 20, 0x23416D, 0x111111, "pattern1", 5, 0x000000, 0.4, "MOJA GRAND PRIX", 40, 0, 8, 0xFFFFFF],
["title2", 160, 20, 0xFFFFFF, 0xBBBBBB, "pattern1", 5, 0x000000, 0.1, "MOJA GRAND PRIX", 40, 0, 8, 0x000000],
["moja", 60, 40, 0x444444, 0x111111, "pattern1", 10, 0x000000, 0.4, "MOJA", 16, 10, 8, 0xFFFFFF],
["hoge", 60, 40, 0x444444, 0x111111, "pattern1", 10, 0x000000, 0.4, "HOGE", 16, 10, 8, 0xFFFFFF],
["wonderfl", 60, 40, 0x6C0502, 0x111111, "pattern1", 10, 0x000000, 0.5, "wonderfl", 10, 10, 8, 0xFFFFFF],
["flash", 60, 40, 0xD30909, 0x680302, "pattern1", 10, 0xFF0000, 0.1, "Flash", 16, 10, 8, 0xFFFFFF]
];
for each (var item:Array in data) {
var bmd:BitmapData = new BitmapData(item[1], item[2], false);
bmd.draw(Create.gradientBox(0, 0, bmd.width, bmd.height, true, 90, [item[3], item[4]], [1, 1], [0, 255]));
bmd.draw(Create.bitmapFillBox(0, 0, bmd.width, bmd.height, Dot[item[5]], item[6], item[6], 0, 0), null, new ColorTransform(0, 0, 0, item[8], item[7] >> 16 & 0xFF, item[7] >> 8 & 0xFF, item[7] & 0xFF));
bmd.draw(UI.createLabel(null, 0, 0, item[9], item[12], item[13]), new Matrix(1, 0, 0, 1, item[10], item[11]));
ads[item[0]] = bmd;
}
}
static public function setParticleColor(rgb1:uint = 0x6d8a15, rgb2:uint = 0xb6e034):void {
grassParticle = image(8, 5, "'00@'01''10'2001'''20''''02''10", [rgb1, rgb2]);
}
static public function image(width:int, height:int, dot:String, colors:Array):BitmapData {
var bmd:BitmapData = new BitmapData(width, height, true, 0), data:Array = dot.split("@");
while (data[0].length>=3) {
data[1] = data[1].split(data[0].substr(0,1)).join(data[0].substr(1,2));
data[0] = data[0].substr(3);
}
var pixels:Array = String(data[1]).split("");
for (var i:int = 0; i < pixels.length; i++) bmd.setPixel32(i % bmd.width, int(i / bmd.width), (pixels[i] == "0")? 0 : 0xFF << 24 | colors[parseInt(pixels[i], 36) - 1]);
return bmd;
}
}
/**
* 球面線形補完で動くカメラ用ベクトル
*/
class CameraVector {
private var _gaze:Vector3D = new Vector3D();
private var _offset:Vector3D = new Vector3D(0, 1, 0);
private var _position:Vector3D = new Vector3D();
private var _distance:Number = 100;
private var _gazeTarget:Vector3D = new Vector3D();
private var _offsetTarget:Vector3D = new Vector3D(0,1,0);
private var _distanceTarget:Number = 100;
private var _gazeSpeed:Number = 1;
private var _offsetSpeed:Number = 1;
public function CameraVector() {
tick();
}
public function tick():void {
if (!_gaze.equals(_gazeTarget)) {
_gaze.x += (_gazeTarget.x - _gaze.x) * _gazeSpeed;
_gaze.y += (_gazeTarget.y - _gaze.y) * _gazeSpeed;
_gaze.z += (_gazeTarget.z - _gaze.z) * _gazeSpeed;
}
if (_distanceTarget != _distance) _distance += (_distanceTarget - _distance) * _offsetSpeed;
if (!_offset.equals(_offsetTarget)) {
_offset = Vector3DUtil.slerpVector(_offset, _offsetTarget, _offsetSpeed);
}
_offset.normalize();
_offset.scaleBy(_distance);
_position.x = _gaze.x + _offset.x;
_position.y = _gaze.y + _offset.y;
_position.z = _gaze.z + _offset.z;
}
public function moveDistance(d:Number, speed:Number = 0.2):void {
_offsetSpeed = speed;
_distanceTarget = d;
if (speed == 1) _distance = _distanceTarget;
}
public function movePositionXYZ(x:Number, y:Number, z:Number, speed:Number = 0.2):void {
moveOffsetXYZ(x - _gazeTarget.x, y - _gazeTarget.y, z - _gazeTarget.z, speed);
}
public function movePosition(v:Vector3D, speed:Number = 0.2):void {
movePositionXYZ(v.x, v.y, v.z, speed);
}
public function moveOffset(v:Vector3D, speed:Number = 0.2):void {
moveOffsetXYZ(v.x, v.y, v.z, speed);
}
public function moveGaze(v:Vector3D, speed:Number = 0.2):void {
moveGazeXYZ(v.x, v.y, v.z, speed);
}
public function moveOffsetXYZ(x:Number, y:Number, z:Number, speed:Number = 0.2):void {
_offsetSpeed = speed;
Vector3DUtil.setXYZ(_offsetTarget, x, y, z);
_distanceTarget = _offsetTarget.length;
if (speed == 1) {
Vector3DUtil.setXYZ(_offset, x, y, z);
_distance = _distanceTarget;
}
}
public function moveGazeXYZ(x:Number, y:Number, z:Number, speed:Number = 0.2):void {
_gazeSpeed = speed;
Vector3DUtil.setXYZ(_gazeTarget, x, y, z);
if(speed == 1) Vector3DUtil.setXYZ(_gaze, x, y, z);
}
public function get gaze():Vector3D { return _gaze; }
public function get offset():Vector3D { return _offset; }
public function get distance():Number { return _distance; }
public function get position():Vector3D { return _position; }
}
/**
* 光源
*/
class Light3D {
public var point:Point = new Point();
public var min:Number = 1;
public var max:Number = 5;
public function Light3D() {
}
}
/**
* 環境データ
*/
class Light {
public var hasStars:Boolean = false;
public var useHeadlight:Boolean = false;
public var isLightUp:Boolean = false;
public var fog:uint = 0x1f2f3f;
public var horizon:uint = 0x538BDE;
public var sky:uint = 0x1F1F1F;
public var horizonPer:Number = 0.7;
public var cloud:uint = 0;
public var ambient:uint = 0x0F0F1F;
public var ambientPer:Number = 0.8;
public var ambientColor:ColorTransform;
static public const DAY:int = 0;
static public const SUNSET:int = 1;
static public const NIGHT:int = 2;
static public const DAWN:int = 3;
static public const TWILIGHT:int = 4;
static public const LIST:Array = [DAY, SUNSET, NIGHT, DAWN, TWILIGHT];
static public const LABELS:Array = ["DAY", "SUNSET", "NIGHT", "DAWN", "TWILIGHT"];
public function Light(type:int = DAY) {
setTime(type);
}
public function setTime(type:int):void {
switch(type) {
case DAY:
isLightUp = useHeadlight = hasStars = false;
sky = 0x3172D6;
horizon = 0x5D9DF8;
fog = 0x7BBDFF;
cloud = 0xFFFFFF;
ambient = 0xFFFFFF;
ambientPer = 0;
break;
case SUNSET:
isLightUp = true;
useHeadlight = hasStars = false;
sky = 0x8F8898;
horizon = 0xD9B07F;
fog = 0xE5D065;
cloud = 0x604407;
ambient = 0x74290F;
ambientPer = 0.5;
break;
case NIGHT:
isLightUp = useHeadlight = hasStars = true;
sky = 0x051549;
horizon = 0x2950B7;
fog = 0x317BDE;
cloud = 0x061534;
ambient = 0x051549;
ambientPer = 0.6;
break;
case DAWN:
isLightUp = false;
useHeadlight = hasStars = true;
sky = 0x7B94AA;
horizon = 0xB7BDBB;
fog = 0xDDCFC1;
cloud = 0x7C7A79;
ambient = 0x1E4068;
ambientPer = 0.6;
break;
case TWILIGHT:
isLightUp = true;
useHeadlight = hasStars = false;
sky = 0x856289;
horizon = 0xC992A5;
fog = 0xF3BEB2;
cloud = 0x856289;
ambient = 0x43345B;
ambientPer = 0.5;
break;
}
ambientColor = Palette.getColorTransform(ambient, ambientPer);
}
}
/**
* カメラ
*/
class Camera3D {
public var light:Light = new Light();
public var horizon:Number = 2000;
public var gradientArea:Number = 400;
public var ground:Number = 1100;
public var view:Number = 1400;
public var rotation:Number = 0;
public var angle:Number = 0;
public var center:Vector3D = new Vector3D(0, 0, -314);
public var gaze:Vector3D = new Vector3D();
public var position:Vector3D = new Vector3D();
public var point:Point = new Point();
public var offset:Point = new Point();
public var direction:Point = new Point();
public function Camera3D():void {
}
public function setCenterXY(x:Number, y:Number):void {
center.x = Display.center.x;
center.y = Display.center.y;
}
public function setGaze(v:Vector3D):void {
setGazeXYZ(v.x, v.y, v.z);
}
public function setPosition(v:Vector3D):void {
setPositionXYZ(v.x, v.y, v.z);
}
public function setGazeXYZ(x:Number, y:Number, z:Number):void {
Vector3DUtil.setXYZ(gaze, x, y, z);
}
public function setPositionXYZ(x:Number, y:Number, z:Number):void {
Vector3DUtil.setXYZ(position, x, y, z);
}
public function update():void {
var dx:Number = gaze.x - position.x;
var dy:Number = gaze.y - position.y;
rotation = Math.atan2(dx, dy) + Math.PI;
angle = Math.atan2(Math.sqrt(dx * dx + dy * dy), gaze.z - position.z) + Math.PI;
point.x = position.x;
point.y = position.y;
direction.x = Math.cos( -rotation);
direction.y = Math.sin( -rotation);
offset.x = Math.cos( -rotation + Angle.RAD90);
offset.y = Math.sin( -rotation + Angle.RAD90);
}
}
/**
* 簡易3Dシーン
*/
class Scene3D {
public var camera:Camera3D = new Camera3D();
public var display:Sprite = new Sprite();
public var groundMap:BitmapData;
public var rawMap:BitmapData;
public var lights:Vector.<Light3D> = new Vector.<Light3D>();
private const SCALE:Number = 4;
private var _root:Sprite = new Sprite();
private var _container:Sprite = new Sprite();
private var _lightContainer:Sprite = new Sprite();
private var _bg:Sprite = Create.box(-1000, -1000, 2465, 2465, 0);
private var _sky:BackGround = new BackGround();
private var _fog:Sprite = new Sprite();
private var _wrapper:Sprite = new Sprite();
private var _ground:Sprite = new Sprite();
private var _horizon:Point = new Point();
private var _drawIndex:int = 0;
private var _splitRects:Vector.<Rectangle> = new Vector.<Rectangle>();
private var _recycleParticles:Vector.<Particle3D> = new Vector.<Particle3D>();
private var _recycleLimit:int = 40;
private var _recycleIndex:int = -1;
private var _objects:Vector.<Sprite3D> = new Vector.<Sprite3D>();
private var _cars:Vector.<Car> = new Vector.<Car>();
private var _qboxes:Vector.<QuickBox3D> = new Vector.<QuickBox3D>();
private var _sorts:Vector.<Sprite3D> = new Vector.<Sprite3D>();
public function get cars():Vector.<Car> { return _cars; }
public function Scene3D() {
_sky.init();
display.addChild(_bg);
display.addChild(_sky);
display.addChild(_root);
_root.scaleX = _root.scaleY = _root.scaleZ = SCALE;
_root.addChild(_wrapper);
_wrapper.addChild(_ground);
_wrapper.addChild(_lightContainer);
_lightContainer.blendMode = BlendMode.OVERLAY;
_wrapper.addChild(_fog);
_wrapper.addChild(_container);
}
public function setSize(width:Number, height:Number):void {
camera.setCenterXY(width / 2, height / 2);
}
public function setLight(light:Light):void {
camera.light = light;
updateFog();
_bg.transform.colorTransform = Palette.getColorTransform(camera.light.sky, 1);
_sky.draw(camera.light);
updateLight();
}
public function updateFog():void {
_fog.graphics.clear();
var gr:Number = camera.ground, ga:Number = camera.gradientArea, fog:uint = camera.light.fog;
Draw.gradientBox(_fog.graphics, gr - ga, -gr, ga, gr * 2, true, 0, [fog, fog], [0, 1], [0, 250]);
}
public function updateLight():void {
_lightContainer.visible = $.user.showLight && camera.light.useHeadlight;
}
public function getScreenXYZ(x:Number, y:Number, z:Number):Point {
return _container.local3DToGlobal(new Vector3D(x, y, -z));
}
public function getScreen(v:Vector3D):Point {
return _container.local3DToGlobal(new Vector3D(v.x, v.y, -v.z));
}
public function addLight(light:Light3D):Light3D {
lights.push(light);
return light;
}
public function addParticle(bmd:BitmapData, alpha:Number = 0.5, scaleMin:Number = 1, scaleMax:Number = 1.5, fade:int = 30, x:Number = 0, y:Number = 0, z:Number = 0, tz:Number = 0):Particle3D {
var obj:Particle3D;
if (_recycleParticles.length >= _recycleLimit) {
_recycleIndex = ++_recycleIndex % _recycleParticles.length;
obj = _recycleParticles[_recycleIndex];
obj.setParam.apply(null, arguments);
} else {
obj = new Particle3D(bmd, alpha, scaleMin, scaleMax, fade, x, y, z, tz);
_recycleParticles.push(obj);
addSprite(obj);
}
return obj;
}
public function addSprite(obj:Sprite3D):Sprite3D {
obj.parent = _container;
obj.onDestroy = onDestroySprite;
if (obj is Car) {
_cars.push(obj);
Car(obj).lightParent = _lightContainer;
_lightContainer.addChild(Car(obj).light);
}
_container.addChild(obj.sprite);
_objects.push(obj);
if (obj is QuickBox3D && QuickBox3D(obj).qobject.params.density != 0) _qboxes.push(obj);
return obj;
}
private function onDestroySprite(obj:Sprite3D):void {
var index:int;
index = _objects.indexOf(obj);
if (index > -1) _objects.splice(index, 1);
index = _cars.indexOf(obj);
if (index > -1) _cars.splice(index, 1);
index = _qboxes.indexOf(obj);
if (index > -1) _qboxes.splice(index, 1);
}
public function destroyParticles():void {
var i:int, leng:int = _objects.length - 1;
for (i = leng; i >= 0; i--) if (_objects[i] is Particle3D) _objects[i].destroy();
_recycleParticles.length = 0;
_recycleIndex = -1;
}
public function destroyCars():void {
while (_cars.length) _cars[0].destroy();
}
public function destroyGhosts():void {
var i:int, leng:int = _cars.length - 1;
for (i = leng; i >= 0; i--) if (_cars[i].isGhost) _cars[i].destroy();
}
public function destroyAll():void {
_sorts.length = lights.length = 0;
while (_objects.length) _objects[0].destroy();
destroyParticles();
}
public function updateQuickBox():void {
for each (var qbox:QuickBox3D in _qboxes) {
if (qbox is Car) continue;
var body:b2Body = qbox.qobject.body;
if (!body.IsSleeping()) {
body.GetLinearVelocity().Multiply(0.95);
if ($.game.sceneTime % 5 == 0 && body.GetLinearVelocity().Length() < 0.05) body.PutToSleep();
}
}
}
public function clearRecord():void {
for each (var qobj:QuickBox3D in _qboxes) qobj.replay.clear();
}
public function stopRecord():void {
for each (var qobj:QuickBox3D in _qboxes) qobj.replay.stopRecord();
}
public function startReplay():void {
for each (var qobj:QuickBox3D in _qboxes) qobj.replay.startReplay(qobj.isGhost);
}
public function startRecord():void {
for each (var qobj:QuickBox3D in _qboxes) {
if(!qobj.isGhost) qobj.replay.startRecord();
else qobj.replay.startReplay(qobj.isGhost);
}
}
public function tickRecord():void {
for each (var qobj:QuickBox3D in _qboxes) qobj.tickRecord();
}
/**
* レンダリング
*/
public function render():void {
var i:int, obj:Sprite3D;
camera.update();
_root.x = camera.center.x;
_root.rotationX = camera.angle * Angle.toROT;
_root.y = -camera.position.z * SCALE * S.QtoF * Math.sin(camera.angle) + camera.center.y;
_root.z = camera.position.z * SCALE * S.QtoF * Math.cos(camera.angle) + camera.center.z;
_sorts.length = 0;
for each (obj in _objects) {
obj.update(this);
if (obj.sprite.parent) _sorts.push(obj);
}
_sorts.sort(zsort);
for (i = 0; i < _sorts.length; i++) _container.setChildIndex(_sorts[i].sprite, i);
_container.x = _lightContainer.x = -camera.position.x * S.QtoF;
_container.y = _lightContainer.y = -camera.position.y * S.QtoF;
_wrapper.rotationZ = camera.rotation * Angle.toROT;
if (!groundMap) return;
//地面描画
_ground.graphics.clear();
var mtx:Matrix = new Matrix();
mtx.scale(1 / S.TEXTURE, 1 / S.TEXTURE);
mtx.translate(_container.x - 3000, _container.y - 3000);
mtx.rotate(camera.rotation + Angle.RAD90);
_ground.graphics.beginBitmapFill(groundMap, mtx);
_ground.graphics.drawTriangles(Vector.<Number>([-140, -140, -140, 140, camera.ground, camera.ground, camera.ground, -camera.ground]), Vector.<int>([0, 1, 2, 2, 3, 0]));
_ground.rotationZ = _fog.rotationZ = -camera.rotation * Angle.toROT - 90;
//地平線の高さ計算
var vx:Number = -Math.sin(camera.rotation) * camera.horizon + camera.position.x * S.QtoF;
var vy:Number = -Math.cos(camera.rotation) * camera.horizon + camera.position.y * S.QtoF;
_horizon = getScreenXYZ(vx, vy, 0);
//背景スライド
_sky.slide(camera.rotation % Angle.RAD360 / Angle.RAD360);
_sky.y = _horizon.y;
}
/**
* 地面に付いた跡を徐々に消す
*/
public function fadeTireTrack():void {
if (groundMap && rawMap) {
_drawIndex = ++_drawIndex % _splitRects.length;
groundMap.copyPixels(rawMap, _splitRects[_drawIndex], _splitRects[_drawIndex].topLeft, null, null, true);
}
}
/**
* 地面の画像を細かく分割した矩形を計算
*/
public function splitRawImage():void {
var size:int = 100, x:int = 0, y:int = 0;
_splitRects.length = 0;
while (1) {
_splitRects.push(new Rectangle(x, y, Math.min(rawMap.width - x, size), Math.min(rawMap.height - y, size)));
if ((x += size) >= rawMap.width) {
x = 0;
if ((y += size) >= rawMap.height) break;
}
}
}
private function zsort(a:Sprite3D, b:Sprite3D):int {
var az:Number = a.point.x * Math.sin(camera.rotation) + a.point.y * Math.cos(camera.rotation);
var bz:Number = b.point.x * Math.sin(camera.rotation) + b.point.y * Math.cos(camera.rotation);
return int(az > bz) - int(az < bz);
}
}
/**
* 簡易3Dスプライト
*/
class Sprite3D {
public var sprite:Sprite;
public var screen:Point;
public var parent:DisplayObjectContainer;
public var lookAtCamera:Boolean = true;
public var isStand:Boolean = true;
public var isEmit:Boolean = false;
public var point:Point = new Point();
public var position:Vector3D = new Vector3D();
public var radius:Number = 0;
public var angle:Number = 0;
public var twoSides:Boolean = true;
public var isReverse:Boolean = false;
public var lightEnabled:Boolean = true;
public var ambientEnabled:Boolean = true;
public var shredder:Shredder = new Shredder();
private var _inDisplay:Boolean = true;
private var _alpha:Number = 1;
private var _direction:Point = new Point();
private var _visible:Boolean = true;
private var _ct:ColorTransform = new ColorTransform();
private var _ct2:ColorTransform = new ColorTransform();
private var _lightPer:Number = 1;
private var _lightUpdate:int = -1;
private var _inScreen:Boolean;
private var _dp:Point = new Point();
private var _sp:Point = new Point();
private var _blend:Point = new Point();
private var _lastBlend:Point = new Point();
protected var _distance:Number = 0;
public var onDestroy:Function;
public function get visible():Boolean { return _visible; }
public function set visible(value:Boolean):void { if (!(_visible = value) && sprite.parent) parent.removeChild(sprite); }
public function get alpha():Number { return _alpha; }
public function set alpha(value:Number):void { sprite.alpha = _alpha = value; }
public function get inDisplay():Boolean { return _inDisplay; }
public function Sprite3D(sprite:Sprite, lookAtCamera:Boolean = true, stand:Boolean = true, x:Number = 0, y:Number = 0, z:Number = 0, angle:Number = 0, two:Boolean = true, reverse:Boolean = false) {
setPosition(x, y, z);
this.sprite = sprite;
this.lookAtCamera = lookAtCamera;
this.angle = angle * Angle.toRAD;
this.twoSides = two;
this.isReverse = reverse;
updateDirection();
var bounds:Rectangle = sprite.getRect(sprite);
radius = Math.max(Math.abs(bounds.left), Math.abs(bounds.right)) * sprite.scaleX * S.FtoQ;
isStand = stand;
if (stand) sprite.rotationX = 90;
shredder.addData(sprite);
}
public function setPosition(x:Number, y:Number, z:Number):void {
point.x = position.x = x;
point.y = position.y = y;
position.z = z;
}
protected function updateDirection():void {
_direction.x = Math.cos(angle+Angle.RAD180);
_direction.y = Math.sin(angle+Angle.RAD180);
}
public function setSide(two:Boolean, reverse:Boolean = false):void {
twoSides = two;
isReverse = reverse;
}
public function getScreen():Point {
return (sprite.parent && _inScreen)? sprite.parent.local3DToGlobal(new Vector3D(position.x * S.QtoF, position.y * S.QtoF, -position.z * S.QtoF)) : null;
}
public function update(scene:Scene3D):void {
if (!_visible) return;
var camera:Camera3D = scene.camera;
var light:Light = camera.light;
camera.offset.normalize(5 + radius);
_dp.x = point.x - camera.point.x;
_dp.y = point.y - camera.point.y;
_sp.x = _dp.x - camera.offset.x;
_sp.y = _dp.y - camera.offset.y;
_distance = Point.distance(point, camera.point) * S.QtoF;
_inScreen = VectorUtil.cross(camera.direction, _dp) < 0;
var cross:Number = (twoSides)? 1 : VectorUtil.cross(_direction, _dp);
if (isReverse && !twoSides) cross *= -1;
var show:Boolean = cross > 0 && VectorUtil.cross(camera.direction, _sp) < 0 && _distance < camera.view;
if (show) {
var ang:Number = VectorUtil.getAngleXY( -camera.offset.x, -camera.offset.y, _dp.x, _dp.y) * Angle.toROT;
if (ang - (radius * 500 / _distance) > 55 && _distance > (radius * 30 + 100)) show = false;
}
_inDisplay = show;
if (_inDisplay) {
//位置更新
sprite.x = point.x * S.QtoF;
sprite.y = point.y * S.QtoF;
sprite.z = -position.z * S.QtoF;
if (lookAtCamera) {
sprite.rotationZ = -camera.rotation * Angle.toROT;
if(!isStand) sprite.rotationX = -camera.angle * Angle.toROT;
}
else sprite.rotationZ = angle * Angle.toROT;
//ライトの影響をうけるか
if (!isEmit && lightEnabled && $.user.showLight && light.useHeadlight && ++_lightUpdate % 2 == 0) {
var min:Number = Number.MAX_VALUE;
var targetLight3D:Light3D = null;
for each (var light3D:Light3D in scene.lights) {
var d:Number = Point.distance(light3D.point, point) - radius;
if (min > d) {
min = d;
targetLight3D = light3D;
}
}
_lightPer = (targetLight3D && min < targetLight3D.max)? (min - targetLight3D.min) / (targetLight3D.max - targetLight3D.min) : 1;
if (_lightPer < 0) _lightPer = 0;
}
//フォグ着色
_blend.x = (_distance - camera.view + camera.gradientArea) / camera.gradientArea;
if (_blend.x < 0) _blend.x = 0;
//環境光着色
_blend.y = (!ambientEnabled || light.ambientPer == 0 || isEmit)? 0 : (($.user.showLight && light.useHeadlight)? light.ambientPer * _lightPer : 1);
//着色量が変化した時だけ更新
if (!_blend.equals(_lastBlend)) {
Palette.setColorTransform(_ct, light.fog, _blend.x, _alpha);
if (_blend.y == 1) {
_ct.concat(light.ambientColor);
} else if (_blend.y > 0) {
Palette.setColorTransform(_ct2, light.ambient, light.ambientPer * _lightPer);
_ct.concat(_ct2);
}
sprite.transform.colorTransform = _ct;
}
_lastBlend.x = _blend.x;
_lastBlend.y = _blend.y;
}
if (_inDisplay) {
if (!sprite.parent) parent.addChild(sprite);
} else if (sprite.parent) parent.removeChild(sprite);
}
public function destroy():void {
if (onDestroy != null) onDestroy(this);
shredder.destroy();
}
}
/**
* パーティクルスプライト
*/
class Particle3D extends Sprite3D {
private var _alphaMax:Number = 1;
private var _scaleMin:Number = 1;
private var _scaleMax:Number = 2;
private var _time:int = 0;
private var _fadeTime:int = 30;
private var _zMin:Number = 0;
private var _zMax:Number = 0;
private var _active:Boolean = true;
public function Particle3D(bmd:BitmapData, alpha:Number = 1, scaleMin:Number = 1, scaleMax:Number = 2, fade:int = 30, x:Number = 0, y:Number = 0, z:Number = 0, tz:Number = 0) {
super(Create.spriteBmp(bmd, 1, -bmd.width / 2, -bmd.height / 2), true, false, x, y, z, 0, true, false);
setParam(bmd, alpha, scaleMin, scaleMax, fade, x, y, z, tz);
lightEnabled = false;
}
public function setParam(bmd:BitmapData, alpha:Number = 1, scaleMin:Number = 1, scaleMax:Number = 2, fade:int = 30, x:Number = 0, y:Number = 0, z:Number = 0, tz:Number = 0):void{
var bmp:Bitmap = sprite.getChildAt(0) as Bitmap;
bmp.bitmapData = bmd;
bmp.x = -bmd.width / 2;
bmp.y = -bmd.height / 2;
setPosition(x, y, z);
_time = 0;
this.alpha = 0;
_alphaMax = alpha;
_scaleMax = scaleMax;
_scaleMin = scaleMin;
_fadeTime = fade;
_zMin = z;
_zMax = tz;
_active = true;
}
override public function update(scene:Scene3D):void {
if (!_active) return;
_time++;
var per:Number = _time / _fadeTime;
sprite.scaleX = sprite.scaleY = _scaleMin + (_scaleMax - _scaleMin) * per;
if ((alpha = _alphaMax * (1 - per)) <= 0) {
_active = false;
return;
}
position.z = _zMin + (_zMax - _zMin) * per;
updateDirection();
super.update(scene);
}
}
/**
* 簡易3DスプライトにBox2Dを関連付けたもの
*/
class QuickBox3D extends Sprite3D {
public var qobject:QuickObject;
public var isStatic:Boolean = false;
public var isGhost:Boolean = false;
public var replay:ReplayData = new ReplayData();
public function QuickBox3D(qobj:QuickObject, sprite:Sprite, lookAtCamera:Boolean = true, stand:Boolean = true, x:Number = 0, y:Number = 0, z:Number = 0, angle:Number = 0) {
super(sprite, lookAtCamera, stand, x, y, z, angle);
qobject = qobj;
shredder.addData(qobject);
isStatic = (qobject.params.density == 0);
point.x = position.x = qobject.x = x;
point.y = position.y = qobject.y = y;
}
public function addForce(v:Point):void {
var mass:Number = qobject.body.GetMass();
qobject.body.ApplyForce(new b2Vec2(v.x * mass, v.y * mass), qobject.body.GetWorldCenter());
}
public function tickRecord():void {
if (!replay.isPlaying) replay.add(point, qobject.angle);
replay.tick();
}
override public function destroy():void {
super.destroy();
if(!isGhost) replay.clear();
}
override public function update(scene:Scene3D):void {
if (!replay.isPlaying) {
qobject.angle %= Angle.RAD360;
point.x = position.x = qobject.x;
point.y = position.y = qobject.y;
angle = qobject.angle;
} else if (!isStatic && replay.isValid) {
qobject.x = point.x = position.x = replay.x;
qobject.y = point.y = position.y = replay.y;
qobject.angle = angle = replay.angle;
}
updateDirection();
super.update(scene);
}
}
/**
* データをまとめて破棄する
*/
class Shredder {
private var _data:Array = [];
public function Shredder() {
}
public function addData(...arg):void {
_data = _data.concat(arg);
}
public function destroy():void {
for each (var item:* in _data) {
if (item is QuickObject) QuickObject(item).fullDestroy();
if (item is BitmapData) BitmapData(item).dispose();
if (item is Array) item.length = 0;
if (item is DisplayObject && item.parent) DisplayObject(item).parent.removeChild(item);
}
_data.length = 0;
}
}
/**
* ワンコ
*/
class Wanco extends QuickBox3D {
private var _active:Boolean = false;
private var _target:Sprite3D;
public function get active():Boolean { return _active; }
public function Wanco(qobj:QuickObject, sprite:Sprite, lookAtCamera:Boolean = true, stand:Boolean = true, x:Number = 0, y:Number = 0, z:Number = 0, angle:Number = 0) {
super(qobj, sprite, lookAtCamera, stand, x, y, z, angle);
}
public function love(target:Sprite3D):void {
_target = target;
_active = true;
}
override public function update(scene:Scene3D):void {
if (_target) chase();
super.update(scene);
}
private function chase():void {
var p:Point = _target.point.subtract(point);
if (p.x * p.x + p.y * p.y < 4) return;
p.normalize(26 * qobject.body.GetMass());
qobject.body.ApplyForce(new b2Vec2(p.x, p.y), qobject.body.GetPosition());
qobject.body.WakeUp();
}
}
/**
* 車オブジェクト
*/
class Car extends QuickBox3D {
public var mapMark:Sprite;
public var rankMark:Sprite;
public var light:Sprite = new Sprite();
public var light3D:Light3D = new Light3D();
public var lightParent:DisplayObjectContainer;
public var autoSteer:Boolean = true;
public var isPlayer:Boolean = false;
public var ghostVisible:Boolean = true;
//加速スピード
public var accel:Number = 4;
public var accelFirst:Number = 6;
public var handling:Number = 0.38;
public var driftPower:Number = 0.75;
//大きいほど自動操縦時にカーブを早めに曲がる(0~1くらい)
public var proactiveRate:Number = 1;
public var isAlwaysLight:Boolean = false;
public var prevPoint:Point = new Point();
public var tireLprev:Point = new Point();
public var tireRprev:Point = new Point();
public var tireL:Point = new Point();
public var tireR:Point = new Point();
public var steerSpeed:Number = 0.25;
private var _rank:int = 0;
private var _rankLabel:Label;
private var _speedRate:Number = 0;
private var _dirtRate:Number = 0;
private var _speed:Number = 0;
private var _front:Point = new Point();
private var _slip:Number = 0;
private var _torque:Number = 0;
private var _driftPer:Number = 0;
private var _driftStart:int;
private var _readyDrift:Boolean = false;
private var _tireOffsetL:Point = new Point(-0.35, 0.4);
private var _tireOffsetR:Point = new Point(0.35, 0.4);
//周回数+周回率
private var _lap:Number = 0;
//[COM]最高難易度専用のニトロ量
private var _nitro:int = 0;
//[COM]次に向かうコーナー番号
private var _targetIndex:int = 1;
//[COM]バックするモード
private var _backMode:Boolean = false;
//[COM]動けないと増えていく
private var _stress:int = 0;
//リプレイ用
private var _velocity:Point = new Point();
//周回判定用
private var _areaID:int = 1;
private var _roundNum:int = 0;
private var _key:uint;
private var _distanceEstimator:DistanceEstimator;
public function get front():Point { return _front; }
public function get speedRate():Number { return _speedRate; }
public function get dirtRate():Number { return _dirtRate; }
public function get speed():Number { return _speed; }
public function get lap():Number { return _lap; }
public function get velocity():Point { return _velocity; }
public function get slip():Number { return _slip; }
public function get nitro():int { return _nitro; }
public function get rank():int { return _rank; }
public function Car(sim:QuickBox2D, isPlayer:Boolean = true, rgb:uint = 0xC80000, density:Number = 0.3, restitution:Number = 0.8, de:DistanceEstimator = null) {
this.isPlayer = isPlayer;
autoSteer = !isPlayer;
var qobj:QuickObject;
if (isPlayer) {
var box:QuickObject = sim.addBox( { skin:"none", density:density, restitution:restitution, friction:0.01, x:0, y:0.2, width:0.6, height:1.0 } );
var circle:QuickObject = sim.addCircle( { skin:"none", density:density*0.425, restitution:restitution, friction:0.01, x:0, y:-0.4, radius:0.3 } );
qobj = sim.addGroup( { objects:[box, circle] } );
} else {
qobj = sim.addBox( { density:density, restitution:restitution, friction:0.01, x:0, y:0.2, width:0.6, height:1.2 } );
}
super(qobj, qobj.userData, false, false);
light.graphics.clear();
Draw.circle(light.graphics, -10, -70, 20, 50, 0xFFFFFF, 1);
Draw.circle(light.graphics, 10, -70, 20, 50, 0xFFFFFF, 1);
mapMark = Create.box( -2, -2, 5, 5, (isPlayer)? 0xFFFF00 : 0xFF0000);
rankMark = Create.spriteBmp(Dot.arrow, 2, -Dot.arrow.width / 2, -Dot.arrow.height - 6);
_rankLabel = UI.createLabel(rankMark, -6, -55, "");
shredder.addData(mapMark, rankMark, light);
_distanceEstimator = de;
}
public function finish():void {
_roundNum = 1000;
}
override public function tickRecord():void {
if (!replay.isPlaying) replay.add(point, qobject.angle, ! !(_key & 0x0F000), _slip > 0.8, _dirtRate > 0.2);
replay.tick();
if (isGhost && replay.isFinish) destroy();
}
public function setRank(num:int):void {
_rank = num;
_rankLabel.text = String(num);
}
public function stockPrev():void {
prevPoint.x = point.x;
prevPoint.y = point.y;
tireLprev = PointUtil.rotate(_tireOffsetL, angle).add(point);
tireRprev = PointUtil.rotate(_tireOffsetR, angle).add(point);
}
override public function update(scene:Scene3D):void {
super.update(scene);
tireL = PointUtil.rotate(_tireOffsetL, angle).add(point);
tireR = PointUtil.rotate(_tireOffsetR, angle).add(point);
var v:Boolean = !(isGhost && (replay.isWaiting || !ghostVisible));
if (visible != v) visible = v;
if (replay.isPlaying) {
updateFront();
_velocity.x = point.x - prevPoint.x;
_velocity.y = point.y - prevPoint.y;
_speed = _velocity.length * 30;
updateSpeedRate();
if (replay.isValid) {
_slip = int(replay.isDrift);
_dirtRate = int(replay.inDirt);
}
}
var showLight:Boolean = inDisplay || isAlwaysLight;
if (showLight && !light.parent) lightParent.addChild(light);
if (!showLight && light.parent) lightParent.removeChild(light);
if (showLight) {
light.x = sprite.x + Math.cos(angle - Angle.RAD90) * 0;
light.y = sprite.y + Math.sin(angle - Angle.RAD90) * 0;
light.rotation = sprite.rotation;
}
light3D.point.x = point.x + _front.x * 2.5;
light3D.point.y = point.y + _front.y * 2.5;
}
override public function destroy():void {
super.destroy();
}
public function setGhost(replay:ReplayData):void {
_lap = -100000;
var f:b2FilterData, objects:Array;
if (qobject is GroupObject) objects = qobject.params.objects;
else objects = [qobject];
for each(var obj:QuickObject in objects) {
f = obj.shape.GetFilterData();
f.maskBits = f.categoryBits = 0;
obj.shape.SetFilterData(f);
}
_rankLabel.visible = false;
isGhost = true;
this.replay = replay;
}
/**
* 車の初期位置を指定
* @param x
* @param y
* @param index 次のコーナーID
* @param race
*/
public function setStartPosition(x:Number, y:Number, index:int, race:Race):void {
point.x = position.x = qobject.x = x;
point.y = position.y = qobject.y = y;
var vec:Point = race.course[index].subtract(new Point(x, y));
qobject.angle = Math.atan2(vec.y, vec.x) + Angle.RAD90;
updateFront();
stockPrev();
_targetIndex = index;
if (race.lineID.length) {
var id:int = race.lineID[index];
var nextID:int = (id + 1) % race.checkPoints.length;
_roundNum = _areaID = (race.checkSide(id, this))? nextID : id;
}
}
/**
* 自動操縦用のキーを取得
*/
public function getAutoKey(race:Race):uint {
var key:uint = 0xF0000;
var p:Point = new Point(qobject.x, qobject.y), cp:Point = race.course[_targetIndex], ofp:Point = cp.subtract(p);
var d:Number = Point.distance(p, cp);
//次のコーナーに近づいたらターゲットを次に移す
if (d < 10 + _speed / 20 * 8 * proactiveRate) _targetIndex = ++_targetIndex % race.course.length;
//次のコーナーを向くようにハンドリング調整
if (Math.acos((ofp.x * _front.x + ofp.y * _front.y) / (ofp.length * _front.length)) > 0.13)
key |= (ofp.x * _front.y - ofp.y * _front.x > 0)? 0x00F00 : 0x000F0;
//一定時間止まっていたらバックに切り替える
if (!_backMode && _speed < 2 && ++_stress > 80) _backMode = true;
else if (_backMode && --_stress <= 0) _backMode = false;
//バック中は進む方向とハンドリングを逆転させる
if (_backMode) key ^= 0xFFFF0;
else if (_speed > 4) _stress = 0;
return key;
}
/**
* 車にかかる力を調整
*/
public function simulate(race:Race):void {
qobject.angle = qobject.angle % Angle.RAD360;
updateFront();
if (replay.isPlaying) return;
//周回判定処理
checkLap(race);
//key: [accel][brake/back][left][right][empty]
_key = (autoSteer)? getAutoKey(race) : race.key;
//ドリフト
var steering:Number = Math.abs(qobject.body.GetAngularVelocity());
if (!_readyDrift && !autoSteer && _key & 0x00FF0 && !(_key & 0xF0000)) {
_driftStart = $.game.getSceneTime();
_readyDrift = true;
} else if (_readyDrift && (_key & 0x00FF0) && (_key & 0xF0000)) {
_readyDrift = false;
if ($.game.getSceneTime() - _driftStart < 1000) {
_driftPer = Math.min(1, _speedRate * steering);
}
}
var fv0:Point = _front.clone();
var fv:Point = _front.clone();
var vec:b2Vec2 = qobject.body.GetLinearVelocity();
_speed = (vec.x * fv0.x + vec.y * fv0.y) * (1 - _driftPer) + vec.Length() * _driftPer;
fv.normalize(_speed);
updateSpeedRate();
//摩擦とブレーキ
_dirtRate = 1 - (race.dirtMap.getPixel(S.QtoD(qobject.x), S.QtoD(qobject.y)) & 0xFF) / 0xFF;
var isBraking:Boolean = (_key & 0xFF000) == 0xFF000 || (_speed > 0.1 && (_key & 0x0F000));
var brakeRate:Number = isBraking? 0.99 - (1 - _speedRate) * (1 - _speedRate) * (1 - _speedRate) * 0.15 : 0.996;
var friction:Number = brakeRate * (1 - _dirtRate * race.track.dirtFriction);
var tslip:Number = Math.min(0.99, steering / 2.67 * _speedRate * 2.5 * (1 + _driftPer * 0.4));
_slip += (tslip - _slip) * ((tslip > _slip)? 0.11 : 0.07);
vec.x = (vec.x * _slip + fv.x * (1-_slip)) * friction;
vec.y = (vec.y * _slip + fv.y * (1-_slip)) * friction;
qobject.body.SetLinearVelocity(vec);
var a:Number = (accel * _speedRate + accelFirst * (1 - _speedRate)) * ((_nitro > 0)? 1.35 : 1);
if (_nitro > 0) _nitro--;
fv0.normalize(qobject.body.GetMass() * a * int(!!(_key & 0xF0000)) - qobject.body.GetMass() * a / 2 * int(!!(_key & 0x0F000)));
if (!isBraking) qobject.body.ApplyForce(new b2Vec2(fv0.x, fv0.y) , qobject.body.GetPosition());
//ハンドリング制御
var t:Number = (autoSteer? 5 : 6 * (1 - _speedRate * (1 - handling))) * (int(!!(_key & 0x000F0)) - int(!!(_key & 0x00F00))) * ((_speed > 0)? 1 : -1);
//_torque += (t - _torque) * (autoSteer? steerSpeed : 0.35);
if(autoSteer)
_torque += (t - _torque) * (autoSteer? steerSpeed : 0.35);
else
_torque += ((7*(_distanceEstimator.currentAngle/Math.PI-0.5)*2) - _torque) * (autoSteer? steerSpeed : 0.35);
var trq:Number = qobject.body.GetMass() * vec.Length() / (14 + _speedRate * 43) * _torque * (1 + _driftPer * driftPower);
qobject.body.ApplyTorque(trq);
qobject.body.SetAngularVelocity(qobject.body.GetAngularVelocity() * 0.8);
if (_driftPer > 0 && ((steering < 0.2 && _slip <= 1.5) || _speedRate < 0.5 || _dirtRate > 0.5 || isBraking)) _driftPer *= 0.8;
if ((_driftPer -= 0.005) < 0.2) _driftPer = 0;
}
private function updateSpeedRate():void {
var rate:Number = _speed / 20;
if (rate < 0) rate *= -1;
_speedRate = (rate > 1)? 1 : (rate < 0)? 0 : rate;
}
/**
* 一定時間加速
*/
public function chargeNitro():void {
_nitro = 50;
}
//周回チェック
private function checkLap(race:Race):void {
if (!race.checkPoints.length || (prevPoint.x == qobject.x && prevPoint.y == qobject.y)) return;
var prevID:int = (_areaID - 1 + race.checkPoints.length) % race.checkPoints.length;
if (race.checkCross(_areaID, this) && race.checkSide(_areaID, this)) {
_areaID = ++_areaID % race.checkPoints.length;
_roundNum++;
} else if (race.checkCross(prevID, this) && !race.checkSide(prevID, this)) {
_areaID = prevID;
_roundNum--;
}
_lap = (_roundNum - 1 + (10000 - race.getDistance(_areaID, this)) / 10000) / race.checkPoints.length;
}
public function updateMark():void {
mapMark.x = S.QtoM(qobject.x);
mapMark.y = S.QtoM(qobject.y);
var screen:Point = (isPlayer)? null : getScreen();
rankMark.visible = (!!screen && _distance < 700);
if (rankMark.visible) {
rankMark.x = screen.x | 0;
rankMark.y = screen.y | 0;
}
}
private function updateFront():void {
_front.x = Math.cos(qobject.angle - Angle.RAD90);
_front.y = Math.sin(qobject.angle - Angle.RAD90);
}
}
/**
* リプレイ管理
*/
class ReplayManager {
//ゴーストカーの上限数
private const LIMIT:int = 10;
private var _data:Vector.<ReplayData> = new Vector.<ReplayData>();
private var _last:ReplayData;
public function get data():Vector.<ReplayData> { return _data; }
public function get last():ReplayData { return _last; }
public function ReplayManager() {
}
public function getDataByID(id:int):Vector.<ReplayData> {
var list:Vector.<ReplayData> = new Vector.<ReplayData>();
for (var i:int = 0; i < _data.length; i++) {
if (_data[i].trackID == id) list.push(_data[i]);
}
return list;
}
public function add(replay:ReplayData):void {
_last = replay;
var same:Vector.<ReplayData> = new Vector.<ReplayData>();
var other:Vector.<ReplayData> = new Vector.<ReplayData>();
for (var i:int = 0; i < _data.length; i++) {
if (replay.trackID == _data[i].trackID) same.push(_data[i]);
else other.push(_data[i]);
}
same.push(replay);
same.sort(function(a:ReplayData, b:ReplayData):int { return a.raceTime - b.raceTime } );
if (same.length > LIMIT) same.length = LIMIT;
if (other.length + same.length > LIMIT) other.length = LIMIT - same.length;
_data = same.concat(other);
}
}
/**
* リプレイデータ
*/
class ReplayData {
public var limit:int = 21600;//4data * 30frame * 60sec * 3min;
public var data:Vector.<int> = new Vector.<int>();
public var index:int = 0;
public var finish:int = 0;
public var start:int = 0;
public var end:int = 0;
public var timeCount:int = 0;
public var wait:int = 0;
public var isPlaying:Boolean = false;
public var raceTime:int = 0;
public var trackID:int;
public function get x():Number { return data[index] / 1000; }
public function get y():Number { return data[index+1] / 1000; }
public function get angle():Number { return data[index+2] / 100; }
public function get inDirt():Boolean { return (data[index+3] & 4) > 0; }
public function get isBrake():Boolean { return (data[index+3] & 2) > 0; }
public function get isDrift():Boolean { return (data[index+3] & 1) > 0; }
public function get isValid():Boolean { return index < data.length - 3; }
public function get isFinish():Boolean { return index == finish; }
public function get isWaiting():Boolean { return wait > 0; }
public function ReplayData() {
}
public function clone():ReplayData {
var r:ReplayData = new ReplayData();
for each(var node:XML in describeType(this)..variable)
if (["int", "Boolean", "String", "Number", "uint"].indexOf(String(node.@type)) != -1)
r[node.@name] = this[node.@name];
r.data = data.concat();
return r;
}
public function clear():void {
data.length = index = finish = start = end = timeCount = wait = 0;
isPlaying = false;
}
public function setFinish(race:Race):void {
finish = index;
trackID = race.track.id;
raceTime = race.raceTime;
}
public function startRecord():void {
clear();
timeCount = limit / 4;
index = 0;
}
public function stopRecord():void {
if (data.length < limit) {
start = 0;
end = data.length - 1;
} else {
start = index;
end = (index - 4 + limit) % limit;
}
}
/**
* リプレイデータを最初から再生
* @param isGhost ゴーストデータかどうか
*/
public function startReplay(isGhost:Boolean = false, offset:int = 0):void {
index = start;
isPlaying = true;
wait = (isGhost)? Math.max(0, -timeCount) : 0;
if (offset < 0) offset = 0;
wait -= offset;
if (wait < 0) index = (index - wait * 4) % limit;
}
public function add(point:Point, angle:Number, isBrake:Boolean = false, isDrift:Boolean = false, isDirt:Boolean = false):void {
data[index] = (point.x * 1000) | 0;
data[index+1] = (point.y * 1000) | 0;
data[index + 2] = (angle * 100) | 0;
data[index + 3] = int(isDirt) << 2 | int(isBrake) << 1 | int(isDrift);
}
public function toObject():Object {
return { track:trackID, data:data };
}
public function tick():void {
if (wait-- > 0) return;
index = (index + 4) % limit;
if (!isPlaying) timeCount--;
}
}
/**
* SiONで効果音
*/
class SE {
//OMP_*** = [voice1, voice2, note, length]
static public const OMP_COLLISIONS:Array = [[14, 32, 5, 1], [1, 51, 20, 1], [1, 47, 30, 1], [6, 13, 30, 3]];
static public const OMP_OPTION:Array = [0, 13, 90, 1];
static public const OMP_SELECT:Array = [14, 0, 50, 1];
static public const OMP_SWITCH:Array = [14, 0, 80, 1];
static public const OMP_CANCEL:Array = [0, 11, 50, 1.5];
static public const OMP_BO:Array = [0, 3, 35, 0.5];
static public const OMP_BOO:Array = [0, 3, 40, 5];
static public const SND_LAP:String = "lap";
static public const SND_NEWRECORD:String = "highscore";
static public const SND_FINAL:String = "final";
static public const SND_FINISH:String = "finish";
static public const SND_COUNT:String = "count";
static public const SND_GO:String = "go";
static private var _time:int = 0;
static private var _driver:SiONDriver = new SiONDriver();
static private var _voices:SiONPresetVoice = new SiONPresetVoice();
static private var _engineData:Array = [];
static private var _isLastDirt:Boolean = false;
static private var _isLastDrift:Boolean = false;
static private var _isMute:Boolean = false;
static private var _effectData:Object = { };
static public function get mute():Boolean { return _isMute; }
static public function set mute(value:Boolean):void { if(_isMute = value) stopAll(); }
public function SE() {
}
static public function init():void {
_driver.volume = 1;
_driver.bpm = 120;
//[voice1, voice2, min, max, old]
_engineData.push([0, 10, 13, 30, -1]);
_engineData.push([13, 111, 10, 27, -1]);
_effectData[SND_COUNT] = _driver.compile("t120; %3@1 cr2;");
_effectData[SND_GO] = _driver.compile("t120; %3@1 <cr2;");
_effectData[SND_LAP] = _driver.compile("t120; %3@17 l24 <1q0ccc;");
_effectData[SND_NEWRECORD] = _driver.compile("t120 %3@1 l16v10<cg;");
_effectData[SND_FINAL] = _driver.compile("t120; %3@17 l32 <1q0cdcd;");
_effectData[SND_FINISH] = _driver.compile("%0@1 l32 v4c1&v3c16&v2c16; %0@0v2l8 r8<3c*>c*<c32>3r8<3c*>c*<c32;");
_driver.play();
}
static public function effect(data:String):void {
if (_isMute) return;
_driver.sequenceOn(_effectData[data], null, 0, 0, 0, 4);
}
static public function note(data:Array):void {
if (_isMute) return;
_driver.noteOn(data[2], _voices.categolies[data[0]][data[1]], data[3], 0, 0, 3);
}
static public function setVolume(value:Number):void {
_driver.volume = value;
}
static public function update(car:Car):void {
if (_isMute) return;
var per:Number = car.speed / 25;
if (per < 0) per *= -1;
per = per > 1? 1 : per < 0? 0 : per;
var isDirt:Boolean = car.dirtRate > 0 && per > 0.05;
var isDrift:Boolean = car.slip > 0.8 && per > 0.05;
if (_isLastDrift != isDrift) {
if (isDrift) _driver.noteOn(19, _voices.categolies[5][38], 0, 0, 0, 3);
else _driver.noteOff(19, 3);
_isLastDrift = isDrift;
}
if (_isLastDirt != isDirt) {
if (isDirt) _driver.noteOn(35, _voices.categolies[13][73], 0, 0, 0, 2);
else _driver.noteOff(35, 2);
_isLastDirt = isDirt;
}
for (var i:int = 0; i < _engineData.length; i++) {
var data:Array = _engineData[i];
var note:int = data[2] + (data[3] - data[2]) * per;
if (data[4] == note && ++_time<150) continue;
_time = 0;
_driver.noteOff(data[4], i);
_driver.noteOn(note, _voices.categolies[data[0]][data[1]], 0, 0, 0, i);
data[4] = note;
}
}
static public function stopAll():void {
for (var i:int = 0; i < _engineData.length; i++) {
var data:Array = _engineData[i];
if (data[4] != -1) _driver.noteOff(data[4], i);
data[4] = -1;
}
_isLastDirt = false;
_driver.noteOff(35, 2);
_driver.noteOff(19, 3);
}
}
/**
* フェードエフェクト
*/
class FadeTransition {
public var sprite:Sprite = new Sprite();
private var _tween:ITween;
private var _func:Function;
private var _isFading:Boolean = true;
/**フェード中か*/
public function get isFading():Boolean { return _isFading; }
public function FadeTransition() {
sprite.visible = true;
sprite.alpha = 1;
}
public function init():void {
Draw.box(sprite.graphics, 0, 0, Display.width, Display.height, 0);
}
public function fadeIn(func:Function = null):void {
if (_tween) _tween.stop();
_tween = BetweenAS3.to(sprite, { alpha:0 }, 0.5);
_tween.onComplete = function():void {
sprite.visible = false;
_isFading = false;
if (func != null) func();
};
_tween.play();
}
public function fadeOut(func:Function = null):void {
sprite.visible = true;
_isFading = true;
if (_tween) _tween.stop();
_tween = BetweenAS3.to(sprite, { alpha:1 }, 0.5);
_tween.onComplete = func;
_tween.play();
}
public function fadeOutIn(func:Function = null):void {
//指定のfunc処理が重いと時間が飛ぶので前後に数フレーム間を空ける
fadeOut(function():void {
FrameTimer.setTimer(2, function():void {
if (func != null) func();
FrameTimer.setTimer(2, fadeIn);
});
});
}
}
/**
* 選択肢
*/
class LabelMenu extends Sprite {
private var _enabled:Boolean = true;
private var _selectFunc:Function;
private var _cancelFunc:Function;
private var _changeFunc:Function;
private var _switchFunc:Function;
private var _selected:int = 0;
private var _items:Vector.<MenuItem> = new Vector.<MenuItem>();
private var _labels:Vector.<Array> = new Vector.<Array>();
private var _options:Vector.<int> = new Vector.<int>();
public function get items():Vector.<MenuItem> { return _items; }
public function get options():Vector.<int> { return _options; }
public function get selected():int { return _selected; }
public function get enabled():Boolean { return _enabled; }
public function set enabled(value:Boolean):void {
_enabled = value;
if(_enabled) Display.stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
else Display.stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
}
/**
* @param parent addChild()する場所
* @param x X座標
* @param y Y座標
* @param texts 選択肢をラベル名の配列で指定。XXX{A,B,C}YYYの書式で{}の中のリストが左右で切り替えできる
* @param selectFunc 決定キーを押したら呼ばれる
* @param cancelFunc キャンセルキーを押したら呼ばれる
* @param changeFunc 上下移動したら呼ばれる
* @param switchFunc 左右に切り替えたら呼ばれる
* @param space 選択肢の配置間隔
*/
public function LabelMenu(parent:DisplayObjectContainer = null, x:Number = 0, y:Number = 0, texts:Array = null, selectFunc:Function = null, cancelFunc:Function = null, changeFunc:Function = null, switchFunc:Function = null, space:Number = 30) {
if (parent) parent.addChild(this);
this.y = y;
_selectFunc = selectFunc;
_cancelFunc = cancelFunc;
_changeFunc = changeFunc;
_switchFunc = switchFunc;
var i:int, match:Array, labels:Array, item:MenuItem;
if (!texts) texts = [];
for (i = 0; i < texts.length; i++) {
match = texts[i].match(/(.*)\{(.*)\}(.*)/);
labels = [];
if (match == null) labels = [texts[i]];
else for each(var str:String in match[2].split(",")) labels.push(match[1] + str + match[3]);
item = addChild(new MenuItem(x, space)) as MenuItem;
item.index = i;
item.setText(labels[0]);
item.y = i * space;
item.icon.bitmapData = (labels.length >= 2)? Dot.LR : Dot.Z;
item.icon.y += (labels.length >= 2)? 2 : 0;
_items.push(item);
_labels.push(labels);
_options.push(0);
}
update();
enabled = true;
}
public function setLabelsAt(n:int, labels:Array):void {
_labels[n] = labels;
_items[n].setText(_labels[n][_options[n]]);
}
public function dispose():void {
enabled = false;
if (parent) parent.removeChild(this);
_selectFunc = _cancelFunc = _changeFunc = _switchFunc = null;
}
private function onKeyDown(e:KeyboardEvent):void {
if (!_enabled) return;
switch(e.keyCode) {
case Keyboard.UP: updown(-1); break;
case Keyboard.DOWN: updown(1); break;
case Keyboard.RIGHT: switchOption(1); break;
case Keyboard.LEFT: switchOption(-1); break;
case Keyboard.ENTER: case 90:
if (!_items[_selected].enabled) {
SE.note(SE.OMP_BO);
} else {
if (_selectFunc != null) _selectFunc(_selected);
SE.note(SE.OMP_SELECT);
}
break;
case Keyboard.SHIFT: case 88:
if (_cancelFunc != null) _cancelFunc();
SE.note(SE.OMP_CANCEL);
break;
}
}
/**
* インデックス指定でアイテムを選択
*/
public function select(index:int):void {
_selected = index;
update();
}
/**
* 左右のオプションを切り替える
* @param index
* @param option
* @param dispatchEvent
*/
public function setOption(index:int, option:int, dispatchEvent:Boolean = false):void {
_options[index] = option;
_items[index].setText(_labels[index][option]);
if (dispatchEvent) _switchFunc(index, option);
}
private function switchOption(delta:int):void {
_options[_selected] = (_options[_selected] + delta + _labels[_selected].length) % _labels[_selected].length;
_items[_selected].setText(_labels[_selected][_options[_selected]]);
if (_labels[_selected].length >= 2) {
SE.note(SE.OMP_OPTION);
if (_switchFunc != null) _switchFunc(_selected, _options[_selected]);
}
}
private function updown(delta:int):void {
_selected = (_selected + delta + _items.length) % _items.length;
update();
SE.note(SE.OMP_SWITCH);
}
private function update():void {
for each (var item:MenuItem in _items) item.setSelect(item.index == _selected);
if (_changeFunc != null) _changeFunc(_selected);
}
}
/**
* 選択肢用アイテム
*/
class MenuItem extends Sprite {
private var _label:Label;
private var _base:Sprite;
public var icon:Bitmap = new Bitmap();
public var index:int = 0;
public var enabled:Boolean = true;
public function MenuItem(x:Number = 0, height:Number = 30) {
_label = UI.createLabel(null, x, int((height - 34) / 2), "");
_base = Create.gradientBox(0, 0, Display.width, height, true, 90, [UI.BASE, UI.DARK], [0.9, 0.9], [0, 0xFF]);
addChild(_base);
addChild(_label);
addChild(icon);
icon.x = _label.x - 25;
icon.y = _label.y + 7;
icon.scaleX = icon.scaleY = 2;
icon.visible = false;
}
public function setText(str:String):void {
_label.text = str;
}
public function setEnabled(enabled:Boolean):void {
this.enabled = enabled;
var rgb:uint = enabled? 0xFFFFFF : 0xDDDDDD;
_label.transform.colorTransform = Palette.getColorTransform(rgb);
}
public function setSelect(select:Boolean):void {
icon.visible = _base.visible = select;
filters = (select)? [] : UI.TEXT_FILTERS;
}
}
/**
* フレームベースのタイマー
*/
class FrameTimer {
static private var _sprite:Sprite = new Sprite();
static private var _timers:Object = { };
static private var _count:int = 0;
static public function clearTimer(id:String = ""):void {
if (id == "") _timers = { };
else _timers[id] && delete _timers[id];
}
static public function setTimer(interval:int, complete:Function, args:Array = null, id:String = ""):void {
if (interval <= 0) {
complete.apply(null, args || []);
return;
}
_timers[id || "_"+(++_count)] = { time:interval, complete:complete, args:(args || []) };
_sprite.addEventListener(Event.ENTER_FRAME, onTickTimer);
}
static private function onTickTimer(e:Event = null):void {
for (var k:String in _timers) {
if (--_timers[k].time <= 0) {
_timers[k].complete.apply(null, _timers[k].args);
clearTimer(k);
}
}
}
}
/**
* ラジアンと通常角の変換
*/
class Angle {
static public const RAD45:Number = Math.PI / 4;
static public const RAD90:Number = Math.PI / 2;
static public const RAD180:Number = Math.PI;
static public const RAD360:Number = Math.PI * 2;
static public const toRAD:Number = Math.PI / 180;
static public const toROT:Number = 180 / Math.PI;
}
/**
* 色操作
*/
class Palette {
static public function mix(rgb1:uint, rgb2:uint, per:Number = 1):uint {
var r:uint = (rgb1 >> 16 & 0xFF) * (1 - per) + (rgb2 >> 16 & 0xFF) * per;
var g:uint = (rgb1 >> 8 & 0xFF) * (1 - per) + (rgb2 >> 8 & 0xFF) * per;
var b:uint = (rgb1 & 0xFF) * (1 - per) + (rgb2 & 0xFF) * per;
return r << 16 | g << 8 | b;
}
static public function getColorTransform(rgb:uint, per:Number = 1, alpha:Number = 1):ColorTransform {
var ct:ColorTransform = new ColorTransform();
setColorTransform(ct, rgb, per, alpha);
return ct;
}
static public function setColorTransform(ct:ColorTransform, rgb:uint, per:Number, alpha:Number = 1):void {
ct.redMultiplier = ct.greenMultiplier = ct.blueMultiplier = 1 - per;
ct.redOffset = (rgb >> 16 & 0xFF) * per;
ct.greenOffset = (rgb >> 8 & 0xFF) * per;
ct.blueOffset = (rgb & 0xFF) * per;
ct.alphaMultiplier = alpha;
}
}
/**
* グラフィックを生成する
*/
class Create {
static public function gradientLabel(sp:Sprite, rgb1:uint, rgb2:uint, start:uint = 0x0, end:uint = 0xFF):Bitmap {
var mask:BitmapData = new BitmapData(sp.width, sp.height, false, 0xFF000000);
Display.cacheQuality(StageQuality.BEST);
mask.draw(sp, null, Palette.getColorTransform(0xFFFFFF));
var bmd:BitmapData = new BitmapData(mask.width, mask.height, true, 0);
bmd.draw(Create.gradientBox(0, 0, bmd.width, bmd.height, true, 90, [rgb1, rgb2], [1, 1], [start, end]));
bmd.copyChannel(mask, mask.rect, PointUtil.ZERO, BitmapDataChannel.BLUE, BitmapDataChannel.ALPHA);
bmd.applyFilter(bmd, bmd.rect, PointUtil.ZERO, new DropShadowFilter(1, 45, 0x0, 4, 4, 4, 60, 1));
mask.dispose();
Display.restoreQuality();
return new Bitmap(bmd);
}
static public function circle(x:Number, y:Number, width:Number, height:Number, rgb:uint = 0x000000, alpha:Number = 1):Sprite {
var sp:Sprite = new Sprite();
Draw.circle(sp.graphics, x, y, width, height, rgb, alpha);
return sp;
}
static public function gradientCircle(x:Number, y:Number, width:Number, height:Number, rgbs:Array, alphas:Array, ratios:Array):Sprite {
var sp:Sprite = new Sprite();
Draw.gradientCircle(sp.graphics, x, y, width, height, rgbs, alphas, ratios);
return sp;
}
static public function box(x:Number, y:Number, width:Number, height:Number, rgb:uint, alpha:Number = 1, tx:Number = 0, ty:Number = 0):Sprite {
var sp:Sprite = new Sprite();
Draw.box(sp.graphics, x, y, width, height, rgb, alpha);
sp.x = tx;
sp.y = ty;
return sp;
}
static public function gradientBox(x:Number, y:Number, width:Number, height:Number, isLinear:Boolean, rotation:Number, rgbs:Array, alphas:Array, ratios:Array):Sprite {
var sp:Sprite = new Sprite();
Draw.gradientBox(sp.graphics, x, y, width, height, isLinear, rotation, rgbs, alphas, ratios);
return sp;
}
static public function spriteBmp(bmd:BitmapData, scale:Number = 1, tx:Number = 0, ty:Number = 0, x:Number = 0, y:Number = 0):Sprite {
var sp:Sprite = new Sprite();
sp.addChild(bitmap(bmd, scale, tx, ty));
sp.x = x;
sp.y = y;
return sp;
}
static public function cloud(width:Number, height:Number, seed:int, rgb1:uint, rgb2:uint):BitmapData {
var bmd:BitmapData = new BitmapData(width, height, true, 0);
for (var i:int = 0; i < 3; i++) bmd.draw(smoke(width, height, seed, 0.7 - i * 0.2, Palette.mix(rgb1, rgb2, 1 - i / 2)));
return bmd;
}
static public function smoke(width:Number, height:Number, seed:int, per:Number, rgb:uint):BitmapData {
var bmd:BitmapData = new BitmapData(width, height, true, 0);
bmd.perlinNoise(width/4, height/4, 3, seed, false, true, BitmapDataChannel.RED, false);
bmd.draw(new Bitmap(bmd), null, null, BlendMode.OVERLAY);
bmd.draw(gradientBox(0, 0, width, height, false, 0, [0x000000, 0x000000], [1, 0], [0x00, 0xFF]), null, null, BlendMode.OVERLAY);
bmd.draw(gradientBox(0, 0, width, height, false, 0, [0xFF0000, 0xFF0000], [0, 1], [0x80, 0xFF]));
bmd.threshold(bmd, bmd.rect, PointUtil.ZERO, ">", 0xFF000000 | per*0xFF<<16, 0);
bmd.colorTransform(bmd.rect, new ColorTransform(0, 0, 0, 1, rgb>>16&0xFF, rgb>>8&0xFF, rgb&0xFF));
return bmd;
}
static public function bitmapFillBox(x:Number, y:Number, width:Number, height:Number, bmd:BitmapData, scaleX:Number = 1, scaleY:Number = 1, tx:Number = 0, ty:Number = 0):Sprite {
var sp:Sprite = new Sprite();
Draw.bitmapFillBox(sp.graphics, x, y, width, height, bmd, scaleX, scaleY, tx, ty);
return sp;
}
static public function bitmap(bmd:BitmapData, scale:Number = 1, x:Number = 0, y:Number = 0):Bitmap {
var bmp:Bitmap = new Bitmap(bmd);
bmp.scaleX = bmp.scaleY = scale;
bmp.x = x * scale;
bmp.y = y * scale;
return bmp;
}
}
/**
* グラフィックを描画する
*/
class Draw {
static public function bitmapFillBox(g:Graphics, x:Number, y:Number, width:Number, height:Number, bmd:BitmapData, scaleX:Number = 1, scaleY:Number = 1, tx:Number = 0, ty:Number = 0):void {
g.beginBitmapFill(bmd, new Matrix(scaleX, 0, 0, scaleY, tx, ty), true);
g.drawRect(x, y, width, height);
g.endFill();
}
static public function box(g:Graphics, x:Number, y:Number, width:Number, height:Number, rgb:uint, alpha:Number = 1):void {
g.beginFill(rgb, alpha);
g.drawRect(x, y, width, height);
g.endFill();
}
static public function circle(g:Graphics, x:Number, y:Number, width:Number, height:Number, rgb:uint = 0x000000, alpha:Number = 1):void {
g.beginFill(rgb, alpha);
g.drawEllipse(x - width, y - height, width * 2, height * 2);
g.endFill();
}
static public function gradientBox(g:Graphics, x:Number, y:Number, width:Number, height:Number, isLinear:Boolean, rotation:Number, rgbs:Array, alphas:Array, ratios:Array):void {
var mtx:Matrix = new Matrix();
mtx.createGradientBox(width, height, rotation * Angle.toRAD, x, y);
g.beginGradientFill(isLinear? GradientType.LINEAR : GradientType.RADIAL, rgbs, alphas, ratios, mtx);
g.drawRect(x, y, width, height);
g.endFill();
}
static public function gradientCircle(g:Graphics, x:Number, y:Number, width:Number, height:Number, rgbs:Array, alphas:Array, ratios:Array):void {
var mtx:Matrix = new Matrix();
mtx.createGradientBox(width*2, height*2, 0, x - width, y - height);
g.beginGradientFill(GradientType.RADIAL, rgbs, alphas, ratios, mtx);
g.drawEllipse(x - width, y - height, width * 2, height * 2);
g.endFill();
}
}
/**
* 2D座標操作
*/
class PointUtil {
static public const ZERO:Point = new Point();
static public function rotate(p:Point, radian:Number):Point {
var np:Point = new Point();
np.x = p.x * Math.cos(radian) - p.y * Math.sin(radian);
np.y = p.x * Math.sin(radian) + p.y * Math.cos(radian);
return np;
}
}
/**
* ピクセル操作
*/
class Pixel {
static public function drawDarkLine(bmd:BitmapData, x1:int, y1:int, x2:int, y2:int, per:Number, skipFirst:Boolean = false):void {
var dx:int = (x2 > x1)? x2 - x1 : x1 - x2;
var dy:int = (y2 > y1)? y2 - y1 : y1 - y2;
var tx:int = (x2 > x1)? 1 : -1
var ty:int = (y2 > y1)? 1 : -1;
var e:int, i:int, x:int = x1, y:int = y1;
if (dx >= dy) {
e = 2 * dy - dx;
for (i = 0; i <= dx; i++) {
if (!skipFirst || i) setDark(bmd, x, y, per);
x += tx;
e += 2*dy;
if (e >= 0) {
y += ty;
e -= 2 * dx;
}
}
} else {
e = 2 * dx - dy;
for (i = 0; i <= dy; i++) {
if(!skipFirst || i)setDark(bmd, x, y, per);
y += ty;
e += 2 * dx;
if (e >= 0) {
x += tx;
e -= 2 * dy;
}
}
}
}
static public function setDark(bmd:BitmapData, x:int, y:int, alpha:Number):void {
var rgb:uint = bmd.getPixel(x, y);
rgb = (rgb >> 16 & 0xFF) * alpha << 16 | (rgb >> 8 & 0xFF) * alpha << 8 | (rgb & 0xFF) * alpha;
bmd.setPixel(x, y, rgb);
}
}
/**
* Vector3D操作
*/
class Vector3DUtil {
static private var _fromN:Vector3D = new Vector3D;
static private var _toN:Vector3D = new Vector3D;
static public function slerpVector(from:Vector3D, to:Vector3D, t:Number):Vector3D {
if (!from.lengthSquared || !from.lengthSquared || from.equals(to)) return from.clone();
copy(from, _fromN);
copy(to, _toN);
_fromN.normalize();
_toN.normalize();
var angle:Number = getAngleUnit(_fromN, _toN);
if (angle == Math.PI) {
_fromN.x += 0.000001;
if (!_fromN.y && !_fromN.z) _fromN.y += 0.000001;
_fromN.normalize();
angle = getAngleUnit(_fromN, _toN);
}
var sin:Number = Math.sin(angle);
if (!sin) return _fromN.clone();
var sinf:Number = Math.sin(angle * (1 - t));
var sint:Number = Math.sin(angle * t);
var v:Vector3D = new Vector3D();
if (sin) {
v.x = (_fromN.x * sinf + _toN.x * sint) / sin;
v.y = (_fromN.y * sinf + _toN.y * sint) / sin;
v.z = (_fromN.z * sinf + _toN.z * sint) / sin;
}
v.normalize();
return v;
}
static public function setXYZ(v:Vector3D, x:Number, y:Number, z:Number):void {
v.x = x;
v.y = y;
v.z = z;
}
static public function mix(a:Vector3D, b:Vector3D, per:Number = 0):Vector3D {
return new Vector3D(a.x * (1 - per) + b.x * per, a.y * (1 - per) + b.y * per, a.z * (1 - per) + b.z * per);
}
static public function cross(a:Vector3D, b:Vector3D):Vector3D {
return new Vector3D((a.y * b.z) - (a.z * b.y), (a.z * b.x) - (a.x * b.z), (a.x * b.y) - (a.y * b.x));
}
static public function copy(from:Vector3D, to:Vector3D):void {
to.x = from.x;
to.y = from.y;
to.z = from.z;
to.w = from.w;
}
static public function getAngle(a:Vector3D, b:Vector3D):Number {
var dot:Number = (a.x * b.x + a.y * b.y + a.z * b.z) / (a.length * b.length);
return Math.acos(dot > 1? 1 : dot < -1? -1 : dot);
}
static public function getAngleUnit(a:Vector3D, b:Vector3D):Number {
var dot:Number = (a.x * b.x + a.y * b.y + a.z * b.z);
return Math.acos(dot > 1? 1 : dot < -1? -1 : dot);
}
}
/**
* 2Dベクトル操作
*/
class VectorUtil {
static public function dot(a:Point, b:Point):Number {
return dotXY(a.x, a.y, b.x, b.y);
}
static public function cross(a:Point, b:Point):Number {
return crossXY(a.x, a.y, b.x, b.y);
}
/**
* 2つのベクトルの角度をXYで求める
*/
static public function getAngleXY(ax:Number, ay:Number, bx:Number, by:Number):Number {
var cos:Number = (ax * bx + ay * by) / (Math.sqrt(ax * ax + ay * ay) * Math.sqrt(bx * bx + by * by));
return Math.acos(cos > 1? 1 : (cos < -1? -1 : cos));
}
/**
* 2つのベクトルの内積をXYで求める
* >1に近いほど同方向に平行
* >-1に近いほど逆向き平行
* >0に近いほど直角
*/
static public function dotXY(ax:Number, ay:Number, bx:Number, by:Number):Number {
return ax * bx + ay * by;
}
/**
* 2つのベクトルの外積をXYで求める
* >結果の符号でベクトルAに対してベクトルBが左右どちらにあるか判定できる
* >結果が0なら2つのベクトルは平行
*/
static public function crossXY(ax:Number, ay:Number, bx:Number, by:Number):Number {
return ax * by - ay * bx;
}
}
/**
* 直線処理
*/
class LineUtil {
/**
* 2線分の交点をPointで求める
*/
static public function crossSegment(a1:Point, a2:Point, b1:Point, b2:Point):Point {
if (!isCross.apply(null, arguments)) return null;
else return crossLine.apply(null, arguments);
}
/**
* 2直線の交点をPointで求める
*/
static public function crossLine(a1:Point, a2:Point, b1:Point, b2:Point):Point {
return crossLineXY(a1.x, a1.y, a2.x, a2.y, b1.x, b1.y, b2.x, b2.y);
}
/**
* 2直線の交点をXYで求める
*/
static public function crossLineXY(ax1:Number, ay1:Number, ax2:Number, ay2:Number, bx1:Number, by1:Number, bx2:Number, by2:Number):Point {
var v1x:Number = ax2 - ax1, v1y:Number = ay2 - ay1;
var v2x:Number = bx1 - ax1, v2y:Number = by1 - ay1;
var v3x:Number = bx2 - bx1, v3y:Number = by2 - by1;
var cross:Number = VectorUtil.crossXY(v3x, v3y, v1x, v1y);
if (!cross) return null;
var scale:Number = VectorUtil.crossXY(v3x, v3y, v2x, v2y) / cross;
return new Point(v1x * scale + ax1, v1y * scale + ay1);
}
/**
* 2線分が交差しているかPointで調べる(先端が接触していても交差とみなす)
*/
static public function isCross(a1:Point, a2:Point, b1:Point, b2:Point):Boolean {
return isCrossXY(a1.x, a1.y, a2.x, a2.y, b1.x, b1.y, b2.x, b2.y);
}
/**
* 2線分が交差しているかXYで調べる(先端が接触していても交差とみなす)
*/
static public function isCrossXY(ax1:Number, ay1:Number, ax2:Number, ay2:Number, bx1:Number, by1:Number, bx2:Number, by2:Number):Boolean {
if (((ax1 - ax2) * (by1 - ay1) + (ay1 - ay2) * (ax1 - bx1)) * ((ax1 - ax2) * (by2 - ay1) + (ay1 - ay2) * (ax1 - bx2)) > 0) return false;
if (((bx1 - bx2) * (ay1 - by1) + (by1 - by2) * (bx1 - ax1)) * ((bx1 - bx2) * (ay2 - by1) + (by1 - by2) * (bx1 - ax2)) > 0) return false;
return true;
}
/**
* 2点間の距離をXYで求める
*/
static public function getDistanceXY(ax:Number, ay:Number, bx:Number, by:Number):Number {
var dx:Number = ax - bx;
var dy:Number = ay - by;
return Math.sqrt(dx * dx + dy * dy);
}
/**
* 1つの点と線分の最短距離をPointで求める
*/
static public function getNearDistance(a:Point, b:Point, p:Point):Number {
return getNearDistanceXY(a.x, a.y, b.x, b.y, p.x, p.y);
}
/**
* 1つの点と線分の最短距離をXYで求める
*/
static public function getNearDistanceXY(x1:Number, y1:Number, x2:Number, y2:Number, px:Number, py:Number):Number {
var dx:Number = x2 - x1, dy:Number = y2 - y1;
var t:Number = -(dx * (x1 - px) + dy * (y1 - py)) / (dx * dx + dy * dy);
t = (t < 0)? 0 : (t > 1)? 1 : t;
var tx:Number = x1 + dx * t;
var ty:Number = y1 + dy * t;
return Math.sqrt((px - tx) * (px - tx) + (py - ty) * (py - ty));
}
}
/**
* 曲線処理
*/
class CurveUtil {
public function CurveUtil() {
}
static public function getBezierListXY(ax:Number, ay:Number, bx:Number, by:Number, cax:Number, cay:Number, cbx:Number, cby:Number, segments:int = 1):Vector.<Point> {
var points:Vector.<Point> = new Vector.<Point>();
for (var i:int = 0; i < segments + 1; i++) points.push(getBezierXY(ax, ay, bx, by, cax, cay, cbx, cby, i / segments));
return points;
}
static public function getBezierList(a:Point, b:Point, ca:Point, cb:Point, segments:int = 1):Vector.<Point> {
return getBezierListXY(a.x, a.y, b.x, b.y, ca.x, ca.y, cb.x, cb.y, segments);
}
static public function drawBezierXY(graphics:Graphics, ax:Number, ay:Number, bx:Number, by:Number, cax:Number, cay:Number, cbx:Number, cby:Number, segments:int = 1, scale:Number = 1):void {
var points:Vector.<Point> = getBezierListXY(ax, ay, bx, by, ax + cax, ay + cay, bx + cbx, by + cby, segments);
for (var i:int = 0; i < points.length; i++) {
if (!i) graphics.moveTo(points[i].x * scale, points[i].y * scale);
else graphics.lineTo(points[i].x * scale, points[i].y * scale);
}
}
static public function drawBezier(graphics:Graphics, a:Point, b:Point, ca:Point, cb:Point, segments:int = 1, scale:Number = 1):void {
drawBezierXY(graphics, a.x, a.y, b.x, b.y, ca.x, ca.y, cb.x, cb.y, segments, scale);
}
static public function getBezierXY(ax:Number, ay:Number, bx:Number, by:Number, cax:Number, cay:Number, cbx:Number, cby:Number, t:Number):Point {
var t2:Number = 1 - t;
var v1:Number = t2 * t2 * t2;
var v2:Number = 3 * t * t2 * t2;
var v3:Number = 3 * t * t * t2;
var v4:Number = t * t * t;
return new Point(v1 * ax + v2 * cax + v3 * cbx + v4 * bx, v1 * ay + v2 * cay + v3 * cby + v4 * by);
}
static public function getBezier(a:Point, b:Point, ca:Point, cb:Point, t:Number):Point {
return getBezierXY(a.x, a.y, b.x, b.y, ca.x, ca.y, cb.x, cb.y, t);
}
}
/**
* bkzenさんのをお借りしました
* @see http://wonderfl.net/c/cuY4
* @see http://wonderfl.net/c/kYyY
*/
class ScoreWindow {
public static var sprite:Sprite = new Sprite();
public static var title:String = "Test";
private static var _api:WonderflAPI;
private static var _content:Object;
private static const SWF:String = "http://swf.wonderfl.net/swf/usercode/5/57/579a/579a46e1306b5770d429a3738349291f05fec4f3.swf";
public static function init(loaderInfo:LoaderInfo, complete:Function = null, error:Function = null): void {
_api = new WonderflAPI(loaderInfo.parameters);
var loader:Loader = new Loader();
var removeEvent:Function = function():void {
loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, compFunc);
loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, errorFunc);
loader.contentLoaderInfo.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, errorFunc);
}
var errorFunc:Function = function(e:Event): void {
removeEvent();
if(error != null) error();
}
var compFunc:Function = function(e:Event): void{
removeEvent();
_content = loader.content;
if(complete != null) complete();
}
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, compFunc);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, errorFunc);
loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, errorFunc);
loader.load(new URLRequest(SWF), new LoaderContext(true));
}
/**
* スコア登録ウィンドウを開く
* @param score 登録するスコア
* @param close 閉じられた時呼ばれる
* @param scoreTitle スコアの種類を決める名前
* @param unit スコアの後ろにつけるテキスト
* @param decimal 小数点を何桁まで使うか
* @param limit スコア表示件数
* @param reverse trueでスコアが小さい方が上位になる
* @param modal モーダル処理
*/
public static function show(score:int, close:Function = null, scoreTitle:String = "Score", unit:String = "", decimal:int = 0, limit:int = 99, reverse:Boolean = false, modal:Boolean = true):void {
var tweet:String = "Playing " + title + " [" + scoreTitle + ": %SCORE%" + unit + "] #wonderfl";
var win:DisplayObject = _content.makeScoreWindow(_api, score, title, Math.pow(10, decimal), tweet, scoreTitle, unit, limit, int(!reverse));
var closeFunc:Function = function(e: Event):void {
win.removeEventListener(Event.CLOSE, closeFunc);
if(close != null) close();
}
win.addEventListener(Event.CLOSE, closeFunc);
sprite.addChild(win);
}
}
import com.bit101.components.CheckBox;
import com.bit101.components.HSlider;
import com.bit101.components.Label;
import com.bit101.components.PushButton;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.IBitmapDrawable;
import flash.display.Loader;
import flash.display.Shader;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.filters.BlurFilter;
import flash.filters.ShaderFilter;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import flash.media.Camera;
import flash.media.Video;
import flash.net.FileFilter;
import flash.net.FileReference;
import flash.utils.clearTimeout;
import flash.utils.getTimer;
import flash.utils.setTimeout;
//import net.hires.debug.Stats;
class DistanceEstimator extends Sprite {
public var video:Video;
public var source:IBitmapDrawable;
public var file:FileReference;
public var loader:Loader;
public var timeout:uint = 0;
public var resized:BitmapData;
public var input:BitmapData;
public var output:BitmapData;
public var output2:BitmapData;
public var bfilter:BlurFilter;
public var sfilter:ShaderFilter;
public var dfilter:ShaderFilter;
public var kslider:HSlider;
public var kslider2:HSlider;
public var info:Label;
public var info2:Label;
public var mainAngle:CheckBox;
public var lines:Shape;
public var currentAngle:Number = 0;
public var wheel:Wheel;
public var bmp:Bitmap;
public var ibmp:Bitmap;
public var obmp:Bitmap;
public var obmp2:Bitmap;
public var panel:Sprite = new Sprite();
public var g:Sprite = new Sprite();
public function DistanceEstimator (w:Wheel, cw:Number = 320, ch:Number = 240, fr:Number = 30) {
addChild(new Bitmap(new BitmapData(465,465,true,0x88FFFFFF)));
this.visible = false;
wheel = w;
//stage.scaleMode = "noScale";
// for lines to draw fast
//stage.quality = "low";
// set up webcam feed
//stage.frameRate = 30;
var cam:Camera = Camera.getCamera ();
if(!cam) return;
cam.setMode (cw, ch, fr);
source = video = new Video; video.attachCamera (cam);
video.x = cw; video.scaleX = -1;
//addChild (video);
// set up file feed
//file = new FileReference;
//file.addEventListener (Event.SELECT, onFileSelected);
//file.addEventListener (Event.COMPLETE, onFileLoaded);
// set up images
bmp = new Bitmap (resized = new BitmapData (cw, ch, true, 0));
with (bmp) {
x = cw; scaleX = -1;
}
/**/
ibmp = new Bitmap (input = new BitmapData (cw/2, ch/2, false, 0));
ibmp.x = cw; //addChild (ibmp);
obmp = new Bitmap (output = input.clone ());
obmp.x = cw; obmp.y = ch/2; //addChild (obmp);
obmp2 = new Bitmap (output2 = output.clone ());
obmp2.x = cw; obmp2.y = ch; //addChild (obmp2);
// set up filters
bfilter = new BlurFilter (4, 4, 2);
sfilter = new ShaderFilter (new Shader (new Base64 (SlopeEstimator3.pbj)));
dfilter = new ShaderFilter (new Shader (new Base64 (DistanceEstimator3.pbj)));
// lines
lines = new Shape; lines.scrollRect = resized.rect; //addChild (lines);
// image load button
//var button:PushButton = new PushButton (this, 0, 0, "LOAD IMAGE", onButtonClicked);
// treshold sliders
var tslider:HSlider = new HSlider (panel, 0, 0, onTSlider);
tslider.minimum = 0; tslider.maximum = 9; tslider.tick = 0.01;
tslider.value = sfilter.shader.data.threshold.value [0];
tslider.x = 320 + (160 - tslider.width) / 2;
tslider.y = 240 - tslider.height;
var tslider2:HSlider = new HSlider (panel, 0, 0, onTSlider2);
tslider2.minimum = 0.001; tslider2.maximum = 0.1; tslider2.tick = 0.001;
tslider2.value = dfilter.shader.data.threshold.value [0];
tslider2.x = 320 + (160 - tslider2.width) / 2;
tslider2.y = 360 - tslider2.height;
// blur slider
var bslider:HSlider = new HSlider (panel, 0, 0, onBSlider);
bslider.minimum = 1.0; bslider.maximum = 8.0; bslider.tick = 1.0;
bslider.value = bfilter.blurX;
bslider.x = 320 + (160 - bslider.width) / 2;
bslider.y = 120 - bslider.height;
// locality sliders
kslider = new HSlider (panel, 200, 270);
kslider.minimum = 2; kslider.maximum = 20; kslider.tick = 2.0;
kslider.value = 10;
kslider2 = new HSlider (panel, 200, 310);
kslider2.minimum = 2; kslider2.maximum = 22; kslider2.tick = 2.0;
kslider2.value = 2;
// info labels
info = new Label (panel, 200, 250, "");
info2 = new Label (panel, 200, 290, "");
// mode
mainAngle = new CheckBox (panel, tslider2.x, tslider2.y + 30, "Dominant angle only");
mainAngle.selected = true;
/**/
// processing
addEventListener (Event.ENTER_FRAME, loop);
// mrdoob's stats
//var stats:Stats = new Stats; stats.alpha = 0.75; addChild (stats);
//button.x = stats.width;
}
public function hide():DistanceEstimator
{
removeChild (video);
removeChild (ibmp);
removeChild (obmp);
removeChild (obmp2);
removeChild (bmp);
removeChild (panel);
removeChild (lines);
removeChild (g);
return this;
}
public function show():DistanceEstimator
{
addChild (video);
addChild (ibmp);
addChild (obmp);
addChild (obmp2);
addChild (bmp);
addChild (panel);
addChild (lines);
addChild (g);
return this;
}
public var h_linear:Vector.<Number> = new Vector.<Number> (768, true);
public var h_linear3:Vector.<Number> = new Vector.<Number> (256, true);
public var h_indices:Vector.<int> = new Vector.<int> (50, true);
public var h_angles:Vector.<Number> = new Vector.<Number> (9, true);
public function loop (e:Event):void {
input.fillRect (input.rect, 0); input.draw (source,
new Matrix (-0.5, 0, 0, 0.5, 160), null, null, null, true
);
input.applyFilter (input, input.rect, input.rect.topLeft, bfilter);
output.applyFilter (input, input.rect, output.rect.topLeft, sfilter);
// fetch results
var r:Rectangle = output.rect; r.inflate ( -2 * bfilter.blurX, -2 * bfilter.blurY);
var h:Vector.<Vector.<Number>> = output.histogram (r);
// copy to linear array, and find max value
var h_max:Number = copyToLinearArray3 (h, h_linear3);
// find local maxima (and draw them)
if(this.visible) g.graphics.clear ();
/*
if (getTimer () > 8000) {
1 + 2;
}
/**/
var j:int = findLocalMaxima (h_linear3, 0.2 * h_max, h_indices, kslider.value);
var i_max:int = 0, n_max:Number = 0;
for (var k:int = 0; k < h_angles.length; k++) {
h_angles [k] = -1;
}
for (k = 0; k < j; k++) {
var i:int = h_indices [k];
var n:Number = h_linear3 [i] / h_max;
if (n_max < n) {
n_max = n;
i_max = i;
}
var a:Number = Math.PI * i / 255.0;
if(this.visible)
{
g.graphics.lineStyle (2, 65536 * i);
g.graphics.moveTo (2, 360);
g.graphics.lineTo (2 + n * 120 * Math.sin (a), 360 - n * 120 * Math.cos (a));
}
if (k < h_angles.length) h_angles [k] = a;
}
if(this.visible)
{
info.text = j + " local maxima (angle)";
if (j < 1) {
output2.fillRect (output2.rect, 0);
lines.graphics.clear ();
return;
}
}
/**/
// mark dominant angle
a = Math.PI * i_max / 255.0;
currentAngle = a;
wheel.rotation = a/Math.PI*180;
//graphics.lineTo (2 + n_max * 120 * Math.sin (a), 360 - n_max * 120 * Math.cos (a));
if(this.visible)
{
g.graphics.lineStyle (2, 0);
g.graphics.moveTo (2, 360);
g.graphics.lineTo (2 + n_max * 120 * Math.sin (a), 360 - n_max * 120 * Math.cos (a));
g.graphics.beginFill (0xFFFFFF);
g.graphics.drawCircle (2 + n_max * 120 * Math.sin (a), 360 - n_max * 120 * Math.cos (a), 5);
g.graphics.endFill ();
/**/
// let's now find lines for this angle (or h_angles)
info2.text = "(multiple angles)";
lines.graphics.clear ();
lines.graphics.lineStyle (2, 0xFF7F00);
for (var m:int = 0; m < h_angles.length; m++) {
if (!mainAngle.selected) {
a = h_angles [m];
if (a < 0) {
continue;
}
}
dfilter.shader.data.angle.value [0] = a;
output2.applyFilter (output, output.rect, output2.rect.topLeft, dfilter);
h = output2.histogram (r);
h_max = copyToLinearArray (h, h_linear);
// find local maxima (and draw them)
j = findLocalMaxima (h_linear, 0.5 * h_max, h_indices, kslider2.value);
for (k = 0; k < j; k++) {
i = h_indices [k];
g.graphics.lineStyle (0, [65536, 256, 1][i >> 8] * (i % 256));
if (mainAngle.selected) {
g.graphics.moveTo (200 + i / 4, 470);
g.graphics.lineTo (200 + i / 4, 470 - 100 * h_linear [i] / h_max);
} else {
g.graphics.moveTo (200 + i / 4, 470 - 10 * m);
g.graphics.lineTo (200 + i / 4, 470 - 10 * m - 10 * h_linear [i] / h_max);
}
// draw lines: Ax + By + C = 0, y = - (Ax + C) / B (also scale up by 2)
var A:Number = - Math.cos (+a);
var B:Number = - Math.sin (+a);
var C:Number = i - 384;
lines.graphics.moveTo (0, -2 * C / B);
lines.graphics.lineTo (2 * 160, -2 * (A * 160 + C) / B);
}
if (mainAngle.selected) {
info2.text = j + " local maxima (distance)";
break;
}
}
g.graphics.moveTo (200, 470);
for (i = 0; i < 3; i++) {
g.graphics.lineStyle (0, [0xFF0000, 0xFF00, 0xFF][i]);
g.graphics.lineTo (200 + (768 / 12) * (i + 1), 470);
}
}
/**/
}
public function copyToLinearArray3 (h_in:Vector.<Vector.<Number>>, h_out:Vector.<Number>):Number {
var h_max:Number = 0;
h_out [0] = 0;
for (var i:int = 1; i < 256; i++) {
var c:Number = h_in [0][i] + h_in [1][i] + h_in [2][i];
if (c > h_max) h_max = c;
h_out [i] = c;
}
return h_max;
}
public function copyToLinearArray (h_in:Vector.<Vector.<Number>>, h_out:Vector.<Number>):Number {
var h_max:Number = 0;
for (var i:int = 0; i < 256 * 3; i++) {
if (i % 256 == 0) continue;
var c:Number = h_in [i >> 8] [i % 256];
if (c > h_max) h_max = c;
h_out [i] = c;
}
for (i = 0; i < 3; i++) {
h_out [256 * i] = 0.5 * (
h_out [(256 * i - 1 + 768) % 768] +
h_out [(256 * i + 1 + 768) % 768]
);
}
return h_max;
}
public function findLocalMaxima (input:Vector.<Number>, threshold:Number, output:Vector.<int>, K:int):int {
var L:int = input.length, j:int = 0;
var n:int = input.length / output.length;
search: {
for (var p:int = 0; p < output.length; p++) {
for (var q:int = 0; q < n; q++) {
var i:int = n * p + q;
if (i < L) {
var i_value:Number = input [i];
if (i_value > threshold) {
var i_ismax:Boolean = true;
for (var k:int = -K; k < K; k++) {
if (k < 0) {
if (input [(i + L + k) % L] > i_value) {
i_ismax = false; break;
}
} else if (k > 0) {
if (input [(i + L + k) % L] >= i_value) {
i_ismax = false; break;
}
}
}
if (i_ismax) {
// dijkstra would hate me :(
output [j] = i; j++; if (j >= output.length) break search;
}
}
}
}
}
}
for (k = j; k < output.length; k++) {
output [k] = -1;
}
return j;
}
public function onTSlider (e:Event):void {
sfilter.shader.data.threshold.value [0] = HSlider (e.target).value;
}
public function onTSlider2 (e:Event):void {
dfilter.shader.data.threshold.value [0] = HSlider (e.target).value;
}
public function onBSlider (e:Event):void {
bfilter.blurX = bfilter.blurY = HSlider (e.target).value;
}
/**/
/*
public function onButtonClicked (e:MouseEvent):void {
file.browse ([new FileFilter ("Images", "*.jpe;*.jpeg;*.jpg;*.gif;*.png")]);
}
public function onFileSelected (e:Event):void { file.load (); }
public function onFileLoaded (e:Event):void {
loader = new Loader;
loader.contentLoaderInfo.addEventListener (Event.COMPLETE, onImageReady);
loader.loadBytes (file.data);
}
public function onImageReady(e:Event):void {
if (loader.content) {
loader.contentLoaderInfo.removeEventListener (Event.COMPLETE, onImageReady);
resized.draw (loader.content,
new Matrix (
-320 / loader.content.width, 0, 0,
+240 / loader.content.height, 320
), null, null, null, true
);
source = resized;
if (timeout != 0) clearTimeout (timeout);
timeout = setTimeout (backToWebcamFeed, 15000);
}
}
public function backToWebcamFeed ():void {
resized.fillRect (resized.rect, 0); source = video;
}
/**/
}
import flash.display.Stage;
class Wheel extends Shape
{
public function Wheel(s:Stage)
{
graphics.lineStyle(3,0,0.5);
graphics.drawCircle(0,0,10);
graphics.moveTo(0,-10);
graphics.lineTo(0,10);
scaleX = 7; scaleY = 7;
x = s.stageWidth/2; y = s.stageHeight - 20;
//visible = false;
}
}
// base64 code by 2ndyofyyx,
// http://wonderfl.kayac.com/code/b3a19884080f5ed34137e52e7c3032f3510ef861
import flash.utils.ByteArray;
class Base64 extends ByteArray {
private static const BASE64:Array = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,62,0,0,0,63,52,53,54,55,56,57,58,59,60,61,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,0,0,0,0,0,0,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,0,0,0,0,0];
public function Base64(str:String) {
var n:int, j:int;
for (var i:int = 0; i < str.length && str.charAt(i) != "="; i++) {
if (str.charCodeAt(i) < 32) continue;
j = (j << 6) | BASE64[str.charCodeAt(i)];
n += 6;
while(n >= 8) {
writeByte((j >> (n -= 8)) & 0xFF);
}
}
position = 0;
}
}
// http://www.motobit.com/util/base64-decoder-encoder.asp
class SlopeEstimator3 {
public static var pbj:XML = <pbj>pQEAAACkDwBTbG9wZUVzdGltYXRvcjOgDG5hbWVzcGFjZQBleHBlcmltZW50YWwAoAx2ZW5kb3IA
bWFrYwCgCHZlcnNpb24AAQCgDGRlc2NyaXB0aW9uAHNsb3BlIGVzdGltYXRvcgChAQIAAAxfT3V0
Q29vcmQAoQEBAAACdGhyZXNob2xkAKIBbWluVmFsdWUAAAAAAKIBbWF4VmFsdWUAQRAAAKIBZGVm
YXVsdFZhbHVlAD6ZmZqjAARzcmMAoQIEAQAPZHN0AB0CAMEAABAAMgMAgAAAAAAyAwBAAAAAADID
ACAAAAAAMgMAED+AAAAyAAAQP4AAAB0EAIACAAAAAQQAgAAAwAAdAgAgBAAAADIAABA/gAAAHQQA
gAIAQAACBACAAADAAB0CABAEAAAAMAQA8QIAsAAdBQDzBAAbADIAABA/gAAAHQQAgAIAAAABBACA
AADAAB0CACAEAAAAMgAAED+AAAAdBACAAgBAAAEEAIAAAMAAHQIAEAQAAAAwBADxAgCwAB0GAPME
ABsAMgAAED+AAAAdBACAAgAAAAIEAIAAAMAAHQIAIAQAAAAyAAAQP4AAAB0EAIACAEAAAQQAgAAA
wAAdAgAQBAAAADAEAPECALAAHQcA8wQAGwAyAAAQP4AAAB0EAIACAAAAAgQAgAAAwAAdAgAgBAAA
ADIAABA/gAAAHQQAgAIAQAACBACAAADAAB0CABAEAAAAMAQA8QIAsAAdCADzBAAbADIAABA/gAAA
HQQAgAIAAAABBACAAADAAB0CACAEAAAAHQIAEAIAQAAwBADxAgCwADIAABA/gAAAHQkAgAIAAAAC
CQCAAADAAB0CACAJAAAAHQIAEAIAQAAwCQDxAgCwAB0KAPMEABsAAgoA8wkAGwAyAAAQPo6rNh0E
APMFABsAAQQA8wYAGwAdCQDzBAAbAAIJAPMIABsAHQQA8wkAGwACBADzBwAbAB0JAPMAAP8AAwkA
8wQAGwAdBADzCgAbAAEEAPMJABsAHQkA8wQAGwAdAgAgAgAAADIAABA/gAAAHQQAgAIAQAABBACA
AADAAB0CABAEAAAAMAQA8QIAsAAdAgAgAgAAADIAABA/gAAAHQoAgAIAQAACCgCAAADAAB0CABAK
AAAAMAoA8QIAsAAdCwDzBAAbAAILAPMKABsAMgAAED6OqzYdBADzBgAbAAEEAPMHABsAHQoA8wQA
GwACCgDzBQAbAB0EAPMKABsAAgQA8wgAGwAdCgDzAAD/AAMKAPMEABsAHQQA8wsAGwABBADzCgAb
AB0KAPMEABsAHQAAEAkAAAABAAAQCQBAAB0EAIAAAMAAAQQAgAkAgAAdAgAgBAAAAB0AABAKAAAA
AQAAEAoAQAAdBACAAADAAAEEAIAKAIAAHQIAEAQAAAAdBADBAgCwACQAABEEABAAKgAAIAAAwAAd
AYCAAIAAADQAAAABgAAAMgAAED6i+YMdAgAgBABAAAYCACAEAAAAHQIAEAAAwAADAgAQAgCAAB0A
ABACAMAAMgIAIAAAAAArAAAQAgCAAB0BgEAAgAAANAAAAAGAQAAyAgAgP4AAAAEAABACAIAANgAA
AAAAAAAdAwCAAADAADICACA7gAAAHQIAEAAAwAACAgAQAgCAAB0DAEACAMAAMgIAIDuAAAAdAgAQ
AADAAAECABACAIAAHQMAIAIAwAA2AAAAAAAAAB0BAPMDABsA</pbj>;
}
class DistanceEstimator3 {
public static var pbj:XML = <pbj>pQEAAACkEgBEaXN0YW5jZUVzdGltYXRvcjOgDG5hbWVzcGFjZQBleHBlcmltZW50YWwAoAx2ZW5k
b3IAbWFrYwCgCHZlcnNpb24AAQCgDGRlc2NyaXB0aW9uAGRpc3RhbmNlIGVzdGltYXRvcgChAQIA
AAxfT3V0Q29vcmQAoQEBAAACYW5nbGUAogFtaW5WYWx1ZQAAAAAAogFtYXhWYWx1ZQBASQ/bogFk
ZWZhdWx0VmFsdWUAP4AAAKEBAQAAAXRocmVzaG9sZACiAW1pblZhbHVlADqDEm+iAW1heFZhbHVl
AD3MzM2iAWRlZmF1bHRWYWx1ZQA8I9cKowAEc3JjAKECBAEAD2RzdAAdAgDBAAAQADADAPECABAA
HQQA8wMAGwAyAgAgAAAAACoCACAEAAAAHQGAgACAAAA0AAAAAYAAADICACBASQ/bHQIAEAIAgAAD
AgAQBAAAAB0CACACAMAAHQIAEAIAgAACAgAQAACAABgDAIACAMAAKgMAgAAAwAAdAYBAAIAAADQA
AAABgEAADQIAEAIAgAAdAwCAAgDAAAMDAIACAAAADAIAEAIAgAAdAwBAAgDAAAMDAEACAEAAHQIA
EAMAAAABAgAQAwBAAB0DAIACAMAAMgIAEEPAAAABAwCAAgDAADICABA7gAAAAwMAgAIAwAAyAgAQ
P4AAACsDAIACAMAAHQGAIACAAAA0AAAAAYCAAB0EAIADAAAAMgQAQAAAAAAyBAAgAAAAADUAAAAA
AAAAMgIAEEAAAAArAwCAAgDAAB0BgBAAgAAANAAAAAGAwAAyBACAAAAAADICABA/gAAAHQMAQAMA
AAACAwBAAgDAAB0EAEADAEAAMgQAIAAAAAA1AAAAAAAAADIEAIAAAAAAMgQAQAAAAAAyAgAQQAAA
AB0DAEADAAAAAgMAQAIAwAAdBAAgAwBAADYAAAAAAAAANgAAAAAAAAA1AAAAAAAAADIEAIAAAAAA
MgQAQAAAAAAyBAAgAAAAADYAAAAAAAAANgAAAAAAAAAdAQDzBAAbAA==</pbj>;
}