flash on 2010-7-3
衝突判定
「詳解 ActionScript 3.0 アニメーション」より
写経であーる。
♥0 |
Line 234 |
Modified 2010-07-03 13:05:10 |
MIT License
archived:2017-03-20 07:47:14
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/hAcw
*/
//衝突判定
//「詳解 ActionScript 3.0 アニメーション」より
//写経であーる。
package {
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.text.TextField;
import flash.utils.getTimer;
public class FlashTest extends Sprite {
private const GRID_SIZE:Number = 50;
private const RADIUS:Number = 25;
private var _balls:Array;
private var _grid:Array;
private var _numBalls:int = 100;
private var _numChecks:int = 0;
public function FlashTest() {
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
makeBalls();
drawGrid();
var startTime:int;
var elapsed:int;
var i:int;
startTime = getTimer();
for(i = 0;i < 10;i++)
{
makeGrid();
AssignBallsToGrid();
checkGrid();
}
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);
startTime = getTimer();
for(i = 0;i < 10;i++)
{
basicCheck();
}
elapsed = getTimer() - startTime;
var tf2:TextField = new TextField();
tf2.text = "通常判定時間:" + elapsed + "ms";
tf2.background = true;
tf2.backgroundColor = 0xFFFFFF;
tf2.autoSize = "left";
tf2.x = 250;
tf2.y = 440;
tf2.selectable = false;
stage.addChild(tf2);
}
public function makeBalls():void
{
_balls = new Array();
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;
addChild(ball);
_balls.push(ball);
}
}
public function makeGrid():void
{
_grid = new Array();
for(var i:int = 0;i < stage.stageWidth / GRID_SIZE;i++)
{
_grid[i] = new Array();
for(var j:int = 0;j < stage.stageHeight / GRID_SIZE;j++)
{
_grid[i][j] = new Array();
}
}
}
public function drawGrid():void
{
graphics.lineStyle(0, 0.5);
for(var i:int = 0;i <= stage.stageWidth;i += GRID_SIZE)
{
graphics.moveTo(i, 0);
graphics.lineTo(i, stage.stageHeight);
}
for(i = 0;i <= stage.stageHeight;i += GRID_SIZE)
{
graphics.moveTo(0, i);
graphics.lineTo(stage.stageWidth, i);
}
}
public function AssignBallsToGrid():void
{
for(var i:int = 0;i < _numBalls;i++)
{
var ball:Ball = _balls[i] as Ball;
//ここで、ひとつのグリッドに2個以上のBallが入る場合がある。
//また、ひとつもBallが入ってない場合もある。
var xpos:int = Math.floor(ball.x / GRID_SIZE);
var ypos:int = Math.floor(ball.y / GRID_SIZE);
_grid[xpos][ypos].push(ball);
}
}
public function checkGrid():void
{
for(var i:int = 0;i < _grid.length;i++)
{
for(var j:int = 0;j < _grid[i].length;j++)
{
//グリッド内でのチェック
checkOneCell(i, j);
//隣接するグリッド間のチェック
checkTwoCells(i, j, i + 1, j);
checkTwoCells(i, j, i - 1, j + 1);
checkTwoCells(i, j, i, j + 1);
checkTwoCells(i, j, i + 1, j + 1);
}
}
}
public function checkOneCell(x:int, y:int):void
{
var cell:Array = _grid[x][y] as Array;
//グリッド内のBallを引き出し、衝突判定メソッドを呼び出す。
for(var i:int = 0;i < cell.length - 1;i++)
{
var ballA:Ball = cell[i] as Ball;
for(var j:int = i + 1;j < cell.length;j++)
{
var ballB:Ball = cell[j] as Ball;
checkCollision(ballA, ballB);
}
}
}
public function checkTwoCells(x1:int, y1:int, x2:int, y2:int):void
{
if(x2 < 0) return;
if(x2 >= _grid.length) return;
if(y2 >= _grid[x2].length) return;
var cell0:Array = _grid[x1][y1] as Array;
var cell1:Array = _grid[x2][y2] as Array;
//グリッド内のBallを引き出し、衝突判定メソッドを呼び出す。
for(var i:int = 0;i < cell0.length;i++)
{
var ballA:Ball = cell0[i] as Ball;
for(var j:int = 0;j < cell1.length;j++)
{
var ballB:Ball = cell1[j] as Ball;
checkCollision(ballA, ballB);
}
}
}
public function checkCollision(ballA:Ball, ballB:Ball):void
{
_numChecks++;
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;
}
}
public function basicCheck():void
{
for(var i:int = 0;i < _balls.length - 1;i++)
{
var ballA:Ball = _balls[i] as Ball;
for(var j:int = i + 1;j < _balls.length;j++)
{
var ballB:Ball = _balls[j] as Ball;
checkCollision(ballA, ballB);
}
}
}
}
}
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;
}
}