hit test

by wrotenodoc 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.
♥0 | Line 125 | Modified 2016-06-19 23:06:29 | MIT License
play

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 }
    
}