forked from: Gravity - revamped in faux 3D
// forked from antalg's Gravity - revamped in faux 3D
package {
import flash.net.*;
import flash.events.KeyboardEvent;
import flash.filters.ConvolutionFilter;
import flash.filters.ColorMatrixFilter;
import flash.filters.BlurFilter;
import flash.geom.Matrix;
import flash.ui.Mouse;
import flash.geom.Point;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.display.AVM1Movie;
import flash.display.Sprite;
public class FlashTest extends Sprite {
public function FlashTest() {
addChild(new Bitmap(_bmd));
for each (var p:Point in start) {
placeWell(p, 10000);
}
addChild(_miniMap);
_miniMap.x = 465-MMSIZE-10;
_miniMap.y = 5;
addChild(_lineSpr);
spawnRandomBalls(100);
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseD);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseU);
stage.addEventListener(Event.ENTER_FRAME, onEF);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
}
private function placeWell(p:Point, str:int) :void {
var spr:Sprite = new Sprite();
spr.graphics.beginFill(0xFFFFFF);
spr.graphics.drawCircle(0, 0, SPRWELLSIZE-RAD);
spr.graphics.endFill();
addChild(spr);
spr.x = p.x;
spr.y = toDispCoords(p.y);
spr.addEventListener(MouseEvent.MOUSE_DOWN, dragWell);
spr.addEventListener(MouseEvent.MOUSE_UP, dropWell);
wells.push({sprite:spr, strength:str, realX:p.x, realY:p.y});
}
private function spawnRandomBalls(count:int) :void{
var i:int;
var v:Number = 10;
for(i=0; i<count; i++) {
var x:Number = RAD+Math.random()*(stage.stageWidth-2*RAD);
var y:Number = RAD+Math.random()*(stage.stageHeight-2*RAD);
var angle:Number = 2*Math.PI*Math.random();
spawnBall(x, y, v*Math.cos(angle), v*Math.sin(angle));
}
}
private function spawnBall(X:Number, Y:Number, VX:Number, VY:Number):void {
var myBall:Ball = new Ball(X, Y, VX, VY);
addChild(myBall);
_balls.push(myBall);
}
private var _miniMap:Sprite = new Sprite();
private const MMSIZE:int = 100;
private var mouseV:Point = new Point();
private var lastMousePos:Point = new Point();
private var _center:Point = new Point(stage.stageWidth/2, stage.stageHeight/2);
private var _lineSpr:Sprite = new Sprite();
private const RAD:Number = 10;
private const SPRWELLSIZE:Number = 30;
private const WELLSIZE:Number = SPRWELLSIZE*SPRWELLSIZE;
private var start:Array = [_center]; // startpoints
private var wells:Array = new Array(); // sprites
private var _bmd:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0x000000);
private var _balls:Array = new Array();
private var mD:Boolean = true;
private function dragWell(e:MouseEvent):void {
mD = true;
(e.target as Sprite).startDrag(true);
}
private function dropWell(e:MouseEvent):void {
mD = false;
(e.target as Sprite).stopDrag();
}
private function onKeyDown(e:KeyboardEvent):void {
if(e.keyCode == 32) {
clearBalls();
}
}
private function mouseD(e:MouseEvent):void {
spawnBall(stage.mouseX, stage.mouseY, mouseV.x, mouseV.y);
}
private function mouseU(e:MouseEvent):void {
}
private function onEF(e:Event):void {
mouseSpeed();
move();
//bounds();
gravity();
bmdFilters();
updateWellPos();
}
private function mouseSpeed():void {
mouseV.x = (mouseV.x + stage.mouseX-lastMousePos.x)/2;
mouseV.y = (mouseV.y + stage.mouseY-lastMousePos.y)/2;
lastMousePos.x = stage.mouseX;
lastMousePos.y = stage.mouseY;
Mouse.hide();
_lineSpr.x = stage.mouseX;
_lineSpr.y = stage.mouseY;
_lineSpr.graphics.clear();
_lineSpr.graphics.lineStyle(1,0xFFFFFF);
_lineSpr.graphics.moveTo(0,0);
_lineSpr.graphics.lineTo(-mouseV.x<<1, -mouseV.y<<1);
}
private function move():void {
var i:int;
for(i=0; i<_balls.length; i++) {
for each (var p:Object in wells){
var sq:Number = distSq(_balls[i], p);
if(sq<WELLSIZE || sq>64000000) {
removeChild(_balls[i]);
_balls.splice(i,1);
return;
}
}
_balls[i].realX += _balls[i].vx;
_balls[i].realY += _balls[i].vy;
_balls[i].x = _balls[i].realX;
_balls[i].y = toDispCoords(_balls[i].realY);
_balls[i].scaleX = _balls[i].scaleY = toDispScale(_balls[i].realY);
if(_balls[i].realY<wells[0].realY && wells[0].sprite.hitTestObject(_balls[i])) {
_balls[i].visible = false;
} else {
_balls[i].visible = true;
}
_bmd.setPixel(_balls[i].x, _balls[i].y , 0xFFFFFF);
}
}
private function gravity():void {
for each (var p:Object in wells) {
var i:int;
for(i=0; i<_balls.length; i++) {
var dx:Number = p.realX-_balls[i].realX;
var dy:Number = p.realY-_balls[i].realY;
var rSq:Number = dx*dx+dy*dy;
var angle:Number = Math.atan2(dy,dx);
var f:Number = p.strength*_balls[i].mass/rSq;
_balls[i].vx += Math.cos(angle)*f/_balls[i].mass; // fx = Math.cos(angle)*f
_balls[i].vy += Math.sin(angle)*f/_balls[i].mass; // fy = Math.sin(angle)*f
}
}
}
private var cmf:ColorMatrixFilter = new ColorMatrixFilter( [ 1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 0.95, 0]);
private function bmdFilters():void {
_bmd.applyFilter(_bmd, _bmd.rect, new Point(0,0), cmf);
}
private function updateWellPos():void {
for each (var p:Object in wells) {
p.realX = p.sprite.x;
p.realY = toRealCoords(p.sprite.y);
p.sprite.scaleX = p.sprite.scaleY = toDispScale(p.realY);
}
drawMiniMap();
}
private function drawMiniMap():void {
_miniMap.graphics.clear();
_miniMap.graphics.lineStyle(1, 0xFFFFFF);
_miniMap.graphics.beginFill(0xFFFFFF, 0.1);
_miniMap.graphics.drawRect(0, 0, MMSIZE, MMSIZE);
_miniMap.graphics.endFill();
_miniMap.graphics.drawCircle(wells[0].realX/465*MMSIZE, wells[0].realY/465*MMSIZE, 3);
for each (var b:Ball in _balls) {
if(b.realX>=0 && b.realX<465 && b.realY>=0 && b.realY<465) {
_miniMap.graphics.drawCircle(b.realX/465*MMSIZE, b.realY/465*MMSIZE, 1);
}
}
_miniMap.graphics.lineStyle(1,0xFF0000);
_miniMap.graphics.drawCircle(stage.mouseX/465*MMSIZE, stage.mouseY/465*MMSIZE, 1);
}
private function bounds():void {
var i:int;
for(i=0; i<_balls.length; i++) {
if(_balls[i].realX<RAD || _balls[i].realX>stage.stageWidth-RAD) {
_balls[i].vx *= -1;
_balls[i].realX += _balls[i].vx;
}
if(_balls[i].realY<RAD || _balls[i].realY>stage.stageHeight-RAD) {
_balls[i].vy *= -1;
_balls[i].realY += _balls[i].vy;
}
}
}
private function distSq(ball:Ball, well:Object):Number {
var dx:Number = well.realX - (ball.realX + ball.vx);
var dy:Number = well.realY - (ball.realY + ball.vy);
return dx*dx+dy*dy;
}
private function clearBalls():void {
for(var i:int = 0; i<_balls.length; i++) {
removeChild(_balls[i]);
}
_balls = new Array();
}
private function toDispCoords(y:Number):Number {
return (y/465-0.5)*70+232;
}
private function toRealCoords(y:Number):Number {
return 465*((y-232)/70+0.5);
}
private function toDispScale(y:Number):Number {
y = y/500+1;
return y>.05?y:.05;
}
}
}
import flash.geom.Point;
import flash.display.Sprite;
class Ball extends Sprite{
public function Ball(X:Number, Y:Number, VX:Number, VY:Number) {
createGraphics();
realX = X;
realY = Y;
//x = X;
//y = Y;
vx = VX;
vy = VY;
mass = 100;
}
public var realX:Number;
public var realY:Number;
public var mass:Number;
public var vx:Number;
public var vy:Number;
private const RADIUS:Number = 5;
private function createGraphics():void {
var r1:int = Math.random()*255;
var r2:int = (255-r1) - Math.random()*(255-r1);
var r3:int = 255-r1-r2;
this.graphics.beginFill((r1<<16)|(r2<<8)|r3);
this.graphics.drawCircle(0,0,RADIUS);
this.graphics.endFill();
}
}