スクロール処理の応用事例紹介



目次



このページについて

 このページでは、筆者が過去に制作したロックマン6の改造作品から、原作にはないスクロール処理の使い方をしたものの事例を紹介します。なお、その性質上、筆者の改造作品についてのネタバレが含まれます。
 原作での事例については、スクロール処理を読み解いてみるのページをご参照ください。そちらは既に読んでいるものとして、話を進めますのでご了承ください。



同方向分岐スクロール(After Tournament)

 Rockman 6 After Tournamentのヤマトマンステージは迷路構造となっており、間違ったルートに進むと戻される、いわゆるループ構造になっています。その中で、同じ方向で別の部屋へ分岐するという構造の場所があります。

 通常、分岐構造は別方向でなければ出来ませんが、1つの方向での分岐を実現しています。

 同方向分岐について解説する前に、通常のデータ列定義スクロールについて解説します。
 スクロール処理を読み解いてみるのページに書いたように、データ列定義スクロールは常時処理と同じタイミングで行われます。
 データ列定義スクロールの1方向分の処理は以下のようになっています。

  1. $73にスクロール時のパターンテーブル書込番号をセット
  2. $72と$0687にスクロール時のパレット変更番号をセット
  3. $697に現在の部屋番号をセット
  4. スクロール元部屋番号が指定されている場合、$697にその部屋番号をセット
  5. スクロール方向別のサブルーチンを実行

 このような処理を、定義されている方向の数だけ行います。
 スクロール方向別のサブルーチンのアドレスは、バンク$39の$9A88-$9A8Eと$9A8F-9A95に定義されています。
 下表にまとめておきます。

スクロール報告 アドレス
01 下(部屋番号増加) $D587
02 上(部屋番号増加) $D612
03 下(部屋番号減少) $D540
04 上(部屋番号減少) $D5D1
05 右(部屋番号増加) $D653
06 左(部屋番号減少) $D6B3

 これを定義されている方向別にそれぞれ実行します。
 また、同じことを常時処理として記述することで、データ列定義スクロールと同じことができます。

 さて、ここで同方向分岐に話を戻しましょう。
 上記の通り、データ列定義スクロールは常時処理として自分で書くこともできます。つまり、ここで座標によってスクロール元部屋番号を分けることで、同方向分岐が実現できます。

 再掲になりますが、下図のような分岐の場合の処理を見ていきます。
 上の場合は部屋番号$01に、下の場合は現在の部屋番号+1に移動します。

 これを実現するためには、以下のような処理を行います。

  1. $73にスクロール時のパターンテーブル書込番号をセット
  2. $72と$0687にスクロール時のパレット変更番号をセット
  3. $697に#$00をセット
  4. ロックマンのY座標が下半分の場合、$697に現在の部屋番号をセット
  5. 右方向スクロールのサブルーチン($D653)を実行

 実際のコードは以下のようになっています。

86DA:02855700                       ;スクロール定義

8557:A900   lda #$00                ;
8559:8573   sta $73                 ;スクロール時のパターンテーブル書き込み番号
855B:8572   sta $72                 ;スクロール時のパレット変更番号
855D:8D8706 sta $0687               ;スクロール時のパレット変更番号($72と同じ?)
8560:8D9706 sta $0697               ;スクロール元部屋番号
8563:ADCB04 lda $04CB               ;Y座標(low)(ロックマン)
8566:1005   bpl $856D               ;
8568:A557   lda $57                 ;Scroll X(high)
856A:8D9706 sta $0697               ;スクロール元部屋番号
856D:4C53D6 jmp $d653               ;右スクロール処理

 次は別方向の分岐についても見ていきます。考え方自体は先程と同じです。
 左の場合は部屋$06、右の場合は部屋$0Cに移動します。

 コードは以下のようになっています。

86E5:00857000                       ;スクロール定義

8570:A900   lda #$00                ;
8572:8573   sta $73                 ;スクロール時のパターンテーブル書き込み番号
8574:8572   sta $72                 ;スクロール時のパレット変更番号
8576:8D8706 sta $0687               ;スクロール時のパレット変更番号($72と同じ?)
8579:AD8604 lda $0486               ;X座標(low)(ロックマン)
857C:1003   bpl $8581               ;
857E:A90B   lda #$0B                ;
8580:2C     bit $05A9               ;
8581:A905   lda #$05                ;
8583:8D9706 sta $0697               ;スクロール元部屋番号
8586:4C87D5 jmp $D587               ;下スクロール(部屋番号増加)処理

 ここでは座標によって分岐していますが、他の条件によって分岐させる手法も考えられるでしょう。



条件付きスクロール(After Tournament)

 同方向分岐スクロールと似たような考え方の活用法です。筆者は同方向分岐スクロールもまとめて条件付きスクロールとして考えています。
 Rockman 6 After TournamentのMr.Xステージ3は往復構成になっており、往路は通常状態、復路は上昇気流によって空中制動が水中と同じになります。
 この往復は実際に同じ部屋を行き来しますが、上下移動を除いて後戻りが出来ないようになっています。これは、被弾ノックバックによって後戻りさせられるのが鬱陶しいためと、プレイヤーが迷わないように進路を固定化するための2つの理由があります。

 前提条件として、After Tournamentでは上昇気流発生フラグが存在しており、このフラグが立っている間は水中挙動になるという仕様になっています。このフラグは$FFを使用しています。
 往路復路のどちらであるかは、このフラグを見て判断します。

 下の場所は横長スクリーンの左端ですが、往路では右に進むため左スクロールは発生せず、復路では左に進むため左スクロールが発生します。

 同方向分岐と似たような考え方で、以下のような処理となります。

  1. $FFが0の場合、このフレームの常時処理を終了
  2. $697に現在の部屋番号をセット
  3. $73にスクロール時のパターンテーブル書込番号をセット
  4. $72と$0687にスクロール時のパレット変更番号をセット
  5. 左スクロールのサブルーチンを実行

 実際のコードは以下のようになっています。

8504:0180C500                       ;スクロール定義

80C5:A5FF   lda $FF                 ;上昇気流フラグ
80C7:D001   bne $80CA               ;
80C9:60     rts                     ;
80CA:20D080 jsr $80D0               ;現在部屋基準のスクロール事前設定
80CD:4CB3D6 jmp $D6B3               ;左スクロール処理

;現在部屋基準のスクロール事前設定
80D0:A557   lda $57                 ;Scroll X(high)
80D2:8D9706 sta $0697               ;スクロール元部屋番号
80D5:A900   lda #$00                ;
80D7:8573   sta $73                 ;スクロール時のパターンテーブル書き込み番号
80D9:8572   sta $72                 ;スクロール時のパレット変更番号
80DB:8D8706 sta $0687               ;スクロール時のパレット変更番号($72と同じ?)
80DE:60     rts                     ;

 次は同じ横長スクリーンの右端で、往路では右に進むため右スクロールが発生し、復路では左に進むため右スクロールは発生しません。

 コードは以下のようになっています。

8508:0280DF00                       ;スクロール定義

80DF:A5FF   lda $FF                 ;上昇気流フラグ
80E1:F001   beq $80E4               ;
80E3:60     rts                     ;
80E4:20D080 jsr $80D0               ;現在部屋基準のスクロール事前設定
80E7:4C53D6 jmp $D653               ;右スクロール処理

 $80D0は先のものと共通のため省略します。



所持アイテムによる分岐(After Tournament)

 Rockman 6 After Tournamentでは、特殊武器とビートプレートの所持状況によって進めるルートが変わるようになっているところがあります。Dr.ワイリーステージ4が該当します。

 特殊武器を8つ全て持っている場合は左に、プレートEとゲノムインスピレーション(ケンタウロスマン武器)を所持している場合は右に進めるようになっています。地形に対応した武器/プレートを所持していると青くなり通れるようになり、所持していないと灰色になり通れないという仕組みになっています。
 この地形操作を1つ前の部屋でスクロールの生成時処理を利用して行っています。

 特殊武器を所持しているかどうかは、武器エネルギーが#$80なら未所持、それ以外なら所持となります。プレートアイテムはエネルギーバランサーフラグ$0696の下位4ビットでそれぞれ判定します。
 これらの所持状況を確認し、地形を変化させるためのフラグを立てます。
 実際のコードは以下のようになっています。

8F8C:955400000001DF0000             ;スクロール定義

9554:A900   lda #$00                ;
9556:8D5E03 sta $035E               ;Destroyed blocks
9559:8D5F03 sta $035F               ;Destroyed blocks

955C:A008   ldy #$08                ;
955E:B98806 lda $0688,y             ;Weapon energy
9561:C980   cmp #$80                ;
9563:F002   beq $9567               ;
9565:38     sec                     ;
9566:A9     lda #$18                ;
9567:18     clc                     ;
9568:2E5E03 rol $035E               ;Destroyed blocks
956B:88     dey                     ;
956C:D0F0   bne $955E               ;

956E:AD9606 lda $0696               ;エネルギーバランサーフラグ
9571:290F   and #$0F                ;
9573:8D5F03 sta $035F               ;Destroyed blocks

9576:4C958F jmp $8F95               ;元々のスクロール$73生成時処理

 また、分岐のある部屋では条件付きスクロールも利用しています。地形でルート分岐自体は成立しているため、条件付きスクロール自体は必須ではないのですが、何らかの不具合等で壁抜けが起きた場合に備えて、分岐条件を満たしている場合にのみスクロールするようになっています。こちらについては、特に詳細は紹介しません。



ブーンブロックの同期化(After Tournament/再 Ver.2)

 ロックマン6のブーンブロックは、1部屋でのみ使用される想定で作られているため、横長のスクリーンで使用すると出現タイミングがズレます。
 Rockman 6 After Tournamentおよびロックマン6再(Ver.2)では、このタイミングのズレを無くして同期を取る対応をしています。この同期化対応は、管理オブジェクトを配置しておき、各ブロックオブジェクトから管理オブジェクトの状態を見て出現/消滅処理を行うという方法を採っています。
 この管理オブジェクトの生成を、スクロールの生成時処理で行っています。なお、同期化対応そのものの解説はここでは行いません。

 管理オブジェクトの生成をスクロールで行う理由は、生成するスロット番号を固定するため、そして複数の管理オブジェクトが生成されてしまうことを防ぐためです。
 通常、オブジェクトは空きスロット番号の降順に生成されるため、最も重複の可能性が低い$08($00-$07はロックマン側で使用されます)に生成します。既に$08にオブジェクトが存在する場合は、管理オブジェクトの生成は行いません。これにより、複数生成を防ぎます。このようにすることで、スクリーンの左右どちらから入ってきた場合にも管理オブジェクトが1つだけ生成されるようになります。
 実際のコードは以下のようになっています。

87E1:87E701000000                   ;スクロール定義

87E7:A93C   lda #$3C                ;配置X座標(ブーンブロックの切替時間)
87E9:48     pha                     ;
87EA:A91F   lda #$1F                ;配置Y座標(ブーンブロックの効果音タイミング)
87EC:48     pha                     ;
87ED:4CF481 jmp $81F4               ;ブーンブロック同期用Obj生成

;ブーンブロック同期用Obj生成
81F4:ADA803 lda $03A8               ;Object ID[8]
81F7:C9F4   cmp #$F4                ;
81F9:D003   bne $81FE               ;
81FB:68     pla                     ;
81FC:68     pla                     ;
81FD:60     rts                     ;
81FE:A208   ldx #$08                ;オブジェクトスロット番号
8200:A0F4   ldy #$F4                ;オブジェクト:ブーンブロック同期用
8202:2028CB jsr $CB28               ;パラメータ毎に処理内容が変わる
8205:41     .db                     ;Yレジスタで指定した番号のオブジェクトを生成
8206:68     pla                     ;
8207:9DCB04 sta $04CB,x ;           ;Y座標(low)
820A:68     pla                     ;
820B:9D8604 sta $0486,x ;           ;X座標(low)
820E:60     rts                     ;

 ロックマン6では、オブジェクトが配置されている座標を引数のように扱うことがあります。
 この管理オブジェクトでは、X座標でブーンブロックの切替時間、Y座標でブーンブロックの効果音タイミングを設定出来るようにしてあります。切替時間は再では一定ですが、After Tournamentでは一部異常に早くなっている箇所があります。効果音タイミングを指定する理由は、ブロック側で鳴らしてしまうと切り替えではないタイミングでスポーンした場合に、効果音の同期が取れなくなってしまうからです。ですので、効果音は管理オブジェクト側で鳴らしています。



まとめ

 筆者の改造作品におけるスクロールの応用事例を紹介しました。
 今後、他に使い方が増えた場合は追記することがあるかもしれません。




戻る