hit test
forked from stack (diff: 98)
move: arrow keys buggy behavior with the ground (which is of infinite mass) setting the mass of the ground to a very large number, like 1000000000, doesn't solve the problem.
ActionScript3 source code
/**
* Copyright wrotenodoc ( http://wonderfl.net/user/wrotenodoc )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/s7GD
*/
// forked from wrotenodoc's stack
package {
import flash.events.KeyboardEvent;
import flash.geom.Point;
import flash.ui.Keyboard
import flash.events.Event;
import flash.display.Sprite;
public class FlashTest extends Sprite {
private var _agents:Array = []
private var _player:Agent
private var _keyStates:Object = {}
private var _worldWidth:Number, _worldHeight:Number
public function FlashTest() {
_worldWidth = stage.stageWidth
_worldHeight = 400 //stage.stageHeight
// write as3 code here..
graphics.lineStyle(2, 0x0)
graphics.moveTo(0, _worldHeight)
graphics.lineTo(_worldWidth, _worldHeight)
graphics.lineStyle()
// obstacles
var agent:Agent
for(var i:int=0; i<150; i++){
agent = new Agent(10, 10)
agent.x = 50 + Math.random() * 300
agent.y = 50 + Math.random() * 200
addChild(agent)
_agents.push(agent)
}
// ground
agent = new Agent(_worldWidth, 20)
agent.y = _worldHeight - 20
agent.mass = Infinity
_agents.push(agent)
addChild(agent)
// player
_player = new Agent(20, 20)
_agents.push(_player)
addChild(_player)
addEventListener("enterFrame", loop)
stage.addEventListener("keyDown", keydown)
stage.addEventListener("keyUp", keyup)
}
private function keydown(e:KeyboardEvent):void {
_keyStates[e.keyCode] = true
}
private function keyup(e:KeyboardEvent):void {
_keyStates[e.keyCode] = false
}
private function isDown(keyCode:uint):Boolean {
return _keyStates[keyCode] == true
}
private function loop(e:Event):void {
var vx:Number = 0, vy:Number = 0
if(isDown(Keyboard.LEFT)) vx = -5
else if(isDown(Keyboard.RIGHT)) vx = 5
if(isDown(Keyboard.UP)) vy = -5
else if(isDown(Keyboard.DOWN)) vy = 5
_player.setVel(vx, vy)
for each(var a:Agent in _agents) a.integrate()
for(var i:int=0; i<10; i++) constraints()
}
private function constraints():void {
for(var i:int=0; i<_agents.length; i++){
for(var j:int=i+1; j<_agents.length; j++){
push(_agents[i], _agents[j])
}
}
}
private function push(a:Agent, b:Agent):void {
if(a.hitTestObject(b)){
var dx:Number, dy:Number, d:Number
dx = a.x - b.x
dy = a.y - b.y
d = Math.sqrt(dx*dx + dy*dy)
dx /= d ; dy /= d
var a_scale:Number, b_scale:Number
// buggy behavior with an object of infinite mass
if(a.mass == Infinity && b.mass == Infinity){
return
}else if(a.mass == Infinity){
a_scale = 0
b_scale = 1
dx *= b.vx
dy *= b.vy
}else if(b.mass == Infinity){
a_scale = 1
b_scale = 0
dx *= a.vx
dy *= a.vy
}else{
a_scale = b.mass / (a.mass + b.mass)
b_scale = a.mass / (a.mass + b.mass)
}
a.x += dx * a_scale
b.x -= dx * b_scale
a.y += dy * a_scale
b.y -= dy * b_scale
}
}
}
}
// outside of package //
import flash.display.Sprite;
class Agent extends Sprite {
private var _width:Number, _height:Number
private var _vx:Number = 0, _vy:Number = 0
private var _ax:Number = 0, _ay:Number = 0
public var mass:Number = 1
public function Agent(w:Number, h:Number) {
graphics.beginFill(Math.random() * 0xffffff)
graphics.drawRect(0, 0, w, h)
_width = w
_height = h
}
public function setVel(vx:Number, vy:Number):void {
_vx = vx ; _vy = vy
}
public function setAccel(ax:Number, ay:Number):void {
_ax = ax ; _ay = ay
}
public function integrate():void {
_vx += _ax
_vy += _ay
x += _vx
y += _vy
}
public function get right():Number { return x + _width }
public function get bottom():Number { return y + _height }
public function get vx():Number { return _vx }
public function get vy():Number { return _vy }
}
