スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

--.--.-- | | スポンサー広告

直線ぽくフォーカスを移動する

フォーカスをタイル上で直線ぽく移動させます。




























Adobe Flash Player を取得






ステージ上で、タイルをクリックすると、クリックした位置にフォーカスが移動します。
フォーカスは2つあって、は単純な移動、は移動開始位置からクリック位置まで引いた直線に近い経路をたどります。

は、列/行それぞれクリック位置に近づくように1タイルずつ移動します。
結果として、行か列が等しくなるまでナナメに進んで、あとは横or縦移動します。

は、元いた位置からクリック位置までの直線に沿うようにタイル上を移動します。

今回のサンプルも、第一フレームのアクションとして記述しています。

// 行数
var rowCnt:uint = 20;
// 列数
var colCnt:uint = 30;
// タイルのサイズ
var tileSize:Number = 16;
// タイルを生成する
setupTile();
// 目標列
var targetCol:uint = 0;
// 目標行
var targetRow:uint = 0;
// 素朴な移動をするフォーカスを生成する
var simpleFocus:Sprite = new Sprite();
simpleFocus.graphics.lineStyle(0, 0x0000FF);
simpleFocus.graphics.drawCircle(tileSize / 2, tileSize / 2, tileSize / 2);
simpleFocus.addEventListener(Event.ENTER_FRAME,
function (e:Event):void {
// 現在の列インデックスと行インデックスを取得する
var col:uint = getColIndex(simpleFocus.x);
var row:uint = getRowIndex(simpleFocus.y);
// 目標地点であったら何もしない
if (col == targetCol && row == targetRow) {
return;
}
// 列を目標地点に近づける
if (col > targetCol) {
simpleFocus.x = getX(col - 1);
} else if (col < targetCol) {
simpleFocus.x = getX(col + 1);
}
// 行を目標地点に近づける
if (row > targetRow) {
simpleFocus.y = getY(row - 1);
} else if (row < targetRow) {
simpleFocus.y = getY(row + 1);
}
});
addChild(simpleFocus);
// ブレゼンハムのアルゴリズムで移動するフォーカスを生成する
var bresenhamPath:Array = [];
var bresenhamIdx:uint = 0;
var bresenhamFocus:Sprite = new Sprite();
bresenhamFocus.graphics.lineStyle(0, 0xFF0000);
bresenhamFocus.graphics.drawCircle(tileSize / 2, tileSize / 2, tileSize / 2);
bresenhamFocus.addEventListener(Event.ENTER_FRAME,
function (e:Event):void {
// 移動先の経路がなければ何もしない
if (bresenhamIdx >= bresenhamPath.length) {
return;
}
// 移動する
var nextObj:Object = bresenhamPath[bresenhamIdx];
bresenhamFocus.x = getX(nextObj.col);
bresenhamFocus.y = getY(nextObj.row);
// 経路を勧める
bresenhamIdx++;
});
addChild(bresenhamFocus);

// ブレゼンハムのアルゴリズムで経路を算出する
function bresenham(startCol:uint, startRow:uint):Array {
// 結果を保持する配列を準備する
var ary:Array = [];
// 列の距離、行の距離を算出する
var dCol:int = Math.abs(targetCol - startCol);
var dRow:int = Math.abs(targetRow - startRow);
// 列、行の移動方向を決定する
var stepCol:int = targetCol - startCol > 0 ? 1 : -1;
var stepRow:int = targetRow - startRow > 0 ? 1 : -1;
// 列と行のどちらの移動距離が多いかによって場合分けする
var e:Number;
var col:uint = startCol;
var row:uint = startRow;
var dCol2:int = dCol * 2;
var dRow2:int = dRow * 2;
if (dCol >= dRow) {
// 列方向が遠い場合は、列移動しながら必要に応じて行を移動する
e = dCol;
// 目的地まで進む
while (col != targetCol) {
col += stepCol;
e += dRow2;
if (e >= dCol2) {
e -= dCol2;
row += stepRow;
}
ary.push({col:col, row:row});
}
} else {
// 行方向が遠い場合は、行移動しながら必要に応じて列を移動する
e = dRow;
// 目的地まで進む
while (row != targetRow) {
row += stepRow;
e += dCol2;
if (e >= dRow2) {
e -= dRow2;
col += stepCol;
}
ary.push({col:col, row:row});
}
}
return ary;
}

// タイルを生成する
function setupTile() {
for (var rowIdx:int = 0; rowIdx < rowCnt; rowIdx++) {
for (var colIdx:int = 0; colIdx < colCnt; colIdx++) {
var tile:Sprite = new Sprite();
tile.graphics.moveTo(0, 0);
tile.graphics.beginFill(0xCCCCCC);
tile.graphics.drawRect(0, 0, tileSize, tileSize);
tile.graphics.endFill();
tile.graphics.beginFill(0x00CC00);
tile.graphics.drawRect(1, 1, tileSize - 2, tileSize - 2);
tile.graphics.endFill();
tile.x = colIdx * tileSize;
tile.y = rowIdx * tileSize;
tile.addEventListener(MouseEvent.CLICK,
function (e:Event):void {
var clickCol = getColIndex(mouseX);
var clickRow = getRowIndex(mouseY);
// 目的タイルが変わらなければ何もしない
if (clickRow == targetRow && clickCol == targetCol) {
return;
}
targetCol = getColIndex(mouseX);
targetRow = getRowIndex(mouseY);
// 経路を求める
bresenhamPath = bresenham(getColIndex(bresenhamFocus.x), getRowIndex(bresenhamFocus.y));
bresenhamIdx = 0;
});
addChild(tile);
}
}
}

// 列インデックスを戻します。
function getColIndex(x:Number):uint {
return x / tileSize;
}
// 行インデックスを戻します。
function getRowIndex(y:Number):uint {
return y / tileSize;
}
// x座標を戻します。
function getX(col:uint):Number {
return col * tileSize;
}
// y座標を戻します。
function getY(row:uint):Number {
return row * tileSize;
}


最初にタイルを生成して並べています。
setupTile()メソッドが実際にタイルを生成している部分で、規定の数だけSpriteオブジェクトを作っています。

それぞれのタイルはマウスクリックイベントリスナを登録してあってクリックしたら自身が目的地となるようにtargetCol, targetRowを更新しています。
また、の移動用に経路を生成しています。

simpleFocusはで表現されるフォーカスです。
コイツは、単純に現在位置と目的位置から移動先を決定しています。

bresenhamFocusはで表現されるフォーカスで、bresenhamPath配列で示される経路どおりに移動します。

bresenhamPath配列はどうしてるのかというと、タイルをクリックしたときにbresenham(uint, uint)メソッドが実行され、そこで生成されます。
メソッドパラメータは移動の開始位置(列、行)です。

bresenham(uint, uint)メソッドは、ブレゼンハムのアルゴリズムという直線を描画するためのアルゴリズムを利用して経路を生成しています。
行方向と列方向の移動量のどちらが多いかで場合分けしていますが、内容は基本的には同じです。
たとえば列方向の移動が多い場合は、列を1ずつ移動しながら直線の傾きに相当(2 × dx倍)する分変数を加算し、変数が1マス相当(2 × dx倍)に達したら行を1つ移動する。というカンジです。たぶん。
こうやって取得した座標を配列にセットしておいて、実際の移動は配列の中身を順次使用します。
スポンサーサイト

テーマ:Flash - ジャンル:コンピュータ

2010.10.13 | | Comments(0) | Trackback(0) | Flash CS5

«  | HOME |  »

プロフィール

HundredthMonkey

Author:HundredthMonkey
プログラマ。

ブロとも申請フォーム

この人とブロともになる

メールフォーム

名前:
メール:
件名:
本文:

ブログ内検索


上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。