フルカラーLEDのWS2812Bを10個使い、LED1個をボールに見立てたスカッシュゲームです。
今回は、IchigoJam Rを使ってプログラムしました。
一番手前のLEDが光った時に、IchigoJamのタクトスイッチ(SW2)を押して打ち返します。
空振りなどで打ち損じたときはゲームオーバーです。
フルカラーLEDの使い方は、テキスト「LEDでナナイロづくり」も参考にしてください。
‘simpleSQUASH
30 CLV:W=20:Q=10
100 @MAIN
110 [ABS(P)*3]=0
130 P=P+1
140 [ABS(P)*3]=50
150 WS.LED Q
160 IF P==Q-1 BEEP30:P=1-Q
170 IF P!=0 WAIT W:GOTO@MAIN
180 IF BTN() GOTO@GAMEOVER
210 CLT
220 @HIT
230 IF BTN() BEEP5:GOTO@MAIN
240 IF TICK()<W GOTO@HIT
250 @GAMEOVER
260 BEEP 100,120
■変数の説明■
W ボールスピード
ボールが動く際の待ち時間(WAIT値)を指定します。
値を大きくすると遅く、小さくするとに早くなります。
Q フルカラーLEDの個数
WS2812Bの個数を指定します
定数*1としてWS.LED命令のパラメータとして使うほか、打球位置や壁判定などに使用します。
今回のスカッシュプログラムでは10個ですが、もっと多く使う時は配列の制限により30個以内としてください。
P 現在のボールの位置※2
LEDを光らせる、ボールの位置が入ります
一番手前のボールを打つ場所のLEDが0で、壁になるところが9もしくは-9の値になります。
[] 配列 WS.LED命令が使う各フルカラーLEDのGRB値を指定します
1個目のLEDは、[0][1][2]の各配列に、G、R、Bの輝度値(0~255)が設定されます
※1 定数として使う場合には、プログラム実行中に値を変えないようにします。
わざわざ変数とした理由は、LED個数が違うWS2812Bを取り付けても、プログラムの修正が一箇所で済むためです。
■プログラムの説明■
30行目 CLV:W=20:Q=10
使用する変数の初期化をします。
▪️変数の説明▪️を参照してください
100行目 @MAIN
ボールを打って帰ってくるまでを繰り返す、メイン処理です。
110行目 [ABS(P)*3]=0
現在のボール位置※2を、消灯に設定します。
130行目 P=P+1
ボールの位置を移動※2させます。
140行目 [ABS(P)*3]=50
新しいボールの位置※2を、緑色(輝度50)に設定します。
150行目 WS.LED Q
フルカラーLEDを、配列に設定した値で点灯させます。
この行を実行する毎に、ボールが動いて見えます。
160行目 IF P==Q-1 BEEP30:P=1-Q
ボールが端(壁)に到達したら、方向を反転※2させます。
今回のスカッシュプログラムでは、変数Pが9のときに、-9に書き換えます。
BEEP30で音を鳴らして、ボールが壁から跳ね返った効果を出します。
170行目 IF P!=0 WAIT W:GOTO@MAIN
ボールが一番手前の打球位置でなければ(変数Pが0でなければ)、@MAIN処理に戻りボール移動※2を続けます。
ボールが打球位置にあるならば(変数Pが0ならば)、次の行に進みます。
180行目 IF BTN() GOTO@GAMEOVER
不正対策の処理です。
タクトスイッチを押し続けていれば、ここで@ゲームオーバー処理に行きます。
210行目 CLT
220行目 @HIT
230行目 IF BTN() BEEP5:GOTO@MAIN
240行目 IF TICK()<W GOTO@HIT
打球判定処理※3をおこないます。
制限時間内に、IchigoJamのタクトスイッチが押されれば打ち返し成功となり、
高いBEEP音を鳴らして、@MAIN処理に戻ってゲームを続けます。
打ち損じたときは、次の行に進みます。
250行目 @GAMEOVER
260行目 BEEP 100,120
ゲームオーバーの処理を行います。
BEEP音を低く長く鳴らして、ゲームオーバーの効果を出します。
プログラムはここで終了し、コマンドプロンプトになります。
※2 ボール移動は変数Pの正負を利用して動かします。
Pの値は、1,2,3,4,5,6,7,8,9,-8,-7,-6,-5,-4,-3,-2,-1,0 のように変化していき、
値が正数ならボールが壁に近づく動きとなり、負数なら壁から離れる動きをします。
ABS(P)はPの絶対値を返すので、この値をそのまま配列で使うことができきます。
ボールの動き(LEDの位置)と変数Pの値の変化は、次のプログラムを追加して、
1ステップずつ実行してみるとよくわかります。
145 PRINT P:INPUT Z
※3 220〜240行目の打球判定処理は、1行にまとめることもできます。
220 ifBtn()beep5:goto@MAIN:elseIfTick()<Wcont
■応用と改良■
1.ボールの色を好きな色にする
・140行目でボールの色を決めるので、次の式で設定します。
[ABS(P)*3]=緑の輝度(G)
[ABS(P)*3+1]=赤の輝度(R)
[ABS(P)*3+2]=青の輝度(B)
緑、赤、青の輝度を、0から255の範囲で設定します。
・LET命令で1行で色設定することもできます。
緑なら、LET[ABS(P)*3],50,0,0
赤なら、LET[ABS(P)*3],0,50,0
マゼンダは、LET[ABS(P)*3],0,50,50
明るい青なら、LET[ABS(P)*3],0,100,0
眩しいホワイトなら、LET[ABS(P)*3],255,255,255
のようにプログラムします。
この方法ならプログラム量も少なくて済みます。
・ 色設定サブルーチンの仕組みを利用すると、虹色も設定できます。
140 C=C+1:LET[ABS(P)*3],C&150,C>>1&150,C>>2&1*50:IFC>6C=1
いずれの方法も、110行目でボールを消灯する設定をしてください。
110 LET[ABS(P)*3],0,0,0
2.ボールの残像を残す
110行目の消灯処理を改造して、徐々に光が消えるようにします。
ボールの通った跡に残像が残るようになります。
110 FOR J=0 TO Q*3:[J]=[J]/2:NEXT
なお、IchigoJam R以外は処理速度が遅いため、
次のようにFOR命令にSTEPオプションを追加すると改善できるでしょう
110 FOR J=0 TO Q*3 STEP3:[J]=[J]/2:NEXT
3.ボールを打つところから、ゲームスタートにする
@MAIN処理の前にカウントダウン処理を加え、P=-1を設定しておくと、
カウントダウン後に、タクトスイッチ押打でゲームスタートできます。
空振りは、即ゲームオーバーとなります。
4. 壁と打球位置を別の色で点灯する
例えば、壁を赤、打球位置を青にする場合は、次のようにプログラムを加えます。
新しいボール位置を設定する直前の行に追加すると、ボールが壁や打球位置で消えることがありません。
120 LET[(Q-1)*3)],0,50,0:LET[0],0,0,50
5.打ち返すごとに得点を入れる&最高得点を表示する
得点用の変数Tなどを追加し、打ち返すごとに+10づつ足していくようにします。
ゲームオーバー処理で最高得点を表示させ、ゲームをより楽しくすることもできます
6.ボールをスピードアップしていく
ボールを打ち返すたびに、変数Wの値を-1ずつ減らして難易度をあげるようにします。
7.壁が迫るようにする
ボールを打ち返すたびに、壁が迫るように位置を変えていきます。
変数QにLED個数が設定されていることを利用して、壁で打ち返すごとにQの値を減らすとよいでしょう。
こちらもだんだん難しくなっていくので、ゲームバリエーションが増えて楽しくなります。
8.2人対戦にする
壁側にもう一人の打球位置を設定して、キーボードのスペースキーで打ち返すように改造します。
160行目の壁判定の後に2人目の打球処理を追加するとよいでしょう。
IF命令やループ命令が必要になるので、サブルーチンにすると作りやすいです。
対戦ゲームとなるので、得点の変数や、再ゲームなどの処理も必要となり、多岐に改良が必要です。

この教材は「Creative Commons — CC BY-SA 4.0」の下に提供されています。
