プログラミングのメモ帳(C/C++/HSP)

日々のプログラミングで気づいた点や小技集を紹介します。(Windows 10/XP/Vista、VC2017、HSP)

[HSP]第3回 弾丸の発射 (シューティング・ゲームのミニ講座)

2013年12月01日 05時28分03秒 | HSP講座

スクリプト言語の HSP については、公式ホームページの「HSPTV!」をどうぞ。


なお、このページはシューティング・ゲームのミニ講座シリーズの1つです。
今回は第3回「弾丸の発射」について説明します。(戻る)

弾丸の管理

自機の弾丸は、最大10個発射できることを考えてみます。
まずは弾丸の横軸(x)、縦軸(y)は絶対に必要なので、この2つを配列で管理します。
さらに弾丸の配列が、画面内を移動中(有効)か、画面外に外れた(無効)かを判定するフラグ(flag)も必要になりますね。
それでは3つを配列で管理すると次のようになります。

dim tamaF,10
dim tamaX,10
dim tamaY,10

上記の3つの配列は次の意味があります。

  • tamaF は、弾丸の有無フラグで 0 なら無効、1 なら有効を意味
  • tamaX は、弾丸の横軸で 0 ~ 550 の値を管理(弾丸の横サイズが 50 の場合)
  • tamaY は、弾丸の縦軸で 0 ~ 350 の値を管理(弾丸の縦サイズが 50 の場合)

弾丸の処理

弾丸を処理するには、弾丸の発射、移動、描画の最低でも3つの処理が必要です。
今回は、弾丸の発生部(TamaBirth)、弾丸の描画部(TamaDraw)の2つをサブルーチンにします。
なお、弾丸の移動は描画部(TamaDraw)処理と一緒に記述して、サブルーチンの数を減らしてみます。
それでは前回の「自機の操作」ソースに追加してみましょう。

*Init dim tamaF,10 dim tamaX,10 dim tamaY,10
*Main screen 0,600,400,SCREEN_FIXEDSIZE font MSGOTHIC,50 repeat redraw 0 stick key,%1111 if(key&1):x-=5:if(x<0):x=0 if(key&2):y-=5:if(y<0):y=0 if(key&4):x+=5:if(x>550):x=550 if(key&8):y+=5:if(y>350):y=350
if(key&16):gosub *TamaBirth
color $00,$00,$00:boxf color $00,$FF,$00:pos x,y:mes "山"
gosub *TamaDraw
redraw 1 await (1000/60) loop stop
*TamaBirth ; ;記述 ; return *TamaDraw ; ;記述 ; return

とりあえず、上記の4カ所を追加します。

弾丸の発生

それでは、弾丸の発生ルーチン(TamaBirth)を考えてみましょう。
弾丸の発生手順は、次のようになると思います。

  1. tamaF 配列から弾丸情報が無効である場所を探す
  2. 無効領域が見つかったら弾丸を発生(a)~(c)を行う

    1. 弾丸の有無フラグに 1 をセット
    2. 弾丸の横軸(x)に自機の x をセット
    3. 弾丸の縦軸(y)に自機の y をセット

  3. 繰り返しを抜ける
*TamaBirth
    foreach tamaF
        if(tamaF(cnt)==0){
            tamaF(cnt)=1
            tamaX(cnt)=x
            tamaY(cnt)=y
            break
        }
    loop
    return

上記のように tamaF 配列の分だけ繰り返す場合は repeat 命令よりも foreach 命令が便利です。
たったのこれだけで、無効領域に有効な弾丸情報をセットして、新しい弾丸を発生できます。

どうですか?
以外にも簡単ですね。
これで「弾丸の発生」は終わりですよ。

弾丸の描画

続いて、弾丸の描画ルーチン(TamaDraw)を考えてみましょう。
こちらは、弾丸の移動も含まれますので、先に移動処理、続いて描画処理を行います。

  1. tamaF 配列から弾丸情報が有効である場所を探す
  2. 有効領域が見つかったら弾丸の移動(a)~(d)を行う

    1. 弾丸の縦軸(y)から 8 ドット引く
    2. 弾丸の縦軸(y)が画面外に外れたかチェック
    3. 画面外に外れた場合は、弾丸の有無フラグに 0 をセット
    4. 次の繰り返しへジャンプ(continue)

  3. 弾丸の描画位置を設定(pos)
  4. 弾丸の描画色を設定(color)
  5. 弾丸の文字を描画(mes)
*TamaDraw
    foreach tamaF
        if tamaF(cnt){
            tamaY(cnt)-=8:if(tamaY(cnt)<-50):tamaF(cnt)=0:continue
            pos tamaX(cnt),tamaY(cnt)
            color $FF,$FF,$00:mes ":"
        }
    loop
    return

上記のソースで continue 命令がありますが、これを実行すると次の繰り返し処理にジャンプします。
そのため次の行の pos 命令、color 命令、mes 命令は実行されません。
これで「弾丸の移動」+「弾丸の描画」は終わりですね。

弾丸の発射

それでは第3回目の「弾丸の発射」ソースを紹介します。

//------------------------------------------------------------------------------
// シューティング・ゲームのミニ講座 for HSP(Ver.3.3.2)
//==============================================================================
// 第3回「弾丸の発射」by 科学太郎
//------------------------------------------------------------------------------

//--------------------------------------
// メイン部
//--------------------------------------
*Init
    ;弾丸の管理
    dim tamaF,10
    dim tamaX,10
    dim tamaY,10
*Main
    screen 0,600,400,SCREEN_FIXEDSIZE
    font MSGOTHIC,50
    repeat
        redraw 0
        stick key,%1111
        if(key&1):x-=5:if(x<0):x=0
        if(key&2):y-=5:if(y<0):y=0
        if(key&4):x+=5:if(x>550):x=550
        if(key&8):y+=5:if(y>350):y=350
        if(key&16):gosub *TamaBirth
        color $00,$00,$00:boxf
        color $00,$FF,$00:pos x,y:mes "山"
        gosub *TamaDraw
        redraw 1
        await (1000/60)
    loop
    stop
//--------------------------------------
// 弾丸の発生
//--------------------------------------
*TamaBirth
    foreach tamaF
        if(tamaF(cnt)==0){
            tamaF(cnt)=1
            tamaX(cnt)=x
            tamaY(cnt)=y
            break
        }
    loop
    return
//--------------------------------------
// 弾丸の描画
//--------------------------------------
*TamaDraw
    foreach tamaF
        if tamaF(cnt){
            tamaY(cnt)-=8:if(tamaY(cnt)<-50):tamaF(cnt)=0:continue
            pos tamaX(cnt),tamaY(cnt)
            color $FF,$FF,$00:mes ":"
        }
    loop
    return
//------------------------------------------------------------------------------
// End of lesson-3.hsp
//------------------------------------------------------------------------------

上記のソースを実行すると[SPACE]キーを押すことで、1発だけ弾丸が発射されますね。
これは stick 命令で[SPACE]キーがトリガー・タイプなので単発なのです。

弾丸の連射

それでは連射する場合は、どうすれば良いでしょうか。
とりあえず、単純に[SPACE]キーを非トリガー・タイプにしてみましょう。

repeat
    redraw 0
stick key,%11111
if(key&1):x-=5:if(x<0):x=0 if(key&2):y-=5:if(y<0):y=0 if(key&4):x+=5:if(x>550):x=550 if(key&8):y+=5:if(y>350):y=350 if(key&16):gosub *TamaBirth color $00,$00,$00:boxf color $00,$FF,$00:pos x,y:mes "山" gosub *TamaDraw redraw 1 await (1000/60) loop

変更箇所は1カ所です。
メイン部の stick 命令の第2引数を「%1111」から「%11111」に変更してみました。
それでは、実行して見ましょう。

どうですか?
期待通りでしたか。
なぜかレーザのような弾丸が一気に発射されちゃいましたね。
あらら。何これ。という感じでしょうか。

このように一気に弾丸が発射されるのは[SPACE]キーが押しっぱなしの場合は、連続して発射されてるからですよ。
だって連射だもの。ね。おかしくはないでしょう。
でも、期待通りではないよね。

弾丸の間隔

それでは、期待通りの連射とは何か。考えてみましょう。
まずは、1個おきに弾丸が発射されるように改良しましょう。
改良する部分は TamaBirth のサブルーチンのみで行います。

*TamaBirth
if(tamaTrigg):tamaTrigg--:return
foreach tamaF if(tamaF(cnt)==0){ tamaF(cnt)=1 tamaX(cnt)=x tamaY(cnt)=y break } loop
tamaTrigg=2
return

上記の2カ所だけ追加します。
これで tamaTrigg 変数が 0 以外の場合は、デクリメントしてサブルーチンを終わります。
そして tamaTrigg 変数が 0 のみの場合は、弾丸を1発だけ発射しますね。
弾丸の発射が終わったら tamaTrigg 変数に 2 をセットします。
これで2サイクルで1回だけ弾丸が発射されるわけです。

でも、まだ、まだ、発射間隔が短すぎて一気に10発も発射されてますね。
それでは tamaTrigg 変数に 3、4、5、… 60 と発射間隔を多くしてみましょう。
5 ~ 10 当たりが丁度良さそうですが 15 もお気に入りの間隔です。

なお、60 にすると1秒間に1回しか弾丸が発射されず期待外れになります。
この発射間隔は、お好みで設定して欲しいと思います。
とりあえず、ミニ講座では 8 に設定しておきますよ。

弾丸の連射

それでは第3回目の「弾丸の連射」ソースを紹介します。

//------------------------------------------------------------------------------
// シューティング・ゲームのミニ講座 for HSP(Ver.3.3.2)
//==============================================================================
// 第3回「弾丸の発射」by 科学太郎
//------------------------------------------------------------------------------

//--------------------------------------
// メイン部
//--------------------------------------
*Init
    ;弾丸の管理
    dim tamaF,10
    dim tamaX,10
    dim tamaY,10
*Main
    screen 0,600,400,SCREEN_FIXEDSIZE
    font MSGOTHIC,50
    repeat
        redraw 0
        stick key,%11111
        if(key&1):x-=5:if(x<0):x=0
        if(key&2):y-=5:if(y<0):y=0
        if(key&4):x+=5:if(x>550):x=550
        if(key&8):y+=5:if(y>350):y=350
        if(key&16):gosub *TamaBirth
        color $00,$00,$00:boxf
        color $00,$FF,$00:pos x,y:mes "山"
        gosub *TamaDraw
        redraw 1
        await (1000/60)
    loop
    stop
//--------------------------------------
// 弾丸の発生
//--------------------------------------
*TamaBirth
    if(tamaTrigg):tamaTrigg--:return
    foreach tamaF
        if(tamaF(cnt)==0){
            tamaF(cnt)=1
            tamaX(cnt)=x
            tamaY(cnt)=y
            break
        }
    loop
    tamaTrigg=8
    return
//--------------------------------------
// 弾丸の描画
//--------------------------------------
*TamaDraw
    foreach tamaF
        if tamaF(cnt){
            tamaY(cnt)-=8:if(tamaY(cnt)<-50):tamaF(cnt)=0:continue
            pos tamaX(cnt),tamaY(cnt)
            color $FF,$FF,$00:mes ":"
        }
    loop
    return
//------------------------------------------------------------------------------
// End of lesson-3.hsp
//------------------------------------------------------------------------------

これで「弾丸の発射」は終わります。
次は自動的に敵機が発生する「敵機の表示」を紹介します。(次を読む)

←前へ] [目次] [次へ→

コメント    この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« [HSP]第2回 自機の操作 (シ... | トップ | [HSP]第4回 敵機の表示 (シ... »
最新の画像もっと見る

コメントを投稿

HSP講座」カテゴリの最新記事