Author Topic: Galleon's Minecraft - what did I do to make it run so slow?  (Read 2599 times)

0 Members and 1 Guest are viewing this topic.

Offline madscijr

  • Seasoned Forum Regular
  • Posts: 295
    • View Profile
Galleon's Minecraft - what did I do to make it run so slow?
« on: November 29, 2021, 12:02:46 pm »
Over the weekend I tried playing with the QB Minecraft from
https://www.qb64.org/forum/index.php?topic=1199.0

The unmodded program runs nice and quick,
but my changes seem to really bog it down,
and I'm not sure why.

Changes are
  • modified to get all the input from the keyboard (no mouse)
  • changed which keys do what
  • added a new world generator

Apart from checking for the different keyboard input,
the main game loop itself isn't any different, so I'm not sure why it's slower.

If anyone has any interest in looking at this,
and offering some advice on speeding it up,
that would be most appreciated!

Code: QB64: [Select]
  1. ' #############################################################################
  2. ' NOTES:
  3.  
  4. ' https://www.qb64.org/forum/index.php?topic=3949.0
  5. ' SpriggsySpriggs:
  6. ' To make a console in QB64 you need to use the metacommand $CONSOLE.
  7. ' You toggle it ON or OFF with _CONSOLE ON or _CONSOLE OFF.
  8. ' _ECHO allows you to output to the window.
  9. ' Example:
  10. ' $CONSOLE
  11. ' _DELAY 4
  12. ' _CONSOLE ON
  13. ' _ECHO "Window Handle: "; STR$(imgScreen&)
  14. ' (etc)
  15. ' _CONSOLE OFF
  16.  
  17. ' =============================================================================
  18. ' GLOBAL DECLARATIONS a$=string, i%=integer, L&=long, s!=single, d#=double
  19.  
  20. ' boolean constants
  21. Const FALSE = 0
  22. Const TRUE = Not FALSE
  23.  
  24. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  25. ' KeyDownConstants
  26. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  27. Const c_iKeyDown_Esc = 27
  28. Const c_iKeyDown_F1 = 15104
  29. Const c_iKeyDown_F2 = 15360
  30. Const c_iKeyDown_F3 = 15616
  31. Const c_iKeyDown_F4 = 15872
  32. Const c_iKeyDown_F5 = 16128
  33. Const c_iKeyDown_F6 = 16384
  34. Const c_iKeyDown_F7 = 16640
  35. Const c_iKeyDown_F8 = 16896
  36. Const c_iKeyDown_F9 = 17152
  37. Const c_iKeyDown_F10 = 17408
  38. Const c_iKeyDown_Tilde = 96
  39. Const c_iKeyDown_1 = 49
  40. Const c_iKeyDown_2 = 50
  41. Const c_iKeyDown_3 = 51
  42. Const c_iKeyDown_4 = 52
  43. Const c_iKeyDown_5 = 53
  44. Const c_iKeyDown_6 = 54
  45. Const c_iKeyDown_7 = 55
  46. Const c_iKeyDown_8 = 56
  47. Const c_iKeyDown_9 = 57
  48. Const c_iKeyDown_0 = 48
  49. Const c_iKeyDown_Minus = 45
  50. Const c_iKeyDown_EqualPlus = 61
  51. Const c_iKeyDown_BkSp = 8
  52. Const c_iKeyDown_Ins = 20992
  53. Const c_iKeyDown_Home = 18176
  54. Const c_iKeyDown_PgUp = 18688
  55. Const c_iKeyDown_Del = 21248
  56. Const c_iKeyDown_End = 20224
  57. Const c_iKeyDown_PgDn = 20736
  58. Const c_iKeyDown_KEYPAD_7_Home = 18176
  59. Const c_iKeyDown_KEYPAD_8_Up = 18432
  60. Const c_iKeyDown_KEYPAD_9_PgUp = 18688
  61. Const c_iKeyDown_KEYPAD_4_Left = 19200
  62. Const c_iKeyDown_KEYPAD_6_Right = 19712
  63. Const c_iKeyDown_KEYPAD_1_End = 20224
  64. Const c_iKeyDown_KEYPAD_2_Down = 20480
  65. Const c_iKeyDown_KEYPAD_3_PgDn = 20736
  66. Const c_iKeyDown_KEYPAD_0_Ins = 20992
  67. Const c_iKeyDown_KEYPAD_Period_Del = 21248
  68. Const c_iKeyDown_Tab = 9
  69. Const c_iKeyDown_Q = 113
  70. Const c_iKeyDown_W = 119
  71. Const c_iKeyDown_E = 101
  72. Const c_iKeyDown_R = 114
  73. Const c_iKeyDown_T = 116
  74. Const c_iKeyDown_Y = 121
  75. Const c_iKeyDown_U = 117
  76. Const c_iKeyDown_Pipe = 105
  77. Const c_iKeyDown_O = 111
  78. Const c_iKeyDown_P = 112
  79. Const c_iKeyDown_BracketLeft = 91
  80. Const c_iKeyDown_BracketRight = 93
  81. Const c_iKeyDown_Backslash = 92
  82. Const c_iKeyDown_A = 97
  83. Const c_iKeyDown_S = 115
  84. Const c_iKeyDown_D = 100
  85. Const c_iKeyDown_F = 102
  86. Const c_iKeyDown_G = 103
  87. Const c_iKeyDown_H = 104
  88. Const c_iKeyDown_J = 106
  89. Const c_iKeyDown_K = 107
  90. Const c_iKeyDown_L = 108
  91. Const c_iKeyDown_SemiColon = 59
  92. Const c_iKeyDown_Apostrophe = 39
  93. Const c_iKeyDown_Enter = 13
  94. Const c_iKeyDown_Z = 22
  95. Const c_iKeyDown_X = 120
  96. Const c_iKeyDown_C = 99
  97. Const c_iKeyDown_V = 118
  98. Const c_iKeyDown_B = 98
  99. Const c_iKeyDown_N = 110
  100. Const c_iKeyDown_M = 109
  101. Const c_iKeyDown_Comma = 44
  102. Const c_iKeyDown_Period = 46
  103. Const c_iKeyDown_Slash = 47
  104. Const c_iKeyDown_Up = 18432
  105. Const c_iKeyDown_Left = 19200
  106. Const c_iKeyDown_Down = 20480
  107. Const c_iKeyDown_Right = 19712
  108. Const c_iKeyDown_Spacebar = 32
  109.  
  110. Const c_West = -1.5
  111. Const c_North = -3.65 ' 6.28
  112. Const c_East = 1.5
  113. Const c_South = 3.18
  114.  
  115. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  116.  
  117. Const MaxVis& = 15 ' how many squares away you can see (warning: massive performance implications at this stage)
  118. Const HardwareOnly& = 1 ' set to 1 to disable the software "SCREEN" (you will lose PRINTed debugging output but will get performance gains)
  119.  
  120. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  121. ' ACTIVATE DEBUGGING WINDOW
  122. '$CONSOLE
  123. '_DELAY 4
  124. '_CONSOLE ON
  125.  
  126. ' =============================================================================
  127. ' GLOBAL VARIABLES
  128. Dim ProgramPath$
  129. Dim ProgramName$
  130.  
  131. Dim i2$
  132. Dim iNum%
  133. Dim bFound As Integer
  134. Dim bMove As Integer
  135. Dim iCount As Integer
  136. Dim iLoop As Integer
  137.  
  138. Dim arrMap(16, 16) As String ' y, x
  139. 'DIM arrMap(16, 16, 16) AS STRING ' z, y, x
  140. Dim iLoopX%, iLoopY%, iLoopZ%
  141.  
  142. ' =============================================================================
  143. ' INITIALIZE
  144. ProgramName$ = Mid$(Command$(0), _InStrRev(Command$(0), "\") + 1)
  145. ProgramPath$ = Left$(Command$(0), _InStrRev(Command$(0), "\"))
  146.  
  147. Dim imgScreen&
  148.  
  149.  
  150.  
  151.  
  152.  
  153. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  154. ' FIND IMAGE FOLDER(S)
  155. If _DirExists("mycraft") Then ChDir "mycraft"
  156. If _DirExists("blocks") = 0 Or _DirExists("items") = 0 Then
  157.     Print "ERROR: Could not locate resource files."
  158.     Print "Please place the " + Chr$(34) + "blocks" + Chr$(34)
  159.     Print "and " + Chr$(34) + "items" + Chr$(34) + " folders"
  160.     Print "in the same folder as the program file."
  161.     Print ""
  162.     Input "Press <ENTER> to exit", i2$
  163.     End
  164.  
  165. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  166. ' SHOW SOME INSTRUCTIONS
  167. Print "Galleon's Mycraft"
  168. Print "From: https://www.qb64.org/forum/index.php?topic=1199.0"
  169. Print "Modifications:"
  170. Print "* Added this instruction screen"
  171. Print "* Added ESC key to exit program"
  172. Print "* Changed controls to all keyboard, no mouse"
  173. Print "* Played with world generation (random + from text map)"
  174. Print "Issues:"
  175. Print "* Runs much slower than original - why??"
  176. Print "CONTROL            ACTION"
  177. Print "-------            ------"
  178. Print "Crsr Left/right... turn right/left"
  179. Print "Page Up/Down...... look up/down"
  180. Print "Crsr Up........... walk forwards"
  181. Print "Crsr Down......... walk backwards"
  182. Print "Home.............. move vertically / jump (teleport up 1 square)"
  183. Print "End............... move vertically / down?"
  184. Print "<Spacebar>........ high jump / fly (teleport up 2 squares)"
  185. Print "<ESC>............. quit game"
  186. Input "Press <ENTER> to begin", in$
  187. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  188.  
  189.  
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197. DefLng A-Z
  198. '$DYNAMIC
  199.  
  200. Screen _NewImage(1024, 600, 32)
  201.  
  202. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  203. ' Generate Perlin Noise
  204. ' Modified from http://forum.qbasicnews.com/index.php?action=printpage;topic=3459.0
  205. ' -generates noise from 0 to 255
  206. ' -doesn't use x=0,y=0
  207. ' -noise tiles
  208. DefSng A-Z
  209. Iter = 8
  210. BumpFactor = 1.2
  211. CloudWidth% = 2 ^ Iter + 1
  212. CloudHeight% = 2 ^ Iter + 1
  213.  
  214. Dim Cloud%(CloudWidth%, CloudHeight%)
  215. Dim CloudBumpFactor(CloudWidth%, CloudHeight%) As Single
  216.  
  217. ' 1.5=undulating hills (mostly walkable, quite bumpy)
  218. ' 2.0=ultra-flat
  219.  
  220. Dim CloudDirectionBias(CloudWidth%, CloudHeight%) As Single '-0.3 to 0.3
  221. For x = 0 To CloudWidth%
  222.     For y = 0 To CloudHeight%
  223.         '1.3=perfect mountains
  224.         '1.5=plains
  225.         CloudBumpFactor(x, y) = 1.3 '1.4 '+ x * 0.002 '1.2 + x
  226.     Next y
  227. For x = 0 To CloudWidth%
  228.     For y = 0 To CloudHeight%
  229.         CloudDirectionBias(x, y) = 0 '0.3 'x * 0.0008 '1.1 + x * 0.004 '1.2 + x
  230.     Next y
  231.  
  232. T0 = Timer
  233.  
  234. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  235. ' Init the corners
  236. Cloud%(1, 1) = 128
  237. Cloud%(1, CloudHeight%) = 128
  238. Cloud%(CloudWidth%, 1) = 128
  239. Cloud%(CloudWidth%, CloudHeight%) = 128
  240.  
  241. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  242. ' Init the edges
  243. For Rank% = 1 To Iter
  244.     dx = 2 ^ (Iter - Rank% + 1)
  245.     dy = 2 ^ (Iter - Rank% + 1)
  246.     Nx% = 2 ^ (Rank% - 1) + 1
  247.     Ny% = 2 ^ (Rank% - 1) + 1
  248.    
  249.     For kx = 1 To Nx% - 1
  250.         x% = (kx - 1) * dx + 1: y% = 1
  251.         Alt% = (Cloud%(x%, y%) + Cloud%(x% + dx, y%)) / 2
  252.         'zNew% = Bump%(Alt%, Rank%, BumpFactor)
  253.         zNew% = Bump%(Alt%, Rank%, CloudBumpFactor(x% + dx / 2, 1), CloudDirectionBias(x% + dx / 2, 1))
  254.         Cloud%(x% + dx / 2, 1) = zNew%
  255.         Cloud%(x% + dx / 2, CloudHeight%) = zNew%
  256.     Next kx
  257.    
  258.     For ky = 1 To Ny% - 1
  259.         x% = 1: y% = (ky - 1) * dy + 1
  260.         Alt% = (Cloud%(x%, y%) + Cloud%(x%, y% + dy)) / 2
  261.         'zNew% = Bump%(Alt%, Rank%, BumpFactor)
  262.         zNew% = Bump%(Alt%, Rank%, CloudBumpFactor(1, y% + dy / 2), CloudDirectionBias(1, y% + dy / 2))
  263.         Cloud%(1, y% + dy / 2) = zNew%
  264.         Cloud%(CloudWidth%, y% + dy / 2) = zNew%
  265.     Next ky
  266. Next Rank%
  267.  
  268. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  269. ' Fill the clouds
  270. For Rank% = 1 To Iter
  271.     dx = 2 ^ (Iter - Rank% + 1): dy = dx
  272.     Nx% = 2 ^ (Rank% - 1) + 1: Ny% = Nx%
  273.    
  274.     For kx = 1 To Nx% - 1
  275.         For ky = 1 To Ny% - 1
  276.             x% = (kx - 1) * dx + 1
  277.             y% = (ky - 1) * dy + 1
  278.            
  279.             Alt% = (Cloud%(x%, y%) + Cloud%(x% + dx, y%) + Cloud%(x%, y% + dy) + Cloud%(x% + dx, y% + dy)) / 4
  280.             Cloud%(x% + dx / 2, y% + dy / 2) = Bump%(Alt%, Rank%, CloudBumpFactor(x% + dx / 2, y% + dy / 2), CloudDirectionBias(x% + dx / 2, y% + dy / 2))
  281.             Alt% = (Cloud%(x%, y%) + Cloud%(x% + dx, y%)) / 2
  282.             If y% <> 1 Then Cloud%(x% + dx / 2, y%) = Bump%(Alt%, Rank%, CloudBumpFactor(x% + dx / 2, y%), CloudDirectionBias(x% + dx / 2, y%))
  283.             Alt% = (Cloud%(x%, y%) + Cloud%(x%, y% + dy)) / 2
  284.             If x% <> 1 Then Cloud%(x%, y% + dy / 2) = Bump%(Alt%, Rank%, CloudBumpFactor(x%, y% + dy / 2), CloudDirectionBias(x%, y% + dy / 2))
  285.             Alt% = (Cloud%(x% + dx, y%) + Cloud%(x% + dx, y% + dy)) / 2
  286.             If (x% + dx) <> CloudWidth% Then Cloud%(x% + dx, y% + dy / 2) = Bump%(Alt%, Rank%, CloudBumpFactor(x% + dx, y% + dy / 2), CloudDirectionBias(x% + dx, y% + dy / 2))
  287.             Alt% = (Cloud%(x%, y% + dy) + Cloud%(x% + dx, y% + dy)) / 2
  288.             If (y% + dy) <> CloudHeight% Then Cloud%(x% + dx / 2, y% + dy) = Bump%(Alt%, Rank%, CloudBumpFactor(x% + dx / 2, y% + dy), CloudDirectionBias(x% + dx / 2, y% + dy))
  289.         Next ky
  290.     Next kx
  291. Next Rank%
  292. dt = Timer - T0
  293. For x = 0 To CloudWidth%
  294.     For y = 0 To CloudHeight%
  295.         PSet (x, y), _RGB(Cloud%(x, y), 0, 0)
  296.     Next y
  297.  
  298. DefLng A-Z
  299.  
  300. Dim Shared MapLimitX As Long, MapLimitY As Long, MapLimitZ As Long
  301. MapLimitX = CloudWidth% - 1 ' 256
  302. MapLimitY = CloudHeight% - 1 ' 256
  303. MapLimitZ = 100
  304.  
  305. '_ECHO "MapLimitX=" + cstrl$(MapLimitX)
  306. '_ECHO "MapLimitY=" + cstrl$(MapLimitY)
  307. '_ECHO "MapLimitZ=" + cstrl$(MapLimitZ)
  308. 'WaitForEnter
  309.  
  310.  
  311.  
  312.  
  313. Dim Shared TexLast
  314. TexLast = 0
  315. Dim Shared Tex(1000, 15, 3) As Long 'handle, brightness, hue-specific to time of day
  316.  
  317. Dim Shared darken
  318. darken = _NewImage(1, 1)
  319. _Dest darken
  320. PSet (0, 0), _RGBA(0, 0, 0, 50)
  321.  
  322.  
  323.  
  324.  
  325. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  326. ' DEFAULT STARTING LOCATION
  327. PX = 73
  328. PY = 78
  329. PZ = 2 ' start at ground level
  330. 'PZ = 70
  331.  
  332. ' DEFAULT STARTING ORIENTATION
  333. ax = c_North ' direction player is pointing
  334. ay = 0 ' viewing angle (up/down)
  335. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  336.  
  337. 'TYPE BoxType
  338. '    left AS LONG
  339. '    right AS LONG
  340. '    top AS LONG
  341. '    bottom AS LONG
  342. '    front AS LONG
  343. '    back AS LONG
  344. 'END TYPE ' BoxType
  345.  
  346. 'DIM SHARED Box(1000) AS BoxType
  347.  
  348. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  349. ' load textures
  350. grass = LoadTexture("grass")
  351. water = LoadTexture("water")
  352.  
  353. 'I = 0
  354. 'I = I + 1
  355.  
  356. 'h = grass
  357. 'Box(I).left = h
  358. 'Box(I).right = h
  359. 'Box(I).top = h
  360. 'Box(I).bottom = h
  361. 'Box(I).front = h
  362. 'Box(I).back = h
  363.  
  364. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  365. ' VARIABLES THAT HOLD THE WORLD
  366.  
  367. Type MapBlockType
  368.     Typ As Long '0=air, 1=...
  369.     Vis As Long
  370.     Lit As Long 'light offset
  371. End Type ' MapBlockType
  372.  
  373. Dim Blk(-1 To MapLimitX + 1, -1 To MapLimitY + 1, -1 To MapLimitZ + 1) As MapBlockType
  374.  
  375.  
  376.  
  377.  
  378. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  379. ' place bottom layer (a single layer of "rock" which cannot be crossed)
  380. z = 0
  381. For x = 0 To MapLimitX
  382.     For y = 0 To MapLimitY
  383.         Blk(x, y, z).Typ = 1: boxcount = boxcount + 1
  384.     Next y
  385.  
  386.  
  387.  
  388.  
  389.  
  390.  
  391.  
  392.  
  393.  
  394.  
  395.  
  396.  
  397. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  398. Dim GM(-1 To MapLimitX + 1, -1 To MapLimitY + 1)
  399.  
  400. ' get GM
  401. For x = 0 To MapLimitX
  402.     For y = 0 To MapLimitY
  403.         h = Cloud%(x + 1, y + 1) \ 4 + 30
  404.         GM(x, y) = h
  405.     Next y
  406.  
  407. For f = 5 To 8
  408.     ' despeckle "pinacles"
  409.     For x = 0 To MapLimitX
  410.         For y = 0 To MapLimitY
  411.             h = GM(x, y)
  412.             c = 0
  413.             c2 = 0
  414.             For x2 = x - 1 To x + 1
  415.                 For y2 = y - 1 To y + 1
  416.                     If x2 <> x Or y2 <> y Then
  417.                         h2 = GM(x2, y2)
  418.                         If h2 < h Then c = c + 1
  419.                         If h2 > h Then c2 = c2 + 1
  420.                     End If
  421.                 Next y2
  422.             Next x2
  423.             If c >= 5 Then
  424.                 GM(x, y) = GM(x, y) - 1
  425.                 'END
  426.                 'GM(x, y) = 2
  427.             End If
  428.             If c2 >= 5 Then
  429.                 GM(x, y) = GM(x, y) + 1
  430.             End If
  431.         Next y
  432.     Next x
  433.  
  434. wl = 128 \ 4 + 30 - 3 ' result = 59
  435.  
  436. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  437. ' place "dirt"
  438. For x = 0 To MapLimitX
  439.     For y = 0 To MapLimitY
  440.         zz = GM(x, y)
  441.         For z = zz To 1 Step -1
  442.             Blk(x, y, z).Typ = 1
  443.         Next z
  444.     Next y
  445.  
  446. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  447. ' place water
  448. For x = 0 To MapLimitX
  449.     For y = 0 To MapLimitY
  450.         zz = GM(x, y)
  451.         If zz < wl Then
  452.             Blk(x, y, wl).Typ = 2
  453.         End If
  454.     Next y
  455.  
  456.  
  457.  
  458.  
  459.  
  460.  
  461.  
  462.  
  463.  
  464.  
  465. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  466. ' BEGIN CLEAR WORLD
  467. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  468. ' z=0 = floor, layer of rock
  469. If 1 = 1 Then
  470.     For z = 1 To MapLimitZ
  471.         For x = 0 To MapLimitX
  472.             For y = 0 To MapLimitY
  473.                 Blk(x, y, z).Typ = 0
  474.             Next y
  475.         Next x
  476.     Next z
  477. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  478. ' END CLEAR WORLD
  479. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  480.  
  481.  
  482.  
  483. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  484. ' BEGIN TEMP DRAW WORLD #1
  485. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  486. ' 0 = air
  487. ' 1 = dirt
  488. ' 2 = water
  489. If 1 = 0 Then
  490.     'FOR z = 0 TO MapLimitZ
  491.     For z = 16 To (MapLimitZ - 16)
  492.         For x = 0 To MapLimitX
  493.             For y = 0 To MapLimitY
  494.                 'iNum% = RandomNumber%(1, 10)
  495.                 'if iNum% > 7 then
  496.                 iNum% = RandomNumber%(1, 20)
  497.                 If iNum% > 15 Then
  498.                    
  499.                     bFound = FALSE
  500.                    
  501.                     ' IS THERE A BLOCK UNDERNEATH?
  502.                     If Blk(x, y, z - 1).Typ = 1 Then
  503.                         bFound = TRUE
  504.                     Else
  505.                         ' IS THERE A BLOCK ADJACENT?
  506.                        
  507.                         If x > 0 Then
  508.                             If Blk(x - 1, y, z).Typ = 1 Then
  509.                                 bFound = TRUE
  510.                             End If
  511.                         End If
  512.                        
  513.                         If x < MapLimitX Then
  514.                             If Blk(x + 1, y, z).Typ = 1 Then
  515.                                 bFound = TRUE
  516.                             End If
  517.                         End If
  518.                        
  519.                         If y > 0 Then
  520.                             If Blk(x, y - 1, z).Typ = 1 Then
  521.                                 bFound = TRUE
  522.                             End If
  523.                         End If
  524.                        
  525.                         If y < MapLimitY Then
  526.                             If Blk(x, y + 1, z).Typ = 1 Then
  527.                                 bFound = TRUE
  528.                             End If
  529.                         End If
  530.                     End If
  531.                    
  532.                     If bFound = TRUE Then
  533.                         'iNum% = RandomNumber%(1, 10)
  534.                         iNum% = RandomNumber%(1, 20)
  535.                         'if iNum% > 4 then
  536.                         If iNum% > 15 Then
  537.                             Blk(x, y, z).Typ = 1
  538.                         End If
  539.                     End If
  540.                    
  541.                 Else
  542.                     Blk(x, y, z).Typ = 0
  543.                 End If
  544.             Next y
  545.         Next x
  546.     Next z
  547. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  548. ' END TEMP DRAW WORLD #1
  549. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  550.  
  551.  
  552.  
  553.  
  554.  
  555.  
  556.  
  557.  
  558. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  559. ' BEGIN TEMP DRAW WORLD #2 (draw pillars of varying height every 8 squares)
  560. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  561. ' 0 = air
  562. ' 1 = dirt
  563. ' 2 = water
  564. If 1 = 1 Then
  565.     iCount = 0
  566.     For x = 0 To MapLimitX Step 8
  567.         For y = 0 To MapLimitY Step 8
  568.             iCount = iCount + 2
  569.             If iCount > 8 Then
  570.                 iCount = 0
  571.             End If
  572.             For z = iCount To 1 Step -1
  573.                 Blk(x, y, z).Typ = 1
  574.             Next z
  575.         Next y
  576.     Next x
  577. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  578. ' END TEMP DRAW WORLD #2
  579. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  580.  
  581. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  582. ' BEGIN CLEAR SPACE AROUND #3
  583. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  584. If 1 = 1 Then
  585.     For z = 1 To MapLimitZ
  586.         For iLoopY% = LBound(arrMap, 1) To UBound(arrMap, 1) + 4
  587.             For iLoopX% = LBound(arrMap, 2) To UBound(arrMap, 2) + 4
  588.                 x = (iLoopX% + 62)
  589.                 y = (iLoopY% + 62)
  590.                
  591.                 Blk(x, y, z).Typ = 0
  592.             Next iLoopX%
  593.         Next iLoopY%
  594.     Next z
  595. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  596. ' END CLEAR SPACE AROUND #3
  597. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  598.  
  599. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  600. ' BEGIN TEMP DRAW WORLD #3 (defined in GetPyramidMap16x16$ and GetNextMapArray)
  601. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  602. 'DIM arrMap(16, 16) AS STRING ' y, x
  603. 'DIM iLoopX%, iLoopY%, iLoopZ%
  604. 'PRINT "ubound(arrMap,1 ) = " + STR$(UBOUND(arrMap, 1))
  605. 'PRINT "ubound(arrMap,2 ) = " + STR$(UBOUND(arrMap, 2))
  606. 'PRINT "ubound(arrMap,3 ) = " + STR$(UBOUND(arrMap, 2))
  607.  
  608. ''FOR z = 0 TO MapLimitZ
  609. 'FOR iLoopZ% = LBOUND(arrNextObject, 1) TO UBOUND(arrNextObject, 1)
  610. For iLoopZ% = 1 To 8
  611.     ' GET SLICE OF MAP FOR THE CURRENT LEVEL (iLoopZ%)
  612.     GetNextMapArray arrMap(), iLoopZ%
  613.    
  614.     For iLoopY% = LBound(arrMap, 1) To UBound(arrMap, 1)
  615.         For iLoopX% = LBound(arrMap, 2) To UBound(arrMap, 2)
  616.             x = (iLoopX% + 64)
  617.             y = (iLoopY% + 64)
  618.             z = iLoopZ%
  619.             If arrMap(iLoopY%, iLoopX%) = "#" Then
  620.                 Blk(x, y, z).Typ = 1
  621.             ElseIf arrMap(iLoopY%, iLoopX%) = "^" Then
  622.                 PX = x
  623.                 PY = y
  624.                 PZ = z + 1 ' for player we use z+1 for some reason
  625.                 ax = c_North ' direction player is pointing
  626.             ElseIf arrMap(iLoopY%, iLoopX%) = "v" Then
  627.                 PX = x
  628.                 PY = y
  629.                 PZ = z + 1 ' for player we use z+1 for some reason
  630.                 ax = c_South ' direction player is pointing
  631.             ElseIf arrMap(iLoopY%, iLoopX%) = "<" Then
  632.                 PX = x
  633.                 PY = y
  634.                 PZ = z + 1 ' for player we use z+1 for some reason
  635.                 ax = c_West ' direction player is pointing
  636.             ElseIf arrMap(iLoopY%, iLoopX%) = ">" Then
  637.                 PX = x
  638.                 PY = y
  639.                 PZ = z + 1 ' for player we use z+1 for some reason
  640.                 ax = c_East ' direction player is pointing
  641.             Else
  642.                 Blk(x, y, z).Typ = 0
  643.             End If
  644.         Next iLoopX%
  645.     Next iLoopY%
  646. Next iLoopZ%
  647.  
  648. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  649. ' END TEMP DRAW WORLD #3
  650. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  651.  
  652.  
  653.  
  654.  
  655.  
  656.  
  657.  
  658.  
  659.  
  660.  
  661.  
  662.  
  663.  
  664. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  665.  
  666. If 1 = 0 Then
  667.     zrange = 10
  668.     For basez = 1 To MapLimitZ - zrange - 50
  669.         For I = 1 To (MapLimitX * MapLimitY) * 10
  670.             x = Int(Rnd * (MapLimitX + 1))
  671.             y = Int(Rnd * (MapLimitY + 1))
  672.             z = basez + Int(Rnd * (10)) 'cannot replace lowest layer
  673.            
  674.             '''IF Blk(x, y, z).Typ = 0 AND Blk(x, y, z - 1).Typ <> 0 THEN
  675.             n = 0
  676.             For z2 = z - 1 To z + 1
  677.                 For y2 = y - 1 To y + 1
  678.                     For x2 = x - 1 To x + 1
  679.                         dist = Abs(x2 - x) + Abs(y2 - y) + Abs(z2 - z)
  680.                         If dist <= 2 Then
  681.                             x3 = x2: y3 = y2: z3 = z2
  682.                             MapOffset x3, y3, z3
  683.                             If Blk(x3, y3, z3).Typ > 0 Then
  684.                                 n = n + 1
  685.                             End If
  686.                         End If
  687.                     Next x2
  688.                 Next y2
  689.             Next z2
  690.            
  691.             If n >= 3 Then
  692.                 Blk(x, y, z).Typ = 1: boxcount = boxcount + 1
  693.                 If z > highestz Then highestz = z
  694.             End If
  695.             '''END IF
  696.         Next I
  697.     Next basez
  698.     ' fill map till top reached
  699.  
  700. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  701. ' assess visibility
  702. For z = 0 To MapLimitZ
  703.     For x = 0 To MapLimitX
  704.         For y = 0 To MapLimitY
  705.             If Blk(x, y, z).Typ Then
  706.                 visible = 0
  707.                 For x2 = x - 1 To x + 1
  708.                     If Blk(x2, y, z).Typ <> 1 Then visible = 1
  709.                 Next x2
  710.                 For y2 = y - 1 To y + 1
  711.                     If Blk(x, y2, z).Typ <> 1 Then visible = 1
  712.                 Next y2
  713.                 For z2 = z - 1 To z + 1
  714.                     If Blk(x, y, z2).Typ <> 1 Then visible = 1
  715.                 Next z2
  716.                
  717.                 If visible = 1 Then
  718.                     Blk(x, y, z).Vis = 1: viscount = viscount + 1
  719.                 End If
  720.             End If
  721.         Next y
  722.     Next x
  723.  
  724. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  725. ' assess lighting offsets
  726. For z = 0 To MapLimitZ
  727.     For x = 0 To MapLimitX
  728.         For y = 0 To MapLimitY
  729.             If Blk(x, y, z).Vis Then 'it is visible
  730.                 count = 0
  731.                 For z2 = z + 1 To z + 5
  732.                     For y2 = y - 1 To y + 1
  733.                         For x2 = x - 1 To x + 1
  734.                             If Blk(x2, y2, z2).Typ <> 0 Then count = count + 1
  735.                         Next x2
  736.                     Next y2
  737.                 Next z2
  738.                 If count > 30 Then count = 30
  739.                 Blk(x, y, z).Lit = -count / 2
  740.             End If
  741.         Next y
  742.     Next x
  743.  
  744. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  745.  
  746.  
  747. Type Point3D
  748.     x As Single
  749.     y As Single
  750.     z As Single
  751. End Type ' Point3D
  752.  
  753. Type TexturePoint3D
  754.     p As Point3D
  755.     tx As Single
  756.     ty As Single
  757. End Type ' TexturePoint3D
  758.  
  759. Type Triangle3D
  760.     p1 As TexturePoint3D
  761.     p2 As TexturePoint3D
  762.     p3 As TexturePoint3D
  763.     textureHandle As Long
  764. End Type ' Triangle3D
  765.  
  766. Type Rect3D
  767.     p1 As TexturePoint3D
  768.     p2 As TexturePoint3D
  769.     p3 As TexturePoint3D
  770.     p4 As TexturePoint3D
  771.     textureHandle As Long
  772. End Type ' Rect3D
  773.  
  774. Dim Shared vert(1 To 8) As Point3D
  775. Dim Shared side(1 To 6) As Rect3D
  776.  
  777. zz = -10
  778.  
  779. If HardwareOnly Then
  780.     bgImage = _NewImage(1, 1, 32)
  781.     _Dest bgImage
  782.     PSet (0, 0), _RGB(180, 220, 255)
  783.     _Dest 0
  784.     bgImage = _CopyImage(bgImage, 33)
  785.  
  786. ETT = Timer(0.001)
  787.  
  788. TOD = 0
  789.  
  790. 'gun32 = _LOADIMAGE("items\gun1.png", 32)
  791. gun32 = _LoadImage("items\sworddiamond.png", 32)
  792. gun = _CopyImage(gun32, 33)
  793.  
  794. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  795. ' sets of vertexes for scaling/rotation/etc
  796. Dim Shared VertexSource As Long
  797. Dim Shared VertexCount As Long 'the number of vertices to apply an operation to
  798. Dim Shared VertexLast As Long
  799. VertexLast = 0
  800. Dim Shared VertexX(1 To 10000) As Single
  801. Dim Shared VertexY(1 To 10000) As Single
  802. Dim Shared VertexZ(1 To 10000) As Single
  803. Dim Shared VertexTX(1 To 10000) As Single
  804. Dim Shared VertexTY(1 To 10000) As Single
  805.  
  806. Dim Shared TriangleSource As Long 'the base index of the first triangle's vertex
  807.  
  808. Dim Shared TriangleLast As Long
  809. TriangleLast = 0
  810. Dim Shared TriangleCount As Long 'the number of triangles to apply an operation to
  811. Dim Shared TriangleVertex(1 To 10000) As Long
  812.  
  813. Type MODEL
  814.     VertexCount As Long
  815.     FirstVertex As Long
  816.     FirstTriangle As Long
  817.     TriangleCount As Long
  818. End Type ' MODEL
  819. Dim Shared Model(1 To 10000) As MODEL
  820.  
  821. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  822. ' add object
  823. tex = gun
  824. tx = _Width(tex)
  825. ty = _Height(tex)
  826. p = VertexLast
  827. t = TriangleLast
  828. d = 1
  829.  
  830. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  831. ' convert 2D image into a 3D object by giving it depth
  832.  
  833. ' place image onto a canvas which has an extra unit on each size
  834. tex = gun32
  835. w = _Width(tex)
  836. h = _Height(tex)
  837. I = _NewImage(w + 2, h + 2, 32)
  838. _PutImage (1, 1), tex, I
  839.  
  840. Dim col As Long
  841. For y = 1 To h
  842.     For x = 1 To w
  843.         col = Point(x, y)
  844.         alpha = _Alpha(col)
  845.         col2 = Point(x, y - 1)
  846.         alpha2 = _Alpha(col2)
  847.        
  848.         If alpha2 = 0 And alpha <> 0 Then
  849.             x1 = x - 1
  850.             y1 = y - 1
  851.            
  852.             bp = p
  853.            
  854.             t = t + 1: TriangleVertex(t) = bp + 1
  855.             t = t + 1: TriangleVertex(t) = bp + 2
  856.             t = t + 1: TriangleVertex(t) = bp + 3
  857.             t = t + 1: TriangleVertex(t) = bp + 1
  858.             t = t + 1: TriangleVertex(t) = bp + 3
  859.             t = t + 1: TriangleVertex(t) = bp + 4
  860.            
  861.             p = p + 1: VertexX(p) = x1: VertexY(p) = -y1: VertexZ(p) = 0
  862.             VertexTX(p) = x1: VertexTY(p) = y1
  863.             p = p + 1: VertexX(p) = x1 + 1: VertexY(p) = -y1: VertexZ(p) = 0
  864.             VertexTX(p) = x1: VertexTY(p) = y1
  865.             p = p + 1: VertexX(p) = x1 + 1: VertexY(p) = -y1: VertexZ(p) = d
  866.             VertexTX(p) = x1: VertexTY(p) = y1
  867.             p = p + 1: VertexX(p) = x1: VertexY(p) = -y1: VertexZ(p) = d
  868.             VertexTX(p) = x1: VertexTY(p) = y1
  869.         End If
  870.        
  871.         col2 = Point(x - 1, y)
  872.         alpha2 = _Alpha(col2)
  873.        
  874.         If alpha2 = 0 And alpha <> 0 Then
  875.             x1 = x - 1
  876.             y1 = y - 1
  877.            
  878.             bp = p
  879.            
  880.             t = t + 1: TriangleVertex(t) = bp + 1
  881.             t = t + 1: TriangleVertex(t) = bp + 2
  882.             t = t + 1: TriangleVertex(t) = bp + 3
  883.             t = t + 1: TriangleVertex(t) = bp + 1
  884.             t = t + 1: TriangleVertex(t) = bp + 3
  885.             t = t + 1: TriangleVertex(t) = bp + 4
  886.            
  887.             p = p + 1: VertexX(p) = x1: VertexY(p) = -y1: VertexZ(p) = 0
  888.             VertexTX(p) = x1: VertexTY(p) = y1
  889.             p = p + 1: VertexX(p) = x1: VertexY(p) = -y1: VertexZ(p) = d
  890.             VertexTX(p) = x1: VertexTY(p) = y1
  891.             p = p + 1: VertexX(p) = x1: VertexY(p) = -y1 - 1: VertexZ(p) = d
  892.             VertexTX(p) = x1: VertexTY(p) = y1
  893.             p = p + 1: VertexX(p) = x1: VertexY(p) = -y1 - 1: VertexZ(p) = 0
  894.             VertexTX(p) = x1: VertexTY(p) = y1
  895.         End If
  896.     Next x
  897.  
  898.  
  899. itemPicture = I
  900.  
  901. For oz = 0 To d Step d
  902.     bp = p
  903.    
  904.     t = t + 1: TriangleVertex(t) = bp + 1
  905.     t = t + 1: TriangleVertex(t) = bp + 2
  906.     t = t + 1: TriangleVertex(t) = bp + 3
  907.     t = t + 1: TriangleVertex(t) = bp + 1
  908.     t = t + 1: TriangleVertex(t) = bp + 3
  909.     t = t + 1: TriangleVertex(t) = bp + 4
  910.    
  911.     p = p + 1: VertexX(p) = 0: VertexY(p) = 0: VertexZ(p) = oz
  912.     VertexTX(p) = -0.49: VertexTY(p) = -0.49
  913.     p = p + 1: VertexX(p) = tx: VertexY(p) = 0: VertexZ(p) = oz
  914.     VertexTX(p) = tx - 1 + 0.49: VertexTY(p) = -0.49
  915.     p = p + 1: VertexX(p) = tx: VertexY(p) = -ty: VertexZ(p) = oz
  916.     VertexTX(p) = tx - 1 + 0.49: VertexTY(p) = ty - 1 + 0.49
  917.     p = p + 1: VertexX(p) = 0: VertexY(p) = -ty: VertexZ(p) = oz
  918.     VertexTX(p) = -0.49: VertexTY(p) = ty - 1 + 0.49
  919. Next oz
  920.  
  921. VertexCount = p - VertexLast
  922. TriangleCount = (t - TriangleLast) \ 3
  923.  
  924. m = 1
  925. Model(m).VertexCount = VertexCount
  926. Model(m).FirstVertex = VertexLast + 1
  927. Model(m).TriangleCount = TriangleCount
  928. Model(m).FirstTriangle = TriangleLast + 1
  929.  
  930. VertexLast = p
  931. TriangleLast = t
  932.  
  933.  
  934.  
  935.  
  936.  
  937.  
  938.  
  939.  
  940.  
  941.  
  942.  
  943.  
  944.  
  945.  
  946.  
  947.  
  948. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  949. ' BEGIN MAIN GAME LOOP
  950. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  951.     T# = Timer(0.001)
  952.     ET = T# - ETT
  953.     ETT = T#
  954.    
  955.     TOD = TOD + ET
  956.     If TOD >= 24 Then TOD = TOD - 24
  957.    
  958.     SINax = Sin(ax)
  959.     COSax = Cos(ax)
  960.     SINay = Sin(ay)
  961.     COSay = Cos(ay)
  962.    
  963.     If HardwareOnly Then
  964.         _PutImage (0, 0)-(_Width - 1, _Height - 1), bgImage
  965.     Else
  966.         Cls , _RGB(180, 220, 255)
  967.     End If
  968.    
  969.     'LOCATE 1, 1
  970.     'PRINT TOD
  971.     'PRINT boxcount, viscount
  972.     'PRINT zz
  973.    
  974.     Randomize Timer 'USING 1
  975.    
  976.     OX = Int(PX)
  977.     OY = Int(PY)
  978.     oz = Int(PZ)
  979.    
  980.     'PRINT PX, PY, PZ
  981.     'PRINT OX, OY, oz
  982.    
  983.     x = OX
  984.     y = OY
  985.     z = oz
  986.    
  987.     MapOffset x, y, z
  988.    
  989.     'PRINT x, y, z, "!"
  990.    
  991.     _PutImage (0, 0), itemPicture
  992.    
  993.     nn = 0
  994.    
  995.     ' opaque pass
  996.     For mapz = oz + MaxVis To oz - MaxVis Step -1
  997.         For mapx = OX - MaxVis To OX + MaxVis
  998.             For mapy = OY - MaxVis To OY + MaxVis
  999.                 x = mapx
  1000.                 y = mapy
  1001.                 z = mapz
  1002.                 MapOffset x, y, z
  1003.                 If Blk(x, y, z).Vis Then
  1004.                     typ = Blk(x, y, z).Typ
  1005.                     If typ = 1 Then
  1006.                         DrawCube mapx - PX, mapz - PZ, mapy - PY, typ, Blk(x, y, z).Lit
  1007.                     End If
  1008.                 End If
  1009.             Next mapy
  1010.         Next mapx
  1011.     Next mapz
  1012.    
  1013.     ' semi-tranparent pass
  1014.     '_DEPTHBUFFER LOCK
  1015.     For mapz = oz - MaxVis To oz + MaxVis
  1016.         For mapx = OX - MaxVis To OX + MaxVis
  1017.             For mapy = OY - MaxVis To OY + MaxVis
  1018.                 x = mapx
  1019.                 y = mapy
  1020.                 z = mapz
  1021.                 MapOffset x, y, z
  1022.                 If Blk(x, y, z).Vis Then
  1023.                     typ = Blk(x, y, z).Typ
  1024.                     If typ = 2 Then
  1025.                         DrawCube mapx - PX, mapz - PZ, mapy - PY, typ, Blk(x, y, z).Lit
  1026.                     End If
  1027.                 End If
  1028.             Next mapy
  1029.         Next mapx
  1030.     Next mapz
  1031.    
  1032.     ' draw object(s)
  1033.    
  1034.     ' preserve offsets of permanent content
  1035.     oldVertexLast = VertexLast
  1036.     oldTriangleLast = TriangleLast
  1037.    
  1038.     VertexSource = Model(1).FirstVertex
  1039.     TriangleSource = Model(1).FirstTriangle
  1040.     TriangleCount = Model(1).TriangleCount
  1041.     VertexCount = Model(1).VertexCount
  1042.    
  1043.     TriangleSource = TriangleLast + 1
  1044.     VertexSource = VertexLast + 1
  1045.     CopyModel (1)
  1046.    
  1047.     tex = gun
  1048.    
  1049.     ' orient pointing forwards
  1050.     VertexRotateXZ_YZ -90, 0
  1051.    
  1052.     ' scale
  1053.     VertexScale 0.1 * 0.7 * 2
  1054.    
  1055.     ' move to right hand
  1056.     VertexTranslate 1, 0, -2 - 0.5
  1057.    
  1058.     ' render the objects
  1059.    
  1060.     For t = TriangleSource To TriangleSource + TriangleCount * 3 - 3 Step 3
  1061.         p1 = TriangleVertex(t)
  1062.         p2 = TriangleVertex(t + 1)
  1063.         p3 = TriangleVertex(t + 2)
  1064.         _MapTriangle (VertexTX(p1), VertexTY(p1))-(VertexTX(p2), VertexTY(p2))-(VertexTX(p3), VertexTY(p3)), tex To(VertexX(p1), VertexY(p1), VertexZ(p1))-(VertexX(p2), VertexY(p2), VertexZ(p2))-(VertexX(p3), VertexY(p3), VertexZ(p3))
  1065.     Next t
  1066.    
  1067.    
  1068.    
  1069.     bMove = FALSE
  1070.    
  1071.     ' -----------------------------------------------------------------------------
  1072.     ' move vertically
  1073.     ms! = 0.1
  1074.     'IF _KEYDOWN(ASC("q")) THEN
  1075.     If _KeyDown(c_iKeyDown_Home) Then
  1076.         PZ = PZ + ms! * 4
  1077.         'bMove = TRUE
  1078.     End If
  1079.    
  1080.     'IF _KEYDOWN(ASC("z")) THEN
  1081.     If _KeyDown(c_iKeyDown_End) Then
  1082.         PZ = PZ - ms! * 4
  1083.         'bMove = TRUE
  1084.     End If
  1085.    
  1086.     oPX = PX: oPY = PY: oPZ = PZ
  1087.    
  1088.     ' -----------------------------------------------------------------------------
  1089.     ' SPACE = JUMP
  1090.     ' c_iKeyDown_Spacebar
  1091.     Do
  1092.         'k$ = INKEY$
  1093.         'IF k$ = " " THEN 'jump (teleport up 2 squares)
  1094.         If _KeyDown(c_iKeyDown_Spacebar) Then
  1095.             PZ = PZ + 2
  1096.             'bMove = TRUE
  1097.         End If
  1098.     Loop Until k$ = ""
  1099.    
  1100.     ' -----------------------------------------------------------------------------
  1101.     ' walk forwards
  1102.     'IF _KEYDOWN(ASC("w")) THEN
  1103.     If _KeyDown(c_iKeyDown_Up) Then
  1104.         PX = PX + Sin(ax) * ms!
  1105.         PY = PY - Cos(ax) * ms!
  1106.         'PZ = PZ + SIN(ay) * ms!
  1107.         'bMove = TRUE
  1108.     End If
  1109.    
  1110.     ' -----------------------------------------------------------------------------
  1111.     ' walk backwards
  1112.     'IF _KEYDOWN(ASC("s")) THEN
  1113.     If _KeyDown(c_iKeyDown_Down) Then
  1114.         PX = PX - Sin(ax) * ms!
  1115.         PY = PY + Cos(ax) * ms!
  1116.         'PZ = PZ - SIN(ay) * ms!
  1117.         'bMove = TRUE
  1118.     End If
  1119.    
  1120.     ' -----------------------------------------------------------------------------
  1121.     ' get coordinates
  1122.     If _KeyDown(c_iKeyDown_Enter) Then
  1123.         bMove = TRUE
  1124.     End If
  1125.    
  1126.    
  1127.    
  1128.     ' -----------------------------------------------------------------------------
  1129.    
  1130.     PZ = PZ - 1 * ms!
  1131.    
  1132.     x = Int(PX)
  1133.     y = Int(PY)
  1134.     z = Int(PZ)
  1135.    
  1136.     MapOffset x, y, z
  1137.    
  1138.     t = Blk(x, y, z).Typ
  1139.    
  1140.     If t = 1 Then
  1141.         'PX = oPX
  1142.         'PY = oPY
  1143.         'PZ = oPZ
  1144.     End If
  1145.    
  1146.     ' calculate x/y/z dist to adjacent blocks
  1147.    
  1148.     ' check z movement
  1149.     newpx! = PX
  1150.     newpy! = PY
  1151.     newpz! = PZ
  1152.    
  1153.     PX = oPX
  1154.     PY = oPY
  1155.     PZ = newpz!
  1156.    
  1157.     x = Int(PX)
  1158.     y = Int(PY)
  1159.     z = Int(PZ)
  1160.    
  1161.     ox! = PX - Int(PX)
  1162.     oy! = PY - Int(PY)
  1163.     oz! = PZ - Int(PZ)
  1164.    
  1165.     ' IF PX >= 0 THEN
  1166.     dx1! = ox!
  1167.     dx2! = 1 - ox!
  1168.     ' ELSE
  1169.     '     dx2! = ox!
  1170.     '     dx1! = 1 - ox!
  1171.     ' END IF
  1172.    
  1173.     ' IF PY >= 0 THEN
  1174.     dy1! = oy!
  1175.     dy2! = 1 - oy!
  1176.     ' ELSE
  1177.     '     dy2! = oy!
  1178.     '     dy1! = 1 - oy!
  1179.     ' END IF
  1180.    
  1181.     ' IF PZ >= 0 THEN
  1182.     dz1! = oz!
  1183.     dz2! = 1 - oz!
  1184.     ' ELSE
  1185.     '     dz2! = oz!
  1186.     '     dz1! = 1 - oz!
  1187.     ' END IF
  1188.    
  1189.     'PRINT
  1190.     'PRINT PX; PY; PZ
  1191.     'PRINT dx1!; dx2!; dy1!; dy2!; dz1!; dz2!;
  1192.     'PRINT
  1193.    
  1194.     For z2 = z - 1 To z + 1
  1195.         relevant = 0
  1196.         If z2 = z Then relevant = 0 ' if we are already in the square--too bad!
  1197.        
  1198.         'IF z2 <> z THEN
  1199.         'check z relevance
  1200.         'relvant = 0
  1201.         If z2 < z And dz1! < 0.4 Then relevant = 1
  1202.         If z2 > z And dz2! < 0.4 Then relevant = 1
  1203.         'IF relevant THEN PRINT z2
  1204.        
  1205.         If relevant Then
  1206.             For y2 = y - 1 To y + 1
  1207.                 For x2 = x - 1 To x + 1
  1208.                     dx = Abs(x2 - x)
  1209.                     dy = Abs(y2 - y)
  1210.                     relevant = 0
  1211.                     If dx + dy Then
  1212.                         ' check if location should be checked
  1213.                         dx! = 0
  1214.                         If x2 > x Then dx! = dx2!
  1215.                         If x2 < x Then dx! = dx1!
  1216.                         dy! = 0
  1217.                         If y2 > y Then dy! = dy2!
  1218.                         If y2 < y Then dy! = dy1!
  1219.                         If dx! < 0.4 And dy! < 0.4 Then
  1220.                             relevant = 1
  1221.                             'PRINT "["; x2 - x; ","; y2 - y; "]";
  1222.                         End If
  1223.                     Else
  1224.                         relevant = 1
  1225.                     End If
  1226.                     'END IF
  1227.                    
  1228.                     If relevant Then
  1229.                         x3 = x2: y3 = y2: z3 = z2
  1230.                         MapOffset x3, y3, z3
  1231.                         t2 = Blk(x3, y3, z3).Typ
  1232.                         If t2 = 1 Then
  1233.                             'PZ = oPZ
  1234.                             newpz! = oPZ
  1235.                         End If
  1236.                     End If
  1237.                 Next x2
  1238.             Next y2
  1239.         End If
  1240.     Next z2
  1241.    
  1242.     PX = newpx!
  1243.     PY = oPY
  1244.     PZ = newpz!
  1245.    
  1246.     x = Int(PX)
  1247.     y = Int(PY)
  1248.     z = Int(PZ)
  1249.    
  1250.     ox! = PX - Int(PX)
  1251.     oy! = PY - Int(PY)
  1252.     oz! = PZ - Int(PZ)
  1253.    
  1254.     ' IF PX >= 0 THEN
  1255.     dx1! = ox!
  1256.     dx2! = 1 - ox!
  1257.     ' ELSE
  1258.     '     dx2! = ox!
  1259.     '     dx1! = 1 - ox!
  1260.     ' END IF
  1261.    
  1262.     ' IF PY >= 0 THEN
  1263.     dy1! = oy!
  1264.     dy2! = 1 - oy!
  1265.     ' ELSE
  1266.     '     dy2! = oy!
  1267.     '     dy1! = 1 - oy!
  1268.     ' END IF
  1269.    
  1270.     ' IF PZ >= 0 THEN
  1271.     dz1! = oz!
  1272.     dz2! = 1 - oz!
  1273.     ' ELSE
  1274.     '     dz2! = oz!
  1275.     '     dz1! = 1 - oz!
  1276.     ' END IF
  1277.    
  1278.     z2 = z
  1279.     For x2 = x - 1 To x + 1
  1280.         relevant = 0
  1281.         If x2 < x And dx1! < 0.4 Then relevant = 1
  1282.         If x2 > x And dx2! < 0.4 Then relevant = 1
  1283.         If relevant Then
  1284.             For y2 = y - 1 To y + 1
  1285.                 For z2 = z - 1 To z + 1
  1286.                     dy = Abs(y2 - y)
  1287.                     dz = Abs(z2 - z)
  1288.                    
  1289.                     relevant = 0
  1290.                    
  1291.                     If dy + dz Then
  1292.                         ' check if location should be checked
  1293.                         dz! = 0
  1294.                         If z2 > z Then dz! = dz2!
  1295.                         If z2 < z Then dz! = dz1!
  1296.                        
  1297.                         dy! = 0
  1298.                         If y2 > y Then dy! = dy2!
  1299.                         If y2 < y Then dy! = dy1!
  1300.                        
  1301.                         If dy! < 0.4 And dz! < 0.4 Then
  1302.                             relevant = 1
  1303.                         End If
  1304.                     Else
  1305.                         relevant = 1
  1306.                     End If
  1307.                    
  1308.                     If relevant Then
  1309.                         x3 = x2: y3 = y2: z3 = z2
  1310.                         MapOffset x3, y3, z3
  1311.                         t2 = Blk(x3, y3, z3).Typ
  1312.                         If t2 = 1 Then
  1313.                             'PX = oPX
  1314.                             newpx! = oPX
  1315.                         End If
  1316.                     End If
  1317.                 Next z2
  1318.             Next y2
  1319.         End If
  1320.     Next x2
  1321.    
  1322.     PX = newpx!
  1323.     PY = newpy!
  1324.     PZ = newpz!
  1325.    
  1326.     x = Int(PX)
  1327.     y = Int(PY)
  1328.     z = Int(PZ)
  1329.    
  1330.     ox! = PX - Int(PX)
  1331.     oy! = PY - Int(PY)
  1332.     oz! = PZ - Int(PZ)
  1333.    
  1334.     ' IF PX >= 0 THEN
  1335.     dx1! = ox!
  1336.     dx2! = 1 - ox!
  1337.     ' ELSE
  1338.     '     dx2! = ox!
  1339.     '     dx1! = 1 - ox!
  1340.     ' END IF
  1341.    
  1342.     ' IF PY >= 0 THEN
  1343.     dy1! = oy!
  1344.     dy2! = 1 - oy!
  1345.     ' ELSE
  1346.     '     dy2! = oy!
  1347.     '     dy1! = 1 - oy!
  1348.     ' END IF
  1349.    
  1350.     ' IF PZ >= 0 THEN
  1351.     dz1! = oz!
  1352.     dz2! = 1 - oz!
  1353.     ' ELSE
  1354.     '     dz2! = oz!
  1355.     '     dz1! = 1 - oz!
  1356.     ' END IF
  1357.    
  1358.     z2 = z
  1359.     For y2 = y - 1 To y + 1
  1360.         relevant = 0
  1361.         If y2 < y And dy1! < 0.4 Then relevant = 1
  1362.         If y2 > y And dy2! < 0.4 Then relevant = 1
  1363.         If relevant Then
  1364.             For z2 = z - 1 To z + 1
  1365.                 For x2 = x - 1 To x + 1
  1366.                     dx = Abs(x2 - x)
  1367.                     dz = Abs(z2 - z)
  1368.                    
  1369.                     relevant = 0
  1370.                     If dx + dz Then
  1371.                         ' check if location should be checked
  1372.                         dz! = 0
  1373.                         If z2 > z Then dz! = dz2!
  1374.                         If z2 < z Then dz! = dz1!
  1375.                        
  1376.                         dx! = 0
  1377.                         If x2 > x Then dx! = dx2!
  1378.                         If x2 < x Then dx! = dx1!
  1379.                        
  1380.                         If dx! < 0.4 And dz! < 0.4 Then
  1381.                             relevant = 1
  1382.                         End If
  1383.                     Else
  1384.                         relevant = 1
  1385.                     End If
  1386.                    
  1387.                     If relevant Then
  1388.                         x3 = x2: y3 = y2: z3 = z2
  1389.                         MapOffset x3, y3, z3
  1390.                         t2 = Blk(x3, y3, z3).Typ
  1391.                         If t2 = 1 Then
  1392.                             'PY = oPY
  1393.                             newpy! = oPY
  1394.                         End If
  1395.                     End If
  1396.                 Next x2
  1397.             Next z2
  1398.         End If
  1399.     Next y2
  1400.    
  1401.     PX = newpx!
  1402.     PY = newpy!
  1403.     PZ = newpz!
  1404.    
  1405.     'DO WHILE _MOUSEINPUT
  1406.     '    mmx = mmx + _MOUSEMOVEMENTX
  1407.     '    mmy = mmy + _MOUSEMOVEMENTY
  1408.     'LOOP
  1409.     'PRINT mmx, mmy
  1410.     '
  1411.     'ax = mmx / 100
  1412.     'ay = -mmy / 400
  1413.     '
  1414.     'my = _MOUSEY
  1415.     'MX = _MOUSEX
  1416.    
  1417.     ' -----------------------------------------------------------------------------
  1418.     ' turn left
  1419.     If _KeyDown(c_iKeyDown_Left) Then
  1420.         ax = ax - 0.05
  1421.         If ax < -6.28 Then
  1422.             ax = 6.28
  1423.         End If
  1424.         'bMove = TRUE
  1425.     End If
  1426.    
  1427.     ' -----------------------------------------------------------------------------
  1428.     ' turn right
  1429.     If _KeyDown(c_iKeyDown_Right) Then
  1430.         ax = ax + 0.05
  1431.         If ax > 6.28 Then
  1432.             ax = -6.28
  1433.         End If
  1434.         'bMove = TRUE
  1435.     End If
  1436.    
  1437.     ' -----------------------------------------------------------------------------
  1438.     ' turn up
  1439.     If _KeyDown(c_iKeyDown_PgUp) Then
  1440.         ay = ay - 0.05
  1441.         If ay < -1.65 Then
  1442.             ay = -1.65
  1443.         End If
  1444.         'bMove = TRUE
  1445.     End If
  1446.    
  1447.     ' -----------------------------------------------------------------------------
  1448.     ' turn down
  1449.     If _KeyDown(c_iKeyDown_PgDn) Then
  1450.         ay = ay + 0.05
  1451.         If ay > 1.65 Then
  1452.             ay = 1.65
  1453.         End If
  1454.         'bMove = TRUE
  1455.     End If
  1456.    
  1457.    
  1458.    
  1459.    
  1460.     '' ****************************************************************************************************************************************************************
  1461.     '' SHOW COORDS IN DEBUG WINDOW
  1462.     'IF bMove = TRUE THEN
  1463.     '    _ECHO "x=" + cstr$(x) + " " + "y=" + cstr$(y) + " " + "z=" + cstr$(z) + " " + "ax=" + cstrs$(ax) + " " + "ay=" + cstrs$(ay)
  1464.     'END IF
  1465.     '' ****************************************************************************************************************************************************************
  1466.    
  1467.    
  1468.    
  1469.    
  1470.     ' -----------------------------------------------------------------------------
  1471.    
  1472.     _Limit 30
  1473.     '_LIMIT 120
  1474.     _Display
  1475.    
  1476.     VertexLast = oldVertexLast
  1477.     TriangleLast = oldTriangleLast
  1478.    
  1479.         oldscreen = _Dest
  1480.        
  1481.        
  1482.         'imgScreen& = _NEWIMAGE(_RESIZEWIDTH, _RESIZEHEIGHT, 32)
  1483.         'SCREEN imgScreen&
  1484.        
  1485.         _FreeImage oldscreen
  1486.     End If
  1487.    
  1488.  
  1489.    
  1490.     ' -----------------------------------------------------------------------------
  1491.     ' SHOW COORDINATES ON SCREEN
  1492.     '_DEST imgScreen&
  1493.     'LOCATE 2, 2 : PRINT " ax=" + cstrs$(ax)
  1494.     'LOCATE 2, 2 : PRINT " ay=" + cstrs$(ay)
  1495.     '_ECHO "ax=" + cstrs$(ax) + " " + "ay=" + cstrs$(ay)
  1496.    
  1497.     ' -----------------------------------------------------------------------------
  1498.     ' ESC = QUIT
  1499.     If _KeyDown(c_iKeyDown_Esc) Then
  1500.         Exit Do
  1501.     End If
  1502.    
  1503. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1504. ' END MAIN GAME LOOP
  1505. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1506.  
  1507.  
  1508.  
  1509.  
  1510.  
  1511.  
  1512.  
  1513.  
  1514.  
  1515.  
  1516.  
  1517.  
  1518.  
  1519.  
  1520.  
  1521.  
  1522. ' =============================================================================
  1523. ' FINISH
  1524.  
  1525. '' -----------------------------------------------------------------------------
  1526. '' DEACTIVATE DEBUGGING WINDOW
  1527. '_CONSOLE OFF
  1528.  
  1529.  
  1530. System ' return control to the operating system
  1531. Print ProgramName$ + " finished."
  1532.  
  1533.  
  1534.  
  1535.  
  1536.  
  1537.  
  1538.  
  1539. ' ################################################################################################################################################################
  1540. ' BEGIN WORLD ROUTINES
  1541. ' ################################################################################################################################################################
  1542.  
  1543. ' /////////////////////////////////////////////////////////////////////////////
  1544.  
  1545. Function GetBlankMap16x16$
  1546.     Dim m$
  1547.     m$ = ""
  1548.     '                                                                                                             1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111222222222222222222222222222222222222222222222222222222222
  1549.     '                   1111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999000000000011111111112222222222333333333344444444445555555
  1550.     '          1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456
  1551.     m$ = m$ + "................" + Chr$(13)
  1552.     m$ = m$ + "................" + Chr$(13)
  1553.     m$ = m$ + "................" + Chr$(13)
  1554.     m$ = m$ + "................" + Chr$(13)
  1555.     m$ = m$ + "................" + Chr$(13)
  1556.     m$ = m$ + "................" + Chr$(13)
  1557.     m$ = m$ + "................" + Chr$(13)
  1558.     m$ = m$ + "................" + Chr$(13)
  1559.     m$ = m$ + "................" + Chr$(13)
  1560.     m$ = m$ + "................" + Chr$(13)
  1561.     m$ = m$ + "................" + Chr$(13)
  1562.     m$ = m$ + "................" + Chr$(13)
  1563.     m$ = m$ + "................" + Chr$(13)
  1564.     m$ = m$ + "................" + Chr$(13)
  1565.     m$ = m$ + "................" + Chr$(13)
  1566.     m$ = m$ + "................" + Chr$(13)
  1567.     GetBlankMap16x16$ = m$
  1568. End Function ' GetBlankMap16x16$
  1569.  
  1570. ' /////////////////////////////////////////////////////////////////////////////
  1571. '   air: 0
  1572. ' dirt : Blk(x, y, z).Typ = 1
  1573. ' water: Blk(x, y, wl).Typ = 2
  1574.  
  1575. ' TEXT    VALUE   MAP    TYPE                  COMMENT
  1576. ' .       46      0      open space            can move freely
  1577. ' G       71      ?      grass                 can walk on
  1578. ' ~       126     2      water                 can move freely through
  1579. ' #       35      1      rock                  grass
  1580. ' %       37             stone                 (not in use yet)
  1581. ' S       83             sand                  (not in use yet)
  1582. ' W       88             wood                  (not in use yet)
  1583. ' @       64             lava                  (not in use yet)
  1584. ' ^       94             player facing north   starting position of player
  1585. ' v       118            player facing south   starting position of player
  1586. ' <       60             player facing west    starting position of player
  1587. ' >       62             player facing east    starting position of player
  1588.  
  1589. ' Receives iY% = which level to return map for
  1590. ' Returns string with map for level iY%
  1591. ' delimited by CHR$(13)
  1592. Function GetPyramidMap16x16$ (iY%)
  1593.     Dim m$
  1594.     m$ = ""
  1595.     If iY% = 1 Then
  1596.         m$ = m$ + "................" + Chr$(13)
  1597.         m$ = m$ + ".####......####." + Chr$(13)
  1598.         m$ = m$ + ".#............#." + Chr$(13)
  1599.         m$ = m$ + ".#............#." + Chr$(13)
  1600.         m$ = m$ + ".#............#." + Chr$(13)
  1601.         m$ = m$ + ".#............#." + Chr$(13)
  1602.         m$ = m$ + ".#............#." + Chr$(13)
  1603.         m$ = m$ + ".#............#." + Chr$(13)
  1604.         m$ = m$ + ".#............#." + Chr$(13)
  1605.         m$ = m$ + ".#............#." + Chr$(13)
  1606.         m$ = m$ + ".#............#." + Chr$(13)
  1607.         m$ = m$ + ".#............#." + Chr$(13)
  1608.         m$ = m$ + ".#.....^......#." + Chr$(13)
  1609.         m$ = m$ + ".#............#." + Chr$(13)
  1610.         m$ = m$ + ".##############." + Chr$(13)
  1611.         m$ = m$ + "................" + Chr$(13)
  1612.     ElseIf iY% = 2 Then
  1613.         m$ = m$ + "................" + Chr$(13)
  1614.         m$ = m$ + "................" + Chr$(13)
  1615.         m$ = m$ + "..####....####.." + Chr$(13)
  1616.         m$ = m$ + "..#..........#.." + Chr$(13)
  1617.         m$ = m$ + "..#..........#.." + Chr$(13)
  1618.         m$ = m$ + "................" + Chr$(13)
  1619.         m$ = m$ + "................" + Chr$(13)
  1620.         m$ = m$ + "..#..........#.." + Chr$(13)
  1621.         m$ = m$ + "..#..........#.." + Chr$(13)
  1622.         m$ = m$ + "................" + Chr$(13)
  1623.         m$ = m$ + "................" + Chr$(13)
  1624.         m$ = m$ + "..#..........#.." + Chr$(13)
  1625.         m$ = m$ + "..#..........#.." + Chr$(13)
  1626.         m$ = m$ + "..###..##..###.." + Chr$(13)
  1627.         m$ = m$ + "................" + Chr$(13)
  1628.         m$ = m$ + "................" + Chr$(13)
  1629.     ElseIf iY% = 3 Then
  1630.         m$ = m$ + "................" + Chr$(13)
  1631.         m$ = m$ + "................" + Chr$(13)
  1632.         m$ = m$ + "................" + Chr$(13)
  1633.         m$ = m$ + "...####..####..." + Chr$(13)
  1634.         m$ = m$ + "...#........#..." + Chr$(13)
  1635.         m$ = m$ + "...#........#..." + Chr$(13)
  1636.         m$ = m$ + "...#........#..." + Chr$(13)
  1637.         m$ = m$ + "...##########..." + Chr$(13)
  1638.         m$ = m$ + "...#........#..." + Chr$(13)
  1639.         m$ = m$ + "...#........#..." + Chr$(13)
  1640.         m$ = m$ + "...#........#..." + Chr$(13)
  1641.         m$ = m$ + "...#........#..." + Chr$(13)
  1642.         m$ = m$ + "...##########..." + Chr$(13)
  1643.         m$ = m$ + "................" + Chr$(13)
  1644.         m$ = m$ + "................" + Chr$(13)
  1645.         m$ = m$ + "................" + Chr$(13)
  1646.     ElseIf iY% = 4 Then
  1647.         m$ = m$ + "................" + Chr$(13)
  1648.         m$ = m$ + "................" + Chr$(13)
  1649.         m$ = m$ + "................" + Chr$(13)
  1650.         m$ = m$ + "................" + Chr$(13)
  1651.         m$ = m$ + "....########...." + Chr$(13)
  1652.         m$ = m$ + "....#......#...." + Chr$(13)
  1653.         m$ = m$ + "....#......#...." + Chr$(13)
  1654.         m$ = m$ + "....#......#...." + Chr$(13)
  1655.         m$ = m$ + "....#......#...." + Chr$(13)
  1656.         m$ = m$ + "....#......#...." + Chr$(13)
  1657.         m$ = m$ + "....#......#...." + Chr$(13)
  1658.         m$ = m$ + "....########...." + Chr$(13)
  1659.         m$ = m$ + "................" + Chr$(13)
  1660.         m$ = m$ + "................" + Chr$(13)
  1661.         m$ = m$ + "................" + Chr$(13)
  1662.         m$ = m$ + "................" + Chr$(13)
  1663.     ElseIf iY% = 5 Then
  1664.         m$ = m$ + "................" + Chr$(13)
  1665.         m$ = m$ + "................" + Chr$(13)
  1666.         m$ = m$ + "................" + Chr$(13)
  1667.         m$ = m$ + "................" + Chr$(13)
  1668.         m$ = m$ + "................" + Chr$(13)
  1669.         m$ = m$ + ".....######....." + Chr$(13)
  1670.         m$ = m$ + ".....######....." + Chr$(13)
  1671.         m$ = m$ + ".....###.##....." + Chr$(13)
  1672.         m$ = m$ + ".....######....." + Chr$(13)
  1673.         m$ = m$ + ".....######....." + Chr$(13)
  1674.         m$ = m$ + ".....######....." + Chr$(13)
  1675.         m$ = m$ + "................" + Chr$(13)
  1676.         m$ = m$ + "................" + Chr$(13)
  1677.         m$ = m$ + "................" + Chr$(13)
  1678.         m$ = m$ + "................" + Chr$(13)
  1679.         m$ = m$ + "................" + Chr$(13)
  1680.     ElseIf iY% = 6 Then
  1681.         m$ = m$ + "................" + Chr$(13)
  1682.         m$ = m$ + "................" + Chr$(13)
  1683.         m$ = m$ + "................" + Chr$(13)
  1684.         m$ = m$ + "................" + Chr$(13)
  1685.         m$ = m$ + "................" + Chr$(13)
  1686.         m$ = m$ + "................" + Chr$(13)
  1687.         m$ = m$ + "......####......" + Chr$(13)
  1688.         m$ = m$ + "......##.#......" + Chr$(13)
  1689.         m$ = m$ + "......####......" + Chr$(13)
  1690.         m$ = m$ + "......####......" + Chr$(13)
  1691.         m$ = m$ + "................" + Chr$(13)
  1692.         m$ = m$ + "................" + Chr$(13)
  1693.         m$ = m$ + "................" + Chr$(13)
  1694.         m$ = m$ + "................" + Chr$(13)
  1695.         m$ = m$ + "................" + Chr$(13)
  1696.         m$ = m$ + "................" + Chr$(13)
  1697.     ElseIf iY% = 7 Then
  1698.         m$ = m$ + "................" + Chr$(13)
  1699.         m$ = m$ + "................" + Chr$(13)
  1700.         m$ = m$ + "................" + Chr$(13)
  1701.         m$ = m$ + "................" + Chr$(13)
  1702.         m$ = m$ + "................" + Chr$(13)
  1703.         m$ = m$ + "................" + Chr$(13)
  1704.         m$ = m$ + "................" + Chr$(13)
  1705.         m$ = m$ + ".......#........" + Chr$(13)
  1706.         m$ = m$ + ".......##......." + Chr$(13)
  1707.         m$ = m$ + "................" + Chr$(13)
  1708.         m$ = m$ + "................" + Chr$(13)
  1709.         m$ = m$ + "................" + Chr$(13)
  1710.         m$ = m$ + "................" + Chr$(13)
  1711.         m$ = m$ + "................" + Chr$(13)
  1712.         m$ = m$ + "................" + Chr$(13)
  1713.         m$ = m$ + "................" + Chr$(13)
  1714.     ElseIf iY% = 8 Then
  1715.         m$ = m$ + "................" + Chr$(13)
  1716.         m$ = m$ + "................" + Chr$(13)
  1717.         m$ = m$ + "................" + Chr$(13)
  1718.         m$ = m$ + "................" + Chr$(13)
  1719.         m$ = m$ + "................" + Chr$(13)
  1720.         m$ = m$ + "................" + Chr$(13)
  1721.         m$ = m$ + "................" + Chr$(13)
  1722.         m$ = m$ + "................" + Chr$(13)
  1723.         m$ = m$ + "................" + Chr$(13)
  1724.         m$ = m$ + "................" + Chr$(13)
  1725.         m$ = m$ + "................" + Chr$(13)
  1726.         m$ = m$ + "................" + Chr$(13)
  1727.         m$ = m$ + "................" + Chr$(13)
  1728.         m$ = m$ + "................" + Chr$(13)
  1729.         m$ = m$ + "................" + Chr$(13)
  1730.         m$ = m$ + "................" + Chr$(13)
  1731.     Else
  1732.         m$ = m$ + "................" + Chr$(13)
  1733.         m$ = m$ + "................" + Chr$(13)
  1734.         m$ = m$ + "................" + Chr$(13)
  1735.         m$ = m$ + "................" + Chr$(13)
  1736.         m$ = m$ + "................" + Chr$(13)
  1737.         m$ = m$ + "................" + Chr$(13)
  1738.         m$ = m$ + "................" + Chr$(13)
  1739.         m$ = m$ + "................" + Chr$(13)
  1740.         m$ = m$ + "................" + Chr$(13)
  1741.         m$ = m$ + "................" + Chr$(13)
  1742.         m$ = m$ + "................" + Chr$(13)
  1743.         m$ = m$ + "................" + Chr$(13)
  1744.         m$ = m$ + "................" + Chr$(13)
  1745.         m$ = m$ + "................" + Chr$(13)
  1746.         m$ = m$ + "................" + Chr$(13)
  1747.         m$ = m$ + "................" + Chr$(13)
  1748.     End If
  1749.     GetPyramidMap16x16$ = m$
  1750. End Function ' GetPyramidMap16x16$
  1751.  
  1752. ' /////////////////////////////////////////////////////////////////////////////
  1753. ' VIRTUAL WORLD v1
  1754.  
  1755. Function GetMap$ (iY%)
  1756.     GetMap$ = GetPyramidMap16x16$(iY%)
  1757. End Function ' GetMap$
  1758.  
  1759. ' /////////////////////////////////////////////////////////////////////////////
  1760. ' Receives:
  1761. ' byref arrMap1 = 2D map array of string
  1762. ' iY% = which level to return map for
  1763. ' Returns 2D array with map for level iY%
  1764.  
  1765. Sub GetNextMapArray (arrMap1( 16 , 16) As String, iY%)
  1766.     Dim in$
  1767.     Dim delim$
  1768.     ReDim arrLines$(0)
  1769.     Dim iRow%
  1770.     Dim iCol%
  1771.     Dim sChar$
  1772.    
  1773.     delim$ = Chr$(13)
  1774.     in$ = GetMap$(iY%)
  1775.     split in$, delim$, arrLines$()
  1776.    
  1777.     For iRow% = LBound(arrLines$) To UBound(arrLines$)
  1778.         If iRow% <= 80 Then
  1779.             'PRINT "arrLines$(" + LTRIM$(RTRIM$(STR$(iRow%))) + ") = " + CHR$(34) + arrLines$(iRow%) + CHR$(34)
  1780.             For iCol% = 1 To Len(arrLines$(iRow%))
  1781.                 If iCol% <= 80 Then
  1782.                     sChar$ = Mid$(arrLines$(iRow%), iCol%, 1)
  1783.                     arrMap1(iRow%, iCol%) = sChar$
  1784.                 Else
  1785.                     ' Exit if out of bounds
  1786.                     Exit For
  1787.                 End If
  1788.             Next iCol%
  1789.         Else
  1790.             ' Exit if out of bounds
  1791.             Exit For
  1792.         End If
  1793.     Next iRow%
  1794. End Sub ' GetNextMapArray
  1795.  
  1796. ' ################################################################################################################################################################
  1797. ' END WORLD ROUTINES
  1798. ' ################################################################################################################################################################
  1799.  
  1800.  
  1801.  
  1802.  
  1803.  
  1804.  
  1805.  
  1806. ' /////////////////////////////////////////////////////////////////////////////
  1807.  
  1808. Function cstr$ (myValue)
  1809.     'cstr$ = LTRIM$(RTRIM$(STR$(myValue)))
  1810.     cstr$ = _Trim$(Str$(myValue))
  1811. End Function ' cstr$
  1812.  
  1813. ' /////////////////////////////////////////////////////////////////////////////
  1814.  
  1815. Function cstrl$ (myValue As Long)
  1816.     cstrl$ = _Trim$(Str$(myValue))
  1817. End Function ' cstrl$
  1818.  
  1819. ' /////////////////////////////////////////////////////////////////////////////
  1820.  
  1821. Function cstrs$ (myValue As Single)
  1822.     ''cstr$ = LTRIM$(RTRIM$(STR$(myValue)))
  1823.     cstrs$ = _Trim$(Str$(myValue))
  1824. End Function ' cstrs$
  1825.  
  1826. ' /////////////////////////////////////////////////////////////////////////////
  1827.  
  1828. Function IIF (Condition, IfTrue, IfFalse)
  1829.     If Condition Then IIF = IfTrue Else IIF = IfFalse
  1830.  
  1831. ' /////////////////////////////////////////////////////////////////////////////
  1832.  
  1833. Function IIFSTR$ (Condition, IfTrue$, IfFalse$)
  1834.     If Condition Then IIFSTR$ = IfTrue$ Else IIFSTR$ = IfFalse$
  1835.  
  1836. ' /////////////////////////////////////////////////////////////////////////////
  1837. ' From: Bitwise Manipulations By Steven Roman
  1838. ' http://www.romanpress.com/Articles/Bitwise_R/Bitwise.htm
  1839.  
  1840. ' Returns the 8-bit binary representation
  1841. ' of an integer iInput where 0 <= iInput <= 255
  1842.  
  1843. Function GetBinary$ (iInput1 As Integer)
  1844.     Dim sResult As String
  1845.     Dim iLoop As Integer
  1846.     Dim iInput As Integer: iInput = iInput1
  1847.  
  1848.     sResult = ""
  1849.  
  1850.     If iInput >= 0 And iInput <= 255 Then
  1851.         For iLoop = 1 To 8
  1852.             sResult = LTrim$(RTrim$(Str$(iInput Mod 2))) + sResult
  1853.             iInput = iInput \ 2
  1854.             'If iLoop = 4 Then sResult = " " + sResult
  1855.         Next iLoop
  1856.     End If
  1857.  
  1858.     GetBinary$ = sResult
  1859. End Function ' GetBinary$
  1860.  
  1861. ' /////////////////////////////////////////////////////////////////////////////
  1862. ' wonderfully inefficient way to read if a bit is set
  1863. ' ival = GetBit256%(int we are comparing, int containing the bits we want to read)
  1864.  
  1865. ' See also: GetBit256%, SetBit256%
  1866.  
  1867. Function GetBit256% (iNum1 As Integer, iBit1 As Integer)
  1868.     Dim iResult As Integer
  1869.     Dim sNum As String
  1870.     Dim sBit As String
  1871.     Dim iLoop As Integer
  1872.     Dim bContinue As Integer
  1873.     'DIM iTemp AS INTEGER
  1874.     Dim iNum As Integer: iNum = iNum1
  1875.     Dim iBit As Integer: iBit = iBit1
  1876.  
  1877.     iResult = FALSE
  1878.     bContinue = TRUE
  1879.  
  1880.     If iNum < 256 And iBit <= 128 Then
  1881.         sNum = GetBinary$(iNum)
  1882.         sBit = GetBinary$(iBit)
  1883.         For iLoop = 1 To 8
  1884.             If Mid$(sBit, iLoop, 1) = "1" Then
  1885.                 'if any of the bits in iBit are false, return false
  1886.                 If Mid$(sNum, iLoop, 1) = "0" Then
  1887.                     iResult = FALSE
  1888.                     bContinue = FALSE
  1889.                     Exit For
  1890.                 End If
  1891.             End If
  1892.         Next iLoop
  1893.         If bContinue = TRUE Then
  1894.             iResult = TRUE
  1895.         End If
  1896.     End If
  1897.  
  1898.     GetBit256% = iResult
  1899. End Function ' GetBit256%
  1900.  
  1901. ' /////////////////////////////////////////////////////////////////////////////
  1902. ' From: Bitwise Manipulations By Steven Roman
  1903. ' http://www.romanpress.com/Articles/Bitwise_R/Bitwise.htm
  1904.  
  1905. ' Returns the integer that corresponds to a binary string of length 8
  1906.  
  1907. Function GetIntegerFromBinary% (sBinary1 As String)
  1908.     Dim iResult As Integer
  1909.     Dim iLoop As Integer
  1910.     Dim strBinary As String
  1911.     Dim sBinary As String: sBinary = sBinary1
  1912.  
  1913.     iResult = 0
  1914.     strBinary = Replace$(sBinary, " ", "") ' Remove any spaces
  1915.     For iLoop = 0 To Len(strBinary) - 1
  1916.         iResult = iResult + 2 ^ iLoop * Val(Mid$(strBinary, Len(strBinary) - iLoop, 1))
  1917.     Next iLoop
  1918.  
  1919.     GetIntegerFromBinary% = iResult
  1920. End Function ' GetIntegerFromBinary%
  1921.  
  1922. ' /////////////////////////////////////////////////////////////////////////////
  1923. ' By sMcNeill from https://www.qb64.org/forum/index.php?topic=896.0
  1924.  
  1925. Function IsNum% (text$)
  1926.     Dim a$
  1927.     Dim b$
  1928.     a$ = _Trim$(text$)
  1929.     b$ = _Trim$(Str$(Val(text$)))
  1930.     If a$ = b$ Then
  1931.         IsNum% = TRUE
  1932.     Else
  1933.         IsNum% = FALSE
  1934.     End If
  1935. End Function ' IsNum%
  1936.  
  1937. ' /////////////////////////////////////////////////////////////////////////////
  1938. ' Split and join strings
  1939. ' https://www.qb64.org/forum/index.php?topic=1073.0
  1940.  
  1941. 'Combine all elements of in$() into a single string with delimiter$ separating the elements.
  1942.  
  1943. Function join$ (in$(), delimiter$)
  1944.     result$ = in$(LBound(in$))
  1945.     For i = LBound(in$) + 1 To UBound(in$)
  1946.         result$ = result$ + delimiter$ + in$(i)
  1947.     Next i
  1948.     join$ = result$
  1949. End Function ' join$
  1950.  
  1951. ' /////////////////////////////////////////////////////////////////////////////
  1952. ' ABS was returning strange values with type LONG
  1953. ' so I created this which does not.
  1954.  
  1955. Function LongABS& (lngValue As Long)
  1956.     If Sgn(lngValue) = -1 Then
  1957.         LongABS& = 0 - lngValue
  1958.     Else
  1959.         LongABS& = lngValue
  1960.     End If
  1961. End Function ' LongABS&
  1962.  
  1963. ' /////////////////////////////////////////////////////////////////////////////
  1964. ' Returns blank if successful else returns error message.
  1965.  
  1966. Function PrintFile$ (sFileName As String, sText As String, bAppend As Integer)
  1967.     'x = 1: y = 2: z$ = "Three"
  1968.  
  1969.     Dim sError As String: sError = ""
  1970.  
  1971.     If Len(sError) = 0 Then
  1972.         If (bAppend = TRUE) Then
  1973.             If _FileExists(sFileName) Then
  1974.                 Open sFileName For Append As #1 ' opens an existing file for appending
  1975.             Else
  1976.                 sError = "Error in PrintFile$ : File not found. Cannot append."
  1977.             End If
  1978.         Else
  1979.             Open sFileName For Output As #1 ' opens and clears an existing file or creates new empty file
  1980.         End If
  1981.     End If
  1982.     If Len(sError) = 0 Then
  1983.         ' WRITE places text in quotes in the file
  1984.         'WRITE #1, x, y, z$
  1985.         'WRITE #1, sText
  1986.  
  1987.         ' PRINT does not put text inside quotes
  1988.         Print #1, sText
  1989.  
  1990.         Close #1
  1991.  
  1992.         'PRINT "File created with data. Press a key!"
  1993.         'K$ = INPUT$(1) 'press a key
  1994.  
  1995.         'OPEN sFileName FOR INPUT AS #2 ' opens a file to read it
  1996.         'INPUT #2, a, b, c$
  1997.         'CLOSE #2
  1998.  
  1999.         'PRINT a, b, c$
  2000.         'WRITE a, b, c$
  2001.     End If
  2002.  
  2003.     PrintFile$ = sError
  2004. End Function ' PrintFile$
  2005.  
  2006. ' /////////////////////////////////////////////////////////////////////////////
  2007. ' Generate random value between Min and Max.
  2008. Function RandomNumber% (Min%, Max%)
  2009.     Dim NumSpread%
  2010.  
  2011.     ' SET RANDOM SEED
  2012.     'Randomize ' Initialize random-number generator.
  2013.  
  2014.     ' GET RANDOM # Min%-Max%
  2015.     'RandomNumber = Int((Max * Rnd) + Min) ' generate number
  2016.  
  2017.     NumSpread% = (Max% - Min%) + 1
  2018.  
  2019.     RandomNumber% = Int(Rnd * NumSpread%) + Min% ' GET RANDOM # BETWEEN Max% AND Min%
  2020.  
  2021. End Function ' RandomNumber%
  2022.  
  2023. ' /////////////////////////////////////////////////////////////////////////////
  2024.  
  2025. Sub RandomNumberTest
  2026.     Dim iCols As Integer: iCols = 10
  2027.     Dim iRows As Integer: iRows = 20
  2028.     Dim iLoop As Integer
  2029.     Dim iX As Integer
  2030.     Dim iY As Integer
  2031.     Dim sError As String
  2032.     Dim sFileName As String
  2033.     Dim sText As String
  2034.     Dim bAppend As Integer
  2035.     Dim iMin As Integer
  2036.     Dim iMax As Integer
  2037.     Dim iNum As Integer
  2038.     Dim iErrorCount As Integer
  2039.     Dim sInput$
  2040.  
  2041.     sFileName = "c:\temp\maze_test_1.txt"
  2042.     sText = "Count" + Chr$(9) + "Min" + Chr$(9) + "Max" + Chr$(9) + "Random"
  2043.     bAppend = FALSE
  2044.     sError = PrintFile$(sFileName, sText, bAppend)
  2045.     If Len(sError) = 0 Then
  2046.         bAppend = TRUE
  2047.         iErrorCount = 0
  2048.  
  2049.         iMin = 0
  2050.         iMax = iCols - 1
  2051.         For iLoop = 1 To 100
  2052.             iNum = RandomNumber(iMin, iMax)
  2053.             sText = Str$(iLoop) + Chr$(9) + Str$(iMin) + Chr$(9) + Str$(iMax) + Chr$(9) + Str$(iNum)
  2054.             sError = PrintFile$(sFileName, sText, bAppend)
  2055.             If Len(sError) > 0 Then
  2056.                 iErrorCount = iErrorCount + 1
  2057.                 Print Str$(iLoop) + ". ERROR"
  2058.                 Print "    " + "iMin=" + Str$(iMin)
  2059.                 Print "    " + "iMax=" + Str$(iMax)
  2060.                 Print "    " + "iNum=" + Str$(iNum)
  2061.                 Print "    " + "Could not write to file " + Chr$(34) + sFileName + Chr$(34) + "."
  2062.                 Print "    " + sError
  2063.             End If
  2064.         Next iLoop
  2065.  
  2066.         iMin = 0
  2067.         iMax = iRows - 1
  2068.         For iLoop = 1 To 100
  2069.             iNum = RandomNumber(iMin, iMax)
  2070.             sText = Str$(iLoop) + Chr$(9) + Str$(iMin) + Chr$(9) + Str$(iMax) + Chr$(9) + Str$(iNum)
  2071.             sError = PrintFile$(sFileName, sText, bAppend)
  2072.             If Len(sError) > 0 Then
  2073.                 iErrorCount = iErrorCount + 1
  2074.                 Print Str$(iLoop) + ". ERROR"
  2075.                 Print "    " + "iMin=" + Str$(iMin)
  2076.                 Print "    " + "iMax=" + Str$(iMax)
  2077.                 Print "    " + "iNum=" + Str$(iNum)
  2078.                 Print "    " + "Could not write to file " + Chr$(34) + sFileName + Chr$(34) + "."
  2079.                 Print "    " + sError
  2080.             End If
  2081.         Next iLoop
  2082.  
  2083.         Print "Finished generating numbers. Errors: " + Str$(iErrorCount)
  2084.     Else
  2085.         Print "Error creating file " + Chr$(34) + sFileName + Chr$(34) + "."
  2086.         Print sError
  2087.     End If
  2088.  
  2089.     Input "Press <ENTER> to continue", sInput$
  2090. End Sub ' RandomNumberTest
  2091.  
  2092. ' /////////////////////////////////////////////////////////////////////////////
  2093. ' FROM: String Manipulation
  2094. ' http://www.[abandoned, outdated and now likely malicious qb64 dot net website - don’t go there]/forum/index_topic_5964-0/
  2095. '
  2096. 'SUMMARY:
  2097. '   Purpose:  A library of custom functions that transform strings.
  2098. '   Author:   Dustinian Camburides (dustinian@gmail.com)
  2099. '   Platform: QB64 (www.[abandoned, outdated and now likely malicious qb64 dot net website - don’t go there])
  2100. '   Revision: 1.6
  2101. '   Updated:  5/28/2012
  2102.  
  2103. 'SUMMARY:
  2104. '[Replace$] replaces all instances of the [Find] sub-string with the [Add] sub-string within the [Text] string.
  2105. 'INPUT:
  2106. 'Text: The input string; the text that's being manipulated.
  2107. 'Find: The specified sub-string; the string sought within the [Text] string.
  2108. 'Add: The sub-string that's being added to the [Text] string.
  2109.  
  2110. Function Replace$ (Text1 As String, Find1 As String, Add1 As String)
  2111.     ' VARIABLES:
  2112.     Dim Text2 As String
  2113.     Dim Find2 As String
  2114.     Dim Add2 As String
  2115.     Dim lngLocation As Long ' The address of the [Find] substring within the [Text] string.
  2116.     Dim strBefore As String ' The characters before the string to be replaced.
  2117.     Dim strAfter As String ' The characters after the string to be replaced.
  2118.  
  2119.     ' INITIALIZE:
  2120.     ' MAKE COPIESSO THE ORIGINAL IS NOT MODIFIED (LIKE ByVal IN VBA)
  2121.     Text2 = Text1
  2122.     Find2 = Find1
  2123.     Add2 = Add1
  2124.  
  2125.     lngLocation = InStr(1, Text2, Find2)
  2126.  
  2127.     ' PROCESSING:
  2128.     ' While [Find2] appears in [Text2]...
  2129.     While lngLocation
  2130.         ' Extract all Text2 before the [Find2] substring:
  2131.         strBefore = Left$(Text2, lngLocation - 1)
  2132.  
  2133.         ' Extract all text after the [Find2] substring:
  2134.         strAfter = Right$(Text2, ((Len(Text2) - (lngLocation + Len(Find2) - 1))))
  2135.  
  2136.         ' Return the substring:
  2137.         Text2 = strBefore + Add2 + strAfter
  2138.  
  2139.         ' Locate the next instance of [Find2]:
  2140.         lngLocation = InStr(1, Text2, Find2)
  2141.  
  2142.         ' Next instance of [Find2]...
  2143.     Wend
  2144.  
  2145.     ' OUTPUT:
  2146.     Replace$ = Text2
  2147. End Function ' Replace$
  2148.  
  2149. ' /////////////////////////////////////////////////////////////////////////////
  2150. ' fantastically inefficient way to set a bit
  2151.  
  2152. ' example use: arrMaze(iX, iY) = SetBit256%(arrMaze(iX, iY), cS, FALSE)
  2153.  
  2154. ' See also: GetBit256%, SetBit256%
  2155.  
  2156. ' newint=SetBit256%(oldint, int containing the bits we want to set, value to set them to)
  2157. Function SetBit256% (iNum1 As Integer, iBit1 As Integer, bVal1 As Integer)
  2158.     Dim sNum As String
  2159.     Dim sBit As String
  2160.     Dim sVal As String
  2161.     Dim iLoop As Integer
  2162.     Dim strResult As String
  2163.     Dim iResult As Integer
  2164.     Dim iNum As Integer: iNum = iNum1
  2165.     Dim iBit As Integer: iBit = iBit1
  2166.     Dim bVal As Integer: bVal = bVal1
  2167.  
  2168.     If iNum < 256 And iBit <= 128 Then
  2169.         sNum = GetBinary$(iNum)
  2170.         sBit = GetBinary$(iBit)
  2171.         If bVal = TRUE Then
  2172.             sVal = "1"
  2173.         Else
  2174.             sVal = "0"
  2175.         End If
  2176.         strResult = ""
  2177.         For iLoop = 1 To 8
  2178.             If Mid$(sBit, iLoop, 1) = "1" Then
  2179.                 strResult = strResult + sVal
  2180.             Else
  2181.                 strResult = strResult + Mid$(sNum, iLoop, 1)
  2182.             End If
  2183.         Next iLoop
  2184.         iResult = GetIntegerFromBinary%(strResult)
  2185.     Else
  2186.         iResult = iNum
  2187.     End If
  2188.  
  2189.     SetBit256% = iResult
  2190. End Function ' SetBit256%
  2191.  
  2192. ' /////////////////////////////////////////////////////////////////////////////
  2193. ' Split and join strings
  2194. ' https://www.qb64.org/forum/index.php?topic=1073.0
  2195. '
  2196. ' FROM luke, QB64 Developer
  2197. ' Date: February 15, 2019, 04:11:07 AM »
  2198. '
  2199. ' Given a string of words separated by spaces (or any other character),
  2200. ' splits it into an array of the words. I've no doubt many people have
  2201. ' written a version of this over the years and no doubt there's a million
  2202. ' ways to do it, but I thought I'd put mine here so we have at least one
  2203. ' version. There's also a join function that does the opposite
  2204. ' array -> single string.
  2205. '
  2206. ' Code is hopefully reasonably self explanatory with comments and a little demo.
  2207. ' Note, this is akin to Python/JavaScript split/join, PHP explode/implode.
  2208.  
  2209. 'Split in$ into pieces, chopping at every occurrence of delimiter$. Multiple consecutive occurrences
  2210. 'of delimiter$ are treated as a single instance. The chopped pieces are stored in result$().
  2211. '
  2212. 'delimiter$ must be one character long.
  2213. 'result$() must have been REDIMmed previously.
  2214.  
  2215. Sub split (in$, delimiter$, result$())
  2216.     ReDim result$(-1)
  2217.     start = 1
  2218.     Do
  2219.         While Mid$(in$, start, 1) = delimiter$
  2220.             start = start + 1
  2221.             If start > Len(in$) Then Exit Sub
  2222.         Wend
  2223.         finish = InStr(start, in$, delimiter$)
  2224.         If finish = 0 Then finish = Len(in$) + 1
  2225.         ReDim _Preserve result$(0 To UBound(result$) + 1)
  2226.         result$(UBound(result$)) = Mid$(in$, start, finish - start)
  2227.         start = finish + 1
  2228.     Loop While start <= Len(in$)
  2229. End Sub ' split
  2230.  
  2231. ' /////////////////////////////////////////////////////////////////////////////
  2232.  
  2233. Sub SplitTest
  2234.  
  2235.     Dim in$
  2236.     Dim delim$
  2237.     ReDim arrTest$(0)
  2238.     Dim iLoop%
  2239.  
  2240.     delim$ = Chr$(10)
  2241.     in$ = "this" + delim$ + "is" + delim$ + "a" + delim$ + "test"
  2242.     Print "in$ = " + Chr$(34) + in$ + Chr$(34)
  2243.     Print "delim$ = " + Chr$(34) + delimeter$ + Chr$(34)
  2244.     split in$, delim$, arrTest$()
  2245.  
  2246.     For iLoop% = LBound(arrTest$) To UBound(arrTest$)
  2247.         Print "arrTest$(" + LTrim$(RTrim$(Str$(iLoop%))) + ") = " + Chr$(34) + arrTest$(iLoop%) + Chr$(34)
  2248.     Next iLoop%
  2249.     Print
  2250.     Print "Split test finished."
  2251. End Sub ' SplitTest
  2252.  
  2253. ' /////////////////////////////////////////////////////////////////////////////
  2254.  
  2255. Sub WaitForEnter
  2256.     Dim in$
  2257.     Input "Press <ENTER> to continue", in$
  2258. End Sub ' WaitForEnter
  2259.  
  2260. ' /////////////////////////////////////////////////////////////////////////////
  2261. ' WaitForKey "Press <ESC> to continue", 27, 0
  2262. ' WaitForKey "Press <ENTER> to begin;", 13, 0
  2263. ' waitforkey "", 65, 5
  2264.  
  2265. Sub WaitForKey (prompt$, KeyCode&, DelaySeconds%)
  2266.     ' SHOW PROMPT (IF SPECIFIED)
  2267.     If Len(prompt$) > 0 Then
  2268.         If Right$(prompt$, 1) <> ";" Then
  2269.             Print prompt$
  2270.         Else
  2271.             Print Right$(prompt$, Len(prompt$) - 1);
  2272.         End If
  2273.     End If
  2274.  
  2275.     ' WAIT FOR KEY
  2276.     Do: Loop Until _KeyDown(KeyCode&) ' leave loop when specified key pressed
  2277.  
  2278.     ' PAUSE AFTER (IF SPECIFIED)
  2279.     If DelaySeconds% < 1 Then
  2280.         _KeyClear: '_DELAY 1
  2281.     Else
  2282.         _KeyClear: _Delay DelaySeconds%
  2283.     End If
  2284. End Sub ' WaitForKey
  2285.  
  2286.  
  2287.  
  2288.  
  2289.  
  2290.  
  2291.  
  2292.  
  2293.  
  2294.  
  2295.  
  2296.  
  2297.  
  2298.  
  2299.  
  2300.  
  2301.  
  2302.  
  2303.  
  2304.  
  2305.  
  2306.  
  2307.  
  2308.  
  2309.  
  2310.  
  2311.  
  2312.  
  2313.  
  2314.  
  2315.  
  2316.  
  2317.  
  2318.  
  2319.  
  2320.  
  2321.  
  2322.  
  2323.  
  2324.  
  2325.  
  2326.  
  2327.  
  2328. ' /////////////////////////////////////////////////////////////////////////////
  2329.  
  2330. Sub DrawCube (x As Single, y As Single, z As Single, typ As Long, lit As Long)
  2331.     DefSng A-Z
  2332.     DefLng I
  2333.    
  2334.     size = 1
  2335.     For i = 1 To 8
  2336.         vert(i).x = x: vert(i).y = y: vert(i).z = z
  2337.         If i > 4 Then vert(i).y = vert(i).y + size
  2338.         If i = 2 Or i = 3 Or i = 6 Or i = 7 Then vert(i).x = vert(i).x + size
  2339.         If i = 3 Or i = 4 Or i = 7 Or i = 8 Then vert(i).z = vert(i).z + size
  2340.     Next i
  2341.    
  2342.     ' rotate verticies horizontally x/z
  2343.     For i = 1 To 8
  2344.         x = vert(i).x
  2345.         z = vert(i).z
  2346.         x2 = SINax * z + x * COSax
  2347.         z2 = COSax * z - SINax * x
  2348.         x = x2
  2349.         z = z2
  2350.         vert(i).x = x
  2351.         vert(i).z = z
  2352.        
  2353.         y = vert(i).y
  2354.         z = vert(i).z
  2355.         y2 = SINay * z + y * COSay
  2356.         z2 = COSay * z - SINay * y
  2357.         y = y2
  2358.         z = z2
  2359.         vert(i).y = y
  2360.         vert(i).z = z
  2361.     Next i
  2362.    
  2363.     'base:
  2364.     '1-2
  2365.     '| |
  2366.     '4-3
  2367.     'top:
  2368.     '5-6
  2369.     '| |
  2370.     '8-7
  2371.    
  2372.     i = 0
  2373.    
  2374.     ' front
  2375.     i = i + 1
  2376.     side(i).p1.p = vert(8)
  2377.     side(i).p2.p = vert(7)
  2378.     side(i).p3.p = vert(3)
  2379.     side(i).p4.p = vert(4)
  2380.    
  2381.     ' right
  2382.     i = i + 1
  2383.     side(i).p1.p = vert(7)
  2384.     side(i).p2.p = vert(6)
  2385.     side(i).p3.p = vert(2)
  2386.     side(i).p4.p = vert(3)
  2387.    
  2388.     ' back
  2389.     i = i + 1
  2390.     side(i).p1.p = vert(6)
  2391.     side(i).p2.p = vert(5)
  2392.     side(i).p3.p = vert(1)
  2393.     side(i).p4.p = vert(2)
  2394.    
  2395.     ' left
  2396.     i = i + 1
  2397.     side(i).p1.p = vert(5)
  2398.     side(i).p2.p = vert(8)
  2399.     side(i).p3.p = vert(4)
  2400.     side(i).p4.p = vert(1)
  2401.    
  2402.     ' top
  2403.     i = i + 1
  2404.     side(i).p1.p = vert(5)
  2405.     side(i).p2.p = vert(6)
  2406.     side(i).p3.p = vert(7)
  2407.     side(i).p4.p = vert(8)
  2408.    
  2409.     ' bottom
  2410.     i = i + 1
  2411.     side(i).p1.p = vert(4)
  2412.     side(i).p2.p = vert(3)
  2413.     side(i).p3.p = vert(2)
  2414.     side(i).p4.p = vert(1)
  2415.    
  2416.     b = 1
  2417.     For i = 1 To 6
  2418.         'IF i = 1 THEN t = Box(b).front
  2419.         'IF i = 2 THEN t = Box(b).right
  2420.         'IF i = 3 THEN t = Box(b).back
  2421.         'IF i = 4 THEN t = Box(b).left
  2422.         'IF i = 5 THEN t = Box(b).top
  2423.         'IF i = 6 THEN t = Box(b).bottom
  2424.        
  2425.         l = lit - i
  2426.         If i = 5 Then l = l + 5
  2427.         If l < -15 Then l = -15
  2428.        
  2429.         t = Tex(typ, 15 + l, 0)
  2430.        
  2431.         If typ = 1 Then
  2432.             _DontBlend t
  2433.             _MapTriangle _Clockwise (0, 0)-(63, 0)-(63, 63), t To(side(i).p1.p.x, side(i).p1.p.y, side(i).p1.p.z)-(side(i).p2.p.x, side(i).p2.p.y, side(i).p2.p.z)-(side(i).p3.p.x, side(i).p3.p.y, side(i).p3.p.z), , _SmoothShrunk
  2434.             _MapTriangle _Clockwise (0, 0)-(63, 63)-(0, 63), t To(side(i).p1.p.x, side(i).p1.p.y, side(i).p1.p.z)-(side(i).p3.p.x, side(i).p3.p.y, side(i).p3.p.z)-(side(i).p4.p.x, side(i).p4.p.y, side(i).p4.p.z), , _SmoothShrunk
  2435.         End If
  2436.         If (typ = 2 And i = 5) Then
  2437.             _Blend t
  2438.             _MapTriangle (0, 0)-(63, 0)-(63, 63), t To(side(i).p1.p.x, side(i).p1.p.y, side(i).p1.p.z)-(side(i).p2.p.x, side(i).p2.p.y, side(i).p2.p.z)-(side(i).p3.p.x, side(i).p3.p.y, side(i).p3.p.z), , _SmoothShrunk
  2439.             _MapTriangle (0, 0)-(63, 63)-(0, 63), t To(side(i).p1.p.x, side(i).p1.p.y, side(i).p1.p.z)-(side(i).p3.p.x, side(i).p3.p.y, side(i).p3.p.z)-(side(i).p4.p.x, side(i).p4.p.y, side(i).p4.p.z), , _SmoothShrunk
  2440.         End If
  2441.     Next i
  2442.     DefLng A-Z
  2443. End Sub ' DrawCube
  2444.  
  2445. ' /////////////////////////////////////////////////////////////////////////////
  2446.  
  2447. Function LoadTexture (filename$)
  2448.     TexLast = TexLast + 1
  2449.     T = TexLast
  2450.     path$ = "blocks\"
  2451.     Print path$ + filename$ + ".png"
  2452.     i = _LoadImage(path$ + filename$ + ".png", 32)
  2453.     i2 = _CopyImage(i)
  2454.     For l = 15 To 0 Step -1
  2455.         _PutImage , darken, i2
  2456.         For TOD = 0 To 3 'time of day (will support sunrise & sunset)
  2457.             '_DEST i2
  2458.             'LOCATE 1, 1
  2459.             'PRINT l;
  2460.             'PRINT tod;
  2461.             _Dest 0
  2462.             Tex(T, l, TOD) = _CopyImage(i2, 33)
  2463.         Next TOD
  2464.     Next l
  2465.     LoadTexture = TexLast
  2466. End Function ' LoadTexture
  2467.  
  2468. ' /////////////////////////////////////////////////////////////////////////////
  2469.  
  2470. Sub MapOffset (x, y, z)
  2471.     If x >= 0 Then
  2472.         x = x Mod (MapLimitX + 1)
  2473.     Else
  2474.         x = ((MapLimitX + 1) - ((-x) * -1)) Mod (MapLimitX + 1)
  2475.     End If
  2476.     If y >= 0 Then
  2477.         y = y Mod (MapLimitY + 1)
  2478.     Else
  2479.         y = ((MapLimitY + 1) - ((-y) * -1)) Mod (MapLimitY + 1)
  2480.     End If
  2481.     If z < 0 Then
  2482.         z = 0
  2483.     End If
  2484.     If z > MapLimitZ Then
  2485.         z = MapLimitZ
  2486.     End If
  2487. End Sub ' MapOffset
  2488.  
  2489. ' /////////////////////////////////////////////////////////////////////////////
  2490.  
  2491. DefSng A-Z
  2492. Function Bump% (Alt%, Rank%, BumpFactor, Bias)
  2493.     Do
  2494.         Do
  2495.             r = Rnd - .5 + Bias
  2496.         Loop While r < -.5 Or r > 0.5
  2497.         dAlt = r / (BumpFactor ^ Rank%) * Alt%
  2498.     Loop While Alt% + dAlt < 0 Or Alt% + dAlt > 255
  2499.     Bump% = Int(Alt% + dAlt)
  2500. End Function ' Bump%
  2501.  
  2502. ' /////////////////////////////////////////////////////////////////////////////
  2503.  
  2504. DefLng A-Z
  2505. DefSng A-Z
  2506. Sub VertexTranslate (x, y, z)
  2507.     Dim p As Long
  2508.     For p = VertexSource To VertexSource + VertexCount - 1
  2509.         VertexX(p) = VertexX(p) + x
  2510.         VertexY(p) = VertexY(p) + y
  2511.         VertexZ(p) = VertexZ(p) + z
  2512.     Next p
  2513. End Sub ' VertexTranslate
  2514.  
  2515. ' /////////////////////////////////////////////////////////////////////////////
  2516.  
  2517. DefLng A-Z
  2518. DefSng A-Z
  2519. Sub VertexScale (s)
  2520.     Dim p As Long
  2521.     For p = VertexSource To VertexSource + VertexCount - 1
  2522.         VertexX(p) = VertexX(p) * s
  2523.         VertexY(p) = VertexY(p) * s
  2524.         VertexZ(p) = VertexZ(p) * s
  2525.     Next p
  2526. End Sub ' VertexScale
  2527.  
  2528. ' /////////////////////////////////////////////////////////////////////////////
  2529.  
  2530. DefLng A-Z
  2531. DefSng A-Z
  2532. ' positive XZ/a1 is clockwise (when viewing from above)
  2533. ' positive YZ/a2 is clockwise (when viewing from the right)
  2534. Sub VertexRotateXZ_YZ (a1, a2)
  2535.     Dim p As Long
  2536.    
  2537.     a1_rad = a1 * -0.0174532925
  2538.     a1_sin = Sin(a1_rad): a1_cos = Cos(a1_rad)
  2539.  
  2540.     a2_rad = a2 * 0.0174532925
  2541.     a2_sin = Sin(a2_rad): a2_cos = Cos(a2_rad)
  2542.    
  2543.     For p = VertexSource To VertexSource + VertexCount - 1
  2544.         x = VertexX(p)
  2545.         y = VertexY(p)
  2546.         z = VertexZ(p)
  2547.        
  2548.         x2 = a1_sin * z + x * a1_cos
  2549.         z = a1_cos * z - a1_sin * x
  2550.         x = x2
  2551.        
  2552.         y2 = a2_sin * z + y * a2_cos
  2553.         z = a2_cos * z - a2_sin * y
  2554.         y = y2
  2555.  
  2556.         VertexX(p) = x
  2557.         VertexY(p) = y
  2558.         VertexZ(p) = z
  2559.     Next p
  2560. End Sub ' VertexRotateXZ_YZ
  2561.  
  2562. ' /////////////////////////////////////////////////////////////////////////////
  2563.  
  2564. DefLng A-Z
  2565. Sub CopyModel (m)
  2566.     v2 = VertexLast
  2567.     dif = (v2 + 1) - Model(m).FirstVertex
  2568.     For v1 = Model(m).FirstVertex To Model(m).FirstVertex + Model(m).VertexCount - 1
  2569.         v2 = v2 + 1
  2570.         VertexX(v2) = VertexX(v1)
  2571.         VertexY(v2) = VertexY(v1)
  2572.         VertexZ(v2) = VertexZ(v1)
  2573.         VertexTX(v2) = VertexTX(v1)
  2574.         VertexTY(v2) = VertexTY(v1)
  2575.     Next v1
  2576.     VertexLast = v2
  2577.     t2 = TriangleLast
  2578.     For t1 = Model(m).FirstTriangle To Model(m).FirstTriangle + Model(m).TriangleCount * 3 - 1
  2579.         t2 = t2 + 1
  2580.         TriangleVertex(t2) = TriangleVertex(t1) + dif
  2581.     Next t1
  2582.     TriangleLast = t2
  2583. End Sub ' CopyModel
  2584.  
  2585. ' /////////////////////////////////////////////////////////////////////////////
  2586.