API (Application Program Interface) VB6
 キー入力 前へ 目次へ 次へ 

 VisualBasic(VB)のKeyDown, KeyUp, KeyPressプロシージャはキーが押されときに呼び出される。ひとつのキー、例えば[A]キーを押し続けるとリピート機能が働き、連続して[A]が入力される。しかし、リピート機能が働いているときに別のキーを押すとリピート機能が中断する。また、キーを同時に2つ押しても早く押されたキーのデータしか得られない。
 ゲームなどで、移動しながらミサイルを撃つとき、移動のキーを押したままで発射のキーも押したいが、VBでは発射のキーを押した時点で移動が止まってしまう。

 API関数には、調べたいキーが押されているかどうかを判定する関数GetAsyncKeyStateが用意されている。ただし、関数なのでキーを押したかどうか調べたいところでこの関数を実行する必要がある。

Public Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer

 調べたいキーのコードを引数として呼び出すと、そのときに押されていれば0以外の値が返却される。
 例えば、スペースキーが押されているか調べたいときは次のようにIf文を書く。

    If GetAsyncKeyState(vbKeySpace) <> 0 Then
                  <<スペースキーが押されたときの処理>>
    EndIf


 「ゲームの作成」で制作した"UFO Shooting"に追加する

(1) 標準モジュールにAPI関数GetAsyncKeyStateの宣言を追加する。
 APIビューアを使ってもよいし、キーボードから入力してもよい。ただし、英大文字・小文字は区別されるので注意して入力すること。

(2) キー入力の処理をForm_KeyDownプロシージャで行っていたが、API関数GetAsyncKeyStateで行うのでForm_KeyDownプロシージャを次のように4カ所変更する。

Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)Private Sub KeyDown()
    Dim n As Integer
    Dim r As Long
    '自機の移動(←、→)
    If KeyCode = vbKeyLeft Then         '移動(←)If GetAsyncKeyState(vbKeyLeft) <> 0 Then        '移動(←)

        imgTaihou.Left = imgTaihou.Left - Abs(Dx) * 1.5
    ElseIf KeyCode = vbKeyRight Then    '移動(→)ElseIf GetAsyncKeyState(vbKeyRight) <> 0 Then   '移動(→)
        imgTaihou.Left = imgTaihou.Left + Abs(Dx) * 1.5
    End If
    '自機が両端まで到達したとき → 自機を端に固定
    If imgTaihou.Left <= 0 Then     '左枠を越えた
        imgTaihou.Left = 0
    ElseIf imgTaihou.Left + imgTaihou.Width >= Form1.ScaleWidth Then    '右枠を越えた
        imgTaihou.Left = Form1.ScaleWidth - imgTaihou.Width
    End If
    '- - - - - - - - - - - - - - -
    '自機弾発射 スペースキーON and 自機弾 表示ON
    For n = 0 To MaxTama    '自機弾数分調べる
        If KeyCode = vbKeySpace And imgTama1(n).Visible = False ThenIf GetAsyncKeyState(vbKeySpace) <> 0 And imgTama1(n).Visible = False Then
            With imgTama1(n)    '自機弾発射
                .Left = imgTaihou.Left + imgTaihou.Width / 2
                .Top = imgTaihou.Top
                .Visible = True     '自機弾表示ON
            End With
            r = sndPlaySound("ir_end.wav", SND_ASYNC)
            Exit For        '1発だけ発射してforを抜け出す
        End If
    Next n
End Sub

(3) このままでは、サブプロシージャKeyDownはどこからも呼び出されないので、呼び出す命令をタイマーに追加する。

Private Sub Timer1_Timer()
'ゲームのメイン処理
    Dim flag As Integer
    Dim n As Integer

    KeyDown     'キー入力処理    ←追加
    Idou        '自機弾移動処理
    TekiIdou    '敵移動処理
    Tekidan     '敵弾発射と敵弾移動処理
    UFO         'UFO出現とUFO移動処理
    AtariHantei '当たりの判定
    Bakuha      '爆破図表示
    '- - - - - - - - - - - - - - -
    'ゲームオーバー
    If TaihouNokori = -1 Then
        MsgBox "GAME OVER"
        Unload Me
    End If
    '- - - - - - - - - - - - - - -
    'ゲームクリア
    flag = 0
    '敵の残り確認
    For n = 0 To MaxTeki
        If imgTeki(n).Visible = True Then   '敵の残り有り
            flag = 1
            Exit For
        End If
    Next n
    If flag = 0 Then        'Game Clear
        MsgBox "クリア!! 続けます!"
        InitGame            '再スタート
    End If
End Sub

 実行すると、自機を移動しながら自機弾を発射することができる。


【問題点】サブプロシージャの呼出しが続くので処理が重たくなり、動作が遅く感じられる。
  改善策 → サブプロシージャの呼出しをやめ、プロシージャの処理をタイマー(メイン処理)の中に入れてしまう。かなり長いプログラムになる。

 各処理をタイマー(メイン処理)の中に入れると下のリストのようになる。
 このとき、KeyDown(キー入力処理)、 Idou(自機弾移動処理)、 TekiIdou(敵移動処理)、 Tekidan(敵弾発射と敵弾移動処理)、 UFO(UFO出現とUFO移動処理)、 AtariHantei(当たりの判定)、 Bakuha(爆破図表示)のプロシージャは不要になるので削除する。


 キー入力 前へ 目次へ 次へ 
Copyright © 2002 Hiroshi Masuda 

 

 

inserted by FC2 system