モノ創りで国造りを

ハード/ソフト問わず知見をまとめてます

Verilogでゲームを作る --Designing Video Game Hardware in Verilogの簡易和訳-- part3

Verilogビデオゲーム

Verilogの参考書を探してるとアマゾンで以下の本に出会った。

Designing Video Game Hardware in Verilog

Designing Video Game Hardware in Verilog

プログラミング言語の入門書の多くに、ゲーム作製をテーマにしているものがある。
Verilogでは同様のコンセプトの書籍が見つからなかったので、さっそく購入。
まだ全部読んでいないため、良書かどうかの判断はできないが、
せっかくなので、重要な箇所だけかいつまんで和訳しようと思う。
全部翻訳すると著作権に抵触するらしいので。
なるべく最後まで完結できるように頑張る。

目次はこちら

yuji2yuji.hatenablog.com

17章 スプライト

跳ね返るボールは良いけど、もっと複雑なものを描きたい。
11章で学んだ数字の書き方を応用しよう。

最初の例として、白黒のレースカーのスプライトを作成する。
スプライトは16pixel x 16pixelサイズだ。ただし横方向は左右対称なので8pixelを折り返して表示する。
最初にビットマップROMが必要だ。

moudle car_bitmap(
    input [3:0] yofs,
    output [7:0] bits;
);
    reg [7:0] bitarray[16];
    assign bits = bitarray[yofs];
    initial begin
        bitarray[0]  = 8'b00000000; //
        bitarray[1]  = 8'b00001100; //    **  
        bitarray[2]  = 8'b11001100; //**  **  
        bitarray[3]  = 8'b11111100; //******  
        bitarray[4]  = 8'b11101100; //*** **  
        bitarray[5]  = 8'b11100000; //***     
        bitarray[6]  = 8'b01100000; // **     
        bitarray[7]  = 8'b01110000; // ***    
        bitarray[8]  = 8'b00110000; //  **    
        bitarray[9]  = 8'b00110000; //  **    
        bitarray[10] = 8'b00110000; //  **    
        bitarray[11] = 8'b01101110; // ** *** 
        bitarray[12] = 8'b11101110; //*** *** 
        bitarray[13] = 8'b11111110; //******* 
        bitarray[14] = 8'b11101110; //*** *** 
        bitarray[15] = 8'b00101110; //  * *** 
    end
endmodule

次に11章と同様にYのオフセットを用いて8bitのビットマップをスライスする。
ROMモジュールと同様に入力をyofs、出力をbitsにつなげる。
各スキャンラインで以下を実行する。
スプライトのY座標はスキャンラインと等しい場合は、Yカウンタを15にする。
そうでない場合はYカウンタを0になるまでデクリメントする。

reg[3:0] car_sprite_xofs;
reg[3:0] car_sprite_yofs;

wire[7:0] car_sprite_bits;

car_bitmap car(
    .yofs(car_sprite_yofs),
    .bits(car_sprite_bits)
);

always @(posedge hsync)begin
    if(vpos == player_y)
        car_sprite_yofs <= 15;
    else if(car_sprite_yofs != 0)
        car_sprite_yofs <= car_sprite_yofs -1 ;

X座標についても同様のことをすればよい。

always @posedge clk)
    if(hpos == player_x)
        car_sprite_xofs <= 15:
    else if(car_sprite_xofs != 0)
        car_sprite_xofs <= car_sprite_xofs -1;

スプライトのビットを出力するための式は以下の記載となる。
x方向のビットは8で折り返される点を考慮する。

wire[3:0] car_bit = car_sprite_xofs >= 8? car_sprite_xofs ^ 7 : car_sprite_xofs;
wire car_gfx = car_sprite_bits[car_bit[2:0]];