flash on 2010-11-22
Author: Loki
/**
* Copyright tcper ( http://wonderfl.net/user/tcper )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/xrrb
*/
/**
* Author: Loki
*
*/
package {
import flash.display.Shape;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.display.Sprite;
import com.bit101.components.*;
public class FlashTest extends Sprite {
private var container:Sprite;
private var wall:Vec2D;
private var light:Vec2D;
private var renderList:Array = [];
private var halfW:Number
private var halfH:Number
private var RADIAN:Number = 180 / Math.PI;
private var canon:Sprite;
private var NOW_RADIAN:Number;
private var ballV:int = 10;
private var pb:PushButton = new PushButton();
private var stageCover:Sprite = new Sprite();
private const BALL_RADIUS:int = 5;
private var ballList:Array = [];
private var wallList:Array = [];
private var wallHolderList:Array = [];
public function FlashTest() {
// write as3 code here..
if( stage ){
init();
}else{
this.addEventListener(Event.ADDED_TO_STAGE, init);
}
}
private function init(event:Event = null):void{
this.removeEventListener(Event.ADDED_TO_STAGE, init);
canon = new Sprite();
halfW = stage.stageWidth / 2;
halfH = stage.stageHeight / 2;
initCover();
}
private function initCover():void{
stageCover.graphics.beginFill(0x0,.3);
stageCover.graphics.drawRect(0,0,stage.stageWidth,stage.stageHeight);
stageCover.graphics.endFill();
this.addChild( stageCover );
pb.label = "Start!";
pb.x = (stage.stageWidth - pb.width)/2;
pb.y = (stage.stageHeight - pb.height)/2;
pb.addEventListener(MouseEvent.CLICK, startGame);
this.addChild(pb);
}
private function startGame(event:Event):void{
this.removeChild( pb );
this.removeChild( stageCover );
initWalls();
initCannon();
initSpit();
this.addEventListener(Event.ENTER_FRAME, enterFrame);
}
private function initCannon():void{
canon.graphics.lineStyle(10,0x0,.3);
canon.graphics.lineTo(30,0);
canon.x = halfW;
canon.y = halfH;
this.addChild( canon );
}
private function initWalls():void{
var wh1:Sprite = createWallHolder(0);
wh1.x = 150;
wh1.y = 150;
var wh2:Sprite = createWallHolder(1);
wh2.x = 180;
wh2.y = 80;
var wh3:Sprite = createWallHolder(0);
wh3.x = stage.stageWidth;
wh3.y = 100;
var wh4:Sprite = createWallHolder(1);
wh4.x = stage.stageWidth-100;
wh4.y = 0;
var wh5:Sprite = createWallHolder(0);
wh5.x = 230;
wh5.y = 350;
var wh6:Sprite = createWallHolder(1);
wh6.x = 190;
wh6.y = 340;
var w1:Wall = createWall(wh1,wh2);
var w2:Wall = createWall(wh4,wh3);
var w3:Wall = createWall(wh5,wh6);
wallHolderList = [[wh1,wh2],[wh4,wh3],[wh5,wh6]];
wallList.push( w1,w2 ,w3);
}
private function createWall(h1:Sprite,h2:Sprite):Wall{
var wall:Wall = new Wall(h1.x,h1.y,h2.x,h2.y);
wall.A.x = h1.x;
wall.A.y = h1.y;
wall.B.x = h2.x;
wall.B.y = h2.y;
return wall;
}
private function initSpit():void{
stage.addEventListener(MouseEvent.MOUSE_DOWN, spitHandler);
}
private function spitHandler(event:Event):void{
var ball:Object = generateBall();
ballList.push( ball );
this.addChild( ball.ball );
}
private function generateBall():Object{
var obj:Object = {};
var ball:Sprite = new Sprite();
ball.graphics.beginFill(0xFFFFFF*Math.random(),.5);
ball.graphics.drawCircle(0,0,BALL_RADIUS);
ball.graphics.endFill();
ball.x = halfW;
ball.y = halfH;
obj.ball = ball;
obj.vx = Math.cos(NOW_RADIAN) * ballV;
obj.vy = Math.sin(NOW_RADIAN) * ballV;
return obj;
}
private function handleCannon():void{
var angle:Number = Math.atan2(mouseY - halfH,mouseX - halfW);
NOW_RADIAN = angle;
canon.rotation = angle * RADIAN;
}
private function createWallHolder(n:int = 0):Sprite{
var sprite:Sprite = new Sprite();
if( n == 0 ){
sprite.graphics.beginFill(0xFF0000, .3);
}else{
sprite.graphics.beginFill(0x00FF00, .3);
}
sprite.graphics.drawCircle(0,0,10);
//sprite.addEventListener(MouseEvent.MOUSE_DOWN, dragHolder);
//sprite.addEventListener(MouseEvent.MOUSE_UP, stopDragHolder)
this.addChild( sprite );
return sprite;
}
private function dragHolder(event:Event):void{
event.target.startDrag();
}
private function stopDragHolder(event:Event):void{
event.target.stopDrag();
}
private function handleBallMove():void{
if (ballList.length > 0)
{
for (var i:int = 0; i < ballList.length; i++)
{
var ball:Object = ballList[i];
ballMove(ball);
if ( ball.ball.x < 0 || ball.ball.x > stage.stageWidth ||
ball.ball.y < 0 || ball.ball.y > stage.stageHeight )
{
this.removeChild( ball.ball );
ballList.splice(i,1);
}
if( checkWalls() ){
win();
}
}
}
}
private function checkWalls():Boolean{
for( var i:int = 0; i < wallList.length; i++ ){
var wall:Wall = wallList[i];
if( !wall.hit ){
return false;
}
}
return true;
}
private function win():void{
this.removeEventListener(Event.ENTER_FRAME, enterFrame);
this.graphics.clear();
this.removeEventListener(MouseEvent.MOUSE_DOWN, spitHandler);
while( this.numChildren > 0 ){
this.removeChildAt(0);
}
var label:Label = new Label();
label.text = "Congradulations!";
label.x = (stage.stageWidth - label.width)/2;
label.y = (stage.stageHeight - label.height)/2;
this.addChild( label );
}
private function ballMove(ball:Object):void{
for (var i:int = 0; i < wallList.length; i++)
{
var wall:Wall = wallList[i];
var A:Vec2D = new Vec2D(ball.ball.x ,ball.ball.y );
var normScaledRadius:Vec2D = wall.normal.times(-BALL_RADIUS);
var C:Vec2D = wall.A.plus(normScaledRadius);
var D:Vec2D = wall.B.plus(normScaledRadius);
var AC:Vec2D = C.minus(A);
var dot1:Number = wall.normal.dot(AC);
//trace( dot1 );
var ballAABB:AABB = new AABB();
ballAABB.maxx = ball.ball.x + 10;
ballAABB.maxy = ball.ball.y + 10;
ballAABB.minx = ball.ball.x - 10;
ballAABB.miny = ball.ball.y - 10;
if (wall.aabb.isOverlapping(ballAABB) && dot1 <= 0 ){
wall.hit = true;
var cn:Vec2D = wall.normal;
var dv:Vec2D = new Vec2D(ball.vx,ball.vy);
var impulse:Number = cn.dot(dv.times(-2));
dv.plusEquals( cn.times( impulse ) );
//ball.ball.x += dot1 * wall.normal.x;
//ball.ball.y += dot1 * wall.normal.y;
ball.vx = dv.x;
ball.vy = dv.y;
}
}
ball.ball.x += ball.vx;
ball.ball.y += ball.vy;
}
private function drawWallHolder():void{
this.graphics.clear();
for( var i:int = 0; i < wallHolderList.length; i++ ){
var wall:Wall = wallList[i];
if( !wall.hit ){
this.graphics.lineStyle(2,0x0,.5);
}else{
this.graphics.lineStyle(2,0xFF0000,.5);
}
var holders:Array = wallHolderList[i];
var wh1:Sprite = holders[0];
var wh2:Sprite = holders[1];
wall.A.x = wh1.x;
wall.A.y = wh1.y;
wall.B.x = wh2.x;
wall.B.y = wh2.y;
wall.update();
this.graphics.moveTo(wh1.x,wh1.y);
this.graphics.lineTo(wh2.x,wh2.y);
}
}
private function enterFrame(event:Event):void{
handleCannon();
handleBallMove();
drawWallHolder();
}
}
}
class Vec2D{
public var x:Number;
public var y:Number;
public function Vec2D( x:Number = 0.0, y:Number = 0.0 )
{
this.x = x;
this.y = y;
}
public function plusEquals( vec2D:Vec2D ) : void
{
x += vec2D.x;
y += vec2D.y;
}
public function plus( vec2D:Vec2D ) : Vec2D
{
return new Vec2D( x + vec2D.x, y + vec2D.y );
}
public function minus( vec2D:Vec2D ) : Vec2D
{
return new Vec2D( x - vec2D.x, y - vec2D.y );
}
public function times( s:Number ) : Vec2D
{
return new Vec2D( x * s, y * s );
}
public function dot( vec2D:Vec2D ) : Number
{
return x * vec2D.x + y * vec2D.y;
}
public function get magnitude() : Number
{
return Math.sqrt( x * x + y * y );
}
public function normalize() : void
{
var length:Number = magnitude;
if( length == 0 ) return;
x /= length;
y /= length;
}
}
class Wall
{
public var hit:Boolean = false;
public var A:Vec2D;
public var B:Vec2D;
public var aabb:AABB;
public var normal:Vec2D;
public function Wall( ax:Number, ay:Number, bx:Number, by:Number )
{
A = new Vec2D( ax, ay );
B = new Vec2D( bx, by );
normal = new Vec2D( B.y - A.y, -( B.x - A.x ) );
normal.normalize();
aabb = new AABB();
aabb.minx = Math.min( ax, bx );
aabb.maxx = Math.max( ax, bx );
aabb.miny = Math.min( ay, by );
aabb.maxy = Math.max( ay, by );
}
public function update():void{
normal = new Vec2D( B.y - A.y, -( B.x - A.x ) );
normal.normalize();
aabb.minx = Math.min( A.x, B.x );
aabb.maxx = Math.max( A.x, B.x );
aabb.miny = Math.min( A.y, B.y );
aabb.maxy = Math.max( A.y, B.y );
}
}
class AABB
{
public var minx:Number = 0;
public var maxx:Number = 0;
public var miny:Number = 0;
public var maxy:Number = 0;
public function isOverlapping( aabb:AABB ) : Boolean
{
if( minx > aabb.maxx ) return false;
if( miny > aabb.maxy ) return false;
if( maxx < aabb.minx ) return false;
if( maxy < aabb.miny ) return false;
return true;
}
}