プチコン3号 ショートサンプル&ドリル / 十字キー編

プチコン3号の短いサンプルプログラムと、かんたんな演習問題。ドリルを解くと、だんだんプチコンプログラミングを覚える、みたいな。
「新しい命令」は プチコンで 3DS のゲームを作ろう #petitcom - 木曜不足 に出てきてないもの。

■サンプル 1. 十字キーで移動(斜め移動できない)

X=200:Y=120
SPSET 0,600  ' 600 は好きなキャラクタの番号に変えていいよ
WHILE 1
  B=BUTTON()
  IF B==1 THEN Y=Y-1
  IF B==2 THEN Y=Y+1
  IF B==4 THEN X=X-1
  IF B==8 THEN X=X+1
  SPOFS 0,X,Y
  VSYNC
WEND

キャラクタ(スプライト)の番号はスマイルツールか プチコンの標準 BG とスプライトの一覧を作ってみた #petitcom - 木曜不足 を見てね。


▼新しい命令:

BUTTON(ボタン)
どのボタンが押されているかを返す関数。引数の意味は SmileBasic – 『プチコン3号 SmileBASIC』公式サイト 参照。押されているボタンの数値の足し算を返す。A と B の両方が押されていたら(それ以外が押されてなかったら) 16+32=48 が返る。
十字ボタン上 1
十字ボタン下 2
十字ボタン左 4
十字ボタン右 8
A 16
B 32
X 64
Y 128
L 256
R 512
ZR(拡張パッド) 2048
ZL(拡張パッド) 4096


▼問題:

  • [問題 1-1] 作ったけど、移動がものすごく遅い。速さを3倍にするには?
    • (ヒント) IF B==1 THEN Y=Y-1 は「上を押されたら、上に 1 動く」。動くのを3倍にするには? 新しい命令: なし
  • [問題 1-2] ずっと左を押してると画面から出て行ってしまう。画面のはしっこにきたらそれ以上左に行かないようにするには?
    • (ヒント) 今は「左が押されたら X=X-1」だけなので画面の外に行けてしまう。「左が押されていて、まだ左に行っても大丈夫なら X=X-1」に書き換える。「まだ左に行っても大丈夫」を X の式で書くと? 新しい命令: &&
&&(アンド)
IF 文で「〜と〜の両方が成り立ったら」という、2つ(以上)の条件を書きたいときに使う。「 IF A>0 && B>0 THEN 」と書くと「 A>0 かつ B>0 なら〜」という意味になる
    • (さらにヒント) X や Y がどうなったら「画面のはしっこ」なのかわからないってときは、 X と Y の値を画面に表示してみるといい。 VSYNC の前に次の1行を入れてみよう。
  CLS:PRINT X,Y
PRINT
画面に文字や数を表示する
CLS
画面の文字を消す。 ACLS はスプライトなども全部(オール)消すけど、 CLS が消すのは文字だけ。

■サンプル 2. 十字キーで移動(斜め移動できる)


サンプル 1 では、上ボタンと右ボタンを同時に押したら動かない。
斜めに動いて欲しいとか、「右に移動しながら A ボタンで撃ちたい」とか、そういうのは AND を使って、 IF の条件 B==1 を (B AND 1)==1 のように書き直すと思った通りの動きになる。

X=200:Y=120
SPSET 0,600
WHILE 1
  B=BUTTON()
  IF (B AND 1)==1 THEN Y=Y-1
  IF (B AND 2)==2 THEN Y=Y+1
  IF (B AND 4)==4 THEN X=X-1
  IF (B AND 8)==8 THEN X=X+1
  SPOFS 0,X,Y
  VSYNC
WEND


▼新しい命令:

AND(アンド)
くわしく説明するには「二進数」が必要。学研のまんが「算数頭をつくるひみつ」は「二進数」をやさしくおもしろく説明してくれている。ここではかんたんな説明をする。
たとえば「下ボタンだけ」を押したら B=BUTTON() は 2 だけど、左を押しながらだと 2+4=6 、B と同時押しだと 2+32=34 になる。つまり IF B==2 THEN は「ほかのボタンはどれも押さず、下ボタンだけが押されたら〜」ということ。だから斜めに行けないし、「移動しながら弾をうつ」とかもできない。
IF B==6 THEN, IF B==34 THEN って押されるかもしれない全部のパターンを並べる……なんて無理だから、ここはさっきのような足し算の中にどんな数が入っているのかわかる AND を使う(なんでもわかるわけじゃなくて、この場合はわかるってこと。ここが「二進数」のポイント)。2 AND 2 も、 6 AND 2 も、34 AND 2 も全部、下ボタンが押されていれば B AND 2 は 2 になるけど、下ボタンが押されてなかったら、ほかにどんなボタンが押されていても B AND 2 は 0 になる。
だから、IF (B AND 2)==2 THEN って書けば、「ほかに押されたボタンがあってもなくても、下ボタンが押されたら〜」って命令になる。(B AND 2) にカッコが付くのは、AND より == の方が優先順位が高く、カッコを忘れたら B AND (2==2) になってしまうから。
AND も && も「アンド」なのはたまたまじゃあなくて関係があるんだけど、「二進数」について知らないあいだは別のもの( && は複数の条件を並べるとき用、AND は BUTTON 用)と思っておいた方が間違いがない。プチコン3号のよく使う命令で、「二進数」のことを知ってた方がうれしいのは BUTTON くらいしかないから、急がなくても大丈夫。*1


▼問題:

  • [問題 2-1] 移動がやっぱり遅い。速さを3倍にするには?
    • (ヒント) 問題 1-1 といっしょ。
  • [問題 2-2] いつでも速いと操作しにくい。 B ダッシュ、つまり B ボタンを押しているときだけ速さを3倍にするには?
    • (ヒント) 移動の大きさを V=1 のように変数を使って表せば、B ボタンが押されたときに V に別の値を入れるだけでスピードを変えることできる! でも IF B==32 THEN だと「 B ボタンだけが押されたら」になってしまうので……。新しい命令: なし
  • [問題 2-3] どっちに動かしてもキャラクタの向きが変わらないのはつまらない。上に動かしたときは上に、右に動かしたときは右に向かせたい。
    • (ヒント) お姫様のスプライトの番号は、右=596、下=600、左=604、上=608 である。今は SPSET 0,600 ってなっているからずっと下(正面)向きなわけ。移動の大きさを変えたいときは V=1 と新しい変数を作った。向きに合わせてスプライトの番号を変えたいときは……。新しい命令:IF THEN のあとの :(コロン)
IF(イフ) 〜 THEN(ゼン)
THEN の後ろの命令は条件が成立したら実行されるけど、そこに2つ以上の命令を書きたいとき、命令の後に :(コロン) で区切れば、2つ目・3つ目の命令を続けることができる。
  • [問題 2-4](ちょい難) 向きは変わるようになったけど、動きがないからスケートで滑ってるみたい。歩いてるみたいに足を動かしたい。
    • (ヒント) スプライトの番号を 596,597,598,599 の順番に変えて、599 の次は 596 に戻せば右に歩いているように見える。同じように下は 600,601,602,603、左は 604,605,606,607、上は 608,609,610,611。向きごとにプログラムを書いたら大変そうだけど、よく見ると全部、(最初の数), (最初の数)+1, (最初の数)+2, (最初の数)+3 ってなっている。つまり、[2-3] で用意した変数と、ループを回るたびに 0, 1, 2, 3 の順番に変わる ( 3 のあとは 0 に戻る) 変数があれば……。

*1:次の機会は SPCOL のマスクを使いたいときだろう。