衝突判定の学習 オライリー 衝突判定の学習 Nyarineko forked:6favorite:34lines:269license : MIT License modified : 2010-05-09 23:11:10 Embed Tweet /*オライリー 衝突判定の学習*/ package { import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.display.DisplayObject; import flash.events.Event; public class GridCollision3 extends Sprite { private const GRID_SIZE:Number = 20; private var _grid_size:Number = 20; private const RADIUS:Number = 10; private var _balls:Vector.<DisplayObject>; private var _grid:CollisionGrid; private var _numBalls:int = 200; public function GridCollision3() { stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; /* _grid = new CollisionGrid(stage.stageWidth, stage.stageHeight, GRID_SIZE); _grid.drawGrid(graphics); */ //_grid_size makeBalls(); _grid = new CollisionGrid(stage.stageWidth, stage.stageHeight, _grid_size); _grid.drawGrid(graphics); addEventListener(Event.ENTER_FRAME, onEnterFrame); } private function onEnterFrame(event:Event):void { // 個々のボールについて速度を足す updateBalls(); // チェックが必要なボールを調べる _grid.check(_balls); var numChecks:int = _grid.checks.length; for (var j:int = 0; j < numChecks; j += 2) { // 2つずつ調べる checkCollision(_grid.checks[j] as Ball, _grid.checks[j + 1] as Ball); } } private function makeBalls():void { var max:Number = 0; // 全てのボールを生成する _balls = new Vector.<DisplayObject>(_numBalls); for (var i:int = 0; i < _numBalls; i++) { //var ball:Ball = new Ball(RADIUS); var ball:Ball = new Ball(Math.random() * 10 + 5); ball.x = Math.random() * stage.stageWidth; ball.y = Math.random() * stage.stageHeight; ball.vx = Math.random() * 4 - 2; ball.vy = Math.random() * 4 - 2; if(ball.radius > max) max = ball.radius; addChild(ball); _balls[i] = ball; } _grid_size = max*2; } private function updateBalls():void { for (var i:int = 0; i < _numBalls; i++) { // ボールを移動し、壁に跳ね返らせる var ball:Ball = _balls[i] as Ball; ball.update(); if (ball.x < RADIUS) { ball.x = RADIUS; ball.vx *= -1; } else if (ball.x > stage.stageWidth - RADIUS) { ball.x = stage.stageWidth - RADIUS; ball.vx *= -1; } if (ball.y < RADIUS) { ball.y = RADIUS; ball.vy *= -1; } else if (ball.y > stage.stageHeight - RADIUS) { ball.y = stage.stageHeight - RADIUS; ball.vy *= -1; } ball.color = 0xffffff; } } private function checkCollision(ballA:Ball, ballB:Ball):void { // 2つのボールの衝突判定を行う var dx:Number = ballB.x - ballA.x; var dy:Number = ballB.y - ballA.y; var dist:Number = Math.sqrt(dx * dx + dy * dy); 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 = 0; private var _vy:Number = 0; public function Ball(radius:Number, color:uint = 0xffffff) { _radius = radius; _color = color; draw(); } private function draw():void { // 中心に点のある円を描く graphics.clear(); graphics.lineStyle(0); graphics.beginFill(_color, .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, .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]; // 1次元の格子中の位置を表す配列の添え字を // 計算する var index:int = Math.floor(obj.y / _gridSize) * _numCols + Math.floor(obj.x / _gridSize); // iにオブジェクトがなければ、格子を生成する 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); 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); // 右下 } } } private function checkOneCell(x:int, y:int):void { // (x, y)で表される格子を得る var cell:Vector.<DisplayObject> = _grid[y * _numCols + x]; if (cell == null) return; // 格子中のオブジェクトの個数 var cellLength:int = cell.length; // 全てのオブジェクトを互いに比較する for (var i:int = 0; i < cellLength - 1; 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 checkTwoCells(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; } } Code Fullscreen Preview Fullscreen alwAYs ditch_up savage69kr Evolutor merrycat ninehundred tkinjo zendenmushi asou_jp OKASUKE yoshimax nogud nki2 alumican_net.. clockmaker t_matsuda paq skn code zotin95 smakhtin siouxcitizen.. djankey arkcocco : 衝突判定 aobyrne : collisioncollisionGriddetectiongrid Miya : 衝突判定 postnum : 衝突判定 korooooon : 衝突判定 Seb.Tisluta : collisionGridsimple collision grid fans8 : 碰撞检测 a440hlz : beautifl衝突判定 hacker_5gyk6.. : Really nice collision code Wolfe : collisiondetectionradial goliatone : collisiongrid,Simple Grid Collision beautifl collision collisionGrid detection grid grid, radial 碰撞检测 衝突判定 Math.max Math.ceil addEventListener drawCircle EventDispatcher Vector moveTo Math.floor lineTo lineStyle clear push Math.sqrt endFill beginFill length Math.random uint int Number sort new page view favorite forked pv370 forked from: 衝突判定の学習 + 水滴 ile forked:0 favorite:0lines:321 (diff:114) pv262 forked from: 衝突判定の学習 hacker_5gyk6jxu forked:0 favorite:0lines:269 (diff:1) pv250 forked from: 衝突判定の学習 hacker_5gyk6jxu forked:0 favorite:0lines:269 (diff:5) pv209 forked from: 衝突判定の学習 urasuwa forked:0 favorite:0lines:269 (diff:4) pv0 forked from: 衝突判定の学習 urasuwa forked:0 favorite:0lines:269 (diff:1) pv332 forked from: 衝突判定の学習 Geo877 forked:0 favorite:0lines:286 (diff:23)