M5StickCにはLCDが付いているので、画面上で図形を動かすようなスケッチを作ることができます。
今回は、M5StickCの画面上で、ボールを自由落下させ、地面に着いた時に跳ね返るようなスケッチを作ってみます。
ひとつひとつのステップごとに、動作確認をしながら、進めていきます。
ボールを自由落下させる
まず最初に、ボールを自由落下させてみます。
F = mg の式で重力を求め、そこからボールの加速度「a」、ボールの速度「v」、ボールの移動距離「x」を求めていきます(画面のサイズが小さいので、それにあわせて数値を補正しています)。
その結果に基づいて、ボール(円)を描画します。
これを一定間隔で繰り返します。
スケッチは以下のとおりです。
#include <M5StickC.h> float t = 0.0f; // 画面の上端座標 float g = 9.8f; // 重力加速度 float m = 1.0f; // ボールの質量 float r = 10.0f; // ボールの半径 float x = t+r; // ボールの位置(中心座標) float v = 0.0f; // ボールの速度 void setup() { M5.begin(); M5.Lcd.setRotation(1); } void loop() { M5.update(); if(M5.BtnA.wasPressed()) { x = r; v = 0.0; } float f = m * g; float a = f / m / 10; v += a; x += v; M5.Lcd.fillScreen(BLACK); M5.Lcd.fillCircle((int)x, 40, (int)r, YELLOW); delay(20); }
結果は以下のとおりです。ボタンAを押すと、ボールが落ちます。
ボールをバウンドさせる
上記のスケッチでは、ボールは落ちていくだけなので、ここでは、ボールが地面に到達したときに、バウンドさせてみます。
ボールが地面に沈み込んだ時に、F = kx の式で、弾性力を考慮します。
スケッチは以下のとおりです。
#include <M5StickC.h> float t = 0.0f; // 画面の上端座標 float b = 160.0f; // 画面の下端座標 float g = 9.8f; // 重力加速度 float m = 1.0f; // ボールの質量 float r = 10.0f; // ボールの半径 float k = 20.0f; // バネ定数 float x = t+r; // ボールの位置(中心座標) float v = 0.0f; // ボールの速度 void setup() { M5.begin(); M5.Lcd.setRotation(1); } void loop() { M5.update(); if(M5.BtnA.wasPressed()) { x = r; v = 0.0; } float f = m * g; if(x+r > b) { float f2 = k * ((x+r)-b); f = f - f2; } float a = f / m / 10; v += a; x += v; M5.Lcd.fillScreen(BLACK); M5.Lcd.fillCircle((int)x, 40, (int)r, YELLOW); delay(20); }
結果は以下のとおりで、ボールが地面に到達すると、跳ね返るようになりました。
ただし、ボールの勢いは減衰せず、永遠にバウンドを繰り返します。
ボールのバウンドを減衰させる
上記では、ボールが永遠にバウンドし続けるので、バウンドを減衰させ、最終的には止まるようにしてみます。
弾性力を考慮する時に、同時に F = cv の式で、粘性抵抗も考慮します。
スケッチは以下のとおりです。
#include <M5StickC.h> float t = 0.0f; // 画面の上端座標 float b = 160.0f; // 画面の下端座標 float g = 9.8f; // 重力加速度 float m = 1.0f; // ボールの質量 float r = 10.0f; // ボールの半径 float k = 20.0f; // バネ定数 float c = 2.0f; // 粘性係数 float x = t+r; // ボールの位置(中心座標) float v = 0.0f; // ボールの速度 void setup() { M5.begin(); M5.Lcd.setRotation(1); } void loop() { M5.update(); if(M5.BtnA.wasPressed()) { x = r; v = 0.0; } float f = m * g; if(x+r > b) { float f2 = k * ((x+r)-b); float f3 = c * v; f = f - f2 - f3; } float a = f / m / 10; v += a; x += v; M5.Lcd.fillScreen(BLACK); M5.Lcd.fillCircle((int)x, 40, (int)r, YELLOW); delay(20); }
結果は以下のとおりです。ボールが地面に到達すると跳ね返りますが、跳ね返るごとに高さが低くなり、最終的には止まるようになりました。
それほど難しい処理はしていませんが、視覚的にも結構おもしろいスケッチを作ることができました。
このような処理を組み合わせることで、色々と、より複雑な描画もできそうです。
なお、私がM5Stack、M5StickCの使い方を習得するのにあたっては、以下の書籍を参考にさせていただきました。
ごく基本的なところから、かなり複雑なスケッチや、ネットワーク接続など、比較的高度なものまで、つまづかずに読み進めていけるような構成になっており、大変わかりやすい本です。
このサイトで書いている、M5Stackシリーズ(M5Stack、M5StickCなど)に関するブログ記事を、「さとやまノート」という別のブログページに、あらためて整理してまとめました。
他のM5Stackシリーズの記事にも興味のある方は「さとやまノート」をご覧ください。