TINYRACEGAME(的な疑似3D)道なりにスクロール
アウトランとかファイナルラップとかの疑似3D的な
* スペースキーで進みます(離すと止まる)
* っていうかここまでやったらちゃんとゲームにしろよと
* もうちょっとタイニーな見た目にしたかったのに中途半端。
* ドット感ある感じにしたいです。
* 参考:
* http://hakuhin.jp/as/raster_efc.html#RASTER_EFC_04
* 変更:
* 道路を沿うように左右にスクロール
/**
* Copyright fumix ( http://wonderfl.net/user/fumix )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/po6L
*/
// forked from fumix's TINYRACEGAME(的な疑似3D)
/**
* アウトランとかファイナルラップとかの疑似3D的な
* スペースキーで進みます(離すと止まる)
* っていうかここまでやったらちゃんとゲームにしろよと
* もうちょっとタイニーな見た目にしたかったのに中途半端。
* ドット感ある感じにしたいです。
* 参考:
* http://hakuhin.jp/as/raster_efc.html#RASTER_EFC_04
* 変更:
* 道路を沿うように左右にスクロール
**/
package {
import flash.ui.Keyboard;
import flash.events.KeyboardEvent;
import net.hires.debug.Stats;
import flash.geom.Rectangle;
import flash.display.Graphics;
import flash.events.Event;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
/**
* @author fumix
*/
[SWF(backgroundColor="#FFFFFF", frameRate="31", width="465", height="465")]
public class Road extends Sprite {
//----------------------------------------
//CLASS CONSTANTS
private const SCREEN_WIDTH : int = 465;
private const SCREEN_HEIGHT : int = 465;
private const ANGLE : Number = 60;//1 ~ 180 くらいまでの好きな値; // 視野角
private const FOV : Number = 1 / Math.tan(ANGLE * 0.5 * Math.PI / 180); // 視点からの距離
private const WIDTH : Number = 465 * 0.5;//解像度の幅か高さの大きい方の数値 * 0.5; //
private const HEIGHT : Number = WIDTH * 1.0; // アスペクト比
//----------------------------------------
//VARIABLES
private var buffer : BitmapData;
private var roadObjectArray : Array;
private var _first : RoadObject;
private var roadSprite : Sprite;
private var roadSpriteArray : Array;
private var _firstSp : RoadObject;
private var _acceleration : Number;
private var _velocity : Number;
private var _direction : Number;
private var _keyDownFlag : Boolean;
/**
* コンストラクタ
*/
public function Road() {
//描画用bitmapdata準備
buffer = new BitmapData(SCREEN_WIDTH, SCREEN_HEIGHT, false, 0x0099FF);
addChild(new Bitmap(buffer));
//道路描画用
roadSprite = new Sprite();
//パフォーマンスチェック用
var stats : Stats = addChild(new Stats()) as Stats;
stats.x = stage.stageWidth - 70;
//初期化処理
initialize();
//エンターフレーム処理
addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
//キーイベント
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUpHandler);
}
/**
* 初期化
*/
private function initialize() : void {
var old : RoadObject,
i : int,
j : int = 0,
id : int = 0,
ro : RoadObject;
//キーフラグ
_keyDownFlag = false;
//加速度
_acceleration = 0.1;
//速度
_velocity = 0.0;
//方向
_direction = 0.0;
//グランド部分
roadObjectArray = new Array();
for (i = 40;i >= 1;i -= 2) {
ro = new RoadObject(id, 0, 0.5, i);
id++;
//リンクリスト
if (_first == null) {
old = _first = ro;
} else {
old.next = ro;
old = ro;
}
roadObjectArray.push(ro);
}
//道部分
id = 0;
roadSpriteArray = new Array();
for (i = 40;i >= 1;i -= 1) {
var dx : Number = 4.0 * Math.sin(2 * Math.PI * (id / 40));
if(id % 2 == 0) {
ro = new RoadObject(id, dx, 0.6, i, 2, 0xFF3333);
} else {
ro = new RoadObject(id, dx, 0.6, i, 2, 0xFFAAAA);
}
id++;
//リンクリスト
if (_firstSp == null) {
old = _firstSp = ro;
} else {
old.next = ro;
old = ro;
}
roadSpriteArray.push(ro);
}
}
/**
* キーイベント
*/
private function onKeyDownHandler(event : KeyboardEvent) : void {
if(event.keyCode == Keyboard.SPACE) {
_keyDownFlag = true;
}
}
/**
* キーイベント
*/
private function onKeyUpHandler(event : KeyboardEvent) : void {
if(event.keyCode == Keyboard.SPACE) {
_keyDownFlag = false;
}
}
private function onEnterFrameHandler(event : Event) : void {
interaction();
update();
}
/**
* インタラクション
*/
private function interaction() : void {
var ro : RoadObject = _first;
//速度
if(_keyDownFlag && _velocity < 0.7) {
_velocity += 0.007;
if(_velocity > 0.7) _velocity = 0.7;
}
if(!_keyDownFlag && _velocity > 0) {
_velocity -= 0.01;
if(_velocity < 0) _velocity = 0;
}
//グランド部分のZ軸アップデート
do {
ro.z -= _velocity;
if(ro.z < 1) ro.z += 40;
}
while (ro = ro.next);
//道部分のZ軸アップデート
ro = _firstSp;
do {
ro.z -= _velocity;
if(ro.z < 1 && ro.z >= 0) {
//trace(ro.id);
//方向の更新
var before : RoadObject;
if(ro.id - 1 < 0) {
before = roadSpriteArray[roadSpriteArray.length - 1];
} else {
before = roadSpriteArray[ro.id - 1];
}
_direction = -(ro.x + (before.x - ro.x) * (1.0 - ro.z));
}
if(ro.z < 0) {
ro.z += 40;
}
}
while (ro = ro.next);
//trace("------");
}
/**
* アップデート(描画処理)
*/
private function update() : void {
var offset : Number = 220;
var ro : RoadObject = _first;
//描画
buffer.lock();
//画面リセット
buffer.fillRect(buffer.rect, 0x0099FF);
//グランド部分の描画
do {
var h0 : Number = (ro.y + _velocity * 0.4) / ro.z * FOV * HEIGHT;
var h1 : Number = (ro.y + _velocity * 0.4) / (ro.z + 1.2) * FOV * HEIGHT;
var r : Rectangle = new Rectangle(0, h0 + offset, SCREEN_WIDTH, h0 - h1);
if(h0 - h1 >= 1) buffer.fillRect(r, 0x0066FF);
}
while (ro = ro.next);
//道部分の描画
ro = _firstSp;
roadSprite.graphics.clear();
do {
if(ro.next != null) {
var next : RoadObject = ro.next;
} else {
var next : RoadObject = _firstSp;
}
//スクリーン上のx座標 = 3次元のx座標 / 3次元のz座標 * fov * width;
//スクリーン上のy座標 = 3次元のy座標 / 3次元のz座標 * fov * height;
var y0 : Number = (ro.y + _velocity * 0.4) / ro.z * FOV * HEIGHT + offset + 8;
var x00 : Number = (ro.x - ro.width / 2 + _direction) / ro.z * FOV * WIDTH + SCREEN_WIDTH / 2;
var x01 : Number = (ro.x + ro.width / 2 + _direction) / ro.z * FOV * WIDTH + SCREEN_WIDTH / 2;
var y1 : Number = (next.y + _velocity * 0.4) / next.z * FOV * HEIGHT + offset + 8;
var x10 : Number = (next.x - next.width / 2 + _direction) / next.z * FOV * WIDTH + SCREEN_WIDTH / 2;
var x11 : Number = (next.x + next.width / 2 + _direction) / next.z * FOV * WIDTH + SCREEN_WIDTH / 2;
var x20 : Number = (ro.x - ro.width / 2 - 0.1 + _direction) / ro.z * FOV * WIDTH + SCREEN_WIDTH / 2;
var x21 : Number = (ro.x + ro.width / 2 + 0.1 + _direction) / ro.z * FOV * WIDTH + SCREEN_WIDTH / 2;
var x30 : Number = (next.x - next.width / 2 - 0.1 + _direction) / next.z * FOV * WIDTH + SCREEN_WIDTH / 2;
var x31 : Number = (next.x + next.width / 2 + 0.1 + _direction) / next.z * FOV * WIDTH + SCREEN_WIDTH / 2;
if(y1 >= y0 && y0 < 465) {
roadSprite.graphics.beginFill(ro.color);
roadSprite.graphics.moveTo(x20, y0);
roadSprite.graphics.lineTo(x21, y0);
roadSprite.graphics.lineTo(x31, y1);
roadSprite.graphics.lineTo(x30, y1);
roadSprite.graphics.lineTo(x20, y0);
roadSprite.graphics.endFill();
roadSprite.graphics.beginFill(0xCCCCCC);
roadSprite.graphics.moveTo(x00, y0);
roadSprite.graphics.lineTo(x01, y0);
roadSprite.graphics.lineTo(x11, y1);
roadSprite.graphics.lineTo(x10, y1);
roadSprite.graphics.lineTo(x00, y0);
roadSprite.graphics.endFill();
}
}
while (ro = ro.next);
buffer.draw(roadSprite);
buffer.unlock();
}
}
}
class RoadObject {
public var x : Number;
public var y : Number;
public var z : Number;
public var width : Number;
public var next : RoadObject;
public var id : int;
public var color:uint;
public function RoadObject(id : int,x : Number = 0,y : Number = 0,z : Number = 0,width : Number = 0,color:uint = 0xFFFFFF) {
this.id = id;
this.x = x;
this.y = y;
this.z = z;
this.width = width;
this.color = color;
}
}