1. Gravity free space simulator
OK all you game programmers, here is some real physics for you. Please feel
free to chop and change, some credit would be nice.
You'll want to put your own values in. At the moment it has the earth and the
sun. As you know, the earth takes a year to go round the sun so it is not very
exciting to watch. You will probably want to make things much closer and then
change the SCALE constant. All the others are unchangeable (unless you're
feeling like rewriting the laws of physics).
The bit at the end where the objects are defined is complete gibberish. I'll
explain.
An object has the following properties :
Mass
Position (x,y)
Speed (x,y)
Bearing (This is the way in which you are pointing, which can be different
from the way you are travelling)
Engine type and thrust
They are defined in a sequence as follows :
eg
{10000, {93e9,1e6}, {0,1}, {1/2*2*PI,{30000,1}}}, --ship
{mass, {x_pos,y_pos}, {x_speed,y_speed}, {bearing, {thrust,
thrust_type}}}
where bearing is in radians. Thrust type is rocket or nuclear. Only 1 does
anything.
-----Code starts----
include graphics.e
constant grav_const=6.67e-11,PI=3.1416, --ensures no spurious type check
failures
PLANET_DENSITY=5464.15,
X=1,Y=2,MASS=1,POS=2,SPEED=3,BEARING=4,
SCALE=1000000000 --metres per pixel
constant LEFT=331, RIGHT=333, UP=328, DOWN=336
type angle(atom x)
return x>=-PI and x<=PI
end type
type color(integer x)
return x >= 0 and x <= 255
end type
type coordinate(sequence c)
return atom(c[1]) and atom(c[2])
end type
type thrust(sequence t) --{max_power,type} type is 0,1,2 none,rocket,nuclear
return atom(t[1]) and t[1]>=0 and integer(t[2])
end type
type thing(sequence t)
integer temp
temp=sequence(t[3])
if temp then
temp=atom(t[BEARING][1]) and angle(t[BEARING][1])
and thrust(t[BEARING][2])
end if
return atom(t[MASS]) and t[MASS]>0 and coordinate(t[POS])
and coordinate(t[SPEED])
and temp
--{mass,{x,y},{xspeed,yspeed},{bearing,{max_thrust,type}}}
end type
function force(atom mass1,atom mass2,atom distance)
return mass1*mass2/power(distance,2)*grav_const
end function
function tidy_angle(atom a)
if a>PI then
a=tidy_angle(a-2*PI)
elsif a<-PI then
a=tidy_angle(a+2*PI)
end if
return a
end function
procedure draw(color colour, coordinate xy, atom mass)
atom radius
radius=power(mass/PLANET_DENSITY/(4/3)/PI,1/3)/SCALE
if radius<.5 then
pixel(colour,xy)
else
if radius>10 then radius=10 end if
ellipse(colour,1, xy-radius, xy+radius)
end if
end procedure
atom start start=time()
procedure simulate(sequence things)
sequence but_things, --optimised version of things for simpler processing
speed,pos,bearing
thing bthing
atom accel,xaccel,yaccel,xdist,ydist,mass,
dist,tim,othen
integer leng,temp,times
othen=time()
leng=length(things)
temp=0
while temp != 27 do
while temp != 999 do
temp=get_key()+1000
end while
times=floor(temp/1000)
temp=temp-times*1000
if find(temp,{32,LEFT,RIGHT,UP,DOWN}) then
if temp=32 then
start=start-(time()-othen)*100*times
othen=othen-(time()-othen)*100*times
elsif temp=LEFT then
things[3][BEARING][1]=tidy_angle(things[3][BEARING][1]-PI/3*ti
mes)
elsif temp=RIGHT then
things[3][BEARING][1]=tidy_angle(things[3][BEARING][1]+PI/3*ti
mes)
end if
end if
tim=othen-time()
othen=time()
position(1,1)
printf(1,"%10d",sqrt(power(things[1][SPEED][X],2)+power(things[1][SPEE
D][Y],2))/SCALE) printf(1,"%10d %10d",things[1][POS]/SCALE) puts(1,"\n")
printf(1,"%10d",sqrt(power(things[2][SPEED][X],2)+power(things[2][SPEE
D][Y],2))/SCALE) printf(1,"%10d %10d",things[2][POS]/SCALE) puts(1,"\n")
printf(1,"%10d",sqrt(power(things[3][SPEED][X],2)+power(things[3][SPEE
D][Y],2))/SCALE) printf(1,"%10d %10d",things[3][POS]/SCALE) --puts(1,"\n")
position(1,70) printf(1,"Time %4.1d",time()-start)
but_things={}
for a=1 to leng do
but_things=append(but_things,things[1..a-1]&things[a+1..leng])
end for
for a=1 to leng do
speed=things[a][SPEED]
pos=things[a][POS]
mass=things[a][MASS]
bearing=things[a][BEARING]
accel=bearing[2][1]/mass
xaccel=accel*sin(bearing[1])
yaccel=accel*cos(bearing[1])
for b=1 to leng-1 do
bthing=but_things[a][b]
xdist=bthing[POS][X]-pos[X]
ydist=bthing[POS][Y]-pos[Y]
dist=sqrt(power(xdist,2)+power(ydist,2))
accel=force(mass,bthing[MASS],dist)*tim/mass
xaccel=xaccel+accel*xdist/dist
yaccel=yaccel+accel*ydist/dist
end for
things[a][SPEED][X] = speed[X] + xaccel
things[a][SPEED][Y] = speed[Y] + yaccel
things[a][POS][X] = pos[X] + things[a][SPEED][X]*tim
things[a][POS][Y] = pos[Y] + things[a][SPEED][Y]*tim
end for
for a=1 to leng do
draw(a,(things[a][POS]/SCALE+{320,240}),things[a][MASS])
end for
end while
end procedure
integer temp
temp=graphics_mode(18)
simulate({
{6e30, {0,0}, {0,0}, {0,{0,0}}}, --sun
{6e24, {93e9,0}, {0,2.07442e6}, {0,{0,0}}}, --inner planet
{10000, {93e9,1e6}, {0,1}, {1/2*2*PI,{30000,1}}}, --ship
{6e24, {3e11,0}, {0,1.15499e6}, {0,{0,0}}} --outer planet
})