Solar system simulation problem in Flutter

Viewed 38

I'm trying to translate this python code into Flutter. I think I did everything accurately but in my case planets aren't following the circular trajectory, they are just going straight along the y-axis. It's working perfectly on other platforms but on desktop planets aren't following the circular trajectory, they are just going straight along the y-axis.

import 'dart:math';

import 'package:flame/game.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const SolarSystemApp());
}

class SolarSystemApp extends StatelessWidget {
  const SolarSystemApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: GameWidget(game: SolarSystem()),
    );
  }
}

class SolarSystem with Game {
  static const double au = 149.6e6 * 1000;
  static const double G = 6.67428e-11;
  static const double scale = 250 / au;
  static const double timeStep = 3600 * 24;

  final planets = <Planet>[
    Planet(
        name: "Sun",
        radius: 30,
        mass: 1.98892 * pow(10, 30),
        color: Colors.yellow,
        position: const Offset(0, 0),
        velocity: const Offset(0, 0),
        isSun: true),
    Planet(
      name: "Mercury",
      radius: 8,
      mass: 3.30 * pow(10, 23),
      color: Colors.grey.shade800,
      position: const Offset(0.387 * au, 0),
      velocity: const Offset(0, -47.4 * 1000),
    ),
    Planet(
      name: "Venus",
      radius: 14,
      mass: 4.8685 * pow(10, 24),
      color: Colors.white,
      position: const Offset(0.723 * au, 0),
      velocity: const Offset(0, -35.02 * 1000),
    ),
    Planet(
      name: "Earth",
      radius: 16,
      mass: 5.9742 * pow(10, 24),
      color: Colors.blue,
      position: const Offset(-1 * au, 0),
      velocity: const Offset(0, 29.783 * 1000),
    ),
    Planet(
      name: "Mars",
      radius: 14,
      mass: 6.39 * pow(10, 23),
      color: Colors.brown,
      position: const Offset(-1.524 * au, 0),
      velocity: const Offset(0, 24.077 * 1000),
    ),
  ];

  @override
  void render(Canvas canvas) {
    var background = Paint()..color = Colors.white10;
    var rect = Rect.fromLTWH(0, 0, size.x, size.y);
    canvas.drawRect(rect, background);

    for (Planet planet in planets) {
      updatePosition(planet);

      var paint = Paint()..color = planet.color;
      var position = Offset((size.x / 2) + planet.position.dx * scale,
          ((size.y / 2) + planet.position.dy * scale));

      canvas.drawCircle(position, planet.radius, paint);
    }
  }

  Offset gravitationalForce(Planet self, Planet other) {
    var distance = (self.position - other.position).distance;

    if (other.isSun) {
      self.distanceToSun = distance;
    }

    var force = G * self.mass * other.mass / pow(distance, 2);

    var theta = atan2(other.position.dy - self.position.dy,
        other.position.dx - self.position.dx);
        
    return Offset(cos(theta), sin(theta)) * force;
  }

  updatePosition(Planet self) {
    var force = const Offset(0, 0);

    for (Planet planet in planets) {
      if (planet.name != self.name) {
        force += gravitationalForce(self, planet);
      }
    }

    self.velocity += (force / self.mass) * timeStep;
    self.position += self.velocity * timeStep;
  }

  @override
  void update(double dt) {}
}

class Planet {
  String name;
  double radius;
  double mass;
  Color color;
  Offset position;
  Offset velocity;
  bool isSun;
  double distanceToSun = 0.0;

  Planet(
      {required this.name,
      required this.radius,
      required this.mass,
      required this.color,
      required this.position,
      required this.velocity,
      this.isSun = false});
}


1 Answers

If anyone else stumbles across this; the problem was that a pow operation overflowed on desktop and android/iOS, but the code worked in the browser.

The solution was to use BigInt's pow implementation:

var myBigNumber = 4.8685 * BigInt.from(10).pow(30).toDouble();
Related