Thread Rating:
  • 2 Vote(s) - 4.5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Star Fox
#31
Ah... Cake!

So... Increase the size of the cake and the potential of a "no more cake" error virtually disappears... but, at the cost of speed, because the computer has to check to see how much cake is "free" to eat every time it takes a bite... So... Reducing the number of objects or lowering the resolution should improve performance and help remove the need for increased memory but at the cost of image clarity.

Now you're making me hungry.... (insert "tummy rumble" sound here)
Logic is the beginning of wisdom.
Reply
#32
(10-18-2025, 12:42 PM)johnno56 Wrote: Ah... Cake!

So... Increase the size of the cake and the potential of a "no more cake" error virtually disappears... but, at the cost of speed, because the computer has to check to see how much cake is "free" to eat every time it takes a bite... So... Reducing the number of objects or lowering the resolution should improve performance and help remove the need for increased memory but at the cost of image clarity.

Now you're making me hungry.... (insert "tummy rumble" sound here)

It now keeps track of how much cake there's left. When there's just 1/5 cake left, thorough cake investigation is performed and - if necessary- a new cake is baked. This reduces all cake related slowdowns.

If you've downloaded the n7 version released today you can run the latest "star fox" version:

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

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

#win32

constant RES = 480
' Shadow settings.
constant SHD_OFFS = 0.05
constant SHD_ALPHA = 32
constant SHD_RES = 24

' Set to 1 for non-inverted y-axis. I can only play inverted ...
visible vCtrlYScale = -1
visible vRenderDepth = 50
visible vPlayer, vPlayerShadowImage, vBullets = fill(PlayerBullet(), 64)
visible vCam
visible vFogR = 128, vFogG = 128, vFogB = 192
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)
visible vPlayerMesh
visible vBulletMesh
visible vTargetMesh
visible vTreeMesh
visible vObstacles = []
visible vMinVisObstacle, vMaxVisObstacle
visible vTargets = []
visible vTargetShadowImage
visible vMinVisTarget, vMaxVisTarget
visible vSkyImage
visible vFwdVec = [0, 0, 1, 0]

randomize 382

set window "flight test", RES*min(screenw()/screenh(), 2), RES, false
set redraw off

CreateAssets()

S3D_SetPerspectiveCorrection(S3D_NORMAL)
SetGameView(0)

' Add 1000 obstacles and sort by z.
clear vObstacles
vMinVisObstacle = 0
vMaxVisObstacle = unset
for i = 1 to 1500
    do
        select rnd(4)
            case 0  o = RedObstacle(rnd()*50 - 25, 5 + rnd()*3000)
            case 1  o = GreenObstacle(rnd()*50 - 25, 5 + rnd()*3000)
            case 2  o = BlueObstacle(rnd()*50 - 25, 5 + rnd()*3000)
            case 3  o = TreeObstacle(rnd()*50 - 25, 5 + rnd()*3000)           
        endsel
        ok = true
        foreach e in vObstacles  if o.Overlaps(e)
            ok = false
            break
        endif
    until ok
    vObstacles[sizeof(vObstacles)] = o
next
qsort(vObstacles, function(a, b);  return a.pos[2] - b.pos[2];  endfunc)

' Add some targets for the player to shoot at.
clear vTargets
for i = 1 to 300  vTargets[sizeof(vTargets)] = Target(rnd()*30 - 15, -1.5 - rnd()*15, 50 + rnd()*3000)
qsort(vTargets, function(a, b);  return a.pos[2] - b.pos[2];  endfunc)
vMinVisTarget = 0
vMaxVisTarget = unset

' Player and camera.
vPlayer = Player()

' Camera.
vCam = Object()

' For fps output.
lastClock = clock()

' Game loop.
while not keydown(KEY_ESCAPE, true)
    c = clock()
    dt = (c - lastClock)/1000
    lastClock = c

    vPlayer.Update()   

    ' Position camera.
    vCam.SetPos(0.75*vPlayer.pos[0], 0.6*vPlayer.pos[1] - 2, vPlayer.pos[2] - 7.5)
   
    ' Update bullets.
    for i = 0 to sizeof(vBullets) - 1
        b = vBullets[i]
        if b.act
            if b.pos[1] >= 0 or b.pos[2] > vCam.pos[2] + vRenderDepth
                b.act = false
            else
                b.SetPos(b.pos[0] + b.dir[0], b.pos[1] + b.dir[1], b.pos[2] + b.dir[2])
                hit = false
                j = vMinVisTarget
                while j < vMaxVisTarget and j < sizeof(vTargets)
                    t = vTargets[j]
                    if b.Overlaps(t)
                        hit = true
                        free key vTargets, j
                    else
                        j = j + 1
                    endif
                wend
                j = vMinVisObstacle
                while j < vMaxVisObstacle and j < sizeof(vObstacles)
                    o = vObstacles[j]
                    if b.Overlaps(o)
                        hit = true
                        break
                    else
                        j = j + 1
                    endif
                wend
                if hit
                    b.act = false
                endif
            endif
        endif
    next

    set color vFogR, vFogG, vFogB
    cls
   
    ' Draw.
    S3D_Clear()
    S3D_RotateZ(rad(vPlayer.rot.roll*0.5))
    S3D_Translate(0, -vCam.pos[1], 0)
    S3D_Texture(unset)
    S3D_Color(64, 128, 32)
    S3D_SetDepthBuffer(S3D_Z_BUFFER_WRITE)
    S3D_Begin(S3D_QUADS)
        for i = 0 to vRenderDepth - 10 step 10
            S3D_Vertex5(60, 0.05, i + 10,  1, 1)
            S3D_Vertex5(60, 0.05, i,  1, 0)   
            S3D_Vertex5(-60, 0.05, i, 0, 0)
            S3D_Vertex5(-60, 0.05, i + 10,  0, 1)
        next
    S3D_End()
    S3D_SetDepthBuffer(S3D_Z_BUFFER)
    S3D_Color(255, 255, 255)
    S3D_Translate(-vCam.pos[0], 0, -vCam.pos[2])
   
    ' Obstacles.
    i = vMinVisObstacle
    while i < sizeof(vObstacles)
        o = vObstacles[i]
        dz = o.pos[2] - vCam.pos[2]
        if dz < -10  vMinVisObstacle = i + 1
        if dz > vRenderDepth + 10
            vMaxVisObstacle = i
            break
        endif
        o.Draw()
        i = i + 1
    wend
   
    ' Targets.
    i = vMinVisTarget
    while i < sizeof(vTargets)
        t = vTargets[i]
        dz = t.pos[2] - vCam.pos[2]
        if dz < -10  vMinVisTarget = i + 1
        if dz > vRenderDepth + 10
            vMaxVisTarget = i
            break
        endif
        t.Update()
        t.Draw()
        i = i + 1
    wend

    vPlayer.Draw()

    for i = 0 to sizeof(vBullets) - 1  if vBullets[i].act  vBullets[i].Draw()
 
    S3D_RenderFog(vFogR, vFogG, vFogB, true)
 
    ' draw sky.
    SetGameView(0)
    S3D_ClearTransformation()
    S3D_RotateZ(rad(vPlayer.rot.roll*0.5))
    S3D_Translate(-vCam.pos[0]*0.25, -vCam.pos[1], 0)
    S3D_Color(255, 255, 255)
    SetGameView(20)   
    S3D_SetDepthBuffer(S3D_Z_BUFFER_READ)
    S3D_Texture(vSkyImage)
    y = 120*height(vSkyImage)/width(vSkyImage)
    S3D_Begin(S3D_QUADS)
        S3D_Vertex(-60, -y - 1, vRenderDepth + 10, 0, 0)
        S3D_Vertex(60, -y - 1, vRenderDepth + 10, 1, 0)
        S3D_Vertex(60, 0 - 1, vRenderDepth + 10, 1, 1)
        S3D_Vertex(-60, 0 - 1, vRenderDepth + 10, 0, 1)
    S3D_End()
    S3D_Texture(unset)
    S3D_SetDepthBuffer(S3D_Z_BUFFER)
    SetGameView(0)
           
   
    set color 255, 255, 255
    set caret 4, 4
    wln "fps:      " + floor(1/dt)
    wln "targets:  " + (vMaxVisTarget - vMinVisTarget) + " / " + sizeof(vTargets)
    wln "obstacles: " + (vMaxVisObstacle - vMinVisObstacle) + " / " + sizeof(vObstacles)
    wln "bullets:  " + sizeof(vBullets)

    redraw
    fwait 60
wend

' CreateAssets
' ------------
function CreateAssets()
    vRedObstacleMesh = BoxMesh(5, 2.5, 5, 208, 16, 0)
    vGreenObstacleMesh = BoxMesh(4, 5, 4, 16, 208, 0)
    vBlueObstacleMesh = BoxMesh(2, 13, 2, 16, 0, 208)
    vPlayerMesh = PlayerMesh()
    vBulletMesh = BulletMesh()
    vTargetMesh = TargetMesh()
    vTreeMesh = TreeMesh()
   
    vTargetShadowImage = createimage(4.4*SHD_RES, 4.4*SHD_RES)
    set image vTargetShadowImage
    set color 0, 0, 0, 0
    cls true
    set image primary
   
    w = 512; h = 32
    vSkyImage = createimage(w, h)
    set image vSkyImage
    set color vFogR, vFogG, vFogB
    cls
    p = fill(0, 6)
    set color 160, 160, 192
    for i = 1 to 16
        mw = 32 + rnd(64); mh = 16 + rnd(h - 16)
        x = rnd(w - mw)
        p[0] = x;  p[1] = h
        p[2] = x + mw/2;  p[3] = h - mh
        p[4] = x + mw;  p[5] = h
        draw poly p, true
    next
    for y = 0 to h - 1
        set color vFogR, vFogG, vFogB, 255*y/h
        draw line 0, y, w - 1, y
    next
    set image primary
endfunc

' SetGameView
' -----------
function SetGameView(zOffs)
    S3D_SetView(primary, rad(60), 1, vRenderDepth + zOffs)
endfunc

' 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)
        SetGameView(0)
        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, -so, zmax, 0, 0)
            S3D_Vertex5(xmax, -so, zmax, 1, 0)
            S3D_Vertex5(xmax, -so, zmin, 1, 1)
            S3D_Vertex5(xmin, -so, 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)
                if vObstacles[i].flat
                    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.5)
                            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
                endif
                i = i + 1
            wend
            S3D_End()       
            S3D_SetDepthBuffer(S3D_Z_BUFFER)
        endif
        S3D_Texture(unset)
    endif
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

' RedObstacle
' -----------
function RedObstacle(x, z)
    o = Obstacle()
    o.SetMesh(vRedObstacleMesh)
    o.SetBox(-2.5, -2.5, -2.5, 2.5, 0, 2.5)
    o.SetShadable(true)
    o.SetPos(x, 0, z)
    return o
endfunc

' GreenObstacle
' -------------
function GreenObstacle(x, z)
    o = Obstacle()
    o.SetMesh(vGreenObstacleMesh)
    o.SetBox(-2, -5, -2, 2, 0, 2)
    o.SetShadable(true)
    o.SetPos(x, 0, z)
    return o
endfunc

function TreeObstacle(x, z)
    o = Obstacle()
    o.SetMesh(vTreeMesh)
    o.SetBox(-1, -6, -1, 1, 0, 1)
    o.SetShadable(false)
    o.SetPos(x, 0, z)
    o.SetRot(rnd()*90 - 45, 0, 0)
    return o
endfunc

' BlueObstacle
' ------------
function BlueObstacle(x, z)
    o = Obstacle()
    o.SetMesh(vBlueObstacleMesh)
    o.SetBox(-1, -13, -1, 1, 0, 1)
    o.SetShadable(true)
    o.SetPos(x, 0, z)
    return o
endfunc

' Target
' ------
function Target(x, y, z)
    t = Object()
    t.Update = function()
        this.rot.yaw = (this.rot.yaw + this.dyaw)%360
    endfunc   
    t.SetBox(-2, -1.5, -2, 2, 1.5, 2)
    t.SetMesh(vTargetMesh)
    t.SetRot(rnd()*360, 0, 0)
    t.SetShadow(vTargetShadowImage, 1, 4.4)
    t.SetPos(x, y, z)
    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

function PlayerBullet()
    o = Object()
    o.act = false
    return o
endfunc

' Player
' ------
function Player()
    if not typeof(vPlayerShadowImage)
        vPlayerShadowImage = createimage(5.75*SHD_RES, 5.75*SHD_RES)
        set image vPlayerShadowImage
        set color 0, 0, 0, 0
        cls true
        set image primary
    endif
   
    p = Object()
 
    p.xMin = -15
    p.xMax = 15
    p.yMin = -15
    p.yMax = -1
    p.shootTimer = 0
    p.push = fill(0, 3)
   
    p.Update = function()
        ' 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*vCtrlYScale
        if keydown(KEY_DOWN)  dPitch = dPitch - 30*vCtrlYScale
        this.rot.yaw = 0.95*this.rot.yaw + 0.05*dYaw
        this.rot.pitch = 0.95*this.rot.pitch + 0.05*dPitch
        this.rot.roll = 0.95*this.rot.roll + 0.05*dYaw*0.5
       
        ' Get ships direction as a vector.
        this.UpdateDir()
       
        ' Uhm, slow down when close to x and y limits.
        dxMul = 1;  dyMul =1
        if this.dir[0] < 0  dxMul = min(this.pos[0] - this.xMin, 4)*0.25
        elseif this.dir[0] > 0  dxMul = min(this.xMax - this.pos[0], 4)*0.25
        if this.dir[1] < 0  dyMul = min(this.pos[1] - this.yMin, 4)*0.25
        elseif this.dir[1] > 0  dyMul = min(this.yMax - this.pos[1], 4)*0.25
   
        ' Move.
        this.pos[0] = max(min(this.pos[0] + this.dir[0]*0.25*dxMul + this.push[0]*0.2, this.xMax), this.xMin)
        this.pos[1] = max(min(this.pos[1] + this.dir[1]*0.5*dyMul + this.push[1]*0.2, this.yMax), this.yMin)
        this.pos[2] = this.pos[2] + 0.1 + this.push[2]*0.2
       
        ' Update push, collision effect.
        for i = 0 to 2
            if this.push[i] < 0  this.push[i] = min(this.push[i] + 0.05, 0)
            elseif this.push[i] > 0  this.push[i] = max(this.push[i] - 0.05, 0)
        next
       
        ' Update bounding box.
        this.UpdateBox()
   
        ' Shoot.
        this.shootTimer = max(this.shootTimer - 1, 0)   
        if keydown(KEY_SPACE) and this.shootTimer <= 0
            this.shootTimer = 15
            spd = 1
            ' Add two bullets with positions relative to the player ship.
            for x = -0.75 to 0.75 step 1.5
                for i = 0 to sizeof(vBullets) - 1  if not vBullets[i].act  break
                if i < sizeof(vBullets)
                    b = vBullets[i]
                    b.act = true
                    b.SetMesh(vBulletMesh)
                    this.ToWorld(b.pos, x, 0, 1, 1)                   
                    b.SetBox(-0.5, -0.5, -1.5, 0.5, 0.5, 0.5)
                    b.SetRot(this.rot.yaw, this.rot.pitch, this.rot.roll)
                    b.SetPos(b.pos[0], b.pos[1], b.pos[2])
                    b.UpdateDir()
                endif
            next
        endif
           
        ' Check for collisions between ship and obstacles.
        if typeof(vMaxVisObstacle)
            i = vMinVisObstacle
            px = 0;  py = 0       
            while i < vMaxVisObstacle and i < sizeof(vObstacles)
                if this.Overlaps(vObstacles[i])
                    ob = vObstacles[i].Box()
                    dRight = this.tbox[3] - ob[0]
                    dLeft = ob[3] - this.tbox[0]
                    dDown = this.tbox[4] - ob[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  this.push[0] = sgn(px)
            if py  this.push[1] = sgn(py)
        endif
    endfunc
   
    p.SetMesh(vPlayerMesh)
    p.SetBox(-1.25, -0.25, -0.75, 1.25, 0.25, 1)
    p.SetShadow(vPlayerShadowImage, 0.78, 5.75)
       
    return p
endfunc

function Obstacle()
    o = Object()
    o.flat = false
    o.SetShadable = function(v)
        this.flat = v
    endfunc
    return o
endfunc

' Object
' ------
function Object()
    o = []
   
    o.pos = fill(0, 3)
    o.rot = [yaw: 0, pitch: 0, roll: 0]
    o.dir = fill(0, 4)
    o.box = fill(0, 6)
    o.tbox = fill(0, 6)
    o.mesh = unset
    o.rgb = [255, 255, 255]
    o.shd = unset
   
    o.SetMesh = function(mesh)
        this.mesh = mesh
    endfunc

    o.SetColor = function(r, g, b)
        this.rgb[0] = r;  this.rgb[1] = g;  this.rgb[2] = b
    endfunc
       
    o.SetBox = function(xMin, yMin, zMin, xMax, yMax, zMax)
        this.box[0] = xMin
        this.box[1] = yMin
        this.box[2] = zMin
        this.box[3] = xMax
        this.box[4] = yMax
        this.box[5] = zMax
        this.UpdateBox()
    endfunc
   
    o.Box = function()
        return this.tbox
    endfunc
   
    o.UpdateBox = function()
        this.tbox[0] = this.pos[0] + this.box[0]
        this.tbox[1] = this.pos[1] + this.box[1]
        this.tbox[2] = this.pos[2] + this.box[2]
        this.tbox[3] = this.pos[0] + this.box[3]
        this.tbox[4] = this.pos[1] + this.box[4]
        this.tbox[5] = this.pos[2] + this.box[5]
    endfunc

    o.SetPos = function(x, y, z)
        this.pos[0] = x
        this.pos[1] = y
        this.pos[2] = z
        this.UpdateBox()
    endfunc
   
    o.SetRot = function(yaw, pitch, roll)
        this.rot.yaw = yaw
        this.rot.pitch = pitch
        this.rot.roll = roll
    endfunc
           
    ' UpdateDir
    ' ---------
    ' Update dir vector from rotations.
    o.UpdateDir = function()
        S3D_Push()
            S3D_ClearTransformation()
            S3D_RotateY(rad(this.rot.yaw))
            S3D_RotateX(rad(this.rot.pitch))
            S3D_RotateZ(rad(this.rot.roll))
            S3D_TransformVector(this.dir, vFwdVec)
            VectorNormalize(this.dir)
        S3D_Pop()
        this.UpdateRot()
    endfunc
   
    ' UpdateRot
    ' ---------
    ' Update rotations from dir vector, assuming up-vector is (0, -1, 0).
    o.UpdateRot = function()
        l = sqr(this.dir[0]*this.dir[0] + this.dir[1]*this.dir[1] + this.dir[2]*this.dir[2])
        if this.dir[0] or this.dir[2]  this.rot.yaw = deg(atan2(this.dir[0], this.dir[2]))
        if l > 0  this.rot.pitch = deg(asin(-this.dir[1]/l))
    endfunc
   
    o.ToWorld = function(dst, x, y, z, w)
        S3D_Push()
            S3D_ClearTransformation()
            S3D_Translate(this.pos[0], this.pos[1], this.pos[2])
            S3D_RotateY(rad(this.rot.yaw))
            S3D_RotateX(rad(this.rot.pitch))
            S3D_RotateZ(rad(this.rot.roll))
            dst[0] = x;  dst[1] = y; dst[2] = z; dst[3] = w
            S3D_TransformVector(dst, dst)
        S3D_Pop()
    endfunc
   
    o.SetShadow = function(img, scale, size)
        if this.shd = unset  this.shd = []
        this.shd.img = img
        this.shd.scale = scale
        this.shd.size = size
    endfunc

    o.Draw = function()
        S3D_Push()
            S3D_Color3(this.rgb[0], this.rgb[1], this.rgb[2])
            S3D_Translate(this.pos[0], this.pos[1], this.pos[2])
            S3D_RotateY(rad(this.rot.yaw))
            S3D_RotateX(rad(this.rot.pitch))
            S3D_RotateZ(rad(this.rot.roll))
            S3D_Mesh(this.mesh, 0)
        S3D_Pop()
        if this.shd
            set image this.shd.img, false
            set color 0, 0, 0, 0
            cls true
            S3D_Push()
                S3D_SetView(this.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(this.shd.scale, this.shd.scale, this.shd.scale)
                S3D_RotateX(rad(90))
                S3D_RotateY(rad(this.rot.yaw))
                S3D_RotateX(rad(this.rot.pitch))
                S3D_RotateZ(rad(this.rot.roll))
                S3D_Mesh(this.mesh, 0)
                S3D_SetDepthBuffer(S3D_Z_BUFFER)
                SetGameView(0)
                set image primary
            S3D_Pop()
            so = SHD_OFFS
            hs = this.shd.size*0.5
            xmin = this.pos[0] - hs
            xmax = this.pos[0] + hs
            zmin = this.pos[2] - hs
            zmax = this.pos[2] + hs
            ymin = this.tbox[1]
            S3D_SetDepthBuffer(S3D_Z_BUFFER_READ)
            S3D_Texture(this.shd.img)
            S3D_Color4(255, 255, 255, SHD_ALPHA)
            S3D_Begin(S3D_QUADS)
                S3D_Vertex5(xmin, -so, zmax, 0, 0)
                S3D_Vertex5(xmax, -so, zmax, 1, 0)
                S3D_Vertex5(xmax, -so, zmin, 1, 1)
                S3D_Vertex5(xmin, -so, zmin, 0, 1)
            S3D_End()
            if typeof(vMaxVisObstacle)
                i = vMinVisObstacle
                S3D_Begin(S3D_QUADS)
                while i < vMaxVisObstacle and i < sizeof(vObstacles)
                    if vObstacles[i].flat
                        b = vObstacles[i].Box()
                        'x0 = max(xmin, b[0] - so)
                        'x1 = min(xmax, b[3] + so)
                        'z0 = max(zmin, b[2] - so)
                        'z1 = min(zmax, b[5] + so)               
                        x0 = max(xmin, b[0])
                        x1 = min(xmax, b[3])
                        z0 = max(zmin, b[2] - so*2)
                        z1 = min(zmax, b[5] - so*2)               
                        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.5)
                                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
                    endif
                    i = i + 1
                wend
                S3D_End()       
            endif
            S3D_SetDepthBuffer(S3D_Z_BUFFER)
            S3D_Texture(unset)
        endif
    endfunc

    o.Overlaps = function(obj)
        ab = this.tbox;  bb = obj.tbox
        return not (ab[2] > bb[5] or bb[2] > ab[5] or ab[0] > bb[3] or bb[0] > ab[3] or
                ab[1] > bb[4] or bb[1] > ab[4])
    endfunc
   
    return o
endfunc

function PlayerMesh()
    m = 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()
    return m
endfunc

function BulletMesh()
    m = 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()
    return m
endfunc

function TargetMesh()
    m = 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()
    return m
endfunc

function TreeMesh()
    m = S3D_BeginMesh()
        h = 7; hw = 1.25; t = 0.25
        S3D_Begin(S3D_TRIANGLES)
            S3D_Color(64, 128, 0)
            S3D_Vertex(0, -h, 0, 0, 0)
            S3D_Vertex(hw, -1, -hw, 0, 0)
            S3D_Vertex(-hw, -1, -hw, 0, 0)
            S3D_Color(32, 64, 0)
            S3D_Vertex(0, -h, 0, 0, 0)
            S3D_Vertex(hw, -1, hw, 0, 0)
            S3D_Vertex(hw, -1, -hw, 0, 0)
            S3D_Vertex(0, -h, 0, 0, 0)
            S3D_Vertex(-hw, -1, -hw, 0, 0)
            S3D_Vertex(-hw, -1, hw, 0, 0)
        S3D_End()
        S3D_Begin(S3D_QUADS)
            S3D_Color(96, 64, 16)
            S3D_Vertex(-t, -1, -t, 0, 0)
            S3D_Vertex(t, -1, -t, 0, 0)
            S3D_Vertex(t, -SHD_OFFS, -t, 0, 0)
            S3D_Vertex(-t, -SHD_OFFS, -t, 0, 0)
            S3D_Color(48, 32, 8)
            S3D_Vertex(t, -1, -t, 0, 0)
            S3D_Vertex(t, -1, t, 0, 0)
            S3D_Vertex(t, -SHD_OFFS, t, 0, 0)
            S3D_Vertex(t, -SHD_OFFS, -t, 0, 0)
            S3D_Vertex(-t, -1, t, 0, 0)
            S3D_Vertex(-t, -1, -t, 0 ,0)
            S3D_Vertex(-t, -SHD_OFFS, -t, 0, 0)
            S3D_Vertex(-t, -SHD_OFFS, t, 0, 0)
            S3D_Color4(0, 0, 0, SHD_ALPHA)
            S3D_Vertex(-hw, -SHD_OFFS, hw, 0, 0)
            S3D_Vertex(hw, -SHD_OFFS, hw, 0, 0)
            S3D_Vertex(hw, -SHD_OFFS, -hw, 0, 0)
            S3D_Vertex(-hw, -SHD_OFFS, -hw, 0, 0)
        S3D_End()
    S3D_EndMesh()
    return m
endfunc

You can run it in the old version too, but the ground will look weird Smile
Reply
#33
Cool... Extra cakes! Yummo!
Logic is the beginning of wisdom.
Reply
#34
I don't know about how to manage computer memories efficiently...but I likes cakes too  Big Grin
Reply
#35
Star Fox, with the new N7 installed, runs very nicely. Consistent 62fps.

Well done!!
Logic is the beginning of wisdom.
Reply
#36
Added enemies that follow 3d bezier paths in waves, using a 3d version of the polyline library.



Did the enemy ship in my own modeling tool (created in ... 2002, maybe), will create all models in it ... but I hate 3d modeling.

[Image: flight_test_enemies.jpg]
Reply
#37
Is your game exactly the same as this game?

https://www.youtube.com/watch?v=a0edFbcH1VM
Reply
#38
(10-25-2025, 05:20 PM)luwal Wrote: Is your game exactly the same as this game?

https://www.youtube.com/watch?v=a0edFbcH1VM

Nah, it'll be much worse, like a cheap, crappy and simplified knock-off. I'm spending like an hour per week on it. Today I wrote the routines for enemy attack waves, as shown in the video.

The original Star Fox is awesome, I played it a lot when it was released and return to it every now and then (available on Nintendo Switch).
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)