Advertisement
PolyCreativity

Elevator Shaft Simulation! aka. How camera tilting works in a ray surfer

Sep 23rd, 2024 (edited)
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
QBasic 4.16 KB | None | 0 0
  1. DECLARE FUNCTION lerp! (a!, b!, t!)
  2. DEFINT A-Z
  3.  
  4. '----------------------------------------
  5. ' Elevator Shaft Simulation!
  6. ' aka.  How camera tilting works in a ray surfer
  7. '----------------------------------------
  8. ' Created by Dan McKinnon (dan@danmckinnon.net)
  9. '
  10. ' In a classic ray-casting algorithm you normally
  11. ' only cast vertical lines from the bottom of the
  12. ' screen to the top. When you attempt to tilt
  13. ' your camera (thus spreading out the rays) this
  14. ' produces an inaccurate sheering effect limiting
  15. ' the range of movement and distorting the view.
  16. '
  17. ' To overcome this limitation we switch to
  18. ' projecting non-vertical lines.
  19. '
  20. ' I've spread the rays for demonstration purposes:
  21. '  - Vertical lines = FORWARD
  22. '  - Converging lines = DOWN
  23. '
  24. ' Think of it like you're looking down a really
  25. ' long elevator shaft
  26. '
  27. '
  28. ' Enjoy
  29.  
  30. ' Note:  The range of angles is limited to 90
  31. ' degrees. If we wanted to overcome this we'd
  32. ' divide pitch angles into four 90 degree
  33. ' quadrants and swizzle the axes.  It's
  34. ' important to note that once you tilt
  35. ' by 45 degrees it becomes more efficient
  36. ' to swizzle the algorithm so that down
  37. ' becomes forward, forward becomes up, etc.
  38. '
  39. '----------------------------------------
  40.  
  41. 'Universal constants
  42. CONST TAU = 6.283183
  43. CONST PI = TAU / 2!
  44. CONST DegToRad = TAU / 360!
  45.  
  46. 'Graphics mode constants
  47. CONST ScreenWidth = 320
  48. CONST ScreenHeight = 200
  49.  
  50. 'Algorithm constants
  51. CONST HalfScreenHeight = ScreenHeight / 2
  52. CONST nadirX = ScreenWidth / 2
  53. CONST MinPitch = 0!
  54. CONST MaxPitch = TAU / 4
  55.  
  56. '-------------------- Our Preferences --------------------
  57. CONST PitchStep = 5! * DegToRad
  58. CONST RaySpacingMax = 12
  59. CONST RaySpacingMin = 6
  60.  
  61.  
  62. '-------------------- vec2 --------------------
  63. 'Single Precision 2D Vector
  64. TYPE vec2
  65.    x AS SINGLE
  66.    y AS SINGLE
  67. END TYPE
  68.  
  69. DIM pitch AS SINGLE
  70.  
  71. pitch = 0!
  72. SCREEN 7, , 0, 1
  73.  
  74. '-------------------- Main Loop --------------------
  75. DO
  76.      
  77.       'Switch to draw back buffer
  78.       SCREEN 7, , 1
  79.       CLS
  80.  
  81.       '-------------------- Calculate --------------------
  82.       'nadir is perpendicular to the vanishing point
  83.       sinValue! = SIN(pitch)
  84.  
  85.       'Calculate the nadirY (use y! as a temporary single because nadirY is integer)
  86.       s! = 1 / sinValue!
  87.       y! = (HalfScreenHeight * s!)
  88.      
  89.       'Interpolate the ray spacing
  90.       raySpacing = CINT(lerp!(RaySpacingMin, RaySpacingMax, sinValue!))
  91.  
  92.       'A hack for when we approach zero with our pitch, sometimes it
  93.       'seems QBASIC's line function hits more edge cases without this
  94.       IF y! > 32767! THEN nadirY = 32767! ELSE nadirY = CINT(y!)
  95.  
  96.       'Calculate the ray spacing for the vertical direction
  97.       y! = raySpacing / sinValue!
  98.       verticalStep = CINT(y!)
  99.      
  100.       'Draw lines from the Nadir to the top of the screen (if necessary)
  101.       IF nadirY > 0 THEN
  102.          FOR x = 0 TO ScreenWidth - 1 STEP raySpacing
  103.             LINE (nadirX, nadirY)-(x, 0), 12
  104.          NEXT x
  105.       END IF
  106.  
  107.       'Draw lines from the Nadir to the bottom of the screen (if necessary)
  108.       IF nadirY < ScreenHeight AND nadirY > 0 THEN
  109.          FOR x = 0 TO ScreenWidth - 1 STEP raySpacing
  110.             LINE (nadirX, nadirY)-(x, ScreenHeight - 1), 1
  111.          NEXT x
  112.       END IF
  113.  
  114.       'Draw lines from the nadir to the left of the screen
  115.       FOR y = 0 TO ScreenHeight - 1 STEP verticalStep
  116.          LINE (nadirX, nadirY)-(0, y), 14
  117.       NEXT y
  118.  
  119.       'Draw lines from the nadir to the right of the screen
  120.       FOR y = 0 TO ScreenHeight - 1 STEP verticalStep
  121.          LINE (nadirX, nadirY)-(ScreenWidth - 1, y), 13
  122.       NEXT y
  123.      
  124.  
  125.    '-------------------- Handle Input --------------------
  126.    DO
  127.       k$ = INKEY$
  128.    LOOP UNTIL k$ <> ""
  129.  
  130.    SELECT CASE k$
  131.       CASE CHR$(0) + "H":
  132.          IF pitch > MinPitch THEN pitch = pitch - PitchStep ELSE pitch = MinPitch
  133.       CASE CHR$(0) + "P":
  134.          IF pitch < MaxPitch THEN pitch = pitch + PitchStep ELSE pitch = MaxPitch
  135.    END SELECT
  136.  
  137.    '-------------------- VSync --------------------
  138.    WAIT &H3DA, 8
  139.    SCREEN 7, , 0, 1
  140.      
  141.  
  142. LOOP UNTIL k$ = CHR$(27)
  143.  
  144. FUNCTION lerp! (a!, b!, t!)
  145.    lerp! = (b! - a!) * t! + a!
  146. END FUNCTION
  147.  
  148.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement