これは Jasmine Tea アドベントカレンダー 2023 の 10 日目の記事です。
こんにちは、Jasmine Tea の開発に参加している石川です。この記事では Jasmine Tea の「手続き (PROCEDURE)」について説明します。
手続き(PROCEDURE) は複数の命令をひとまとまりにするための仕組みです。
プログラミングをしていると、プログラムが複雑になったり、似たプログラムが繰り返されてしまうことがあります。もし、複雑なプログラムをひとまとまりの命令のように書ければ、より分かりやすくする事ができます。同様に、繰り返されているプログラムもひとまとまりの命令のように書ければ、簡潔にすることができます。手続きをうまく使うことで、それらを実現できます。
PROCEDURE 命令と CALL 命令
次のプログラムは、クリックされたときや十字キーが押されたときにキャラクターを動かすというものです。
- クリック時: その場所から右にキャラクターを動かす
- 十字キー押下時: 中心からキーの方向にキャラクターを動かす
(動作確認はこちら)
sprite_number = 0
do
tap x, y
if x <> -1 and y <> -1 then
sprite sprite_number, 0, sprite_number * 4 + 3
show sprite_number, (x, y)
direction sprite_number, 3
distance sprite_number, 600
speed sprite_number, 20
move sprite_number
sprite_number = (sprite_number + 1) % 13
end if
key$ = inkey$()
if key$ = "ArrowLeft" then
sprite sprite_number, 0, sprite_number * 4 + 2
show sprite_number, (320, 200)
direction sprite_number, 7
distance sprite_number, 600
speed sprite_number, 20
move sprite_number
sprite_number = (sprite_number + 1) % 13
else if key$ = "ArrowUp" then
sprite sprite_number, 0, sprite_number * 4 + 1
show sprite_number, (320, 200)
direction sprite_number, 1
distance sprite_number, 600
speed sprite_number, 20
move sprite_number
sprite_number = (sprite_number + 1) % 13
else if key$ = "ArrowRight" then
sprite sprite_number, 0, sprite_number * 4 + 3
show sprite_number, (320, 200)
direction sprite_number, 3
distance sprite_number, 600
speed sprite_number, 20
move sprite_number
sprite_number = (sprite_number + 1) % 13
else if key$ = "ArrowDown" then
sprite sprite_number, 0, sprite_number * 4 + 0
show sprite_number, (320, 200)
direction sprite_number, 5
distance sprite_number, 600
speed sprite_number, 20
move sprite_number
sprite_number = (sprite_number + 1) % 13
end if
loop
この sprite から move までの命令は「キャラクターを動かす」ことを意味しています。これを procedure を使ってひとまとまりにしてみましょう。まずは、tap でキャラクタを動かす部分を procedure と end procedure でまとめ、それを call 命令で使うようにしてみましょう。(プログラムの全体はこちら)
procedure move_sprite
sprite sprite_number, 0, sprite_number * 4 + 3
show sprite_number, (x, y)
direction sprite_number, 3
distance sprite_number, 600
speed sprite_number, 20
move sprite_number
end procedure
sprite_number = 0
do
tap x, y
if x <> -1 and y <> -1 then
call move_sprite
sprite_number = (sprite_number + 1) % 13
end if
...
実は、このプログラムはうまく動きません。procedure の中では、sprite_number, x, y という変数に値が代入されていないため、それらの変数を使うことができないからです。
procedure の外の値を使うためには、「引数」として手続きに渡してあげればよいです。引数は procedure move_sprite number, x, y のように定義します。(プログラムの全体はこちら)
procedure move_sprite number, x, y
sprite number, 0, number * 4 + 3
show number, (x, y)
direction number, 3
distance number, 600
speed number, 20
move number
end procedure
sprite_number = 0
do
tap x, y
if x <> -1 and y <> -1 then
call move_sprite sprite_number, x, y
sprite_number = (sprite_number + 1) % 13
end if
このようにすることで、call 時点での sprite_number、x、y の値を、move_sprite の中で number、x、y として使うことができます。
手続きを他の場所でも使う
画面をクリックしたときのキャラクターの動かし方と、十字キーを押したときの画面の動かし方は少し違いますが、ほとんど同じです。違う部分は以下の 2 点です。
-
sprite sprite_number, 0, sprite_number * 4 + sdのsdの部分 -
direction sprite_number, dのdの部分
これら違う部分を引数として与えてあげれば、以下のプログラムのように、クリック用の手続きを十字キーに対しても流用できます。(動作確認はこちら)
procedure move_sprite number, x, y, sd, d
sprite number, 0, number * 4 + sd
show number, (x, y)
direction number, d
distance number, 600
speed number, 20
move number
end procedure
sprite_number = 0
do
tap x, y
if x <> -1 and y <> -1 then
call move_sprite sprite_number, x, y, 3, 3
sprite_number = (sprite_number + 1) % 13
end if
key$ = inkey$()
if key$ = "ArrowLeft" then
call move_sprite sprite_number, 320, 200, 2, 7
sprite_number = (sprite_number + 1) % 13
else if key$ = "ArrowUp" then
call move_sprite sprite_number, 320, 200, 1, 1
sprite_number = (sprite_number + 1) % 13
else if key$ = "ArrowRight" then
call move_sprite sprite_number, 320, 200, 3, 3
sprite_number = (sprite_number + 1) % 13
else if key$ = "ArrowDown" then
call move_sprite sprite_number, 320, 200, 0, 5
sprite_number = (sprite_number + 1) % 13
end if
loop
手続き(PROCEDURE)を使うことで、プログラムを簡潔にすることができました。
次回は
Jasmine Tea には「手続き」と似た仕組みとして、「関数(FUNCTION)」があります。次回はそれを使ってみます。
