今回はプレイヤーがスペースキーを押すことで、自機から弾を発射するプログラムを作ってみます。
前回のVol18. 【2Dシューティング】自機を動かそうで作成したコードに手を加える形で作業を進めます。赤色で示すコードが前回からの変更点または追加点です。
弾は一つのシーンの中で無数に発射されるため、それぞれの動きを常に監視しなければなりません。
まずはゲーム内に存在できる(管理可能な)弾の個数をMAX_SHOTS定数に指定します。弾の一つ一つは、CShotオブジェクトとして生成するのですが、それらを総括して管理しなければなりません。ここではpShotsArrayというオブジェクト配列を用意して、複数のオブジェクトを一つの配列で管理できるようにしています。ShotTime及びTempTime_Shotは、スペースキーが長押しされた場合に、弾を一定間隔で発射するためのカウンタとして利用します。
#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 '弾の最大数 '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
自機が弾を発射するためのメンバ関数CPlane::Shotを定義します。自機はあくまでも弾を発射するだけなので、このCPlane::Shot関数の内容は、CShotオブジェクトを生成するだけになります。その後の動作は、CShotオブジェクトに委ねられます。
'---------------
' 自機クラス
'---------------
Class CPlane
'位置・高さ・幅
x As Long
y As Long
width As Long
height As Long
'移動スピード
speed As Long
'傾き
RudderSituation As Single
'自機が画面からはみ出さないようにチェックする関数
Sub EreaOutCheck()
If x-width/2<0 Then
x=width/2
End If
If x+width/2>SCREEN_WIDTH Then
x=SCREEN_WIDTH-width/2
End If
If y-height/2<0 Then
y=height/2
End If
If y+height/2>SCREEN_HEIGHT Then
y=SCREEN_HEIGHT-height/2
End If
End Sub
Public
'コンストラクタ
Sub CPlane()
width=32
height=32
'初期位置
x=SCREEN_WIDTH/2
y=SCREEN_HEIGHT*0.8
'初期スピード
speed=5
End Sub
'デストラクタ
Sub ~CPlane()
End Sub
'描画
Sub Draw()
Dim TextureX As Long, TextureY As Long
TextureX=32*(Fix(RudderSituation)+2)
TextureY=0
pImage_CharaMap1->DrawStretch(
x-width/2 +SCREENBASE_X,
y-height/2 +SCREENBASE_Y,
width,
height,
TextureX,
TextureY,
32,
32)
End Sub
'自機を移動させる関数
Sub MoveUp()
y=y-speed
EreaOutCheck()
End Sub
Sub MoveDown()
y=y+speed
EreaOutCheck()
End Sub
Sub MoveLeft()
x=x-speed
EreaOutCheck()
If RudderSituation>-2 Then
'左方向に移動中は自機の傾きをマイナス値にする
RudderSituation=RudderSituation-1/speed
End If
End Sub
Sub MoveRight()
x=x+speed
EreaOutCheck()
If RudderSituation<2 Then
'右方向に移動中は自機の傾きをプラス値にする
RudderSituation=RudderSituation+1/speed
End If
End Sub
Sub NoMove()
'移動していないときは自機の傾きを0に近づける
If RudderSituation<0 Then
RudderSituation=RudderSituation+1/speed
ElseIf RudderSituation>0 Then
RudderSituation=RudderSituation-1/speed
End If
End Sub
Sub Shot()
'弾を撃つ
Dim pShot As *CShot
pShot=New CShot(x,y-width/2)
End Sub
End Class
まずは、CShotオブジェクトが生成されたときに呼び出されるAddShot関数、消滅するときに呼び出されるDeleteShot関数を定義します。AddShot関数は、弾を管理するためのオブジェクト配列pShotsArrayに生成直後のCShotオブジェクトを登録する働きをします。DeleteShot関数はその逆で、CShotオブジェクトが破棄されるときにpShotsArrayからそのオブジェクトを排除する働きをします。
'-----------------------
' ショット(弾)の管理
'-----------------------
Sub AddShot(pShot As *CShot)
Dim i As Long
For i=0 To ELM(MAX_SHOTS)
If pShotsArray[i]=0 Then
pShotsArray[i]=pShot
Exit For
End If
Next
End Sub
Sub DeleteShot(pShot As *CShot)
Dim i As Long
For i=0 To ELM(MAX_SHOTS)
If pShotsArray[i]=pShot Then
pShotsArray[i]=0
Exit For
End If
Next
End Sub
'--------------
' ショット(弾)クラス
'--------------
Class CShot
x As Long
y As Long
width As Long
height As Long
speed As Long
Sub EreaOutCheck()
'はみ出しチェック
If y-height/2<0 Then
'画面をはみ出したので、自爆させる
Delete VarPtr(This)
End If
End Sub
Public
Sub CShot(sx As Long, sy As Long)
width=4
height=16
speed=15
'初期位置
x=sx
y=sy
AddShot(VarPtr(This))
End Sub
Sub ~CShot()
DeleteShot(VarPtr(This))
End Sub
'描画
Sub Draw()
pImage_CharaMap2->DrawStretch(
x-width/2 +SCREENBASE_X,
y-height/2 +SCREENBASE_Y,
width,
height,
6,
48,
width,
height)
y=y-speed
EreaOutCheck()
End Sub
End Class
スペースキーが押されたときにCPlane::Shot関数を呼び出すためのコードを記述します。カウンタ変数ShotTime及びTempTime_Shotを活用して、スペースキーが長押しされたときは一定間隔で弾を発射されるようにします。この関数は60FPS(一秒間に60回)で呼ばれるため、ここに示すコードでは一秒間に20回の連射ができるようになっています。
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
End Sub
弾を描画するためのコードを追加します。
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
End Sub
スペースキーを押すと、弾の連発ができるようになっているはずです。次回は、敵機を出現させてみます。
講座インデックスへ戻る | ©2005 Discoversoft |