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

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

[HSP]第4回 敵機の表示 (シューティング・ゲームのミニ講座)

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

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


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

敵機の管理

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

dim enemyF,20
dim enemyX,20
dim enemyY,20

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

  • enemyF は、敵機の有無フラグで 0 なら無効、1 なら有効を意味
  • enemyX は、敵機の横軸で 0 ~ 550 の値を管理(敵機の横サイズが 50 の場合)
  • enemyY は、敵機の縦軸で 0 ~ 350 の値を管理(敵機の縦サイズが 50 の場合)

敵機の処理

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

*Init dim enemyF,20 dim enemyX,20 dim enemyY,20
*Main screen 0,600,400,SCREEN_FIXEDSIZE font MSGOTHIC,50
randomize
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 color $00,$00,$00:boxf color $00,$FF,$00:pos x,y:mes "山"
gosub *EnemyBirth gosub *EnemyDraw
redraw 1 await (1000/60) loop stop
*EnemyBirth ; ;記述 ; return *EnemyDraw ; ;記述 ; return

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

敵機の発生

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

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

    1. 敵機の有無フラグに 1 をセット
    2. 敵機の横軸(x)に 0 ~ 550 をセット(乱数で決定)
    3. 敵機の縦軸(y)に -50 をセット

  3. 繰り返しを抜ける
*EnemyBirth
    foreach enemyF
        if(enemyF(cnt)==0){
            enemyF(cnt)=1
            enemyX(cnt)=rnd(600/50)*50
            enemyY(cnt)=-50
            break
        }
    loop
    return

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

どうですか?
前回の「弾丸の発射」とほぼ同じですね。
つまり、弾丸の発生、敵機の発生、流星の発生などは、同じ要領で管理できるのです。
これで「敵機の発生」は一通り終わりです。

敵機の描画

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

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

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

  3. 敵機の描画位置を設定(pos)
  4. 敵機の描画色を設定(color)
  5. 敵機の文字を描画(mes)
*EnemyDraw
    foreach enemyF
        if enemyF(cnt){
            enemyY(cnt)+=3:if(enemyY(cnt)>400):enemyF(cnt)=0:continue
            pos enemyX(cnt),enemyY(cnt)
            color $00,$FF,$FF:mes "Ж"
        }
    loop
    return

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

敵機の表示

//------------------------------------------------------------------------------
// シューティング・ゲームのミニ講座 for HSP(Ver.3.3.2)
//==============================================================================
// 第4回「敵機の表示」by 科学太郎
//------------------------------------------------------------------------------

//--------------------------------------
// メイン部
//--------------------------------------
*Init
    ;敵機の管理
    dim enemyF,20
    dim enemyX,20
    dim enemyY,20
*Main
    screen 0,600,400,SCREEN_FIXEDSIZE
    font MSGOTHIC,50
    randomize
    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
        color $00,$00,$00:boxf
        color $00,$FF,$00:pos x,y:mes "山"
        gosub *EnemyBirth
        gosub *EnemyDraw
        redraw 1
        await (1000/60)
    loop
    stop
//--------------------------------------
// 敵機の発生
//--------------------------------------
*EnemyBirth
    foreach enemyF
        if(enemyF(cnt)==0){
            enemyF(cnt)=1
            enemyX(cnt)=rnd(600/50)*50
            enemyY(cnt)=-50
            break
        }
    loop
    return
//--------------------------------------
// 敵機の描画
//--------------------------------------
*EnemyDraw
    foreach enemyF
        if enemyF(cnt){
            enemyY(cnt)+=3:if(enemyY(cnt)>400):enemyF(cnt)=0:continue
            pos enemyX(cnt),enemyY(cnt)
            color $00,$FF,$FF:mes "Ж"
        }
    loop
    return
//------------------------------------------------------------------------------
// End of lesson-4.hsp
//------------------------------------------------------------------------------

上記のソースを実行すると一度に20匹の敵機が発生しますね。
これは敵機が発生するタイミングを連続して誕生させてるからです。
前回の「弾丸の発射」の連射と同じ現象です。

発生の間隔

それでは前回の「弾丸の発射」を参考に敵機の発生間隔を組み込んでみましょう。
とりあえず10サイクルに1匹の敵機が発生することにしましょう。
改良する部分は EnemyBirth のサブルーチンですよ。

*EnemyBirth
if(enemyCycle):enemyCycle--:return
foreach enemyF if(enemyF(cnt)==0){ enemyF(cnt)=1 enemyX(cnt)=rnd(600/50)*50 enemyY(cnt)=-50 break } loop
enemyCycle=10
return

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

でも、まだ、発生間隔が短すぎて大量に敵機が発生してますね。
これでは、ゲームの難易度が高くなってしまいます。
しかし、この発生間隔を変えることで「ゲームの難易度」を変えることが可能かもしれません。

それでは enemyCycle 変数に 20、30、40、… 60 と発生間隔を多くしてみましょう。
30 ~ 40 当たりが丁度良さそうですが 60 の1秒間に1匹の敵機が発生してもおかしくありませんね。
この発生間隔は、お好みで設定して欲しいと思います。
とりあえず、ミニ講座では 30 に設定しておきますよ。

敵機の表示

それでは第4回目の「敵機の表示」ソースを紹介します。

//------------------------------------------------------------------------------
// シューティング・ゲームのミニ講座 for HSP(Ver.3.3.2)
//==============================================================================
// 第4回「敵機の表示」by 科学太郎
//------------------------------------------------------------------------------

//--------------------------------------
// メイン部
//--------------------------------------
*Init
    ;敵機の管理
    dim enemyF,20
    dim enemyX,20
    dim enemyY,20
*Main
    screen 0,600,400,SCREEN_FIXEDSIZE
    font MSGOTHIC,50
    randomize
    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
        color $00,$00,$00:boxf
        color $00,$FF,$00:pos x,y:mes "山"
        gosub *EnemyBirth
        gosub *EnemyDraw
        redraw 1
        await (1000/60)
    loop
    stop
//--------------------------------------
// 敵機の発生
//--------------------------------------
*EnemyBirth
    if(enemyCycle):enemyCycle--:return
    foreach enemyF
        if(enemyF(cnt)==0){
            enemyF(cnt)=1
            enemyX(cnt)=rnd(600/50)*50
            enemyY(cnt)=-50
            break
        }
    loop
    enemyCycle=30
    return
//--------------------------------------
// 敵機の描画
//--------------------------------------
*EnemyDraw
    foreach enemyF
        if enemyF(cnt){
            enemyY(cnt)+=3:if(enemyY(cnt)>400):enemyF(cnt)=0:continue
            pos enemyX(cnt),enemyY(cnt)
            color $00,$FF,$FF:mes "Ж"
        }
    loop
    return
//------------------------------------------------------------------------------
// End of lesson-4.hsp
//------------------------------------------------------------------------------

これで「敵機の表示」は終わります。
次は自機、敵機、自機弾の「当たり判定」を紹介します。(次を読む)

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

コメント    この記事についてブログを書く
  • Twitterでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« [HSP]第3回 弾丸の発射 (シ... | トップ | [HSP]第5回 当たり判定 (シ... »
最新の画像もっと見る

コメントを投稿

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