第１１章

## 第１１章　BGスクロール

### BG

スプライトはひとまず終わりです。いよいよBG（BackGround/背景）まで来ました。BGとは、 １画面だけ持てる(ただし画面外にもう１〜３面持てる)背景データです。 スプライトのように横8つまでという制約はありません。このBGをゲーム中に上手に更新することが プログラマの腕の見せ所であり、名作といわれるゲームは総じてこのBGを巧く使っている作品が多いようです。 スプライトのような制約がないので、通常の背景だけでなく巨大な敵や大量の小さい敵を表示してみたり、 ラスタースクロールというテクニックを駆使してファミコンの表現能力の限界に挑戦しているゲームがあります。

### ネームテーブル

第５章で、BGパターンテーブルはVRAMの$0000番地から開始すると説明しました。BGパターンもスプライトと同様のフォーマットで、 8x8のキャラを256種類、4キロバイト分持つことが可能です。この256種類のキャラクターの番号を、ネームテーブルという領域に1バイトずつ指定して画面に敷き詰めます。

第２章のメモリマップを見ると、ネームテーブル領域は４つ存在するように見えますが、普通は２つしか使えず残りはミラーとなります。ただし拡張して４つ使っているゲームも 存在するようです。今回は$2000から$3BF(960)バイト書き込むことにします。960という数は、BGのタイル数が横32x縦30=960だからです。 左上から右下という順に横方向に敷き詰めます。

以下は例です。この場合、BGデータの0番に真っ黒なキャラ、1番と2番に星の絵が入ってるという前提です。Star_Tblは星と星の間の黒い0番の数のテーブルで、 やっていることは、ネームテーブルに黒の0番を60回書き込んで、次に1番の星を書き込んで、次は0番の黒を45個書き込んで、次に2番の星を書き込んで・・ というような処理を行っています。あんまりかっこよい実装でもないですねえ。まあこんなもんでしょう。

    	; $2000のネームテーブルに生成する
    	lda #$20
    	sta $2006
    	lda #$00
    	sta $2006

    	lda #$00        ; 0番(真っ黒)
    	ldy #$00    	; Yレジスタ初期化
    loadNametable1:
    	ldx Star_Tbl, y				; Starテーブルの値をXに読み込む
    loadNametable2:
    	sta $2007				; $2007に属性の値を読み込む
    	dex					; X減算
    	bne loadNametable2	; まだ0でないならばループして黒を出力する
    	; 1番か2番のキャラをYの値から交互に取得
    	tya					; Y→A
    	and #1					; A AND 1
    	adc #1					; Aに1加算して1か2に
    	sta $2007				; $2007に属性の値を読み込む
    	lda #$00        ; 0番(真っ黒)
    	iny					; Y加算
    	cpy #20					; 20回(星テーブルの数)ループする
    	bne loadNametable1

    	; 星テーブルデータ(20個)
    Star_Tbl    .db 60,45,35,60,90,65,45,20,90,10,30,40,65,25,65,35,50,35,40,35

### 属性テーブル

属性テーブルは、その直前のネームテーブルに対するパレットデータです。しかし総タイル数が960なのに、属性テーブルの領域は64バイトしかありません。 これは、2x2の４つのキャラのグループ毎にパレットを１バイトで指定していて、それが8x8=合計64になるからです。BGは32x30ですから縦は余りますね。 そしてその1バイトのパレット指定データはどうなっているかというと、ビット0~1が左上のグループのパレット番号の上位２ビット、 ビット2~3が右上、ビット4~5が左下、ビット6~7が右下となっています。

ここで注意すべきなのは、２進数の上位２ビットという点です。０〜１５までのBGのパレットのうち、 パレット０〜３を使うならば０(%0000)の00、パレット４〜７なら４(%0100)の01、パレット８〜１１なら８(%1000)の10、パレット１２〜１５なら１２の(%1100)の11を指定することになります。 つまりパレットは連番で16/4=4種類うちのどれかしか使用できません。

以下の図は例です。属性テーブルのパレット指定は2x2のセットで左上・右上・左下・右下の順なのに、 ネームテーブルのキャラのアドレス指定は１つずつ左上から右下に横方向に敷き詰められているので、その辺の違いのせいでパレット指定はけっこう面倒になります。

なお、パレットの０〜１５のうちの０・４・８・１２は透明（BG抜き）になり、どんな色を指定しても反映されないので、 実質的に使える色は減ることになります。画面のフェードイン・フェードアウトなどをやる場合は、パレットを上手く書き換えるテクニックが必要ですね。

ちなみにこの制約はスプライトのパレット指定についても同様で、第５章で説明したスプライト情報の４つのうちの３バイト目の、ビット0~1で指定するのもこれと同じようにします。

以下のコードは例です。eorという命令がありますが、これはXOR演算を行う命令で、0→1→0→1と値を交互に変えたいような場合に便利です。 この例の場合、BGのパレットはしましま模様になります。

    	; $23C0の属性テーブルにロードする
    	lda #$23
    	sta $2006
    	lda #$C0
    	sta $2006

    	ldx #$00    ; Xレジスタクリア
    	lda #%00000000				; ４つともパレット0番
    	; 0番か1番にする
    loadAttrib
    	eor #%01010101				; XOR演算で一つおきのビットを交互に０か１にする
    	sta $2007				; $2007に属性の値($0か$55)を読み込む
    	; 64回(全キャラクター分)ループする
    	inx
    	cpx #64
    	bne loadAttrib

### スクロール

そしていよいよBGのスクロール機能の説明です。とりあえず1/60秒毎に1ドット分スクロールさせるのはとても簡単です。以下のようにするだけです。

    	; BGスクロール(Scroll_X,Scroll_Yという変数があるとして)
    	lda $2002			; スクロール値クリア
    	lda Scroll_X	; Xのスクロール値をロード
    	sta $2005			; X方向スクロール
    	lda Scroll_Y	; Yのスクロール値をロード
    	sta $2005			; Y方向スクロール

    	inc Scroll_X	; スクロールX値を加算
    	inc Scroll_Y	; スクロールY値を加算

スクロールはこれだけで出来ます。ただし、これでは同じ画面がループするだけです。 しかし普通のゲームではスクロールするたびに新しい背景が出なくてはならないので、画面外をこっそり更新する必要があります。 それにはネームテーブルを画面外でうまく書き換えなければなりません。後でスクロールについての章を設けるということでそれは置いておきます。

### BG横スクロールプログラム

とりあえず、星が流れるサンプルを作ってみました。これをダウンロードして、nesasm giko011.asmしてください。

相変わらず左上に2番以降のスプライトの下部が出てますが、これは座標を画面外にするか、属性をBGの後ろにするか、0番スプライトを透明にすれば消えます。気になる人はやってみてください。

こういう画面のゲームの場合は、星をスプライトにして、敵をBGに描くものもあるようです。逆転の発想ですね。

トップページ 前のページ 次のページ

FC2 |  | キャッシング 花 | 無料 掲示板 無料ホームページ