Lock&Roll
画面をロックして逆側に移動できるアクションゲーム
操作方法
・十字キー
・移動&ジャンプ
・SPACE
・ロック&アンロック
・画面をロックすると、端から出たときにもう片方の端から出てきます
/**
* Copyright o_healer ( http://wonderfl.net/user/o_healer )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/xq5y
*/
/*
「Lock&Roll」
・画面をロックして逆側に移動できるアクションゲーム
操作方法
・十字キー
・移動&ジャンプ
・SPACE
・ロック&アンロック
・画面をロックすると、端から出たときにもう片方の端から出てきます
その他
・「プレイヤーが押せるブロック」があると幅が広がりそう
・ロックで別のところから持ってくる、とか
・ロック状態で落下させて上から降ってくる、とか
*/
package {
import flash.display.*;
import flash.events.*;
import flash.filters.*;
import flash.geom.*;
import flash.net.*;
import flash.system.*;
import flash.text.*;
[SWF(width="465", height="465", frameRate="30", backgroundColor="0x000000")]
public class GameMain extends Sprite {
//==Const==
//*
static public const URL_BLOCKS:String = "http://assets.wonderfl.net/images/related_images/e/e4/e466/e4667aa771860a2002c45728da23c52285814e86";
static public const URL_PLAYER:String = "http://assets.wonderfl.net/images/related_images/9/93/9300/9300948516d99cd5853f485210378622249f0d7a";
/*/
static public const URL_BLOCKS:String = "Blocks.png";
static public const URL_PLAYER:String = "Player.png";
//*/
//マップ
static public var m_MapIter:int = 0;
static public const O:int = m_MapIter++;//空白
static public const W:int = m_MapIter++;//壁
static public const X:int = m_MapIter++;//トゲ(未対応)
static public const P:int = m_MapIter++;//プレイヤー
static public const G:int = m_MapIter++;//ゴール
static public const MAP:Array = [
[W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,O,O,O,O,O,O,O,O,O,O,W],
[W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,O,O,O,O,O,O,O,O,O,O,W],
[W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,O,O,O,O,O,O,O,O,O,O,W],
[W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,O,O,O,O,O,O,O,O,O,O,W],
[W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,O,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,O,O,O,O,O,O,O,O,O,O,W],
[W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,O,O,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,G,O,O,O,O,O,O,O,O,O,W],
[W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,O,O,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,O,O,O,O,O,W],
[W,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,W,O,O,O,O,O,O,O,O,W,W,W,O,O,O,O,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,W,O,O,O,O,O,W],
[W,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,W,O,O,O,O,O,O,O,O,O,W,W,W,W,W,W,O,O,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,O,O,O,O,O,W],
[W,O,P,O,O,O,O,O,O,O,O,O,O,O,O,O,W,O,O,O,O,O,O,O,O,O,O,W,W,W,W,W,W,W,W,W,W,O,O,O,O,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,O,O,O,O,O,W],
[W,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,W,O,O,O,O,O,O,O,O,O,O,O,W,W,W,W,O,O,W,W,W,W,W,W,W,W,W,O,O,O,O,O,O,O,W,W,W,W,W,W,W,W,O,O,O,O,O,O,O,W],
[W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,O,O,O,W,W,W,W,W,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,O,O,O,O,W,W],
[W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,O,O,W,W,W,W,W,W,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,O,O,W,O,O,W],
[W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,O,W,W,W,W,W,W,W,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,W,O,O,O,O,W],
[W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,O,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,O,O,O,O,W,W,W,W,W,W,W,O,O,O,O,O,O,W],
];
//1マスの大きさ
static public const PANEL_LEN:int = 32;
//マップのサイズ
static public const MAP_NUM_X:int = MAP[0].length;
static public const MAP_NUM_Y:int = MAP.length;
//マップの大きさ
static public const MAP_W:int = PANEL_LEN * MAP_NUM_X;
static public const MAP_H:int = PANEL_LEN * MAP_NUM_Y;
//モード
static public var ModeIter:int = 0;
static public const MODE_MAIN:int = ModeIter++;
static public const MODE_GOAL:int = ModeIter++;
static public const MODE_GAME_OVER:int = ModeIter++;
//==Var==
//Pseudo Singleton
static public var Instance:GameMain;
//レイヤー
public var m_Layer_Root:Sprite = new Sprite();
public var m_Layer_BG:Sprite = new Sprite();
public var m_Layer_Player:Sprite = new Sprite();
//画像
public var m_BitmapData_BG:BitmapData = new BitmapData(MAP_W, MAP_H, false, 0x000000);
//プレイヤー
public var m_Player:Player = new Player();
//ゴール
public var m_Goal:Goal;
//ロックフラグ
public var m_IsLock:Boolean = false;
//ロックされた画面の範囲
public var m_LockRange:Rectangle = new Rectangle(0,0, 465,465);
//テキスト
public var m_Text:TextField = new TextField();
//モード
public var m_Mode:int = MODE_MAIN;
//==Function==
//Init
public function GameMain():void {
//Pseudo Singleton
{
Instance = this;
}
//Layer
{
//Root
addChild(m_Layer_Root);
{
//背景
m_Layer_Root.addChild(m_Layer_BG);
//プレイヤー
m_Layer_Root.addChild(m_Layer_Player);
}
}
//背景
{
m_Layer_BG.addChild(new Bitmap(m_BitmapData_BG));
}
//プレイヤー
{
m_Layer_Player.addChild(m_Player);
}
//Goal
{
m_Goal = new Goal();
m_Layer_BG.addChild(m_Goal);
}
//MAPに応じた処理
{
var rect:Rectangle = new Rectangle(0,0, PANEL_LEN,PANEL_LEN);
for(var y:int = 0; y < MAP_NUM_Y; y++){
rect.y = y * PANEL_LEN;
for(var x:int = 0; x < MAP_NUM_X; x++){
rect.x = x * PANEL_LEN;
switch(MAP[y][x]){
case W:
//ロード前用の仮描画
m_BitmapData_BG.fillRect(rect, 0xFF444444);
break;
case P:
//プレイヤーの位置指定
m_Player.SetPos(
(x+0.5) * PANEL_LEN,
(y+0.5) * PANEL_LEN
);
break;
case G:
//ゴールの位置指定
m_Goal.SetPos(
(x+0.5) * PANEL_LEN,
(y+0.5) * PANEL_LEN
);
break;
}
}
}
}
//Text
{
m_Text.selectable = false;
m_Text.autoSize = TextFieldAutoSize.LEFT;
m_Text.defaultTextFormat = new TextFormat('Verdana', 60, 0xFFFF00, true);
m_Text.text = '';
m_Text.filters = [new GlowFilter(0xFF0000)];
addChild(m_Text);
}
//Update
{
addEventListener(Event.ENTER_FRAME, Update);
}
//画像ロード開始
{
const LoadFunc:Function = function(in_URL:String, in_OnLoad:Function):void{
var loader:Loader = new Loader();
loader.load(new URLRequest(in_URL), new LoaderContext(true));//画像のロードを開始して
loader.contentLoaderInfo.addEventListener(
Event.COMPLETE,//ロードが完了したら
function(e:Event):void{
in_OnLoad(loader.content);//初期化に入る
}
);
}
LoadFunc(URL_BLOCKS, OnLoadEnd_Blocks);
LoadFunc(URL_PLAYER, OnLoadEnd_Player);
}
}
public function OnLoadEnd_Blocks(in_Graphic:DisplayObject):void{
//Init ImageManager
{
ImageManager.Init(in_Graphic);//それを保持した後
}
//ブロック描画
{
ImageManager.DrawBlocks(MAP, m_BitmapData_BG);
}
}
public function OnLoadEnd_Player(in_Graphic:DisplayObject):void{
//プレイヤー
{
var mtx:Matrix = new Matrix(1,0,0,1, 0,0);
for(var i:int = 0; i < Player.GRAPHIC_NUM; i++){
var bmd:BitmapData = m_Player.m_BitmapDataList[i];
//Clear
bmd.fillRect(bmd.rect, 0x00000000);
//Draw
mtx.tx = -i*24;
mtx.ty = -PANEL_LEN;
bmd.draw(in_Graphic, mtx);
}
}
}
//Update
public function Update(e:Event=null):void{
var DeltaTime:Number = 1.0 / stage.frameRate;
//Player
{
m_Player.Update(DeltaTime);
}
//Goal
{
m_Goal.Update();
}
//Camera
{
Update_Camera();
}
}
//Update : Camera
public function Update_Camera():void{
//画面ロック中はカメラ位置を移動しない
if(m_IsLock){return;}
var CAMERA_W:int = stage.stageWidth;
var CAMERA_H:int = stage.stageHeight;
var PlayerX:int = m_Player.x;
var PlayerY:int = m_Player.y;
var CameraLX:int = PlayerX - CAMERA_W*0.5;
var CameraUY:int = PlayerY - CAMERA_H*0.5;
var RootX:int;
{
RootX = -CameraLX;
if(RootX < -MAP_W + CAMERA_W){
RootX = -MAP_W + CAMERA_W;
}
if(RootX > 0){
RootX = 0;
}
}
var RootY:int;
{
RootY = -CameraUY;
if(RootY < -MAP_H + CAMERA_H){
RootY = -MAP_H + CAMERA_H;
}
if(RootY > 0){
RootY = 0;
}
}
/*
m_Layer_Root.x = RootX;
m_Layer_Root.y = RootY;
/*/
var ratio:Number = 0.2;//ロック解除時にすぐに移動するとわかりにくいので、補間してみる
m_Layer_Root.x = Lerp(m_Layer_Root.x, RootX, ratio);
m_Layer_Root.y = Lerp(m_Layer_Root.y, RootY, ratio);
//*/
m_LockRange.x = -m_Layer_Root.x;
m_LockRange.y = -m_Layer_Root.y;
}
//Goal
public function OnGoal():void{
//Mode
{
m_Mode = MODE_GOAL;
}
//Text
{
//Text
m_Text.text = 'Clear';
//Centering
m_Text.x = (stage.stageWidth - m_Text.width) / 2;
m_Text.y = (stage.stageHeight - m_Text.height) / 2;
}
}
//Game Over : Damage
public function OnDead_Damage():void{
//Mode
{
m_Mode = MODE_GAME_OVER;
}
//Text
{
//Text
m_Text.text = 'Game Over';
//Centering
m_Text.x = (stage.stageWidth - m_Text.width) / 2;
m_Text.y = (stage.stageHeight - m_Text.height) / 2;
}
}
//Game Over : Fall
public function OnDead_Fall():void{
//Mode
{
m_Mode = MODE_GAME_OVER;
}
//Text
{
//Text
m_Text.text = 'Game Over';
//Centering
m_Text.x = (stage.stageWidth - m_Text.width) / 2;
m_Text.y = (stage.stageHeight - m_Text.height) / 2;
}
}
//#IsGameOver
public function IsEnd():Boolean{
return (m_Mode != MODE_MAIN);
}
//Lock <=> Unlock
public function FlipLock():void{
m_IsLock = !m_IsLock;
}
//IsLock
public function IsLock():Boolean{
return m_IsLock;
}
//Utility
public function Lerp(in_Src:Number, in_Dst:Number, in_Ratio:Number):Number{
return (in_Src * (1 - in_Ratio)) + (in_Dst * in_Ratio);
}
}
}
import flash.display.*;
import flash.events.*;
import flash.filters.*;
import flash.geom.*;
import flash.net.*;
import flash.system.*;
import flash.ui.*;
//#Player
class Player extends Sprite
{
//==Const==
//移動速度
static public const VEL_X:Number = 100.0;
//ジャンプ速度
static public const JUMP_VEL:Number = 290.0;
//重力
static public const GRAVITY:Number = 500.0;
//最高下降速度(ロックによって無限落下が可能なので、速度制限してみる)
static public const FALL_VEL_MIN:Number = 1000.0;
//アニメーション用パラメータ
static public const ANIM_CYCLE:Number = 1.0;
static public const ANIM_ITER:Array = [0,1,2,1];
static public const ANIM_NUM:int = ANIM_ITER.length;
//用意されたグラフィックの数
static public const GRAPHIC_NUM:int = 3;
//==Var==
//移動まわりのパラメータ
public var m_Pos:Point = new Point(0,0);
public var m_Vel:Point = new Point(0,0);
//入力
public var m_InputL:Boolean = false;
public var m_InputR:Boolean = false;
public var m_InputU:Boolean = false;
public var m_InputLock:Boolean = false;
//表示画像
public var m_Bitmap:Bitmap = new Bitmap();//これの中身を差し替えることでアニメーションさせる
//アニメーション用タイマー
public var m_AnimTimer:Number = 0.0;
//アニメーション用画像リスト
public var m_BitmapDataList:Array = new Array(GRAPHIC_NUM);
//接地フラグ
public var m_GroundFlag:Boolean = false;
//死亡フラグ
public var m_IsDead:Boolean = false;
//==Function==
//Init
public function Player(){
//Input
{
addEventListener(
Event.ADDED_TO_STAGE,//ステージに追加されたら
function(e:Event):void{
//キー入力を見る
stage.addEventListener(KeyboardEvent.KEY_DOWN, OnKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, OnKeyUp);
}
);
}
//プレイヤーグラフィックの仮画像
{
var shape:Shape = new Shape();
var g:Graphics = shape.graphics;
g.lineStyle(0,0,0);
g.beginFill(0x000088, 1.0);
g.drawCircle(GameMain.PANEL_LEN/2, GameMain.PANEL_LEN/2, GameMain.PANEL_LEN/4);
g.endFill();
for(var i:int = 0; i < GRAPHIC_NUM; i++){
m_BitmapDataList[i] = new BitmapData(24, GameMain.PANEL_LEN, true, 0x00000000);
m_BitmapDataList[i].draw(shape);
}
}
//表示画像の登録
{
m_Bitmap.x = -24/2;
m_Bitmap.y = -GameMain.PANEL_LEN/2;
addChild(m_Bitmap);
}
}
//Init : Pos
public function SetPos(in_X:int, in_Y:int):void{
this.x = m_Pos.x = in_X;
this.y = m_Pos.y = in_Y;
}
//Update : Input
private function OnKeyDown(event:KeyboardEvent):void{
if(event.keyCode == Keyboard.LEFT){ m_InputL = true;}
if(event.keyCode == Keyboard.RIGHT){m_InputR = true;}
if(event.keyCode == Keyboard.UP){ m_InputU = true;}
if(!m_InputLock){
if(event.keyCode == Keyboard.SPACE){
m_InputLock = true;
//ロック開始
//・ただし、プレイヤーが画面外に居る時に限る
//範囲チェック
if(this.x < 0){return;}
if(this.x >= GameMain.MAP_W){return;}
if(this.y < 0){return;}
if(this.y >= GameMain.MAP_H){return;}
//ロック
GameMain.Instance.FlipLock();
}
}
}
private function OnKeyUp(event:KeyboardEvent):void{
if(event.keyCode == Keyboard.LEFT){ m_InputL = false;}
if(event.keyCode == Keyboard.RIGHT){m_InputR = false;}
if(event.keyCode == Keyboard.UP){ m_InputU = false;}
if(event.keyCode == Keyboard.SPACE){m_InputLock = false;}
}
//Update
public function Update(in_DeltaTime:Number):void{
//死亡・ゴール時は何もしない
if(GameMain.Instance.IsEnd()){
return;
}
//移動
Update_Move(in_DeltaTime);
//アニメーション
Update_Anim(in_DeltaTime);
//死亡チェック
Check_Dead();
}
//Update : Anim
public function Update_Anim(in_DeltaTime:Number):void{
//m_AnimTimer
{
m_AnimTimer += in_DeltaTime;
if(m_AnimTimer > ANIM_CYCLE){m_AnimTimer -= ANIM_CYCLE;}
}
//m_AnimTimer => iter
var iter:int;
{
iter = ANIM_ITER[int(ANIM_NUM * m_AnimTimer/ANIM_CYCLE)];
}
m_Bitmap.bitmapData = m_BitmapDataList[iter];
}
//Check : Dead
public function Check_Dead():void{
//Check
{
if(m_IsDead){
return;
}
}
//マップより下に行っていたら落下死する
if(this.y > GameMain.MAP_H+GameMain.PANEL_LEN){
//ゲームオーバー処理
{
GameMain.Instance.OnDead_Fall();
}
//フラグ
{
m_IsDead = true;
}
}
}
//Update : Move
public function Update_Move(in_DeltaTime:Number):void{
//入力
{
//X
{
var TrgVX:Number = 0.0;
if(m_InputR){TrgVX = VEL_X; this.scaleX = 1;}
if(m_InputL){TrgVX = -VEL_X; this.scaleX = -1;}
var ratio:Number = 0.5;
m_Vel.x = Lerp(m_Vel.x, TrgVX, ratio);
}
//Jump
{
if(m_InputU && m_GroundFlag){
m_Vel.y = -JUMP_VEL;
}
}
}
//重力
{
m_Vel.y += GRAVITY * in_DeltaTime;
//速度制限
if(m_Vel.y > FALL_VEL_MIN){
m_Vel.y = FALL_VEL_MIN;
}
}
//目標位置
var DstX:Number;
var DstY:Number;
{
DstX = (m_Pos.x) + (m_Vel.x * in_DeltaTime);
DstY = (m_Pos.y) + (m_Vel.y * in_DeltaTime);
}
//移動を試みる
//・端数制御のためにちょっと特殊なことをしているが、基本的にはただ単にX移動→Y移動してるだけ
//・壁判定まわりはかなりムダが多い(高速化の余地が多い)が、ひとまずこれで
//X移動
{
var TryX:int = m_Pos.x;
if(TryX != int(DstX)){
for(;;){
//++
if(TryX < DstX){
TryX++;
}else{
TryX--;
}
//壁があるならその手前で中断
if(IsWall(TryX, m_Pos.y)){
DstX = m_Pos.x;//壁の手前になるように位置補正(=端数切捨て)
m_Vel.x = 0;
break;
}
//移動できたようなので更新(主に上の位置補正のための記憶用)
m_Pos.x = TryX;
//Dstまで辿りついたら終了
if(TryX == int(DstX)){
break;
}
}
}
m_Pos.x = DstX;
}
//Y移動
{
m_GroundFlag = false;//更新のためリセット
var TryY:int = m_Pos.y;
if(TryY != int(DstY)){
for(;;){
//++
if(TryY < DstY){
TryY++;
}else{
TryY--;
}
//壁があるならその手前で中断
if(IsWall(m_Pos.x, TryY)){
if(DstY > m_Pos.y){m_GroundFlag = true;}
DstY = m_Pos.y;//壁の手前になるように位置補正(=端数切捨て)
m_Vel.y = 0;
break;
}
//移動できたようなので更新(主に上の位置補正のための記憶用)
m_Pos.y = TryY;
//Dstまで辿りついたら終了
if(TryY == int(DstY)){
break;
}
}
}
m_Pos.y = DstY;
}
//ロック中ははみ出たら逆から出るようにする
{
if(GameMain.Instance.IsLock()){
var rect:Rectangle = GameMain.Instance.m_LockRange;
if(m_Pos.x < rect.left){ m_Pos.x += rect.width;}
if(m_Pos.x > rect.right){ m_Pos.x -= rect.width;}
if(m_Pos.y < rect.top){ m_Pos.y += rect.height;}
if(m_Pos.y > rect.bottom){ m_Pos.y -= rect.height;}
}
}
//反映
{
this.x = m_Pos.x;
this.y = m_Pos.y;
}
}
//壁があるかどうか
public function IsWall(in_X:int, in_Y:int):Boolean{
//プレイヤーを中心とする四角形の四隅が壁にめり込まないようにする
//・移動方向によって判定を省略して高速化できるはずだが、対応は保留
//・同じく、Indexが変わらなければ判定をスキップできるはずだが、こちらも保留
//四角形用のオフセット
const OffsetX:int = (GameMain.PANEL_LEN-2)/2;
const OffsetY:int = (GameMain.PANEL_LEN-2)/2;
for(var i:int = 0; i < 4; i++){
var PosX:int = in_X + (((i&1)==0)? OffsetX: -OffsetX);
var PosY:int = in_Y + (((i&2)==0)? OffsetY: -OffsetY);
//画面内チェック
{
//ロック中は画面をはみ出た部分を折りたたむ
if(GameMain.Instance.IsLock()){
var rect:Rectangle = GameMain.Instance.m_LockRange;
if(PosX < rect.left){ PosX += rect.width;}
if(PosX > rect.right){ PosX -= rect.width;}
if(PosY < rect.top){ PosY += rect.height;}
if(PosY > rect.bottom){ PosY -= rect.height;}
}
}
var IndexX:int = PosX / GameMain.PANEL_LEN;
var IndexY:int = PosY / GameMain.PANEL_LEN;
//範囲チェック
{
//画面外は空白とみなす
if(IndexX < 0){continue;}
if(IndexX >= GameMain.MAP_NUM_X){continue;}
if(IndexY < 0){continue;}
if(IndexY >= GameMain.MAP_NUM_Y){continue;}
}
//該当箇所が壁ならtrueを返して終了
switch(GameMain.MAP[IndexY][IndexX]){
case GameMain.W:
return true;
}
}
//四隅に壁が見つからなかったら壁はないと判断
return false;
}
//Utility
public function Lerp(in_Src:Number, in_Dst:Number, in_Ratio:Number):Number{
return (in_Src * (1 - in_Ratio)) + (in_Dst * in_Ratio);
}
}
//#Goal
class Goal extends Sprite
{
//==Constt==
static public const GOAL_RANGE:int = 8;
//==Function==
//Init
public function Goal():void{
//Graphic
{
addChild(ImageManager.CreateGoalGraphic());
}
}
//SetPos
public function SetPos(in_X:int, in_Y:int):void{
this.x = in_X;
this.y = in_Y;
}
//Update
public function Update():void{
//プレイヤーが一定範囲に来たらゴールとする
//そもそもすでにゴールしてたら何も処理しない
{
if(GameMain.Instance.IsEnd()){
return;
}
}
//プレイヤーとの距離が一定以上離れていたら何も処理しない
{
var GapX:Number = GameMain.Instance.m_Player.x - this.x;
var GapY:Number = GameMain.Instance.m_Player.y - this.y;
var Distance:Number = Math.sqrt(GapX*GapX + GapY*GapY);
if(Distance > GOAL_RANGE){
return;
}
}
//上のチェックに全てクリアしたらゴールしたものとして処理する
{
GameMain.Instance.OnGoal();
}
}
}
//#ImageManager
class ImageManager
{
//==Const==
//#Graphic
static public var m_GraphicIndexIter:int = 0;
static public const GRAPHIC_INDEX_BG:int = m_GraphicIndexIter++;
static public const GRAPHIC_INDEX_WALL:int = m_GraphicIndexIter++;
static public const GRAPHIC_INDEX_WALL_X:int = m_GraphicIndexIter++;
static public const GRAPHIC_INDEX_WALL_Y:int = m_GraphicIndexIter++;
static public const GRAPHIC_INDEX_WALL_XorY:int = m_GraphicIndexIter++;
static public const GRAPHIC_INDEX_WALL_XandY:int = m_GraphicIndexIter++;
static public const GRAPHIC_INDEX_NEEDLE:int = m_GraphicIndexIter++;
static public const GRAPHIC_INDEX_NEEDLE_X:int = m_GraphicIndexIter++;
static public const GRAPHIC_INDEX_NEEDLE_Y:int = m_GraphicIndexIter++;
static public const GRAPHIC_INDEX_NEEDLE_XY:int = m_GraphicIndexIter++;
static public const GRAPHIC_INDEX_NUM:int = m_GraphicIndexIter;
//#enum:Quater
static public const LU:int = 0;
static public const RU:int = 1;
static public const LD:int = 2;
static public const RD:int = 3;
//#enum:Pos
static public const POS_X:int = 0;
static public const POS_Y:int = 1;
//#Graphic
static public var m_BitmapData_View:BitmapData;
//#Mapping
static public var GRAPHIC_INDEX_TO_POS:Array;
//#Palette
static public var m_Palette_ForView:Array;
//#Utility
static public const POS_ZERO:Point = new Point(0,0);
//==Function==
//#Init
static public function Init(in_Graphic:DisplayObject):void{
var x:int, y:int, i:int;
//m_BitmapData_View
{
m_BitmapData_View = new BitmapData(256, 256, false, 0x000000);
m_BitmapData_View.draw(in_Graphic);
}
//GRAPHIC_INDEX_TO_POS
{//GRAPHIC_INDEX_~から画像の位置へのマッピング(さらにどの隅での処理かも含む)(そして左から何マス目、上から何マス目、という指定)
GRAPHIC_INDEX_TO_POS = new Array(GRAPHIC_INDEX_NUM);
//[LU][RU][LD][RD]
GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_BG] = [[3,2], [3,2], [3,2], [3,2]];
GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_WALL] = [[1,1], [1,1], [1,1], [1,1]];
GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_WALL_X] = [[0,1], [2,1], [0,1], [2,1]];
GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_WALL_Y] = [[1,0], [1,0], [1,2], [1,2]];
GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_WALL_XorY] = [[0,0], [2,0], [0,2], [2,2]];
GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_WALL_XandY] = [[3,0], [4,0], [3,1], [4,1]];
GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_NEEDLE] = [[3,3], [4,3], [3,4], [4,4]];
GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_NEEDLE_X] = [[0,4], [2,4], [0,4], [2,4]];
GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_NEEDLE_Y] = [[1,3], [1,3], [1,5], [1,5]];
GRAPHIC_INDEX_TO_POS[GRAPHIC_INDEX_NEEDLE_XY] = [[0,3], [2,3], [0,5], [2,5]];
}
//m_Palette_ForView
{
m_Palette_ForView = new Array(256);
var index_graphic:int = GRAPHIC_INDEX_BG;
for(i = 0; i < 256; i++){
//区切りごとにindexを変更。次の区切りまではその値をセット
switch(i){
case 0:
case 6:
case 18:
case 24:
index_graphic = GRAPHIC_INDEX_BG; break;
case 3:
case 21:
index_graphic = GRAPHIC_INDEX_NEEDLE_Y; break;
case 9:
case 15:
index_graphic = GRAPHIC_INDEX_NEEDLE_X; break;
case 12:
index_graphic = GRAPHIC_INDEX_NEEDLE_XY; break;
case 27:
index_graphic = GRAPHIC_INDEX_NEEDLE; break;
case 54:
case 63:
index_graphic = GRAPHIC_INDEX_WALL_XorY; break;
case 60:
case 69:
index_graphic = GRAPHIC_INDEX_WALL_X; break;
case 72:
index_graphic = GRAPHIC_INDEX_WALL_Y; break;
case 78:
index_graphic = GRAPHIC_INDEX_WALL_XandY; break;
case 80:
index_graphic = GRAPHIC_INDEX_WALL; break;
}
m_Palette_ForView[i] = index_graphic;
}
}
}
//#Draw : BG
static public function DrawBG(in_NumX:int, in_NumY:int, out_BitmapData_View:BitmapData):void
{
var x:int, y:int, i:int;
var mtx:Matrix = new Matrix();
var rect:Rectangle = new Rectangle(0,0, 16,16);
var NumX:int = in_NumX;
var NumY:int = in_NumY;
for(y = 0; y < NumY; y++){
for(x = 0; x < NumX; x++){
for(i = 0; i < 4; i++){
rect.x = x * 32 + 16 * ((i&1)>>0);
rect.y = y * 32 + 16 * ((i&2)>>1);
var index:int = GRAPHIC_INDEX_BG;
//#view
mtx.tx = rect.x - 16 * GRAPHIC_INDEX_TO_POS[index][i][POS_X];
mtx.ty = rect.y - 16 * GRAPHIC_INDEX_TO_POS[index][i][POS_Y];
out_BitmapData_View.draw(m_BitmapData_View, mtx, null, null, rect);
}
}
}
}
//#Draw : Blocks
static public function DrawBlocks(in_Map:Array, out_BitmapData_View:BitmapData):void
{
var x:int, y:int, i:int;
var mtx:Matrix = new Matrix();
var NumX:int = in_Map[0].length;
var NumY:int = in_Map.length;
//Map => Bitmap_Base
//Mapの要素を元に、「0:空白」「1:トゲ」「2:壁」というBitmapを生成
var BitmapData_Base:BitmapData;
{
BitmapData_Base = new BitmapData(NumX, NumY, false, 0x000000);
for(y = 0; y < NumY; y++){
for(x = 0; x < NumX; x++){
var index:int = 0;//default(O, P, G)
{
switch(in_Map[y][x]){
case GameMain.W:
index = 2;
break;
case GameMain.X:
index = 1;
break;
}
}
BitmapData_Base.setPixel(x, y, index);
}
}
}
//Bitmap_Base => Bitmap_LU,Bitmap_RU,Bitmap_LD,Bitmap_RD
//Bitmap_Baseを元に、四隅の隣接状況をそれぞれ求める(Uniqueな値になるようにする)
var BitmapData_Quater:Array = new Array(4);
{
//Create Filter
const filter:Array = [
new ConvolutionFilter(3,3,
[//LU
1, 3, 0,
9, 27, 0,
0, 0, 0,
]
),
new ConvolutionFilter(3,3,
[//RU
0, 3, 1,
0, 27, 9,
0, 0, 0,
]
),
new ConvolutionFilter(3,3,
[//LD
0, 0, 0,
9, 27, 0,
1, 3, 0,
]
),
new ConvolutionFilter(3,3,
[//RD
0, 0, 0,
0, 27, 9,
0, 3, 1,
]
),
];
for(i = 0; i < 4; i++){
//Init
BitmapData_Quater[i] = new BitmapData(NumX, NumY, false, 0x000000);
//Apply Filter
BitmapData_Quater[i].applyFilter(BitmapData_Base, BitmapData_Base.rect, POS_ZERO, filter[i]);
}
}
//Bitmap_LU,Bitmap_RU,Bitmap_LD,Bitmap_RD => ForView
//Uniqueな値から、対応するIndexへと変換する
var BitmapData_ForView:Array = new Array(4);
{
for(i = 0; i < 4; i++){
//Init
BitmapData_ForView[i] = new BitmapData(NumX, NumY, false, 0x000000);
//Apply Palette
BitmapData_ForView[i].paletteMap(BitmapData_Quater[i], BitmapData_Quater[i].rect, POS_ZERO, null, null, m_Palette_ForView);
}
}
//Draw
//上で求めたIndexに基づき描画
{
var rect:Rectangle = new Rectangle(0,0, 16,16);
for(y = 0; y < NumY; y++){
for(x = 0; x < NumX; x++){
for(i = 0; i < 4; i++){
rect.x = x * 32 + 16 * ((i&1)>>0);
rect.y = y * 32 + 16 * ((i&2)>>1);
index = BitmapData_ForView[i].getPixel(x, y);
//#view
mtx.tx = rect.x - 16 * GRAPHIC_INDEX_TO_POS[index][i][POS_X];
mtx.ty = rect.y - 16 * GRAPHIC_INDEX_TO_POS[index][i][POS_Y];
out_BitmapData_View.draw(m_BitmapData_View, mtx, null, null, rect);
}
}
}
}
}
//Image : Goal
static public function CreateGoalGraphic():Sprite{
//
const W:int = 48;
const H:int = 64;
const BLUR_VAL:int = 20;
//
var result:Sprite = new Sprite();
//基本画像
var bmd:BitmapData = new BitmapData(W, H, true, 0x00000000);
var bmp:Bitmap = new Bitmap(bmd);
{
//白い楕円の上半分を描画
const RAD_W:int = 12;//W/2-BLUR_VAL;
const RAD_H:int = 32;//H-BLUR_VAL;
var shape:Shape = new Shape();
var g:Graphics = shape.graphics;
g.lineStyle(0, 0x000000, 0.0);
g.beginFill(0xFFFFFF, 1.0);
g.drawEllipse(W/2-RAD_W, H-RAD_H, RAD_W*2, RAD_H*2);
g.endFill();
// shape.filters = [new GlowFilter(0xFFFFFF,1.0, 2*BLUR_VAL,2*BLUR_VAL)];
// shape.filters = [new GlowFilter(0xFFFFFF,1.0, 1,2*BLUR_VAL,255), new GlowFilter(0xFFFFFF,1.0, 2*BLUR_VAL,1,255)];
bmd.draw(shape);
shape.filters = [new BlurFilter(BLUR_VAL, BLUR_VAL)];
bmd.draw(shape);
bmd.draw(shape);
result.addChild(bmp);
}
//発光っぽくする
{
//フィルターを追加
// bmp.filters = [new GlowFilter(0xFFFFFF, 1.0, 2*BLUR_VAL,2*BLUR_VAL)];
//フィルターで下に広がるのを防止するためのマスク
var msk:Bitmap = new Bitmap(new BitmapData(W, H, false, 0xFFFFFF));
result.mask = msk;
result.addChild(msk);
//加算化
bmp.blendMode = BlendMode.ADD;
}
//位置調整
{
result.x = -W/2;
result.y = -H+16;
}
return result;
}
}