AI講座・上級編~第1回:コマンド入力を実装する~
【重要】新しいBlogに移転しています:あるネットゲーマーの日常
2006年04月25日 (火)
今回からは不定期に、私が改造を加えたAIを紹介していきます
第1回はホムAIスレからヒントを得て、
「コマンド入力」でホムの動きを制御するやり方を紹介します
これを使うことで、一つのAIで
先攻・非先攻の切り替えが可能になったりします
ぜひ応用して試してみてください
第1回はホムAIスレからヒントを得て、
「コマンド入力」でホムの動きを制御するやり方を紹介します
これを使うことで、一つのAIで
先攻・非先攻の切り替えが可能になったりします
ぜひ応用して試してみてください
スポンサーサイト
Open↓
~3章~ ちょっと難しい改造
3-1:スイッチを入れてみよう
今回から改造内容が複雑になるので、
先にAIを公開しておきます
AI 2006/04/25版
保存して、「AI.lua」に名前を変えればそのまま動きます
さて、具体的にどのように「コマンド」を実装するか、ですが、
「右左右」のように、ホムが特定の動きをしたとき、
スイッチが入るようにしてみます
例えば、ホムを以下のように動かした時、
何らかのスイッチが切り替わるようにするわけです
具体的な判別方法ですが、
主人の座標とホムの移動先を比較すれば、
「コマンド」であるかを判別できます
具体的なコードは以下の通りです
------------------------------------------
-- mode flag
------------------------------------------
MODE_ACTIVE = 0 -- 先攻モード
MODE_NONACTIVE = 1 -- 非先攻モード
MyActiveMode = MODE_NONACTIVE -- 先攻モードフラグ
ActiveModeCounter = 0 -- コマンドカウンター
------------------------------------------
function OnMOVE_CMD (x,y)
TraceAI ("OnMOVE_CMD")
(中略)
Move (MyID,x,y)
MyState = MOVE_CMD_ST
MyDestX = x
MyDestY = y
MyEnemy = 0
MySkill = 0
CheckMoveCommand()
end
function CheckMoveCommand()
local ownerX, ownerY
ownerX, ownerY = GetV (V_POSITION,GetV(V_OWNER,MyID)) -- 主人の座標
-- 先攻・非先攻切り替え
if (MyDestY == ownerY) then
if (ActiveModeCounter == 0 and MyDestX == ownerX+1) then -- 右
ActiveModeCounter = 1
elseif (ActiveModeCounter == 1 and MyDestX == ownerX-1) then -- 左
ActiveModeCounter = 2
elseif (ActiveModeCounter == 2 and MyDestX == ownerX+1) then -- 右
ActiveModeCounter = 0
if (MyActiveMode == MODE_NONACTIVE) then -- 先攻切り替え
MyActiveMode = MODE_ACTIVE
else
MyActiveMode = MODE_NONACTIVE
end
else
ActiveModeCounter = 0
end
else
ActiveModeCounter = 0
end
end
CheckMoveCommandという関数がスイッチを判定する核となるところです
デフォルトAIのOnMOVE_CMD関数の最後にこの判定スイッチを入れることで、
移動がコマンドに沿ったものであるかを判断できるわけです
続いて核となるCheckMoveCommandですが、
まず主人の座標を取得しています
その上で、移動先が主人の右ならカウント+1、
カウント1で主人の左ならカウント2・・・のようにして、
「右左右」の動きが完成したところで、MyActiveModeフラグを入れ替えています
で、実際にMyActiveModeフラグをどう使っているかというと・・・
function GetMyEnemy (myid)
(中略)
-- 他の敵を探す
if (get_flg == 0 and MyActiveMode == MODE_ACTIVE) then
-- 自分を攻撃する敵がいない? & 自分が先攻モード?
local max_dis = 10 -- 索敵範囲
local target_dis
for i,v in ipairs(actors) do -- 敵を探す
if (v ~= owner and v ~= myid) then
target_dis = GetDistance2 (myid,v) -- 距離計算
if (target_dis < max_dis) then -- 近いところにいる?
if (1 == IsMonster(v)) then
target = GetV (V_TARGET,v) -- 対象のターゲット確認
if (target == 0) then -- ターゲットがいない
enemys[index] = v
index = index+1
get_flg = 1
end
end
end
end
end
end
(後略)
end
・・・このように、索敵時にフラグの判定を入れることで、
先攻・非先攻を切り替えることが可能が可能です
どうでしょうか
このように動きをコマンドスイッチとすることで、
一つのAIで複数の動きをさせることが可能になります
ちなみに、先ほど公開したAIには、
もう一つのスイッチが実装されています
コードをよーく読んで、何ができるのかを調べてみてください
それでは、またいつか
~3章~ ちょっと難しい改造
3-1:スイッチを入れてみよう
今回から改造内容が複雑になるので、
先にAIを公開しておきます
AI 2006/04/25版
保存して、「AI.lua」に名前を変えればそのまま動きます
さて、具体的にどのように「コマンド」を実装するか、ですが、
「右左右」のように、ホムが特定の動きをしたとき、
スイッチが入るようにしてみます
例えば、ホムを以下のように動かした時、
何らかのスイッチが切り替わるようにするわけです
□□□ □□□ □□□
□●■ → ■●□ → □●■
□□□ □□□ □□□
●:主人 ■:移動先
具体的な判別方法ですが、
主人の座標とホムの移動先を比較すれば、
「コマンド」であるかを判別できます
具体的なコードは以下の通りです
------------------------------------------
-- mode flag
------------------------------------------
MODE_ACTIVE = 0 -- 先攻モード
MODE_NONACTIVE = 1 -- 非先攻モード
MyActiveMode = MODE_NONACTIVE -- 先攻モードフラグ
ActiveModeCounter = 0 -- コマンドカウンター
------------------------------------------
function OnMOVE_CMD (x,y)
TraceAI ("OnMOVE_CMD")
(中略)
Move (MyID,x,y)
MyState = MOVE_CMD_ST
MyDestX = x
MyDestY = y
MyEnemy = 0
MySkill = 0
CheckMoveCommand()
end
function CheckMoveCommand()
local ownerX, ownerY
ownerX, ownerY = GetV (V_POSITION,GetV(V_OWNER,MyID)) -- 主人の座標
-- 先攻・非先攻切り替え
if (MyDestY == ownerY) then
if (ActiveModeCounter == 0 and MyDestX == ownerX+1) then -- 右
ActiveModeCounter = 1
elseif (ActiveModeCounter == 1 and MyDestX == ownerX-1) then -- 左
ActiveModeCounter = 2
elseif (ActiveModeCounter == 2 and MyDestX == ownerX+1) then -- 右
ActiveModeCounter = 0
if (MyActiveMode == MODE_NONACTIVE) then -- 先攻切り替え
MyActiveMode = MODE_ACTIVE
else
MyActiveMode = MODE_NONACTIVE
end
else
ActiveModeCounter = 0
end
else
ActiveModeCounter = 0
end
end
CheckMoveCommandという関数がスイッチを判定する核となるところです
デフォルトAIのOnMOVE_CMD関数の最後にこの判定スイッチを入れることで、
移動がコマンドに沿ったものであるかを判断できるわけです
続いて核となるCheckMoveCommandですが、
まず主人の座標を取得しています
その上で、移動先が主人の右ならカウント+1、
カウント1で主人の左ならカウント2・・・のようにして、
「右左右」の動きが完成したところで、MyActiveModeフラグを入れ替えています
で、実際にMyActiveModeフラグをどう使っているかというと・・・
function GetMyEnemy (myid)
(中略)
-- 他の敵を探す
if (get_flg == 0 and MyActiveMode == MODE_ACTIVE) then
-- 自分を攻撃する敵がいない? & 自分が先攻モード?
local max_dis = 10 -- 索敵範囲
local target_dis
for i,v in ipairs(actors) do -- 敵を探す
if (v ~= owner and v ~= myid) then
target_dis = GetDistance2 (myid,v) -- 距離計算
if (target_dis < max_dis) then -- 近いところにいる?
if (1 == IsMonster(v)) then
target = GetV (V_TARGET,v) -- 対象のターゲット確認
if (target == 0) then -- ターゲットがいない
enemys[index] = v
index = index+1
get_flg = 1
end
end
end
end
end
end
(後略)
end
・・・このように、索敵時にフラグの判定を入れることで、
先攻・非先攻を切り替えることが可能が可能です
どうでしょうか
このように動きをコマンドスイッチとすることで、
一つのAIで複数の動きをさせることが可能になります
ちなみに、先ほど公開したAIには、
もう一つのスイッチが実装されています
コードをよーく読んで、何ができるのかを調べてみてください
それでは、またいつか
リンクだけでもはらしてもらってぇぇすかぁ??(′・ω・`)モフ