Pseudo 3d road beginnings

Rob Hewitt

Active Member
I'm still learning the language so while I've been researching I found Lou's Pseudo 3d Page. Lots of good info there and I also found an example in a BASIC dialect (Can't remember which one!). So I converted it! I then added some gradients and a fade in for the road. *EDIT And cursor key movement and acceleration. It's not the best conversion as all of the code is called in OnRender() but it works!

Code:
``````' *****************************************************
' **** Converted to Cerberus-X by Coagulus in 2017 ****
' *****************************************************

'Road Demonstration Program by Louis Gorenfeld 2010

'This program is intended to show concepts described at Lou's Pseudo 3d Page
'http://www.gorenfeld.net/lou/pseudo
' * ABOVE ADDRESS IS NOW http://www.extentofthejam.com/pseudo/  *

'It defaults to generating 80 frames during which the road curves right,
'uncurves, and repeats.

'I've left much detail off of the road.  You can draw them in around line 70! (*Now in drawroad()*)
'Happy coding! :)

Strict

Import mojo

Global RoadLines:Int = 99
Global ScrollSpeed:Float = 0
Global RoadY:Int = -1        'arbitrary
Global ResX:Int = 320
Global ResY:Int = 240
Global PlrLine:Int = 8       'What line is the player sprite on?
Global ScreenLine:Int

Global GrassColor:Int

Global TexOffset:Float = 100
Global SegY:Float = RoadLines
Global DX:Float = 0
Global DDX:Float = .02    ' This controls the steepness of the curve
Global X:Float 'AS SINGLE
Global HalfWidth:Float 'AS SINGLE
Global NextStretch:String = "Straight"

Global _scaleRatio:Float
Global _maxX:Int
Global xoff:Int

Global WidthStep:Int = 1

Global ZMap:Float[100]
Global linex:Float[100]

Class road Extends App

Method OnCreate:Int()
Local resX:Float = Float( DeviceWidth() )
Local resY:Float = Float( DeviceHeight() )
Local loop:Int
_scaleRatio = resY / 240
_maxX = resX / _scaleRatio
xoff = ((resX - (320 * _scaleRatio)) / 2) /_scaleRatio ' so that the game screen remains centred
SetUpdateRate(0)
TexOffset = 100
DX = 0
DDX = .03    ' This controls the steepness of the curve
initzmap()
Return 0
End Method

Method OnUpdate:Int()

Return 0
End Method

Method OnRender:Int()
Cls 0,0,0
PushMatrix()
Scale(_scaleRatio,_scaleRatio)
PopMatrix()
Return 0
End Method

Method initzmap:Void()
For Local A:Int = 1 To RoadLines
ZMap[A] = RoadY / (A - (ResY / 2.0))
Next

' Normalize ZMap so the line with the player on it is scale=1 (or would be
' If we had a player sprite :))
Local b:Float = 1.0 / ZMap[PlrLine]
b = b * 100   'in percents because QBasic's MOD is lame
For Local A:Int = 1 To RoadLines
ZMap[A] = ZMap[A] * b
Next
End Method

SetColor 0,255,255

For Local A:Int = 1 To ResY - RoadLines
Local CL:Int = A * 2
If CL>255 Then CL=255
SetColor 0,255-CL,255-CL
DrawLine  0,A,ResX-1,A
Next

X = ResX / 2
DX = 0
HalfWidth = 120
ScreenLine = ResY - 1

For Local A:Int = 1 To RoadLines
If (ZMap[A] + TexOffset) Mod 100 > 50
GrassColor = 10
Else
GrassColor = 2
End If

'draw the road with stripe
If RoadColor=7 Then SetColor 128,128,128 Else SetColor 64,64,64
DrawLine linex[A]+(X-HalfWidth),ScreenLine,linex[A]+X+HalfWidth,ScreenLine
'draw the grass with stripe
If GrassColor=10 Then SetColor 0,255,0 Else SetColor 0,128,0
DrawLine 0, ScreenLine,    linex[A]+(X - HalfWidth), ScreenLine
DrawLine linex[A]+(X + HalfWidth), ScreenLine, ResX - 1, ScreenLine

HalfWidth = HalfWidth - WidthStep
ScreenLine = ScreenLine - 1

If NextStretch = "Straight" Then
If A > SegY Then
DX = DX + (DDX)
End If
Elseif  NextStretch = "Curved" Then
If A < SegY Then
DX = DX + (DDX)
End If
End If
X = X + DX
Next A

SetAlpha 1.0

If KeyDown(KEY_LEFT)
For Local A:Int = 1 To RoadLines
Next
End If
If KeyDown(KEY_RIGHT)
For Local A:Int = 1 To RoadLines
Next
End If

If KeyDown(KEY_UP) Then ScrollSpeed=ScrollSpeed+0.01
If KeyDown(KEY_DOWN) Then ScrollSpeed=ScrollSpeed-0.01

If ScrollSpeed>10.0 Then ScrollSpeed = 10.0
If ScrollSpeed<0.0 Then ScrollSpeed = 0.0

TexOffset = TexOffset + ScrollSpeed
While TexOffset >= 100
TexOffset = TexOffset - 100
Wend
SegY = SegY - ScrollSpeed  ' Decrease SegY by an arbitrary amount.  Adjust to taste.
While SegY < 0
SegY = SegY + RoadLines
If NextStretch = "Curved" Then
NextStretch = "Straight"
Elseif NextStretch = "Straight" Then
NextStretch = "Curved"
End If
Wend

End Method

End Class

Function Main:Int()
Return 0
End Function``````

Aktayr

New Member
Rob Hewitt

Hi Rob. Thanks a lot for your code. It's very readable. I want to know : your table linex[] has a length of 100 but what values you give to it ? It seems have null values.
ZMap[] is initialized in the function initzmap() but i don't see the same way for linex[]. Maybe i'm wrong.
Thanks again for the code and eventually for your answer.

Rich

Well-Known Member
CX Code Contributor
3rd Party Module Dev
3rd Party Tool Dev
@Rob Hewitt Thats a really cool guide. Keep at it as Iove these types of games

I followed it a few years back and then got carried away adding more and more. This is what it turned into in the end...

Sadly I abandoned my project, maybe ill get back to one day

Aktayr

New Member
Rich

This is really nice. Could you share the code who generates just the road, like Rob Hewitt did ?

Rob Hewitt

Active Member
Rob Hewitt

Hi Rob. Thanks a lot for your code. It's very readable. I want to know : your table linex[] has a length of 100 but what values you give to it ? It seems have null values.
ZMap[] is initialized in the function initzmap() but i don't see the same way for linex[]. Maybe i'm wrong.
Thanks again for the code and eventually for your answer.
Hi. It was 2 and a half years ago and i didn't get any further as i got sidetracked with other projects. I converted the code for the original examples on Lou's page. Doesn't look like linex[] is ever initialized just added to. I'll have another look when i can.

Rob Hewitt

Active Member
@Rob Hewitt Thats a really cool guide. Keep at it as Iove these types of games

I followed it a few years back and then got carried away adding more and more. This is what it turned into in the end...
View attachment 781
Sadly I abandoned my project, maybe ill get back to one day
Wow that's so much better than i got to.

Rich

Well-Known Member
CX Code Contributor
3rd Party Module Dev
3rd Party Tool Dev
ta. sadly something went wrong with my maths. I have taken the code apart and rebuilt it 3 times and always end up with same issue.
The cars "stutter" going round the track and it doesnt look right.

Rich

Well-Known Member
CX Code Contributor
3rd Party Module Dev
3rd Party Tool Dev
Rich

This is really nice. Could you share the code who generates just the road, like Rob Hewitt did ?
Technically im doing the same thing but Im using DrawPoly on the points of the segment rather than drawing scanlines

Aktayr

New Member
The code of Rob Hewitt is the clearest i found until now. But i have some issues with a table. That's why i'd like to see your code to compare.
Anyway, thanks a lot Rich.

Rich

Well-Known Member
CX Code Contributor
3rd Party Module Dev
3rd Party Tool Dev
I'll see what i can do... wont be for a few days though

Aktayr

New Member
Hi@ @Rich and @Rob Hewitt

I solved my problem. I just wrote "linex[A]=0" in the drawRoad() loop and voilà !
Thanks a lot @Rob Hewitt for your useful and great code and @Rich for your advice and patience.
I share here the code i made in Lua with the framework LÖVE2D for anyone it could help.
Next step : the curves.

Pseudo3d:
``````io.stdout:setvbuf('no')

love.graphics.setDefaultFilter("nearest")

if arg[#arg] == "-debug" then require("mobdebug").start() end

love.window.setMode(1280,720)

screenWidth = love.graphics.getWidth()
screenHeight = love.graphics.getHeight()

scrollSpeed = 0
roadY = -1 -- arbitrary
plrLine = 8 -- What line is the player sprite on?
screenLine = 0

grassColor = 0
stripeColor = 0

texOffSet = 100
x = 0
halfWidth = 0

widthStep = 1

zMap = {}
line_x = {}

resX = screenWidth
resY = screenHeight
loop = 0
scaleRatio = resY/240

function init_z_map()
for i = 1, roadLines do
zMap[i] = roadY / (i-(resY / 2.0))
end

b = 1.0 / zMap[plrLine]
b = b * 100
for i = 1, roadLines do
zMap[i] = zMap[i] * b
end
end

init_z_map()
end

for i = 1, resY - roadLines do
local cl = i*.001
if(cl>1) then cl = 1 end
--love.graphics.setColor(1,1-cl,1-cl)
--love.graphics.line(0, i, resX-1, i)
end

x = resX*.5
dx = 0
halfWidth = 120
screenLine = resY - 1

for i = 1, roadLines do
line_x[i]=0

if((zMap[i]+texOffSet)%20 > 10) then
grassColor = 10
else
grassColor = 2
end

if((zMap[i]+texOffSet)%20 > 10) then
stripeColor = 5
else
stripeColor = 6
end

if((zMap[i]+texOffSet)%20>10) then
else
end

--draw the road with stripe
if(roadColor == 7) then
love.graphics.setColor(.5,.5,.5, setAlpha)
elseif(roadColor == 8) then
love.graphics.setColor(.25,.25,.25, setAlpha)
end
love.graphics.line(line_x[i] + (x-halfWidth), screenLine, line_x[i]+(x+halfWidth), screenLine)

--draw the stripeColors
if(stripeColor == 6) then
love.graphics.setColor(1,0,0, setAlpha)
elseif(stripeColor == 5) then
love.graphics.setColor(1,1,1, setAlpha)
end
love.graphics.line(x-halfWidth/.5, screenLine, line_x[i]+(x-halfWidth), screenLine)
love.graphics.line(line_x[i]+(x+halfWidth), screenLine, line_x[i]+(x+halfWidth/.5), screenLine)

--draw the grass with stripe

if(grassColor == 2) then
love.graphics.setColor(0,1,0, setAlpha)
elseif(grassColor == 10) then
love.graphics.setColor(0,.5,0, setAlpha)
end
love.graphics.line(0, screenLine, line_x[i]+(x-halfWidth/.5), screenLine)
love.graphics.line(line_x[i]+(x+halfWidth/.5), screenLine, resX-1, screenLine)

halfWidth = halfWidth - widthStep
screenLine = screenLine - 1

end

end

function love.update(dt)
if(love.keyboard.isDown("up","z")) then
scrollSpeed = scrollSpeed + .01
else
scrollSpeed = scrollSpeed - .01
end
if(love.keyboard.isDown("down","q")) then
scrollSpeed = scrollSpeed - .01
end
if(love.keyboard.isDown("right","d")) then
end
if(love.keyboard.isDown("left","s")) then
end

if(scrollSpeed>2) then scrollSpeed=2 end
if(scrollSpeed<0) then scrollSpeed=0 end

texOffSet = texOffSet + scrollSpeed

end

function love.draw()

love.graphics.setColor(1,1,1)
love.graphics.print('FPS          ' .. love.timer.getFPS(), 0, 0)
love.graphics.print('ScrollSpeed          ' .. scrollSpeed, 0, 20)
end

function love.keypressed(key)
if key == "escape" then
love.event.push("quit")
end
--print(key)
end``````

Aktayr

New Member
This is the file. You must to have LÖVE2D on your PC to launch it.
Take care of yourselves.

Attachments

• 32 KB Views: 27

Rich

Well-Known Member
CX Code Contributor
3rd Party Module Dev
3rd Party Tool Dev
Glad you got it working. Keep up the good word. I love these types of games

Aktayr

New Member
Rich
Thank you four support !