sync on : set global collision on : disable escapekey : set camera range 5,10000
 
autocam off
 
type xyz
    x as float
    y as float
    z as float
endtype
 
ol as xyz
nw as xyz
tmpxyz as xyz
 
#constant PLAYER_SPEED 3.0
#constant ENEMY_SPEED 3.5
#constant PLAYER_TURN 1.0
#constant ENEMY_TURN 0.8
#constant CAM_SMOOTH 7
 
global CurObj as integer
global CurImg as integer
global ECenterX as float
global ECenterY as float
global ECenterZ as float
CurObj = 0
CurImg = 0
 
inc CurObj
make object plain CurObj,10000,10000
Xrotate object CurObj,90
Ground = CurObj
 
inc CurObj
make object box CurObj,2,2,10000
ColorLimb(CurObj, 0, rgb(0,0,0))
EnemyBullet = CurObj
inc CurObj
make object box CurObj,2,2,10000
ColorLimb(CurObj, 0, rgb(0,0,0))
PlayerBullet = CurObj
position object PlayerBullet,0,5050,0
position object EnemyBullet,0,5050,0
Xrotate object PlayerBullet,90
Xrotate object EnemyBullet,90
fix object pivot PlayerBullet
fix object pivot EnemyBullet
hide object PlayerBullet
hide object EnemyBullet
set object collision on PlayerBullet
set object collision on EnemyBullet
set object collision to boxes PlayerBullet
set object collision to boxes EnemyBullet
 
Player = MakePlane()
Enemy = MakePlane()
glue object to limb PlayerBullet,Player,0
glue object to limb EnemyBullet,Enemy,0
position object Player,500,5000,0
position object Enemy,-500,5000,0
 
null = make matrix4(1)
null = make vector3(2)
 
MakeExplosion()
 
color backdrop rgb(50,50,100)
 
PlayerHealth = 100
EnemyHealth = 100
 
createsound("LowerEngine",0,1,1,261,8000,0.00,1.00,0.15,5,0.00,0,0.00)
createsound("Explosion",0,2,1,1000,8000,-0.02,0.50,0.50,10,0.00,0,0.00)
createsound("Shoot",0,3,100,200,8000,-0.01,1.00,1.00,5,0.00,0,10.00)
clone sound 4,3
set sound speed 1,100000
loop sound 1
set sound speed 2,20000
set sound speed 3,30000
set sound speed 4,30000
 
do
 
    if Stop = 0
        camx# = camera position x()
        camy# = camera position y()
        camz# = camera position z()
        position camera object position x(Player),object position y(Player),object position z(Player)
        set camera to object orientation Player
        pitch camera down 20
        move camera -1000
        pitch camera up 20
        newcamx# = camera position x()
        newcamy# = camera position y()
        newcamz# = camera position z()
        position camera curvevalue(newcamx#,camx#,CAM_SMOOTH),curvevalue(newcamy#,camy#,CAM_SMOOTH),curvevalue(newcamz#,camz#,CAM_SMOOTH)
 
        move object Player,PLAYER_SPEED
        position object Enemy,object position x(Enemy)-object position x(Player),object position y(Enemy),object position z(Enemy)-object position z(Player)
        position object Player,0,object position y(Player),0
        pitch object down Player,(upkey()-downkey())*PLAYER_TURN
        roll object right Player,(rightkey()-leftkey())*PLAYER_TURN
        if reloading
            dec reloading
            if reloading = 5
                hide object PlayerBullet
                if hit1
                    hide object hitobj1
                endif
            endif
        endif
        if spacekey()
            if reloading = 0
                show object PlayerBullet
                play sound 3
                reloading = 10
                ol.x = object position x(Player)
                ol.y = object position y(Player)
                ol.z = object position z(Player)
                move object Player,10000
                nw.x = object position x(Player)
                nw.y = object position y(Player)
                nw.z = object position z(Player)
                position object Player,ol.x,ol.y,ol.z
                tmpxyz.x = object position x(Enemy)
                tmpxyz.y = object position y(Enemy)
                tmpxyz.z = object position z(Enemy)
                if CheckLineIntersectSphere(ol, nw, tmpxyz, 100)
                    dec EnemyHealth
                    fx# = object position x(Enemy)+rnd(100)-50
                    fy# = object position y(Enemy)+rnd(100)-50
                    fz# = object position z(Enemy)+rnd(100)-50
                    hitobj1 = rnd(699)+101
                    hit1 = 1
                    position object hitobj1,fx#,fy#,fz#
                    show object hitobj1
                    point object hitobj1,camera position x(),camera position y(),camera position z()
                endif
            endif
        endif
 
        move object Enemy,ENEMY_SPEED
 
        currentx# = object angle x(Enemy)
        currenty# = object angle y(Enemy)
        currentz# = object angle z(Enemy)
        AimMode = 1
        if object position y(Enemy) < 200
            rotate object Enemy,-90,0,0
            AimMode = 0
        else
            point object Enemy,object position x(Player),object position y(Player),object position z(Player)
            distx# = object position x(Enemy)
            disty# = object position y(Enemy)-object position y(Player)
            distz# = object position z(Enemy)
            if (distx#*distx#+disty#*disty#+distz#*distz#) < 500*500
                steerclear = 1
            else
                if steerclear
                    if (distx#*distx#+disty#*disty#+distz#*distz#) > 900*900
                        steerclear = 0
                    endif
                endif
            endif
            if steerclear
                Xrotate object Enemy,object angle x(Enemy)+180.0
                AimMode = 0
            endif
        endif
        wantedx# = wrapvalue(object angle x(Enemy)+180.0-currentx#)-180.0
        wantedy# = wrapvalue(object angle y(Enemy)+180.0-currenty#)-180.0
        wantedz# = wrapvalue(object angle z(Enemy)+180.0-currentz#)-180.0
        OnTarget = 1
        if wantedx# >= ENEMY_TURN
            inc currentx#,ENEMY_TURN
            OnTarget = 0
        else
            if wantedx# <= -ENEMY_TURN
                dec currentx#,ENEMY_TURN
                OnTarget = 0
            endif
        endif
        if wantedy# >= ENEMY_TURN
            inc currenty#,ENEMY_TURN
            OnTarget = 0
        else
            if wantedy# <= -ENEMY_TURN
                dec currenty#,ENEMY_TURN
                OnTarget = 0
            endif
        endif
        if wantedz# >= ENEMY_TURN
            inc currentz#,ENEMY_TURN
            OnTarget = 0
        else
            if wantedz# <= -ENEMY_TURN
                dec currentz#,ENEMY_TURN
                OnTarget = 0
            endif
        endif
        rotate object Enemy,currentx#,currenty#,currentz#
        if reloaded > 0
            dec reloaded
            if reloaded = 5
                hide object EnemyBullet
                if hit2
                    hide object hitobj2
                endif
            endif
        endif
        if OnTarget and AimMode
            if reloaded = 0
                show object EnemyBullet
                play sound 4
                reloaded = 10
                ol.x = object position x(Enemy)
                ol.y = object position y(Enemy)
                ol.z = object position z(Enemy)
                move object Enemy,10000
                nw.x = object position x(Enemy)+rnd(3000)-1500
                nw.y = object position y(Enemy)+rnd(3000)-1500
                nw.z = object position z(Enemy)+rnd(3000)-1500
                position object Enemy,ol.x,ol.y,ol.z
                tmpxyz.x = object position x(Player)
                tmpxyz.y = object position y(Player)
                tmpxyz.z = object position z(Player)
                if CheckLineIntersectSphere(ol, nw, tmpxyz, 100)
                    dec PlayerHealth
                    fx# = object position x(Player)+rnd(100)-50
                    fy# = object position y(Player)+rnd(100)-50
                    fz# = object position z(Player)+rnd(100)-50
                    hitobj2 = rnd(699)+101
                    hit2 = 1
                    position object hitobj2,fx#,fy#,fz#
                    show object hitobj2
                    point object hitobj2,camera position x(),camera position y(),camera position z()
                endif
            endif
        endif
 
        if camera position y() <= 0
            if hidden = 0
                hidden = 1
                hide object Ground
            endif
        else
            if hidden = 1
                hidden = 0
                show object Ground
            endif
        endif
 
        if object collision(Player, Enemy)
            Stop = 1
            explosionx# = object position x(Player)+object position x(Enemy)
            explosiony# = object position y(Player)+object position y(Enemy)
            explosionz# = object position z(Player)+object position z(Enemy)
            ShowExplosion(explosionx#*0.5,explosiony#*0.5,explosionz#*0.5)
            hide object Player
            hide object Enemy
            Msg$ = "...IT'S A DRAW..."
        else
            if object position y(Enemy) < 50
                Stop = 1
                explosionx# = object position x(Enemy)
                explosiony# = object position y(Enemy)
                explosionz# = object position z(Enemy)
                ShowExplosion(explosionx#,explosiony#,explosionz#)
                hide object Enemy
                Msg$ = "YOU WIN!"
            else
                if object position y(Player) < 50
                    Stop = 1
                    explosionx# = object position x(Player)
                    explosiony# = object position y(Player)
                    explosionz# = object position z(Player)
                    ShowExplosion(explosionx#,explosiony#,explosionz#)
                    hide object Player
                    Msg$ = "YOU LOSE!"
                else
                    if EnemyHealth <= 0
                        Stop = 1
                        explosionx# = object position x(Enemy)
                        explosiony# = object position y(Enemy)
                        explosionz# = object position z(Enemy)
                        ShowExplosion(explosionx#,explosiony#,explosionz#)
                        hide object Enemy
                        Msg$ = "YOU WIN!"
                    else
                        if PlayerHealth <= 0
                            Stop = 1
                            explosionx# = object position x(Player)
                            explosiony# = object position y(Player)
                            explosionz# = object position z(Player)
                            ShowExplosion(explosionx#,explosiony#,explosionz#)
                            hide object Player
                            Msg$ = "YOU LOSE!"
                        endif
                    endif
                endif
            endif
        endif
 
        rem 3D SOUNDS!!! :D
        set identity matrix4 1
        set vector3 2,object position x(Enemy),object position y(Enemy)-object position y(Player),object position z(Enemy)
        set sound volume 1,FixTo(100.0,(3000.0/sqrt(length vector3(2))))
        text 0,60,str$(length vector3(2))
        rotate z matrix4 1,object angle z(Player)
        rotate y matrix4 1,object angle y(Player)
        rotate x matrix4 1,object angle x(Player)
        null# = inverse matrix4(1,1)
        transform coords vector3 2,2,1
        pan# = x vector3(2)*10.0
        if pan# > 10000.0 then pan# = 10000.0
        if pan# < -10000.0 then pan# = -10000.0
        set sound pan 1,pan#
    else
        MoveExplosion()
        inc dead
        if dead = 20
            show object 1000
        endif
        if dead > 150
            set text font "Impact"
            set text size 100
            set text to bold
            center text screen width()/2,100,Msg$
            set text font "System"
            set text to normal
            set text size 12
        endif
    endif
    if escapekey()
        delete objects 1,800
        end
    endif
 
    text 0,0,"Altitude: "+str$(object position y(Player)*0.1,1)+ " metres"
    text 0,20,"Player Health: "+str$(PlayerHealth)
    text 0,40,"Enemy Health: "+str$(EnemyHealth)
 
    sync
loop
 
function FixTo(a#, b#)
    if b# < a#
        exitfunction b#
    endif
endfunction a#
 
function MoveExplosion()
    camx# = camera position x()
    camy# = camera position y()
    camz# = camera position z()
    for i = 101 to 800
        distx# = object position x(i)-ECenterX
        disty# = object position y(i)-ECenterY
        distz# = object position z(i)-ECenterZ
        distx# = distx#*1.1
        disty# = disty#*1.1
        distz# = distz#*1.1
        position object i,distx#+ECenterX,disty#+ECenterY,distz#+ECenterZ
        point object i,camx#,camy#,camz#
    next i
endfunction
 
function ShowExplosion(x#,y#,z#)
    stop sound 1
    play sound 2
    backdrop off
    cls 0
    make object plain 1000,1000,1000
    lock object on 1000
    position object 1000,0,0,10
    ColorLimb(1000,0,rgb(0,0,0))
    set alpha mapping on 1000,2
    hide object 1000
    ECenterX = x#
    ECenterY = y#
    ECenterZ = z#
    dec x#,100.0
    dec y#,100.0
    dec z#,100.0
    for i = 101 to 800
        position object i, x#+rnd(200), y#+rnd(200), z#+rnd(200)
        point object i, camera position x(), camera position y(), camera position z()
        show object i
    next i
endfunction
 
function MakeExplosion()
    Col1 = MakeColor(rgb(255,100,100))
    Col2 = MakeColor(rgb(255,255,100))
    Col3 = MakeColor(rgb(255,200,50))
    Col4 = MakeColor(rgb(255,200,100))
    Col5 = MakeColor(rgb(255,220,100))
    Col6 = MakeColor(rgb(255,230,100))
    Col7 = MakeColor(rgb(255,240,150))
    nextobjnum = 100
    for t = 1 to 7
        select t
            case 1 : col = Col1 : endcase
            case 2 : col = Col2 : endcase
            case 3 : col = Col3 : endcase
            case 4 : col = Col4 : endcase
            case 5 : col = Col5 : endcase
            case 6 : col = Col6 : endcase
            case 7 : col = Col7 : endcase
        endselect
        for d = 1 to 100
            inc nextobjnum
            make object plain nextobjnum,50,50
            ghost object on nextobjnum
            texture object nextobjnum,col
            hide object nextobjnum
        next d
    next t
endfunction
 
function MakePlane()
    inc CurObj
    make object cylinder CurObj,100
    make mesh from object 10,CurObj
 
    lock vertexdata for limb CurObj,0
    for i = 0 to get vertexdata vertex count()
        if get vertexdata position y(i) < 0
            set vertexdata position i,get vertexdata position x(i)*0.1,get vertexdata position y(i),get vertexdata position z(i)*0.1
        else
            set vertexdata position i,get vertexdata position x(i)*0.3,get vertexdata position y(i),get vertexdata position z(i)*0.3
        endif
    next i
    unlock vertexdata
    lock vertexdata for mesh 10
    for i = 0 to get vertexdata vertex count()
        if get vertexdata position y(i) < 0
            set vertexdata position i,get vertexdata position x(i)*0.1,get vertexdata position y(i),get vertexdata position z(i)*0.1
        else
            set vertexdata position i,get vertexdata position x(i)*0.3,get vertexdata position y(i),get vertexdata position z(i)*0.3
        endif
    next i
    unlock vertexdata
    make object box CurObj+1,100,1,20
    make object box CurObj+2,100,1,20
    make object sphere CurObj+3,10
    make object sphere CurObj+4,10
    make object sphere CurObj+5,50,20,20
    make object cylinder CurObj+6,40
    make object cylinder CurObj+7,40
    Xrotate object CurObj,90
    fix object pivot CurObj
    make mesh from object 1,CurObj+1
    make mesh from object 2,CurObj+2
    make mesh from object 3,CurObj+3
    lock vertexdata for mesh 3
    for i = 0 to get vertexdata vertex count()
        if get vertexdata position z(i) > 0
            set vertexdata position i,get vertexdata position x(i),get vertexdata position y(i),0
        endif
    next i
    unlock vertexdata
    make mesh from object 4,CurObj+4
    make mesh from object 5,CurObj+5
    make mesh from object 6,CurObj+6
    make mesh from object 7,CurObj+7
    add limb CurObj,1,1
    add limb CurObj,2,2
    add limb CurObj,3,3
    add limb CurObj,4,4
    add limb CurObj,5,5
    add limb CurObj,6,6
    add limb CurObj,7,7
    add limb CurObj,8,5
    offset limb CurObj,1,0,30,15
    offset limb CurObj,2,0,30,-25
    offset limb CurObj,3,0,-50,0
    offset limb CurObj,4,0,-50,0
    offset limb CurObj,5,0,50,0
    offset limb CurObj,6,30,30,-5
    offset limb CurObj,7,-30,30,-5
    offset limb CurObj,8,0,55,0
    rotate limb CurObj,1,90,0,0
    rotate limb CurObj,2,90,0,0
    rotate limb CurObj,6,90,0,0
    rotate limb CurObj,7,90,0,0
    scale limb CurObj,3,100,200,500
    scale limb CurObj,4,500,200,100
    scale limb CurObj,5,61,5,61
    scale limb CurObj,6,10,100,10
    scale limb CurObj,7,10,100,10
    scale limb CurObj,8,100,5,100
    delete object CurObj+1
    delete object CurObj+2
    delete object CurObj+3
    delete object CurObj+4
    delete object CurObj+5
    delete object CurObj+6
    delete object CurObj+7
    set object normals CurObj
    set object smoothing CurObj,100
    set object ambient CurObj,0
    set object light CurObj,0
    ColorLimb(CurObj,0,rgb(255,0,0))
    ColorLimb(CurObj,1,rgb(0,0,255))
    ColorLimb(CurObj,2,rgb(0,0,255))
    ColorLimb(CurObj,3,rgb(255,0,0))
    ColorLimb(CurObj,4,rgb(255,0,0))
    ColorLimb(CurObj,5,rgb(255,0,0))
    ColorLimb(CurObj,6,rgb(255,0,0))
    ColorLimb(CurObj,7,rgb(255,0,0))
    ColorLimb(CurObj,8,rgb(100,100,255))
    MakeCartoon(CurObj,0,10)
    MakeCartoon(CurObj,1,1)
    MakeCartoon(CurObj,2,2)
    MakeCartoon(CurObj,3,3)
    MakeCartoon(CurObj,4,4)
    MakeCartoon(CurObj,5,5)
    MakeCartoon(CurObj,6,6)
    MakeCartoon(CurObj,7,7)
    MakeCartoon(CurObj,8,5)
    delete mesh 1
    delete mesh 2
    delete mesh 3
    delete mesh 4
    delete mesh 5
    delete mesh 6
    delete mesh 7
    delete mesh 10
    set object collision on CurObj
    set object collision to boxes CurObj
endfunction CurObj
 
function MakeCartoon(ObjNum as integer, LimbNum as integer, MeshNum as integer)
    lmb = NextLimb(ObjNum)
    add limb ObjNum,lmb,MeshNum
    offset limb ObjNum,lmb,limb offset x(ObjNum,LimbNum),limb offset y(ObjNum,LimbNum),limb offset z(ObjNum,LimbNum)
    rotate limb ObjNum,lmb,limb angle x(ObjNum,LimbNum),limb angle y(ObjNum,LimbNum),limb angle z(ObjNum,LimbNum)
    scale limb ObjNum,lmb,limb scale x(ObjNum,LimbNum)*-1.0-5,limb scale y(ObjNum,LimbNum)*1.0+5,limb scale z(ObjNum,LimbNum)*1.0+5
    ColorLimb(ObjNum,lmb,rgb(0,0,0))
endfunction
 
function NextLimb(ObjNum as integer)
    i = 0
    repeat
        inc i
    until limb exist(ObjNum, i) = 0
endfunction i
 
function ColorLimb(ObjNum as integer, LimbNum as integer, Col as dword)
    texture limb ObjNum,LimbNum,MakeColor(Col)
endfunction
 
function MakeColor(Col as dword)
    inc CurImg
    make memblock 1,16
    write memblock dword 1,0,1
    write memblock dword 1,4,1
    write memblock dword 1,8,32
    write memblock dword 1,12,Col
    make image from memblock CurImg,1
    delete memblock 1
endfunction CurImg
 
function CheckLineIntersectSphere(p1 as xyz, p2 as xyz, pSphere as xyz, R as float)
    a as float
    b as float
    c as float
 
    D as float
    Sq as float
    A2 as float
    mu as float
 
    L as xyz
    vRel as xyz
 
    `calculate vectors
    L.x = p2.x-p1.x
    L.y = p2.y-p1.y
    L.z = p2.z-p1.z
    vRel.x = p1.x-pSphere.x
    vRel.y = p1.y-pSphere.y
    vRel.z = p1.z-pSphere.z
 
    `set up quadratic equation
    a = (L.X * L.X) + (L.Y * L.Y) + (L.z * L.z)
    b = 2.0 * ((L.X * vRel.X) + (L.Y * vRel.Y) + (L.z * vRel.z))
    c = (pSphere.X * pSphere.X) + (pSphere.Y * pSphere.Y) + (pSphere.z * pSphere.z) + (p1.X * p1.X) + (p1.Y * p1.Y) + (p1.z * p1.z) - (2 * ((pSphere.X * p1.X) + (pSphere.Y * p1.Y) + (pSphere.z * p1.z))) - (R * R)
 
    `calculate discriminant
    D = (b * b) - (4 * a * c)
    if D < 0 or a = 0
        exitfunction 0
    endif
endfunction 1
 
function createsound(name$,soundtype,soundnumber,frequency#,length#,loudness#,bend#,decay#,vibratospeed#,vibratodepth#,tremelospeed#,tremelodepth#,attack#)
 
outWord as word
dword1 as dword: dword2 as dword: dword3 as dword: dword4 as dword
dword5 as dword: dword6 as dword: dword7 as dword
 
samples=int((length#/1000)*44100)
 
if memblock exist(1) then delete memblock 1
make memblock 1,samples*2+44
 
` write 28 memblock header bytes
dword1=1      ` gg query: is this the number of channels?
dword2=2
dword3=22050  ` gg query: seems to be half the number of samples per second - why?
dword4=88200  ` gg query: is this the number of bytes per second?
dword5=4      ` gg query: what does this represent?
dword6=16     ` gg query:     (ditto)            ?
dword7=0      ` gg query:     (ditto)            ?
 
position=0
write memblock byte 1, position, asc("R") : inc position
write memblock byte 1, position, asc("I") : inc position
write memblock byte 1, position, asc("F") : inc position
write memblock byte 1, position, asc("F") : inc position
 
write memblock dword 1, position, samples*2+36 : inc position,4
 
write memblock byte 1, position, asc("W") : inc position
write memblock byte 1, position, asc("A") : inc position
write memblock byte 1, position, asc("V") : inc position
write memblock byte 1, position, asc("E") : inc position
 
write memblock byte 1, position, asc("f") : inc position
write memblock byte 1, position, asc("m") : inc position
write memblock byte 1, position, asc("t") : inc position
write memblock byte 1, position, asc(" ") : inc position
write memblock dword 1, position, 16 : inc position,4
 
write memblock word 1, position, dword1 : inc position,2
write memblock word 1, position, dword2 : inc position,2
write memblock dword 1, position, dword3 : inc position,4
write memblock dword 1, position, dword4 : inc position,4
write memblock word 1, position, dword5 : inc position,2
write memblock word 1, position, dword6 : inc position,2
`write memblock word 1, position, dword7 : inc position,2 `MAYBE UNCOMMENT?
 
write memblock byte 1, position, asc("d") : inc position
write memblock byte 1, position, asc("a") : inc position
write memblock byte 1, position, asc("t") : inc position
write memblock byte 1, position, asc("a") : inc position
write memblock dword 1, position, samples*2 : inc position,4
 
rem generate and write wave
`inc param_attackamount#,0.0001
riseinloudness#=loudness#
for x=1 to samples
  outInteger=int(sin((x/122.5)*(frequency#+vibratodepth#*sin(theta#)))*(loudness#-fallinloudness#-riseinloudness#+tremelodepth#*sin(phi#)))*3.0
  if outInteger <-32767 then outInteger=-32767  ` gg query: is this the valid range?
  if outInteger>32767 then outInteger=32767     ` gg query:       (ditto)          ?
  outWord=outInteger
  inc theta#,vibratospeed#
  inc phi#,tremelospeed#
  dec frequency#,bend#
  if fallinloudness#<loudness#
		inc fallinloudness#,decay#
  endif
  if riseinloudness#>0
    dec riseinloudness#,attack#
  endif
  write memblock word 1,position,outWord : inc position,2
next x
 
if file exist(name$+".wav") then delete file name$+".wav"
open to write 1,name$+".wav"
make file from memblock 1,1
close file 1
 
if sound exist(soundnumber)=1 then delete sound soundnumber
 
if soundtype
    load 3dsound name$+".wav", soundnumber
else
    load sound name$+".wav", soundnumber
endif
 
` memblock no longer required
delete memblock 1
 
endfunction