M5core2を使って惑星軌道のシミュレーションをしてみた【物理演算】

動いている様子

ベースとしたのは上記ツイートの物理演算。以下ではボールの速度に対応して軌跡の色を変え、初期値として画面中央に重力源を設置しました。

完成プログラム(コピペで動きます)

#include <M5Core2.h>
#include <Fonts/EVA_20px.h>

uint16_t getRGB(double h){
  int r,g,b;
  r = 400.0 *h;
  g = 100;
  b = 200.0-300.0*h;
  return M5.Lcd.color565(r,g,b);
}
class Ball{
private:
  int X;
  int Y;
  double Vx;
  double Vy;
public:
  Ball(int x, int y, double vx, double vy){
    X = x;
    Y = y;
    Vx = vx;
    Vy = vy;
  }
  void setValues(int x, int y, double vx, double vy){
    X = x;
    Y = y;
    Vx = vx;
    Vy = vy;
  }
  void addVelocity(double vx, double vy){
    Vx = Vx + vx;
    Vy = Vy + vy;
  }
  void updatePosition(){
    X = X + Vx;
    Y = Y + Vy;
  }
  void addAttractive(int posx, int posy){
    double force = -30.0/((X-posx)*(X-posx) + (Y-posy)*(Y-posy));
    Vx = Vx + force*(X-posx);
    Vy = Vy + force*(Y-posy);
  }
  void draw(){
    double velocity = (Vx*Vx + Vy*Vy)/200.0;    
    M5.Lcd.drawPixel(X,Y,getRGB(velocity));
  }
};


Ball ball1(100,100,0,10);

void placeString(short int X, short int Y, char *string){
  M5.Lcd.setCursor(X, Y);
  M5.Lcd.printf(string);
}
void setup() {
  M5.begin(true, true, true, true);
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setTextColor(BLACK);
  M5.Lcd.setTextSize(2);
  delay(1000);
}

void loop() {
    TouchPoint_t pos = M5.Touch.getPressPoint();
    if(pos.x > 0){
      if(pos.y > 240 && pos.x > 218){
        ball1.setValues(100,100,0,0);
      }else{
        ball1.addAttractive(pos.x, pos.y);            
      }
    }
    ball1.addAttractive(160,120);
    ball1.updatePosition();
    delay(10);
    ball1.draw();  
    
}

プチ解説

このプログラムではBallというクラスを作成し、loop処理の中で位置を更新しています。Ballクラスの中身は上記のプログラムを参照ください。

Ballクラスを使った物理演算の順番は以下の通り。

Ball ball1(100,100,0,10); //ball1という名前のクラスを生成

まずBallオブジェクトを生成します。ball1という名前にしましたが何でも構いません。引数の前半2つは設置するx,y座標、後半2つは初期の速度vx,vyです。今回はy方向に10pixel/frameの速度を与えました。

ball1.addAttractive(160,120);

これは更新処理です。ball1に対して引力を与える点を引数の座標に追加します。太陽系でいう太陽ですね。

ball1.updatePosition();

このメソッドの呼び出しで、現在の座標に速度を足して新たな座標を設定します。

ball1.draw();

最後にdraw()をすれば、更新された座標に新たな点を打ちます。

過去の点はそのまま残るため、移動した軌跡が見えるようになっています。

コメントする

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

Exit mobile version