DirectXプログラミング講座 〜Vol22. 【2Dシューティング】爆発を演出しよう〜

前回までの章で、最低限のシューティング理論をマスターできましたでしょうか?今回からは、シューティングテンプレートに対して、演出効果という付加価値をつけていきたいと思います。

まずは、敵機をやっつけたときに起こる爆発を再現してみましょう。


理論は至って簡単。敵機を撃墜し、プログラム側で敵機を破棄する際に爆発のアニメーションを生成するのです。

今回のサンプルプロジェクト

爆発のアニメーションってどんな風にやるの?

アニメーションとはいっても、特別なことはやりません。ビットマップをコマ送りにして画面に表示するだけです。考えてみれば、自機の動き、弾の動きなんかも時間と共に画面の中を駆けずり回る、アニメーションと捉えることができますね。

Vol17. 【2Dシューティング】自機と背景を表示しようで用意したキャラクタマップその2(chara_map2.bmp)に、爆発アニメーションのコマ画像が含まれているので、それを利用します。

↑の画像をコマ送りにすると…

のような感じで表示できるんですね☆

コーディング作業

前回のVol21. 【2Dシューティング】当たり判定で作成したコードに手を加える形で作業を進めます。赤色で示すコードが前回からの変更点または追加点です。

"fight.abp" の先頭部分のコーディング

MAX_BLASTSで管理できる爆発の最大数を定義します。続いて、すべての爆発オブジェクトを総括して管理するためのオブジェクトポインタ配列pBlastsArrayを定義します。

#include "fight.idx"


Dim ScreenX=640 As Long	'ディスプレイの幅  (ピクセル単位)
Dim ScreenY=480 As Long	'ディスプレイの高さ(ピクセル単位)

' TODO: この位置にグローバル変数を定義してください。

Const SCREENBASE_X=140   'ゲーム画面左上のスクリーンX座標
Const SCREENBASE_Y=0     'ゲーム画面左上のスクリーンY座標
Const SCREEN_WIDTH=360   'ゲーム画面の幅
Const SCREEN_HEIGHT=480  'ゲーム画面の高さ

Const MAX_SHOTS=50     '弾の最大数
Const MAX_ENEMIES=50   '敵機の最大数
Const MAX_BLASTS=50    '爆発の最大数

'DirectInput用
Dim pInKey As *CInputKeyboard

'背景画像
Dim pImage_BackGround As *CImage2D

'キャラクタマップ画像
Dim pImage_CharaMap1 As *CImage2D
Dim pImage_CharaMap2 As *CImage2D

'ショット(弾)を管理する配列
Dim pShotsArray[ELM(MAX_SHOTS)] As *CShot
Dim ShotTime As Long, TempTime_Shot As Long

'自機クラス
Dim pMyPlane As *CPlane

'敵機クラス
Dim pEnemiesArray[ELM(MAX_ENEMIES)] As *CEnemie
Dim TempTime_Enemie=0 As Long

'爆発を管理する配列
Dim pBlastsArray[ELM(MAX_BLASTS)] As *CBlast

爆発の管理及びCBlastのコーディング

まずは、CBlastオブジェクトが生成されたときに呼び出されるAddBlast関数、消滅するときに呼び出されるDeleteBlast関数を定義します。AddBlast関数は、敵機を管理するためのオブジェクト配列pBlastsArrayに生成直後のCBlastオブジェクトを登録する働きをします。DeleteBlast関数はその逆で、CBlastオブジェクトが破棄されるときにpBlastsArrayからそのオブジェクトを排除する働きをします。

CBlastは、爆発を管理するクラスです。メンバ変数TempTime、TempStepを利用して一定間隔でのコマ送り再生を可能にしています。爆発し終わると、自動的にオブジェクト自身を破棄します。

'-------------
' 爆発の管理
'-------------
Sub AddBlast(pBlast As *CBlast)
    Dim i As Long

    For i=0 To ELM(MAX_BLASTS)
        If pBlastsArray[i]=0 Then
            pBlastsArray[i]=pBlast
            Exit For
        End If
    Next
End Sub
Sub DeleteBlast(pBlast As *CBlast)
    Dim i As Long

    For i=0 To ELM(MAX_BLASTS)
        If pBlastsArray[i]=pBlast Then
            pBlastsArray[i]=0
            Exit For
        End If
    Next
End Sub

'-----------------
' 爆発クラス
'-----------------
Class CBlast
    '位置
    x As Long
    y As Long
    width As Long
    height As Long

    TempTime As Long
    TempStep As Long

Public

    Sub CBlast(sx As Long, sy As Long)
        x=sx
        y=sy
        width=32
        height=32

        TempTime=0
        TempStep=-5

        AddBlast(VarPtr(This))
    End Sub

    Sub ~CBlast()
        DeleteBlast(VarPtr(This))
    End Sub

    Sub Draw()
        pImage_CharaMap2->DrawStretch(
            x-width/2    +SCREENBASE_X,
            y-height/2   +SCREENBASE_Y,
            width,
            height,

            Abs(TempStep)*32,
            160,
            width,
            height)

        TempTime=TempTime+1
        If TempTime=3 Then
            If TempStep>=5 Then
                '爆発しきったとき
                Delete VarPtr(This)
                Exit Sub
            End If

            TempStep=TempStep+1
            TempTime=0
        End If
    End Sub
End Class

InputActionProc関数のコーディング

敵機と弾の当たり判定によって敵機を破棄する際に、爆発(CBlastクラス)を生成します。

Sub InputActionProc()
    ' TODO: この位置に入力に関するコードを記述してください。
    '       (キーボード、マウス、ジョイパッド、ジョイスティックなどによる入力)

    ' メモ - キャラクタの移動など、状況進行(アクション)を意味するコードを
    '        記述することもできます。

    Dim KeyState[255] As Byte
    pInKey->GetState(KeyState)

    'ESCキーが押されたときは終了する
    If KeyState[DIK_ESCAPE] and &H80 Then
        PostQuitMessage(0)
    End If

    If KeyState[DIK_UP] and &H80 Then
        '方向キー(上)が押されているとき
        pMyPlane->MoveUp()
    ElseIf KeyState[DIK_DOWN] and &H80 Then
        '方向キー(下)が押されているとき
        pMyPlane->MoveDown()
    End If

    If KeyState[DIK_LEFT] and &H80 Then
        '方向キー(左)
        pMyPlane->MoveLeft()
    ElseIf KeyState[DIK_RIGHT] and &H80 Then
        '方向キー(右)
        pMyPlane->MoveRight()
    Else
        '左右キーが押されていないとき
        pMyPlane->NoMove()
    End If

    ShotTime=ShotTime+1
    If KeyState[DIK_SPACE] and &H80 Then
        'スペースキーが押された、弾を発射
        If ShotTime>TempTime_Shot+3 Then
            pMyPlane->Shot()

            TempTime_Shot=ShotTime
        End If
    End If

    '一定間隔で敵機を生成
    TempTime_Enemie=TempTime_Enemie+1
    If (TempTime_Enemie mod 20)=0 Then
        Dim pEnemie As *CEnemie
        pEnemie=New CEnemie
    End If


    '-----------------------
    ' 弾と敵機の当たり判定
    '-----------------------
    Dim i As Long, i2 As Long
    Dim pos1 As POINTAPI, size1 As SIZE
    Dim pos2 As POINTAPI, size2 As SIZE
    For i=0 To ELM(MAX_SHOTS)
        If pShotsArray[i] Then
            For i2=0 To ELM(MAX_ENEMIES)
                If pEnemiesArray[i2] Then
                    pShotsArray[i]->GetHitPositionAndSize(pos1,size1)
                    pEnemiesArray[i2]->GetHitPositionAndSize(pos2,size2)
                    If HitTest(pos1,size1,pos2,size2) Then
                        '爆発を生成
                        Dim pBlast As *CBlast
                        pBlast=New CBlast(pos2.x,pos2.y)

                        'ヒットしたときは弾、敵機ともに破棄
                        Delete pShotsArray[i]
                        Delete pEnemiesArray[i2]
                        Exit For
                    End If
                End If
            Next
        End If
    Next


    '-------------------------
    ' 敵機と自機の当たり判定
    '-------------------------
    For i=0 To ELM(MAX_SHOTS)
        If pEnemiesArray[i] Then
            pMyPlane->GetHitPositionAndSize(pos1,size1)
            pEnemiesArray[i]->GetHitPositionAndSize(pos2,size2)
            If HitTest(pos1,size1,pos2,size2) Then
                'ヒットしたときは敵機を破棄(同時にビープ音を鳴らす)
                Delete pEnemiesArray[i]
                MessageBeep(0)
                Exit For
            End If
        End If
    Next
End Sub

RenderProc関数のコーディング

爆発を描画するためのコードを追加します。

Sub RenderProc()
    ' TODO: この位置に描画に関するコードを記述してください。

    Dim i As Long

    '背景を描画
    pImage_BackGround->Draw(
        SCREENBASE_X,
        SCREENBASE_Y,
        SCREEN_WIDTH,
        SCREEN_HEIGHT)

    '自機を描画
    pMyPlane->Draw()

    '弾を描画
    For i=0 To ELM(MAX_SHOTS)
        If pShotsArray[i] Then
            pShotsArray[i]->Draw()
        End If
    Next

    '敵機を描画
    For i=0 To ELM(MAX_ENEMIES)
        If pEnemiesArray[i] Then
            pEnemiesArray[i]->Draw()
        End If
    Next

    '爆発を描画
    For i=0 To ELM(MAX_BLASTS)
        If pBlastsArray[i] Then
            pBlastsArray[i]->Draw()
        End If
    Next
End Sub

実行してみよう

敵機を撃墜してみてください。意外とリアルな爆発、ご体験できましたでしょうか??次回は、更に臨場感を高めるために、効果音を鳴らしてみます。



講座インデックスへ戻る ©2005 Discoversoft