Touch Event를 이용한 비행기 컨트롤 (Android)
터치 이벤트를 이용해 비행기를 컨트롤해보자. +표시 를 중심으로 터치해보세요. 그 방향으로 비행기가 움직입니다. +에서 터치포인트가 멀어지면 속도도 증가합니다.
/**
* Copyright jidolstar ( http://wonderfl.net/user/jidolstar )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/4Akd
*/
// forked : keyboard Test
// arrows or [wad] to move,rotation
//--------------------------------------------------------------------------------
package {
import flash.display.*;
import flash.events.*;
import flash.filters.*;
import flash.geom.*;
import flash.ui.*;
import flash.utils.*;
import net.hires.debug.Stats;
[SWF(backgroundColor='#000000', frameRate='30')]
/**
* Touch Event를 이용한 비행기 컨트롤 (Android)
* @author jidolstar
* @see http://blog.jidolstar.com/672
*/
public class MobileShootGame extends Sprite {
function MobileShootGame() {
if (stage) {
ADDED_TO_STAGE();
} else {
addEventListener(Event.ADDED_TO_STAGE, ADDED_TO_STAGE);
}
}
private function ADDED_TO_STAGE($e:Event=null):void {
// stage
stage.tabChildren=false;
stage.stageFocusRect=false;
stage.mouseChildren=false;
stage.align=StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
//stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
WIDTH = stage.stageWidth;
HEIGHT = stage.stageHeight;
_landscape = new Landscape(WIDTH, HEIGHT);
_screen = new BitmapData(WIDTH, HEIGHT, true, 0x0);
// background
addChild(_landscape);
// rendering layer
addChild(new Bitmap(_screen));
// initialize
_plane=new Plane(_screen.width >> 1, _screen.height >> 1, 0);
// event listener
stage.addEventListener(Event.ENTER_FRAME, ENTER_FRAME);
// Stats
var stats:Stats;
addChild(stats = new Stats);
stats.alpha = 0.5;
TOUCH_SETUP();
}
private function TOUCH_SETUP():void {
//조정위치 및 영역
MoveControl.controlXCenter = stage.stageWidth/2;
MoveControl.controlYCenter = stage.stageHeight-100;
MoveControl.controlCenterRadius = 50;
var speedBox:Sprite = new Sprite();
speedBox.graphics.clear();
speedBox.graphics.lineStyle(1,0xff000,1.0);
speedBox.graphics.moveTo(MoveControl.controlXCenter, MoveControl.controlYCenter-50);
speedBox.graphics.lineTo(MoveControl.controlXCenter, MoveControl.controlYCenter+50);
speedBox.graphics.moveTo(MoveControl.controlXCenter-50, MoveControl.controlYCenter);
speedBox.graphics.lineTo(MoveControl.controlXCenter+50, MoveControl.controlYCenter);
addChild(speedBox);
var dots:Object = new Object();
var dotCount:uint = 0;
var THIS:DisplayObjectContainer = stage;
if(Multitouch.supportsTouchEvents) {
Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
stage.addEventListener(TouchEvent.TOUCH_BEGIN, onTouchBegin);
stage.addEventListener(TouchEvent.TOUCH_MOVE, onTouchMove);
stage.addEventListener(TouchEvent.TOUCH_END, onTouchEnd);
function onTouchBegin(e:TouchEvent):void {
if (dotCount == 1/*Multitouch.maxTouchPoints*/) return;
var dot:Sprite = getCircle();
dot.x = e.stageX;
dot.y = e.stageY;
THIS.addChild(dot);
++dotCount;
dots[e.touchPointID] = dot;
MoveControl.calc(e.stageX, e.stageY);
//dot.startTouchDrag(e.touchPointID, true);
}
function onTouchMove(e:TouchEvent):void {
var dot:Sprite = dots[e.touchPointID];
dot.x = e.stageX;
dot.y = e.stageY;
MoveControl.calc(e.stageX, e.stageY);
}
function onTouchEnd(e:TouchEvent):void {
var dot:Sprite = dots[e.touchPointID];
THIS.removeChild(dot);
delete dots[e.touchPointID];
--dotCount;
MoveControl.clear();
}
} else {
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
function onMouseDown(e:MouseEvent):void {
var dot:Sprite = getCircle();
dot.x = e.stageX;
dot.y = e.stageY;
THIS.addChild(dot);
dots[0] = dot;
MoveControl.calc(e.stageX, e.stageY);
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
//dot.startTouchDrag(e.touchPointID, true);
}
function onMouseMove(e:MouseEvent):void {
var dot:Sprite = dots[0];
dot.x = e.stageX;
dot.y = e.stageY;
MoveControl.calc(e.stageX, e.stageY);
}
function onMouseUp(e:MouseEvent):void {
var dot:Sprite = dots[0];
THIS.removeChild(dot);
delete dots[0];
MoveControl.clear();
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
}
function getCircle(circumference:uint = 20):Sprite {
var circle:Sprite = new Sprite();
circle.graphics.beginFill((dotCount==0)?0x1695A3:0xff0000);
circle.graphics.drawCircle(0, 0, circumference);
return circle;
}
}
private function ENTER_FRAME($e:Event):void {
//update
_plane.update();
//rendering
_screen.lock();
_screen.colorTransform(_screen.rect,new ColorTransform(1,1,1,0.9,0,0,0));
_screen.fillRect(_screen.rect, 0x000000);
_plane.render();
_screen.unlock();
}
}
}
import flash.display.*;
import flash.events.*;
import flash.filters.*;
import flash.geom.*;
import flash.system.*;
import flash.ui.*;
import flash.utils.*;
var _plane:Plane;
var _landscape:Landscape;
var _screen:BitmapData;
var _mainScreen:Sprite;
var WIDTH:Number;
var HEIGHT:Number;
class MoveControl {
static public var controlXCenter:Number;
static public var controlYCenter:Number;
static public var controlCenterRadius:Number;
static public var speed:Number = 0;
static public var planeDirection:Number = 0;
static public var direction:Number = 0;
static public function calc($x:Number, $y:Number):void {
var dx:Number = controlXCenter - $x;
var dy:Number = controlYCenter - $y;
speed = Math.sqrt(dx*dx+dy*dy);
if(speed > 100) speed = 100;
speed /= 10;
direction = Math.atan2(dy, dx)*180/Math.PI;
}
static public function clear():void {
//left = 0;
//right = 0;
//up = 0;
speed = 0;
}
}
// Resource
//----------------------------------------------------------------------------------------------------
class DisplayImage {
public var bmp:BitmapData;
public var rect:Rectangle;
public var cx:int, cy:int;
function DisplayImage($bmp:BitmapData, $cx:int, $cy:int) {
bmp=$bmp;
cx=$cx;
cy=$cy;
trimming();
}
private function trimming():void {
var r:Rectangle=bmp.getColorBoundsRect(0xFF000000, 0x00000000);
var temp:BitmapData=new BitmapData(r.width, r.height, true, 0x00000000);
cx-=r.x;
cy-=r.y;
temp.copyPixels(bmp, r, new Point(0, 0));
bmp.dispose();
bmp=temp;
rect=r;
}
}
// Plane
//----------------------------------------------------------------------------------------------------
class Plane {
private const D2R:Number=Math.PI / 180; //Degree -> Radian
private const ROT_STEPS:Number=100;
private const ROT_STEP_DIRECTION:Number=ROT_STEPS / 360;
private const FRAMES:int=3;
private const KEY_W:int=87;
private const KEY_D:int=68;
private const KEY_A:int=65;
private const KEY_UP:int=Keyboard.UP;
private const KEY_RIGHT:int=Keyboard.RIGHT;
private const KEY_LEFT:int=Keyboard.LEFT;
private var loader:Loader=new Loader();
private var rotArr:Vector.<DisplayImage>=new Vector.<DisplayImage>(3 * ROT_STEPS, true);
private var r:Number=-90; //rotation
private var vr:Number=0; //rotation velocity
private var x:Number=0; //x-axis position
private var y:Number=0; //y-axis position
private var v:Number=0;
private var currentImg:DisplayImage;
private var currentFrame:int=0;
private var frameInterval:Number=0;
private var ready:int=0;
private var planeBitmap:Bitmap;
function Plane($x:Number, $y:Number, $rotation:Number) {
// 원본이미지를 Base64로 Encode 하는 방법
//[Embed(source="../assets/brownplane.png")]
//private var PLANE:Class;
//var plane:Bitmap = new PLANE as Bitmap;
//var encoder:Base64Encoder = new Base64Encoder;
//var byte:ByteArray = (new PNGEncoder).encode(plane.bitmapData);
//encoder.encodeBytes( byte );
//trace( encoder.drain() );
// plane base64 data
// http://www.brighthub.com/internet/web-development/articles/11010.aspx
// plane image : http://www.brighthub.com/internet/web-development/articles/11010.aspx
var pdata:String="", byteArr:ByteArray;//, base64Dec:Base64Decoder=new Base64Decoder();
pdata+="iVBORw0KGgoAAAANSUhEUgAAAMMAAABBCAYAAABsBxB5AAAF5UlEQVR42u2dr1fcWBiGx1UgViAq";
pdata+="KhCIFRUViAoEAoGsQFZUjFgxYkUFArECMaJ/AKKiogKBWIkYUYlArEAgVyAqkZVZ3tt9c765JJmE";
pdata+="mUBO53nP+U6SmztfvvuU5N7cH+lohBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIoV9Pm3uTYmdnpzQd";
pdata+="wwAGa8fgxet3xV8Hr4q/j3eLq8+HaatjpcMABuvEYLS//aKYfToobmeT4u7qKG11rHQYwGBtGKga";
pdata+="1N2vJ4EA/Li9TlsdK30dqkkY/MIMilwbvyU7OjqaM+Xd2HlffJ3sFDfnH4ri32mCoK2Ola7zXX0O";
pdata+="QXlcjjdXFwZdfA6ZwTJ/B118Dkq/b45SQXR3y7SvtLydqHRViRGCjpWetxfb+IQBDAZX7TlYFUjm";
pdata+="oGOVt7W1NQfBZgg639UnDGAwLG3vpd4ABRrvcqXpXA5BhRm9PSjNhYsQ2vqEAQyeRC8PjtPdJ1M7";
pdata+="TtWXTMHaVF19Otwu79wYsNL+eLuZ8si0r8Kq4F9ubovrH0Xa6ljped46n64mYxyOTXE6ZsUPAxg8";
pdata+="moHbc+rmchutyZQvVmN5wAbkfeV99/l87iVQx0rP8zZB6Bpfl/5rGMCgBBAvbnO7Lj9Wl9giCG7r";
pdata+="GcL4fJaeBjYdG0LM2wRB15XFNmeMzefjb9qAgAEM0ouKLuw77e7mWxmQ7PvleUrTNqbLNJReF7DO";
pdata+="VUG4+H5XWhWEtj7bxOcng/w3vXTBAAbl0yBCiHZzMS2urq6K6eV12qbjcP7k5KQMOL8TfS6vHj9e";
pdata+="XJZWVT229dkmvgih6akAAxjMzRVxOyzaP1+PU7Cj0be01XE8v+juzSFsTY5TwW06ziEs8tklPrcX";
pdata+="F819gQEMyupRb+4OVKbuK9l0Oi3Ozs7SBWazWXF5OnlwAQcc+4xdcOezb+2r4Db7yPPW+cz/oVI8";
pdata+="93EpPsWpeB27yyJ/Kt+iJgIMYFA+Fd6/2Sg+7r2cgyHTsPfp6encBeKF6qqyKgiurmwuWB2Eqpeg";
pdata+="PAbFpfgUZ4xbflQelavtyyMMYFCC0MxB/ejP3c1UpeRA8iAiBAUjixCcz340B8U9ANp6Tkqet85n";
pdata+="1fXzgituxa9yqDxduxVhAIOyqtTonn6cA8kvaPMLjRdq+OWmCYJnKzZBqPJZF0Ne8DQd+L4cjxm2";
pdata+="hwEMHow8aiRPI3u7r0YlEJkuePrhdTJDGI/HZcDar4NQNXW3DkKVT+X1tRWHY1J8HoVU3KsafYUB";
pdata+="DFoDUTBNEGK1lbcrY5WX522CEAuueJa+82EAg2WAeH6KgtFdnFdl8SkQC6kXI89l1zb2IsS8dT51";
pdata+="vV7vfBjA4LGKsxAVaGzTqfr6Mn6TzIX0ulebX3503nndLq3yOTercSCCAQxGceWS17R6PaurMRUu";
pdata+="WgQRAUTT7+p8eiUUDGAwuJtB1ZMDdl+wA/ZU3DglN4KIAyF53jqfg6gOYQCDOqlKU6E8ZK59pVX1";
pdata+="X0cQBlDV/9vWJwxgMCgdHv5sx3nIXPtKa+q/ttW9/XfxCQMYDA6Cq7JVBNyHTxjAoHft7+8/CFhp";
pdata+="Q/MJAxj0Li8KiQs4lh386MMnDGDwJD0JecDLvu334RMGMHgS+UsG/hrCUH3CAAa9SwMkDlj7Q/UJ";
pdata+="Axj0Lg2QeFHGqj7/14dPGMCgl5elNCS+vVd+SEpzSWT5KOIyFn2m+Sj31/NHomAAg2dloItruq5G";
pdata+="An23ehah9jU66Lko+YLsrtbkU9dUHM8BAwYw+Kn/v3+pQOLCDAXpEUIH7IlY7gmIy/zqtvE7N1U+";
pdata+="7c8gnuW7ozCAQQ4hD9iDIk0QFtkin/EbOEP4Q4DBGjOIEOJ8dL/xV0GIINpYk8+h/SHAYI0ZNLUV";
pdata+="qyDknwNp85HY2FbMfQ69vQyD9WGQpKm2CsArkrTvZX9elKGtF2zHvE0W89tP7jPmfc7/HRIGMChV";
pdata+="tQbW3V/aX0V3Wu5zaGteYQCD2qeEv1awqju1D58wgMGTtSNX3XbrwycMYIAQQgghhBBCCCGEEEII";
pdata+="IYQQWqH+A2OxL7+zKnbXAAAAAElFTkSuQmCC";
// decode
byteArr=Base64.decode(pdata);
// load
loader.loadBytes(byteArr, new LoaderContext(false, ApplicationDomain.currentDomain, null));
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, COMPLETE);
//initialize
x=$x;
y=$y;
r=$rotation;
}
private function COMPLETE($e:Event):void {
loader=null;
var i:int, j:int, k:int, src:BitmapData, temp:BitmapData;
var rect:Rectangle, destPoint:Point, frameWidth:Number, frameHeight:Number, matrix:Matrix;
var stepBmpList:Vector.<Bitmap>;
src=Bitmap(LoaderInfo($e.target).content).bitmapData
destPoint=new Point(0, 0);
frameWidth=src.width / FRAMES;
frameHeight=src.height;
j=FRAMES;
stepBmpList=new Vector.<Bitmap>(FRAMES, true);
while (j--) {
rect=new Rectangle(j * frameWidth, 0, frameWidth, frameHeight);
temp=new BitmapData(frameWidth, frameHeight, true, 0x0);
temp.copyPixels(src, rect, destPoint);
stepBmpList[j]=new Bitmap(temp);
}
j=FRAMES;
matrix=new Matrix;
rect=new Rectangle(frameWidth, 0, frameWidth, frameHeight);
while (j--) { //frame
i=ROT_STEPS;
k=j * ROT_STEPS;
while (i--) { //rotation
matrix.identity();
matrix.translate(-frameWidth / 2, -frameHeight / 2);
matrix.rotate((360 / ROT_STEPS * i) * D2R);
matrix.translate(frameWidth / 2, frameHeight / 2);
temp=new BitmapData(frameWidth, frameHeight, true, 0x0);
temp.draw(stepBmpList[j], matrix, null, null, null, true);
rotArr[i + k]=new DisplayImage(temp, frameWidth / 2, frameHeight / 2);
}
}
ready=1;
/*
var a:Number = 0;
var b:int = 0;
for(i=0;i<rotArr.length;i++) {
var img:DisplayImage = rotArr[i];
_screen.copyPixels(img.bmp,img.rect,new Point((a-b*10)*img.rect.width,b * img.rect.height));
a += 1;
b = a/10 ;
}*/
//planeBitmap = new Bitmap;
//_mainScreen.addChild(planeBitmap);
}
public function update():void {
if (!ready)
return;
var a:Number;
// rotation
var d:Number = MoveControl.direction-r;
if(d < -180) d = 360 + d;
else if(d > 180) d = d - 360;
r += d*0.1;
MoveControl.planeDirection = r;
// move
var theta:Number = (270 - r) * D2R;
v += (MoveControl.speed-v)*0.1
x+=v * Math.sin(theta);
y+=v * Math.cos(theta);
// check boundary
(x > WIDTH) ? x=0 : (x < 0) ? x=WIDTH : 0;
(y > HEIGHT) ? y=0 : (y < 0) ? y=HEIGHT : 0;
// find image
var i:Number = r-90;
i = i - Math.floor(i/360) * 360;
currentImg=rotArr[int(i * ROT_STEP_DIRECTION) + ROT_STEPS * currentFrame];
// check frame
if (frameInterval + 100 < getTimer()) {
if (++currentFrame === FRAMES) {
currentFrame=0;
}
frameInterval=getTimer();
}
}
public function render():void {
if (!ready)
return;
_screen.copyPixels(currentImg.bmp, currentImg.rect, new Point(x - currentImg.cx, y - currentImg.cy));
}
}
// Background
//----------------------------------------------------------------------------------------------------
class Landscape extends Bitmap {
// This color gradation is refered from psyrak's BumpyPlanet
// http://wonderfl.net/code/d79cd85845773958620f42cb3e6cb363c2020c73
public var gradation:*={color: [0x000080, 0x0066ff, 0xcc9933, 0x00cc00, 0x996600, 0xffffff], alpha: [100, 100, 100, 100, 100, 100], ratio: [0, 96, 96, 128, 168, 192]};
public var pixels:BitmapData, texture:BitmapData, rect:Rectangle;
private var pt:Point=new Point();
function Landscape(w:int, h:int) {
texture=new BitmapData(w * 2, h * 2, false, 0);
pixels=new BitmapData(w, h, false, 0);
rect=new Rectangle(0, 0, w, h);
super(pixels);
// height map
var hmap:BitmapData=new BitmapData(w, h, false, 0);
hmap.perlinNoise(w * 0.5, h * 0.5, 10, Math.random() * 0xffffffff, true, false, 0, true);
hmap.colorTransform(hmap.rect, new ColorTransform(1.5, 1.5, 1.5, 1, -64, -64, -64, 0));
// texture
var mapR:Array=new Array(256), mapG:Array=new Array(256), mapB:Array=new Array(256);
var gmap:BitmapData=new BitmapData(256, 1, false, 0), render:Shape=new Shape(), mat:Matrix=new Matrix();
mat.createGradientBox(256, 1, 0, 0, 0);
render.graphics.clear();
render.graphics.beginGradientFill("linear", gradation.color, gradation.alpha, gradation.ratio, mat);
render.graphics.drawRect(0, 0, 256, 1);
render.graphics.endFill();
gmap.draw(render);
for (var i:int=0; i < 256; i++) {
var col:uint=gmap.getPixel(i, 0);
mapR[i]=col & 0xff0000;
mapG[i]=col & 0x00ff00;
mapB[i]=col & 0x0000ff;
}
gmap.dispose();
mat.identity();
texture.paletteMap(hmap, hmap.rect, hmap.rect.topLeft, mapR, mapG, mapB);
// shading
var smap:BitmapData=new BitmapData(w, h, false, 0);
smap.applyFilter(hmap, hmap.rect, hmap.rect.topLeft, new ConvolutionFilter(3, 3, [-1, -1, 0, -1, 0, 1, 0, 1, 1], 1, 0, true, true));
texture.draw(smap, null, new ColorTransform(4, 4, 4, 1, 160, 160, 160, 0), "multiply");
// copy 2x2
pt.x=w;
pt.y=h;
texture.copyPixels(texture, hmap.rect, pt);
pt.x=0;
pt.y=h;
texture.copyPixels(texture, hmap.rect, pt);
pt.x=w;
pt.y=0;
texture.copyPixels(texture, hmap.rect, pt);
pt.x=0;
pt.y=0;
// rendering
pixels.copyPixels(texture, rect, pt);
}
}
/** Base64 */
class Base64 {
private static const encodeChars:Array =
['A','B','C','D','E','F','G','H',
'I','J','K','L','M','N','O','P',
'Q','R','S','T','U','V','W','X',
'Y','Z','a','b','c','d','e','f',
'g','h','i','j','k','l','m','n',
'o','p','q','r','s','t','u','v',
'w','x','y','z','0','1','2','3',
'4','5','6','7','8','9','+','/'];
private static const decodeChars:Array =
[-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, 62, -1, -1, -1, 63,
52, 53, 54, 55, 56, 57, 58, 59,
60, 61, -1, -1, -1, -1, -1, -1,
-1, 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, -1, -1, -1, -1, -1,
-1, 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, -1, -1, -1, -1, -1];
public static function encode(data:ByteArray):String {
var out:Array = [];
var i:int = 0;
var j:int = 0;
var r:int = data.length % 3;
var len:int = data.length - r;
var c:int;
while (i < len) {
c = data[i++] << 16 | data[i++] << 8 | data[i++];
out[j++] = encodeChars[c >> 18] + encodeChars[c >> 12 & 0x3f] + encodeChars[c >> 6 & 0x3f] + encodeChars[c & 0x3f];
}
if (r == 1) {
c = data[i++];
out[j++] = encodeChars[c >> 2] + encodeChars[(c & 0x03) << 4] + "==";
}
else if (r == 2) {
c = data[i++] << 8 | data[i++];
out[j++] = encodeChars[c >> 10] + encodeChars[c >> 4 & 0x3f] + encodeChars[(c & 0x0f) << 2] + "=";
}
return out.join('');
}
public static function decode(str:String):ByteArray {
var c1:int;
var c2:int;
var c3:int;
var c4:int;
var i:int;
var len:int;
var out:ByteArray;
len = str.length;
i = 0;
out = new ByteArray();
while (i < len) {
// c1
do {
c1 = decodeChars[str.charCodeAt(i++) & 0xff];
} while (i < len && c1 == -1);
if (c1 == -1) {
break;
}
// c2
do {
c2 = decodeChars[str.charCodeAt(i++) & 0xff];
} while (i < len && c2 == -1);
if (c2 == -1) {
break;
}
out.writeByte((c1 << 2) | ((c2 & 0x30) >> 4));
// c3
do {
c3 = str.charCodeAt(i++) & 0xff;
if (c3 == 61) {
return out;
}
c3 = decodeChars[c3];
} while (i < len && c3 == -1);
if (c3 == -1) {
break;
}
out.writeByte(((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2));
// c4
do {
c4 = str.charCodeAt(i++) & 0xff;
if (c4 == 61) {
return out;
}
c4 = decodeChars[c4];
} while (i < len && c4 == -1);
if (c4 == -1) {
break;
}
out.writeByte(((c3 & 0x03) << 6) | c4);
}
return out;
}
}