りょうのゲーム塾 -110ページ目

りょうのゲーム塾

再開、準備中。

チェックポイント
修正版とありますが、実は何も変わっていません。
プログラム中のソースコードの書き方で誤表示する場合があります。
元のプログラムとの変更点は赤で表示してあります。


■プログラム
0001 ' initialize
0002 GOSUB @SYS_INI
0003 GOSUB @PLY_INI
0004 GOSUB @WPN_INI
0005 GOSUB @UFO_INI
0006 GOSUB @UFW_INI
0007 ' game loop
0008 @LOOP
0009 GOSUB @SYS_MAIN
0010 ' task
0011 GOSUB @PLY_TASK
0012 GOSUB @WPN_TASK
0013 GOSUB @UFO_TASK
0014 GOSUB @UFW_TASK
0015 GOTO @LOOP
0016 '
0017 ' system
0018 '
0019 @SYS_INI
0020 CLEAR
0021 SCORE=0
0022 SYS_CNT = 0
0023 SYS_KEY = BUTTON()
0024 RETURN
0025 '
0026 @SYS_MAIN
0027 VSYNC 1
0028 CLS
0029 LOCATE 0,22
0030 PRINT "---------------------------------";SCORE;
0031 '
0032 SYS_CNT = (SYS_CNT + 1) AND &H3FFFF
0033 OLD_KEY = SYS_KEY
0034 SYS_KEY = BUTTON()
0035 TRG_KEY = SYS_KEY XOR OLD_KEY
0036 ON_KEY = TRG_KEY AND SYS_KEY
0037 RETURN
0038 '
0039 ' UFO task
0040 '
0041 @UFO_INI
0042 UFO_MAX=3
0043 DIM UFO_F(UFO_MAX)
0044 DIM UFO_X(UFO_MAX)
0045 DIM UFO_Y(UFO_MAX)
0046 DIM UFO_CNT(UFO_MAX)
0047 FOR I=0 TO UFO_MAX-1
0048 UFO_F(I)=0
0049 UFO_CNT(I)=RND(120)
0050 NEXT I
0051 UFO_SX = 0.1
0052 RETURN
0053 '
0054 @UFO_TASK
0055 FOR UFO_I=0 TO UFO_MAX-1
0056 GOSUB @UFO_SUB
0057 NEXT UFO_I
0058 RETURN
0059 '
0060 @UFO_SUB
0061 ON UFO_F(UFO_I) GOTO @UFO_WAIT,@UFO_MVR,@UFO_MVL,@UFO_EXPL
0062 STOP
0063 '
0064 @UFO_WAIT
0065 UFO_CNT(UFO_I) = UFO_CNT(UFO_I) - 1
0066 IF UFO_CNT(UFO_I) > 0 THEN RETURN
0067 IF RND(2) GOTO @UFO_LSET
0068 GOTO @UFO_RSET
0069 ' move right
0070 @UFO_MVR
0071 LOCATE UFO_X(UFO_I), UFO_Y(UFO_I)
0072 PRINT "A"
0073 UFO_X(UFO_I) = UFO_X(UFO_I) + UFO_SX
0074 IF UFO_X(UFO_I) > 32 GOTO @UFO_DETH
0075 HITX = UFO_X(UFO_I)
0076 HITY = UFO_Y(UFO_I)
0077 GOSUB @WPN_HITC
0078 IF HITF GOTO @UFO_DAMG
0079 GOSUB @UFW_FIRE
0080 RETURN
0081 '
0082 @UFO_LSET
0083 UFO_X(UFO_I) = 31
0084 UFO_Y(UFO_I) = RND(10)
0085 UFO_F(UFO_I) = 2
0086 RETURN
0087 ' move left
0088 @UFO_MVL
0089 LOCATE UFO_X(UFO_I), UFO_Y(UFO_I)
0090 PRINT "A"
0091 UFO_X(UFO_I) = UFO_X(UFO_I) - UFO_SX
0092 IF UFO_X(UFO_I) < 0 GOTO @UFO_DETH
0093 HITX = UFO_X(UFO_I)
0094 HITY = UFO_Y(UFO_I)
0095 GOSUB @WPN_HITC
0096 IF HITF GOTO @UFO_DAMG
0097 GOSUB @UFW_FIRE
0098 RETURN
0099 '
0100 @UFO_RSET
0101 UFO_X(UFO_I) = 0
0102 UFO_Y(UFO_I) = RND(10)
0103 UFO_F(UFO_I) = 1
0104 RETURN
0105 '
0106 @UFO_DAMG
0107 BEEP 13
0108 SCORE=SCORE+1
0109 '
0110 UFO_F(UFO_I)=3
0111 UFO_CNT(UFO_I)=30
0112 RETURN
0113 '
0114 @UFO_EXPL
0115 LOCATE UFO_X(UFO_I),UFO_Y(UFO_I)
0116 IF SYS_CNT AND 8 GOTO @LBL101
0117 PRINT"●";
0118 GOTO @LBL100
0119 @LBL101
0120 PRINT"*";
0121 @LBL100
0122 UFO_CNT(UFO_I)=UFO_CNT(UFO_I)-1
0123 IF UFO_CNT(UFO_I)!=0 THEN RETURN
0124 '
0125 @UFO_DETH
0126 UFO_F(UFO_I) = 0
0127 UFO_CNT(UFO_I) = RND(60)
0128 RETURN
0129 '
0130 ' UFO weapon
0131 '
0132 @UFQ_INI
0133 UFW_MAX=10
0134 DIM UFW_F(UFW_MAX)
0135 DIM UFW_X(UFW_MAX)
0136 DIM UFW_Y(UFW_MAX)
0137 FOR I=0 TO UFW_MAX-1
0138 UFW_F(I)=0
0139 NEXT I
0140 UFW_SY=0.1
0141 RETURN
0142 '
0143 @UFW_TASK
0144 FOR UFW_I=0 TO UFW_MAX-1
0145 GOSUB @UFW_SUB
0146 NEXT UFW_I
0147 RETURN
0148 '
0149 @UFW_SUB
0150 ON UFW_F(UFW_I) GOTO @WFW_WAIT,@UFW_MOVE
0151 STOP
0152 '
0153 @UFW_WAIT
0154 RETURN
0155 '
0156 @UFW_MOVE
0157 LOCATE UFW_X(UFW_I),UFW_Y(UFW_I)
0158 PRINT"$";
0159 UFW_Y(UFW_I)=UFW_Y(UFW_I)+UFW_SY
0160 IF UFW_Y(UFW_I)>22 GOTO @UFW_DETH
0161 '
0162 HITX=UFW_X(UFW_I)
0163 HITY=UFW_Y(UFW_I)
0164 GOSUB @PLY_HITC
0165 IF HITF GOTO @UFW_DETH
0166 GOSUB @WPN_HITC
0167 IF HITF==0 THEN RETURN
0168 '
0169 @UFW_DETH
0170 UFW_F(UFW_I)=0
0171 RETURN
0172 '
0173 @UFW_FIRE
0174 IF SYS_CNT AND &H7F THEN RETURN
0175 '
0176 N=0
0177 @LBL300
0178 IF UFW_F(N)==0 GOTO @LBL301
0179 N=N+1
0180 IF N < UFW_MAX GOTO @LBL300
0181 RETURN

0182 '
0183 @LBL301
0184 BEEP 0
0185 UFW_F(N)=1
0186 UFW_X(N)=UFO_X(UFO_I)
0187 UFW_Y(N)=UFO_Y(UFO_I)+1
0188 RETURN
0189 '
0190 ' player task
0191 '
0192 @PLY_INI
0193 PLY_X = 15
0194 PLY_Y = 21
0195 PLY_SX = 0.5
0196 PLY_F = 0
0197 PLY_HITF=1
0198 RETURN
0199 '
0200 @PLY_TASK
0201 ON PLY_F GOTO @PLY_STOP,@PLY_MVR,@PLY_MVL,@PLY_EXPL,@PLY_WAIT
0202 STOP
0203 ' stop
0204 @PLY_STOP
0205 LOCATE PLY_X,PLY_Y
0206 PRINT "P"
0207 IF ON_KEY AND 16 THEN GOSUB @WPN_FIRE
0208 IF SYS_KEY AND 8 GOTO @PLY1
0209 IF SYS_KEY AND 4 GOTO @PLY2
0210 RETURN
0211 @PLY1
0212 PLY_F = 1
0213 RETURN
0214 @PLY2
0215 PLY_F = 2
0216 RETURN
0217 ' move right
0218 @PLY_MVR
0219 LOCATE PLY_X,PLY_Y
0220 PRINT "P"
0221 IF ON_KEY AND 16 THEN GOSUB @WPN_FIRE
0222 PLY_X = PLY_X + PLY_SX
0223 IF PLY_X > 31 THEN PLY_X = 31
0224 IF SYS_KEY AND 8 THEN RETURN
0225 PLY_F = 0
0226 RETURN
0227 ' move left
0228 @PLY_MVL
0229 LOCATE PLY_X,PLY_Y
0230 PRINT "P"
0231 IF ON_KEY AND 16 THEN GOSUB @WPN_FIRE
0232 PLY_X = PLY_X - PLY_SX
0233 IF PLY_X < 0 THEN PLY_X = 0
0234 IF SYS_KEY AND 4 THEN RETURN
0235 PLY_F = 0
0236 RETURN
0237 '
0238 @PLY_EXPL
0239 LOCATE PLY_X,PLY_Y
0240 IF SYS_CNT AND 8 GOTO @LBL200
0241 PRINT"○";
0242 GOTO @LBL201
0243 @LBL200
0244 PRINT"◎";
0245 @LBL201
0246 PLY_CNT=PLY_CNT-1
0247 IF PLY_CNT!=0 THEN RETURN
0248 '
0249 PLY_F=4
0250 RETURN
0251 '
0252 @PLY_WAIT
0253 IF SYS_CNT AND &H40 GOTO @LBL202
0254 LOCATE 11,11
0255 PRINT"GAME OVER";
0256 @LBL202
0257 RETURN
0258 '
0259 @PLY_HITC
0260 HITF=0
0261 IF PLY_HITF==0 THEN RETURN
0262 IF FLOOR(PLY_X)!=FLOOR(HITX) THEN RETURN
0263 IF FLOOR(PLY_Y)!=FLOOR(HITY) THEN RETURN
0264 HITF=1
0265 '
0266 BEEP 13
0267 PLY_F=3
0268 PLY_HITF=0
0269 PLY_CNT=30
0270 RETURN
0271 '
0272 ' weapon task
0273 '
0274 @WPN_INI
0275 WPN_MAX = 3
0276 DIM WPN_F(WPN_MAX)
0277 DIM WPN_X(WPN_MAX)
0278 DIM WPN_Y(WPN_MAX)
0279 FOR I=0 TO WPN_MAX-1
0280 WPN_F(I) = 0
0281 NEXT I
0282 WPN_SY = 0.5
0283 RETURN
0284 '
0285 @WPN_TASK
0286 FOR WPN_I=0 TO WPN_MAX-1
0287 GOSUB @WPN_SUB
0288 NEXT WPN_I
0289 RETURN
0290 '
0291 @WPN_SUB
0292 ON WPN_F(WPN_I) GOTO @WPN_WAIT,@WPN_MOVE
0293 STOP
0294 '
0295 @WPN_WAIT
0296 RETURN
0297 '
0298 @WPN_MOVE
0299 LOCATE WPN_X(WPN_I),WPN_Y(WPN_I)
0300 PRINT "!"
0301 WPN_Y(WPN_I) = WPN_Y(WPN_I) + WPN_SY
0302 IF WPN_Y(WPN_I) >= 0 THEN RETURN
0303 WPN_F(WPN_I) = 0
0304 RETURN
0305 '
0306 @WPN_FIRE
0307 GOSUB @WPN_GET
0308 IF WPN_N < 0 THEN RETURN
0309 BEEP 10
0310 WPN_F(WPN_N) = 1
0311 WPN_X(WPN_N) = PLY_X
0312 WPN_Y(WPN_N) = 20
0313 RETURN
0314 '
0315 @WPN_HITC
0316 HITF = 0
0317 'FOR WPN_N=0 TO WPN_MAX-1
0318 WPN_N=0
0319 @LBL003
0320 IF WPN_F(WPN_N) == 0 GOTO @WPN_NEXT
0321 IF FLOOR(WPN_X(WPN_N)) != FLOOR(HITX) GOTO @WPN_NEXT
0322 IF FLOOR(WPN_Y(WPN_N)) == FLOOR(HITY) GOTO @WPN_HOK
0323 @WPN_NEXT
0324 'NEXT WPN_N
0325 IF WPN_N==WPN_MAX-1 THEN RETURN
0326 WPN_N=WPN_N+1
0327 GOTO @LBL003
0328 '
0329 @WPN_HOK
0330 HITF = 1
0331 WPN_F(WPN_N) = 0
0332 RETURN
0333 '
0334 @WPN_GET
0335 'FOR WPN_N=0 TO WPN_MAX-1
0336 WPN_N=0
0337 @LBL001
0338 IF WPN_F(WPN_N)==0 THEN RETURN
0339 'NEXT WPN_N
0340 IF WPN_N==WPN_MAX-1 GOTO @LBL002
0341 WPN_N=WPN_N+1
0342 GOTO @LBL001
0343 @LBL002
0344 WPN_N = -1
0345 RETURN
0346 'End of line


誤表示の件ですが実はプログラム中に不等号(’>’および’<’)がある場合です。
HTMLタグがこの不等号を使用しているため、回避策として’>’の場合には’&gt;’、’<’の場合’&lt;’と記述すると問題はなくなります。
ただ、プログラムとして読みづらいので無視していました。
書き方によっては誤表示を起こさないので今回はそちらに変更しています。
チェックポイント
以前に追加したシステムカウンタを使ったアニメーションの例です。
システムカウンタにマスク処理を行うことでインターバル処理を行うことができます。


今回はシステムカウンタの使用方法を解説します。
まずは簡単なアニメーションを行うためにシステムカウンタにマスク処理を行い使用します。
サンプルでは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フレーム毎に何か処理することができます。


チェックポイント
前回の乱数導入でプログラムの変更が完全ではありませんでした。
UFOにY座標を付加したのですが当たり判定でそのY座標の変更をしていませんでした。


UFOタスクの修正プログラムです。

■プログラム
'
' 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
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_DETH
HITX = UFO_X
HITY = UFO_Y
GOSUB @WPN_HITC
IF HITF GOTO @UFO_DETH
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_DETH
RETURN
'
@UFO_RSET
UFO_X = 0
UFO_Y = RND(10)
UFO_F = 1
RETURN
'
@UFO_DETH
UFO_F = 0
UFO_CNT = RND(60)
RETURN

ペタしてね