2019年02月12日

ActiveBasicとDXライブラリでゲームプログラミング!~第4回・分岐する骨組みを作ろう!

n88_reon.gif
玲音:どうもこんにちは! 玲音です。先に言っておくと、楓ちゃんを引きずり込んだ、なんてことはありませんので!

n88_kaede.gif
楓:あ、先手打たれちゃった。玲音先輩の後輩の楓です! 先輩、今日は何をするんですか?

n88_reon.gif
うん。今日は、前回話した通り、ゲームプログラムの骨格の部分を作っちゃおうと思います! それじゃさっそく、始めていきましょう!

n88_kaede.gif
はーい!

~一つの流れで、複数のシーンに飛ばすには?~

n88_reon.gif
さてさて。まずは、これが今までの講座で使っていた、プログラムの基本骨格だったね。

=-=-=-=-=-=-=-=-=-=-
#include "Dxlib.sbp"

''初期処理
dxChangeWindowMode(1)
dxDxLib_Init()
dxSetDrawScreen(DX_SCREEN_BACK)

Do
''画面をクリア
dxClearDrawScreen()

''何等かの処理

''画面に反映
dxScreenFlip()
''メッセージ処理
If dxProcessMessage() = -1 Then
Exit Do
End If
Loop

''後処理
dxDxLib_End()
End
=-=-=-=-=-=-=-=-=-=-

n88_kaede.gif
はいっ。このDoとLoopの間、''何等かの処理、ってコメントの下に処理を書くんでしたよね。

n88_reon.gif
うん。でも、このまま使うとちょっと問題があるの。わかる?

n88_kaede.gif
問題、ですか? うーん……。

n88_reon.gif
今までは、キャラを動かしたり、文字を表示したりと、いわばゲームのプレイ中の部分だけを作っていたけど、実際のゲームには他にも色々なシーンがあるよね? タイトル画面とかクリア時のシーンとか、ゲームオーバーとか。

n88_kaede.gif
あっ、それはそうですね! それをどうするか、ですか。うーん……。

n88_reon.gif
ヒント。どのシーンでも、画面を描いて、それを反映させる、って処理は共通だよね? 違うのは描くのがタイトル画面か、それともゲームの背景やキャラか、ってだけで。

abdx1902-01.jpg

n88_kaede.gif
なるほど! ということは、何らかの方法で、タイトル画面を描く処理や、ゲーム中の画面を描く処理とかに分岐させればいいわけですねっ。こんな風に。

abdx1902-02.jpg

n88_reon.gif
うん、その通り! 具体的にどうするかは、これから解説するよ。

~Select Caseを使おう!~
n88_reon.gif
さてさて。その分岐させるために、変数とSelect Case文と、そしてサブプロシージャを使います。

n88_kaede.gif
変数はいわば、数や文字列をいれておく箱のようなものでしたよね。確か、使う前に、Dim命令であらかじめ宣言する必要があるんでしたっけ。こんな風に。

=-=-=-=-=-=-=-=-=-=-
Dim 変数の名前 As 変数の型

(例)
Dim hensu As Integer
=-=-=-=-=-=-=-=-=-=-

n88_kaede.gif
それで、Select Caseはどんな文なんでしたっけ?

n88_reon.gif
うん。それは、指定した変数や式の内容によって、処理を分岐させる文だよ。このように使うの。

=-=-=-=-=-=-=-=-=-=-
Select Case 変数or式
Case 値1
 処理1
Case 値2
 処理2
……
End Select

(例)
Select Case hensu
Case 0
 dxDrawString(50, 40, "hensu=0", white)
Case 1
 dxDrawString(50, 40, "hensu=1", white)
Case 2
 dxDrawString(50, 40, "hensu=2", white)
End Select
=-=-=-=-=-=-=-=-=-=-

n88_reon.gif
この例だと、変数hensuが0のときは、Case 0の下の、dxDrawString(50, 40, "hensu=0", white)が実行されて、1のときは、Case 1の下の、dxDrawString(50, 40, "hensu=1", white)が実行されるんだよ。

n88_kaede.gif
なるほどっ。例えば、上の例で、0、1、2以外の値のときに分岐させる処理を作りたいときはどうするんですか?

n88_reon.gif
そのときは、Case Elseを使うんだよ。これを入れると、Case 〇で指定した数以外の場合は、このCase Elseの下の処理を実行するようになるの。

=-=-=-=-=-=-=-=-=-=-
Select Case hensu
Case 0
 dxDrawString(50, 40, "hensu=0", white)
Case 1
 dxDrawString(50, 40, "hensu=1", white)
Case 2
 dxDrawString(50, 40, "hensu=2", white)
Case Else
 dxDrawString(50, 40, "hensu=X", white)
End Select
=-=-=-=-=-=-=-=-=-=-

n88_reon.gif
上の例の場合なら、hensuが0、1、2以外の場合は、Case Elseの下のdxDrawString(50, 40, "hensu=X", white)が実行されるんだよ。

n88_kaede.gif
なるほどっ!

~サブプロシージャって何?~
n88_reon.gif
さてさて。次に行くね。サブプロシージャというのは、昔のBASICにあった、サブルーチンを発展したようなものだよ。
サブプロシージャは次のように書きます。

=-=-=-=-=-=-=-=-=-=-
Sub サブプロシージャ名(引数1 As 引数1の型, 引数2 As 引数2の型, ……)
実際の処理
End Sub
=-=-=-=-=-=-=-=-=-=-

n88_reon.gif
そして、呼び出すときはこのように書きます。
=-=-=-=-=-=-=-=-=-=-
サブプロシージャ名(引数1, 引数2……)
=-=-=-=-=-=-=-=-=-=-

n88_kaede.gif
先輩っ。この引数ってなんですか?

n88_reon.gif
うん。それは、呼び出し元からサブプロシージャに渡す値のことだよ。例えば。

=-=-=-=-=-=-=-=-=-=-
Sub SubProc1(hiki1 As Integer, hiki2 As Integer)

End Sub

SubProc1(3, 5)
=-=-=-=-=-=-=-=-=-=-

n88_reon.gif
とすると、変数hiki1に3が、hiki2に5が入るの。そうそう。Subのところで指定した引数を入れる変数(例の場合だと、hiki1とhiki2)は、このサブプロシージャの中。具体的には、SubとEnd Subの間でしか使えないから気を付けてね。

abdx1902-03.jpg

n88_kaede.gif
はーいっ。

n88_reon.gif
さてさて。例にある通り、サブプロシージャを呼び出すと、該当するSubからEnd Subの間の処理が実行されます。そして、End Subまで実行したところで、元の処理に戻るよ。

abdx1902-04.jpg

n88_kaede.gif
なるほどっ。

n88_reon.gif
最後にもう一つ。今扱ったようなSubを使ったサブプロシージャでは、呼び出し元に処理結果を返すことはできないの。返したいときは、Subではなく、Functionを使うよ。Functionを使う場合は、このように書きます。

=-=-=-=-=-=-=-=-=-=-
Function サブプロシージャ名(引数1 As 引数1の型, 引数2 As 引数2の型, ……) As 戻り値の型

End Function
=-=-=-=-=-=-=-=-=-=-

n88_reon.gif
値を返すときは、サブプロシージャ名と同じ名前の変数に結果を入れてあげればOKだよ。こんな風にね。あ、この変数については、Dim命令で宣言する必要はないからね。それは、SubやFunctionのところで宣言する、引数を入れる変数についても同じ。

n88_kaede.gif
ふむふむ。

n88_reon.gif
そして、Functionのサブプロシージャは、それ自体を変数や関数のように使うことができるよ。だから、変数に代入したり、式に使ったりすることができるの。

=-=-=-=-=-=-=-=-=-=-
hensu1 = SubProc1(3, 5)
※hensu1に、SubProc1から返ってきた値を入れる

hensu2 = SubProc2(4) + 5
※hensu2に、SubProc2から返ってきた値に5を足したものを入れる
=-=-=-=-=-=-=-=-=-=-

n88_kaede.gif
なるほど、わかりましたっ。

~骨格を作ろう!~
n88_reon.gif
さて、それではここまで説明してきた、変数とSelect Case、そしてサブプロシージャを使って、骨組みを作ってみましょう! どうすればいいかな?

n88_kaede.gif
はーい! シーンが切り替わるときに、変数にそのシーンを表す数を入れて、そしてSelect Caseで、その変数で分岐させて、それぞれの画面を描くサブプロシージャを呼び出せばいいんじゃないですか?

n88_reon.gif
はい、正解! それではやっていきましょう。最初に紹介した基本の骨組みに追加する形でやっていくからね。
さてさて。まずは、そのシーンを表す変数が必要だよね。#include "Dxlib.sbp"の下あたりに、次の文を入れてね。

=-=-=-=-=-=-=-=-=-
Dim scene As Integer
=-=-=-=-=-=-=-=-=-

n88_kaede.gif
このsceneという変数に、シーンを表す数を入れるんですねっ。

n88_reon.gif
そうだよ。さらにその下に次の文も入れましょう。

=-=-=-=-=-=-=-=-=-=-
Const TITLE = 0
Const GAME = 1
Const GAMEOVER = 2
=-=-=-=-=-=-=-=-=-=-

n88_kaede.gif
先輩。このConstって文はなんですか?

n88_reon.gif
これは定数といって、簡単にいえば、単語と値を結びつけるものだよ。これをやっておくと、例えば、式でGAMEという単語を使うと、このGAMEという単語が1と同じ意味になるの。

abdx1902-05.jpg

n88_kaede.gif
なるほど。確かに、GAMEとかいう単語のほうがわかりやすいですよねっ。

n88_reon.gif
うん。さて、まずはゲーム開始時はタイトルだよね。なので、Doの直前に、次の一文をいれよう。

=-=-=-=-=-=-=-=-=-=-
scene = TITLE
=-=-=-=-=-=-=-=-=-=-

n88_reon.gif
さて、ここからいよいよ本番。''何らかの処理、ってコメントの下に、次のSelect Case文をいれましょう!

=-=-=-=-=-=-=-=-=-=-
Select Case scene
Case TITLE
  TitleProc()
Case GAME
GameProc()
Case GAMEOVER
  OverProc()
End Select
=-=-=-=-=-=-=-=-=-=-

n88_kaede.gif
変数sceneの値がTITLE(0)のときはTitleProc、GAME(1)のときはGameProc、そしてGAMEOVER(2)のときはOverProcのサブプロシージャを実行するわけですね。

n88_reon.gif
そうだよ。さて、そしたら、そのサブプロシージャも作っておかなきゃいけないよね。プログラムの一番最後に作っていきましょう。

=-=-=-=-=-=-=-=-=-=-
Sub TitleProc()

End Sub

Sub GameProc()

End Sub

Sub OverProc()

End Sub
=-=-=-=-=-=-=-=-=-=-

n88_reon.gif
これで完成だよ!

n88_kaede.gif
わーい!

n88_reon.gif
次回は、これにさらに追加して、タイトル画面やゲーム画面などを実際に表示させようと思います。お楽しみに!

n88_kaede.gif
次回も楽しみですっ! また次回~!



※次の更新は、2月15日、『師匠TのチャレンジARSゲーム!』の予定です。お楽しみに!

2019年01月14日

ActiveBasicとDXライブラリでゲームプログラミング!~第3回・キー入力、ジョイパッド入力を使ってみよう!

n88_reon.gif
玲音:あけましておめでとうございます! B-Maga編集部の紅一点、玲音です! 今月も、ActiveBasicとDXライブラリを使ったプログラミングを勉強していきましょう!

n88_kaede.gif
楓:玲音先輩に、この講座に引きずり込まれちゃった楓です! あけましておめでとうございます!

n88_reon.gif
だから、引きずり込んだなんて、人聞き悪いなぁ。

n88_kaede.gif
えへへ。それで先輩。今月は何をするんですか?

n88_reon.gif
うん。今月は、IF文を使った移動の制御と、そして、キー入力でキャラクタを動かす方法について説明していくよ。

n88_kaede.gif
はーい!



~こたえあわせ~
n88_reon.gif
さてさて。これが問題のプログラムだったね。

=-=-=-=-=-=-=-=-=-=-
#include "Dxlib.sbp"

Dim haikei As Long
Dim chara As Long
Dim x As Long
Dim y As Long

''初期処理
dxChangeWindowMode(1)
dxDxLib_Init()
dxSetDrawScreen(DX_SCREEN_BACK)

''背景を読み込む
haikei = dxLoadGraph("haikei.bmp")
''ニコニコを読み込む
chara = dxLoadGraph("niko.bmp")

x = 100
y = 70

Do
  ''画面をクリア
  dxClearDrawScreen()

  ''何等かの処理
  dxDrawGraph(0, 0, haikei, 1)
  dxDrawGraph(x, y, chara, 1)

  x = x + 4

  ''画面に反映
  dxScreenFlip()
  ''メッセージ処理
  If dxProcessMessage() = -1 Then
    Exit Do
  End If
Loop

''後処理
dxDxLib_End()
End
=-=-=-=-=-=-=-=-=-=-



n88_kaede.gif
これを実行すると、ニコニコが右に移動していくけど、画面の端にぶつかっても止まらないので、それをどうするか、って話でしたよね。

n88_reon.gif
そうだね。その答えなんだけど、言葉にすると簡単。『画面の端にぶつかったら止まる』ようにすればいいんだよ。

n88_kaede.gif
画面の端にぶつかったら、止まる、ですか……。あ! ここであの命令が出てくるんじゃないですか?

n88_reon.gif
おっ、楓ちゃんもピンときたみたいだね。さぁ、その命令は?

n88_kaede.gif
IF命令ですっ!

n88_reon.gif
正解! その通り。IF文で、画面の端にぶつかったかどうかチェックして、そしてぶつかっていたら動きを止めればいいんだよ。

n88_kaede.gif
なるほどっ。まず、画面の端にぶつかったかどうか、ですけど、それはどうしたらいいんですか?

n88_reon.gif
この場合は、キャラクタが画面の右端を表す640を超えたかどうかでチェックするのがいいと思うよ。かといって、そのまま

=-=-=-=-=-=-=-=-=-=-
X >= 640
=-=-=-=-=-=-=-=-=-=-

n88_reon.gif
ってしてもダメだけどね。

n88_kaede.gif
どうしてです?

n88_reon.gif
思い出してみて。座標に使っている変数XとYはキャラクターの左上の位置だったじゃない? だから、上のようにすると、結局キャラは左端を超えちゃうんだよ。

abdx1901-01.jpg

n88_kaede.gif
あっ、なるほどっ。ということは、Xにニコニコの幅を足した値が、640以上かどうかを判定すればいいんですねっ。

n88_reon.gif
うん、その通り。次にニコニコの動きをどう止めるかだけど、これは簡単。640-ニコニコの幅をXに入れればいいだけ。
ということで、それらを入れるとこうなりまーすっ。

=-=-=-=-=-=-=-=-=-=-
#include "Dxlib.sbp"

Dim haikei As Long
Dim chara As Long
Dim x As Long
Dim y As Long

''初期処理
dxChangeWindowMode(1)
dxDxLib_Init()
dxSetDrawScreen(DX_SCREEN_BACK)

''背景を読み込む
haikei = dxLoadGraph("haikei.bmp")
''ニコニコを読み込む
chara = dxLoadGraph("niko.bmp")

x = 100
y = 70

Do
  ''画面をクリア
  dxClearDrawScreen()

  ''何等かの処理
  dxDrawGraph(0, 0, haikei, 1)
  dxDrawGraph(x, y, chara, 1)

  x = x + 4
  If x + 100 > 640 Then
  x = 640 - 100
  End If

  ''画面に反映
  dxScreenFlip()
  ''メッセージ処理
  If dxProcessMessage() = -1 Then
    Exit Do
  End If
Loop

''後処理
dxDxLib_End()
End
=-=-=-=-=-=-=-=-=-=-



n88_kaede.gif
おー! ニコニコが画面の右端で止まりましたよ!

n88_reon.gif
これをちょっといじくるともっと面白いのができるよ。例えば、画面の端についたら、移動量を逆に(+4なら-4というように)するようにして、画面の左右を行ったりきたり、とか。興味があればやってみてね。

n88_kaede.gif
はーい!

n88_reon.gif
さてさて。それでは、ここからが本題だよ!

~キー入力しよう!~
n88_reon.gif
さて、キー入力だけど、それにはある関数を使うんだよ。その名も、dxGetJoypadInputState関数!

n88_kaede.gif
その関数って、どんな命令なんですか?

n88_reon.gif
うん。この関数は、ジョイパッドやカーソルキーなどを押すと、押したキーに対応した情報を返してくるんだよ。返ってきた情報から、あるキーが押されたかどうかをチェックするには、こうすればいいの。

=-=-=-=-=-=-=-=-=-=-
dxGetJoypadInputStateの戻り値 And キーの値
=-=-=-=-=-=-=-=-=-=-

n88_reon.gif
戻り値を変数に代入して、それを使うといいと思うよ。こんな風にね。

=-=-=-=-=-=-=-=-=-=-
k = dxGetJoypadInputState(DX_INPUT_KEY_PAD1)
If (k & @@@) <> 0 Then

End If
=-=-=-=-=-=-=-=-=-=-

n88_reon.gif
上の例にある通り、Andを取った結果が0でなければ押されたことになるの。

n88_kaede.gif
なるほど。それで先輩っ。例の中にある、DX_INPUT_KEY_PAD1ってなんなんですか?

n88_reon.gif
あぁ、それはどのジョイパッドをチェックするかを表したものだよ。DX_INPUT_KEY_PAD1なら、キーボードとジョイパッドの1番をチェックするの。ちなみにジョイパッドの2番なら、DX_INPUT_PAD2だよ。

n88_kaede.gif
なるほどー。

n88_reon.gif
それで、キーに対応した値だけど、代表的なものでは次の通り。

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
DX_PAD_INPUT_DOWN……下、テンキーの2
DX_PAD_INPUT_LEFT……左、テンキーの4
DX_PAD_INPUT_RIGHT……右、テンキーの6
DX_PAD_INPUT_UP……上、テンキーの8
DX_PAD_INPUT_1……ボタン1、Zキー
DX_PAD_INPUT_2……ボタン2、Xキー
DX_PAD_INPUT_3……ボタン3、Cキー
DX_PAD_INPUT_9……ボタン9、ESCキー
DX_PAD_INPUT_10……ボタン10、スペースキー
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

n88_reon.gif
これだけ覚えておけば、ゲーム作りで困ることはまずないと思うよ。後は、リファレンスを読んでね。

n88_kaede.gif
はーい。ということは、Xキーが押されたかどうかチェックするなら、

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
k = dxGetJoypadInputState(DX_INPUT_KEY_PAD1)

If (k And DX_PAD_INPUT_1) <> 0 Then

End If
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

n88_kaede.gif
とすれば、いいわけですねっ。

n88_reon.gif
うん、その通り。ではさっそく、これを使って、ニコニコを動かしてみよう!

n88_kaede.gif
はーい!

~ニコニコを動かそう!~
n88_reon.gif
さてさて、キー入力でニコニコを動かす考え方だけど、基本的な考えは次の通り。
・上が押されたら、上に動かす
・下が押されたら、下に動かす
・右が押されたら、右に動かす
・左が押されたら、左に動かす
これをプログラムにすればいいんだよ。

n88_kaede.gif
動かすには、位置を表す変数の値を変えてやればいいんですよね。

n88_reon.gif
画面の上や左の端についたかどうかもチェックする必要があるよね。画面の上端は0、左端も0、そして下端は480だよ。

abdx1901-02.jpg

n88_reon.gif
なお、上端や左端を超えたかどうかをチェックするさいには、普通に変数の値を比べればいいよ。

abdx1901-03.jpg

n88_reon.gif
それらを踏まえて、最初のプログラムを改造すると、こうなります。

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#include "Dxlib.sbp"

Dim haikei As Long
Dim chara As Long
Dim x As Long
Dim y As Long
Dim k As Long

''初期処理
dxChangeWindowMode(1)
dxDxLib_Init()
dxSetDrawScreen(DX_SCREEN_BACK)

''背景を読み込む
haikei = dxLoadGraph("haikei.bmp")
''ニコニコを読み込む
chara = dxLoadGraph("niko.bmp")

x = 100
y = 70

Do
  ''画面をクリア
  dxClearDrawScreen()

  ''何等かの処理
  dxDrawGraph(0, 0, haikei, 1)
  dxDrawGraph(x, y, chara, 1)

  ''キー入力
  k = dxGetJoypadInputState(DX_INPUT_KEY_PAD1)

  If (k And DX_PAD_INPUT_UP) <> 0 Then
    ''上に動かす
    y = y - 4
  End If

  If (k And DX_PAD_INPUT_DOWN) <> 0 Then
    ''下に動かす
    y = y + 4
  End If

  If (k And DX_PAD_INPUT_LEFT) <> 0 Then
    ''左に動かす
    x = x - 4
  End If

  If (k And DX_PAD_INPUT_RIGHT) <> 0 Then
    ''右に動かす
    x = x + 4
  End If

  ''画面の端に出たかチェック
  ''上端
  If y < 0 Then
    y = 0
  End If

  ''下端
  If y + 100 > 480 Then
    y = 480 - 100
  End If

  ''左端
  If x < 0 Then
    x = 0
  End If

  ''右端
  If x + 100 > 640 Then
    x = 640 - 100
  End If

  ''画面に反映
  dxScreenFlip()
  ''メッセージ処理
  If dxProcessMessage() = -1 Then
    Exit Do
  End If
Loop

''後処理
dxDxLib_End()
End

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

n88_kaede.gif
おー! ニコニコがカーソルキーで動くようになりましたよ!

n88_reon.gif
これでゲームの基本部分は完成。来月からは、いよいよゲーム作りに進むよ。
次回はまず、ゲームを作るための骨組みの考え方について説明していきます。お楽しみに!



=-=-=-=-=-=-=-=-=-=-
※次の更新は、1月17日、『師匠TのチャレンジARSゲーム!』の予定です。お楽しみに!

2018年12月10日

ActiveBasicとDXライブラリでゲームプログラミング!~第2回・画像を表示、移動させてみよう!

n88_reon.gif
玲音:どうもこんにちは! 玲音です! 今日も、ActiveBasicとDXライブラリを使ったゲームプログラミングについて勉強しちゃいましょう!

n88_kaede.gif
楓:どうもこんにちは! 楓ですっ。玲音先輩っ。今回は何をするんですかっ?

n88_reon.gif
うん。今回は、背景やキャラクターを表示させて、さらにキャラクターを移動させちゃおうと思います。よろしくね!

n88_kaede.gif
おーっ。それは大切な部分ですよねっ。頑張りますっ。

~dxLoadGraph関数と、dxDrawGraph関数を使ってみよう~

n88_reon.gif
さて、背景やキャラなどの画像を表示させるためには、二種類の関数を使うよ。まず一つが、画像を読み込むdxLoadGraph関数。そしてもう一つが、その画像を表示させる、dxDrawGraph系の関数でーす。

n88_kaede.gif
dxLoadGraph関数と、dxDrawGraph系の関数ですかー。それって、どう使うんですかっ?

n88_reon.gif
それではさっそく、dxLoadGraph関数と、dxDrawGraph系の中でも基本であるdxDrawGraph関数を使ってみちゃおう!
まず、フォルダを作って、その中に次の画像をダウンロードしてね。

niko.bmp

n88_kaede.gif
はーい、できましたっ。

n88_reon.gif
そしたら続いて、ActiveBasicを起動して、次のプログラムを入力してみて。できたら、さっきのフォルダに保存しておくのを忘れずにね。

=-=-=-=-=-=-=-=-=-=-
#include "Dxlib.sbp"

Dim chara As Long

''初期処理
dxChangeWindowMode(1)
dxDxLib_Init()
dxSetDrawScreen(DX_SCREEN_BACK)

''ニコニコを読み込む
chara = dxLoadGraph("niko.bmp")

Do
  ''画面をクリア
  dxClearDrawScreen()

  ''何等かの処理
  dxDrawGraph(200, 150, chara, 1)

  ''画面に反映
  dxScreenFlip()
  ''メッセージ処理
  If dxProcessMessage() = -1 Then
    Exit Do
  End If
Loop

''後処理
dxDxLib_End()
End
=-=-=-=-=-=-=-=-=-=-

n88_kaede.gif
できましたよー。実行してみますねっ。

abdx1812-02.JPG

n88_kaede.gif
おーっ! ウィンドウの左上のほうに、ニコニコマークが表示されましたよっ。

~これが使い方!~

n88_reon.gif
それじゃ、dxLoadGraph関数と、dxDrawGraph関数の使い方について説明するよ。

n88_kaede.gif
はーい。よろしくお願いしまーす!

n88_reon.gif
まず、dxLoadGraph関数は、このように書くんだよ。

=-=-=-=-=-=-=-=-=-=-
dxLoadGraph(ファイル名)

例:dxLoadGraph("samp1.bmp")
=-=-=-=-=-=-=-=-=-=-

n88_kaede.gif
引数にファイル名を指定するだけでOKなんですね。

n88_reon.gif
うん。それで、このdxLoadGraph関数は、メモリに画像を読み込んで、表示できるようにする関数だよ。これを実行すると、dxLoadGraph関数は、ハンドルという値を返してくるの。

abdx1812-03.JPG

n88_kaede.gif
はんどる?

n88_reon.gif
ハンドルというのは、メモリに読み込んだ画像につけられる番号で、dxDrawGraph系の命令では、このハンドルを使って、どの画像を表示するかを指定するんだよ。

n88_kaede.gif
なるほどっ。だからハンドルを使うために、変数に入れているわけですねっ。

n88_reon.gif
うん。そして、dxDrawGraph関数はこう使うの。

=-=-=-=-=-=-=-=-=-=-
dxDrawGraph(X座標, Y座標, ハンドル, 背景を透過するかどうか)

例:dxDrawGraph(100, 50, gazou, 1)
=-=-=-=-=-=-=-=-=-=-

n88_reon.gif
まず一番目と二番目の数字は、表示する座標。DXライブラリは、指定した画像の左上隅が、ここで指定した座標になるように表示してくれるの。例えば、例の場合なら、画像の左上隅が、(100, 50)の座標に来るように表示されるわけだね。

abdx1812-04.JPG

n88_kaede.gif
三番目に入れるのは、表示させる画像のハンドルですよねっ。

n88_reon.gif
うん、その通り。例でいえば、変数gazouに格納された数字のハンドルを持つ画像を表示するわけ。

abdx1812-05.JPG

n88_kaede.gif
ふむふむ。先輩っ。最後の『背景を透過するかどうか』はなんですかっ?

n88_reon.gif
うん。それを1にすると、画像の黒の部分を透明にして、背景が透けるようになるんだよ。こんな風にね。

abdx1812-06.JPG

n88_kaede.gif
なるほどー。あ、そうそうっ、先輩。もし、複数のdxDrawGraph関数を実行した場合はどうなるんですかっ?

n88_reon.gif
その場合は、前にdxDrawGraphで表示された内容が、後に表示された内容で上書きされるの。これを利用すれば、背景とキャラを表示させることもできるよ。試しに、これを実行してみて。あ、そうそう。次の画像をダウンロードしておいてね。

haikei.bmp

=-=-=-=-=-=-=-=-=-=-
#include "Dxlib.sbp"

Dim chara As Long

''初期処理
dxChangeWindowMode(1)
dxDxLib_Init()
dxSetDrawScreen(DX_SCREEN_BACK)

''背景を読み込む
haikei = dxLoadGraph("haikei.bmp")
''ニコニコを読み込む
chara = dxLoadGraph("niko.bmp")

Do
  ''画面をクリア
  dxClearDrawScreen()

  ''何等かの処理
  dxDrawGraph(0, 0, haikei, 1)
  dxDrawGraph(100, 70, chara, 1)

  ''画面に反映
  dxScreenFlip()
  ''メッセージ処理
  If dxProcessMessage() = -1 Then
    Exit Do
  End If
Loop

''後処理
dxDxLib_End()
End
=-=-=-=-=-=-=-=-=-=-

abdx1812-08.JPG

n88_kaede.gif
ほんとだっ! 背景も表示されていますっ!

n88_reon.gif
二番目のdxDrawGraph関数の4番目の数字を0にすると、違いがわかると思うよ。試してみてね。

n88_kaede.gif
はーいっ。

~キャラクターを移動させてみよう!~

n88_reon.gif
さて。キャラクターを移動させる前に、ちょっとさっきのプログラムを改造してみようー。さっきのを、次のように改造してみて。

=-=-=-=-=-=-=-=-=-=-
#include "Dxlib.sbp"

Dim haikei As Long
Dim chara As Long
Dim x As Long
Dim y As Long

''初期処理
dxChangeWindowMode(1)
dxDxLib_Init()
dxSetDrawScreen(DX_SCREEN_BACK)

''背景を読み込む
haikei = dxLoadGraph("haikei.bmp")
''ニコニコを読み込む
chara = dxLoadGraph("niko.bmp")

x = 100
y = 70


Do
  ''画面をクリア
  dxClearDrawScreen()

  ''何等かの処理
  dxDrawGraph(0, 0, haikei, 1)
  dxDrawGraph(x, y, chara, 1)

  ''画面に反映
  dxScreenFlip()
  ''メッセージ処理
  If dxProcessMessage() = -1 Then
    Exit Do
  End If
Loop

''後処理
dxDxLib_End()
End
=-=-=-=-=-=-=-=-=-=-

n88_reon.gif
太字で書かれているのが、追加したり修正したりした部分だよ。できたら、実行してみてね。

n88_kaede.gif
はーい。それじゃ、実行してみますね。

abdx1812-09.JPG

n88_kaede.gif
さっきと同じように表示されましたよっ。

n88_reon.gif
そして、プログラムを見て、何か気づかないかな?

n88_kaede.gif
あっ! 二番目のdxDrawGraph関数、一つ目と二つ目のところが数でなく変数で指定されてるのに、ちゃんと動いてますっ。dxDrawGraph関数は、変数も使えるんですねっ。

n88_reon.gif
そのとおり。その場合、dxDrawGraph関数は、変数に入っている数に従って表示してくれるの。さて、ここで何か気づかない?

n88_kaede.gif
あっ! 変数の値を変えてやれば、キャラクターを表示させることができるんじゃないですかっ?

n88_reon.gif
せいかーい! ということでやってみよう! プログラムをさらに、次のように改造してみてね。

=-=-=-=-=-=-=-=-=-=-
#include "Dxlib.sbp"

Dim haikei As Long
Dim chara As Long
Dim x As Long
Dim y As Long

''初期処理
dxChangeWindowMode(1)
dxDxLib_Init()
dxSetDrawScreen(DX_SCREEN_BACK)

''背景を読み込む
haikei = dxLoadGraph("haikei.bmp")
''ニコニコを読み込む
chara = dxLoadGraph("niko.bmp")

x = 100
y = 70

Do
  ''画面をクリア
  dxClearDrawScreen()

  ''何等かの処理
  dxDrawGraph(0, 0, haikei, 1)
  dxDrawGraph(x, y, chara, 1)

x = x + 4

  ''画面に反映
  dxScreenFlip()
  ''メッセージ処理
  If dxProcessMessage() = -1 Then
    Exit Do
  End If
Loop

''後処理
dxDxLib_End()
End
=-=-=-=-=-=-=-=-=-=-

n88_kaede.gif
ニコニコが、右に移動していきました! でも、画面の右端についても止まらずに消えていっちゃいました。どうしたらいいんでしょう?

n88_reon.gif
そこは、次回の話にも少しかかわるから、宿題にしておくね。楓ちゃんも、読者のみんなも考えてみて。さて、次回はキー入力して、キャラクターを動かす方法について勉強していきます!

n88_kaede.gif
おー。それは楽しみです! 早く次回にならないかなぁ。

n88_reon.gif
くすくす。それでは、また次回!

=-=-=-=-=-=-=-=-=-=-

※次の更新は、12月13日、『師匠Tのチャレンジ・ARSゲーム!』の予定です。お楽しみに!

2018年11月12日

ActiveBasicとDXライブラリでゲームプログラミング!~第1回・メッセージを表示させてみよう!

※使っているアイコンは、以前、伊地山基之さんが描いてくれたものを使わせていただいております。
 ありがとうございます!

n88_reon.gif
玲音:どうもはじめまして! 玲音です!

n88_kaede.gif
楓:どうもこんにちは! 玲音先輩にこの講座に引きずり込まれちゃった、後輩の楓ですっ。
 よろしくお願いしますっ!

n88_reon.gif
引きずりこんだなんて、人聞きが悪いなぁ……。

n88_kaede.gif
えへへ。さて、この講座は、BASIC言語『ActiveBasic』と、ゲーム開発用ライブラリ『DXライブラリ』を使って、ゲームを作ってみよう、という講座、だそうですっ。それで先輩っ。今月は何をするんですか?

n88_reon.gif
うん。今月はまず初歩の初歩、文字を表示させるところから始めるよ。さぁ、スタート!

~これが骨格!

n88_reon.gif
まず最初に、DXライブラリを使ったプログラムの骨格を教えちゃうよ。これです!

ab1811-01.jpg

n88_reon.gif
このように、DXライブラリを使ったプログラムでは、画面をクリアして、何かの処理を行い、描画して、それを反映させる、という流れになるんだよ。

n88_kaede.gif
なるほどなるほどっ。それで、これをActiveBasicにするとどうなるんですか?

n88_reon.gif
うん、お待たせしました。ActiveBasicでの骨格がこれです!

----------
#include "Dxlib.sbp"

Dim white As Long

''初期処理
dxChangeWindowMode(1)
dxDxLib_Init()
dxSetDrawScreen(DX_SCREEN_BACK)

Do
  ''画面をクリア
  dxClearDrawScreen()

  ''何等かの処理

  ''画面に反映
  dxScreenFlip()
  ''メッセージ処理
  If dxProcessMessage() = -1 Then
    Exit Do
  End If
Loop

''後処理
dxDxLib_End()
End
----------

n88_reon.gif
dxClearDrawScreen()が、画面をクリアするところ。dxScreenFlip()が、画面に反映させるところに当たるよ。

n88_kaede.gif
この二つの関数の間、『何等かの処理』ってコメントがついているところに、処理などを書いていくわけですねっ。

n88_reon.gif
その通りだよ。さぁ、これをいじって、メッセージを表示させてみよーう!

n88_kaede.gif
はーい!

~dxDrawStringを使ってみよう!

n88_reon.gif
さてさて。文字を表示させるには、dxDrawStringという関数を使うよ。

n88_kaede.gif
それって、どう使うんですかっ?

n88_reon.gif
習うより慣れろ。さっそく使ってみちゃおう! まず、#include "Dxlib.sbp"の次の行に、こう書いてみて。

----------
Dim white As Long
----------

n88_kaede.gif
はい、できましたよー。

n88_reon.gif
そして、ここからが本番。『何等かの処理』ってコメントの後ろにこれを書いてね。

----------
white = dxGetColor(255, 255, 255)
dxDrawString(50, 40, "DXLIB!", white)
----------

n88_reon.gif
できたら、ソース(簡単に言うとプログラムのこと)を保存して実行してみてね。あ、そうそう。今月の特集にもあるけど、Dxlib.sbpとDxLibDll.dllを、ソースを保存したのと同じフォルダにコピーしておくのを忘れないでね。

n88_kaede.gif
はーい。それじゃこの、ビックリマークのボタンを押せばいいんですよね? えいっ。

ab1811-02.JPG

n88_kaede.gif
おー。ウィンドウの左上に、DXLIB!ってメッセージが表示されましたよ!

n88_reon.gif
それじゃ、dxDrawString関数の使い方について説明するよ。まず、最初の二つの数字は、メッセージを書く座標。一つ目がX位置、二つ目がY位置だよ。つまり、例でいえば、(X:50, Y:40)の位置に書いているわけだね。

n88_kaede.gif
ふむふむ。その次のは、書くメッセージの内容ですよね。その次のは何ですか?

n88_reon.gif
うん。ここは、何色で書くかを入れるんだよ。色の数字は、この例にある通り、dxGetColor関数を使って得ることができるよ。ちなみに、そのdxGetColor関数の使い方はこちら。

----------
dxGetColor(赤成分, 緑成分, 青成分)
----------

n88_reon.gif
成分の値を指定してやると、その成分でできる色を返してくれるの。

n88_kaede.gif
なるほどっ。

~数字はdxDrawFormatStringで

n88_kaede.gif
あの先輩。数字を書くことはできないんですか?

n88_reon.gif
うん。数そのものを書くことはできないよ。だから、数は、Str$関数で、文字列にしてあげる必要があるの。

----------
Str$(数値)
----------

n88_reon.gif
これがStr$関数の使い方なんだけど……。

n88_kaede.gif
なるほどっ。さっそくやってみまーすっ。

----------
#include "Dxlib.sbp"

Dim white As Long
Dim num As Integer
Dim numstr As String

''初期処理
dxChangeWindowMode(1)
dxDxLib_Init()
dxSetDrawScreen(DX_SCREEN_BACK)

Do
  ''画面をクリア
  dxClearDrawScreen()

  ''何等かの処理
  num = 50
  numstr = Str$(num)
  white = dxGetColor(255, 255, 255)
  dxDrawString(50, 50, numstr, white)

  ''画面に反映
  dxScreenFlip()
  ''メッセージ処理
  If dxProcessMessage() = -1 Then
    Exit Do
  End If
Loop

''後処理
dxDxLib_End()
End
----------

ab1811-03.JPG

n88_kaede.gif
うん、ちゃんとできましたっ。それじゃ今度は計算の答えを表示させてみようかな。それっと。

----------
#include "Dxlib.sbp"

Dim white As Long
Dim num1 As Integer
Dim num2 As Integer
Dim num3 As Integer
Dim numstr As String

''初期処理
dxChangeWindowMode(1)
dxDxLib_Init()
dxSetDrawScreen(DX_SCREEN_BACK)

Do
  ''画面をクリア
  dxClearDrawScreen()

  ''何等かの処理
  num1 = 10
  num2 = 3
  num3 = num1 + num2
  numstr = Str$(num3)
  white = dxGetColor(255, 255, 255)
  dxDrawString(50, 50, numstr, white)

  ''画面に反映
  dxScreenFlip()
  ''メッセージ処理
  If dxProcessMessage() = -1 Then
    Exit Do
  End If
Loop

''後処理
dxDxLib_End()
End
----------

n88_reon.gif
うん。あ、そうだ、計算結果を表示させるにはちょっと問題が……って、ちょっと待ってっ……。

ab1811-04.JPG

n88_kaede.gif
あれー? 小数点まで表示されているうえに、計算結果が違ってるんですけど。玲音せんぱーい。どうなってるんですか?

n88_reon.gif
あああ、だから待ってって言ったのに……。うん。ActiveBasicの問題か、それともDXライブラリの問題かわからないんだけど、特定の計算をさせて、それをdxDrawStringで表示させると、このようにおかしくなることがあるの。

n88_kaede.gif
そうなんですかぁ……。そしたら、どうしたらいいんですか?

n88_reon.gif
そこで出てくるのが、dxDrawFormatString関数でーすっ。これは、数値を決められた形式で書いてくれるものなの。使い方は次の通りだよ。

----------
dxDrawFormatString(Xの位置, Yの位置, 色, 形式の文字列, 数)
----------

n88_kaede.gif
Xの位置、Yの位置、そして色というのは、dxDrawString関数のと同じですよね?

n88_reon.gif
うん、その通りだよ。そしてその次の『形式の文字列』というのは、数値をどのような形式で書くのか、というもの。これはちょっと難しいけど、例として、このような書き方があるよ。

----------
"%d"→十進数の整数で表示する
"%05d"→十進数の整数で表示する。そのさい、5桁で表示し、空いているところは0で埋める
----------

n88_reon.gif
このほかにもいっぱいあるけど、それはC言語関係の解説サイトか本を読んでね。

n88_kaede.gif
はーいっ。その次の数は、表示させる数ですよね。

n88_reon.gif
そうだよ。例えば、変数aの内容を6桁表示で、開いている桁は0で埋める形式で表示させたいときは、こう書けばいいの。

----------
dxDrawFormatString(100, 100, white, "%05d", a)
----------

n88_kaede.gif
なるほどーっ。あ、そうだ。複数の数値を表示させることもできるんですか?

n88_reon.gif
うん。その場合は"%d"とか"%05d"とかの表示を複数書いて、その後の数の指定も複数書けばいいの。こんな風にね。

----------
dxDrawFormatString(100, 100, white, "%d %05d", a, b)
※この場合、変数aが5、変数bが13なら、このように表示される。
→5 00013
----------

n88_reon.gif
そうそう。メッセージも一緒に書くことができるよ。こんな感じ。

----------
dxDrawFormatString(100, 100, white, "変数Aは %d。変数Bは %d", a, b)
→変数Aは 5。変数Bは 13 と表示される。
----------

n88_reon.gif
さて。それじゃ、これを踏まえたうえで、さっきのプログラムを、dxDrawFormatStringで書きなおしてみよう!

n88_kaede.gif
はーいっ。

n88_reon.gif
とはいっても、さっきのプログラムのdxDrawStringの行を、こう書きなおすだけ。やってみて?

----------
dxDrawFormatString(100, 100, white, "%d", num3)
----------

n88_kaede.gif
はーい、できました。実行してみますね。

ab1811-05.JPG

n88_kaede.gif
わーい、できたーっ。

n88_reon.gif
このように、基本的にはdxDrawString関数でOKだけど、数の表示が変になるときは、dxDrawFormatStringを使うことも考えてみてね。

n88_kaede.gif
わかりましたっ。

n88_reon.gif
それじゃ、次回は、いよいよキャラクタの表示をやってみるよ。お楽しみにね。

n88_kaede.gif
また次回ですっ。



※次の更新は、11月15日。『師匠Tのチャレンジ・ARSゲーム!』の予定です。お楽しみに!