How to make a race track ? - 1micha.elok - 11-06-2024
Hi, Marcus,
I wonder how to make a race track (see the picture above), could you please advice me ?
This is the code that you made some months ago.
I believe there are some minor changes with the latest s3d library
I haven't use it (.... just kidding ...)
Code: ' A library that I'm working on, not finished at all, don't use it!
include "s3d.n7"
#dbg
set window "test", 320, 240, false, 2
set redraw off
roadImg = loadimage("road.png")
roadImgW = width(roadImg)
roadImgH = height(roadImg)
decorImg = loadimage("winter_tree.png")
tunnelImg = loadimage("tunnel_winter.png")
bgImg = loadimage("sky_winter.png")
' Set up 3d view.
S3D_SetView(primary, rad(90), 0.1, 20)
' Render polygons as we add them. If direct mode is false, all polygons are batched, sorted by
' distance and rendered when we call S3D_Render. Here we draw from back to front manually.
S3D_SetDirectMode(true)
road = []
for z = 0 to 999 road[z] = [x: sin(z*0.05)*6, y: sin(z*0.1)*3]
playerz = 0.0
playerx = 0
playery = -1
projected = dim(4) ' Don't want to spawn too many tables in a game loop, reused for calculations.
lastTick = clock()
while not keydown(KEY_ESCAPE, true)
t = clock()
dt = (t - lastTick)/1000
lastTick = t
playerz = playerz + 4*dt
' calculate camera y
if int(playerz) < sizeof(road) - 2
k = playerz%1
playery = (1 - k)*road[int(playerz)].y + k*road[int(playerz) + 1].y - 0.5
else
playery = road[sizeof(road) - 1].y - 0.5
endif
' move left and right
if keydown(KEY_LEFT) playerx = playerx - 4*dt
if keydown(KEY_RIGHT) playerx = playerx + 4*dt
set color 255, 255, 255
draw image bgImg, 0, -80 - playery*5
S3D_Clear()
S3D_Translate(-playerx, -playery, -playerz)
S3D_Begin(S3D_QUADS)
didFill = false
strips = 0
fills = 0
for i = int(playerz) + 20 to int(playerz)
if i < sizeof(road) - 2
strips = strips + 1
' Do we need to fill with snow color to hide distant objects?
S3D_Project(projected, 0, road[i + 1].y, i + 1)
y0 = round(projected[1])
S3D_Project(projected, 0, road[i].y, i)
y1 = round(projected[1])
if y1 > y0
if not didFill
didFill = true
fills = fills + 1
set color 218, 218, 218
draw rect 0, y0, width(primary), height(primary) - y0, true
set color 255, 255, 255
endif
else
didFill = false
endif
' Draw road.
x0 = road[i].x
x1 = road[i + 1].x
set color 255, 255, 255
S3D_Texture(roadImg)
S3D_Vertex(x0 - 2, road[i].y, i, 0, roadImgH)
S3D_Vertex(x0 + 2, road[i].y, i, roadImgW, roadImgH)
S3D_Vertex(x1 + 2, road[i + 1].y, i + 1, roadImgW, 0)
S3D_Vertex(x1 - 2, road[i + 1].y, i + 1, 0, 0)
' Draw sprites.
' Fade in.
z = (i + 1) - playerz
if z > 15
a = ((20 - z)/5)*255
set color 255, 255, 255, a
endif
if i%20 = 0
S3D_Texture(tunnelImg)
S3D_Vertex(road[i].x - 5, road[i].y + 0.2, i, 0, height(tunnelImg))
S3D_Vertex(road[i].x + 5, road[i].y + 0.2, i, width(tunnelImg), height(tunnelImg))
S3D_Vertex(road[i].x + 5, road[i].y - 3.5, i, width(tunnelImg), 0)
S3D_Vertex(road[i].x - 5, road[i].y - 3.5, i, 0, 0)
else
if i%2 = 0
S3D_Texture(decorImg)
x = x0 - 2.5
S3D_Vertex(x - 0.4, road[i].y, i, 0, height(decorImg))
S3D_Vertex(x + 0.4, road[i].y, i, width(decorImg), height(decorImg))
S3D_Vertex(x + 0.4, road[i].y - 1, i, width(decorImg), 0)
S3D_Vertex(x - 0.4, road[i].y - 1, i, 0, 0)
else
S3D_Texture(decorImg)
x = x0 + 2.5
S3D_Vertex(x - 0.4, road[i].y, i, 0, height(decorImg))
S3D_Vertex(x + 0.4, road[i].y, i, width(decorImg), height(decorImg))
S3D_Vertex(x + 0.4, road[i].y - 1, i, width(decorImg), 0)
S3D_Vertex(x - 0.4, road[i].y - 1, i, 0, 0)
endif
endif
endif
next
S3D_End()
'S3D_Render()
set caret 0, 0
wln round(1/dt)
wln strips
wln fills
redraw
wait 1
wend
RE: How to make a race track ? - johnno56 - 11-06-2024
Cool demo...
J
RE: How to make a race track ? - 1micha.elok - 11-06-2024
(11-06-2024, 04:39 AM)johnno56 Wrote: Cool demo...
J
The demo was made some months ago by the creator of S3D Library (a.k.a Marcus )
I have almost forgotten the S3D library.... but it is really interesting to learn.
Regarding the car racing, I have still some questions :
1. how to make a race track ( a little map on the right upper corner) to track the player
2. there should be some opponents, how to add those opponents' car to the game, and they should appear on the little map on the right upper corner too.
3. to make a start and a finish line
Still scratching my head on how to make them ...
RE: How to make a race track ? - Marcus - 11-06-2024
Yes, the car racing test initiated the entire 3D thing in n7
That code is pretty useless for a real game though. For example, there are no real turns or turning. The "track" is just a sine curve going forward, and the car just moves left and right - it never turns.
We need to create a real road, based on a polygon or a closed curve. And I actually started writing some code for that a while ago. I shall have a look at the code when I come home from work.
RE: How to make a race track ? - Marcus - 11-06-2024
I checked the code I wrote a while ago and replaced the texture with one generated by code. But this truely isn't much to look at, it was just a test for creating a road from a curve (polyline library, which is full of bugs btw).
Code: include "s3d.n7"
include "file.n7"
include "polyline.n7"
visible vRes = 480
set window "Futuracer", vRes*screenw()/screenh(), vRes, false
set redraw off
texture = createimage(128, 128)
set image texture
for y = 0 to 127 for x = 0 to 127
i = 16 + rnd(64)
set color i, i, i
set pixel x, y
next
set image primary
BoxBlur(texture, 2, 2)
set image texture
set color 255, 255, 255, 128
draw rect 60, 0, 8, 64, true
set image primary
BoxBlur(texture, 1, 1)
p = PolyLine([[-50, 50], [50, 50], [50, -50], [-50, -50]], true)
mesh = S3D_BeginMesh()
S3D_Begin(S3D_QUADS)
hrw = 8
stp = 15
i = 0
while i < p.GetLength()
pos = p.GetPoint(i, true)
dir = p.GetDirection(i, true)
x0 = pos[0]; y0 = pos[1]
tx0 = dir[1]; ty0 = -dir[0]
j = i + stp
if j > p.GetLength() j = 0
pos = p.GetPoint(j, true)
dir = p.GetDirection(j, true)
x1 = pos[0]; y1 = pos[1]
tx1 = dir[1]; ty1 = -dir[0]
S3D_Vertex(x0 - tx0*hrw, 0, y0 - ty0*hrw, 0, 1)
S3D_Vertex(x1 - tx1*hrw, 0, y1 - ty1*hrw, 0, 0)
S3D_Vertex(x1 + tx1*hrw, 0, y1 + ty1*hrw, 1, 0)
S3D_Vertex(x0 + tx0*hrw, 0, y0 + ty0*hrw, 1, 1)
i = i + stp
wend
S3D_End()
S3D_EndMesh()
S3D_SetView(primary, rad(74), 0.1, 100)
x = -70
z = 0
a = 0
lastTick = clock()
while not keydown(KEY_ESCAPE, true)
t = clock()
dt = (min(t - lastTick, 100))/1000
lastTick = t
if keydown(KEY_LEFT) a = a - 90*dt
if keydown(KEY_RIGHT) a = a + 90*dt
if keydown(KEY_UP)
x = x + sin(rad(a))*10*dt
z = z + cos(rad(a))*10*dt
elseif keydown(KEY_DOWN)
x = x - sin(rad(a))*10*dt
z = z - cos(rad(a))*10*dt
endif
set color 0, 0, 0
cls
S3D_Clear()
S3D_RotateY(-rad(a))
S3D_Translate(-x, 2, -z)
S3D_Texture(texture)
S3D_Mesh(mesh, 0)
S3D_Render()
S3D_RenderFog(0, 0, 0, false)
set caret width(primary) - fwidth(" "), height(primary) - fheight()
set justification right
set color 0, 255, 0
write "FPS: " + str(round(1/dt))
set justification left
redraw
wait 1
wend
' BoxBlur
' -------
function BoxBlur(img, rx, ry)
rx = max(int(rx), 0); ry = max(int(ry), 0)
set image img
w = width(img); h = height(img)
data = dim(w, h)
' Blur vertically
for y = 0 to h - 1 for x = 0 to w - 1 data[x][y] = pixeli(img, x, y)
count = ry*2 + 1
for x = 0 to w - 1
sr = 0; sg = 0; sb = 0; sa = 0
for y = -ry to ry
p = data[x][y%h];
sr = sr + Red(p); sg = sg + Green(p); sb = sb + Blue(p); sa = sa + Alpha(p)
next
for y = 0 to h - 1
set color sr/count, sg/count, sb/count, sa/count
set pixel x, y
p = data[x][(y - ry)%h]
sr = sr - Red(p); sg = sg - Green(p); sb = sb - Blue(p); sa = sa - Alpha(p)
p = data[x][(y + ry + 1)%h]
sr = sr + Red(p); sg = sg + Green(p); sb = sb + Blue(p); sa = sa + Alpha(p)
next
next
' Blur horizontally.
for y = 0 to h - 1 for x = 0 to w - 1 data[x][y] = pixeli(img, x, y)
count = rx*2 + 1
for y = 0 to h - 1
sr = 0; sg = 0; sb = 0; sa = 0
for x = -rx to rx
p = data[x%w][y]
sr = sr + Red(p); sg = sg + Green(p); sb = sb + Blue(p); sa = sa + Alpha(p)
next
for x = 0 to w - 1
set color sr/count, sg/count, sb/count, sa/count
set pixel x, y
p = data[(x - rx)%w][y]
sr = sr - Red(p); sg = sg - Green(p); sb = sb - Blue(p); sa = sa - Alpha(p)
p = data[(x + rx + 1)%w][y]
sr = sr + Red(p); sg = sg + Green(p); sb = sb + Blue(p); sa = sa + Alpha(p)
next
next
set image primary
' Pixeli helpers.
function Alpha(c); return int(c/16777216); endfunc
function Red(c); return int((c/65536))%256; endfunc
function Green(c); return int((c/256))%256; endfunc
function Blue(c); return c%256; endfunc
endfunc
I have never made a racing game, except for a mode7 experiment. And I frankly don't know what is the best way to store a track in memory or how to render it in a good way. It probably depends on what type of racing game you're doing.
Anyhow, as I wrote earlier, the thing I wrote this spring is not good for anything. I'll see if I can think of a good way to make a racing game, either based on road segments (like above, but with heights) or a heightmap.
Sorry for not being to any help here, it's an unexplored area for me.
RE: How to make a race track ? - Marcus - 11-06-2024
https://youtu.be/Pw-RBsfM4v4?si=MriLCHSYrEQnjNSu
This is the mode7 racer I wrote many years ago. The enemies TRY to follow pre-recorded paths, which worked quite well.
RE: How to make a race track ? - 1micha.elok - 11-07-2024
(11-06-2024, 04:07 PM)Marcus Wrote: I checked the code I wrote a while ago and replaced the texture with one generated by code.
...
How blown away I am by the code you sent over for coding a race track. It is truly beyond my expectations and has given me a whole new insight on how to approach coding in general, including the code generated texture. I can't thank you enough for taking the time to create such a detailed and thoughtful piece of code. I will dig into it and learn as much as I can from it. Your expertise and talent in coding never ceases to amaze me.
It's very cool
RE: How to make a race track ? - 1micha.elok - 11-07-2024
What I've learned so far :
1. The 2D polyline can be transformed to 3D race track
2. Control key modification
- Display control key indication : on/off
- If UP is on, the car moves forward until SPACEBAR is on
I haven't still succeeded to show the car position on the little 2D polyline race track
Don't worry, it is just my curiousity. I am amazed that 2D polyline can be transformed to 3D race track.
Code: '=====================================
' Some modification on Futuracer
'
' Resources :
' * Futuracer, original code by Marcus
'
'=====================================
'----------------
' INITIALIZATION
'----------------
'library
include "s3d.n7"
include "polyline.n7"
'screen size
visible vRes = 480
set window "Futuracer", vRes*screenw()/screenh(), vRes, false
set redraw off
'color definition
black = [0,0,0]
white = [255,255,255]
green = [0,255,0]
'create road and white strips image
texture = createimage(128, 128)
set image texture 'road
for y = 0 to 127 for x = 0 to 127
i = 16 + rnd(64)
set color i, i, i
set pixel x, y
next
set image primary
BoxBlur(texture, 2, 2)
set image texture 'white strips
set color white
draw rect 60, 0, 8, 64, true
set image primary
BoxBlur(texture, 1, 1)
'race track
points = [[-50, 50], [50, 50], [50, -50], [-50, -50]]
p = PolyLine(points, true) 'true = closed loop
'draw race track in 3D
mesh = S3D_BeginMesh()
S3D_Begin(S3D_QUADS)
hrw = 8
stp = 15
i = 0
while i < p.GetLength()
pos = p.GetPoint(i, true)
dir = p.GetDirection(i, true)
x0 = pos[0]; y0 = pos[1]
tx0 = dir[1]; ty0 = -dir[0]
j = i + stp
if j > p.GetLength() j = 0
pos = p.GetPoint(j, true)
dir = p.GetDirection(j, true)
x1 = pos[0]; y1 = pos[1]
tx1 = dir[1]; ty1 = -dir[0]
S3D_Vertex(x0 - tx0*hrw, 0, y0 - ty0*hrw, 0, 1)
S3D_Vertex(x1 - tx1*hrw, 0, y1 - ty1*hrw, 0, 0)
S3D_Vertex(x1 + tx1*hrw, 0, y1 + ty1*hrw, 1, 0)
S3D_Vertex(x0 + tx0*hrw, 0, y0 + ty0*hrw, 1, 1)
i = i + stp
wend
S3D_End()
S3D_EndMesh()
'--------------
' MAIN PROGRAM
'--------------
S3D_SetView(primary, rad(74), 0.1, 100)
'initial values
x = -70
z = 0
a = 0
lastTick = clock()
toggleUp = 0
toggleDown = 0
infoLeft = "OFF"
infoRight = "OFF"
infoUp = "OFF"
infoDown = "OFF"
infoBrake = "OFF"
while not keydown(KEY_ESCAPE, true)
'delta time
t = clock()
dt = (min(t - lastTick, 100))/1000
lastTick = t
'control keys
if keydown(KEY_LEFT)
a = a - 90*dt
infoLeft = "ON"
else
infoLeft = "OFF"
endif
if keydown(KEY_RIGHT)
a = a + 90*dt
infoRight = "ON"
else
infoRight = "OFF"
endif
if keydown(KEY_UP) or toggleUp = 1
x = x + sin(rad(a))*10*dt
z = z + cos(rad(a))*10*dt
toggleUp = 1 'keep forward
toggleDown = 0
infoUp = "ON"
infoDown = "OFF"
infoBrake = "OFF"
endif
if keydown(KEY_DOWN) or toggleDown = 1
x = x - sin(rad(a))*10*dt
z = z - cos(rad(a))*10*dt
toggleUp = 0 'stop
toggleDown = 1 'keep backward
infoUp = "OFF"
infoDown = "ON"
infoBrake = "OFF"
endif
if keydown(KEY_SPACE)
toggleUp = 0 'stop
toggleDown = 0 'stop
infoUp = "OFF"
infoDown = "OFF"
infoBrake = "ON"
endif
'clear background
set color black; cls
'draw race track in 2D
shiftX = 320
shiftY = 90
set color green
for i = 0 to sizeof(points) - 1
j = (i + 1)%sizeof(points)
draw line shiftX+points[i][0], shiftY+points[i][1], shiftX+points[j][0], shiftY+points[j][1]
next
set caret 270,10 ; write "Race Track"
d = d + 1
pos = p.GetPoint(d, true)
dir = p.GetDirection(d, true)
draw line pos[0] - dir[0]*16+shiftX, pos[1] - dir[1]*16+shiftY, pos[0]+shiftX, pos[1]+shiftY
'S3D rendering process
S3D_Clear()
S3D_RotateY(-rad(a))
S3D_Translate(-x, 2, -z)
S3D_Texture(texture)
S3D_Mesh(mesh, 0)
S3D_Render()
S3D_RenderFog(0, 0, 0, false)
'FPS info
set caret 10,10
set color green
wln "FPS: " + str(round(1/dt))
wln ""
wln "Control keys : "
wln " Left (Left) : "+infoLeft
wln " Right (Right) : "+infoRight
wln " Forward (Up) : "+infoUp
wln " Backward (Down) : "+infoDown
wln " Brake (Space Bar) : "+infoBrake
redraw
wait 1
wend
'-----------
' FUNCTIONS
'-----------
' BoxBlur
' -------
function BoxBlur(img, rx, ry)
rx = max(int(rx), 0); ry = max(int(ry), 0)
set image img
w = width(img); h = height(img)
data = dim(w, h)
' Blur vertically
for y = 0 to h - 1 for x = 0 to w - 1 data[x][y] = pixeli(img, x, y)
count = ry*2 + 1
for x = 0 to w - 1
sr = 0; sg = 0; sb = 0; sa = 0
for y = -ry to ry
p = data[x][y%h];
sr = sr + Red(p); sg = sg + Green(p); sb = sb + Blue(p); sa = sa + Alpha(p)
next
for y = 0 to h - 1
set color sr/count, sg/count, sb/count, sa/count
set pixel x, y
p = data[x][(y - ry)%h]
sr = sr - Red(p); sg = sg - Green(p); sb = sb - Blue(p); sa = sa - Alpha(p)
p = data[x][(y + ry + 1)%h]
sr = sr + Red(p); sg = sg + Green(p); sb = sb + Blue(p); sa = sa + Alpha(p)
next
next
' Blur horizontally.
for y = 0 to h - 1 for x = 0 to w - 1 data[x][y] = pixeli(img, x, y)
count = rx*2 + 1
for y = 0 to h - 1
sr = 0; sg = 0; sb = 0; sa = 0
for x = -rx to rx
p = data[x%w][y]
sr = sr + Red(p); sg = sg + Green(p); sb = sb + Blue(p); sa = sa + Alpha(p)
next
for x = 0 to w - 1
set color sr/count, sg/count, sb/count, sa/count
set pixel x, y
p = data[(x - rx)%w][y]
sr = sr - Red(p); sg = sg - Green(p); sb = sb - Blue(p); sa = sa - Alpha(p)
p = data[(x + rx + 1)%w][y]
sr = sr + Red(p); sg = sg + Green(p); sb = sb + Blue(p); sa = sa + Alpha(p)
next
next
set image primary
' Pixeli helpers.
function Alpha(c); return int(c/16777216); endfunc
function Red(c); return int((c/65536))%256; endfunc
function Green(c); return int((c/256))%256; endfunc
function Blue(c); return c%256; endfunc
endfunc
RE: How to make a race track ? - kevin - 11-10-2024
This looks very interesting, and I look forward to seeing any updates that you post on it. I have tried in the past to make a car racing game, but never succeeded. Thank you for posting.
|