プチコン3号講座 SMILE BASIC

NINTENDO 3DSのプチコン3号の使い方、プログラミング方法を紹介します。

2014年12月

実行を終わらせるには END

あまり使うことはないかもしれませんが、プログラムを途中で終わらせたい。
というときに使う命令があります。

それはENDです。

これを書くと、その部分を実行するときにプログラムが終了します。

サンプルを作ってみましょう。
100回中に99が出るまで繰り返すのですが、最後の20回で出たらそこで終了します。
最後の20回以外は99が出ても繰り返しを続けます。

' 画面をクリアする
ACLS
' 100回繰り返す
FOR intLoop = 1 TO 100
  ' ランダムに数を取得する(Aに設定)
  A= RND(99) + 1
  ' もし、Aが99の場合
  IF A = 99 THEN
    ' 繰り返し回数が80回を超えていた場合
    IF intLoop > 80 THEN
      ' メッセージの表示(?かいめですがおわります。)
      PRINT intLoop;"かいめですがおわります。"
      ' プログラムを終了する
      END
    ' 判定終わり
    ENDIF
    ' メッセージの表示(?かいめ:?がでました)
    PRINT intLoop;"かいめ:";A;"がでました"
  ' 判定終わり
  ENDIF
' 繰り返し終わり
NEXT intLoop
' メッセージ(さいごのほうで99がでませんでしたby  ヒロシ or イエモン )
PRINT "さいごのほうで99はでませんでした でませんでした でませんでした"

2014123003

上記の実行結果は下のようになります。

2014123004

2014123005

画面にタッチされたことを判断する TOUCH

ボタンでの操作は前回学びましたが、3DSといったら、やはりタッチ操作もそのひとつですね。

タッチした場所を取得する命令はTOUCHです。

TOUCH [端末ID], OUT STTM, TX, TY

端末IDというのは、複数の3DSを接続したときに一つ一つを識別する固有IDです。
これについては、マルチプレイゲームを作るころに書きたいと思います。

OUTというのは、外から入ってくる値という意味で、INPUT$のときに入力した文字や数字が入るのと同じです。

TOUCHを実行すると、STTM, TX, TYに値が入ります。

STTMには、タッチされているかどうかが入ります。
0:タッチされていない  1:タッチされている。
タッチされている場合にTXにタッチされたいるX座標
TYにタッチされているY座標が入ります。

では、サンプルを作ってみましょう。
タッチしたら、それに該当する上画面にキャラクターを表示するというものです。
Bボタンを押すと終了します。

' 画面をクリアする
ACLS
' 終了フラグに0を入れておく
ENDFLG = 0
' 終了フラグが0の間繰り返す
WHILE (ENDFLG == 0)
  ' ボタン取得命令
  BT = BUTTON(1)
  ' Bボタンが押されたら
  IF (BT AND 32) == 32 THEN
    ' 終了フラグに1を設定(繰り返しを抜けるため)
    ENDFLG = 1
  ' 判定終わり
  ENDIF

  ' タッチ取得命令
  TOUCH OUT STTM, TX, TY

  ' タッチされたなら
  IF STTM > 0 THEN
    ' 位置をタッチされた1/10の場所にする
    LOCATE TX / 10, TY / 10
    ' 大を表示する
    PRINT "大"
  ' 判定終わり
  ENDIF

  ' 垂直同期
  VSYNC
' 繰り返し終わり
WEND
2014123001


ボタン命令については
ボタンの入力を受け付けるには? BUTTON VSYNC

WHILE~WENDについては
繰り返し処理をしたいその2 WHILE~WEND

LOCATEは
文字の表示位置を指定するには? LOCATE

さて、実行した結果は
2014123002

Bボタンを押すと終了します。

ボタンの入力を受け付けるには? BUTTON VSYNC

パソコンのゲームならキーボードのキーを入力して移動とかしますが、NINTENDO 3DSなら十字キーやAボタンなどで動かすほうが楽しいですよね。

NINTENDO 3DSのボタンの入力を受け付ける命令はBUTTONです。

変数=BUTTON([機能ID [,端末ID]])

機能IDは
0:押され続けている状態
1:押された瞬間(リピート機能付き)
2:押された瞬間(リピート機能なし)
3:放された瞬間

端末IDは、通信対戦で使うNINTENDO 3DSを識別するID
ということです。

通信対戦については、もう少し先で取り上げたいと思います。

このBUTTONの命令で、ボタンが押されると変数に値が入ります。

変数の値(ビット単位での状態)
1:十字ボタンの上
2:十字ボタンの下
4:十字ボタンの左
8:十字ボタンの右
16:A
32:B
64:X
128:Y
256:L
512:R
1024:未使用
2048:XL(拡張パッド使用時)
4096:XR(拡張パッド使用時)

さて、返って来る変数の値はビット単位での状態という注釈がついています。
どういうことでしょう?

まず、ビットについては
ビットとは?

を読んでください。

上記を読んでも、今回の数字とは結びつかないかもしれません。
ビットは0と1であらわせます。
1は1ですが、2は10とあらわせます。
4は100で8は1000です。
(※二進数で表記しています。)

こうみていくと、ボタンごとに1の位置が変わることがわかります。

つまりボタンが何も押されていない状態
0=0000000000000
十字ボタンの上が押されると
1=0000000000001
十字ボタンの下が押されると
2=0000000000010
十字ボタンの左が押されると
4=0000000000100
十字ボタンの右が押されると
8=0000000001000
となっていきます。

A
16=0000000010000
B
32=0000000100000
X
64=0000001000000
Y
128=0000010000000
L
256=0000100000000
R
512=0001000000000

XL
2048=0100000000000
XR
2048=1000000000000

さて、どうしてこういう値をとっているのでしょうか?

それは、ボタンというのは同時に押されるからです。
たとえば、上と左が押されたらどうなるでしょうか。
上(1)+左(4)=5 
5=0000000000101
数字の5で見ると、よくわかりませんがビットで見ると
上ボタンの位置(1桁目)と左ボタンの位置(3桁目)が1になっています。

つまりビットで見るとどのボタンが押されているかがわかるのです。

さて、受け取ったボタンの値を使うにはどうすればいいでしょうか?
たとえば上ボタンが押されたときに↑を表示したいときです。

A=BUTTON()
IF A == 1 THEN
  PRINT "↑"
ENDIF

これでどうでしょうか?

先ほど書いたとおり上と左を同時に押されることもあります。
そのときももちろん上ボタンが押されているので↑を表示しなければなりません。

IF A == 1 OR IF A == 5 THEN
  PRINT "↑"
ENDIF

しかし、右上や、Aボタンを押しながら上を押されたらどうなるでしょう?
それぞれ値が異なることになり、全部のパターンを書いていたら大変です。

そこでビット演算子を使用します。
わからない方は
ビット演算子とは?
を読んでみましょう。

さて、ビット演算子を使うと簡単にあらわすことができます。
A=BUTTON()
IF (A AND 1) == 1 THEN
  PRINT "↑"
ENDIF

A AND 1 の1は上ボタンの値です。
押されたボタンと上ボタンの値をAND演算子で計算したときに1が返って来ると押されたボタンの中に上が含まれているとなります。

ちなみに左ボタンが押されていることを判断したいなら
A=BUTTON()
IF (A AND 4) == 4 THEN
  PRINT "←"
ENDIF

となります。

さて、簡単なサンプルを作ってみましょう。

画面上の「大」をボタン操作で動かすというものです。
Bボタンを押すと終わります。

---------------------------------------------------------------------
ACLS '画面をクリアする

AX=0 'X座標の位置
AY=0 'Y座標の位置
AZ=0 'Z座標の位置
A=0  'ボタン変数

WHILE A != 32  'Bボタンが押されるまで繰り返す
  A = BUTTON() 'ボタンの入力状態の取得 ()内を指定しないときは0と同じ
  IF (A AND 1) == 1 THEN '上ボタンが押されたら
    AY = AY - 1        'AYから1を引く("大"の位置をひとつ上にする)
  ENDIF
  IF (A AND 2) == 2 THEN '下ボタンが押されたら
    AY = AY + 1        'AYから1を足す("大"の位置をひとつ下にする)
  ENDIF
  IF (A AND 4) == 4 THEN '左ボタンが押されたら
    AX = AX - 1        'AXから1を引く("大"の位置をひとつ左にする)
  ENDIF
  IF (A AND 8) == 8 THEN '右ボタンが押されたら
    AX = AX + 1        'AXから1を足す("大"の位置をひとつ右にする)
  ENDIF
  IF (A AND 256) == 256 THEN 'Lボタンが押されたら
    AZ = AZ - 1        'AZから1を引く("大"の位置をひとつ奥にする)
  ENDIF
  IF (A AND 512) == 512 THEN 'Rボタンが押されたら
    AZ = AZ + 1        'AZから1を足す("大"の位置をひとつ手前にする)
  ENDIF

  IF AX < 0 THEN 'AXが0より小さくなったら
    AX = 0     ' AXに0を入れる(画面からはみださないように)
  ENDIF
  IF AX > 49 THEN 'AXが49より大きくなったら
    AX = 49     ' AXに49を入れる(画面からはみださないように)
  ENDIF
  IF AY < 0 THEN 'AYが0より小さくなったら
    AY = 0     ' AYに0を入れる(画面からはみださないように)
  ENDIF
  IF AY > 28 THEN 'AYが28より大きくなったら
    AY = 28     ' AYに28を入れる(画面からはみださないように)
  ENDIF
  IF AZ < -256 THEN 'AZが-256より小さくなったら
    AZ = -256     ' AZに-256を入れる(画面からはみださないように)
  ENDIF
  IF AZ > 1024 THEN 'AZが1024より大きくなったら
    AZ = 1024     ' AZに1024を入れる(画面からはみださないように)
  ENDIF

  LOCATE AX, AY, AZ  '位置の指定
  PRINT "大"        'キャラクタ"大"の表示
WEND            '繰り返しここまで

LOCATE 0,0,0       '画面位置の初期化

------------------------------------------------------------------------
ACLSについては
画面をきれいに(クリア)するには? CLS ACLS

WHILEについては
繰り返し処理をしたいその2 WHILE~WEND

IFについては
どちらか選ぶには?IF文

LOCATEについては
文字の表示位置を指定するには? LOCATE
ちなみにLOCATEの説明を読むと、AX,AY,AZの最大値の判断をしているかがわかります(指定値の最大)

PRINTについては
簡単な命令を実行してみる

さて、実行してみましょう。

いろいろボタンを押してみると、画面のようになってしまい、思ったように動きません。
2014122901


これはBUTTONの命令が前に押された情報を持ち続けてしまうためです。
たとえば、上ボタンを押すと、Aに1が入ります。
しかし、上ボタンを離してもAには1が入り続けます。

そのため、AYの値が変わり続けます。

Bボタンを押してプログラムを終了しましょう。

さて、この情報を持ち続けてしまうのをやめるにはどうしたらいいか?

それがVSYNC命令です。

VSYNC [フレーム数]
と指定します。

フレーム数を入れないと、1になります。

ヘルプを読むと、指定回数分の垂直同期が来るまでプログラムの実行を停止。
と書いてあります。

垂直同期とはなんでしょうか?

3DSは画面を表示するとき、1秒間に何回も画面を書き換えています。
1秒間に何回書き換えられるかで、カクカクしないキャラクタの動きになります。

パラパラ漫画ってありますよね。
書く枚数が多いほど、なめらかに動きます。

あれと一緒で、1秒間に30回とか、60回とか画面が書き換えられているのです。

そして、垂直同期というのはその書き換え時に同期をとって、調整をする
といった感じです。

がり勉君が、集中して勉強をしていました。
5時間ぶっつづけで国語の勉強をしています。
お母さんが、何回か、お夜食を持ってきて、食べたら?と聞いたのですが、集中しているので何も聞こえません。

そこで、1時間に1回休憩するように取り決めをしました。

そうすると、1時間ごとに、お夜食を食べたり、別の教科の勉強を始めることができました。

この休憩が垂直同期だと思ってもらえばいいでしょう。

VSYNCのパラメータ[フレーム数]の
フレーム数は、パラパラ漫画の1枚を1フレームとすると、何個分パラパラさせた後に休憩をとるか・
といった感じになります。

これを、どこにいれましょうか。
それは、繰り返しの一番最後くらいに入れておきましょう。

最終的に、こんなプログラムです。
2014122902
2014122903


実行結果はこんな感じです。

2014122904

さて、ボタンの説明のつけたしですが、

機能IDは
0:押され続けている状態
1:押された瞬間(リピート機能付き)
2:押された瞬間(リピート機能なし)
3:放された瞬間

ということです。

どういう違いがあるでしょうか。

まず、0もしくは、パラメータを入れなかった場合は押され続けている状態です。
ボタンを押している間キャラクタがその方向に動きます。

1、2、3は、それぞれ、ボタンを押したその1回分だけ動きます。
手を放して、もう一度押すことでさらに動きます。

連打ゲームなんかでは有効な感じです。
押したときか、手を放したときか、どっちかを判断したいときに、1,2,3
それぞれ使います。
1と2の違いはまた別の機能が関係します。

リピート機能をつけたときには、1、リピート機能をOFFにしたときは2を使うといいでしょう。

さて、リピート機能、2進数については、詳しく説明する予定はありませんが、コメントに説明希望が多かったらあやることにしましょう。


ビット演算子とは?

計算に使える+-×÷()あたりは以前学習しました。

値の設定

それ以外にも、ビット演算子というものも使えます。
どういったものでしょうか?

AND
OR
XOR
NOT
<<
>>

です。

ANDやOR、NOTはなんとなくわかる気がします。

ANDは、~かつ~
ORは、~または~
NOTは、~以外
といった意味合いを持ちます。

それを計算式に使うとは?

まず、ビット演算子というくらいですから、ビットに関係します。
ビットについては
ビットとは?
を見てください。

1ビットの計算で考えて見ましょう

1ビットは0と1であらわせるということです。
では、
A AND B
を考えて見ます。

Aと、Bとも1ビットの値だとします。
Aが1で、かつBも1だと、答えは1になります。

Aが1で、Bが0だと答えは0になります。
これは逆にAが0でBが1でも0になります。

1 + 1 = 2
ですが
1 AND 1 = 1
1 AND 0 = 0
0 AND 1 = 0
0 AND 0 = 0
となります。
両方が1の場合のみ1になります。

わかりますでしょうか?

では、条件で考えて見ましょう。
スーパーマリオブラザーズの敵にぶつかって死ぬ条件を考えて見ましょう。

マリオが小さい状態かつ敵にぶつかったら、マリオ死亡です。

マリオが小さい:1
マリオが大きい:0

敵にぶつかった:1
敵にぶつかっていない:0

マリオ死亡:1
マリオ生きている:0

と考えると、
マリオが小さい(1) AND 敵にぶつかった(1)で、マリオ死亡(1)

マリオが大きい(0)と敵にぶつかって(1)もマリオは死にません(0)
またマリオが小さい(1)ときでも敵にぶつかっていない(0)なら死にません(0)

2つの条件がどちらも正しいときにその結果が起きるというわけです。

なんとなくわかったでしょうか?

続いてORです。
これはどちらかが成立すればよいとなります。
ビットであらわすと
1 OR 0 = 1
0 OR 1 = 1
1 OR 1 = 1
0 OR 0 = 0

というように、どちらかが1なら1になります。

王様が勇者の証か、ロトの剣を持ってきたら、勇者と認めてあげようといったとします。

勇者の証を持っている:1
勇者の証を持っていない:0

ロトの剣を持っている:1
ロトの剣を持っていない:0

勇者として認める:1
勇者として認めない:0

勇者の証を持っていれ(1)ば、ロトの剣を持っていなく(0)ても、勇者として認められます(1)。
勇者の証を持っていなくても(0)、ロトの剣を持っていれば(1)、勇者として認められます(1)。
もちろん両方持っていれば(1)(1)、文句なく勇者として認められます(1)

2014121304


続いてNOTです。
これは、否定の意味ですから
ある事象の反対の意味にします。
魔王を倒す。という事象の反対の意味は魔王を倒さない。
NOT 魔王を倒す = 魔王を倒さない
生存の反対の意味は死亡だとしたら
NOT 生存 = 死亡

となります。


では、ここからよくわからない演算子になります。
XOR

1 XOR 1 = 0
1 XOR 0 = 1
0 XOR 1 = 1
0 XOR 0 = 0

これはなかなか使わないので、現実世界の例は出せません。
私が使用した例は暗号化と、復号化というものです。

たとえば4ビット使って6という数字をビットであらわすと
0110
これに 4ビットの15のXOR計算します。
15は1111です。

0110 XOR 1111 = 1001
(1桁ずつXORしています)
で、9になりました。

今度はその9にたいして、15のXORをとります。
1001 XOR 1111 = 0110
で、6になりました。

つまり、元の数字に戻りましたね。

本当は6という数字を保存しておきたいが、そのままだと誰にでもわかってしまうので、15でXORした数字を保存しておきます。
その元の数字を使いたいときに、15でXORすることで使えるようになります。

データを暗号化して、元に戻したいときなどに利用できる演算子といえます。

次は>>
右シフトです。

これはビット値を右に移すというもので、
たとえば6という数字の4ビット
0110
を右に1桁シフトしたい場合
6 >> 1
とします。
0110は右にひとつずつずれると0011になります。
0011は3ですから、6>>1=3になります。

逆に<<左シフトは
ビット値を左に移します。
6<<1は6のビット値を左に1桁移します。
0110を左に一桁移すと1100です。
1100は12ですから、
6<<1は12になります。
2014121305

ビットとは?

プログラムをしている人でもなかなか聞かない言葉ですが、結構重要な言葉だったりします。

パルテナの鏡の主人公はピットですが、ここで話しているのはビットです。
弓矢は関係ありません。

では、いったいビットとはなんでしょうか?

これはコンピュータがわかる最小の単位といいましょうか。

ちなみにこの講座を読んでいる世代が、いまだ特定できていないためどういうたとえのほうがわかりやすいのか見えていません。

ためしに、小学生でもわかるかもしれない感じで例を出して見ましょう。

理科で豆電球と電池をつないで、電球の光がついたりつかなかったり、といった実験をしたことがありますよね。

スイッチをつなげると、光がついて、スイッチをはずすと、光が消えます。
これがコンピュータがわかる最小の単位です。

まだ、わかりにくいですよね。

光がついてない・・・電気が流れていない状態を0とします。
光がついている・・・電気が流れている状態を1とします。

コンピュータはこの0と1でいろいろな状態を知ることができます。

1ビットというと、この0と1を1個だけ持っているような感じです。

たとえば、パルテナの鏡の主人公ピットが
弓矢を撃っていない状態を0
弓矢を撃っている状態を1
として、弓の撃つ情報を1ビットで持っています。
(本当かどうかは別として)

もっと身近な例としては、
まぶたを閉じた状態を0
まぶたを開けた状態を1
として1ビットで表すことができます。

このビットをつなげていくと、もっと多くの状態がわかるようになります。

2ビットだと、二つのビットを持っていますので
00、01、10、11の4つの情報がわかります。
4択問題があらわせる様になります。

3ビットだと001~111の8つの情報
4ビットだと0001~1111の16個の情報を持てるようになります。

1ビット増えるごとに情報量が2倍になります。

ですから、8ビットはどれだけ情報を持てるかというと
2×2×2×2×2×2×2×2=256個の情報がもてるということになります。

ちなみにファミコンは8ビットコンピュータで、1度に処理できるのが256個の情報ということになります。
よく、持ち物の上限が255個だったりするのはそういう関係があったりします。

ビットについて、なんとなくわかったでしょうか?
最新コメント
カテゴリー