forked from: flash on 2010-7-3

by fakestar0826 forked from flash on 2010-7-3 (diff: 273)
衝突判定
「詳解 ActionScript 3.0 アニメーション」より
写経であーる。
♥0 | Line 238 | Modified 2010-07-08 22:31:59 | MIT License
play

ActionScript3 source code

/**
 * Copyright fakestar0826 ( http://wonderfl.net/user/fakestar0826 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/3mKn
 */

// forked from fakestar0826's flash on 2010-7-3
//衝突判定
//「詳解 ActionScript 3.0 アニメーション」より
//写経であーる。
package {
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.text.TextField;
    import flash.utils.getTimer;
    import flash.display.DisplayObject;
    
    public class FlashTest extends Sprite {
        private const GRID_SIZE:Number = 50;
        private const RADIUS:Number = 25;
        
        private var _balls:Vector.<DisplayObject>;
        private var _grid:CollisionGrid;
        private var _numBalls:int = 100;
        private var _numChecks:int = 0;
        
        public function FlashTest() {
            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;
            
            _grid = new CollisionGrid(stage.stageWidth, stage.stageHeight, GRID_SIZE);
            _grid.drawGrid(graphics);
            
            makeBalls();
            
            var startTime:int;
            var elapsed:int;
            var i:int;
            
            startTime = getTimer();
            for(i = 0;i < 10;i++)
            {
                _grid.check(_balls);
                var numChecks:int = _grid.checks.length;
                for(var j:int = 0;j < numChecks; j += 2)
                {
                    checkCollision(_grid.checks[j] as Ball, _grid.checks[j + 1] as Ball);
                }
            }
            elapsed = getTimer() - startTime;
            
            var tf:TextField = new TextField();
            tf.text = "グリッド判定時間:" + elapsed + "ms";
            tf.background = true;
            tf.backgroundColor = 0xFFFFFF;
            tf.autoSize = "left";
            tf.x = 50;
            tf.y = 440;
            tf.selectable = false;
            stage.addChild(tf);
            
        }
        
        public function makeBalls():void
        {
            _balls = new Vector.<DisplayObject>(_numBalls);
            for(var i:int = 0;i < _numBalls;i++)
            {
                var ball:Ball = new Ball(Math.random() * RADIUS);
                ball.x = Math.random() * stage.stageWidth;
                ball.y = Math.random() * stage.stageHeight;
                ball.vx = Math.random() * 4 - 2;
                ball.vy = Math.random() * 4 - 2;
                
                addChild(ball);
                _balls[i] = ball;
            }

        }
        
        public function checkCollision(ballA:Ball, ballB:Ball):void
        {
            var dx:Number = ballB.x - ballA.x;
            var dy:Number = ballB.y - ballA.y;
            var dist:Number = Math.sqrt(dx * dx + dy * dy);
            //Ball間の距離で衝突判定。
            if(dist < ballA.radius + ballB.radius)
            {
                ballA.color = 0xFF0000;
                ballB.color = 0xFF0000;
            }

        }
    }
}

import flash.display.Sprite;

class Ball extends Sprite
{
    private var _color:uint;
    private var _radius:Number;
    private var _vx:Number;
    private var _vy:Number;
    
    public function Ball(radius:Number, color:uint = 0xFFFFFF)
    {
        _radius = radius;
        _color = color;
        draw();
    }
    
    public function draw():void
    {
        graphics.clear();
        graphics.lineStyle(0);
        graphics.beginFill(_color, 0.5);
        graphics.drawCircle(0, 0, _radius);
        graphics.endFill();
        graphics.drawCircle(0, 0, 1);
    }
    
    public function update():void
    {
        x += _vx;
        y += _vy;
    }
    
    public function set color(value:uint):void
    {
        _color = value;
        draw();
    }
    
    public function get color():uint
    {
        return _color;
    }
    
    public function set radius(value:Number):void
    {
        _radius = value;
        draw();
    }
    
    public function get radius():Number
    {
        return _radius;
    }
    
    public function set vx(value:Number):void
    {
        _vx = value;
    }
    
    public function get vx():Number
    {
        return _vx;
    }
    
    public function set vy(value:Number):void
    {
        _vy = value;
    }
    
    public function get vy():Number
    {
        return _vy;
    }
}



import flash.display.DisplayObject;
import flash.display.Graphics;
import flash.events.EventDispatcher;

class CollisionGrid extends EventDispatcher
{
    private var _checks:Vector.<DisplayObject>;
    private var _grid:Vector.<Vector.<DisplayObject>>;
    private var _gridSize:Number;
    private var _height:Number;
    private var _numCells:int;
    private var _numCols:int;
    private var _numRows:int;
    private var _width:Number;
    
    public function CollisionGrid(width:Number, height:Number, gridSize:Number)
    {
        _width = width;
        _height = height;
        _gridSize = gridSize;
        _numCols = Math.ceil(_width / _gridSize);
        _numRows = Math.ceil(_height / _gridSize);
        _numCells = _numCols * _numRows;
        
    }
    
    public function drawGrid(graphics:Graphics):void
    {
        graphics.lineStyle(0, 0.5);
        for (var i:int = 0; i <= _width;i += _gridSize )
        {
            graphics.moveTo(i, 0);
            graphics.lineTo(i, _height);
        }
        for (i = 0; i <= _height;i += _gridSize )
        {
            graphics.moveTo(0, i);
            graphics.lineTo(_width, i);
        }
    }
    
    public function check(objects:Vector.<DisplayObject>):void
    {
        var numObjects:int = objects.length;
        _grid = new Vector.<Vector.<DisplayObject>>(_numCells);
        _checks = new Vector.<DisplayObject>();
        
        for (var i:int = 0; i < numObjects;i++ )
        {
            var obj:DisplayObject = objects[i];
            var index:int = Math.floor(obj.y / _gridSize) * _numCols + Math.floor(obj.x / _gridSize);
            
            if (_grid[index] == null)
            {
                _grid[index] = new Vector.<DisplayObject>;
            }
            
            _grid[index].push(obj);
        }
        
        checkGrid();
    }
    
    private function checkGrid():void
    {
        for (var i:int = 0; i < _numCols; i++ )
        {
            for (var j:int = 0; j < _numRows; j++ )
            {
                checkOneCell(i, j);
                checkTwoCell(i, j, i + 1, j);
                checkTwoCell(i, j, i - 1, j + 1);
                checkTwoCell(i, j, i, j + 1);
                checkTwoCell(i, j, i + 1, j + 1);
            }
        }
    }
    
    private function checkOneCell(x:int, y:int):void
    {
        var cell:Vector.<DisplayObject> = _grid[y * _numCols + x];
        if (cell == null) return;
        var cellLength:int = cell.length;
        
        for (var i:int; i < cellLength; i++ )
        {
            var objA:DisplayObject = cell[i];
            for (var j:int = i + 1; j <  cellLength; j++ )
            {
                var objB:DisplayObject = cell[j];
                _checks.push(objA, objB);
            }
        }
    }
    
    private function checkTwoCell(x1:int, y1:int, x2:int, y2:int):void
    {
        if (x2 >= _numCols || x2 < 0 || y2 >= _numRows) return;
        
        var cellA:Vector.<DisplayObject> = _grid[y1 * _numCols + x1];
        var cellB:Vector.<DisplayObject> = _grid[y2 * _numCols + x2];
        
        if (cellA == null || cellB == null ) return;
        
        var cellALength:int = cellA.length;
        var cellBLength:int = cellB.length;
        
        for (var i:int = 0; i < cellALength; i++ )
        {
            var objA:DisplayObject = cellA[i];
            for (var j:int = 0; j < cellBLength; j++ )
            {
                var objB:DisplayObject = cellB[j];
                _checks.push(objA, objB);
            }
        }
    }
    
    public function get checks():Vector.<DisplayObject>
    {
        return _checks;
    }
}

Forked