Thread Rating:
  • 2 Vote(s) - 4.5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Star Fox
#21
(09-15-2025, 06:57 PM)johnno56 Wrote: Ok. It's not much of a change but I think it adds a little 'nostalgia' to the demo. Joystick (keyboard still works... lol) and 3 simple sounds.



Enjoy! Big Grin

J


Nice!

Your joystick is analogue, right? 'joyx' and 'joyy' do return floating point values in the range [-1..1]. So how does the joystick work with this modification:

Code:
    ' Change direction.
    dYaw = 0
    dPitch = 0
    'if keydown(KEY_LEFT) or joyx() = -1 dYaw = dYaw - 45
    'if keydown(KEY_RIGHT) or joyx() = 1 dYaw = dYaw + 45
    'if keydown(KEY_UP) or joyy() = -1  dPitch = dPitch + 30*ctrlYScale
    'if keydown(KEY_DOWN) or joyy() = 1  dPitch = dPitch - 30*ctrlYScale
    jx = joyx();  jy = joyy()
    if keydown(KEY_LEFT)  jx = -1
    if keydown(KEY_RIGHT)  jx = 1
    if keydown(KEY_UP)  jy = -1
    if keydown(KEY_DOWN)  jy = 1
    dYaw = jx*45;  dPitch = -jy*30*ctrlYScale

I only have gamepads without analogue sticks, so I can't test it.
Reply
#22
(09-16-2025, 04:45 PM)Marcus wrote Wrote: Your joystick is analogue, right? 'joyx' and 'joyy' do return floating point values in the range [-1..1]. So how does the joystick work with this modification?


I remember the old 'atari style' sticks. The contacts were either on or off. -1, 0 and 1. My stick, depending on how far you move the handle, will produce varying values between -1 and 0; 0 and 1.

The stick needs to be fully moved to register 'movement'. Which means "-1" or "1". So, it is somewhat 'laborious', but it still works. As I stated earlier, the keyboard has a better response... It was just a 'lets see if it will works' kind of deal... lol

I hope that helps...

J

Oh, while I think of it...

The Triangles and Quads that you used for the 'ship', did you have to design (pencil and paper) yourself or did you use something like Blender to export the object? Just curious as to the process...
Logic is the beginning of wisdom.

Live long and prosper.
Reply
#23
I'm good at visualizing 3d figures in my head and simply enter the coordinates, no need for modelling tools or pen and paper Smile

The code snippet I pasted should deal with analogue joystick input, so that if you press your joystick 25% to the right, the ship should move slower in that direction. But maybe it didn't work as expected. Hm, gotta get an analogue controller myself to debug Smile
Reply
#24
"In your head"? Aw man... that says a lot about 'my' skills (or lack of them... lol) I was hoping for a method that could be replicated to create a model of choice... Me... I am a fan of pencil and paper... A physical representation... Your method requires imagination and creativity... *sigh*

In regards to the stick, I wouldn't waste too much effort, on that one... It was just an experiment... I thought that moving the stick slightly would move it 'slower' but it didn't. I had to reduce the angle to at least 30% of the original. When I first tried it, it moved way to fast, and it would only move when the stick movement was at its limit...

On the subject of sticks... Is there an N7 command for detecting the connection of a stick? Just curious...
Logic is the beginning of wisdom.

Live long and prosper.
Reply
#25
My son forgot to take his gamepad with him, xbox-thingy, when he moved out (again). I plugged it in and tried the code for analogue input that I posted yesterday and here it works fine Smile This is the full source code, not just the changed part.

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

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

#win32

constant RES = 480
' Shadow settings.
constant SHD_OFFS = 0.01
constant SHD_ALPHA = 64
constant SHD_RES = 16

visible pew = loadsound("pew02.wav")
visible bang = loadsound("explode.wav")
visible thud = loadsound("thud.wav")

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

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

randomize 382

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

'while not mousebutton(0, true) wait 100

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

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_Color3(208, 208, 208)
        ' right side.
        S3D_Vertex3(0, 0, 2)
        S3D_Vertex3(0.5, 0.125, -1.25)
        S3D_Vertex3(0, -0.25, -1)
        ' left side.
        S3D_Vertex3(0, 0, 2)
        S3D_Vertex3(0, -0.25, -1)
        S3D_Vertex3(-0.5, 0.125, -1.25)
        ' back.
        S3D_Color3(255, 160, 0)
        S3D_Vertex3(0, -0.25, -1)
        S3D_Vertex3(0.5, 0.125, -1.25)
        S3D_Vertex3(-0.5, 0.125, -1.25)
        ' bottom.
        S3D_Color3(128, 128, 128)
        S3D_Vertex3(0, 0, 2)
        S3D_Vertex3(-0.5, 0.125, -1.25)
        S3D_Vertex3(0.5, 0.125, -1.25)
        ' right wing.
        S3D_Color3(64, 128, 208)
        S3D_Vertex3(0.5, 0, 0.25)
        S3D_Vertex3(2.0, 0.25, -2)
        S3D_Vertex3(0.5, 0, -1.5)
        S3D_Vertex3(0.5, 0, 0.25)
        S3D_Vertex3(0.5, 0, -1.5)
        S3D_Vertex3(2.0, 0.25, -2)
        ' left wing.
        S3D_Color3(64, 128, 208)
        S3D_Vertex3(-0.5, 0, 0.25)
        S3D_Vertex3(-2.0, 0.25, -2)
        S3D_Vertex3(-0.5, 0, -1.5)
        S3D_Vertex3(-0.5, 0, 0.25)
        S3D_Vertex3(-0.5, 0, -1.5)
        S3D_Vertex3(-2.0, 0.25, -2)
    S3D_End()
S3D_EndMesh()

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

' Something to shoot at.
visible vTargetMesh = S3D_BeginMesh()
    xz = []
    res = 6;  r = 2;  h = 3
    for i = 0 to res - 1  xz[sizeof(xz)] = [sin(i*2*PI/res)*r, cos(i*2*PI/res)*r]
    S3D_Begin(S3D_TRIANGLES)
        for i = 0 to res - 1
            j = (i + 1)%res
            if i%2 = 0  S3D_Color3(192, 192, 192)
            else  S3D_Color3(224, 32, 0)
            S3D_Vertex3(0, -h*0.5, 0)
            S3D_Vertex3(xz[i][0], 0, xz[i][1])
            S3D_Vertex3(xz[j][0], 0, xz[j][1])
            if i%2 = 1  S3D_Color3(192, 192, 192)
            else  S3D_Color3(224, 32, 0)
            S3D_Vertex3(0, h*0.5, 0)
            S3D_Vertex3(xz[j][0], 0, xz[j][1])
            S3D_Vertex3(xz[i][0], 0, xz[i][1])
        next
    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.shd = []
ship.shd.img = createimage(5.75*SHD_RES, 5.75*SHD_RES)
ship.shd.scale = 0.78
ship.shd.size = 5.75
ship.shootTimer = 0
set image ship.shd.img
set color 0, 0, 0, 0
cls true
set image primary

' 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.
visible vObstacles = []
for i = 1 to 1000
    select rnd(3)
        case 0  vObstacles[sizeof(vObstacles)] = RedObstacle(rnd()*40 - 20, 5 + rnd()*2000)
        case 1  vObstacles[sizeof(vObstacles)] = GreenObstacle(rnd()*40 - 20, 5 + rnd()*2000)
        case 2  vObstacles[sizeof(vObstacles)] = BlueObstacle(rnd()*40 - 20, 5 + rnd()*2000)
    endsel
next
qsort(vObstacles, function(a, b);  return a.pos[2] - b.pos[2];  endfunc)
' Used for optimizing drawing and collision checks.
visible vMinVisObstacle = 0
visible vMaxVisObstacle = unset

' Add some targets for the player to shoot at.
visible vTargets = []
' All targets can share shadow image.
visible vTargetShadowImage = createimage(4.4*SHD_RES, 4.4*SHD_RES)
set image vTargetShadowImage
set color 0, 0, 0, 0
cls true
set image primary
for i = 1 to 200  vTargets[sizeof(vTargets)] = Target(rnd()*30 - 15, -1.5 - rnd()*15, 50 + rnd()*2000)
qsort(vTargets, function(a, b);  return a.pos[2] - b.pos[2];  endfunc)
visible vMinVisTarget = 0
visible vMaxVisTarget = 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) or joyx() = -1 dYaw = dYaw - 45
    'if keydown(KEY_RIGHT) or joyx() = 1 dYaw = dYaw + 45
    'if keydown(KEY_UP) or joyy() = -1   dPitch = dPitch + 30*ctrlYScale
    'if keydown(KEY_DOWN) or joyy() = 1  dPitch = dPitch - 30*ctrlYScale
    jx = joyx();  jy = joyy()
    if keydown(KEY_LEFT)  jx = -1
    if keydown(KEY_RIGHT)  jx = 1
    if keydown(KEY_UP)  jy = -1
    if keydown(KEY_DOWN)  jy = 1
    dYaw = jx*45;  dPitch = -jy*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()
    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) or joybutton(0) = 1) and ship.shootTimer <= 0
        play sound pew
        ship.shootTimer = 15
        spd = 1

        ' Add two bullets with positions relative to the player ship.
        S3D_ClearTransformation()
        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],
                box: dim(6),
                shd: unset]
            S3D_TransformVector(bullet.pos, srcVec)
            bullet.box[0] = bullet.pos[0] - 0.5
            bullet.box[1] = bullet.pos[1] - 0.5
            bullet.box[2] = bullet.pos[2] - 1.5
            bullet.box[3] = bullet.pos[0] + 0.5
            bullet.box[4] = bullet.pos[1] + 0.5
            bullet.box[5] = bullet.pos[2] + 0.5
            bullets[sizeof(bullets)] = bullet
        next
    endif
        
    ' Check for collisions between ship and obstacles.
    if typeof(vMaxVisObstacle)
        i = vMinVisObstacle
        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 < vMaxVisObstacle and i < sizeof(vObstacles)
            o = vObstacles[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
                    play sound thud
                endif
                ' 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] + vRenderDepth
            free key bullets, i
        else
            bb = b.box;  bp = b.pos
            bb[0] = bp[0] - 0.5
            bb[1] = bp[1] - 0.5
            bb[2] = bp[2] - 1.5
            bb[3] = bp[0] + 0.5
            bb[4] = bp[1] + 0.5
            bb[5] = bp[2] + 0.5
            hit = false
            j = vMinVisTarget
            while j < vMaxVisTarget and j < sizeof(vTargets)
                t = vTargets[j]
                if BoxesOverlap(bb, t.box)
                    play sound bang
                    hit = true
                    free key vTargets, j
                else
                    j = j + 1
                endif
            wend
            if hit
                free key bullets, i
            else
                i = i + 1
            endif
        endif
    wend

    set color 48, 96, 128
    cls
    
    ' Draw.
    S3D_Clear()
    S3D_RotateZ(rad(ship.rot.roll*0.5))
    S3D_Translate(-cam.pos[0], -cam.pos[1], -cam.pos[2])

    ' Obstacles.
    i = vMinVisObstacle
    while i < sizeof(vObstacles)
        o = vObstacles[i]
        dz = o.pos[2] - cam.pos[2]
        if dz < -10  vMinVisObstacle = i + 1
        if dz > vRenderDepth + 10
            vMaxVisObstacle = 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
    
    ' Targets.
    i = vMinVisTarget
    while i < sizeof(vTargets)
        t = vTargets[i]
        dz = t.pos[2] - cam.pos[2]
        if dz < -10  vMinVisTarget = i + 1
        if dz > vRenderDepth + 10
            vMaxVisTarget = i
            break
        endif
        t.rot.yaw = (t.rot.yaw + t.dyaw)%360
        DrawObject(t)
        i = i + 1
    wend

    DrawObject(ship)    

    foreach b in bullets  DrawObject(b)
  
    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: " + vMinVisObstacle
    'wln "max obs: " + vMaxVisObstacle
    'wln
    wln "joyx: " + str(jx, 1, 2)
    wln "joyy: " + str(jy, 1, 2)
    wln "fps:  " + floor(1/dt)
    
    ' Draw ship shadow.
    'x = width(primary) - width(vTargetShadowImage) - 4
    'set color 255, 0, 255
    'draw rect x, 4, width(vTargetShadowImage), height(vTargetShadowImage), true
    'set color 255, 255, 255
    'draw image vTargetShadowImage, x, 4

    redraw
    fwait 60
wend

' DrawObject
' ----------
function DrawObject(o)
    ' Object.
    S3D_Push()
        S3D_Color3(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?
    if o.shd
        ' Render shadow, experimental stuff.
        set image o.shd.img, false
        set color 0, 0, 0, 0
        cls true
        S3D_Push()
        S3D_SetView(o.shd.img, rad(10), 0.1, 50)
        S3D_ClearTransformation()
        S3D_SetDepthBuffer(S3D_NONE)
        S3D_Color3(0, 0, 0)
        S3D_Translate(0, 0, 25)
        S3D_Scale(o.shd.scale, o.shd.scale, o.shd.scale)
        S3D_RotateX(rad(90))
        S3D_RotateY(rad(o.rot.yaw))
        S3D_RotateX(rad(o.rot.pitch))
        S3D_RotateZ(rad(o.rot.roll))
        S3D_Mesh(o.mesh, 0)
        S3D_SetDepthBuffer(S3D_Z_BUFFER)
        S3D_SetView(primary, rad(60), 0.1, vRenderDepth)
        set image primary
        S3D_Pop()

        so = SHD_OFFS
        hs = o.shd.size*0.5
        xmin = o.pos[0] - hs
        xmax = o.pos[0] + hs
        zmin = o.pos[2] - hs
        zmax = o.pos[2] + hs
        ymin = o.box[1]
        S3D_Texture(o.shd.img)
        S3D_Color4(255, 255, 255, SHD_ALPHA)
        ' Ground.
        S3D_Begin(S3D_QUADS)
            S3D_Vertex5(xmin, 0, zmax, 0, 0)
            S3D_Vertex5(xmax, 0, zmax, 1, 0)
            S3D_Vertex5(xmax, 0, zmin, 1, 1)
            S3D_Vertex5(xmin, 0, zmin, 0, 1)
        S3D_End()
        ' Obstacles
        if typeof(vMaxVisObstacle)
            i = vMinVisObstacle
            S3D_SetDepthBuffer(S3D_Z_BUFFER_READ)
            S3D_Begin(S3D_QUADS)
            while i < vMaxVisObstacle and i < sizeof(vObstacles)
                b = vObstacles[i].box
                ' Calculate intersection between shadow and obstacle.
                x0 = max(xmin, b[0] - so)
                x1 = min(xmax, b[3] + so)
                z0 = max(zmin, b[2] - so)
                z1 = min(zmax, b[5] + so)                
                if not (z1 < b[2] or z0 >= b[5] or x0 >= b[3] or x1 < b[0] or ymin > b[1])
                    umin = (x0 - xmin)/(xmax - xmin)
                    umax = (x1 - xmin)/(xmax - xmin)
                    vmin = 1 - (z0 - zmin)/(zmax - zmin)
                    vmax = 1 - (z1 - zmin)/(zmax - zmin)
                    y = b[1] - so
                    S3D_Color4(255, 255, 255, SHD_ALPHA)
                    S3D_Vertex5(x0, y, z1, umin, vmax)
                    S3D_Vertex5(x1, y, z1, umax, vmax)
                    S3D_Vertex5(x1, y, z0, umax, vmin)
                    S3D_Vertex5(x0, y, z0, umin, vmin)
                    if z0 < b[2]
                        'S3D_Color4(255, 255, 255, SHD_ALPHA*0.25)
                        S3D_Vertex5(x0, y, z0, umin, vmin)
                        S3D_Vertex5(x1, y, z0, umax, vmin)
                        S3D_Vertex5(x1, 0, z0, umax, vmin)
                        S3D_Vertex5(x0, 0, z0, umin, vmin)
                    endif
                endif
                i = i + 1
            wend
            S3D_End()        
            S3D_SetDepthBuffer(S3D_Z_BUFFER)
        endif
        S3D_Texture(unset)
    endif
    ' 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_Color3(r*0.5, g*0.5, b*0.5)
            S3D_Vertex5(hx, 0, -hz,  1, 0)
            S3D_Vertex5(hx, 0, hz,   1, 1)
            S3D_Vertex5(-hx, 0, hz,  0, 1)
            S3D_Vertex5(-hx, 0, -hz, 0, 0)
            ' Top face.
            S3D_Color3(r*1.25, g*1.25, b*1.25)            
            S3D_Vertex5(hx, -ySize, hz,   1, 1)
            S3D_Vertex5(hx, -ySize, -hz,  1, 0)    
            S3D_Vertex5(-hx, -ySize, -hz, 0, 0)
            S3D_Vertex5(-hx, -ySize, hz,  0, 1)
            ' Back face.
            S3D_Color3(r*0.5, g*0.5, b*0.5)
            S3D_Vertex5(hx, 0, hz,       1, 1)
            S3D_Vertex5(hx, -ySize, hz,  1, 0)
            S3D_Vertex5(-hx, -ySize, hz, 0, 0)
            S3D_Vertex5(-hx, 0, hz,      0, 1)
            ' Front face.
            S3D_Color3(r, g, b)
            S3D_Vertex5(hx, -ySize, -hz,  1, 0)
            S3D_Vertex5(hx, 0, -hz,       1, 1)
            S3D_Vertex5(-hx, 0, -hz,      0, 1)
            S3D_Vertex5(-hx, -ySize, -hz, 0, 0)
            ' Left face.
            S3D_Color3(r*0.75, g*0.75, b*0.75)
            S3D_Vertex5(-hx, 0, hz,       1, 1)
            S3D_Vertex5(-hx, -ySize, hz,  0, 1)
            S3D_Vertex5(-hx, -ySize, -hz, 0, 0)
            S3D_Vertex5(-hx, 0, -hz,      1, 0)
            ' Right face.
            S3D_Vertex5(hx, 0, -hz,      1, 0)
            S3D_Vertex5(hx, -ySize, -hz, 0, 0)
            S3D_Vertex5(hx, -ySize, hz,  0, 1)
            S3D_Vertex5(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

' Target
' ------
function Target(x, y, z)
    t = []
    t.mesh = vTargetMesh
    t.pos = [x, y, z]
    t.box = [x - 2, y - 1.5, z - 2, x + 2, y + 1.5, z + 2]
    t.rot = [yaw: rnd()*360, pitch: 0, roll: 0]
    t.shd = [img: vTargetShadowImage, scale: 1, size: 4.4]
    t.dyaw = rnd()*12 - 6
    return t
endfunc

' BoxesOverlap
' ------------
function BoxesOverlap(a, b)
    return not (a[2] > b[5] or b[2] > a[5] or a[0] > b[3] or b[0] > a[3] or a[1] > b[4] or b[1] > a[4])
endfunc

Here I output that 'joyx' and 'joyy' values and as you can see the ship moves slower when I just press the controller slightly.




There's currently no way to detect whether a controller is plugged in or not. When the window is created I ask to receive events for joystick id 1, then I forward any such events to n7. If there's no controller plugged in when the window is created, the program won't be able to read joystick input. So it's better to write code that works for both joysticks and keyboard .
Reply
#26
Ah, yes. I see what you've done there... Better way of coding the stick and much smoother. Cool... Thank you! Gotta love the "pew pew"!
Logic is the beginning of wisdom.

Live long and prosper.
Reply
#27
As usual, leaving me with my mouth open, not at all, very good.
Reply
#28


Sorry for not posting in a while, been a couple of busy weeks.

This version of the program would look like crap without the latest, unreleased, version of n7. I've just changed the rasterizer for un-textured polygons so that it writes perspective correct z values to the depth buffer. Without that, the ground would look really, really weird - gradients going all over the place.

While testing this program I managed to make the n7 runtime enter a state where it ran SUPER slowly (fps dropped to 10). The runtime needs some memory just for executing, and if there's too little memory left (close to trigger "garbage collecting" but not quite there yet), things get slow. So I shall dive into the darkness of my memory managment code and fix this issue before releasing a new version of n7. In theory the solution is easy: don't wait with garbage collecting until there's NO memory left, do it when there's like 25% left, and increase the heap size if not much memory could be released. But in practice, it will most likely be a nightmare to fix Smile
Reply
#29
This might sound like a stupid question... Garbage? I am not all that familiar with this 3D type of stuff... Garbage and memory... In layman's terms, would you be so kind as to explain the relationship? What part of the process is using, or requiring, the most memory?

If memory (no pun intended) serves correctly, Star Fox, was from the early 90's and the average home PC ran with anything up to 8mb of ram running Win3.1 and DOS5. The SNES, at the time, has 128kb of work ram and 64kb of video ram.

I am totally confused... 30 years later, our PC's, now have built-in memory exceeding 8gb of ram with CPU's that run WAY faster... Either those programmers of yester-year were Wizards or there is something else that does not make sense... In 1993 the game ran flawlessly running with either 128kb or 4-8mb of ram... and 'we' have memory issues today? I wander what has changed? lol Not a judgement or criticism, just curious... I miss the old days... Simpler times...
Logic is the beginning of wisdom.

Live long and prosper.
Reply
#30
(10-18-2025, 09:35 AM)johnno56 Wrote: This might sound like a stupid question... Garbage? I am not all that familiar with this 3D type of stuff... Garbage and memory... In layman's terms, would you be so kind as to explain the relationship? What part of the process is using, or requiring, the most memory?

If memory (no pun intended) serves correctly, Star Fox, was from the early 90's and the average home PC ran with anything up to 8mb of ram running Win3.1 and DOS5. The SNES, at the time, has 128kb of work ram and 64kb of video ram.

I am totally confused... 30 years later, our PC's, now have built-in memory exceeding 8gb of ram with CPU's that run WAY faster... Either those programmers of yester-year were Wizards or there is something else that does not make sense... In 1993 the game ran flawlessly running with either 128kb or 4-8mb of ram... and 'we' have memory issues today? I wander what has changed? lol  Not a judgement or criticism, just curious... I miss the old days... Simpler times...


There's actually nothing that requires much memory. It's just that n7 is a language that uses a "garbage collector" to deal with "lost memory". Whenever the running program needs memory for something, like a new bullet in this game, it asks the "memory manager" for a slice of memory. The memory manager is lazy and doesn't keep track of what old slices of memory are still in actual use by the program; it just gives the running program a new slice from the big memory cake. If the memory manager can't find a slice of the requested size, it performs garbage collecting. By examining all the variables in the running program, it determines which memory slices are still actually used. All un-used memory slices are made available again for the program. If the memory manager still can't find a slice of memory, it simply creates another cake.

The slowdown occurred when there was just a tiny slice of memory left but before the garbage collector was invoked. So ... I need to do change the memory manager so that it doesn't wait with garbage collecting until it's actually out of cake.

The default memory cake size in an n7 program is 16MB but can be made smaller or larger via the "mem" flag. If you look at the source code of NED, you can see that it requests a cake size of 64MB (#mem64000000). That way the garbage collector is invoked less often.

Cake is good.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)