In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

群れの実装。壁を入れたらうまく動かない・・・

群れを実装する。
@author SIBA
Get Adobe Flash player
by siba2260 24 Feb 2009

    Tags

    AI
    Embed
package
{
	import flash.display.Sprite;
	import flash.events.Event;
	
	[SWF(width=800, height=600, backgroundColor=0xAADDFF)]

	/**
	 * 群れを実装する。
	 * @author SIBA
	 */
	public class Main02 extends Sprite
	{
		// ----------------------------
		//	メンバ変数
		// ----------------------------
		
		private var vehicles:Vector.<Vehicle> = new Vector.<Vehicle>();
		
		
		// ----------------------------
		//	初期化
		// ----------------------------
		
		public function Main02()
		{
			for (var i:int=0; i<20; i++)
			{
				var vehicle:Vehicle = new Vehicle();
				vehicle.x = Math.random()*800;
				vehicle.y = Math.random()*600;
				vehicle.rotation = Math.random()*360;
				addChild(vehicle);
				vehicles.push(vehicle);
			}
			
			addEventListener(Event.ENTER_FRAME, onEnterFrame);
		}
		
		
		// ----------------------------
		//	イベント
		// ----------------------------
		
		private function onEnterFrame(event:Event):void
		{
			for each (var vehicle:Vehicle in vehicles)
			{
				vehicle.move(vehicles);
			}
		}
		
		
	}
}

import __AS3__.vec.Vector;
import flash.display.Sprite;
import flash.text.engine.GraphicElement;
import flash.display.Graphics;
import flash.geom.Point;
	
// ------------------------------------
//	内部クラス
// ------------------------------------

/**
 * ビーグル。
 * @author SIBA
 */
class Vehicle extends Sprite
{
	// --------------------------------
	//	定数
	// --------------------------------
	
	private const SEPARATION_VIEW_AREA:Number = 96;
	private const ALIGNMENT_VIEW_AREA:Number = 128;
	private const COHESION_VIEW_AREA:Number = 128;
	private const VIEW_AREA:Number = 50;
	private const MAX_TURN_THETA:Number = 10;
	private const MAX_FOURCE:Number = 5;
	private const VIEW_AREA_THETA:Number = Math.PI/2;
	
	
	// --------------------------------
	//	メンバ変数
	// --------------------------------
	
	private var nearVehicles:Vector.<Vehicle> = new Vector.<Vehicle>();
	private var nearVehicle:Vehicle = null;
	private var velocity:Number = MAX_FOURCE;
	private var isHitWall:int = 10;
	
	
	// --------------------------------
	//	初期化
	// --------------------------------
	
	public function Vehicle():void
	{
		initDesign();
	}
	
	private function initDesign():void
	{
		const g:Graphics = graphics;
		g.beginFill(0xFF5555);
		g.moveTo(-25, -20);
		g.lineTo(25, 0);
		g.lineTo(-25, 20);
		g.lineTo(-5, 0);
		g.lineTo(-25, -20);
		g.endFill();
	}
	
	
	// --------------------------------
	//	パブリックメソッド
	// --------------------------------
	
	public function move(vehicles:Vector.<Vehicle>):void
	{
		velocity = MAX_FOURCE;
		
		if (isHitWall >= 50)
		{
			calcNearVehicle(vehicles, COHESION_VIEW_AREA);
			cohesion();
			calcNearVehicle(vehicles, ALIGNMENT_VIEW_AREA);
			alignment();
			calcNearVehicle(vehicles, SEPARATION_VIEW_AREA);
			separation();
		}
		
		hitWall();
		
		x += velocity * Math.cos(rotation/180 * Math.PI);
		y += velocity * Math.sin(rotation/180 * Math.PI);
		
		isHitWall++;
	}
	
	
	// --------------------------------
	//	内部メソッド
	// --------------------------------
	
	private function cohesion():void
	{
		if (nearVehicles.length == 0) return;
		
		var aveX:Number = 0;
		var aveY:Number = 0;
		for each (var vehicle:Vehicle in nearVehicles)
		{
			aveX += vehicle.x;
			aveY += vehicle.y;
		}
		aveX += x;
		aveY += y;
		aveX /= nearVehicles.length + 1;
		aveY /= nearVehicles.length + 1;
		
		var tempRotation:Number = Math.atan2(aveY - y, aveX - x)/Math.PI * 180;
		tempRotation -= rotation;
		if (tempRotation > 180) tempRotation -= 360;
		if (tempRotation < -180) tempRotation += 360;
		tempRotation /= 10;
		if (Math.abs(tempRotation) >= MAX_TURN_THETA) tempRotation = tempRotation < 0? -MAX_TURN_THETA : MAX_TURN_THETA;
		
		rotation += tempRotation;
	}
	
	private function alignment():void
	{
		if (nearVehicles.length == 0) return;
		
		var aveRotation:Number = 0;
		for each (var vehicle:Vehicle in nearVehicles)
		{
			aveRotation += vehicle.rotation;
		}
		aveRotation /= nearVehicles.length;
		
		var tempRotation:Number = aveRotation;
		tempRotation -= rotation;
		if (tempRotation > 180) tempRotation -= 360;
		if (tempRotation < -180) tempRotation += 360;
		tempRotation /= 10;
		if (Math.abs(tempRotation) >= MAX_TURN_THETA) tempRotation = tempRotation < 0? -MAX_TURN_THETA : MAX_TURN_THETA;
		
		rotation += tempRotation;
	}
	
	private function separation():void
	{
		if (nearVehicle == null) return;
		
		var tempRotation:Number = Math.atan2(nearVehicle.y - y, nearVehicle.x - x)/Math.PI * 180;
		tempRotation -= rotation;
		if (tempRotation > 180) tempRotation -= 360;
		if (tempRotation < -180) tempRotation += 360;
		if (Math.abs(tempRotation) >= MAX_TURN_THETA) tempRotation = tempRotation < 0? -MAX_TURN_THETA : MAX_TURN_THETA;
		if (nearVehicle.hitTestObject(this)) rotation -= tempRotation;
	}
	
	private function hitWall():void
	{
		if (x < 0)
		{
			x = 0;
			if (rotation > 0) rotation = 80;
			else rotation = -80;
			isHitWall = 0;
		}
		else if (x > 800)
		{
			x = 800;
			if (rotation > 0) rotation = 100;
			else rotation = -100;
			isHitWall = 0;
		}
		
		if (y < 0)
		{
			y = 0;
			rotation *= -1;
			isHitWall = 0;
		}
		else if (y > 600)
		{
			y = 600;
			rotation *= -1;
			isHitWall = 0;
		} 
	}
	
	private function calcNearVehicle(vehicles:Vector.<Vehicle>, viewArea:Number):void
	{
		nearVehicles.splice(0, nearVehicles.length);
	
		var nearDistance:Number = 0;
		for each (var vehicle:Vehicle in vehicles)
		{
			if (vehicle == this) continue;
			
			var viewRotation:Number = Math.atan2(vehicle.y-y, vehicle.x-x) - rotation/180*Math.PI;
			if (viewRotation > Math.PI) viewRotation -= 2*Math.PI;
			if (viewRotation < -Math.PI) viewRotation += 2*Math.PI;
			if (viewRotation < -Math.PI + VIEW_AREA_THETA || viewRotation > Math.PI - VIEW_AREA_THETA) continue;
			
			var distance:Number = (x - vehicle.x) * (x - vehicle.x) + (y - vehicle.y) * (y - vehicle.y);
			if (nearDistance == 0 || nearDistance > distance)
			{
				nearDistance = distance;
				nearVehicle = vehicle;
			}
			if (distance < viewArea * viewArea)
			{
				nearVehicles.push(vehicle);
			}
		}
	}
}