B+, 2D perspective code = iffy

Started by Dabz, May 04, 2025, 08:24:54

Previous topic - Next topic

Dabz

Code: BASIC
Graphics 800,600,32, 2

SetBuffer BackBuffer()

Const HORIZON = 200
Const ROAD_HEIGHT = 400
Const ROAD_MAX_WIDTH# = 600.0
Const ROAD_MIN_WIDTH# = 80.0
Const MAX_SEGMENTS = 1000

Dim curveArray#(MAX_SEGMENTS)

Type Car
    Field x#
    Field z#
    Field speed#
End Type

Global cameraZ# = 0.0
Global sx#, sy#, sz#

For i = 0 To MAX_SEGMENTS - 1
    curveArray#(i) = Sin(i * 0.02) * 200.0
Next

For i = 0 To 5
    c.Car = New Car
    c\z# = 100 + i * 40
    c\x# = Rnd(-ROAD_MAX_WIDTH#/2, ROAD_MAX_WIDTH#/2) * (ROAD_MIN_WIDTH# / ROAD_MAX_WIDTH#) 
    c\speed# = 0.2 + Rnd(0.1)
Next

Function ProjectCarToScreen(carX#, carZ#, cameraZ#)
    Local relZ#, perspective#, seg, baseSeg, roadX#, camRoadX#, dx#, screenCenterX#, roadW#
    
    relZ# = carZ# - cameraZ#
    If relZ# <= 0 Or relZ# >= 50 Then Return

    perspective# = relZ# / 50.0
    seg = Int(carZ#) Mod MAX_SEGMENTS
    baseSeg = Int(cameraZ#) Mod MAX_SEGMENTS

    roadX# = curveArray#(seg)
    camRoadX# = curveArray#(baseSeg)
    dx# = roadX# - camRoadX#

    screenCenterX# = 400 + dx# * perspective#
    roadW# = ROAD_MIN_WIDTH# + (ROAD_MAX_WIDTH# - ROAD_MIN_WIDTH#) * perspective#

    sx# = screenCenterX# + (carX# / ROAD_MAX_WIDTH#) * roadW# * perspective#
    sy# = HORIZON + (1.0 - perspective#) * ROAD_HEIGHT
    sz# = 16.0 * (1.0 - perspective#) + 4.0
End Function

While Not KeyDown(1)
    Cls
    cameraZ# = cameraZ# + 0.5

    Color 135,206,235 : Rect 0,0,800,HORIZON,True
    Color 34,139,34 : Rect 0,HORIZON,800,600-HORIZON,True

    For y = ROAD_HEIGHT To 0 Step -1
        perspective# = Float(y) / ROAD_HEIGHT
        worldZ# = cameraZ# + (1.0 - perspective#) * 50.0
        seg = Int(worldZ#) Mod MAX_SEGMENTS

        roadX# = curveArray#(seg)
        camRoadX# = curveArray#(Int(cameraZ#) Mod MAX_SEGMENTS)
        dx# = roadX# - camRoadX#

        screenX# = 400 + dx# * perspective#
        roadW# = ROAD_MIN_WIDTH# + (ROAD_MAX_WIDTH# - ROAD_MIN_WIDTH#) * perspective#
        left# = screenX# - roadW# / 2
        right# = screenX# + roadW# / 2

        Color 50,50,50 : Rect left#, HORIZON + y, right# - left#, 1, True

        If y Mod 10 = 0 Then
            Color 255,255,0
            Rect left#, HORIZON + y, 3,1, True
            Rect right# - 3, HORIZON + y, 3,1, True
        End If

        If Int(worldZ# * 2) Mod 20 < 5 Then
            Color 255,255,255
            Rect screenX# - 2, HORIZON + y, 4, 1, True
        End If
    Next

    For c.Car = Each Car
        ProjectCarToScreen(c\x#, c\z#, cameraZ#)
        If sz# > 0 Then
            Color 200,0,0
            Rect sx# - sz#/2, sy# - sz#, sz#, sz#, True
        End If
        c\z# = c\z# - c\speed#
        If c\z# <= cameraZ# Then Delete c
    Next

    Flip
Wend
End

Having a bit of a clear out of some bits and bobs and came across a CD with all sorts of shite on it, and, found this old bit of Blitz+ code that I couldnt figure out what I was doing wrong... If you run it, you'll see the "car" starts at the horizon, but drifts in to the centre of the screen, not out... I never figured out way back then because it looks right, but it's not, and I spent last night going over it again in a "I'm gonna get you you b[eep]d!" :D

But I cannot fathom at all where my maths are going wrong, and well, the "must know" twinge is on me, and, well... I just cannot see it! :/

Can anyone see where I've gone wrong, because I'm plainly not understanding something and it's doing my nut in again! :D

Dabz

EDIT: Watch, now I've posted I'll go for a shite, come back, and it'll dawn on me, cos thats what happens you know! :P
Dell Inspiron 16 Plus 7630 Laptop - 16.0-inch 16:10 2.5K Display, Intel Core i7-13620H Processor, 16 DDR5 RAM, 1, NVIDIA GeForce RTX 4060 GDDR6 Graphics, Windows 11 Piss Flap.

Dabz

#1
CRACKED IT!!!

Updated code:

Code: BASIC
Graphics 800,600,32,2
SetBuffer BackBuffer()

Const HORIZON = 200
Const ROAD_HEIGHT = 400
Const ROAD_MIN_WIDTH# = 80.0
Const ROAD_MAX_WIDTH# = 600.0

Type Car
    Field startX#     ; screen X at horizon
    Field endX#       ; screen X at bottom
    Field z#
    Field speed#
End Type

Global cameraZ# = 0.0
Global sx#, sy#, sz#

For i = 0 To 5
    c.Car = New Car
    c\z# = 100 + i * 40
    c\speed# = 0.2 + Rnd(0.1)

    Local startRoadW# = ROAD_MIN_WIDTH#
    Local endRoadW# = ROAD_MAX_WIDTH#

    c\startX# = 400 + Rnd(-startRoadW#/2, startRoadW#/2)
    c\endX#   = 400 + Rnd(-endRoadW#/2, endRoadW#/2)
Next

Function Interpolate#(a#, b#, t#)
    Return a# + (b# - a#) * t#
End Function

Function ProjectCarToScreen(car.Car)
    Local relZ# = car\z# - cameraZ#
    If relZ# <= 0 Or relZ# >= 50 Then Return

    Local perspective# = relZ# / 50.0
    sx# = Interpolate(car\endX#, car\startX#, perspective#)
    sy# = HORIZON + (1.0 - perspective#) * ROAD_HEIGHT
    sz# = 16.0 * (1.0 - perspective#) + 4.0
End Function

While Not KeyDown(1)
    Cls
    cameraZ# = cameraZ# + 0.5

    Color 135,206,235 : Rect 0,0,800,HORIZON,True
    Color 34,139,34 : Rect 0,HORIZON,800,600-HORIZON,True

    For y = ROAD_HEIGHT To 0 Step -1
        Local perspective# = Float(y) / ROAD_HEIGHT
        Local roadW# = ROAD_MIN_WIDTH# + (ROAD_MAX_WIDTH# - ROAD_MIN_WIDTH#) * perspective#
        Local left# = 400 - roadW# / 2
        Local right# = 400 + roadW# / 2

        Color 50,50,50 : Rect left#, HORIZON + y, right# - left#, 1, True

        ; Center line
        If Int(perspective# * 50 * 2) Mod 20 < 5 Then
            Color 255,255,255
            Rect 400 - 2, HORIZON + y, 4, 1, True
        End If
    Next

    For c.Car = Each Car
        ProjectCarToScreen(c)
        If sz# > 0 Then
            Color 200,0,0
            Rect sx# - sz#/2, sy# - sz#, sz#, sz#, True
        End If
        c\z# = c\z# - c\speed#
        If c\z# <= cameraZ# Then Delete c
    Next

    Flip
Wend
End

Amazing what a good shite, then some dinner and a glass of Ribena can do! :D

I'm not 100% with it, but, it's good enough that I can put this to bed after it's sat there for years, and, and, I'll have a decent kip tonight! :P

Right, I've achieved, time for the garden! Hehehe

Dabz
Dell Inspiron 16 Plus 7630 Laptop - 16.0-inch 16:10 2.5K Display, Intel Core i7-13620H Processor, 16 DDR5 RAM, 1, NVIDIA GeForce RTX 4060 GDDR6 Graphics, Windows 11 Piss Flap.

Dabz

It's decided to piss down... Great! :(

Dabz
Dell Inspiron 16 Plus 7630 Laptop - 16.0-inch 16:10 2.5K Display, Intel Core i7-13620H Processor, 16 DDR5 RAM, 1, NVIDIA GeForce RTX 4060 GDDR6 Graphics, Windows 11 Piss Flap.

Baggey

I wont tell you ive just got back from kayaking up the river in the blazing sunshine then. Oh and i stopped of at the beach for a beer :-X

Baggey
Running a PC that just Aint fast enough!? i7 4Ghz Quad core 32GB ram  2x1TB SSD and NVIDIA Quadro K1200 on 2 x HP Z24's . DID Technology stop! Or have we been assimulated!

Windows10, Parrot OS, Raspberry Pi Black Edition! , ZX Spectrum 48k, C64, Enterprise 128K, The SID chip. Im Misunderstood!

Dabz

Dell Inspiron 16 Plus 7630 Laptop - 16.0-inch 16:10 2.5K Display, Intel Core i7-13620H Processor, 16 DDR5 RAM, 1, NVIDIA GeForce RTX 4060 GDDR6 Graphics, Windows 11 Piss Flap.

Dabz

Since the garden went for a burton... I've had a bit more play with that code:

denathorn.co.uk/share/RoadThing.mp4

:)

Dabz
Dell Inspiron 16 Plus 7630 Laptop - 16.0-inch 16:10 2.5K Display, Intel Core i7-13620H Processor, 16 DDR5 RAM, 1, NVIDIA GeForce RTX 4060 GDDR6 Graphics, Windows 11 Piss Flap.