fc2ブログ
ホムンクルスAIについての独り言
[ラグナロクオンライン]のホムンクルスシステムで使用する ホムンクルスAIのカスタマイズについてのメモ
プロフィール

モルティシア

Author:モルティシア
何時の間にやら貧乏キャラが定着しそのまま「安ケミ」と呼ばれるようになった「安っぽいケミ」
一時休止していたものの、最近ふたたびホムンクルスのカスタムAIの開発&公開を再開
メマー無しPC3の42転職
[完全製薬・完全露店]キャラ

カテゴリー

月別アーカイブ

最近の記事

最近のコメント

最近のトラックバック

ブロとも申請フォーム

この人とブロともになる

リンク

このブログをリンクに追加する

ブログ内検索

RSSフィード

FC2カウンター

メールフォーム

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

役に立つか分からないもの
れぽーととかバイトとかまだまだ忙しい今日この頃

頭のなかでおぼろげに浮かんでいる動作をさせるために「必要だろうなぁ」と思う補助関数をぽちぽち作成
でもいざ組みあがると、もっと短くて効率のいい方法があるんじゃないかって気がしてくる

そもそも数学好きだったけど苦手だったので方程式とかあまり思い出せない
数字とにらめっこしつつ机上デバックでチマチマ作成
実際の動作テストはまた後日

以下、今日作ってみたもの
(※動作未テスト)

-- NowXY、idを添え字にしてXとYの座標情報を一つの値にまとめたものがぽいっと入ってる一元テーブル
-- BeforDest、NowXYの一秒前の座標が入ってる一元テーブル
--------------------------------------------------------------------------------
-- id1から見たid2の方向(角度)を得る
-- 戻り値:0~359(右方向=0度、上方向=90、左方向=180度、下方向=270)
--------------------------------------------------------------------------------
function GetDegree( x1, y1, x2, y2 )
local degrees = math.deg( math.atan2( y2 - y1, x2 - x1 ) )
if( degrees < 0) then
degrees = 360 + degrees
end
return degrees
end
function GetDegree2( id1, id2 )
local x1, y1 = GetV( V_POSITION, id1 )
local x2, y2 = GetV( V_POSITION, id2 )
if (x1 == -1 or x2 == -1) then
return -1
end
return GetDegree( x1, y1, x2, y2 )
end
-- idの一秒後の進路予想
function GuessNextMove(id)
local NowXY, BeforXY
local NowX, NowY, BeforX, BeforY, GuessX, GuessY
local A, B
NowXY = NowXY[id]
BeforXY = BeforDest[id] -- 一秒前の座標
NowX = math.floor(NowXY / 1000)
NowY = math.mod(NowXY,1000)
BeforX = math.floor(BeforXY / 1000)
BeforY = math.mod(BeforXY,1000)

A = NowX - BeforX
if (A < 0) then
A = math.abs(A)
GuessX = NowX - A
else
GuessX = NowX + A
end
B = NowY - BeforY
if (B < 0) then
B = math.abs(B)
GuessY = NowY - B
else
GuessY = NowY + B
end
return GuessX, GuessY -- 一秒後の予想地点
end
-- idがid2へ向かっているかどうか
function GuessKillSteal(id1, id2)
local GuessX, GuessY = GuessNextMove(id1)
local Guess_X, Guess_Y = GuessNextMove(id2)
local Now_XY, Now_X_Y
local NowX, NowY, Now_X, Now_Y
local A, B, A_, B_

Now_XY = NowXY[id1]
NowX = math.floor(Now_XY / 1000)
NowY = math.mod(Now_XY,1000)
A = GuessX - NowX
B = GuessY - NowY
A = math.floor(B / A)
B = NowY - NowX * A

Now_X_Y = NowXY[id2]
Now_X = math.floor(Now_X_Y / 1000)
Now_Y = math.mod(Now_X_Y,1000)
A_ = Guess_X - Now_X
B_ = Guess_Y - Now_Y
A_ = math.floor(B_ / A_)
B_ = Now_Y - Now_X * A_

if (A == A_ and B == B_) then -- 同じ直線上だったら
return true
end

local a = GetDegree(GuessX, GuessY, NowX, NowY) -- idの移動する方向
local b = GetDegree2(id1, id2) -- id1から見たid2の方向
local c = GetDegree(GuessX, GuessY, NowX, NowY) -- id1から見たid2の目的地の方向
if ((a >= 0 and a <= 45 and b >= 0 and b <= 45) or (a >= 0 and a <= 45 and c >= 0 and c <= 45)) then
return true
end
if ((a >= 45 and a <= 90 and b >= 45 and b <= 90) or (a >= 45 and a <= 90 and c >= 45 and c <= 90)) then
return true
end
if ((a >= 90 and a <= 135 and b >= 90 and b <= 135) or (a >= 90 and a <= 135 and c >= 90 and c <= 135)) then
return true
end
if ((a >= 135 and a <= 180 and b >= 135 and b <= 180) or (a >= 135 and a <= 180 and c >= 135 and c <= 180)) then
return true
end
if ((a >= 180 and a <= 225 and b >= 180 and b <= 225) or (a >= 180 and a <= 225 and c >= 180 and c <= 225)) then
return true
end
if ((a >= 225 and a <= 270 and b >= 225 and b <= 270) or (a >= 225 and a <= 270 and c >= 225 and c <= 270)) then
return true
end
if ((a >= 270 and a <= 315 and b >= 270 and b <= 315) or (a >= 270 and a <= 315 and c >= 270 and c <= 315)) then
return true
end
if ((a >= 315 and a <= 360 and b >= 315 and b <= 360) or (a >= 315 and a <= 360 and c >= 315 and c <= 360)) then
return true
end
return false
end
-- モンスターの進路が画面内PCの進路と被る可能性を予想
function GuessMonsterSteal(enemy)
local NowXY, BeforXY, NowX_Y, BeforX_Y
local NowX, NowY, BeforX, BeforY, Now_X, Now_Y, Befor_X, Befor_Y
local A, B, A_, B_
local GuessMove{}
local index = 0
NowXY = NowXY[enemy]
BeforXY = BeforDest[enemy] -- 一秒前の座標
NowX = math.floor(NowXY / 1000)
NowY = math.mod(NowXY,1000)
BeforX = math.floor(BeforXY / 1000)
BeforY = math.mod(BeforXY,1000)

A = NowX - BeforX
B = NowY - BeforY
A = math.floor(B / A)
B = NowY - NowX * A
for k, v in (NowXY) do
if(IsPlayer(k, 0) and k ~= enemy) then
NowX_Y = v
BeforX_Y = BeforDest[k]
Now_X = math.floor(NowXY / 1000)
Now_Y = math.mod(NowXY,1000)
Befor_X = math.floor(BeforXY / 1000)
Befor_Y = math.mod(BeforXY,1000)
A_ = NowX - BeforX
B_ = NowY - BeforY
A_ = math.floor(B_ / A_)
B_ = NowY - NowX * A_

-- モンスターの進路と交わる進路を取るかどうか
local ax, b_
ax = A - A_
b_ = B - B_
b_ = b_ * (9 - 10)
ax = b_ / ax -- 交わる点のx座標
if (A * ax + B == A_ * ax + B_) then
index = index + 1
GuessMove[index] = k
end
end
end

-- 進路が交わるキャラのうち最もモンスターに近いキャラ(ホムよりモンスターに近い)
local min_dis = 100
local result = 0
local Mydis = GetDistance2 (MyID,v)
for i,v in ipairs(GuessMove) do
dis = GetDistance2 (id,v)
if (dis < Mydis and dis < min_dis and dis ~= -1) then
result = v
min_dis = dis
end
end


return result -- Mobが被る可能性の高いキャラID
end
--

なんだか処理内容が被ってるものがあるけど、とりあえずこんなものかしら
GuessNextMove:一秒前の座標と現在の座標から一秒後の目的地を予想。一秒後の座標をただ予測するだけの関数。
GuessKillSteal:idの移動している方向と、idに対するid2の方向が一致しているかどうかを見る。これが一致していればidはid2を狙っている、追いかけているということになる。なんかここはもちょっと上手い方法がありそうな気がする。
GuessMonsterSteal:enemyの進路を方程式にしてその直線と交わる進路のプレイヤーの中から、enemyに最も近く且つホムより近くに居るプレイヤーIDを取り出す
これでフリーのenemyを狙っているキャラが居るかどうかと、enemyを殴る時タゲが被りそうかどうかがある程度分かる。
GuessKillStealとちょっと中身被ってる

これを実際にどう使うか考え直して改良を加えたら動作テストをしてみましょう
スポンサーサイト



この記事に対するコメント

この記事に対するコメントの投稿














管理者にだけ表示を許可する


この記事に対するトラックバック
トラックバックURL
→http://yasukemi.blog49.fc2.com/tb.php/77-9509691c
この記事にトラックバックする(FC2ブログユーザー)