Saturday, September 23, 2023

Gravity Simulator #1,000,006

I've written a lot of gravity simulators. This one is the first time I've built one into a game engine. First, I created a Node2D and a Sprite2D with a texture so it's visible. I then attached the following code to the sprite node:


extends Sprite2D


var v:Vector2=Vector2(100,0)
var center:Vector2=Vector2(500,200)
var mu=3e6


# Called when the node enters the scene tree for the first time.
func _ready():
	var vec=Vector2(500,0)
	global_position=vec


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
	var r:Vector2=(global_position-center)
	var a:Vector2=-mu*r/r.length()**3
	v+=a*delta
	global_position+=v*delta
The _process() function is a very simple Euler integrator. The acceleration is the standard test-particle gravity equation of motion, where the center is considered to be infinitely heavier than the test particle, such that the gravity of the test particle doesn't affect the motion of the center. 

The next obvious things to do:
  • Use Runge-Kutta instead of Euler
  • Gravitate towards another sprite instead of an invisible point
  • Give both points finite mass 
  • Gravitate towards any number of masses, to make an N-body simulator.

It looks like I might be right about how to do physics in Godot, but it still doesn't feel quite right. Godot includes ragdoll physics and joints. In order to integrate custom physics, I would have to be able to generate custom forces and moments, instead of directly doing the numerical integration myself. I expect something more like:

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
    var r:Vector2=(global_position-center)
    var F:Vector2=-mu*global_mass*r/r.length()**3
    add_force(F)
    var M=... #calculate moment on the object
    add_moment(M)
This way if the engine does a higher-order integrator or has its own forces, this slides in nicely.

func _process(delta)

 I wish that GodotScript was just Python. It isn't, for a reason, but I don't know the reason yet. It could be:

  1. GodotScript came first, or before Python was widely known.
  2. Python is too hard to integrate. In this case, they considered *creating an entire new language interpreter* easier than incorporating Python
  3. True Python implies that the entire marketplace of Python libraries can be used, and that may have been too difficult to achieve.
  4. Python doesn't match the authors' internal model for how to do scripting
  5. Godot was started as a personal project, and a scripting engine was one of the "fun" things that they wanted to do with it.
In any case, I have reached the part of the tutorial where scripting is introduced. The template for a script for a node includes the following interesting code:

extends Node2D


# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass


The interesting one is _process(). I can imagine a mode of using the game engine where I just use it as a graphics engine -- every frame, this function is executed by the graphics engine, where it does all of my custom physics etc, changes the position properties of a bunch of nodes, then returns and lets the graphics part of the engine do its thing. 

Seriously, this function can implement a Runge-Kutta numerical integrator from the ground up -- it could use the node properties as part of its state, can keep global or static variables for the rest, and implement any law of motion I can think of. I'm not smarter than Newton or Euler and I intend to use their laws, but I don't *have* to.

If this was all Godot did for me, it might be just right. I'm still exploring, seeing what else it can do for me (I'm on part 25 of 47 of the Intro to Godot course). I strongly suspect that the engine does have a physics component though, since I have seen "gravity" as a property of some of the nodes.


Friday, September 22, 2023

Fallout from the Unity Disaster

 I have always been a low-level kind of programmer. I have a good intuitive sense of How Things Work, but I tend to build my own mental abstractions on top of these and I often have trouble learning other peoples' abstractions.

For instance, one of my unfinished projects is making math explainer videos. I knew about Manim from 3blue1brown, but he uses a completely different mental model of how animations work. It's tough to argue with success -- he has hundreds of videos and millions of subscribers, while I have zero and zero. Plus, I could never get the dancing equations to work as well in PictureBox as he does with TransformMatchingTex().

Similarly, I have always wanted to get into 3D simulator development -- not necessarily a game, more like a virtual environment where I can program virtual robots. One of my other long-term unfinished goals is to animate the launch of various historical spacecraft, much like Jim Blinn animated the flybys of Voyager. I want to be able to write a physically realistic rocket guidance program similar to what a Titan would have actually used, and use that to create a physically accurate, properly scaled animation of the launch. The legend goes that the second Voyager launch (Voyager 1, don't ask) only had about two seconds of fuel left in the upper stage when it finished the boost. How much did the first launch (Voyager 2) have? Is two seconds a lot? This can't really be answered without proper scale.

Anyway, one of the things I have been avoiding as someone else's abstraction, is game engine design and usage. I always thought myself capable of writing my own, even though I kept bouncing off of OpenGL and *its* abstractions. I have written simulator engines any number of times, basically just fancy numerical integrators. I have never learned anyone's game engine -- I have never explored anyone else's abstractions.

In the last couple of weeks, the Unity game engine has claimed authority to alter its relation with its developers. 



Lets just say that the development community hasn't taken it well.

One aspect of the fallout of this announcement is a mad scramble to other engines. It might be too late for programs which are years along and too intertwined with Unity, but many many people are looking at alternatives, and one of the ones that came up is Godot (https://godotengine.org/). This one is free and open source, so it can't help but stay free.

Even though it is free, I did spend about $26 on an online course for it (https://www.humblebundle.com/software/everything-you-need-to-know-about-godot-4-encore-software). The biggest thing I am looking for is how well their abstractions match up with my own. This will be interesting, as I'm not even sure what I expect a game engine to do for me. How does the physics part work? Can I write my own physics? Is there a numerical integrator underlying things? Are translational and rotational kinematics already implemented, and I just have to write my own dynamics? The engine might do too little, and require me to implement my own numerical integrator, or it might do to much, and implement things in such a way that I can't do a rocket.