×

[PR]この広告は3ヶ月以上更新がないため表示されています。
ホームページを更新後24時間以内に表示されなくなります。

ゲームを作ろう! ダンジョン探索その1 十字キーで動かす


RPGといえば、プレイヤーキャラを十字キーで動かしてマップ上を探索、というのがお約束です。
Shapeオブジェクトで円か四角形を作って、それをキーボードの十字キーで動かすというだけなら、さほど難しくはありません。

marusize = 20
maru = Shapes.AddEllipse(marusize, marusize)
maruX = 50
maruY = 50
Shapes.Move(maru, maruX, maruY)

GraphicsWindow.KeyDown = OnKeyDown

Sub OnKeyDown
  If GraphicsWindow.LastKey = "Right" Then
    maruX = maruX + 10
    Shapes.Move(maru, maruX, maruY)
  EndIf
EndSub

簡略化のために、右キーのみのプログラムを書きました。
このプログラムを実行すると、キーボードの右キーを押している間、図形maruが右に移動します。
でも、何か動きがギクシャクしていますね。
最初はちょっと遅くて、その後はダダダダっと早くなり一気に移動します。
パソコンのキーボードというのは、キーを押しっぱなしにすると、同じキーを連打しているのと同じ効果が得られますね。
メモ帳あたりに、数字の1か何かのキーを押しっぱなしにすると、1がずらっと並びます。
ただ、最初のほんの一瞬だけ、自動的に遅延が起こって文字の表示が続きません。
これを設定しておかないと、私たちが普段文章を打ち込む時に、「キーをちょっと押しただけなのに、文字がいっぱい表示された!」ってことが起こるからです。
しかし、上のプログラムの時には困りますね。
これを解決するには、

・キーが押されていることを検出する。
・自動的な遅延が終わるまでの時間、押されたキーの状態は「押されていない」になっている。これを無視させる。

という、ややこしいことをしなければならず……
そして、これを解決する為のプログラムが、Small Basicの公式Wikiに解説してあります。英語だけど。

Small Basic: Dynamic Graphics - TechNet Articles - United States (English) - TechNet Wiki

ここに書いてある、以下のプログラムが「遅延回避用」の記述です。

While ("True")
  start = Clock.ElapsedMilliseconds
  
  UpdateGamePlay()
  
  delay = 20 - (Clock.ElapsedMilliseconds - start)
  If (delay > 0) Then
    Program.Delay(delay)
  EndIf
EndWhile

UpdateGamePlay()は図形maruを動かす為のサブルーチンです。この後に記述します。
サブルーチン前にまず、start = Clock.ElapsedMillisecondsで、開始時の時間を取得しstartという名前にします。
Clock.ElapsedMillisecondsは、1900年から現在までのミリ秒数を取得します。
そしてサブルーチンを動かし(つまり、右キーを押して図形maruを右に動かした)、更にこのサブルーチンを動かした時のClock.ElapsedMillisecondsも取得します。

Clock.ElapsedMillisecondsからstartを引くと、「キーを押してからの経過時間」がミリ秒で取得できます。
「自動的な遅延時間」と「キーを押してからの経過時間」が同じ値になるまで、プログラムを無視(つまりプログラムの実行を遅らせる)すれば良いのです。
上では、「自動的な遅延時間」を20ミリ秒と設定しています。
「自動的な遅延時間」と「キーを押してからの経過時間」が同じ値になる、ということは、20-「キーを押してからの経過時間」がゼロということですね。
上では20-「キーを押してからの経過時間」を「delay」という変数にして、もし「delay」が0より大きいのなら「delay」の時間分だけProgram.Delay(プログラムの実行を遅らせる)する、としてあります。
これをWhileループを使って、20-「キーを押してからの経過時間」がゼロになるまで繰り返しています。

要するにこれは、
『サブルーチン「UpdateGamePlay」での行動は、常にキー入力を20ミリ秒遅延して実行する。遅延中は一切キー入力を受け付けない』
ということです。
これにより、プレイヤー側にとっては、入力したキーが20ミリ秒の遅延で実行されているということになるのですが、そんなのがわかるのはかなりのゲーマーさんくらいのはず……です。w

ちなみに上の解説では、この後のキーを押した時用のサブルーチンの書き方も丁寧に説明してあります。英語で。

Sub Initialise
  GraphicsWindow.KeyDown = OnKeyDown
  GraphicsWindow.KeyUp = OnKeyUp
  keyLeft = "False"
  keyRight = "False"
  keyUp = "False"
  keyDown = "False"
EndSub

Sub OnKeyDown
  lastKey = GraphicsWindow.LastKey
  If (lastKey = "Left") Then
    keyLeft = "True"
  ElseIf (lastKey = "Right") Then
    keyRight = "True"
  ElseIf (lastKey = "Up") Then
    keyUp = "True"
  ElseIf (lastKey = "Down") Then
    keyDown = "True"
  EndIf
EndSub

Sub OnKeyUp
  lastKey = GraphicsWindow.LastKey
  If (lastKey = "Left") Then
    keyLeft = "False"
  ElseIf (lastKey = "Right") Then
    keyRight = "False"
  ElseIf (lastKey = "Up") Then
    keyUp = "False"
  ElseIf (lastKey = "Down") Then
    keyDown = "False"
  EndIf
EndSub

ここは、「キーを押した時のサブルーチンOnKeyDown」「キーを離した時のサブルーチンOnKeyUp」が書いてありますが、中身自体は「オン・オフの切り替え」だけです。
"True"が「オン」、"False"が「オフ」だと思ってください。
つまりキーを押したら実行、キーを離したらやめる、ってことです。
サブルーチン「Initialise」は、「開始時にはキーはオフ状態」と書いてある部分になります。

実際の行動は、サブルーチン「UpdateGamePlay」に書きます。

Sub UpdateGamePlay
  If (keyLeft) Then
    (左キーをおしてやること)
  EndIf
  If (keyRight) Then
    (右キーをおしてやること)
  EndIf
  If (keyUp) Then
    (上キーをおしてやること)
  EndIf
  If (keyDown) Then
    (下キーをおしてやること)
  EndIf
EndSub

ここに、最初に書いた
    maruX = maruX + 10
    Shapes.Move(maru, maruX, maruY)
などを入れていくわけです。
以下は適当に作った一例です。

GraphicsWindow.Width = 600
GraphicsWindow.Height = 400
GraphicsWindow.Title = "game"

marusize = 50
maru = Shapes.AddEllipse(marusize, marusize)
maruX = 50
maruY = 50
Shapes.Move(maru, maruX, maruY)

Initialise()

While ("True")
  start = Clock.ElapsedMilliseconds
  
  UpdateGamePlay()

  delay = 20 - (Clock.ElapsedMilliseconds - start)
  If (delay > 0) Then
    Program.Delay(delay)
  EndIf
EndWhile

Sub Initialise
  GraphicsWindow.KeyDown = OnKeyDown
  GraphicsWindow.KeyUp = OnKeyUp
  keyLeft = "False"
  keyRight = "False"
  keyUp = "False"
  keyDown = "False"
EndSub

Sub OnKeyDown
  lastKey = GraphicsWindow.LastKey
  If (lastKey = "Left") Then
    keyLeft = "True"
  ElseIf (lastKey = "Right") Then
    keyRight = "True"
  ElseIf (lastKey = "Up") Then
    keyUp = "True"
  ElseIf (lastKey = "Down") Then
    keyDown = "True"
  EndIf
EndSub

Sub OnKeyUp
  lastKey = GraphicsWindow.LastKey
  If (lastKey = "Left") Then
    keyLeft = "False"
  ElseIf (lastKey = "Right") Then
    keyRight = "False"
  ElseIf (lastKey = "Up") Then
    keyUp = "False"
  ElseIf (lastKey = "Down") Then
    keyDown = "False"
  EndIf
EndSub

Sub UpdateGamePlay
  If (keyLeft) Then
    maruX = maruX - 10
    Shapes.Move(maru, maruX, maruY)
  EndIf
  If (keyRight) Then
    maruX = maruX + 10
    Shapes.Move(maru, maruX, maruY)
  EndIf
  If (keyUp) Then
    maruY = maruY - 10
    Shapes.Move(maru, maruX, maruY)
  EndIf
  If (keyDown) Then
    maruY = maruY + 10
    Shapes.Move(maru, maruX, maruY)
  EndIf
EndSub


ダンジョン

キーボードの上下左右キーで、好きなように図形maruを移動できるのがわかります。
しかも最初に書いたプログラムのような、不自然な動きもありませんね。
ただし、これだけだと、キーをずっと押しっぱなしにしていると画面外にmaruが出ていってしまいます。
maruXとmaruYの範囲を制限しないといけないということがわかりますね。

もちろん、これに背景を描き加えて初めてダンジョンになります。
ついでに、プレイヤーキャラをmaruのままにするというのもちょっと……w
ここからは絵を作る作業になります。



▲TOPへ戻る