Thread Rating:
  • 2 Vote(s) - 4.5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Star Fox
#1
Here's an attempt of capturing the controls of Star Fox. The SNES had no analogue stick, yet the controls of Star Fox felt awesome. We'll see what happens when obstacles and enemies are added.

Code:
' flight_test.n7
' --------------
' Move with arrow keys, shoot with space bar. Change y-axis inversion below if you need to.

include "s3d.n7"

constant RES = 480

' Set to 1 for non-inverted y-axis. I can only play inverted ...
ctrlYScale = -1

winAspect = min(screenw()/screenh(), 2)

set window "flight test", RES*winAspect, RES, false
set redraw off

S3D_SetView(primary, rad(60), 0.1, 100)

' Create player ship model.
shipMesh = S3D_BeginMesh()
    hw = 0.5
    S3D_Begin(S3D_TRIANGLES)
        S3D_Color(208, 208, 208)
        ' right side.
        S3D_Vertex(0, 0, 2,          0, 0)
        S3D_Vertex(0.5, 0.125, -1.25, 0, 0)
        S3D_Vertex(0, -0.25, -1,      0, 0)
        ' left side.
        S3D_Vertex(0, 0, 2,            0, 0)
        S3D_Vertex(0, -0.25, -1,      0, 0)
        S3D_Vertex(-0.5, 0.125, -1.25, 0, 0)
        ' back.
        S3D_Color(255, 160, 0)
        S3D_Vertex(0, -0.25, -1,      0, 0)
        S3D_Vertex(0.5, 0.125, -1.25,  0, 0)
        S3D_Vertex(-0.5, 0.125, -1.25, 0, 0)
        ' bottom.
        S3D_Color(128, 128, 128)
        S3D_Vertex(0, 0, 2,            0, 0)
        S3D_Vertex(-0.5, 0.125, -1.25, 0, 0)
        S3D_Vertex(0.5, 0.125, -1.25,  0, 0)
        ' right wing.
        S3D_Color(64, 128, 208)
        S3D_Vertex(0.5, 0, 0.25,  0, 0)
        S3D_Vertex(2.0, 0.25, -2, 0, 0)
        S3D_Vertex(0.5, 0, -1.5,  0, 0)
        S3D_Vertex(0.5, 0, 0.25,  0, 0)
        S3D_Vertex(0.5, 0, -1.5,  0, 0)
        S3D_Vertex(2.0, 0.25, -2, 0, 0)
        ' left wing.
        S3D_Color(64, 128, 208)
        S3D_Vertex(-0.5, 0, 0.25,  0, 0)
        S3D_Vertex(-2.0, 0.25, -2, 0, 0)
        S3D_Vertex(-0.5, 0, -1.5,  0, 0)
        S3D_Vertex(-0.5, 0, 0.25,  0, 0)
        S3D_Vertex(-0.5, 0, -1.5,  0, 0)
        S3D_Vertex(-2.0, 0.25, -2, 0, 0)
    S3D_End()
S3D_EndMesh()

' Player bullet model, probably needs volume ...
bulletMesh = S3D_BeginMesh()
    S3D_Color(255, 208, 96)
    S3D_Begin(S3D_QUADS)
        S3D_Vertex(0, 0, 0.5,  0, 0)
        S3D_Vertex(0.5, 0, 0,  0, 0)
        S3D_Vertex(0, 0, -1.5, 0, 0)
        S3D_Vertex(-0.5, 0, 0, 0, 0)
        S3D_Vertex(-0.5, 0, 0, 0, 0)
        S3D_Vertex(0, 0, -1.5, 0, 0)
        S3D_Vertex(0.5, 0, 0,  0, 0)
        S3D_Vertex(0, 0, 0.5,  0, 0)
    S3D_End()
S3D_EndMesh()

' Player.
ship = []
ship.mesh = shipMesh
ship.pos = []
ship.pos[0] = 0
ship.pos[1] = -2
ship.pos[2] = 0
ship.rot = []
ship.rot.yaw = 0
ship.rot.pitch = 0
ship.rot.roll = 0
ship.dir = [0, 0, 0, 0]
ship.shootTimer = 0

' Player bullets.
bullets = []

' Camera.
cam = []
cam.pos = []
cam.pos[0] = 0
cam.pos[1] = 0
cam.pos[2] = 0
cam.rot = []
cam.rot.yaw = 0
cam.rot.pitch = 0
cam.rot.roll = 0
cam.followX = 0.125

' X and y limitations of player.
xMin = -8
xMax = 8
yMin = -15
yMax = -1

' Forward vector.
fwdVec = [0, 0, 1, 0]
' For computations using s3d.
srcVec = [0, 0, 0, 0]
dstVec = [0, 0, 0, 0]

while not keydown(KEY_ESCAPE, true)
    ' Change direction.
    dYaw = 0
    dPitch = 0
    if keydown(KEY_LEFT)  dYaw = dYaw - 45
    if keydown(KEY_RIGHT)  dYaw = dYaw + 45
    if keydown(KEY_UP)  dPitch = dPitch + 30*ctrlYScale
    if keydown(KEY_DOWN)  dPitch = dPitch - 30*ctrlYScale
    ship.rot.yaw = 0.95*ship.rot.yaw + 0.05*dYaw
    ship.rot.pitch = 0.95*ship.rot.pitch + 0.05*dPitch
    ship.rot.roll = 0.95*ship.rot.roll + 0.05*dYaw*0.5

    ' Get ships direction as a vector.
    S3D_ClearTransformation()
    ' A window aspect effect is applied in ClearTransformation, so we have to revert it to get
    ' proper coordinates from TransformVector. I have ... NO idea of why I did it like that. I'll
    ' fix that in the next n7 release.
    S3D_Scale(winAspect, 1, 1)
    S3D_RotateY(rad(ship.rot.yaw))
    S3D_RotateX(rad(ship.rot.pitch))
    S3D_RotateZ(rad(ship.rot.roll))
    S3D_TransformVector(ship.dir, fwdVec)
    VectorNormalize(ship.dir)
   
    ' Uhm, slow down when close to x and y limits.
    dxMul = 1;  dyMul =1
    if ship.dir[0] < 0  dxMul = min(ship.pos[0] - xMin, 4)*0.25
    elseif ship.dir[0] > 0  dxMul = min(xMax - ship.pos[0], 4)*0.25
    if ship.dir[1] < 0  dyMul = min(ship.pos[1] - yMin, 4)*0.25
    elseif ship.dir[1] > 0  dyMul = min(yMax - ship.pos[1], 4)*0.25

    ' Move.   
    ship.pos[0] = max(min(ship.pos[0] + ship.dir[0]*0.25*dxMul, xMax), xMin)
    ship.pos[1] = max(min(ship.pos[1] + ship.dir[1]*0.5*dyMul, yMax), yMin)

    ' Shoot.
    ship.shootTimer = max(ship.shootTimer - 1, 0)   
    if keydown(KEY_SPACE) and ship.shootTimer <= 0
        ship.shootTimer = 15
        spd = 1

        ' Add two bullets with positions relative to the player ship.
        S3D_ClearTransformation()
        S3D_Scale(winAspect, 1, 1)
        S3D_Translate(ship.pos[0], ship.pos[1], ship.pos[2])
        S3D_RotateY(rad(ship.rot.yaw))
        S3D_RotateX(rad(ship.rot.pitch))
        S3D_RotateZ(rad(ship.rot.roll))
        for x = -0.75 to 0.75 step 1.5
            srcVec[0] = x;  srcVec[1] = 0; srcVec[2] = 1; srcVec[3] = 1
            bullet = [
                mesh: bulletMesh,
                pos: dim(3),
                rot: [yaw: ship.rot.yaw, pitch: ship.rot.pitch, roll: ship.rot.roll],
                mvec: [ship.dir[0]*spd, ship.dir[1]*spd, ship.dir[2]*spd]]
            S3D_TransformVector(bullet.pos, srcVec)
            bullets[sizeof(bullets)] = bullet 
        next
    endif

    ' Position camera.
    cam.pos[0] = cam.followX*ship.pos[0]
    cam.pos[1] = 0.5*ship.pos[1] - 3
    cam.pos[2] = ship.pos[2] - 10
   
    ' Update bullets.
    i = 0
    while i < sizeof(bullets)
        b = bullets[i]
        VectorAdd(b.pos, b.mvec)
        if b.pos[1] >= 0 or b.pos[2] > cam.pos[2] + 50  free key bullets, i
        else  i = i + 1
    wend

    ' Draw.
    set color 48, 48, 48
    cls
   
    S3D_Clear()
    S3D_Translate(-cam.pos[0], -cam.pos[1], -cam.pos[2])

    DrawObject(ship)   
   
    foreach b in bullets  DrawObject(b)
   
    set color 255, 255, 255
    set caret 4, 4
    wln "dx:      " + str(ship.dir[0], 0, 2)
    wln "dy:      " + str(ship.dir[1], 0, 2)
    wln "dz:      " + str(ship.dir[2], 0, 2)
    wln
    wln "bullets: " + sizeof(bullets)
   
    redraw
    fwait 60
wend

' DrawObject
' ----------
function DrawObject(o)
    ' Object.
    S3D_Push()
        S3D_Color(255, 255, 255)
        S3D_Translate(o.pos[0], o.pos[1], o.pos[2])
        S3D_RotateY(rad(o.rot.yaw))
        S3D_RotateX(rad(o.rot.pitch))
        S3D_RotateZ(rad(o.rot.roll))
        S3D_Mesh(o.mesh, 0)
    S3D_Pop()
    ' Shadow.
    S3D_SetDepthBuffer(S3D_Z_BUFFER_READ)
    S3D_Push()
        S3D_Translate(o.pos[0], 0, o.pos[2])
        S3D_Scale(1, 0, 1)
        S3D_RotateY(rad(o.rot.yaw))
        S3D_RotateX(rad(o.rot.pitch))
        S3D_RotateZ(rad(o.rot.roll))
        S3D_Color(0, 0, 0)
        S3D_Mesh(o.mesh, 0)
    S3D_Pop()
    S3D_SetDepthBuffer(S3D_Z_BUFFER)   
endfunc

' VectorNormalize
' ---------------
function VectorNormalize(v)
    k = 1/sqr(v[0]*v[0] + v[1]*v[1] + v[2]*v[2])
    v[0] = v[0]*k;  v[1] = v[1]*k;  v[2] = v[2]*k
endfunc

' VectorAdd
' ---------
function VectorAdd(dst, src)
    dst[0] = dst[0] + src[0]
    dst[1] = dst[1] + src[1]
    dst[2] = dst[2] + src[2]
endfunc
Reply
#2
That is SO cool!! Very smooth indeed.... Looking forward to shooting and blowing stuff up... Ha... I'll even dust of my joystick... Moo Ha Ha Ha...
Logic is the beginning of wisdom.
Reply
#3
(09-12-2025, 12:18 AM)johnno56 Wrote: That is SO cool!! Very smooth indeed.... Looking forward to shooting and blowing stuff up... Ha... I'll even dust of my joystick... Moo Ha Ha Ha...

Do you play these kind of games with inverted y-axis (press down to look up) or not? I'm just curious Smile  I believe it was Top Gun on NES that made me an inverted player for life. I have bought games that I've never been able to play because there's been no option to invert the controls.
Reply
#4
I'm trying to give a starfleet effect as a background, but I'm curious, why the stars are not coming from the center of the screen. Would you please advise me ? Thank you.

Code:
' flight_test.n7
' --------------
' Move with arrow keys, shoot with space bar. Change y-axis inversion below if you need to.

include "s3d.n7"

constant RES = 480

' Set to 1 for non-inverted y-axis. I can only play inverted ...
ctrlYScale = -1

winAspect = min(screenw()/screenh(), 2)

set window "flight test", RES*winAspect, RES, false
set redraw off

S3D_SetView(primary, rad(60), 0.1, 100)

' Create player ship model.
shipMesh = S3D_BeginMesh()
    hw = 0.5
    S3D_Begin(S3D_TRIANGLES)
        S3D_Color(208, 208, 208)
        ' right side.
        S3D_Vertex(0, 0, 2,          0, 0)
        S3D_Vertex(0.5, 0.125, -1.25, 0, 0)
        S3D_Vertex(0, -0.25, -1,      0, 0)
        ' left side.
        S3D_Vertex(0, 0, 2,            0, 0)
        S3D_Vertex(0, -0.25, -1,      0, 0)
        S3D_Vertex(-0.5, 0.125, -1.25, 0, 0)
        ' back.
        S3D_Color(255, 160, 0)
        S3D_Vertex(0, -0.25, -1,      0, 0)
        S3D_Vertex(0.5, 0.125, -1.25,  0, 0)
        S3D_Vertex(-0.5, 0.125, -1.25, 0, 0)
        ' bottom.
        S3D_Color(128, 128, 128)
        S3D_Vertex(0, 0, 2,            0, 0)
        S3D_Vertex(-0.5, 0.125, -1.25, 0, 0)
        S3D_Vertex(0.5, 0.125, -1.25,  0, 0)
        ' right wing.
        S3D_Color(64, 128, 208)
        S3D_Vertex(0.5, 0, 0.25,  0, 0)
        S3D_Vertex(2.0, 0.25, -2, 0, 0)
        S3D_Vertex(0.5, 0, -1.5,  0, 0)
        S3D_Vertex(0.5, 0, 0.25,  0, 0)
        S3D_Vertex(0.5, 0, -1.5,  0, 0)
        S3D_Vertex(2.0, 0.25, -2, 0, 0)
        ' left wing.
        S3D_Color(64, 128, 208)
        S3D_Vertex(-0.5, 0, 0.25,  0, 0)
        S3D_Vertex(-2.0, 0.25, -2, 0, 0)
        S3D_Vertex(-0.5, 0, -1.5,  0, 0)
        S3D_Vertex(-0.5, 0, 0.25,  0, 0)
        S3D_Vertex(-0.5, 0, -1.5,  0, 0)
        S3D_Vertex(-2.0, 0.25, -2, 0, 0)
    S3D_End()
S3D_EndMesh()

' Player bullet model, probably needs volume ...
bulletMesh = S3D_BeginMesh()
    S3D_Color(255, 208, 96)
    S3D_Begin(S3D_QUADS)
        S3D_Vertex(0, 0, 0.5,  0, 0)
        S3D_Vertex(0.5, 0, 0,  0, 0)
        S3D_Vertex(0, 0, -1.5, 0, 0)
        S3D_Vertex(-0.5, 0, 0, 0, 0)
        S3D_Vertex(-0.5, 0, 0, 0, 0)
        S3D_Vertex(0, 0, -1.5, 0, 0)
        S3D_Vertex(0.5, 0, 0,  0, 0)
        S3D_Vertex(0, 0, 0.5,  0, 0)
    S3D_End()
S3D_EndMesh()

' Player.
ship = []
ship.mesh = shipMesh
ship.pos = []
ship.pos[0] = 0
ship.pos[1] = -2
ship.pos[2] = 0
ship.rot = []
ship.rot.yaw = 0
ship.rot.pitch = 0
ship.rot.roll = 0
ship.dir = [0, 0, 0, 0]
ship.shootTimer = 0

' Player bullets.
bullets = []

' Camera.
cam = []
cam.pos = []
cam.pos[0] = 0
cam.pos[1] = 0
cam.pos[2] = 0
cam.rot = []
cam.rot.yaw = 0
cam.rot.pitch = 0
cam.rot.roll = 0
cam.followX = 0.125

' X and y limitations of player.
xMin = -8
xMax = 8
yMin = -15
yMax = -1

' Forward vector.
fwdVec = [0, 0, 1, 0]
' For computations using s3d.
srcVec = [0, 0, 0, 0]
dstVec = [0, 0, 0, 0]

'-----------------------------
'starfleet
visible stars = []
for i = 0 to 199  stars[i] = [x: rnd()*2-1, y:rnd()*2-1, z:0.1+rnd()*0.9]

'center of the screen
visible wp = screenw()/2
visible hp = screenh()/2
'------------------------------

' MAIN PROGRAM
while not keydown(KEY_ESCAPE, true)
    ' Change direction.
    dYaw = 0
    dPitch = 0
    if keydown(KEY_LEFT)  dYaw = dYaw - 45
    if keydown(KEY_RIGHT)  dYaw = dYaw + 45
    if keydown(KEY_UP)  dPitch = dPitch + 30*ctrlYScale
    if keydown(KEY_DOWN)  dPitch = dPitch - 30*ctrlYScale
    ship.rot.yaw = 0.95*ship.rot.yaw + 0.05*dYaw
    ship.rot.pitch = 0.95*ship.rot.pitch + 0.05*dPitch
    ship.rot.roll = 0.95*ship.rot.roll + 0.05*dYaw*0.5

    ' Get ships direction as a vector.
    S3D_ClearTransformation()
    ' A window aspect effect is applied in ClearTransformation, so we have to revert it to get
    ' proper coordinates from TransformVector. I have ... NO idea of why I did it like that. I'll
    ' fix that in the next n7 release.
    S3D_Scale(winAspect, 1, 1)
    S3D_RotateY(rad(ship.rot.yaw))
    S3D_RotateX(rad(ship.rot.pitch))
    S3D_RotateZ(rad(ship.rot.roll))
    S3D_TransformVector(ship.dir, fwdVec)
    VectorNormalize(ship.dir)
   
    ' Uhm, slow down when close to x and y limits.
    dxMul = 1;  dyMul =1
    if ship.dir[0] < 0  dxMul = min(ship.pos[0] - xMin, 4)*0.25
    elseif ship.dir[0] > 0  dxMul = min(xMax - ship.pos[0], 4)*0.25
    if ship.dir[1] < 0  dyMul = min(ship.pos[1] - yMin, 4)*0.25
    elseif ship.dir[1] > 0  dyMul = min(yMax - ship.pos[1], 4)*0.25

    ' Move.   
    ship.pos[0] = max(min(ship.pos[0] + ship.dir[0]*0.25*dxMul, xMax), xMin)
    ship.pos[1] = max(min(ship.pos[1] + ship.dir[1]*0.5*dyMul, yMax), yMin)

    ' Shoot.
    ship.shootTimer = max(ship.shootTimer - 1, 0)   
    if keydown(KEY_SPACE) and ship.shootTimer <= 0
        ship.shootTimer = 15
        spd = 1

        ' Add two bullets with positions relative to the player ship.
        S3D_ClearTransformation()
        S3D_Scale(winAspect, 1, 1)
        S3D_Translate(ship.pos[0], ship.pos[1], ship.pos[2])
        S3D_RotateY(rad(ship.rot.yaw))
        S3D_RotateX(rad(ship.rot.pitch))
        S3D_RotateZ(rad(ship.rot.roll))
        for x = -0.75 to 0.75 step 1.5
            srcVec[0] = x;  srcVec[1] = 0; srcVec[2] = 1; srcVec[3] = 1
            bullet = [
                mesh: bulletMesh,
                pos: dim(3),
                rot: [yaw: ship.rot.yaw, pitch: ship.rot.pitch, roll: ship.rot.roll],
                mvec: [ship.dir[0]*spd, ship.dir[1]*spd, ship.dir[2]*spd]]
            S3D_TransformVector(bullet.pos, srcVec)
            bullets[sizeof(bullets)] = bullet
        next
    endif

    ' Position camera.
    cam.pos[0] = cam.followX*ship.pos[0]
    cam.pos[1] = 0.5*ship.pos[1] - 3
    cam.pos[2] = ship.pos[2] - 10
   
    ' Update bullets.
    i = 0
    while i < sizeof(bullets)
        b = bullets[i]
        VectorAdd(b.pos, b.mvec)
        if b.pos[1] >= 0 or b.pos[2] > cam.pos[2] + 50  free key bullets, i
        else  i = i + 1
    wend

    ' Draw.
    set color 48, 48, 48
    cls
   
    S3D_Clear()
    S3D_Translate(-cam.pos[0], -cam.pos[1], -cam.pos[2])

    DrawObject(ship)   
   
    foreach b in bullets  DrawObject(b)
   
    set color 255, 255, 255
    set caret 4, 4
    wln "dx:      " + str(ship.dir[0], 0, 2)
    wln "dy:      " + str(ship.dir[1], 0, 2)
    wln "dz:      " + str(ship.dir[2], 0, 2)
    wln
    wln "bullets: " + sizeof(bullets)
   
    starfleet()
   
    redraw
    fwait 60
wend

' DrawObject
' ----------
function DrawObject(o)
    ' Object.
    S3D_Push()
        S3D_Color(255, 255, 255)
        S3D_Translate(o.pos[0], o.pos[1], o.pos[2])
        S3D_RotateY(rad(o.rot.yaw))
        S3D_RotateX(rad(o.rot.pitch))
        S3D_RotateZ(rad(o.rot.roll))
        S3D_Mesh(o.mesh, 0)
    S3D_Pop()
    ' Shadow.
    S3D_SetDepthBuffer(S3D_Z_BUFFER_READ)
    S3D_Push()
        S3D_Translate(o.pos[0], 0, o.pos[2])
        S3D_Scale(1, 0, 1)
        S3D_RotateY(rad(o.rot.yaw))
        S3D_RotateX(rad(o.rot.pitch))
        S3D_RotateZ(rad(o.rot.roll))
        S3D_Color(0, 0, 0)
        S3D_Mesh(o.mesh, 0)
    S3D_Pop()
    S3D_SetDepthBuffer(S3D_Z_BUFFER)   
endfunc

' VectorNormalize
' ---------------
function VectorNormalize(v)
    k = 1/sqr(v[0]*v[0] + v[1]*v[1] + v[2]*v[2])
    v[0] = v[0]*k;  v[1] = v[1]*k;  v[2] = v[2]*k
endfunc

' VectorAdd
' ---------
function VectorAdd(dst, src)
    dst[0] = dst[0] + src[0]
    dst[1] = dst[1] + src[1]
    dst[2] = dst[2] + src[2]
endfunc

'--------------------------------------
function starfleet()
    for i = 0 to 199
        stars[i].z = stars[i].z - 0.01
        if stars[i].z < 0.1
            stars[i].z = stars[i].z + 0.9
        endif
       
        'Coordinate (x,y) is moving from center
        x = wp + stars[i].x*wp/stars[i].z
        y = hp + stars[i].y*hp/stars[i].z
                     
        radius = 1/stars[i].z
        set color 255,255,255 'white
        draw ellipse x,y,radius,radius,1 '1=filled
    next
endfunc
'-----------------------------------------
Reply
#5
shadow of the ship in space ?
hmmm
Reply
#6
I can't test your code now, since I'm outside a store, waiting for the wife. But I'm guessing you should replace the center of the screen:

Code:
'center of the screen
visible wp = screenw()/2
visible hp = screenh()/2

, with the center of the window:

Code:
'center of the screen
visible wp = width(primary)/2
visible hp = height(primary)/2
Reply
#7
Came home from work and added some obstacles that the player can collide with.

Code:
' flight_test.n7
' --------------

include "s3d.n7"
include "qsort.n7"

constant RES = 720

' Set to 1 for non-inverted y-axis. I can only play inverted ...
ctrlYScale = -1
renderDepth = 50

winAspect = min(screenw()/screenh(), 2)

set window "flight test", RES*winAspect, RES, true
set redraw off

S3D_SetView(primary, rad(60), 0.1, renderDepth)

visible vRedObstacleMesh = BoxMesh(5, 2.5, 5, 208, 16, 0)
visible vGreenObstacleMesh = BoxMesh(4, 5, 4, 16, 208, 0)
visible vBlueObstacleMesh = BoxMesh(2, 13, 2, 16, 0, 208)

' Create player ship model.
shipMesh = S3D_BeginMesh()
    hw = 0.5
    S3D_Begin(S3D_TRIANGLES)
        S3D_Color(208, 208, 208)
        ' right side.
        S3D_Vertex(0, 0, 2,           0, 0)
        S3D_Vertex(0.5, 0.125, -1.25, 0, 0)
        S3D_Vertex(0, -0.25, -1,      0, 0)
        ' left side.
        S3D_Vertex(0, 0, 2,            0, 0)
        S3D_Vertex(0, -0.25, -1,       0, 0)
        S3D_Vertex(-0.5, 0.125, -1.25, 0, 0)
        ' back.
        S3D_Color(255, 160, 0)
        S3D_Vertex(0, -0.25, -1,       0, 0)
        S3D_Vertex(0.5, 0.125, -1.25,  0, 0)
        S3D_Vertex(-0.5, 0.125, -1.25, 0, 0)
        ' bottom.
        S3D_Color(128, 128, 128)
        S3D_Vertex(0, 0, 2,            0, 0)
        S3D_Vertex(-0.5, 0.125, -1.25, 0, 0)
        S3D_Vertex(0.5, 0.125, -1.25,  0, 0)
        ' right wing.
        S3D_Color(64, 128, 208)
        S3D_Vertex(0.5, 0, 0.25,  0, 0)
        S3D_Vertex(2.0, 0.25, -2, 0, 0)
        S3D_Vertex(0.5, 0, -1.5,  0, 0)
        S3D_Vertex(0.5, 0, 0.25,  0, 0)
        S3D_Vertex(0.5, 0, -1.5,  0, 0)
        S3D_Vertex(2.0, 0.25, -2, 0, 0)
        ' left wing.
        S3D_Color(64, 128, 208)
        S3D_Vertex(-0.5, 0, 0.25,  0, 0)
        S3D_Vertex(-2.0, 0.25, -2, 0, 0)
        S3D_Vertex(-0.5, 0, -1.5,  0, 0)
        S3D_Vertex(-0.5, 0, 0.25,  0, 0)
        S3D_Vertex(-0.5, 0, -1.5,  0, 0)
        S3D_Vertex(-2.0, 0.25, -2, 0, 0)
    S3D_End()
S3D_EndMesh()

' Player bullet model, probably needs volume ...
bulletMesh = S3D_BeginMesh()
    S3D_Color(255, 208, 96)
    S3D_Begin(S3D_QUADS)
        S3D_Vertex(0, 0, 0.5,  0, 0)
        S3D_Vertex(0.5, 0, 0,  0, 0)
        S3D_Vertex(0, 0, -1.5, 0, 0)
        S3D_Vertex(-0.5, 0, 0, 0, 0)
        S3D_Vertex(-0.5, 0, 0, 0, 0)
        S3D_Vertex(0, 0, -1.5, 0, 0)
        S3D_Vertex(0.5, 0, 0,  0, 0)
        S3D_Vertex(0, 0, 0.5,  0, 0)
    S3D_End()
S3D_EndMesh()

' Player.
ship = []
ship.mesh = shipMesh
ship.pos = []
ship.pos[0] = 0
ship.pos[1] = -2
ship.pos[2] = 0
ship.box = dim(6)
ship.rot = []
ship.rot.yaw = 0
ship.rot.pitch = 0
ship.rot.roll = 0
ship.dir = [0, 0, 0, 0]
ship.push = fill(0, 3)
ship.shootTimer = 0

' Player bullets.
bullets = []

' Camera.
cam = []
cam.pos = []
cam.pos[0] = 0
cam.pos[1] = 0
cam.pos[2] = 0
cam.rot = []
cam.rot.yaw = 0
cam.rot.pitch = 0
cam.rot.roll = 0
cam.followX = 0.75

' X and y limitations of player.
xMin = -15
xMax = 15
yMin = -15
yMax = -1

' Add 1000 obstacles and sort by z.
obstacles = []
for i = 1 to 1000
    select rnd(3)
        case 0  obstacles[sizeof(obstacles)] = RedObstacle(round(rnd()*40 - 20), round(5 + rnd()*2000))
        case 1  obstacles[sizeof(obstacles)] = GreenObstacle(round(rnd()*40 - 20), round(5 + rnd()*2000))
        case 2  obstacles[sizeof(obstacles)] = BlueObstacle(round(rnd()*40 - 20), round(5 + rnd()*2000))
    endsel
next
qsort(obstacles, function(a, b);  return a.pos[2] - b.pos[2];  endfunc)
' Used for optimizing drawing and collision checks.
minVisObstacle = 0
maxVisObstacle = unset

' Forward vector.
fwdVec = [0, 0, 1, 0]
' For computations using s3d.
srcVec = [0, 0, 0, 0]
dstVec = [0, 0, 0, 0]

' Screen flash effect when ship hits an obstacle.
hitParam = 0

' For fps output.
lastClock = clock()

while not keydown(KEY_ESCAPE, true)
    c = clock()
    dt = (c - lastClock)/1000
    lastClock = c
    
    ' Change direction.
    dYaw = 0
    dPitch = 0
    if keydown(KEY_LEFT)  dYaw = dYaw - 45
    if keydown(KEY_RIGHT)  dYaw = dYaw + 45
    if keydown(KEY_UP)  dPitch = dPitch + 30*ctrlYScale
    if keydown(KEY_DOWN)  dPitch = dPitch - 30*ctrlYScale
    ship.rot.yaw = 0.95*ship.rot.yaw + 0.05*dYaw
    ship.rot.pitch = 0.95*ship.rot.pitch + 0.05*dPitch
    ship.rot.roll = 0.95*ship.rot.roll + 0.05*dYaw*0.5
    
    ' Get ships direction as a vector.
    S3D_ClearTransformation()
    ' A window aspect effect is applied in ClearTransformation, so we have to revert it to get
    ' proper coordinates from TransformVector. I have ... NO idea of why I did it like that. I'll
    ' fix that in the next n7 release.
    S3D_Scale(winAspect, 1, 1)
    S3D_RotateY(rad(ship.rot.yaw))
    S3D_RotateX(rad(ship.rot.pitch))
    S3D_RotateZ(rad(ship.rot.roll))
    S3D_TransformVector(ship.dir, fwdVec)
    VectorNormalize(ship.dir)
    
    ' Uhm, slow down when close to x and y limits.
    dxMul = 1;  dyMul =1
    if ship.dir[0] < 0  dxMul = min(ship.pos[0] - xMin, 4)*0.25
    elseif ship.dir[0] > 0  dxMul = min(xMax - ship.pos[0], 4)*0.25
    if ship.dir[1] < 0  dyMul = min(ship.pos[1] - yMin, 4)*0.25
    elseif ship.dir[1] > 0  dyMul = min(yMax - ship.pos[1], 4)*0.25

    ' Move.
    ship.pos[0] = max(min(ship.pos[0] + ship.dir[0]*0.25*dxMul + ship.push[0], xMax), xMin)
    ship.pos[1] = max(min(ship.pos[1] + ship.dir[1]*0.5*dyMul + ship.push[1], yMax), yMin)
    ship.pos[2] = ship.pos[2] + 0.1 + ship.push[2]
    
    ' Update push, collision effect.
    for i = 0 to 2
        if ship.push[i] < 0  ship.push[i] = min(ship.push[i] + 0.01, 0)
        elseif ship.push[i] > 0  ship.push[i] = max(ship.push[i] - 0.01, 0)
    next

    hitParam = max(hitParam - 0.025, 0)
    
    ' Update bounding box.
    ship.box[0] = ship.pos[0] - 1.25 ' 2
    ship.box[3] = ship.pos[0] + 1.25 ' 2
    ship.box[1] = ship.pos[1] - 0.25
    ship.box[4] = ship.pos[1] + 0.25
    ship.box[2] = ship.pos[2] - 0.75 ' 1.25
    ship.box[5] = ship.pos[2] + 1 '2

    ' Shoot.
    ship.shootTimer = max(ship.shootTimer - 1, 0)    
    if keydown(KEY_SPACE) and ship.shootTimer <= 0
        ship.shootTimer = 15
        spd = 1

        ' Add two bullets with positions relative to the player ship.
        S3D_ClearTransformation()
        S3D_Scale(winAspect, 1, 1)
        S3D_Translate(ship.pos[0], ship.pos[1], ship.pos[2])
        S3D_RotateY(rad(ship.rot.yaw))
        S3D_RotateX(rad(ship.rot.pitch))
        S3D_RotateZ(rad(ship.rot.roll))
        for x = -0.75 to 0.75 step 1.5
            srcVec[0] = x;  srcVec[1] = 0; srcVec[2] = 1; srcVec[3] = 1
            bullet = [
                mesh: bulletMesh,
                pos: dim(3),
                rot: [yaw: ship.rot.yaw, pitch: ship.rot.pitch, roll: ship.rot.roll],
                mvec: [ship.dir[0]*spd, ship.dir[1]*spd, ship.dir[2]*spd]]
            S3D_TransformVector(bullet.pos, srcVec)
            bullets[sizeof(bullets)] = bullet  
        next
    endif
    
    ' Check for collisions between ship and obstacles.
    if typeof(maxVisObstacle)
        i = minVisObstacle
        xmin = ship.box[0]
        xmax = ship.box[3]
        ymin = ship.box[1]
        ymax = ship.box[4]
        zmin = ship.box[2]
        zmax = ship.box[5]
        px = 0;  py = 0        
        while i < maxVisObstacle and i < sizeof(obstacles)
            o = obstacles[i]
            if zmax > o.box[2] and zmin < o.box[5] and
                    ymax > o.box[1] and ymin < o.box[4] and
                    xmax > o.box[0] and xmin < o.box[3]
                dRight = xmax - o.box[0]
                dLeft = o.box[3] - xmin
                dDown = ymax - o.box[1]
                if hitParam <= 0  hitParam = 1
                ' Find the smallest valid distance to the obstacle in the three directions and push
                ' the ship in the opposite direction.
                if dLeft > 0 and dRight > 0
                    if dLeft < dRight
                        if dDown > 0 and dDown < dLeft  py = py -1
                        else  px = px + 1
                    else
                        if dDown > 0 and dDown < dRight  py = py - 1
                        else  px = px - 1
                    endif
                elseif dLeft > 0
                    if dDown > 0 and dDown < dLeft  py = py - 1
                    else  px = px + 1
                elseif dRight > 0
                    if dDown > 0 and dDown < dRight  py = py - 1
                    else  px = px - 1
                elseif dDown > 0  py = py -1
            endif
            i = i + 1
        wend
        if px  ship.push[0] = sgn(px)*0.2
        if py  ship.push[1] = sgn(py)*0.15
    endif

    ' Position camera.
    cam.pos[0] = cam.followX*ship.pos[0]
    cam.pos[1] = 0.6*ship.pos[1] - 2
    cam.pos[2] = ship.pos[2] - 7.5
    
    ' Update bullets.
    i = 0
    while i < sizeof(bullets)
        b = bullets[i]
        VectorAdd(b.pos, b.mvec)
        if b.pos[1] >= 0 or b.pos[2] > cam.pos[2] + renderDepth  free key bullets, i
        else  i = i + 1
    wend

    ' Draw.
    S3D_Clear()
    S3D_RotateZ(rad(ship.rot.roll*0.5))
    S3D_Translate(-cam.pos[0], -cam.pos[1], -cam.pos[2])

    DrawObject(ship)    
    
    foreach b in bullets  DrawObject(b)
    
    S3D_Color(255, 255, 255)
    i = minVisObstacle
    while i < sizeof(obstacles)
        o = obstacles[i]
        dz = o.pos[2] - cam.pos[2]
        if dz < -10  minVisObstacle = i + 1
        if dz > renderDepth + 10
            maxVisObstacle = i
            break
        endif
        S3D_Push()
            S3D_Translate(o.pos[0], o.pos[1], o.pos[2])
            S3D_Mesh(o.mesh, 0)
        S3D_Pop()
        i = i + 1
    wend
    
    S3D_RenderFog(48, 96, 128, false)
    
    if hitParam > 0
        set color 192, 0, 0, hitParam*255
        cls
    endif
    
    set color 255, 255, 255
    set caret 4, 4
    wln "dx:      " + str(ship.dir[0], 0, 2)
    wln "dy:      " + str(ship.dir[1], 0, 2)
    wln "dz:      " + str(ship.dir[2], 0, 2)
    wln
    wln "bullets: " + sizeof(bullets)
    wln "min obs: " + minVisObstacle
    wln "max obs: " + maxVisObstacle
    wln
    wln "fps:     " + floor(1/dt)
    
    redraw
    fwait 60
wend

' DrawObject
' ----------
function DrawObject(o)
    ' Object.
    S3D_Push()
        S3D_Color(255, 255, 255)
        S3D_Translate(o.pos[0], o.pos[1], o.pos[2])
        S3D_RotateY(rad(o.rot.yaw))
        S3D_RotateX(rad(o.rot.pitch))
        S3D_RotateZ(rad(o.rot.roll))
        S3D_Mesh(o.mesh, 0)
    S3D_Pop()
    ' Shadow.
    'S3D_SetDepthBuffer(S3D_Z_BUFFER_READ)
    S3D_Push()
        S3D_Color(0, 0, 0)
        S3D_Translate(o.pos[0], 0, o.pos[2])
        S3D_Scale(1, 0, 1)
        S3D_RotateY(rad(o.rot.yaw))
        S3D_RotateX(rad(o.rot.pitch))
        S3D_RotateZ(rad(o.rot.roll))
        S3D_Mesh(o.mesh, 0)
    S3D_Pop()
    'S3D_SetDepthBuffer(S3D_Z_BUFFER)    
endfunc

' VectorNormalize
' ---------------
function VectorNormalize(v)
    k = 1/sqr(v[0]*v[0] + v[1]*v[1] + v[2]*v[2])
    v[0] = v[0]*k;  v[1] = v[1]*k;  v[2] = v[2]*k
endfunc

' VectorAdd
' ---------
function VectorAdd(dst, src)
    dst[0] = dst[0] + src[0]
    dst[1] = dst[1] + src[1]
    dst[2] = dst[2] + src[2]
endfunc

' BoxMesh
' -------
function BoxMesh(xSize, ySize, zSize, r, g, b)
    hx = xSize*0.5
    hz = zSize*0.5
    m = S3D_BeginMesh()
        S3D_Begin(S3D_QUADS)
            ' Bottom face.
            S3D_Color(r*0.5, g*0.5, b*0.5)
            S3D_Vertex(hx, 0, -hz,  1, 0)
            S3D_Vertex(hx, 0, hz,   1, 1)
            S3D_Vertex(-hx, 0, hz,  0, 1)
            S3D_Vertex(-hx, 0, -hz, 0, 0)
            ' Top face.
            S3D_Color(r*1.25, g*1.25, b*1.25)            
            S3D_Vertex(hx, -ySize, hz,   1, 1)
            S3D_Vertex(hx, -ySize, -hz,  1, 0)    
            S3D_Vertex(-hx, -ySize, -hz, 0, 0)
            S3D_Vertex(-hx, -ySize, hz,  0, 1)
            ' Back face.
            S3D_Color(r*0.5, g*0.5, b*0.5)
            S3D_Vertex(hx, 0, hz,       1, 1)
            S3D_Vertex(hx, -ySize, hz,  1, 0)
            S3D_Vertex(-hx, -ySize, hz, 0, 0)
            S3D_Vertex(-hx, 0, hz,      0, 1)
            ' Front face.
            S3D_Color(r, g, b)
            S3D_Vertex(hx, -ySize, -hz,  1, 0)
            S3D_Vertex(hx, 0, -hz,       1, 1)
            S3D_Vertex(-hx, 0, -hz,      0, 1)
            S3D_Vertex(-hx, -ySize, -hz, 0, 0)
            ' Left face.
            S3D_Color(r*0.75, g*0.75, b*0.75)
            S3D_Vertex(-hx, 0, hz,       1, 1)
            S3D_Vertex(-hx, -ySize, hz,  0, 1)
            S3D_Vertex(-hx, -ySize, -hz, 0, 0)
            S3D_Vertex(-hx, 0, -hz,      1, 0)
            ' Right face.
            S3D_Vertex(hx, 0, -hz,      1, 0)
            S3D_Vertex(hx, -ySize, -hz, 0, 0)
            S3D_Vertex(hx, -ySize, hz,  0, 1)
            S3D_Vertex(hx, 0, hz,       1, 1)        
        S3D_End()
    S3D_EndMesh()
    return m
endfunc

' Obstacle
' --------
function Obstacle(mesh, x, y, z, w, h, d)
    o = [
        mesh: mesh,
        pos: [x, y, z],
        box: [x - w*0.5, y - h, z - d*0.5, x + w*0.5, y, z + d*0.5]]
    return o
endfunc

' RedObstacle
' -----------
function RedObstacle(x, z)
    return Obstacle(vRedObstacleMesh, x, 0, z, 5, 2.5, 5)
endfunc

' GreenObstacle
' -------------
function GreenObstacle(x, z)
    return Obstacle(vGreenObstacleMesh, x, 0, z, 4, 5, 4)
endfunc

' BlueObstacle
' ------------
function BlueObstacle(x, z)
    return Obstacle(vBlueObstacleMesh, x, 0, z, 2, 13, 2)
endfunc

You will notice a flicker in the graphics. It's a bug when rendering solid color 3d polygons. By mistake I'm casting the z values at the vertices to integers and then interpolate those values over the polygons. I'll have it fixed in the next version of n7. I want to fix some more things too that would, among all, allow me to "cast shadows" not only on the ground but also on the obstacles. On the other hand, Star Fox didn't have that ...
Reply
#8
(09-12-2025, 04:30 AM)Marcus Wrote:
(09-12-2025, 12:18 AM)johnno56 Wrote: That is SO cool!! Very smooth indeed.... Looking forward to shooting and blowing stuff up... Ha... I'll even dust of my joystick... Moo Ha Ha Ha...

Do you play these kind of games with inverted y-axis (press down to look up) or not?

Ha... Never gave that a thought... I just accepted what the game produced... In most cases, point the "nose" down and the background went "up"... etc But that was a long time ago...Back then I used a modified analogue stick with one button... Now I use a stick with heaps of buttons, top hat, slider and multiple triggers... Now... Where are you hiding those aliens? Moo Ha Ha Ha...

(09-12-2025, 06:36 AM)aurel Wrote: shadow of the ship in space ?
hmmm

Shadow? Nice catch! Actually, unless the "ship" was producing its own light, the ship would be virtually invisible to the eye.... After all, as it is so far from a light source, there would be no highlighting for it to be seen... Star Wars and star Trek have got a lot to answer for... lol
Logic is the beginning of wisdom.
Reply
#9
(09-12-2025, 01:22 PM)Marcus Wrote: ...

Code:
'center of the screen
visible wp = width(primary)/2
visible hp = height(primary)/2

Thank you, it's working flawlessly !
Reply
#10
The stuff I've fixed and added to n7 make simple shadow casting work fine:



I render the ship as seen from above on an image and project that image on the ground and the obstacles. Anything that helps with depth perception is important in a game like this.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)