/**
* 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/dTm5
*/
/*
DisplacementMapFilterの使い方を試し中。
とりあえずベタな効果を作りつつ、さらにプレイヤーの移動と組み合わせてみる
操作方法(画面を2回ほどクリックしないと十字キーがきかなかったりする)
・十字キー
・移動&ジャンプ
・マウス移動
・背景を歪ませる
*/
package
{
import flash.display.*;
import flash.events.*;
import flash.geom.*;
import flash.net.*;
import flash.text.*;
import flash.filters.*;
import flash.ui.*;
public class GameMain extends Sprite
{
//==Const==
//干渉半径
static public const DIS_RAD:int = 0x50;
//プレイヤーの初期位置
static public const PLAYER_INIT_X:int = 70;
static public const PLAYER_INIT_Y:int = 70;
//Utility
static public const POS_ZERO:Point = new Point(0,0);
//==Var==
//背景
public var m_BitmapData_View:BitmapData;
//カーソル部分(背景は直接変更せず、カーソル位置に湾曲した画像を作ってかぶせる)
public var m_Bitmap_Cursor:Bitmap;
//コリジョン(背景+カーソルの結果を書き出して、プレイヤーのためのコリジョンとして扱う)
public var m_BitmapData_Collision:BitmapData;
//プレイヤー
public var m_Player:Player;
//==Function==
//Static Global Access
static private var m_Instance:GameMain;
static public function Instance():GameMain{return m_Instance;}
//Init
public function GameMain()
{
m_Instance = this;
addEventListener(Event.ADDED_TO_STAGE, Init);
}
public function Init(e:Event=null):void
{
var g:Graphics;
//Init Once
{
removeEventListener(Event.ADDED_TO_STAGE, init);
}
//コリジョン
{
m_BitmapData_Collision = new BitmapData(stage.stageWidth, stage.stageHeight, true, 0xFFFFFFFF);
//debug
//addChild(new Bitmap(m_BitmapData_Collision));
}
//背景
{
//Create & Regist
{
m_BitmapData_View = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0xFFFFFF);
addChild(new Bitmap(m_BitmapData_View));
}
//Draw
{
var shape_bg:Shape = new Shape();
g = shape_bg.graphics;
g.clear();
g.lineStyle(3, 0x000000);
g.drawRect(50, 50, 200, 100);
g.drawRect(150, 250, 200, 100);
g.drawRect(350, 100, 200, 100);
g.beginFill(0x000000, 1.0);
g.drawRect(0, 400, 100, 50);
g.endFill();
m_BitmapData_View.draw(shape_bg);
}
}
//カーソル
{
//Create & Regist
{
m_Bitmap_Cursor = new Bitmap(new BitmapData(2*DIS_RAD, 2*DIS_RAD, true, 0x00000000));
addChild(m_Bitmap_Cursor);
}
//フィルター
{
//オフセットから色を計算
const calc_color:Function = function(in_GapX:int, in_GapY:int):uint{
var r:uint = 0x00;
var g:uint = 0x80 + in_GapX;
var b:uint = 0x80 + in_GapY;
return (r << 16) | (g << 8) | (b << 0);
};
//オフセット値を格納したBitmap
var bmd_sampling:BitmapData = new BitmapData(2*DIS_RAD, 2*DIS_RAD, false, calc_color(0,0));
//歪めるための計算
for(var y:int = 0; y < 2*DIS_RAD; y++){
var GapY:int = (2*DIS_RAD-1)/2 - y;
for(var x:int = 0; x < 2*DIS_RAD; x++){
var GapX:int = (2*DIS_RAD-1)/2 - x;
var distance:Number = Math.sqrt(GapX*GapX + GapY*GapY);
if(distance < DIS_RAD){
var ratio:Number = 1 - distance/DIS_RAD;
ratio = Math.sin(0.5*Math.PI * ratio);
ratio = 0.5 - 0.5*Math.cos(Math.PI * ratio);
bmd_sampling.setPixel(x, y, calc_color(GapX*ratio, GapY*ratio));
}
}
}
//実際にフィルターとして生成&セット
m_Bitmap_Cursor.filters = [
new DisplacementMapFilter(
bmd_sampling,//Sampling : Bitmap
null,//Sampling : Point
BitmapDataChannel.GREEN,//X
BitmapDataChannel.BLUE,//Y
0x100,//ScaleX
0x100,//ScaleY
DisplacementMapFilterMode.COLOR,//Mode
0x000000,//color
0//alpha
)
];
}
//カーソルの更新
{
//初期化
Update_Cursor();
//マウスの移動のたびに更新
stage.addEventListener(MouseEvent.MOUSE_MOVE, Update_Cursor);
}
}
//プレイヤー
{
//Create & Regist
{
m_Player = new Player(PLAYER_INIT_X, PLAYER_INIT_Y);
addChild(m_Player);
}
}
}
//カーソルの更新(背景からカーソル位置の画像をコピー)
static public var copy_rect:Rectangle = new Rectangle(0,0, 2*DIS_RAD,2*DIS_RAD);
public function Update_Cursor(e:Event=null):void{
var lx:int = mouseX-DIS_RAD;
var uy:int = mouseY-DIS_RAD;
//背景の該当部分をカーソル用のBitmapにコピー
copy_rect.x = lx;
copy_rect.y = uy;
m_Bitmap_Cursor.bitmapData.copyPixels(m_BitmapData_View, copy_rect, POS_ZERO);
m_Bitmap_Cursor.x = lx;
m_Bitmap_Cursor.y = uy;
//さらにコリジョンも更新
Update_Collision();
}
//コリジョンの更新(背景+カーソル)
static public var mtx:Matrix = new Matrix();
public function Update_Collision(e:Event=null):void{
//背景を描画
m_BitmapData_Collision.copyPixels(m_BitmapData_View, m_BitmapData_View.rect, POS_ZERO);
//カーソルを重ねて描画
mtx.tx = m_Bitmap_Cursor.x;
mtx.ty = m_Bitmap_Cursor.y;
m_BitmapData_Collision.draw(m_Bitmap_Cursor, mtx);
//白い部分を透明にする
m_BitmapData_Collision.threshold(m_BitmapData_Collision, m_BitmapData_Collision.rect, POS_ZERO, ">", 0xFF/2, 0x00000000, 0x000000FF);
//さらにプレイヤーの厚みに合わせて相対的にコリジョン側の厚みを増やす(プレイヤーは1ドット分の大きさで済むように)
const glow_filter_x:GlowFilter = new GlowFilter(0x000000,1.0, 2*Player.RAD,0, 255);
const glow_filter_y:GlowFilter = new GlowFilter(0x000000,1.0, 0,2*Player.RAD, 255);
m_BitmapData_Collision.applyFilter(m_BitmapData_Collision, m_BitmapData_Collision.rect, POS_ZERO, glow_filter_x);
m_BitmapData_Collision.applyFilter(m_BitmapData_Collision, m_BitmapData_Collision.rect, POS_ZERO, glow_filter_y);
}
//コリジョンがあるか
public function IsCollision(in_X:int, in_Y:int):Boolean{
//範囲外チェック:ぶつかるようにする
{
if(in_X < 0){return true;}
if(in_X >= m_BitmapData_Collision.width){return true;}
if(in_Y < 0){return true;}
if(in_Y >= m_BitmapData_Collision.height){return true;}
}
//あとは普通にコリジョンを見る
var color:uint = m_BitmapData_Collision.getPixel32(in_X, in_Y);
var a:uint = (color >> 24) & 0xFF;
return a > 0xFF/2;//一定以上不透明だったらコリジョンとみなす
}
}
}
import flash.display.*;
import flash.events.*;
import flash.geom.*;
import flash.net.*;
import flash.text.*;
import flash.filters.*;
import flash.ui.*;
//プレイヤー
internal class Player extends Sprite{
//==Cost==
//#Size
static public const RAD:int = 8;
//#Input
static public var button_enum:int = 0;
static public const BUTTON_L:int = button_enum++;
static public const BUTTON_R:int = button_enum++;
static public const BUTTON_U:int = button_enum++;
static public const BUTTON_NUM:int = button_enum;
//#Move
static public const VEL_X:Number = 100.0;
static public const VEL_Y:Number = 300.0;
static public const ACC_Y:Number = 500.0;
//==Var==
//#Input
public var m_Input:Array = new Array(BUTTON_NUM);
//#Move
public var m_VY:Number = 0.0;
public var m_OnGround:Boolean = false;
//==Function==
//#Init
public function Player(in_X:int, in_Y:int){
//Pos
{
this.x = in_X;
this.y = in_Y;
}
//Init Later (for Using "stage" etc.)
addEventListener(Event.ADDED_TO_STAGE, Init );
}
public function Init(e:Event = null):void{
var i:int;
//Init Once Only
{
removeEventListener(Event.ADDED_TO_STAGE, Init );
}
//Create Graphic
{
var shape:Shape = new Shape();
var g:Graphics = shape.graphics;
g.lineStyle(2, 0xFF0000, 1.0);
g.beginFill(0xFFFFFF, 1.0);
g.drawCircle(0,0, RAD);
g.endFill();
addChild(shape);
}
//Input
{
//Init
for(i = 0; i < BUTTON_NUM; i++){
m_Input[i] = false;
}
//Listener
stage.addEventListener(KeyboardEvent.KEY_DOWN, KeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, KeyUp);
}
//Call Update
{
addEventListener(Event.ENTER_FRAME, Update);
}
}
//#Input
public function KeyDown(e:KeyboardEvent):void{
switch(e.keyCode){
case Keyboard.LEFT: m_Input[BUTTON_L] = true; break;
case Keyboard.RIGHT: m_Input[BUTTON_R] = true; break;
case Keyboard.UP: m_Input[BUTTON_U] = true; break;
}
}
public function KeyUp(e:KeyboardEvent):void{
switch(e.keyCode){
case Keyboard.LEFT: m_Input[BUTTON_L] = false; break;
case Keyboard.RIGHT: m_Input[BUTTON_R] = false; break;
case Keyboard.UP: m_Input[BUTTON_U] = false; break;
}
}
//#Update
public function Update(e:Event):void{
var DeltaTime:Number = 1.0 / 24.0;
//Move
{
//Calc MoveVal
var MoveX:int;
var MoveY:int;
{
//X
{
MoveX = 0;
if(m_Input[BUTTON_L]){MoveX -= VEL_X * DeltaTime;}
if(m_Input[BUTTON_R]){MoveX += VEL_X * DeltaTime;}
}
//Y
{
//ジャンプ
if(m_OnGround && m_Input[BUTTON_U]){
m_VY = -VEL_Y;
}
m_OnGround = false;//毎回着地判定を行うので、着地しなかった時のためにリセット
//重力
m_VY += ACC_Y * DeltaTime;
MoveY = m_VY * DeltaTime;
}
}
//移動アルゴリズム実行
const BaseOffset:int = 1;//浮く量
var Offset:int;
var TrgX:int;
var TrgY:int;
var i:int;
//Move : Up
{
TrgX = this.x;
Offset = (MoveY < 0)? BaseOffset-MoveY: BaseOffset;
for(i = 0; i < Offset; i++){
TrgY = this.y - 1;
if(GameMain.Instance().IsCollision(TrgX, TrgY)){
//天井にぶつかったので速度は0にする
m_VY = 0;
break;
}
this.y = TrgY;
}
}
//Move : Horz
{
TrgX = this.x;
TrgY = this.y;
for(i = 0; i != MoveX; ){
if(i < MoveX){
i++;
TrgX++;
}else{
i--;
TrgX--;
}
if(GameMain.Instance().IsCollision(TrgX, TrgY)){break;}
this.x = TrgX;
}
}
//Move : Down
{
TrgX = this.x;
Offset = (MoveY > 0)? BaseOffset+MoveY: BaseOffset;
for(i = 0; i < Offset; i++){
TrgY = this.y + 1;
if(GameMain.Instance().IsCollision(TrgX, TrgY)){
//接地したとみなす
m_OnGround = true;//ジャンプできるようにフラグオン
m_VY = 0;//速度リセット
break;
}
this.y = TrgY;
}
}
}
}
}