set display mode 1024,768,32
hide mouse
sync
ink rgb(100,100,255),0
text 450,350,"-Leet- by Ric."
ink rgb(255,0,0),0
text 350,370,"Aim: Destroy ships and improve your rating"
text 450,410,"Press any key"
sync
wait key
text 450,450,"Loading ....."
sync
sw=screen width()
sh=screen height()
sync on
sync rate 60
gosub make_sun_texture
gosub display
 
#constant static_variable=global
 
 
type SHIP_CLASS
 
   objectnumber as integer
   Human as integer `0 for computer, >0 for human player
   Name as String
   Image as Integer
   velocity as float
   acceleration as float
   maxvelocity as float
   camdistance as float
   shield as integer
   maxshield as integer
   alive as integer
   aimode as string
   newbearingx as float
   newbearingy as float
   newbearingz as float
   changingcourse as integer
   turnspeed as integer
   fullcharge as integer `weapon max charge
   firepower as integer
   delaytime as integer  `interval between laser pulses
   rechargerate as integer
   maxduration as integer `duration of laser pulse
   fireduration as integer
   `flags
   charge as integer
   delay as integer
   fire as integer
   range as integer
   blobnumber as integer `objectnumber of cube on radar representing each ship 'n'
   sticknumber as integer `as above, but for the stick
   distancetoplayer as float
 
endtype
 
 
Dim ship(0) as ship_class
 
 
GLOBAL number_of_ships
number_of_ships=10
GLOBAL cam_mode=2 `set camera to chase-cam mode
GLOBAL keypress
GLOBAL trackinginfo=1000
GLOBAL theta
global weapondummy
global aidummy
global target
global glow
global arrow
global radardummy
global radardummy2
global distancevector
global xvector
global yvector
global zvector
global resultantvector
global resultantvectornormal
global projectedvector
global projectedvectornormal
global dummy
global projectiondist#
global rating
global explodeon
global particle
global numberofparticles
 
distancevector=1
null=make vector3(distancevector)
xvector=2
null=make vector3(xvector)
yvector=3
null=make vector3(yvector)
zvector=4
null=make vector3(zvector)
resultantvector=5
null=make vector3(resultantvector)
resultantvectornormal=6
null=make vector3(resultantvectornormal)
projectedvector=7
null=make vector3(projectedvector)
projectedvectornormal=8
null=make vector3(projectedvectornormal)
 
 
 
 
 
 
 
`forwardvector=2
`rightvector=3
`upvector=4
`null=make vector3(forwardvector)
`null=make vector3(rightvector)
`null=make vector3(upvector)
`targetvector=5
`null=make vector3(targetvector)
 
 
gosub make_sun
make_ships(number_of_ships)
GLOBAL camera_on_ship=1 `initial ship camera will follow
weapondummy=free_object()
make object cube weapondummy,1
hide object weapondummy
aidummy=free_object()
make object cube aidummy,1
hide object aidummy
gosub make_crosshairs
gosub make_radar
dummy=free_object()
make object cube dummy,1
hide object dummy
 
gosub make_explosion_particles
 
 
 
TEMP_FUNCTION1() `called once
 
 
ink rgb(0,255,0),0
do
 
color backdrop 0
show object glow
 
TEMP_FUNCTION2() `called each loop
control_ships(number_of_ships)
move_ships(number_of_ships)
flashing_lights(number_of_ships)
control_camera(cam_mode,camera_on_ship)
starfield(ship(camera_on_ship).velocity,ship(camera_on_ship).objectnumber)
player_weapons()
gosub show_crosshairs
turn object right sun,0.1
point object glow,camera position x(),camera position y(),camera position z()
cockpit()
if explodeon=1 then gosub explode
 
if scancode()=0 then keypress=0
 
 
sync
loop
 
make_explosion_particles:
numberofparticles=20
particle=free_object()
dim particlespeed(particle+20)
for n=particle to particle+numberofparticles-1
  make object triangle n,-1,0,0,0,0,0,0,1,0
  rotate object n,rnd(360),rnd(360),rnd(360)
  fix object pivot n
  rotate object n,rnd(360),rnd(360),rnd(360)
  particlespeed(n)=rnd(40)/10.0
  color object n,rgb(0,rnd(255),rnd(255))
  hide object n
next n
return
 
explode:
 
for n=particle to particle+numberofparticles-1
  roll object right n,3
  move object n,particlespeed(n)
next n
 
inc count
if count>100
  explodeon=0
  count=0
  for n=particle to particle+numberofparticles-1
    hide object n
  next n
endif
 
return
 
make_radar:
 
create bitmap 1,101,101
for x=0 to 101 step 10
line x,0,x,101
next x
for y=0 to 101 step 10
line 0,y,101,y
next y
gridimage=free_image()
get image gridimage,0,0,101,101
delete bitmap 1
 
grid=free_object()
make object plain grid,1,1
position object grid,0,-1.35,3.0
xrotate object grid,90
lock object on grid
texture object grid,gridimage
set object transparency grid,5
disable object zdepth grid
set object light grid,0
 
arrow=free_object()
make object triangle arrow,-0.05,0,0,0.05,0,0,0,0,0.05
position object arrow,0,-1.34,2.95
lock object on arrow
`set object light arrow,0
color object arrow,rgb(255,0,0)
`disable object zdepth arrow
ghost object on arrow
 
for n=2 to number_of_ships
  ship(n).blobnumber=free_object()
  make object cube ship(n).blobnumber,0.01
  hide object ship(n).blobnumber
  lock object on ship(n).blobnumber
  disable object zdepth ship(n).blobnumber
  color object ship(n).blobnumber,rgb(0,255,0)
  ship(n).sticknumber=free_object()
  make object box ship(n).sticknumber,0.005,1,0.005
  hide object ship(n).sticknumber
  lock object on ship(n).sticknumber
  disable object zdepth ship(n).sticknumber
  color object ship(n).sticknumber,rgb(255,0,255)
next n
 
radardummy=free_object()
make object cube radardummy,1
hide object radardummy
 
 
 
 
return
 
display:
autocam off
position camera 0,0,-15
color backdrop 0
set ambient light 50
set light range 1,10000
return
 
make_crosshairs:
 
crosshairs=free_sprite()
crosshairimage=free_image()
create bitmap 1,100,100
ink rgb(100,100,255),0
line 20,50,45,50
line 55,50,80,50
line 50,20,50,45
line 50,55,50,80
get image crosshairimage,0,0,100,100,1
delete bitmap 1
 
sprite crosshairs,0,0,crosshairimage
 
return
 
show_crosshairs:
 
if camera_on_ship=1
if cam_mode=1
  sprite crosshairs,screen width()/2.0-sprite width(crosshairs)/2.0,screen height()/2.0-sprite height(crosshairs)/2.0,crosshairimage
endif
if cam_mode=2
  position object weapondummy,object position x(ship(1).objectnumber),object position y(ship(1).objectnumber),object position z(ship(1).objectnumber)
  set object to object orientation weapondummy,ship(1).objectnumber
  move object weapondummy,100
  x=object screen x(weapondummy)
  y=object screen y(weapondummy)
  sprite crosshairs,x-sprite width(crosshairs)/2.0,y-sprite height(crosshairs)/2.0,crosshairimage
endif
endif
 
 
return
 
function cockpit()
 
`rating
if rating=0 then rating$="Harmless"
if rating=1 then rating$="Rookie"
if rating=2 then rating$="Mediocre"
if rating=3 then rating$="Competent"
if rating=4 then rating$="Noteworthy"
if rating=5 then rating$="Adept"
if rating=6 then rating$="Respected"
if rating=7 then rating$="Dangerous"
if rating=8 then rating$="Deadly"
if rating=9 then rating$="Leet ;)"
 
 
text 0,740,"Your rating: "+rating$
 
text 700,740,"Velocity:"
box 800,740,800+ship(1).velocity*70,760
 
`player shield
text 300,740,"Shield:"
box 387,740,387+(ship(1).shield)/2.0,760
 
`plot ships onto radar
 
for n=2 to number_of_ships
  ship(n).distancetoplayer=distance(ship(1).objectnumber,ship(n).objectnumber)
  if ship(n).distancetoplayer<=800.0 and ship(n).alive=1
    show object ship(n).blobnumber
    show object ship(n).sticknumber
    `position blob at centre of grid
    position object ship(n).blobnumber,object position x(arrow),object position y(arrow),object position z(arrow)
 
 
 
 
`------------------------------- calculate radar coordintaes ---------------
rootobject=ship(1).objectnumber
radartarget=ship(n).objectnumber
 
`root position
x1#=object position x(rootobject)
y1#=object position y(rootobject)
z1#=object position z(rootobject)
 
`create dummy object
position object dummy,x1#,y1#,z1#
set object to object orientation dummy,rootobject
 
`make local z vector (forward on local axis)
move object dummy,1
x2# = object position x(dummy)
y2# = object position y(dummy)
z2# = object position z(dummy)
 
set vector3 zvector, x2#-x1#, y2#-y1#, z2#-z1#
normalize vector3 zvector,zvector
 
`make local x vector (sideways on local axis)
 
move object dummy, -1
turn object right dummy,90
move object dummy,1
x3# = object position x(dummy)
y3# = object position y(dummy)
z3# = object position z(dummy)
 
set vector3 xvector, x3#-x1#, y3#-y1#, z3#-z1#
normalize vector3 xvector,xvector
`make local y vector (upwards on local axis)
`cross product vector3 yvector,xvector,zvector
move object dummy, -1
turn object left dummy,90
pitch object up dummy,90
move object dummy,1
x3b# = object position x(dummy)
y3b# = object position y(dummy)
z3b# = object position z(dummy)
set vector3 yvector, x3b#-x1#, y3b#-y1#, z3b#-z1#
normalize vector3 yvector,yvector
 
`make vector joining two objects - from rootobject to radartarget
x4# = object position x(radartarget)
y4# = object position y(radartarget)
z4# = object position z(radartarget)
 
set vector3 resultantvector, x4#-x1#, y4#-y1#, z4#-z1#
 
`make vector at 90 degrees to the resultant vector, in the plane containing both the resultant vector and the y vector
position object dummy,x1#,y1#,z1#
set object to object orientation dummy,rootobject
point object dummy,x4#,y4#,z4#
pitch object down dummy,90 `not safe - may not be in correct plane
move object dummy,1
x5#=object position x(dummy)
y5#=object position y(dummy)
z5#=object position z(dummy)
 
set vector3 resultantvectornormal, x5#-x1#,y5#-y1#,z5#-z1#
 
 
`get angle between local y axis and radartarget
normalize vector3 resultantvector,resultantvector
normalize vector3 resultantvectornormal,resultantvectornormal
phi#=acos(dot product vector3(yvector,resultantvector))
test#=acos(dot product vector3(yvector,resultantvectornormal))
if test#<90.0 then phi#=360-phi#
 
`get angle between radartarget and plane of root object
theta#=90-phi#
 
`get distance between root object and radartarget
set vector3 resultantvector, x4#-x1#, y4#-y1#, z4#-z1#
radartargetdist#=length vector3(resultantvector)
 
`get smallest distance between radartarget on local object's plane - the projection distance
disttoplane#=radartargetdist#*sin(theta#)
 
`project dummy onto plane
position object dummy,x4#,y4#,z4#
set object to object orientation dummy,rootobject
pitch object down dummy,90
move object dummy,disttoplane#
 
`get projection coordinates
x6#=object position x(dummy)
y6#=object position y(dummy)
z6#=object position z(dummy)
 
`make vector joining root object to projected point
 
set vector3 projectedvector, x6#-x1#,y6#-y1#,z6#-z1#
normalize vector3 projectedvector,projectedvector
 
 
 
`get normal to projected vector in plane of root object
`cross product vector3 projectedvectornormal,projectedvector,yvector
`normalize vector3 projectedvectornormal,projectedvectornormal
 
`get angle between projected vector and z vector
localyangle#=acos(dot product vector3(projectedvector,zvector))
test#=acos(dot product vector3(projectedvector,xvector))
if test#<90.0 then localyangle#=360-localyangle#
 
 
`get projected vector's length
set vector3 projectedvector, x6#-x1#,y6#-y1#,z6#-z1#
projectionlength#=length vector3(projectedvector)
 
 
 
 
`--------------------------------------------------
 
 
    rotate object ship(n).blobnumber,0,-localyangle#,0
    move object ship(n).blobnumber,projectionlength#/1600.0
    pitch object up ship(n).blobnumber,90
    move object ship(n).blobnumber,disttoplane#/1600.0 `calculated globally in function get_projected_bearing
    rotate object ship(n).blobnumber,0,0,0
    height#=object position y(ship(n).blobnumber)-object position y(arrow)
    scale object ship(n).sticknumber,100,height#*100,100
    position object ship(n).sticknumber,object position x(ship(n).blobnumber),object position y(arrow)+height#/2.0,object position z(ship(n).blobnumber)
  else
    hide object ship(n).blobnumber
    hide object ship(n).sticknumber
  endif
 
 
 
next n
 
 
 
 
endfunction
 
function player_weapons()
 
if 0 = 1
static_variable charge
static_variable delay
static_variable fire
static_variable fireduration
 
endif
 
 
fullcharge=100
firepower=1
delaytime=20
rechargerate=1
maxduration=5
 
if spacekey()=1 and charge>0
  fire=1
  dec charge,firepower
endif
 
if fire=1 and delay=0
  inc fireduration
  if fireduration=maxduration then delay=delaytime:fireduration=0
  if cam_mode=1
    line 0,0,screen width()/2.0,screen height()/2.0
    line screen width(),0,screen width()/2.0,screen height()/2.0
    target=pick object(screen width()/2.0,screen height()/2.0,ship(2).objectnumber,ship(number_of_ships).objectnumber)
  endif
  if cam_mode=2
    position object weapondummy,object position x(ship(1).objectnumber),object position y(ship(1).objectnumber),object position z(ship(1).objectnumber)
    set object to object orientation weapondummy,ship(1).objectnumber
    move object left weapondummy,1.5
    x1=object screen x(weapondummy)
    y1=object screen y(weapondummy)
    move object right weapondummy,3
    x2=object screen x(weapondummy)
    y2=object screen y(weapondummy)
    move object left weapondummy,1.5
    move object weapondummy,100
    x3=object screen x(weapondummy)
    y3=object screen y(weapondummy)
    line x1,y1,x3,y3
    line x2,y2,x3,y3
    target=pick object(x3,y3,ship(2).objectnumber,ship(number_of_ships).objectnumber)
  endif
if target>0
    targetnumber=ship_link_list(target)
    dec ship(targetnumber).shield,firepower
    ship(targetnumber).aimode="attack"
    color object ship(targetnumber).blobnumber,rgb(255,0,0)
    if ship(targetnumber).shield<=0
      hide object ship(targetnumber).objectnumber
      ship(targetnumber).alive=0
      explodeon=1
      for n=particle to particle+numberofparticles-1
        position object n,object position x(ship(targetnumber).objectnumber),object position y(ship(targetnumber).objectnumber),object position z(ship(targetnumber).objectnumber)
        show object n
      next n
      inc rating
    endif
  endif
 
endif
 
if charge<fullcharge
  inc charge,rechargerate
  if charge>fullcharge then charge=fullcharge
endif
if delay>0 then dec delay
if spacekey()=0 then fire=0
 
endfunction
 
function ai_weapons(shipnumber)
 
n=shipnumber
 
 
if ship(n).charge>0
  ship(n).fire=1
  dec ship(n).charge,ship(n).firepower
endif
 
if ship(n).fire=1 and ship(n).delay=0
  distance#=distance(ship(n).objectnumber,ship(1).objectnumber)
  if distance#<=ship(n).range
    inc ship(n).fireduration
    if ship(n).fireduration>=ship(n).maxduration then ship(n).delay=ship(n).delaytime:ship(n).fireduration=0
    if cam_mode=1 and camera_on_ship=n
      line 0,0,object screen x(ship(1).objectnumber),object screen y(ship(1).objectnumber)
      line screen width(),0,object screen x(ship(1).objectnumber),object screen y(ship(1).objectnumber)
    endif
    if cam_mode=2
      position object weapondummy,object position x(ship(n).objectnumber),object position y(ship(n).objectnumber),object position z(ship(n).objectnumber)
      set object to object orientation weapondummy,ship(n).objectnumber
      move object left weapondummy,1.5
      x1=object screen x(weapondummy)
      y1=object screen y(weapondummy)
      move object right weapondummy,3
      x2=object screen x(weapondummy)
      y2=object screen y(weapondummy)
      x3=object screen x(ship(1).objectnumber)
      y3=object screen y(ship(1).objectnumber)
      line x1,y1,x3,y3
      line x2,y2,x3,y3
    endif
 
 
    dec ship(1).shield,ship(n).firepower
    color backdrop rgb(255,0,0):hide object glow
    if ship(1).shield<=0
      hide object ship(1).objectnumber
      ship(1).alive=0
    endif
  endif
endif
 
 
 
if ship(n).charge<ship(n).fullcharge
  inc ship(n).charge,ship(n).rechargerate
  if ship(n).charge>ship(n).fullcharge then ship(n).charge=ship(n).fullcharge
endif
if ship(n).delay>0 then dec ship(n).delay
 
 
endfunction
 
 
 
 
function flashing_lights(number_of_ships)
 
for n=1 to number_of_ships
 
ship=ship(n).objectnumber
brightness=int(127*sin(theta))+127
inc theta,1
color limb ship,5,rgb(255,brightness,brightness)
 
next n
 
endfunction
 
 
function make_ships(number)
 
 
   `create temporary texture for spaceships
   create bitmap 1,10,10
      blue=free_image()
      ink rgb(0,0,255),0
      box 0,0,10,10
      get image blue,0,0,10,10
      red=free_image()
      ink rgb(255,0,0),0
      box 0,0,10,10
      get image red,0,0,10,10
      green=free_image()
      ink rgb(0,255,0),0
      box 0,0,10,10
      get image green,0,0,10,10
   delete bitmap 1
   set current bitmap 0
 
   for n=1 to number_of_ships
      array insert at bottom ship(0)
      ship(n).objectnumber=free_object()
      dim ship_link_list(ship(n).objectnumber)
      ship_link_list(ship(n).objectnumber)=n
 
 
 
 
 
  `body
  make object box ship(n).objectnumber,2.0,1.1,5
 
  temp=free_object()
  `nose
  make object box temp,1.4,1,1.4
  yrotate object temp,45
  make mesh from object 1,temp
  delete object temp
  add limb ship(n).objectnumber,1,1
  offset limb ship(n).objectnumber,1,0,0,2.5
  delete mesh 1
  `left wing
  make object box temp,2,0.5,3
  yrotate object temp,45
  make mesh from object 1,temp
  delete object temp
  add limb ship(n).objectnumber,2,1
  offset limb ship(n).objectnumber,2,-1,0,-1.5
  delete mesh 1
  `right wing
  make object box temp,2,0.5,3
  yrotate object temp,-45
  make mesh from object 1,temp
  delete object temp
  add limb ship(n).objectnumber,3,1
  offset limb ship(n).objectnumber,3,1,0,-1.5
  delete mesh 1
  `fin
  make object box temp,0.2,1,4
  xrotate object temp,12
  make mesh from object 1,temp
  delete object temp
  add limb ship(n).objectnumber,4,1
  offset limb ship(n).objectnumber,4,0,0.5,0
  delete mesh 1
  `light
  make object box temp,0.5,0.3,0.5
  yrotate object temp,45
  make mesh from object 1,temp
  delete object temp
  add limb ship(n).objectnumber,5,1
  offset limb ship(n).objectnumber,5,0,0,-2.5
  delete mesh 1
 
  if n>1 then rotate object ship(n).objectnumber,rnd(360),rnd(360),rnd(360)
 
 
  ship(n).acceleration=0.02
  ship(n).maxvelocity=3
  ship(n).camdistance=20
  ship(n).velocity=0.3
  ship(n).maxshield=100
  ship(n).shield=ship(n).maxshield
  ship(n).alive=1
  ship(n).aimode="passive"
  ship(n).turnspeed=60 `smoothness value for curveangle - larger number=slower turnspeed
 
  if n>1
    ship(n).fullcharge=100
    ship(n).firepower=1
    ship(n).delaytime=20
    ship(n).rechargerate=1
    ship(n).maxduration=5
    ship(n).range=300
  endif
 
  if n=1
    ship(n).human=1
    ship(n).maxshield=500
    ship(n).shield=ship(n).maxshield
    ship(n).name="Your ship"
    texture object ship(n).objectnumber,blue
  else
    ship(n).name="Trade ship "+str$(n)
    texture object ship(n).objectnumber,green
  endif
 
  position object ship(n).objectnumber,rnd(50)-25,rnd(50)-25,rnd(50)-25
 
   next n
endfunction
 
 
 
 
 
function free_object()
 
repeat
inc n
until object exist(n)=0
 
endfunction n
 
 
function TEMP_FUNCTION1()
 
 
   text_sprite(free_sprite(),255,255,0,0,0,"arrow keys - control ship")
   text_sprite(free_sprite(),255,255,0,0,20,"+ - increase velocity")
   text_sprite(free_sprite(),255,255,0,0,40,"- - decrease velocity")
   text_sprite(free_sprite(),255,0,0,0,80,"1 - cockpit mode")
   text_sprite(free_sprite(),255,0,0,0,100,"2 - chasecam mode")
   text_sprite(free_sprite(),255,0,0,0,120,"c - change camera")
   text_sprite(free_sprite(),255,0,0,0,140,"a - zoom in")
   text_sprite(free_sprite(),255,0,0,0,160,"z - zoom out")
 
 
   text_sprite(trackinginfo,255,255,0,700,0,"Camera tracking: "+ship(1).name)
 
 
 
endfunction
 
function TEMP_FUNCTION2()
 
if 0=1 then global currenttarget
 
n=ship_link_list(target)
if n>0
  currenttarget=n
endif
if currenttarget>0
  text 700,20,"Ship hit: "+ship(currenttarget).name
  text 700,40,"Shield: "
  box 800,40,800+ship(currenttarget).shield,60
endif
 
 
 
endfunction
 
 
function control_ships(number_of_ships)
   for n=1 to number_of_ships
     if ship(n).alive=1
 
     if ship(n).human=1
       `keyboard control system
        if leftkey()=1 then roll object left ship(1).objectnumber,1
        if rightkey()=1 then roll object right ship(1).objectnumber,1
        if upkey()=1 then  pitch object down ship(1).objectnumber,0.5
        if downkey()=1 then  pitch object up ship(1).objectnumber,0.5
        if keystate(12)=1 and ship(n).velocity > 0 then dec ship(n).velocity,ship(n).acceleration
        if keystate(13)=1 and ship(n).velocity < ship(n).maxvelocity then inc ship(n).velocity,ship(n).acceleration
     else
       `apply AI to computer controlled ships
       if ship(n).aimode="passive"
         if ship(n).changingcourse=0
           if rnd(500)=0
             ship(n).newbearingx=rnd(360)
             ship(n).newbearingy=rnd(360)
             ship(n).newbearingz=rnd(360)
             ship(n).changingcourse=1
           endif
         endif
         if ship(n).changingcourse=1
           rotate object ship(n).objectnumber,curveangle(ship(n).newbearingx,object angle x(ship(n).objectnumber),ship(n).turnspeed),curveangle(ship(n).newbearingy,object angle y(ship(n).objectnumber),ship(n).turnspeed),curveangle(ship(n).newbearingz,object angle z(ship(n).objectnumber),ship(n).turnspeed)
           diffx#=anglebetweenbearings(object angle x (ship(n).objectnumber),ship(n).newbearingx)
           diffy#=anglebetweenbearings(object angle y (ship(n).objectnumber),ship(n).newbearingy)
           diffz#=anglebetweenbearings(object angle z (ship(n).objectnumber),ship(n).newbearingz)
           `if new bearing is reached (within a few degrees), change flag to force a new bearing to be calculated next loop
           if diffx#<5 and diffy#<5 and diffz#<5 then ship(n).changingcourse=0
         endif
       endif
       if ship(n).aimode="attack"
         if ship(n).changingcourse=0
           `find new bearing by pointing dummy towards player and recording results
           position object aidummy,object position x(ship(n).objectnumber),object position y(ship(n).objectnumber),object position z(ship(n).objectnumber)
           point object aidummy,object position x(ship(1).objectnumber),object position y(ship(1).objectnumber),object position z(ship(1).objectnumber)
           ship(n).newbearingx=object angle x(aidummy)
           ship(n).newbearingy=object angle y(aidummy)
           ship(n).newbearingz=object angle z(aidummy)
           ship(n).changingcourse=1
         endif
         if ship(n).changingcourse=1
           `decrease speed if close to player ship, to prevent orbiting
           dist#=ship(n).distancetoplayer
           if dist#<60 then ship(n).velocity=dist#/200.0 else ship(n).velocity=0.3
           `rotate enemy ship towards new bearing
           rotate object ship(n).objectnumber,curveangle(ship(n).newbearingx,object angle x(ship(n).objectnumber),ship(n).turnspeed),curveangle(ship(n).newbearingy,object angle y(ship(n).objectnumber),ship(n).turnspeed),curveangle(ship(n).newbearingz,object angle z(ship(n).objectnumber),ship(n).turnspeed)
           `check to see if bearing has been reached
           diffx#=anglebetweenbearings(object angle x (ship(n).objectnumber),ship(n).newbearingx)
           diffy#=anglebetweenbearings(object angle y (ship(n).objectnumber),ship(n).newbearingy)
           diffz#=anglebetweenbearings(object angle z (ship(n).objectnumber),ship(n).newbearingz)
           `if new bearing is reached (within a few degrees), change flag to force a new bearing to be calculated next loop
           if diffx#<5 and diffy#<5 and diffz#<5
             ai_weapons(n)
             ship(n).changingcourse=0
           endif
         endif
       endif
     endif
 
     endif
   next n
endfunction
 
 
function move_ships(number_of_ships)
   for n=1 to number_of_ships
      move object ship(n).objectnumber,ship(n).velocity
   next n
endfunction
 
 
 
function control_camera(mode,shipnumber)
 
 
if mode=1 `cockpit view
   set camera to object orientation ship(shipnumber).objectnumber
   position camera object position x(ship(shipnumber).objectnumber),object position y(ship(shipnumber).objectnumber),object position z(ship(shipnumber).objectnumber)
   move camera 2
endif
 
if mode=2 `chase cam view
  chase_cam(ship(shipnumber).objectnumber,ship(shipnumber).camdistance)
  if inkey$()="a" and ship(shipnumber).camdistance>5 then dec ship(shipnumber).camdistance,.2
  if inkey$()="z" and ship(shipnumber).camdistance<20 then inc ship(shipnumber).camdistance,.2
endif
 
if keystate(2)=1 then cam_mode=1
if keystate(3)=1 then cam_mode=2
if inkey$()="c" and keypress=0
   keypress=1
   inc camera_on_ship
   if camera_on_ship>number_of_ships then camera_on_ship=1
   text_sprite(trackinginfo,255,255,0,700,0,"Tracking: "+ship(camera_on_ship).name)
endif
 
 
endfunction
 
function free_image()
   repeat
     inc n
   until image exist(n)=0
endfunction n
 
 
function free_sprite()
   repeat
     inc n
   until sprite exist(n)=0 and image exist(n)=0
endfunction n
 
function text_sprite(entity,r,g,b,x,y,text$)
   if text$="" then text$=" "
   create bitmap 1,screen width(),screen height()
      set current bitmap 1
      ink rgb(r,g,b),0
      set text size 20
      `set text font "Arial"
      text 0,0,text$
      if image exist(entity) then delete image entity
      if sprite exist(entity) then delete sprite entity
      get image entity,0,0,text width(text$),text height(text$),1
      sprite entity,x,y,entity
      set sprite priority entity,1
      set sprite alpha entity,255
   delete bitmap 1
   set current bitmap 0
endfunction
 
 
function chase_cam(object,distance#)
 
 
   oldcamx#=camera position x()
   oldcamy#=camera position y()
   oldcamz#=camera position z()
   oldcamangx#=camera angle x()
   oldcamangy#=camera angle y()
   oldcamangz#=camera angle z()
 
   position camera object position x(object),object position y(object),object position z(object)
   set camera to object orientation object
   move camera -distance#
   pitch camera up 90
   move camera distance#/3.0
   pitch camera down 90
 
   newcamx#=camera position x()
   newcamy#=camera position y()
   newcamz#=camera position z()
   newcamangx#=camera angle x()
   newcamangy#=camera angle y()
   newcamangz#=camera angle z()
 
   xrotate camera curveangle(newcamangx#,oldcamangx#,40)
   yrotate camera curveangle(newcamangy#,oldcamangy#,40)
   zrotate camera curveangle(newcamangz#,oldcamangz#,40)
   camx#=curvevalue(newcamx#,oldcamx#,20)
   camy#=curvevalue(newcamy#,oldcamy#,20)
   camz#=curvevalue(newcamz#,oldcamz#,20)
   position camera camx#,camy#,camz#
 
   camangx#=camera angle x()
   camangy#=camera angle y()
   camangz#=camera angle z()
   point camera object position x(object),object position y(object),object position z(object)
   position camera object position x(object),object position y(object),object position z(object)
   move camera -distance#
   rotate camera camangx#,camangy#,camangz#
 
 
endfunction
 
 
function starfield(speed#,camera_on_object)
 
rem 3D Starfield Demo - Written by Jason Clogg
rem Feel free to use any of this code
 
 
rem base sprite number
base=600
rem How widely to spread the stars
spread=800
rem How many stars to display
stars=200
rem The initial distance to start the stars displaying
dist=500
 
`Calculate a point in front of the camera to start drawing the starfield
 
cx#=camera position x()
cy#=camera position y()
cz#=camera position z()
 
pick screen screen width()/2,screen height()/2,dist
sx#=get pick vector x()
sy#=get pick vector y()
sz#=get pick vector z()
 
if object exist(600)=0
   make object box 600,.5,.5,.5
   for i=601 to 600+stars
      clone object i,600
rem stars should not be affected by light or included in collisions
      set object light i,0
      set object collision off i
      position object i,rnd(spread*2)-spread,rnd(spread*2)-spread,camera position z()+rnd(dist)
   next i
endif
 
for i=600 to 600+stars
`reposition stars if they are out of camera shot
   if object in screen(i)=0
   position object i,cx#+sx#+(rnd(spread)-(spread/2)),cy#+sy#+(rnd(spread)-(spread/2)),cz#+sz#+(rnd(spread*2)-(spread/2))
   endif
`Calculate distance of star from camera and scale star accordingly
   dist#=distance2(cx#,cy#,cz#,i)
   scale object i,.1*(dist#*2),.1*(dist#*2),2000*speed#
   set object to object orientation i,camera_on_object
rem The multiple of 1.2 will need to be changed depending on the frame rate.
rem This value works best with a sync rate of 60
   move object i,speed#*-1.2
   next i
 
endfunction
 
function distance(obj1,obj2)
 
x1#=object position x(obj1)
y1#=object position y(obj1)
z1#=object position z(obj1)
 
x2#=object position x(obj2)
y2#=object position y(obj2)
z2#=object position z(obj2)
 
`dist#=sqrt((x1#-x2#)*(x1#-x2#)+(y1#-y2#)*(y1#-y2#)+(z1#-z2#)*(z1#-z2#))
 
set vector3 distancevector,x2#-x1#,y2#-y1#,z2#-z1#
dist# = length vector3(distancevector)
 
 
 
endfunction dist#
 
function distance2(x1#,y1#,z1#,obj)
 
 
x2#=object position x(obj)
y2#=object position y(obj)
z2#=object position z(obj)
 
`dist#=sqrt((x1#-x2#)*(x1#-x2#)+(y1#-y2#)*(y1#-y2#)+(z1#-z2#)*(z1#-z2#))
 
set vector3 distancevector,x2#-x1#,y2#-y1#,z2#-z1#
dist# = length vector3(distancevector)
 
 
 
endfunction dist#
 
 
 
make_sun_texture:
 
autocam off
set ambient light 0
color backdrop 0
hide light 0
make light 1
position light 1,0,0,0
set light range 1,10
temp=free_object()
make object sphere temp,4,50,50
position object temp,0,0,5
 
x1=sw/2-300
x2=sw/2+300
y1=sh/2-300
y2=sh/2+300
 
sync
 
glowtexture=free_image()
get image glowtexture,x1,y1,x2,y2,1
delete object temp
 
 
create bitmap 1,512,512
box 0,0,256,256,rgb(255,0,0),rgb(255,127,0),rgb(255,255,0),rgb(255,127,255)
box 256,0,512,256,rgb(255,255,0),rgb(255,127,255),rgb(255,0,0),rgb(255,127,0)
box 0,256,256,512,rgb(255,127,0),rgb(255,0,0),rgb(255,127,255),rgb(255,255,0)
box 256,256,512,512,rgb(255,127,255),rgb(255,255,0),rgb(255,127,0),rgb(255,0,0)
for n=1 to 10000
ink rgb(255,rnd(255),rnd(255)),0
dot rnd(512),rnd(512)
next n
blur bitmap 1,5
suntexture=free_image()
get image suntexture,0,0,512,512,1
delete bitmap 1
 
return
 
 
make_sun:
 
sun=free_object()
make object sphere sun,400,20,20
position object sun,0,0,800
texture object sun,suntexture
set object diffuse sun,rgb(255,255,255)
ghost object on sun
set object transparency sun,5
set object light sun,0
glow=free_object()
make object plain glow,600,600
position object glow,0,0,800
texture object glow,glowtexture
set object light glow,0
set object transparency glow,4
 
 
return
 
function anglebetweenbearings(bearing1#,bearing2#)
`absolute value for testing if angles are in range of each other
 
a#=abs(wrapvalue(bearing1#+180-bearing2#)-180)
 
endfunction a#
 
function anglebetweenbearings2(bearing2#,bearing1#)
`positive or negative value
a#=180-wrapvalue(bearing1#-bearing2#+180)
 
endfunction a#
 
function get_projected_bearing(target,rootobject)
 
`root position
x1#=object position x(rootobject)
y1#=object position y(rootobject)
z1#=object position z(rootobject)
 
`create dummy object
position object dummy,x1#,y1#,z1#
set object to object orientation dummy,rootobject
 
`make local z vector (forward on local axis)
move object dummy,1
x2# = object position x(dummy)
y2# = object position y(dummy)
z2# = object position z(dummy)
 
set vector3 zvector, x2#-x1#, y2#-y1#, z2#-z1#
 
`make local x vector (sideways on local axis)
 
move object dummy, -1
turn object right dummy,90
move object dummy,1
x3# = object position x(dummy)
y3# = object position y(dummy)
z3# = object position z(dummy)
 
set vector3 xvector, x3#-x1#, y3#-y1#, z3#-z1#
 
`make local y vector (upwards on local axis)
cross product vector3 yvector,xvector,zvector
 
 
`make vector joining two objects - from rootobject to target
x4# = object position x(target)
y4# = object position y(target)
z4# = object position z(target)
 
set vector3 resultantvector, x4#-x1#, y4#-y1#, z4#-z1#
 
`make vector at 90 degrees to the resultant vector, in the plane containing both the resultant vector and the y vector
position object dummy,x1#,y1#,z1#
set object to object orientation dummy,rootobject
point object dummy,x4#,y4#,z4#
pitch object down dummy,90 `not safe - may not be in correct plane
move object dummy,1
x5#=object position x(dummy)
y5#=object position y(dummy)
z5#=object position z(dummy)
 
set vector3 resultantvectornormal, x5#-x1#,y5#-y1#,z5#-z1#
 
 
`get angle between local y axis and target
phi#=acos(dot product vector3(yvector,resultantvector))
test#=acos(dot product vector3(yvector,resultantvectornormal))
if test#<90.0 then phi#=360-phi#
 
`get angle between target and plane of root object
theta#=90-phi#
 
`get distance between root object and target
targetdist#=length vector3(resultantvector)
 
`get smallest distance between target on local object's plane - the projection distance
projectiondist#=targetdist#*sin(theta#)
 
`project dummy onto plane
position object dummy,x4#,y4#,z4#
set object to object orientation dummy,rootobject
pitch object down dummy,90
move object dummy,projectiondist#
 
`get projection coordinates
x6#=object position x(dummy)
y6#=object position y(dummy)
z6#=object position z(dummy)
 
`make vector joining root object to projected point
 
set vector3 projectedvector, x6#-x1#,y6#-y1#,z6#-z1#
 
 
 
`get normal to projected vector in plane of root object
cross product vector3 projectedvectornormal,projectedvector,yvector
 
`get angle between projected vector and z vector
localyangle#=acos(dot product vector3(projectedvector,zvector))
test#=acos(dot product vector3(projectedvector,projectedvectornormal))
if test#<90.0 then localyangle#=360-localyangle#
 
 
endfunction localyangle#
 
 
function get_projected_distance()
 
`get projected vector's length
 
projectionlength#=length vector3(projectedvector)
 
endfunction projectionlength#