SP仕様確認とアニメーション処理の基礎

NScripterと比較して、通常スプライトと拡張スプライトをごっちゃにして扱えるようになった。これは進歩。

最低限の記述

sp "sprite",{name="sprite.png"}

省略した場合の各種値は以下のようになる。

x
y
z
a
255
cell
cellnum
nameの指定による。
w
スプライトによる
h
スプライトによる
animtype
""
animtime
blend
visible
1
rot

通常スプライトと拡張スプライトの判別

もし、与えられたオプションの中にxがあれば、通常スプライトになる。
そうでなければ、cxの有無を調べ、あれば拡張スプライトになる。
さもなければ、やはり通常スプライトになる。

余分なパラメータ

通常スプライトでもrotなどを指定してもエラーにはならない。(反映はされないが)

非整数のパラメータ

xやyに非整数を与えてもエラーにはならない。与えられた値はそのまま保持して、getspinfoで取得できる。
実際の画面では四捨五入っぽい演算がなされた数値で処理される。
zに非整数を与えても問題はない。

zの扱い

マイナスも普通に受け付けて、値が少ないほど画面手前に来る。
同じz値を持つスプライトが複数あると、一つを除いて他は表示されなくなる。どれが表示されなくなるかは判然としない。マニュアルに載せる文言としては「保証しない」くらいだろう。
0.1でもずれていれば大丈夫なので、きちんと管理すること。

alphaの扱い。

設定した数値はそのまま保存される。
端数は受け付けるが効果があるかは不明。
255を越えたら255扱いになり、0で完全に透明。
マイナスも受け付けるが効果のほどは「保証しない」だろう。

通常スプライトと拡張スプライトの切り替え

SPMOVELT命令でスプライトを動かせば、そのスプライトは自動的に拡張スプライトになる。
逆にSPMOVE命令をスプライトを動かせば、そのスプライトは自動的に通常スプライトになる。

アニメーション処理

今回のスプライトのもう一つの革命的拡張は、アニメーションパターンを自前で作成できるようになったことだと思う。
animtimeが0以外の数値であれば、それはアニメーションの設定されたスプライトと判断される。
ここで、animtypeが

""
セル番号を増やしていって、限界数を越えたら最初に戻る。
"normal"
""と同じ。
"round"
最初は増えて、限界に達したら今度は逆にセル番号を減らし、0になったらまたプラスに転じる。(今現在どちらになっているかは、%info.animvecを調査すればわかる)
"stop"
増えていき、限界に達したらそこで止まる。
"lua"
別途作成したLuaの関数を起動させる。
上記以外
アニメーションはしない。

なお、このアニメーションはanimtimeを100に設定したからと言って、必ずしも正確に100ミリ秒きっちりで動いたりはしない。
アニメーション処理するかどうかチェックした時間を調べ、それが前回のアニメーション処理した時間(%info.countに格納)から、animtimeを超えて経過していれば、はじめてアニメーション処理をするようになっている。
なので重い処理を頻繁に挟むと、設定したanimtimeからどんどん遅延していくだろう。
また、アニメーション処理はvisibleの値とは関係なしに処理される。これは後述のanimtype="lua"でも変わらないので、スプライトをいじる以外の処理をしていると、困ったことになるかも知れない。

animtype="lua"

非常に拡張性が高いのに、調べてみると現時点ではまともな設定方法が存在していなかったりする。吐きそうw
Lua的な話になるが。
spをスプライトとして、sp.animtype="lua"ならば、sp.animfunc(spsetname, spname, sp)が実行される仕組みである。
なので、予めsp.animfunc=function()...endと設定しておかなければならないが、これをするための仕組みがBASICに用意されていない。
よって、作成した。

spmove.lua
-- spmove.lua

spmove = {}
do
	-- スプライトを円周上にに動かすアニメーション関数
	local vector = 0
	function spmove.funcname(spsetname, spname, sp)
		sp.cx = 400 + math.cos(vector) * 250
		sp.cy = 300 + math.sin(vector) * 250
		vector = vector + 0.1
	end
end

basic.registercom("SPSETANIMFUNC","SS")
function basic_func.SPSETANIMFUNC(name,funcname)
	local setname,spname=basic.spnamesplit(name)
	if not basic.spriteset[setname] or not basic.spriteset[setname][spname] then
		return -- deleteの場合は何もしない
	end
	local r=basic.spriteset[setname][spname]
	r.animfunc = spmove[funcname]
end

上記スクリプトをspmove.luaの名前で保存する。
その上で、BASICの中から

luafile "spmove.lua"

と実行する。
そうすると、SPSETANIMFUNC命令が作成されるので、スプライト名と関数名を与える。

spsetanimfunc "spname","funcname"

funcnameは、予めspmove.luaの中で作成しておかなければならない。

spmove.funcname = function(spsetname, spname, sp)
	-- ここに諸々の処理を書く。
end

関数の中からは問題のスプライトだけでなくNScripter2で扱える全てのリソースにアクセスできる。
よって、スプライトを動かすだけでなく、他のスプライトや音やキャプションを変更したり、全くもって自由自在である。
本気でスプライトアニメーションを活用しようと思ったら、STGなどで敵を動かしたり、スコア表示オブジェクトを作って点数アニメーションを自動でさせたりと言った使い方になるだろう。
AVGで使うなら、目パチアニメーションを自然な感じでやったり……と言うことになるか。

上記spmove.luaを使ってみた00.txt例
@start
luafile "spmove.lua"
sp "test",{name="chr\chr0.png",cx=400,cy=300,z=0,animtype="lua",animtime=100}
spsetanimfunc "test","funcname"
print #C
click
quit