トップページ > ゲーム制作 > 操舵行動 > 操舵行動 - 経路追従行動



概要

経路追従行動は指定した経路に沿ってオブジェクトを動作させます。
具体的には、位置を表すポイントを複数指定すると、オブジェクトがそれらのポイントを順番に訪れるというものです。


プログラム

public var pathIndex:int = 0;
public var pathThreshold:Number = 10;
 
public function followPath(path:Vector.<Vector2D>, loop:Boolean = false):void
{
	try
	{
		var wayPoint:Vector2D = path[pathIndex];
	}
	catch (e:Error) { }
	if (wayPoint == null)
	{
		velocity = Vector2D.ZERO;
		return;
	}
	if (wayPoint.distance(position) < pathThreshold)
	{
		if (loop && pathIndex >= path.length - 1)
		{
			pathIndex = 0;
		}
		else
		{
			pathIndex++;
		}
	}
 
	if (!loop && pathIndex >= path.length - 1)
	{
		arrive(wayPoint.clone());
	}
	else
	{
		seek(wayPoint.clone());
	}
}
 


public function followPath(path:Vector.<Vector2D>, loop:Boolean = false):void
 
Vector2Dで表したポイントが入ったVectorと、ループして延々と追従させるかどうかを決めるBoolean型変数を受け取ります。


try
{
	var wayPoint:Vector2D = path[pathIndex];
}
catch (e:Error) { }
 
現在の目標位置をpathから取り出します。
pathのインデックスはpathIndex変数が管理をしています。
Vectorの範囲外にアクセスしても問題が起こらないように、try~catch文で囲っておきます。


if (wayPoint == null)
{
	velocity = Vector2D.ZERO;
	return;
}
 
取り出したポイントがnullなら速度を(0, 0)にして停止させます。


if (wayPoint.distance(position) < pathThreshold)
{
	if (loop && pathIndex >= path.length - 1)
	{
		pathIndex = 0;
	}
	else
	{
		pathIndex++;
	}
}
 
実際には各ポイントごとに停止するわけではないので、ある程度目標のポイントに近づくと次のポイントへ向かわせるようにします。
その"ある程度"の距離がpathThresholdで、その距離よりも近い地点まで来たら、次のポイントへ移動するためpathIndexの値を一つ増やします。
ループ対応の場合は、最後のポイントまで来たら、最初のポイントであるpath[0]に向かわせるため、pathIndexの値を0に戻します。


if (!loop && pathIndex >= path.length - 1)
{
	arrive(wayPoint.clone());
}
else
{
	seek(wayPoint.clone());
}
 
ループしない場合で最後のポイントに向かうときは到着行動でゆっくりと減速させます。
それ以外は追求行動で普通に移動させます。


実行結果

flash on 2011-10-29 - wonderfl build flash online


package
{
	import flash.display.Sprite;
	import flash.events.Event;
 
	public class Main extends Sprite
	{
		private var vehicles:Vector.<SteeredVehicle> = new Vector.<SteeredVehicle>();
		private var path:Vector.<Vector2D> = new Vector.<Vector2D>();
 
		public function Main()
		{
			vehicles.push(addChild(new SteeredVehicle(230, 230)));
			vehicles.push(addChild(new SteeredVehicle(230, 230)));
			for each (var vehicle:Vehicle in vehicles)
			{
				vehicle.edgeBehavior = Vehicle.BOUNCE;
			}
			vehicles[1].maxSpeed = 5.0;
			path.push(new Vector2D(20, 40), new Vector2D(100, 200), new Vector2D(60, 400), new Vector2D(370, 370), new Vector2D(232, 232), new Vector2D(400, 10), new Vector2D(20, 40));
			drawPath(path);
			addEventListener(Event.ENTER_FRAME, onEnterFrame);
		}
 
		public function drawPath(vec:Vector.<Vector2D>):void
		{
			graphics.lineStyle(2.0);
			graphics.moveTo(vec[0].x, vec[0].y);
			for each (var point:Vector2D in vec)
			{
				graphics.lineTo(point.x, point.y);
			}
		}
 
		private function onEnterFrame(event:Event):void 
		{	
			vehicles[0].followPath(path, true);
			vehicles[1].followPath(path);
			for each (var vehicle:SteeredVehicle in vehicles)
			{
				vehicle.update();
			}
		}
	}
}
 


ソースコード


|新しいページ|検索|ページ一覧|RSS|@ウィキご利用ガイド | 管理者にお問合せ
|ログイン|
添付ファイル