Gravity free space simulator

new topic     » topic index » view thread      » older message » newer message

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
})

new topic     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu