【はじめてのプチコン】システムカウンタ | りょうのゲーム塾

りょうのゲーム塾

再開、準備中。

チェックポイント
以前に追加したシステムカウンタを使ったアニメーションの例です。
システムカウンタにマスク処理を行うことでインターバル処理を行うことができます。


今回はシステムカウンタの使用方法を解説します。
まずは簡単なアニメーションを行うためにシステムカウンタにマスク処理を行い使用します。
サンプルではUFOが武器で破壊されるときの爆発を追加しました。

あとゲームらしくするためにスコアの追加も同時に行っています。
プログラム中に変更点が記述されています。
赤文字は修正部分です。
青文字は追加部分です。
当然のことですがプログラム中で『※』で始まる注意書きはプログラムとは違います。
プログラムとして入力しようなどとは考えないでください。

■プログラム
' initialize
GOSUB @SYS_INI
GOSUB @PLY_INI
GOSUB @WPN_INI
GOSUB @UFO_INI
' game loop
@LOOP
GOSUB @SYS_MAIN
' task
GOSUB @PLY_TASK
GOSUB @WPN_TASK
GOSUB @UFO_TASK
GOTO @LOOP
'
' system
'
@SYS_INI
CLEAR
SCORE=0 ※スコアの初期化
SYS_CNT = 0
SYS_KEY = BUTTON()
RETURN
'
@SYS_MAIN
VSYNC 1
CLS
※スコアの表示
LOCATE 0,22
PRINT "---------------------------------";SCORE;

'
SYS_CNT = (SYS_CNT + 1) AND &H3FFFF
OLD_KEY = SYS_KEY
SYS_KEY = BUTTON()
TRG_KEY = SYS_KEY XOR OLD_KEY
ON_KEY = TRG_KEY AND SYS_KEY
RETURN
'
' UFO task
'
@UFO_INI
UFO_SX = 0.1
UFO_F = 0
UFO_CNT = 60
RETURN
'
@UFO_TASK
ON UFO_F GOTO @UFO_WAIT,@UFO_MVR,@UFO_MVL,@UFO_EXPL ※爆発処理
STOP
'
@UFO_WAIT
UFO_CNT = UFO_CNT - 1
IF UFO_CNT > 0 THEN RETURN
IF RND(2) GOTO @UFO_LSET
GOTO @UFO_RSET
' move right
@UFO_MVR
LOCATE UFO_X, UFO_Y
PRINT "A"
UFO_X = UFO_X + UFO_SX
IF UFO_X > 32 GOTO @UFO_DETHT
HITX = UFO_X
HITY = UFO_Y
GOSUB @WPN_HITC
IF HITF GOTO @UFO_DAMG ※爆発処理の準備
RETURN
'
@UFO_LSET
UFO_X = 31
UFO_Y = RND(10)
UFO_F = 2
RETURN
' move left
@UFO_MVL
LOCATE UFO_X, UFO_Y
PRINT "A"
UFO_X = UFO_X - UFO_SX
IF UFO_X < 0 GOTO @UFO_DETH
HITX = UFO_X
HITY = UFO_Y
GOSUB @WPN_HITC
IF HITF GOTO @UFO_DAMG ※爆発処理の準備
RETURN
'
@UFO_RSET
UFO_X = 0
UFO_Y = RND(10)
UFO_F = 1
RETURN
※爆発処理の準備
'
@UFO_DAMG
BEEP 13 ※爆発音を鳴らしています
SCORE=SCORE+1 ※スコアの加算
'
UFO_F=3
UFO_CNT=30
RETURN
'※爆発処理
@UFO_EXPL
LOCATE UFO_X,UFO_Y
IF SYS_CNT AND 8 GOTO @LBL101
PRINT"●";
GOTO @LBL100
@LBL101
PRINT"*";
@LBL100
UFO_CNT=UFO_CNT-1
IF UFO_CNT!=0 THEN RETURN

'
@UFO_DETH
UFO_F = 0
UFO_CNT = RND(60)
RETURN
'
' player task
'
@PLY_INI
PLY_X = 15
PLY_SX = 0.5
PLY_F = 0
RETURN
'
@PLY_TASK
LOCATE PLY_X,21
PRINT "P"
IF ON_KEY AND 16 THEN GOSUB @WPN_FIRE
ON PLY_F GOTO @PLY_STOP,@PLY_MVR,@PLY_MVL
STOP
' stop
@PLY_STOP
IF SYS_KEY AND 8 GOTO @PLY1
IF SYS_KEY AND 4 GOTO @PLY2
RETURN
@PLY1
PLY_F = 1
RETURN
@PLY2
PLY_F = 2
RETURN
' move right
@PLY_MVR
PLY_X = PLY_X + PLY_SX
IF PLY_X > 31 THEN PLY_X = 31
IF SYS_KEY AND 8 THEN RETURN
PLY_F = 0
RETURN
' move left
@PLY_MVL
PLY_X = PLY_X - PLY_SX
IF PLY_X < 0 THEN PLY_X = 0
IF SYS_KEY AND 4 THEN RETURN
PLY_F = 0
RETURN
'
' weapon task
'
@WPN_INI
WPN_MAX = 3
DIM WPN_F(WPN_MAX)
DIM WPN_X(WPN_MAX)
DIM WPN_Y(WPN_MAX)
FOR I=0 TO WPN_MAX-1
WPN_F(i) = 0
NEXT I
WPN_SY = 0.5
RETURN
'
@WPN_TASK
FOR WPN_I=0 TO WPN_MAX-1
GOSUB @WPN_SUB
NEXT WPN_I
RETURN
'
@WPN_SUB
ON WPN_F(WPN_I) GOTO @WPN_WAIT,@WPN_MOVE
STOP
'
@WPN_WAIT
RETURN
'
@WPN_MOVE
LOCATE WPN_X(WPN_I),WPN_Y(WPN_I)
PRINT "!"
WPN_Y(WPN_I) = WPN_Y(WPN_I) + WPN_SY
IF WPN_Y(WPN_I) >= 0 THEN RETURN
WPN_F(WPN_I) = 0
RETURN
'
@WPN_FIRE
GOSUB @WPN_GET
IF WPN_N < 0 THEN RETURN
BEEP 10
WPN_F(WPN_N) = 1
WPN_X(WPN_N) = PLY_X
WPN_Y(WPN_N) = 20
RETURN
'
@WPN_HITC
HITF = 0
'FOR WPN_N=0 TO WPN_MAX-1
WPN_N=0
@LBL003
IF WPN_F(WPN_N) == 0 GOTO @WPN_NEXT
IF FLOOR(WPN_X(WPN_N)) != FLOOR(HITX) GOTO @WPN_NEXT
IF FLOOR(WPN_Y(WPN_N)) == FLOOR(HITY) GOTO @WPN_HOK
@WPN_NEXT
'NEXT WPN_N
IF WPN_N==WPN_MAX-1 THEN RETURN
WPN_N=WPN_N+1
GOTO @LBL003
'
※爆発処理による修正
@WPN_HOK
HITF = 1
WPN_F(WPN_N) = 0
RETURN

'
@WPN_GET
'FOR WPN_N=0 TO WPN_MAX-1
WPN_N=0
@LBL001
IF WPN_F(WPN_N)==0 THEN RETURN
'NEXT WPN_N
IF WPN_N==WPN_MAX-1 GOTO @LBL002
WPN_N=WPN_N+1
GOTO @LBL001
@LBL002
WPN_N = -1
RETURN
'End of line


爆発処理タスクではシステムカウンタを使用したアニメションの例です。

@UFO_EXPL
LOCATE UFO_X,UFO_Y
IF SYS_CNT AND 8 GOTO @LBL101
PRINT"●";
GOTO @LBL100
@LBL101
PRINT"*";

SYS_CNT に8をアンドしているのはマスク処理です。
SYS_CNT は毎フレーム1が加算されています。
この値にマスクすると一定の時間間隔の処理(インターバル処理)を行うことができます。

では基本的なシステムカウンタを使ったマスク処理でどのようにしてインターバルを生み出すかみてみましょう。
ここでは説明のためにシステムカウンタを4ビットとし2種類のマスク値でアンドした結果をみてみます。
マスク①は1000でマスク②は0111です。
結果としはIF文で使うことを前提に成り立つ場合は真、成り立たない場合には偽とします。

カウンタ マスク① 結果 マスク② 結果
0000 0000 偽  0000 偽
0001 0000 偽  0001 真
0010 0000 偽  0010 真
0011 0000 偽  0011 真
0100 0000 偽  0100 真
0101 0000 偽  0101 真
0110 0000 偽  0110 真
0111 0000 偽  0111 真
1000 1000 真  0000 偽
1001 1000 真  0001 真
1010 1000 真  0010 真
1011 1000 真  0011 真
1100 1000 真  0100 真
1101 1000 真  0101 真
1110 1000 真  0110 真
1111 1000 真  0111 真

マスク①の場合には8フレーム毎に真偽を繰り返すインターバルを生み出します。
今回のアニメーションでは単に2つの文字を交互に表示しているんですが真と偽を一定時間続けないとパターン変化が早くてアニメーションが分かりません。

マスク②の場合には8フレームに1回偽が現れます。
これにより8フレーム毎に何か処理することができます。