結論から言うと、モジュール変数を外部からそのままアクセスすることは不可能です(全てprivate変数)。
しかし、いくつかの提案はありますので目を通していただければ幸いです。
1. 個別にアクセサを用意する。
#runtime "hsp3cl"
#module playerInfo _pos_x,_pos_y
// pos_xアクセサ
#modcfunc pos_x
return _pos_x
#modfunc set_pos_x int v
_pos_x=v: return
// pos_yアクセサ
#modcfunc pos_y
return _pos_y
#modfunc set_pos_y int v
_pos_y=v: return
// 代入演算子
#define global reset(%1,%2,%3,%4) set_%2%1,%2(%1)%3%4
#modinit
_pos_x=0
_pos_y=0
return
#global
newmod py1,playerInfo
mes pos_x(py1)
set_pos_x py1,10
mes pos_x(py1)
reset py1,pos_x,+,12
mes pos_x(py1)
reset py1,pos_y,-,12
mes pos_y(py1)
愚直ですが、この方法が一番きれいだと思います。
僕はこの方法で一貫してモジュール変数を公開させています。
書き換え不能な変数としたい時も単にsetterを削除すればよいので
アクセス権限も比較的操作しやすいです。
2. モジュール空間内でラベルをコールバックさせる。
#runtime "hsp3cl"
#module playerInfo pos_x,pos_y
#modinit
pos_x=0
pos_y=0
return
// モジュール空間内でラベルをコールバック
#modfunc with label l
gosub l: return
#global
newmod py1,playerInfo
if 0{*py1_l
mes pos_x@playerInfo
pos_x@playerInfo=10
mes pos_x@playerInfo
return}
with py1,*py1_l
/* @playerInfoを省略する書き方 *//*
#define pos_x pos_x@playerInfo
#define pos_y pos_y@playerInfo
if 0{*py1_l
mes pos_x
pos_x=10
mes pos_x
return}
with py1,*py1_l
*//* または、 *//*
#define ctype pi(%1) %1@playerInfo
if 0{*py1_l
mes pi(pos_x)
pi(pos_x)=10
mes pi(pos_x)
return}
with py1,*py1_l
*/
始めに直接モジュール変数を操作することは不可能だと申しましたが、
この方法を使えば無理やりですが可能です。
モジュール内でモジュール変数にアクセスできる状態でgosubで飛ばすと
モジュール外でもラベルに飛ばされている間だけ使用することができます。
使用する時は用法・用量を守ってお使いください。
3. 列挙体と配列で構造体もどき。
#runtime "hsp3cl"
#enum pos_x = 0
#enum pos_y // 1
// #enumの個数
#enum pi_length // 2
#module
#deffunc playerInfo array v
v=0,0: return
#global
playerInfo py1
mes py1.pos_x
py1.pos_x=10
mes py1.pos_x
//多次元配列は始めから上限を指定(dim,sdim,ddim)する必要がある。
#module
#deffunc playerInfo_enemy array enemy,int n
dim enemy,n,pi_length
repeat n
enemy.cnt.pos_x=256
enemy.cnt.pos_y=256
loop
return
#global
playerInfo_enemy enemy,10
// 配列は括弧で括ってもドットで繋いでも良い。
mes enemy.0.pos_x // 256
mes enemy(1,pos_x) // 256
// 配列の自動拡張を利用したい場合は最大次元が可変次元となる必要がある。
#module
#deffunc playerInfo_enemy2 array enemy
dim enemy,pi_length,1
enemy.pos_x.0=512
enemy.pos_y.0=512
return
#global
#module
#deffunc playerInfo_enemy2_add array enemy
enemy_length=length2(enemy)
enemy(pos_x,enemy_length)=512
enemy(pos_y,enemy_length)=512
return
#global
playerInfo_enemy2 enemy2
mes length2(enemy2) // 1
playerInfo_enemy2_add enemy2
mes length2(enemy2) // 2
// 最大次元の0は省略可
mes enemy2.pos_x // 512
mes enemy2(pos_x,1) // 512
古典的な方法ですが、列挙体(#enum)と配列で保持する方法があります。
難点としては型が固定されることや、
配列であるため取り回しが少し悪いことにありますが、
希望される書き方には一番近い物かと思います。
4. マクロ(#define)で専用の変数を生やす。
#runtime "hsp3cl"
#define ctype playerInfo(%1) \
%1_pos_x=0 :\
%1_pos_y=0
playerInfo(py1)
mes py1_pos_x
py1_pos_x=10
mes py1_pos_x
#define ctype playerInfo_add(%1) \
%1_pos_x(length(%1_pos_y))=0 :\
%1_pos_y(length(%1_pos_y))=0
playerInfo(enemy)
playerInfo_add(enemy)
mes enemy_pos_x.0 // 0
mes enemy_pos_x.1 // 0
余談で言っていらした、"専用の変数"をマクロ(#define)で用意させる方法です。
変数を新しく生成しているので、配列のように型による制限はありません。
その代わり、py1を一つの物体として扱うことは難しくなるでしょうか。
py1に対してまとめて操作を与えるときは何をするにもマクロに頼らざるを得なくなると思いますので、
それがデメリットとなるでしょう。
なお、マクロで変数名を繋げる場合、#defineでctypeを使わないと
隙間が空いて変数名が切れてしまうのでctypeが必須となります。
あとは余談ですが、最初のget,setを使う場合は、
switchを使用するよりもif&returnしてしまう方が簡潔に書けますね。
#runtime "hsp3cl"
#module playerInfo pos_x,pos_y
#modinit
pos_x=0
pos_y=0
return
// 変数の値を返す
#modcfunc get str v
if v="pos_x": return pos_x
if v="pos_y": return pos_y
return -1
// 変数の値に代入
#modfunc set str v,int x
if v="pos_x": pos_x=x: return
if v="pos_y": pos_y=x: return
return 1
// 代入演算子
#define global reset(%1,%2,%3,%4) set %1,%2,get(%1,%2)%3%4
#global
newmod py1,playerInfo
mes get(py1,"pos_x")
set py1,"pos_x",10
mes get(py1,"pos_x")
reset py1,"pos_x",+,12
mes get(py1,"pos_x")
reset py1,"pos_y",-,12
mes get(py1,"pos_y")