goo blog サービス終了のお知らせ 

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

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

[HSP]第2回 自機の操作 (シューティング・ゲームのミニ講座)

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

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


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

キーボードの検出

自機を移動する方法は、キーボード、マウス、ジョイパッドなどがあります。
今回は処理を簡単にするため、キーボード操作のみに限定します。

HSPにはキーボードの入力チェックに getkey 命令、stick 命令の2つが用意されてます。
どちらも押されてるキーボードをチェックできますが、1回の呼び出しで必要キーの全てを取得できる stick 命令を使います。
この命令は、カーソル・キー(4個)、特殊キー(5個)、マウス・ボタン(2個)を1回の呼び出しでチェックできます。
特殊キーは、ゲームで良く使われる[SPC]キー、[ENTER]キー、[CTRL]キー、[ESC]キー、[TAB]キーが含まれます。

この命令は、押されてるか、押されてないかを 0 と 1 のビットデータで返します。
チェックする場合は、ビットデータを2進数(バイナリ値)の考えで 0 と 1 を調べます。
まずは、次の一覧をご覧ください。

押されてるキー 変数の値
種類 キーボード 2進表記 10進表記 16進表記
カーソル・キー
「左上/右下」と覚えよう
[←]キー(左) %00000000001    1 $001
[↑]キー(上) %00000000010    2 $002
[→]キー(右) %00000000100    4 $004
[↓]キー(下) %00000001000    8 $008
特殊キー

「SOURCE」(ソース)
と覚えよう
[SPC]キー(Space) %00000010000   16 $010
[RET]キー(Enter) %00000100000   32 $020
[CTRL]キー(Control) %00001000000   64 $040
[ESC]キー(Escape) %00010000000  128 $080
マウス・ボタン
「左右」と覚えよう
マウスの[左]ボタン %00100000000  256 $100
マウスの[右]ボタン %01000000000  512 $200
特殊キー [TAB]キー(Tab) %10000000000 1024 $400

上記の一覧は[←]キー、[↑]キー、[SPC]キーの3つが同時に押されてると次の値が変数に代入されてます。

  • 2進数で解釈すると「%00000010011」の値が変数にセットされる。
  • 10進数で解釈すると「19」の値が変数にセットされる。
  • 16進数で解釈すると「$013」の値が変数にセットされる。

上記の「19」とは、「1+2+16」の値ですよ。
この「19」を2進数で表現すると「%00000010011」、16進数で表現すると「$013」となるのです。
チェックするときは、ビット論理積の「&」演算子、または「and」マクロ演算子を使います。

等号の「=」演算子を使うと1つしかキーが押されてない時しかチェックできません。
この方法が意図的なものなら良いのですが、通常は複数のキーをチェックするので「=」演算子は使いません。

stick命令のテスト

それでは、以下のサンプルを試してみましょう。
[←][↑][→][↓]キー、[SPC][RET][CTRL][ESC][TAB]キー、[左]ボタン、[右]ボタンを押すことで表示が変わります。
同時に複数のキーを押すと複数の表示になりますよね。
これで複数のキーをチェックできます。

*Main
    screen 0,600,400,SCREEN_FIXEDSIZE
    font MSGOTHIC,20
    repeat
        redraw 0
        color $00,$00,$00:boxf
        color $00,$FF,$00
        stick key,$7FF
        if(key & %00000000001):pos 0,  0:mes "   1:[←]キー"
        if(key & %00000000010):pos 0, 20:mes "   2:[↑]キー"
        if(key & %00000000100):pos 0, 40:mes "   4:[→]キー"
        if(key & %00000001000):pos 0, 60:mes "   8:[↓]キー"
        if(key & %00000010000):pos 0, 80:mes "  16:[SPC]キー"
        if(key & %00000100000):pos 0,100:mes "  32:[RET]キー"
        if(key & %00001000000):pos 0,120:mes "  64:[CTRL]キー"
        if(key & %00010000000):pos 0,140:mes " 128:[ESC]キー"
        if(key & %00100000000):pos 0,160:mes " 256:[左]ボタン"
        if(key & %01000000000):pos 0,180:mes " 512:[右]ボタン"
        if(key & %10000000000):pos 0,200:mes "1024:[TAB]キー"
        redraw 1
        await (1000/60)
    loop
stop

上記のソースでは、key 変数のチェックに2進数を使ってます。
その他にも10進数、16進数でも同じことが出来ます。

16進数の記述

stick key,$7FF
if(key & $001):pos 0,  0:mes "   1:[←]キー"
if(key & $002):pos 0, 20:mes "   2:[↑]キー"
if(key & $004):pos 0, 40:mes "   4:[→]キー"
if(key & $008):pos 0, 60:mes "   8:[↓]キー"
if(key & $010):pos 0, 80:mes "  16:[SPC]キー"
if(key & $020):pos 0,100:mes "  32:[RET]キー"
if(key & $040):pos 0,120:mes "  64:[CTRL]キー"
if(key & $080):pos 0,140:mes " 128:[ESC]キー"
if(key & $100):pos 0,160:mes " 256:[左]ボタン"
if(key & $200):pos 0,180:mes " 512:[右]ボタン"
if(key & $400):pos 0,200:mes "1024:[TAB]キー"

10進数の記述

stick key,$7FF
if(key &    1):pos 0,  0:mes "   1:[←]キー"
if(key &    2):pos 0, 20:mes "   2:[↑]キー"
if(key &    4):pos 0, 40:mes "   4:[→]キー"
if(key &    8):pos 0, 60:mes "   8:[↓]キー"
if(key &   16):pos 0, 80:mes "  16:[SPC]キー"
if(key &   32):pos 0,100:mes "  32:[RET]キー"
if(key &   64):pos 0,120:mes "  64:[CTRL]キー"
if(key &  128):pos 0,140:mes " 128:[ESC]キー"
if(key &  256):pos 0,160:mes " 256:[左]ボタン"
if(key &  512):pos 0,180:mes " 512:[右]ボタン"
if(key & 1024):pos 0,200:mes "1024:[TAB]キー"

また、一般的にはカーソル・キー部分を次のように記述してます。

一般的な記述

stick key,15
if(key&1):[←]キーの処理
if(key&2):[↑]キーの処理
if(key&4):[→]キーの処理
if(key&8):[↓]キーの処理

それから stick 命令の第2引数は、非トリガー・タイプのキーをビットデータで指定します。
この非トリガー・タイプとは、押しっぱなし状態でもキーボードが押されてるか検出できる点です。
そのためカーソル・キーなどの場合は、押しっぱなし状態でも検出可能にするために 15 を指定しましょう。
この 15 の値は 1+2+4+8 の合計で10進数を意味し、2進数ならば「%1111」、16進数ならば「$F」となります。

なお、自機ショット(弾丸)の発射は、キーボードを押した瞬間だけ単発で打ちたいことがあります。
このような場合にはトリガー・タイプですから第2引数の非トリガー・タイプを指定しません。
つまり、指定しないとキーボードを押した瞬間の1回だけを検出するのが基本となります。

自機の移動

それでは本題のカーソル・キーによる自機の移動を考えてみます。
全体的には、次のような感じです。

  1. [←]キーが押されてるかチェック → 横軸の変数(x)を減少
  2. [→]キーが押されてるかチェック → 横軸の変数(x)を増加
  3. [↑]キーが押されてるかチェック → 縦軸の変数(y)を減少
  4. [↓]キーが押されてるかチェック → 縦軸の変数(y)を増加
*Main
    screen 0,600,400,SCREEN_FIXEDSIZE
    font MSGOTHIC,50
    repeat
        redraw 0
stick key,%1111 if(key&1):x-=5 if(key&2):y-=5 if(key&4):x+=5 if(key&8):y+=5
color $00,$00,$00:boxf color $00,$FF,$00:pos x,y:mes "山" redraw 1 await (1000/60) loop stop

どうですか?
これで自機が画面を自由自在に動き回れますね。
しかし、ずっと移動し続けると画面から消えてしまいます。
そこで画面外に移動したら画面内に座標を戻す処理を追加してみましょう。

画面外の補正

*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
color $00,$00,$00:boxf color $00,$FF,$00:pos x,y:mes "山" redraw 1 await (1000/60) loop stop

上記の[←]キーの処理だけを考えると次のようになります。

  1. [←]キーが押されてるかチェック
  2. 横軸の変数(x)を減少
  3. 横軸の変数(x)が画面左端から消えたかチェック
  4. 横軸の変数(x)に画面左端を意味する 0 をセット

フローチャート

全体のフローチャートは次のようになります。

  1. [←]キーが押されてるかチェック

    1. 横軸の変数(x)を減少
    2. 横軸の変数(x)が画面左端から消えたかチェック
    3. 横軸の変数(x)に画面左端を意味する 0 をセット

  2. [↑]キーが押されてるかチェック

    1. 縦軸の変数(y)を減少
    2. 縦軸の変数(y)が画面上部から消えたかチェック
    3. 縦軸の変数(y)に画面上部を意味する 0 をセット

  3. [→]キーが押されてるかチェック

    1. 横軸の変数(x)を増加
    2. 横軸の変数(x)が画面右端から消えたかチェック
    3. 横軸の変数(x)に画面右端を意味する 550 をセット

  4. [↓]キーが押されてるかチェック

    1. 縦軸の変数(y)を増加
    2. 縦軸の変数(y)が画面下部から消えたかチェック
    3. 縦軸の変数(y)に画面下部を意味する 350 をセット

自機の操作

それでは第2回目の「自機の操作」ソースを紹介します。

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

//--------------------------------------
// メイン部
//--------------------------------------
*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
        color $00,$00,$00:boxf
        color $00,$FF,$00:pos x,y:mes "山"
        redraw 1
        await (1000/60)
    loop
stop

//------------------------------------------------------------------------------
// End of lesson-2.hsp
//------------------------------------------------------------------------------

上記のソースで x-=5 という記述は x=x-5 と同じ処理です。
これは変数(x)の内容を -5 するという意味で、C/C++言語の複合代入と呼ばれる演算子です。
HSPでも、この省略された記述が許されてるので便利に使いましょう。

それから 600 ではなく 550 で比較してるのは、自機を表す「山」文字の左上隅が座標になってます。
そのため自機の横サイズである 50 を画面の横サイズ 600 から引いた 550 という値で比較するのです。
同様に、自機の縦サイズである 50 を画面の縦サイズ 400 から引いた 350 という値で比較します。

これで「自機の操作」は終わります。
次はスペース・キーで「弾丸の発射」を紹介します。(次を読む)

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

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

コメントを投稿

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