HSP教室 入門編(うすあじさんの運営されているHSPCenter内)、今日は、
その12 ブロック崩し(4)
の完全版です。
以下は打ち込んだプログラムです。多少いじってます。↓
;その11 ブロック崩し3 ラケット+ボール
screen 0,600,480 ;ID0のスクリーンを初期化
cls 4 ;黒で画面クリアー
yy=350 ;ラケットのY座標
bsixe=10 ;ボールの大きさ
gamex=ginfo_winx-20 ;ゲーム域、横幅
gamey=ginfo_winy-30 ;ゲーム域、縦幅
gosub *newball ;ボールを生成するルーチンへ
sdim map,50 ;変数mapに50文字分のメモリを確保
map="1111111"+"1010101"+"1101011"+"1111111" ;
nowmap=""
nowmap=map
gosub *allbl ;全ブロック表示サブルーチンへ
*mainlp ;メインルーチン
gosub *ballmove ;ボールを動かすルーチンへ
gosub *ballput ;ボールを設置するルーチンへ
gosub *memove ;ラケットを動かすルーチンへ
gosub *newball ;ボールを生成するルーチンへ
await 20 ;待ち時間
goto *mainlp ;無限ループ
*newball ;ボール生成ルーチン
if bf!0 : return ;ボールが存在しないならリターン
randomize ;乱数攪拌
rr=rnd(400) ;0〜399までの乱数
bx=50+rr ;ボールの発生位置x座標
rr=rnd(20)-10 ;-10〜9までの乱数(毎回違う角度スピードにするため)
if rr>-2 & rr<2:rr=5 ;rrが-1,0,1の時rr=5にする(角度調整)
by=1 ;ボールの発生位置y座標
dx=rr : dy=5 ;ボールの移動距離
bf=1 ;ボール存在するフラグ上げ
*ballmove ;ボールを動かすルーチン
if bf=0 : return ;ボールが存在しないならリターン
bx=bx+dx ;ボールをx座標だけ動かす
;左右の壁判定↓
if bx<0:bx=0:dx=0-dx ;左壁を超すなら反対向ける
if bx>gamex:bx=gamex:dx=0-dx ;右壁を超すなら反対向ける
gosub *blckx ;ブロックにボールが当たったか判定(X座標)
byy=by ;古いY座標をbyyに代入
by=by+dy ;ボールをy座標だけ動かす
if by<0:by=0:dy=0-dy ;天井を超すなら反対向ける
if (byy<350)&(by>=350):goto *rcheck
;↑古いY座標が350未満、かつ新座標が350以上なら*rcheckへ
gosub *blcky ;ブロックにボールが当たったか判定(Y座標)
if by>480:bf=0:color 0,0,0:boxf bxx,byy,bxx+bsixe,byy+bsixe
;↑Y座標が画面の底を超えたらボールを消去
return
*rcheck ;ラケット当たり判定
if bx<xx:return ;ラケットの左側ならリターン
if bx>(xx+100):return ;ラケットの右側ならリターン
;ラケットに当たったので、
by=350:dy=0-dy:return ;ボールを反対向け、リターン
*overcheck ;ゲーム領域内かどうかチェックする
if by<450:return ;ゲーム領域内ならリターン
bf=0 ;ボール非存在(フラグ下げ)
color 0,0,0:boxf bxx,byy,bxx+bsixe,byy+bsixe ;ゲーム領域外なのでボール消去
return
*ballput ;ボールを設置するルーチン
if bf=0 : return ;ボールが存在しないならリターン
color 0,0,0:boxf bxx,byy,bxx+bsixe,byy+bsixe ;古いボール消去
color 255,255,255:circle bx,by,bx+bsixe,by+bsixe,1 ;新しいボール設置
bxx=bx : byy=by ;ボール現在位置を古い位置に設定
return
*memove ;ラケットを動かすルーチン
xx=mousex ;マウスの現在位置(X座標)を得る
if xx<0 : xx=0 ;マウス位置の左壁限界
if xx>490 : xx=490 ;マウス位置の右壁限界
if xxx!xx:color 0,0,0:boxf xxx,yy,xxx+100,yy+10
;↑ラケットの旧位置と現在位置が違うなら(ラケットが動いたら)ラケットを消去
color 130,130,100:boxf xx,yy,xx+100,yy+10 ;新ラケット表示
xxx=xx ;現在位置を旧位置に設定
return
*blckx ;ブロックにボールが当たったか判定(X座標)
if (bx<19)|(bx>579) :return ;ブロックのない左右はリターン
if (by<39)|(by>119) :return ;ブロックのない上下はリターン
xof=(bx-20)/80 ;左から何番目のブロックか
※ yof=(by-40)/20 ;上から何番目のブロックか
i=yof*7+xof ;左上からi番目のブロック
code=peek(nowmap,i) ;i番目の配列を読む
if code='0':return ;0(ブロックが非存在)
dx=0-dx ;ブロックに当たったのでボールを反対向ける
zz='0' ;ブロックが破壊された
poke nowmap,i,zz ;配列のi番目にzzを書き込む
gosub *allbl ;全ブロック表示サブルーチンへ
return
*blcky ;ブロックにボールが当たったか判定(Y座標)
if (bx<19)|(bx>579) :return ;ブロックのない左右はリターン
if (by<39)|(by>119) :return ;ブロックのない上下はリターン
xof=(bx-20)/80 ;左から何番目のブロックか
yof=(by-40)/20 ;上から何番目のブロックか
i=yof*7+xof ;左上からi番目のブロック
code=peek(nowmap,i) ;i番目の配列を読む
if code='0':return ;0(ブロックが非存在)
dy=0-dy ;ブロックに当たったのでボールを反対向ける
zz='0' ;ブロックが破壊された
poke nowmap,i,zz ;配列のi番目にzzを書き込む gosub *allbl ;全ブロック表示サブルーチンへ
return
*allbl ;全ブロック表示サブルーチン
i=0:cc=0
repeat 4 ;ループ1、以下を4回繰り返す
cty=cnt ;ループ回数をctyに代入
repeat 7 ;ループ2、以下を7回繰り返す
code=peek(nowmap,i) ;nowmapからi番目の値をcodeに代入
i++ ;iを1増やす
if code='0':color 0,0,0 ;codeが0なら黒(何もなし)
if code='1':color 208,219,119:cc++
;↑codeが1なら色をつけて(ブロックあり)ccを1増やす
boxf cnt*80+20,cty*20+40,cnt*80+20+75,cty*20+40+15
;↑座標(ループ2のループ数× 80+20,ループ1のループ数× 20+40)から75× 15の大きさのブロックを描く
loop ;ループ2
loop ;ループ1
if cc=0:nowmap=map:goto*allbl ;ブロック数が0なら初期化し最初からブロックを描きなおす
return
実行結果↓

新しい命令の説明↓
◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆<バッファから1byte分書き込む> poke(バッファの変数名,バッファのインデックス,バッファに書き込む値)バッファの何番目か(インデックス数)を新しく書き換える◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆・配列の中身は、'で囲まないといけないようです。'3'というように…。
※の分析
xof=(bx-20)/80 ;左から何番目のブロックか
yof=(by-40)/20 ;上から何番目のブロックか
i=yof*7+xof ;左上からi番目のブロック
において、
xof…ボールが左から何列目の所にいるかというのを知る
yof…ボールが何行目のラインにいるかを知る
ということだと思います。
1行に7こブロックがあるので、ブロックのインデックスは、
インデックス=7列×yof + xof
になります。(だと思います多分)
-----------