プチコン3号 3日目 絵をボタン操作で動かす

昨日はスプライトを画面に表示して、座標の値を変化させて位置を動かしました。
今日はその続きで、Nintendo 3DSの操作パッドでスプライトを操作してみました。
キャラクターをスライドパッドで移動させ、Aボタンでジャンプさせます。

プチコン3号では、スライドパッドの入力は

STICK OUT DX,DY

です。
DXとDYには、実際にはスライドパッドの値を代入したい変数の名前を書きます。
値はそれぞれ、スティックが中央のとき0、左端・下端のとき-1.0、右端・上端のとき1.0です。
Y軸の座標系が画面とは逆になっています。

ボタンの読み取りはもう少し複雑です。
まず、読み取りモードが複数あり、使うモードをパラメータで指定します。
また、複数のボタンの状態を一度に読み取れるように、読み取り結果はビットパターンで返されます。
使い方は以下のようになります。

B=BUTTON(M)

Mはモードを表す整数、Bは読み取り結果を代入するための変数の名前を書きます。

読み取りモードは、

 0 押され続けている状態
 1 ボタンが押された瞬間だけビットが1になる(リピート機能付き)
 2 ボタンが押された瞬間だけビットが1になる(リピート機能なし)
 3 ボタンが放された瞬間だけビットが1になる

の4つが用意されています。
ゲームでの使い方を考えると、たとえば
・押している間だけ移動する → モード0
・押すと弾丸発射、押しっぱなしで連射 → モード1
・押すと弾丸発射、連射なし → モード2
・画面に描かれたボタンをクリックする場合 → モード3
というようになるでしょう。

返り値のビットパターンは、桁の小さいほう(右)から、
 上下左右ABXYLR
のようになっています。まあまあ覚えやすいですね。
ボタンと、それが押されているときの値の対応は下図のようになっています。

pc3-2.png

上のビットパターンを覚えていれば、値は計算で出せます。
今回はAボタンを使うので、右から5番目のビットですから
 2^(5-1) = 2^4 = 16
となります。小学生には、チョット難しいでしょうか・・・。

複数のボタンが押されている場合、値は足し算になります。
たとえば、上ボタンとAボタンが押されていると、16+1=17が返り値になります。

返り値の中に、ある値が含まれているかどうかはビット演算子「AND」で求めます。
たとえば、Bという変数に16という値が含まれているかどうかは、

B AND 16

の演算結果が0か0でないかで判別できます。含まれていないなら結果は0です。

2進数で書くと、16は10000、1は1、17は10001になります。
ANDという演算は、2つの2進数で両方とも1になっているところだけを抜き出します。
10001 AND 10000 = 10000です。
2進数を使うほうが分かりやすいと感じたら、プログラムも2進数で書くと良いかもしれません。
プチコン3号では、2進数は”&B”を頭につけます。
たとえば「B AND 16」は「B AND &B10000」と書いても同じです。

さて、今日つくったプログラムです。
長さは昨日とほとんど変わりません。

pc3-1.jpg

X=192:Y=112:Z=500
DZ=0
SPSET 0,310
@LOOP
STICK OUT DX,DY
X=X+DX*5
IF X>368 THEN X=368
IF X<0 THEN X=0
Y=Y-DY*5
IF Y>208 THEN Y=208
IF Y<0 THEN Y=0 IF DZ==0 THEN DZ=16 AND BUTTON(2)
Z=Z-DZ
IF Z<-200 THEN DZ=-DZ IF Z>500 THEN DZ=0:Z=500
SPOFS 0,X,Y,Z
S=1.0+(500-Z)/500
SPSCALE 0,S,S
VSYNC 1
GOTO @LOOP

STICK OUTで読み取ったスライドパッドの値は、絶対値が最大1.0と小さいので、5倍して速度の値として使っています。
画面の端から飛び出さないように、Xの最大値と最小値をチェックしています。
MAX、MINといった命令を使って書くやり方もあります。
Yの値もほとんど処理は同じですが、Y軸は画面とスライドパッドが逆方向なので、Y+DYではなくY-DYになっています。

Zですが、常にZ=Z-DZを実行していますので、Zの値をDZだけ減算しつづけています。
ボタンを押さないとき、DZは0で、Zは変化しません。
Aボタンが押されたら、DZに正の値を入れます。
するとZの値がどんどん小さくなっていきますので、最小値(ここでは-200にしています)に達したら、今度はDZを負の値にします。
今度はZがどんどん大きくなっていき、最大値(500)に達したらDZを0にします。

以下の部分は、プログラミング初心者には分かりにくいかもしれません。

IF DZ==0 THEN DZ=16 AND BUTTON(2)

DZに「16 AND BUTTON(2)」を代入しています。
BUTTON(2)には、全てのボタンの状態がすべて入っています。
その中から、Aボタンの状態だけを取り出すために、ビット演算「AND」を使います。
「16 AND BUTTON(2)」の演算結果は、Aボタンが押されたら16、押されていなかったら0になります。
その16という数値を、そのままDZの値として流用しています。

やろうとしていることから考えると、本当は

IF DZ==0 THEN
IF (16 AND BUTTON(2)) >0 THEN DZ=16
ENDIF

と書くべきところですが、IF文ひとつで済ませようと、横着しているわけです。

コメント