モジュール変数の指定を省略する方法を考えた

モジュール変数機能っていちいち命令にモジュール変数を指定するのが面倒です。たとえば以下のコード。

コード1:モジュール変数を普通に使ったスクリプト
#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 を実装してほしい

一度にそのモジュールのモジュール変数を複数使う場合は仕方ないとして、一つしか使わない場合にもいちいちモジュール変数を指定するのはわずらわしいです。では、モジュール変数でなくしてみるとどうでしょうか。

コード2:モジュール変数を使わないスクリプト
#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を上書き設定してまた描画ってすればできないこともないですけれどそれも面倒です)。モジュール変数機能を使うけど、モジュール変数の指定を省略できたらいいなと思いました。そしてそれができるように改良してみました。

コード3:モジュール変数の指定を省略できるようにしたモジュール
#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の場合は少し書き換えが必要です。

コード4:コード2をコード3のモジュールで動作するように書き換えたもの
    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

各命令の後ろにカンマを追加しなければなりません。

このモジュールではマクロの引数デフォルト値を使って、省略した場合はカレントに設定したモジュール変数を使うようになっています。 はじめにテンポラリのモジュール変数を作成して、それをカレントに設定しています。これでモジュール変数を省略しても動作するというわけです。

もちろん、これは一度に複数のモジュール変数を使う場合にも使えます。

コード5:一度に複数のモジュール変数を使う場合
    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 では引数のモジュール変数をカレントに設定します。これでテンポラリでないモジュール変数も省略することができます。

省略したときもカンマが必要なのが少し惜しいのです。でもマクロの引数順序でモジュール変数を一番最後にやれば、「モジュール変数対応にしたいけれどそれだと一度に一つしか使わない場合でもいちいち指定しなければならないなぁ」というときに一度に一つしか使わない場合のコードはそのままでモジュール変数に対応できると思うので便利かもしれません。

インフォメーション

公開日時
2007年12月10日 午後7時38分25秒
最終更新日時
2007年12月20日 午後10時5分32秒
カテゴリ
HSP