HSP講座
基本的なスクリプトのパターン †
ソフトの内容によって基本パターンのようなものがあります。
ここではそれらの紹介をやってみようと思います。
基本は1秒間に数十回画面を書き換えることです。
シューティングゲームなど、画面がアニメーションするゲームなどはこのパターンが適用できます。
※イメージは一例であって、必ずこの手順を踏むとは限りません。
+
| | アニメーション画面
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
|
screen 0, 200, 30
font msgothic, 20, 1
x = 0 : y = 0
*main
redraw 0
color 255,255,255 : boxf : color : pos 0,0
pos x, y
mes "メッセージ"
mx = ginfo(14) x++
if x > ginfo_winx : x = -mx
redraw 1
await 16
goto *main
|
|
Peasの方が処理の流れが分かりやすいかも。→animation.peas
- 初期設定
ループ内で何度も呼んではいけないような設定項目や何度も実行する必要のない項目はループに入る前に済ましておきましょう。
例:ボタンなどのオブジェクト、バッファへの画像読み込み
このスクリプトの場合変数mxもループ外で決定してしまっても良いのですが、簡単のため内部で決定しています。
- メインループ
この間を無限に繰り返すことで、何度も画面の書き換えを行ないます。
repeat〜loopを使わないのはプログラムミスによるネストエラーを起こしにくくするためです。
ゲームやアニメーションの場合、メインループ内では各種演算と描画処理を行うことが多いでしょう。
このスクリプトの場合、描画処理を行ってからその結果を利用して演算処理を行っています。
- redraw
画面のちらつき防止対策です。画面のちらつきの原因は、それぞれの命令で画面に描画させている間の動作が見えてしまっていることにあります。
redraw 0〜redraw 1の間の動作は画面上に表示されないので、ちらつきを防止することが出来ます。
1
2
3
4
5
6
7
8
|
| *main
redraw 0
redraw 1
await 16
goto *main
|
- 画面初期化
1
|
| color 255,255,255 : boxf : color : pos 0,0
|
ループの最初に、前のループで書いた画像全部を白で塗りつぶして、再度描く準備を行なっています。
これにより前のループの残像が残る心配がなくなります。
*画面初期化はscreen命令などによるウィンドウの初期化のことではありません。
「描いた部分だけを消す」や「描き換えない部分は残す」と言うようなことをやると
綺麗に消えず、残像が残るばかりか、プログラムが複雑になってしまいます。
慣れないうちはいったん最初に全部を消して、全部を描き直す方法と取りましょう。
慣れたらパフォーマンス向上の一環として、一部分だけ消去する方法を検討してみても良いでしょう。
また、画面の初期化は白(背景色1色)で塗りつぶす以外に、背景画像や、背景マップで塗りつぶす方法があります。
+
| | コラム:なぜcls命令やscreen命令ではなくboxf命令を使うか?
|
画面消去の命令には、boxf命令の他にcls命令やscreen命令があります。
しかし、cls命令やscreen命令はゲームスクリプトではあまり使用されません。なぜでしょうか?
最大の理由は、redraw命令を使ってもちらつきが抑えられないためです。
cls命令やscreen命令はredraw命令の有無に関係なく、画面を更新してしまいます。
また、cls命令は画面上のオブジェクトをすべて消去し、カレントカラーやカレントポジション、フォントなども初期化されてしまいます。
1
2
3
4
5
6
7
8
9
10
11
|
| *main
redraw 0
pos 30, 30
color 255
font msgothic, 24, 2
cls
mes "ちかちかさせず、赤く斜体で表示したいのに…"
redraw 1
wait 1
goto *main
|
他にも好きな色で初期化できないなどの理由が考えられますね。
以上の点から、ゲームスクリプトの画面消去にcls命令は使うべきではないでしょう。
|
ここでは画像ファイルを使ってアニメーションをさせる場合をやってみたいと思います。
まずは基本のアニメーション その1を習得してください。
画像ファイルを使用するここでのポイントは次のようになります。
画像はループ内で毎回picload命令で読み込むのではなく、メモリ上の仮想画面に画像ファイルを読み込んでおき、
そこからgcopyでメインウィンドウにコピーして表示させます。
もっとも重要な点はbufferウィンドウの概念を理解することにあります。
ここでの解説を応用すれば、「歩行アニメーションをしながら移動するキャラクター」といったようなものも作成することができるはずです。
ここでは上のアニメーション その1の図でいう、「文字などの描画」の部分だけを取り上げて解説します。
※イメージは一例であって、必ずこの手順を踏むとは限りません。
キーボードの矢印キーでキャラクターを移動させるサンプルです。
背景とキャラクターに画像を使っています。
+
| | アニメーション画面
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
|
chdir dirinfo(1)+"\\sample\\demo"
screen 1 : title "背景画像用サブウィンドウ"
buffer 1 picload "sky_bg.jpg"
wsizex.1 = ginfo_winx wsizey.1 = ginfo_winy
screen 2 : title "移動キャラクター用サブウィンドウ"
buffer 2 picload "efx.bmp"
wsizex.2 = ginfo_winx wsizey.2 = ginfo_winy
screen 0
*main
redraw 0
m = 5
stick key, 15
if key&1 : x -= m
if key&2 : y -= m
if key&4 : x += m
if key&8 : y += m
gmode 0
pos 0,0
gcopy 1, 0, 0, wsizex.1, wsizey.1
gmode 5,,,255
pos x, y
gcopy 2, 0, 0, wsizex.2, wsizey.2
redraw 1
await 16
goto *main
|
|
- 仮想画面
画像ファイルを用いたアニメーションでは次の複数のウィンドウを使います。
- メインウィンドウ … アニメーションを表示したりする、見せるウィンドウ。通常1つだけを使う。
- bufferウィンドウ … アニメーションに使用する部品の画像を仮置きするための、見せない作業用ウィンドウ。1つ以上、複数使う場合がある。
メモリからメモリへコピーするgcopy命令に比べ、picload命令はファイルにアクセスするのでとても動作が遅くなっています。
そのため、画像ファイルはいったんbufferウィンドウ(メモリ上)にpicload命令等で読み込んで仮置きしておきます。
メインウィンドウで画像を使うときは仮置きしたウィンドウからコピーして来て表示させます。
こうすることで画像をファイルから読み込むのは最初の1回だけになり、あとは高速なgcopy命令で処理することができるようになります。
- 画面コピーモード
HSPにはいろいろなコピーモードが用意されています。各モードの意味は自分でいろいろ試してみるとよく分かります。
通常ゲームでよく使われるキャラクターの背景を透明にする場合には通常はモード2を使用しますが、今回は使用した画像ファイルの都合でモード5を使用してみました。
ループ内でコピーモードの変更を行なう場合は、コピーモードの戻し忘れをしないよう注意が必要です。
コピーモードは1度設定すると、もう1度設定されるまで変わりません。
うっかり戻し忘れると自分が思っているコピーモードで表示されずにおかしな表示結果になることがあります。
- 画像の大きさを取得するには
picload命令は画像ファイルを読み込むと、自動的にウィンドウのサイズが画像の大きさにあわせられます。
これを利用することで画像の大きさを取得できます。
ツールにもおおよそのパターンが存在します。
ここでは簡単なbutton命令を中心としたツールのパターンを紹介してみます。
※イメージは一例であって、必ずこの手順を踏むとは限りません。
+
| | ツール
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
|
message = ""
mes "ボタンを並べる"
button gosub "ボタン1", *btn1
idBtn1 = stat
button gosub "ボタン2", *btn2
idBtn2 = stat
button gosub "ボタン3", *btn3
idBtn3 = stat
input message, 300
idInput1 = stat
button goto "終了", *owari
onexit goto *owari
stop
*btn1
dialog "ボタン1が押された!\nボタン1のオブジェクトID = " + idBtn1
return
*btn2
objprm idInput1, "ボタン2のオブジェクトID = " + idBtn2
return
*btn3
objprm idInput1, "ボタン3のオブジェクトID = " + idBtn3
return
*owari
dialog "プログラムを終了します"
end
|
|
- 全体の構成
前半で初期設定と画面の作成を行い、後半で実際に動作する部分を記述しています。
全ての処理は必ずstop命令で終了するようにします。stop命令が実行されると、
ボタンなどのオブジェクトの入力受付が開始されます。
- stop命令
スクリプトの前半と後半。各サブルーチン同士は必ずstop命令で区切られるようにしておきます。
誤動作防止です。
- オブジェクトID
オブジェクトIDはオブジェクト作成後、システム変数statに返されます。オブジェクト作成時にいっしょに取得しておくといいでしょう。
オブジェクトを作成した順番をあてにすると、あとからボタンなどのオブジェクトを増やしたり、順番を入れ替えたときに問題が発生しやすくなります。
- onexit命令
ウィンドウ右上の閉じるボタン(クローズボックス)をクリックしたときにジャンプするラベルを設定します。
編集中のファイルを保存するなどの用途に利用できますが、ジャンプ先で必ずend命令を実行するようにしてください。