いよいよRacing Gameのサンプルを実装してゲームを動かす
以下の本を読みつつ進めているFPGAでゲーム機をつくろう日記。前回はtile graphicsというサンプルを実装して動かしてみた。今回はいよいよゲームを動かす。本の19章「Racing Game」の内容をZybo向けにカスタマイズして動かしてみた。
前回と同様、先に動かしてみた動画をのっけておく。
FPGAでゲーム機できた!本に載ってるレースゲームのサンプルRTLで
・非同期回路を同期回路に変更
・VGA用に壁と車の描写位置変更
・タクトスイッチで移動&加速できるようにピンアサイン
してZyboに組み込んだ。他にも細かい変更点はあるけど。これでゲーム機をつくろう日記はひとまず完結できそう😅 pic.twitter.com/l8QfEstQAF— Wakky (@wakky_free) December 23, 2020
今回のサンプルのプロジェクトは例のごとく以下で公開している。
https://github.com/WakkyFree/FpgaGameConsole/tree/master/RacingGame
tclファイルからプロジェクトを生成する方法はこちら。
いつものごとく、日記ではポイントだけ絞ってメモしていきます。
開発環境
Windows 10
Vivado 2020.1
Zybo(Zynq-7000)
hvsync_generator.v、detect_edge.v、MMCM IP、ピンアサインは前回と同じ
前回のMoving Ballのプロジェクトとhvsync_generator.v、detect_edge.v、mmcmのIP(clk_vga_25m)、ピンアサイン情報が記述された制約ファイル(game_console.xdc)は前回と同じ。今回変更&追加したのは
- zybo_top.v
- car_bitmap.v
- racing_game_top.v
- sprite_renderer.v
の4つのVerilogコード。今回はこちらのサンプルコードを利用している。car_bitmap.vとsprite_renderer.vはサンプルそのままで大丈夫だったが、racing_game_top.vには色々と手を加える必要がある。また、車の左右移動、加速を操作するためにzybo_top.vで3つのinput信号を定義して、Zybo上のタクトスイッチに割りあてることで操作ができるようにした。
zybo_top.vの変更ポイント
基本的には前回のtest_ram1_topのモジュールをracing_game_top.vに差し替えているが、Zybo上のタクトスイッチでプレイヤーの車を操作できるように、タクトスイッチ3つに割り当てるinputを追加した。
input BTN0, input BTN1, input BTN2,
また、タクトスイッチのような機械的なスイッチを押すときのチャタリング(詳しくはググってください)により、うまく動かなくなることを防ぐためにチャタリング防止のコードを追加している。
wire w_btn0_rmv_chat; wire w_btn1_rmv_chat; wire w_btn2_rmv_chat; reg [1:0] r_btn0; reg [1:0] r_btn1; reg [1:0] r_btn2; always @(posedge clk_vga) begin r_btn0 <= {r_btn0[0], BTN0}; r_btn1 <= {r_btn1[0], BTN1}; r_btn2 <= {r_btn2[0], BTN2}; end assign w_btn0_rmv_chat = &r_btn0; assign w_btn1_rmv_chat = &r_btn1; assign w_btn2_rmv_chat = &r_btn2;
あとは、追加したinputを忘れずにピンアサインしておく。今回はinputをZybo上のBTN0(R18 pin)、BTN1(R16 pin)、BTN2(V16 pin)に割り当てた。game_console.xdcを見ると、前回までの記述に加えて以下が追加されていることがわかる。
set_property IOSTANDARD LVCMOS33 [get_ports BTN0] set_property IOSTANDARD LVCMOS33 [get_ports BTN1] set_property IOSTANDARD LVCMOS33 [get_ports BTN2] set_property PACKAGE_PIN R18 [get_ports BTN0] set_property PACKAGE_PIN P16 [get_ports BTN1] set_property PACKAGE_PIN V16 [get_ports BTN2]
これでzybo_topの変更は完了。
racing_game_top.vの変更ポイント
ベースになっているのはエミュレータのracing_game_top.vというソースコード。そういえば今までの日記でちゃんと説明していなかった気もするが、エミュレータのソースコードは基本的に256 x 240pixelという解像度に合わせて作ってあるため、VGAで表示するにはRTLを640 x 480pixelに対応した解像度に書き換える必要がある。
そのため、hposやvpos、player_xとplayer_yなどは全て640 x 480pixelに対応できるようにbit長を長くしている。全部挙げてたらキリが無いので詳細はソースコードを見てください。
また、元々のコードでは車の横移動を操作する信号hpaddleは1つのinputになっていたが、どうもうまく動かなかったので、hpaddle_right、hpaddle_leftの2つのスイッチを押したら、左右の固定位置に移動するように変更した。
input hpaddle_left, hpaddle_right, vpaddle;
さらに、表示されるコースのtrack_offside(緑の部分)、track_shoulder(白い部分)も適当な大きさに調整した。
wire track_offside = (hpos[9:7]==3'b000) || (hpos[9:7]==3'b100); wire track_shoulder = (hpos[9:4]==6'b000111) || (hpos[9:4]==6'b100000); wire track_gfx = (vpos[7:3]!=track_pos[7:3]) && track_offside;
かなりざっくりとした説明だが、おおまかなポイントはこのくらい。
動かしてみた
プロジェクトをいつものごとくsynthesisとimplementationしてGenerate bitstream後にFPGAに書き込んで動かすと、最初にのせた動画のようにZybo上のタクトスイッチで車を操作することができた。(写真とってなかったので最初のせた動画のスクショだけど…笑)
これで当初の目的であったFPGAでゲーム機をつくるという目的は達成できた。あとはスコア表示したり、別のゲームに挑戦したり、VGAで表示しているところをHDMIで表示したりなどやりたいことは色々とあるが、今回はひとまずここまで。
FPGAでゲーム機をつくろう日記まとめ
この日記は以下でまとめています。