プチコン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文ひとつで済ませようと、横着しているわけです。

プチコン3号 2日目 絵を動かしてみる

pc2-2.jpg

プチコン2日目は、画面に絵を表示してみます。
表示するだけなら、エディタでプログラムを書かずとも、ダイレクトモードで直接実行できます。

SPSET 0,502
SPOFS 0,200,160,500
SPSCALE 0,2.0,2.0

これで、RPG風のキャラクタが画面に表示されました。

1行目は、0番のスプライトに502番の絵を割り当てました。
スプライトというのは、画面に重ねて表示することができる小さな(16×16ピクセルの)絵です。
スプライトには、表示すると、重ねた下の画面は隠されますが上書きされない、という特徴があります。
ゲームで背景の絵に重ねて、敵や自分のキャラクタを表示するのに大変便利な機能です。
プチコン3号は512枚のスプライトを持っており、0~511の番号で指定します。

次にスプライトに割り当てる絵ですが、これも番号で指定します。
どの番号でどんな絵が出るかは、Smileツールで確認できます。
Smileツールのボタンは画面下部中央あたりにあります。

pc2-0.jpg

Smileツールが表示されたら、その画面の下部中央の「SPDEF」ボタンを押します。
これでスプライトの一覧が表示されます。
絵柄は4096通りあり、0~4095で指定します。

pc2-1.jpg

さて、次にスプライトの表示位置と大きさの指定です。

SPSET 0,502
SPOFS 0,200,160,500
SPSCALE 0,2.0,2.0

SPOFSはスプライトの表示位置を指定します。もちろん3次元で指定できます。
4つのパラメータ「0,200,160,500」はそれぞれスプライト番号、X、Y、Zの値です。
ちなみにOFSとは「offset」、基準点(原点)からの差分というような意味合いです。

SPSCALEはスプライトの拡大率です。
3つのパラメータはスプライトの番号、横方向の拡大率、縦方向の拡大率です。

SPOFSの値を変更すると、スプライトの表示位置が変わります。
値を連続的に変えてやれば、スプライトを動かすことができます。
簡単なプログラムを書いてみました。

pc2-3.jpg

X=0:Y=0:Z=200
DX=1:DY=1:DZ=20
SPSET 0,502
@LOOP
X=X+DX
IF X>368 OR X<0 THEN DX=-DX Y=Y+DY IF Y>208 OR Y<0 THEN DY=-DY Z=Z+DZ IF Z>500 OR Z<-200 THEN DZ=-DZ SPOFS 0,X,Y,Z S=1.0+(500-Z)/500 SPSCALE 0,S,S VSYNC 1 LOCATE 0,0,0 PRINT X," ",Y," ",Z GOTO @LOOP

プログラムの中身ですが、スプライトを一定速度で動かし、画面の端まで行ったら戻ってくるようにしています。
DX、DY、DZが単位時間の移動量(=速度)で、正の値と負の値で移動方向を指定しています。
X, Y, Zでどれもやっていることは同じです。

ちなみに単位時間とは、1/60秒です。
これはVSYNCで指定します。1/60秒が、指定できる最短の単位時間です。

なおVSYNCとはVertical Sync(垂直同期)のことで、アナログのビデオ回路の走査線が下から上へ戻るときの同期信号から来ています。昔のゲーム機は、ビデオ回路が画面を描いている途中で絵を変化させると、ちらつきなどの悪影響が出ていました。そのため、走査線が戻る期間(画面を描いていない時間帯)に一気に画面を更新するようにしていたのですね。

Z軸方向の移動については、スプライトが遠いときほどサイズを小さくするようにして、動きをデフォルメしてみました。
このほうが、画面の中で動いている感じが出ると思います。

画面の座標系は、原点が左上。
一般的なグラフなどと違って、Y軸が下向きです。
画面サイズはX軸が400、Y軸が240です。
Z軸は、画面位置が座標0で、手前が負、遠くが正。
画面奥行き方向は最大1024、画面手前方向は-256までの値で指定します。

スプライトも(特に指定しなければ)原点は左上になります。
2倍に拡大した(32×32ピクセル相当の)スプライトの右端が、画面の右端に一致するとき、スプライトの座標は

400 – 32 = 368

となりますので、上のプログラムでは座標が368を超えたときにX軸上の移動方向を反転するようにしています。

プチコン3号は、小学生にプログラミングを学ばせるのが目的なのかなと思ったのですが、その割に初歩的な解説が少ないようなので、今回は初心者講座っぽく詳しめに書いてみました。
昔はBASICの解説本は非常に多かったのですが、今ではマイナーな言語になってしまったのですね。

プチコン3号 初めの一歩

というわけでプチコン3号の話題です。
公式の簡易マニュアルはこちらにあります。
プチコン3号 – 簡易電子説明書

ただ、このマニュアルは初めてプチコンを使う人向きではないので、最初に眺めるには、最初から入っている公式のデモプログラムを動かすところから始めるこちらの解説のほうが良いと思います。
プチコン3号 – プチコン3号を最初から

用意されたデモは結構多いので、最初は眺めるだけでも結構楽しめます。
ただ、そこからプログラミング開始へは、この解説だとちょっとハードルが高い感じがします。

まずはそれよりも、前回紹介したABAさんの

1000円を握りしめてニンテンドーeショップに駆け込み、プチコン3号を買って、以下のプログラムを打ち込もう。

をやってみました。

まずトップメニューから「SmileBASICでプログラムを作る」を選びます。

pc1-1.jpg

するとこんな画面になります。

上半分は、かつてのマイコン少年にはおなじみの画面です。
下半分はソフトウェアキーボードと開発環境のメニューを兼ねています。

pcshell.jpgpcide.jpg

ただ、昔のマイコンのように上半分の画面で直接プログラムを入力するのではありません。
上半分の画面は「ダイレクトモード」と呼ばれており、要するにコマンドシェルの役割をしているようです。
プログラムを入力するには、下画面のEDITボタンを押します。

pc1-2.jpg

すると上半分の画面がエディタになりますので、ここでプログラムをポチポチと入力していきます。
こんな感じです。

pcedit.jpg

プログラムの内容はABAさんの記事にあるとおり

@1:LOCATE RND(48),RND(30),RND(500)-250:PRINT “バカ”:GOTO @1

です。
SmileBASICでは行番号は無く、@で始まるラベルを用いるようです。
カナの入力はEDITボタンの上にある入力モード切替ボタンで指定します。
「バ」は最初キーボードに出てきませんが、シフトキーを押すと出てきます。

入力が終わったら、EDITボタンの左にあるDIRECTボタンを押します。
すると上画面がダイレクトモードに戻ります。

pc1-3.jpg

ここで

RUN

と入力しEnterキーを押すとプログラムが実行されます。
プログラムの停止は3DS本体のSELECTボタンです。

画面が「バカ」で埋め尽くされたままですので

CLS

と入力してスクリーンをクリアしましょう。

以上でプログラムを入力して動かして止めることができましたが、上のプログラムをちょっとだけ変更して、バカの色をランダムに変更するようにしてみましょう。
それにはプログラムを以下のように変更します。

@1:LOCATE RND(48),RND(30),RND(500)-250:COLOR RND(16),RND(16):PRINT “バカ”:GOTO @1

これで同じように実行すると、今度は文字の色と背景色がそれぞれランダムに設定されます。
ただ、実行が速すぎて何が何だかわかりませんね。
そこで、以下のようにさらに1命令追加します。

@1:LOCATE RND(48),RND(30),RND(500)-250:COLOR RND(16),RND(16):PRINT “バカ”:VSYNC(10):GOTO @1

なお、SELECTでプログラムを停止すると、その時点の文字色・背景色で停止します。
CLSだけでは文字色・背景色が元に戻りませんので、これを元通りに黒の背景・白の文字色にリセットするには、

ACLS

と入力します。

こんな感じで初めの一歩は終わりです。
次は、やっぱり絵を表示したいですね!!