こんにちは。今回はDQ7 TASについてです。
今回、Bizhawkを使用している際にLuaScriptで各種情報の表示をするスクリプトを作成しました。

成果物

 

こんな感じで画面右下に各種情報が表示されます。
1番上から実時間。これはフレーム数から計算しています。
2番目は乱数。これはゲーム内の現在の乱数値を表示しています。
3番目はエンカウント歩数。エンカウントが発生するマップを歩くとこの値が減っていき、0を下回るとエンカウントが発生します。この値は乱数によって決定されています。
4,5番目は主人公を中心とした現在の位置情報を表示しています。x軸が左右の移動、z軸が上下の移動を表しています。

ソースコード

ソースコードについてはこちらのGithubにて公開しています。

--現在の座標を{x,z}で返す
function getPos()
    return {x = memory.read_s32_le(0x0C7020), z = memory.read_s32_le(0x0C7028)}
end

--フレームを時間に変換
function frame2time(frame)
    --hour
    hour = math.floor(frame / (60 * 60 * 60))
    frame = frame - hour * (60 * 60 * 60)
    --min
    min = math.floor(frame / (60 * 60))
    frame = frame - min * (60 * 60)
    --sec
    sec = math.floor(frame / 60)
    frame = frame - sec * 60
    --msec
    msec = math.floor(frame / 60 * 100)

    time = string.format("%2d:%2d:%2d:%2d", hour, min, sec, msec)
    return time
end

-- 出力ファイルのオープン
local file = io.open("gui.txt", "w")

-- ウィンドウサイズの計測
local window_height = client.bufferheight()
local window_width = client.bufferwidth()

while true do
    -- 表示データの取得
    -- フレーム数
    frame = emu.framecount()
    -- 実時間
    time = frame2time(frame)
    -- 乱数
    random_number = string.format("%x", memory.read_u32_le(0x0F9BA0))
    -- エンカウント歩数
    encount_walk = memory.read_u16_le(0x0F78DC)
    -- 位置
    position = getPos()

    -- 画面表示部分
    gui.drawText(
        window_width,
        window_height - 10,
        time ..
            "\n" .. random_number .. "\n" .. encount_walk .. "\n" .. "x:" .. position["x"] .. "\nz:" .. position["z"],
        nil,
        nil,
        15,
        nil,
        nil,
        "right",
        "bottom"
    )
    -- ファイル出力部分
    file:write(
        frame ..
            "," ..
                time ..
                    "," .. random_number .. "," .. encount_walk .. "," .. position["x"] .. "," .. position["z"] .. "\n"
    )
    emu.frameadvance()
end

 

BizhawkでのLuaの関数

以下今回使用したBizhawkに実装されている関数について解説します。

void emu.frameadvance()

エミュレータのフレームを1フレーム進める関数。ゲームを動かしながらLuaを動かす際にはこちらをループさせて適宜フレームを進めてやる必要があります。

memory.readbyte(int addr, [string domain = null])

int memory.read_s8(int addr, [string domain = null])

uint memory.read_u8(int addr, [string domain = null])

int memory.read_s16_le(int addr, [string domain = null])

int memory.read_s16_be(int addr, [string domain = null])

uint memory.read_u16_le(int addr, [string domain = null])

uint memory.read_u16_be(int addr, [string domain = null])

int memory.read_s24_le(int addr, [string domain = null])

int memory.read_s24_be(int addr, [string domain = null])

uint memory.read_u24_le(int addr, [string domain = null])

uint memory.read_u24_be(int addr, [string domain = null])

int memory.read_s32_le(int addr, [string domain = null])

int memory.read_s32_be(int addr, [string domain = null])

uint memory.read_u32_le(int addr, [string domain = null])

uint memory.read_u32_be(int addr, [string domain = null])

こちらはゲームのメモリの値を各形式で読み込む関数です。1byteから4byteの間で、符号付きか符号なし、リトルインディアンかビックインディアンの形式の値を取得できます。上記のLuaScriptではこれを用いて乱数値やエンカウント歩数、座標をメモリから取得しています。上記のreadの部分をwriteにすることで、メモリの読み込みではなく書き込みを行うことができます。

int emu.framecount()

現在のフレーム数を返す関数。上記のLuaScriptではこのフレーム数を元に時間を算出して画面に表示しています。

void gui.drawText(int x, int y, string message, [color? forecolor = null], [color? backcolor = null], [int? fontsize = null], [string fontfamily = null], [string fontstyle = null], [string horizalign = null], [string vertalign = null])

Draws the given message in the emulator screen space (like all draw functions) at the given x,y coordinates and the given color. The default color is white. A fontfamily can be specified and is monospace generic if none is specified (font family options are the same as the .NET FontFamily class). The fontsize default is 12. The default font style is regular. Font style options are regular, bold, italic, strikethrough, underline. Horizontal alignment options are left (default), center, or right. Vertical alignment options are bottom (default), middle, or top. Alignment options specify which ends of the text will be drawn at the x and y coordinates.(TASVideosより引用)

画面に指定のテキストを描画する関数。引数は順番に、「表示するx座標、y座標、表示するメッセージ、フォントの色、背景の色、フォントのサイズ、フォント、フォントのスタイル(ボールドとかイタリックとか)、テキストの表示位置(x,y座標)を決めるときに左右中央どこを基準とするか、同様に上下中央どこを基準とするか」です。上記の[]で囲まれている部分は必須項目ではなく、予めデフォルト値が設定されています。

int client.bufferheight()
int client.bufferwidth()

エミュレータの描画領域の高さと幅を返す関数。上記のLuaScriptでは右下に各種情報を表示したかったので、この値を用いてdrawText()に値を渡しています。

Bizhawkに実装されている関数は以下のTAS Videosのサイトから参照することができます。(英語)



メリット

この関数のメリットとして、Bizhawkに予め備わっているRamWatchと言うメモリの内容を表示する機能よりも高速であるという点があります。このLuaScriptもRamWatchもメモリの内容を表示するという点では同じなのですが前者のほうが柔軟性もあり、高速です。また、各フレームで表示した値を外部ファイルに保存しておくことで、動画作成などに用いることもできます。

というわけで今回は以上です。そもそもTASを始める前にこういうことを勉強しておくべきだった気もしますが…….。この記事の内容とかは他のゲームにも利用できるので是非参考にしてみてください。
以上です。お読み頂き有難う御座いました。また宜しくお願いします。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA