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)
10-18-2025, 03:51 PM (This post was last modified: 10-18-2025, 03:53 PM by Marcus.)
(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:
' 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()
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
' 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
' 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
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
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
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).