A simple ball bouncing and influenced by wind and gravity forces. Wind strength is determined by the location of the mouse: If the mouse is in the middle of the plane then there is no wind, at the left side the wind strength is -2.5, at the right side it is +2.5
Note that there is no negative force so the ball bounces back to the same height, leadin again to a 'perpetuum mobile'
Also, here we have just a single ball. That makes it possible to use separate arrays for position, velocity and acceleration. Even with 2 balls, you could go the same way. But multiple balls at once will require a different approach.
Bouncing Ball with gravity and wind
And this is what it looks like:
When using multiple balls, like 3 in this example, in p5.js, one would make a Ball class and instantiate it three times. As Basic256 is not OOP, we cannot do that.
Also, having three different objects also allows us to use different masses for each object. Different masses react differently to a wind force but, as Galileo showed, mass does not affect gravity so heavy objects fall as fast as light objects (well, in a vacuum they do.)
To get around the OOP limitation, for the three objects, we can use a single large array to store the data on all three objects.
dim obj[3,7]
# This creates an array of max of 3 objects, each with 7 properties:
# 0 = pos_X
# 1 = pos_Y
# 2 = vel_X
# 3 = vel_Y
# 4 = acc_X
# 5 = acc_Y
# 6 = mass
This makes the code a bit harder to read as you'd have to know that obj[2,4] is the acceleration along the x-axis of the third object.
Note that there is no loss of velocity on the bounce so the bounces go just as high as the previous ones.
Forces on multiple objects
And this is what it looks like (half way into the clip, I click a few times with the mouse to affect the objects with a wind force):
Up till now, we had a kinda idealistic environment where energy never dissipated, so bouncing objects kept bouncing forever. Now, let's try to create a dissipating force and like in the NoC book/Site, let's take friction
Again everything is clearly explained in the book so I'll skip the physics. Suffice to say that whenever two surfaces come into contact, they experience friction. This friction causes the kinetic energy of an object to be converted into another form (eg heat), giving the impression of loss, or dissipation.
Friction of course widely differs from substrate to substrate (eg ice versus sandpaper). The strength of the friction is called the 'Coëfficient of friction'. You can find loads of such Coëfficients on the web. We'll be using the arbitrarily value of 0.5
Then, there is also the Normal force, a force perpendicular (90°) to the surface the object is touching. This force is important when you have a slope in the surface (going downhill) but for our simulation, we will simply set it to 1. The real magnitude of friction is the formula 'Coëff of friction times the Normal'
Friction force occurs only when our object touches the ground. It's direction is inverse to the velocity, so we will create friction as the reverse of velocity, normalise the resulting vector and multiply it with the Friction Coëfficient. We then simply apply this force to the velocity, just as we did with wind and gravity
The wind easily moves the objects according to their mass while in the air, but once the objects come to a standstill, you can see the impact of friction as now friction comes into play at each timestep and not just at the bounce
Friction on three objects
And this is what it looks like:
(the objects do not bounce in syncronization becauses the bigger mass touches the floor sooner, thus starts its bounce sooner)
In the previous example, we had three objects that we declare in a predefined array of length 3. That gave us 21 rows of data. What if we want 10, 20, 100 objects?
Well, we just create our array iteratively based on the desired number of objects! For more visual diversity, I also added an additional parameter so that every object has its own coëfficient of friction (between 0.5 and 1.5)!
nr_obj=20
dim obj[nr_obj,8]
# create max 10 objects with 7 properties:
# 0 = pos_X
# 1 = pos_Y
# 2 = vel_X
# 3 = vel_Y
# 4 = acc_X
# 5 = acc_Y
# 6 = mass
# 7 = coëfficient of friction
# object parms
for i = 0 to nr_obj-1
obj[i,0] = width/(rand * 4)
obj[i,1] = (height)/(rand * 15)
obj[i,2] = 0
obj[i,3] = 0
obj[i,4] = 0
obj[i,5] = 0
obj[i,6] = rand * 100 +50
obj[i,7] = rand+0.5
next i
Friction on masses of objects
And this is what it looks like:
>
Friction also occurs when a body passes through a gas or a liquid (think of a parachute jump or a dive in water). These are forces somethimes called drag and like all the other forces, we can also implement them in our little universe
You can (and should) read all the detail of this under the Forces/Modeling a force/Air and liquid resistance section of the site/book.
While the formula for drag is a bit more complex than for friction, we will again simplify this for our environment so that the drag force is the speed squared times the drag coëfficient times the opposite direction (which is the velocitiy's unit vector but negative) or F = v² * c * velocity unit vector * -1. Simple....
Here, we use a single object so for readability sake, we use separate arrays for position, velocity and acceleration
I can't stress enough that the content of the site/book is a lot more in depth than what I describe here in 4 lines...
adding drag to an object
And this is what it looks like:
>
Again, when using multiple objects (3+) it is better to create each of the objects in a loop and store them in a single array. Having multiple objects lets us show the difference in friction between objects of a different mass.
You can clearly see that, unlike with gravity, friction force DOES depend on the mass of an abject, just like wind does and heavier objects are less impacted by friction so move faster through the medium.
Of course, this is still quite an idealized universe. In real life, things like the surface size also impacts the friction. (a thin ,long object falling pointy end first will be less impacted by friction that the same object with the same mass falling sideways...)
drag on multiple objects
And this is what it looks like:
>
Probably the most famous force (in physics!) we are aware of is gravity. If we think of Newton's apple, while the apple is 'pulled' to the ground by the earth's attraction, the earth also has a force pulling it towards the apple. The difference between the two however is so large that this is practically zero
Two object of more or less the same mass do exert a detectable gravitational force on each other. The formula of this gravitational force is G*m1*m2/r² where G is the Gravitational constant. (In our simplyfied universe, we will just set this to 1), m1 and m2 are the masses of the two objects and r² is the square of the distance. the direction of this force is the unit vector of the distance
In other words, the gravitational force between two bodies is proportional to the mass of those bodies and inversely proportional to the square of the distance between them.
Let's start with a immovable mass of value 3 (but drawn larger) in the center and a smaller mass of value 2 that is attracted to that central mass. Since we have only a single moving object, to make it easier on the eyes, we will give it its own arrays for pos, vel and acc
Gravitational attraction
And this is what it looks like:
>
Here we model a simple gravitational pull but this time there are several bodies of different masses and velocities rotating around the center.
Again, lacking OOP, we put all body data inside one big array and iterate the calculation of the gravitational pull for each body
The bodies do not interact with each other and, just like with the single orbiting body, move in highly elliptical orbits.
It's not quite a solar system, but it is a system...
Gravitational attraction with multiple bodies
And this is what it looks like:
>
Instead of having a single body orbiting a stationary one, we will now simulate the gravitational pull where two bodies rotate around each other.
With just 2 bodies, we can still afford to give each their own positional, velocity and acceleration vectors, as well as their mass and the force they feel toward each other
Two bodies with the same mass (here very small) and opposite (small) velocities will form a nice dance around a fixed point in space.
The moment just the masses differ or just the speeds vectors differ, thing still work as designed, but the system will move out of the visual plane quite rapidely
Try to mix things up a bit like making one a bit larger or a lot larger, change the speed vectors slightly etc
To get a nice circular orbit around eatch other, you can change their settings as follows:
# Settings of the orbiting object 1
pos1 = {750, 500}
vel1 = {0,1}
acc1 = {0,0}
mass1= 2
# Settings of the orbiting object 1
pos2 = {250, 500}
vel2 = {0,-1}
acc2 = {0,0}
mass2 = 2
Gravitational attraction - 2 bodies
And this is what it looks like with vel1 = {1,0.5} and vel2 = {-1,-0.5} for a more interesting visual experience:
>
First we had a single body orbiting a stationary one in a stable elliptical orbit, then the same but with multiple bodies orbiting in stable elliptical orbits
Then we had 2 bodies orbiting each other and exerting a gravitational pull on each. Again (after massaging the settings), we got a regular elliptical movement
So, the logical next step would be to have multiple bodies orbiting each other and every body exerting a gravitational pull on all others
Well, as viewers of "The 3-body problem" series have seen, things are not so simple because of .... chaos.
There is no long term predictability with 3 or more bodies exerting gravitational pull on each other
Gravitational attraction - 2 bodies
And this is what it looks like with bodies with a similar mass:
>
Some settings however seem a bit more 'stable' than others, at least in the beginning. To see this, you can try with the following settings:
# Settings of the orbiting object 1
pos1 = {200, 300}
vel1 = {20,0}
acc1 = {0,0}
mass1 = 3
# Settings of the orbiting object 2
pos2 = {600, 500}
vel2 = {-20,0}
acc2 = {0,0}
mass2 = 3
# Settings of the orbiting object 3
pos3 = {400, 400}
vel3 = {0,0}
acc3 = {0,0}
mass3 = 700
And this is what it looks like when we try to put a sun-like object in the middle. It seems stable in the beginning but goes haywire at the end
We can extend this program to have multiple objects (10,20,50,100). We can even merge them if they crash into each other! The idea here is not from 'The Nature of Code' but from a program by Manuel Santos, who was a prolific BASIC256 writer back in the day
You can still find his blog on Manuel's Blog
I massaged the code to fit in my template and added some comments to show what is going on
Gravitational attraction - multiple bodies
And this is what it looks like: