マーク3版 覇邪の封印 on JavaScript 作成リポート

マーク3版 覇邪の封印 on JavaScript 作成リポート




(以下の内容はLINEのタイムラインに投稿して、(全く)反響が無かった内容を再編集し投稿した。)






初めに

仕事が無くなり、1ヶ月くらいはゲームしたり本を読んだりしてました。
暫くして、昨年に作って放置していたこのブログを更新し始め、イース4やランドストーカーの記事等を書きました。
金が無くなり二日で三食という生活を送りつつ、なんとなく新ネタになるかなと思い、セガ・マーク3版の覇邪の封印のマップを作り始めました。


マップ作成

攻略サイトのつもりで作り始めたので、ブラウザで表示させます。
ベースとなるHTMLを作り、中身は全てJavaScriptで書き始めます。
本物と同じクオリティを出したいので、絵はゲーム画面をキャプチャした物を使う事にしました。
本家や他機種版は知りませんが、マーク3版のマップはヨコ96マス x タテ72マス。
平地・森・橋・町・城などのマップ種別を二次元配列に収めて、for文で回せば簡単に描画出来るハズです。
マッピング自体は非常に大変でしたが、マーク3版は実行中のメモリの特定のアドレスの数値を弄ると固定敵以外が出なくなるのを以前に(20数年前?)見つけていたので、他の攻略サイト作成者と比べたら楽だったハズです。
後で気付きましたが、SMS Power! さん等でもっと便利なマップが公開されているので、特筆すべき長所は皆無な出来でした。



カーソルキー操作

半分冗談半分本気で遺作になると思って作り始めたので、暫くしたらコダワリが出始めました。本家は、最初は1x1マスしか見えないので、5x5マスが見える状態で始まるマーク3版は優しい設定です。
しかし見える範囲が他のRPGと比べると雲泥の差ですので、「見える覇邪の封印」は夢でした。
なので、マーク3版と同じ様に真ん中にアイコンを表示させて、矢印キーで移動出来るようにして、ついでに音楽も流れるようにしました。
表示倍率にもよりますが、負荷の関係で41x41辺りが限度でした。
「スゲー見える覇邪の封印」を体感して、一人で感激。



町と左ウィンドウ


移動できるようになると、今度は町に入りたくなりました。そして全ての町のマッピングを開始。
センターアイコンを町に合わせてキーを押しマップと音楽が町に切り替わるようになると、左ウィンドウが欲しくなりました。

元々ゲームでは最大5x5マス表示で、移動はスムーズスクロールせずに1マスごとに切り替わります。
ですので例えば広大な砂漠で移動した時には表示されてるマスの全てが移動前も後も同じで、動いたかどうかわかりません。
それを解消するために、ゲームには「遠景の山」の描画が左ウィンドウに有ります。
上下に動くと、山の描画も上下し、左右に動けば、山の描画も左右に動くコトで、「いま動いたよ」と教えてくれるわけです。
やっぱ移動時にアレが動かないと覇邪の封印っぽくないよねってコトで、「遠景の山」を作り始めます。
当時は気付かなかったのですが、ヨコ32パターン・タテ4パターンで、なんと合計128パターンも有りました!
全てキャプチャして、動く部分、動かない部分を分けて、左に描画する処理を書きました。
ゲームでは常に妖精がパタパタと羽ばたいてますが、コチラは簡易的に1マス動いたら羽を動かすようにしました。



圧縮にハマる

この辺りで、ソースコードよりデカいマップデータの圧縮を考え始めます。
以前書いた事が有るので、ランレングス法で独自アルゴリズムを作ってみましたが、思いのほか縮みません。
検索すると、JavaScriptでの圧縮展開のライブラリが結構出てきます。
使うのが比較的簡単そうなのを見つけました。
Gitでの公開でした。
GoogleのAOSPベースのカスタムROM、CyanogenModやResurrectionRemix、AICP等のメンテナ的なコトをやってた時以来の邂逅です。
早速使ってみますが…
そんなに縮まない!
色々と試行錯誤し、マップ種別がフィールドも町も16個未満な所に注目し、1バイトに2マス分のデータを詰めたりなんだりして、1/8まで縮めました。
バイナリの状態ならもっと小さいんですが、JavaScriptの仕様でバイナリファイルは自動的には読み込めません。
ですので、結局はテキストでの保存になりました。
セキュリティ上の理由で自動的に読み込めるのはテキストや画像・音楽等の比較的セキュアなファイルのみのようです。



町の中を作り始める

移動出来て町にも入れるようになると、今度は会話がしたいですね。
覇邪の封印の町の人(正確には家)は、情報と店の二つに分けられます。
情報系の人たちは一方的に同じコトを話すだけなので、同じ内容を画面に表示するだけでOKです。
会話ウィンドウを作り、会話の文字列を渡すとそれを描画する処理を書きます。
更に、会話時には人が左ウィンドウに出てきますので、全ての人をキャプチャします。
ついでに妖精パタパタもキチンと実装。
ゲームと同じくらいの速度でパタパタするように調整します。



ゴルダ・薬草・牙・知名度を作る

最初は、覇邪の封印の各要素である、金(単位はゴルダ)、薬、牙、知名度は設定していなかったので、
例えば医者の所で薬を買う時、金は足りてるけど所持可能個数を超える場合のセリフが出せなかったりしました。
牙や知名度が無いと城や村の会話がロクに出来ないし、アイテムショップなんかは金が無いと話になりません。それを解消する為に、各要素を作りました。
会話メッセージも全部入力し、仲間加入イベントの処理も書き終えました。
ステータスウィンドウ内に各要素の所持数を表示するようにしてみました。





フォントにこだわり始める

この辺りで、フォントに違和感を覚え始めます。かなりの部分がゲームと同じなのに、フォントはブラウザのデフォルトのフォントです。

1987年発売のゲームなので、漢字表示は有りません。
平仮名・片仮名と、カギカッコや!?等のマーク、濁点・半濁点・句読点くらいしか無いので、全部キャプチャします。
ドラクエ等も同じですが、昔のゲームのお約束で、メッセージは二段でワンセットです。
当時のゲームソフトの容量は凄まじく少ないので、少しでもデータを小さくする為に、濁点と半濁点は別に用意してあるわけです。
ゲームでは8x8ドットの文字がタテに二段詰まれて表示されていますので、こちらで用意するのは8x16ドットの字で良いわけです。
(この判断が後に困るコトになる・・・)

全ての文字の画像を作り終え、既に作った会話文と入れ替えたいワケですが、各文章ごとに画像の順番を記述してたら、生きてるウチに終りそうも有りません。
なので、オリジナルフォント描画をしたい時には、既に出来てる文章の文字からUTF-16コードを取得するように書きます。
そしてオリジナルフォントの画像のファイル名をUTF-16コードにしておきます。
例えば、「あ」はhaja_font_12354.png、「ほ」はhaja_font_12411.pngと言った具合です。
こうすれば、文字列のlengthでfor文を回せばcharCodeAtで対応した文字を画像で描画出来ます。
    for (let i = 0; i < str_.length; i++){
        let image = document.createElement('img');
        image.src = 'font/haja_font_' + (str_).charCodeAt(i) + '.png';
        image.width  = (size ? size : fontSize);
        element.appendChild(image);
    }
こんな具合です。



タップ・クリック操作と自動経路探索

この辺りで、元々キーボード操作のみだった所にクリック操作も追加し始めます。
しかしクリックだと、会話時に「はい・いいえ」を選んだり購入するモノを選んだりするのは良いんですが、移動時に困ります。
町では池?や木が有って、ゲームだと通行不可なマスです。
クリックした所に移動する処理を書こうとすると、通行不可マスが邪魔です。
町では現在位置からクリックした所までの移動経路を自動的に考えて進みたいところです。

というわけで経路探索・迷路探索のアルゴリズムを勉強し始めますが、原理が理解出来てもコードは書けません。
要するに理解出来てないワケなんですが。
そこで実際にコードを書いて公開してるトコから貰ってきて、組み込んでみました。
恐らく幅優先経路探索アルゴリズムで書かれたコードで、公開してる人のサイトではバッチリ結果が出てました。
が、ダメッ!
クリックしてコードが発動するとCPU負荷が一気に上がり、CPUファンがMAXで回り始め、ブラウザはフリーズ寸前になり、「処理を停止しますか?」と言うメッセージが出るだけです。
コードは件のサイトで動いてて、こっちでは動かない。
正確には、答えが返ってこない。
色々試行錯誤してて気がついたのは、「移動可能範囲が広すぎて演算が終わらない」でした。
件のサイトは9x9マスの迷路で、スタートに設定した座標からゴールに設定した座標までの経路を表示する、というモノでした。
覇邪の封印の町マップは16x16です。
既にデカ過ぎな上に、移動可能ゾーンが広すぎます。
「コードを見てワカれよ」と思いますが、要するに総当りして、終わったらゴールする経路だけ出力するというコードです。
なので、移動可能範囲を縮めます。
基本的には石畳っぽい所だけ移動可能にします。
端の方で行く必要が無い所は無視エリアに指定。
2マス幅の通路なんかも、1マス幅に変更。
そうしたら一応動きましたが、何か変です。
確かにクリックした所に到着するんですが、意味不明なまでの遠回りで行きます。
またまた試行錯誤をしていて、このコードは全ての経路を出力する事にやっと気付きます。
つまり、現状では最初に見つけたルートを選んで動いてたワケです。
そこで最短経路を判別するようにして、やっと完成。

GZIP圧縮の時もそうでしたが、最初は「こう言う風にしたい」だったのが「この機能を実装したい」に途中から変わっていった気がします。
手段が目的化した、という感じです。



枠にこだわり始める

フォントがゲームと同じなのにメッセージの枠は普通のテーブルです。
borderはradiusを指定しているので丸みを帯びてますが、やはり違和感があります。
画面に出ているモノは全てゲームと同じなのに、ワクだけが別。
なので、ワクもゲームと同じに置き換えます。

そうしているウチに、常にアイコンの位置が画面のセンターだと町では不便な事に気付き、18x18固定画面モードを作りました。
既に町・村・城は全て作り終え、アイテムや装備も大体実装し終えたので、次はダンジョンを作りました。
ダンジョンに入る為のフラグの処理等も含めて全て作り終え、「つよさ」「もちもの」画面も作りました。



RPGと言えば敵との戦闘

意図的に避けてきた戦闘です。
本来は戦闘が出来ないと2人目・3人目の仲間が加入しないハズなので、アレオス(ゲームの終盤エリア)に行く事が出来ません。
2人目の仲間の加入イベントも作って有りますが、ソースコードの設定値を直接弄ってクロノスの鎧を持った状態で行かないと、加入イベントが発生しません。

現状でワカってるのは攻撃時の経験値入手のアルゴリズムだけです。
それも、敵のレベルが関係しているので、全ての敵のデータを集める所からスタートです。
HPなんかは(数値でなく画像ですが)表示されているので見れば分かるんですが、
攻撃時・被攻撃時のダメージ計算や、攻撃順・攻撃ミス・逃亡成功失敗・エンカウント・魔界の石・炎の魔法・シャオウホウとカイホウリュウのアイテムドロップ等の確率を出さないと話になりません。
エンカウントする敵の種別を決める為には、マップをエリア分けする必要も出てきます。
ワリと膨大なモノを作る必要があるんですが、ゲームではホボ非表示な部分です。
まずはスケルトン・センピ・ハンジョウ・トレモス・ホウダ3兄弟などの固定敵から作り始めたいところです。

と当初は書きましたが、その後の調査でエンカウントしている敵のパラメータはかなりの部分が分かるようになったので、確率絡みが不明なだけです。
所詮シミュレータなので、各要素を1000回程度試行して出た結果をそのまま決め打ちしても問題なさそうですが・・・
マップのエリア分けも大袈裟に考えていましたが、特定の座標を超えたらエリアチェンジ的な処理を書けば、わざわざ全ての座標に新たにエリア情報を加えなくても大丈夫そうです。



タイトル・ロード・ネーム



現実逃避してタイトル画面とネームエントリー画面・ロード画面を作り始めます。
ワリと簡単なコードで出来るハズですので、ロードはローカルに保存したセーブファイルを選択するように作ろうかと思ってます。
セーブは動的にダウンロードを作る事が出来るので、実装は難しくなさそうです。
タイトル画面中段のキラキラロゴが、最初の1フレームだけパレットデータがブッ壊れてて変に黄色いグラフィックになる仕様は再現してません。
ループ時にレジスタが初期化されずにロゴや空の色の遷移状態が初回とは違うトコロも、再現していません。



終わりに

以上が、ココまでの経緯です。
大体一ヶ月でこんな感じです。
「らんの眼」さんの攻略サイト作りに感動して、自分も!と言う感じで覇邪の封印の攻略サイトを作り始めたハズなんですが、何時の間にかゲームの移植になってしまいました。






御質問・御意見・御感想は@m_o_p_u までお気軽にどうぞ







 << 前の記事 次の記事>> 
イメージ  イース4のデバッグモードを実機で ケータイのパーツ交換  イメージ






コメント

このブログの人気の投稿

Ys IVのデバッグモードと未使用ボス

ランドストーカー ~皇帝の財宝~

An intruder has penetrated our force field.

イース4のデバッグモードを実機で

ランドストーカー on JavaScript作成記(4)

ランドストーカー ウォーキングシミュレーター on JavaScript 作成リポート

ランドストーカー on JavaScript作成記(3)

ランドストーカー on JavaScript作成記(2)

チートの話

TWRPにてバックアップ成功