●応用編 で かにしの編 その5 スプライト移動
ちょっと落ち着いたので、一応「応用編」です。
サンプルにすることでかにしの編も兼ねているというあたり、深い意味はなさそうです
前置きとして、Nスクにはスプライトを移動する命令が二つあります
"msp"と"amsp"、前者が相対的な増分を取るのに対して、後者は絶対位置での移動指定。
for文で"msp"を使うのが割と楽なのですが、そのままだと移動速度が環境に依存してしまいます。
PCではシュパーと移動しても、遅いマシン、特にPSPだとし、ゆ、う、ぅ、ぱ、ぁ、ぁというように…
そこでタイマーと組み合わせて移動量を調整することで、ほぼ同じ時間で移動させてみます。
原案はNスクスレその8>450です。感謝
とりあえずPerlでの移植は無視して、Nスクでどうすればいいか
lsp 6,"image/G1_AA01S.jpg",800,-40 saveoff resettimer #タイマー作動 for %1=1 to 999999 #ひたすら繰り返します gettimer %2 #経過した時間を取得 if %2>=500 break #完了時間を超えてたら終了 mov ?1[0],800+(591-(800))*%2/500 #?は配列。x座標を計算してます。 mov ?2[0],-40+(-40-(-40))*%2/500 #y座標(透過度も同じように求められます) amsp 6,?1[0],?2[0],255 #求めた現在あるべき座標に移動 print 1 #表示 next #ふりだしに戻る amsp 6,591,-40,255 #最後に終点で表示 print 1 saveon
このように 始点+(終点-始点)×経過時間÷完了時間 という計算式を立てます。
現時点での絶対位置を求め、そこにスプライトを移動。
あとはタイマーが完了時間を越えるまで、ひたすら上記の処理をぶんまわしてやればおk
そんなに難しくないですね
次に他のスクリプトからの機械的変換を試みます
吉里吉里はデフォルトの"move"タグが都合よく終点と時間を指定しているので、
単純にマッチさせてやればその二つは問題ありません
@move layer=0 path=(-150,0,255) time=2000 ↓ $line =~ /^@move layer=(\d*) path=\((.\d*),(.\d*),(\d*)\) time=(\d*)/ ;
少しめんどくさいのが始点の取得です。
Nスクではスプライトの表示座標を得る命令がないので、表示する度にPerlの変数に
入れておくのがいいでしょう。
例:かにしのでの座標管理
;#スプライト表示(始点取得) elsif ( $line =~ /^%00%48%([0-9A-Fa-f][0-9A-Fa-f])%([0-9A-Fa-f][0-9A-Fa-f])%([0-9A-Fa-f][0-9A-Fa-f])%([0-9A-Fa-f][0-9A-Fa-f])%([0-9A-Fa-f][0-9A-Fa-f])(?:%00){5}%[0-9A-Fa-f][0-9A-Fa-f](.*?)%00/ ){ $num = 6 - hex($1); #スプライト番号(Nスクは若い方が上になります) if ( substr($3,0,1) eq "f" ){ #後ろ1バイトが"F"で始まる場合 $left[$num] = hex($2) - (( 256 - hex($3)) * 256); #こういう式のようです }else{ $left[$num] = hex("$3$2"); #x座標。スプライト番号で配列へ } if ( substr($5,0,1) eq "f" ){ $top[$num] = hex($4) - (( 256 - hex($5)) * 256); #同様にy座標 }else{ $top[$num] = hex("$5$4"); } $dec = $6; $dec =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack("H2", $1)/eg; print OUT "lsp $num,\"image/$dec.jpg\",$left[$num],$top[$num]\n"; }
;#移動時の終点取得 elsif ( $line =~ /^%00%4b%([0-A-Fa-f][0-9A-Fa-f])%([0-A-Fa-f][0-9A-Fa-f])%([0-A-Fa-f][0-9A-Fa-f])%([0-A-Fa-f][0-9A-Fa-f])%([0-A-Fa-f][0-9A-Fa-f])%([0-A-Fa-f][0-9A-Fa-f])%([0-A-Fa-f][0-9A-Fa-f])/ ){ if ( $moveon[$num] == 1 ){ $num = 7 - hex($1); #スプライト番号。上とは一つずれてます $mnum[$mn] = $num; #以下、移動する個数"$mn"でそれぞれの値を配列に if ( substr($3,0,1) eq "f" ){ $endleft[$mn] = $left[$num] + ( hex($2) - (( 256 - hex($3)) * 256) ); #データは増分なので、始点+増分で終点を求めます }else{ $endleft[$mn] = $left[$num] + hex("$3$2"); } if ( substr($5,0,1) eq "f" ){ $endtop[$mn] = $top[$num] + ( hex($4) - (( 256 - hex($5)) * 256)); # }else{ $endtop[$mn] = $top[$num] + hex("$5$4"); } $movetime = hex("$7$6"); $mn++; #移動する個数チェック $moveon[$num] = 0; }else{ $moveon[$num] = 1; #何故か同じ移動命令が二回続くので、一回目はスルー } }
上手いことデータをこねくり回して座標その他を取得出来たら、
}elsif ( $line =~ /^%00%4c%/ ){ #00 4b で記述された移動命令を実行します
&move();
$mn = 0; #移動フラグ初期化
}
sub move{
print OUT "saveoff\nresettimer\n";
print OUT "for %1=1 to 999999\n";
print OUT "gettimer %2\n";
for ( $i = 0 ; $i < $mn ; $i++ ){
$num = $mnum[$i];
print OUT "mov \?1\[$i\],$left[$num]+($endleft[$i]-($left[$num]))*%2/$movetime\n";
print OUT "mov \?2\[$i\],$top[$num]+($endtop[$i]-($top[$num]))*%2/$movetime\n";
print OUT "amsp $num,\?1\[$i\],\?2\[$i\],255\n";
}
print OUT "print 1\n";
print OUT "if %2>=$movetime break\nnext\n";
for ( $i = 0 ; $i < $mn ; $i++ ){
$num = $mnum[$i];
print OUT "amsp $num,$endleft[$i],$endtop[$i],255\n";
$left[$num] = $endleft[$i]; #最後に、移動の終点を次回の始点として使えるようにします
$top[$num] = $endtop[$i];
}
print OUT "print 1\nsaveon\n";saveon
}
と処理。(いつかスクリプトに※入れます)
サブルーチンに一々引数を渡すのがめんどくさいので、座標類はグローバル変数だったりします。
分けた意味ナス
ちなみに途中にあるfor文で、同時に移動するスプライトの数だけ計算→移動を繰り返します
理論上は何個でも動かせるとは思いますが、サンプルに使ったかにしのでは
立ち絵4つが同時に動くのが最大だったので未検証です。というかそれも体験版だけだったし…!
追記)
よく考えると、わざわざ増分から終点求める必要はないですね
始点+増分×経過時間÷完了時間 で済む話でした。
吉里吉里の場合は値が終点なので上記のようにしたのか。
ちなみに吉里吉里はよーいドンで動き出さないので、複数動かすための判定が難しいかも
breakのポイント変更。行き過ぎちゃってましたね


