モジュール変数機能っていちいち命令にモジュール変数を指定するのが面倒です。たとえば以下のコード。
#module ball x, y, r, g, b
#modfunc set_ball_pos int _x, int _y
x = _x : y = _y
return
#modfunc set_ball_color int _r, int _g, int _b
r = _r : g = _g : b = _b
return
#defcfunc get_ball_x modvar ball@
return x
#defcfunc get_ball_y modvar ball@
return y
#modfunc draw_ball
color r, g, b
circle x - 30, y - 30, x + 30, y + 30
return
#global
newmod tamako, ball
set_ball_color tamako, 166, 227, 240
repeat
set_ball_pos tamako, sin( 0.07 * cnt ) * 140 + 320, -cos( 0.07 * cnt ) * 140 + 240
gosub *draw
await 33
loop
stop
*draw
redraw 0
color : boxf
draw_ball tamako
redraw 1
return
※ #defcfunc ~~ modvar MODULENAME@, ~~ で #modfunc の関数版のように使えます。でも公式に発表されている方法ではないのでたとえ今後のバージョンで使えなくなっても文句は言えません。HSP3WishList 46: #modcfunc を実装してほしい
一度にそのモジュールのモジュール変数を複数使う場合は仕方ないとして、一つしか使わない場合にもいちいちモジュール変数を指定するのはわずらわしいです。では、モジュール変数でなくしてみるとどうでしょうか。
#module ball
#deffunc set_ball_pos int _x, int _y
x = _x : y = _y
return
#deffunc set_ball_color int _r, int _g, int _b
r = _r : g = _g : b = _b
return
#defcfunc get_ball_x
return x
#defcfunc get_ball_y
return y
#deffunc draw_ball
color r, g, b
circle x - 30, y - 30, x + 30, y + 30
return
#global
set_ball_color 166, 227, 240
repeat
set_ball_pos sin( 0.07 * cnt ) * 140 + 320, -cos( 0.07 * cnt ) * 140 + 240
gosub *draw
await 33
loop
stop
*draw
redraw 0
color : boxf
draw_ball
redraw 1
return
今度はいちいちモジュール変数を指定する手間がありません。でも、後からボールを追加はできません(ボールAを設定して描画、そこにボールBを上書き設定してまた描画ってすればできないこともないですけれどそれも面倒です)。モジュール変数機能を使うけど、モジュール変数の指定を省略できたらいいなと思いました。そしてそれができるように改良してみました。
#module ball x, y, r, g, b
#define global set_ball_pos(%1=cur_inst@ball,%2,%3) _set_ball_pos %1, %2, %3
#modfunc _set_ball_pos int _x, int _y
x = _x : y = _y
return
#define global set_ball_color(%1=cur_inst@ball,%2,%3,%4) _set_ball_color %1, %2, %3, %4
#modfunc _set_ball_color int _r, int _g, int _b
r = _r : g = _g : b = _b
return
#define global ctype get_ball_x(%1=cur_inst@ball) _get_ball_x(%1)
#defcfunc _get_ball_x modvar ball@
return x
#define global ctype get_ball_y(%1=cur_inst@ball) _get_ball_y(%1)
#defcfunc _get_ball_y modvar ball@
return y
#define global draw_ball(%1=cur_inst@ball) _draw_ball %1
#modfunc _draw_ball
color r, g, b
circle x - 30, y - 30, x + 30, y + 30
return
#deffunc _init@ball
newmod tmp_inst, ball
dup cur_inst, tmp_inst
return
#deffunc new_ball var inst
newmod inst, ball
dup cur_inst, inst
return
#define global delBall(%1=cur_inst@ball) _delBall %1
#deffunc _del_ball var inst
if( varptr( cur_inst ) == varptr( tmp_inst ) ) {
return
}
delmod inst
dup cur_inst, tmp_inst
return
#deffunc select_ball var inst
dup cur_inst, inst
return
#global
_init@ball
コード1のモジュール部分をこれに置き換えても動作します。ただしコード2の場合は少し書き換えが必要です。
set_ball_color, 166, 227, 240
repeat
set_ball_pos, sin( 0.07 * cnt ) * 140 + 320, -cos( 0.07 * cnt ) * 140 + 240
gosub *draw
await 33
loop
stop
*draw
redraw 0
color : boxf
draw_ball
redraw 1
return
各命令の後ろにカンマを追加しなければなりません。
このモジュールではマクロの引数デフォルト値を使って、省略した場合はカレントに設定したモジュール変数を使うようになっています。 はじめにテンポラリのモジュール変数を作成して、それをカレントに設定しています。これでモジュール変数を省略しても動作するというわけです。
もちろん、これは一度に複数のモジュール変数を使う場合にも使えます。
new_ball tamako
set_ball_color , 166, 227, 240
new_ball mariko
set_ball_pos , 30, 60
set_ball_color , 200, 240, 166
repeat
set_ball_pos tamako, sin( 0.07 * cnt ) * 140 + 320, -cos( 0.07 * cnt ) * 140 + 240
select_ball mariko
if( cnt \ 8 == 0 ) {
dx = double( get_ball_x( tamako ) ) - get_ball_x()
dy = double( get_ball_y( tamako ) ) - get_ball_y()
d = sqrt( dx * dx + dy * dy )
}
set_ball_pos , dx / d * 10 + get_ball_x(), dy / d * 10 + get_ball_y()
gosub *draw
await 33
loop
stop
*draw
redraw 0
color : boxf
draw_ball tamako
draw_ball mariko
redraw 1
return
new_ball は新しいモジュール変数を作成して、カレントに設定しています。また、 select_ball では引数のモジュール変数をカレントに設定します。これでテンポラリでないモジュール変数も省略することができます。
省略したときもカンマが必要なのが少し惜しいのです。でもマクロの引数順序でモジュール変数を一番最後にやれば、「モジュール変数対応にしたいけれどそれだと一度に一つしか使わない場合でもいちいち指定しなければならないなぁ」というときに一度に一つしか使わない場合のコードはそのままでモジュール変数に対応できると思うので便利かもしれません。