Author Topic: WIP: Isometric Demo re-revisited v3.00 (edit + load + save isometric drawings)  (Read 2273 times)

0 Members and 1 Guest are viewing this topic.

Offline madscijr

  • Seasoned Forum Regular
  • Posts: 295
    • View Profile
Another update on this isometric 2.5d graphics engine/code thingy, based on the Isometric Mapping Demo code from
https://www.qb64.org/forum/index.php?topic=1903.30

This version lets you draw stuff with a simple palette to select colors, and save it to a human-readable and editable file, and load it back in.
The interface is quite primitive - I haven't bothered with things like modern file dialogs, or mouse input. Maybe later.

There is also a primitive (the word of the day here!) 1-level Undo/Redo (maybe eventually to be unlimited levels - it is already storing the user actions in memory).

(Note: for some reason my old _BUTTON code that I used to detect whether the CTRL key was down is not working, so for now undo/redo is the "a" key.)

Also, I added 2 additional "mini-map" views, so there are now 3 views, one for each axis, showing the "slice" at the current x, y, or z location.

Hopefully someone will find this useful. Comments welcome!

PS Next up, this program is going to get Christmasy....

Code: QB64: [Select]
  1. ' ################################################################################################################################################################
  2. ' #TOP
  3.  
  4. ' Isomatric mapping demo re-revisited
  5. ' Version 3.00 by madscijr
  6.  
  7. ' Based on Isometric Mapping Demo
  8. ' by SMcNeill, bplus, and others at
  9. ' https://www.qb64.org/forum/index.php?topic=1903.30
  10.  
  11. ' This crude version uses a 3-dimensional array (32x32x32)
  12. ' to store cubes of different colors,
  13. ' and draws them to the screen in 2.5D "isometric".
  14.  
  15. ' -----------------------------------------------------------------------------
  16. ' DONE:
  17. ' * Render cubes that block the view of the player as transparent.
  18. ' * 2-D top down "map" view of the player's current Z slice.
  19. ' * variable grid size
  20. ' * change arrMap to global shared variable (for simpler code) & rename m_arrMap
  21. ' * allow player to rotate their view
  22. ' * preliminary multiplayer changes
  23. '   - move player info into array (upto 4 players)
  24. '   - key mapping variables
  25. ' * fixed some keyboard input (repeating keys, continuous motion)
  26. ' * fixed right point of view bug where x & y coordinates were reversed
  27. ' * preliminary multiplayer changes
  28. '   - split screen display (4, 6, or 8?)
  29. '     + for now display player 1's world rotated in each window (for editor)
  30. '       * x4: c_iDir_Left, c_iDir_Right, c_iDir_Back, c_iDir_Forward
  31. '       * x6: c_iDir_Down, c_iDir_Up, c_iDir_Left, c_iDir_Right, c_iDir_Back, c_iDir_Forward
  32. '       * x8: c_iDir_Down, c_iDir_Up, c_iDir_Left, c_iDir_Right, c_iDir_Back, c_iDir_Forward, (none), (none)
  33. '     + will eventually be one per player
  34. ' * 2D minimap background = cKhaki
  35. ' * , and . change minimap size
  36. ' * editor v1 = simple drawing program
  37. '   - change lowest z level to draw full blocks instead of flat tiles (leftover from early version)
  38. '   - add type RecordType to hold recording steps
  39. '   - add array m_arrRecord of RecordType to hold recording
  40. '   - display palette of available colors on screen
  41. '     + 26 colors including empty
  42. '     + 2 tiles (empty, wall)
  43. '   - cursor places tiles (ENTER = add/delete at current space)
  44. '   - 0-9 keys change colors/etc.
  45. '   - simple 1-level UNDO & REDO
  46. '   - save screens to file (stored as editable text)
  47. '     + FORMAT: tile={t},color={c},x={x},y={y},z={z}
  48. '   - load screens line by line (split was too slow)
  49. '     + PARSER:
  50. '       1. remove whitespace
  51. '       2. split by "," into 1D array of name/value pairs
  52. '       3. each element is either tile, color, x, y, z
  53. '       4. parse each into array to playback recording
  54. '   - run commands in m_arrRecord to plot tiles and display
  55. ' * 2-D front/back "map" view of the player's current Y slice.
  56. ' * 2-D right/left "map" view of the player's current X slice.
  57.  
  58. ' -----------------------------------------------------------------------------
  59. ' TO DO:
  60.  
  61. ' * get _BUTTON or some method working to detect keydown/keyup events for CTRL+Z, CTRL+Y for UNDO & REDO
  62.  
  63. ' * save unlinited levels of undo/redo, using history of actions
  64.  
  65. ' * rotating view changes orientation of keys (get it working)
  66.  
  67. ' * add parameters to tiles
  68. '   - color scheme (for cycle colors)
  69.  
  70. ' * add tiles
  71. '   - transparent lights (blinking / cycle colors)
  72.  
  73. ' * editor v2 = simple animation program
  74. '   - records cursor movements and adding/deleting tiles
  75. '   - press key to record a "frame"
  76. '     + flash screen + play a sound
  77. '   - can change animation speed
  78. '   - realtime=on command enables redrawing screen every step (until realtime=off command encountered)
  79. '   - playback mode recreates editing actions
  80. '   - playback updates screen every "update"
  81. '   - tweak save format (still editable text)
  82. '     + FORMAT: TBD
  83. '     + PARSER:
  84. '       1. Commands:
  85. '          - cls
  86. '          - rotate perspective (up, down, left, right, back, forward), FORMAT: rotate={d}
  87. '          - enable/disable screen update every step, FORMAT: realtime{on/off}
  88. '          - set speed, FORAT: speed={s}
  89. '          - update screen, FORMAT: update
  90. '          - clear screen "cls"
  91. '          - select tile
  92. '          - change color
  93. '          - movement? (speed / direction)
  94. '   - effects of gravity (from bottom up, ie z=0 to z=max)
  95.  
  96. ' -----------------------------------------------------------------------------
  97. ' * expand world to bigger than screen (2.5d scrolling view)
  98.  
  99. ' * editor v3 = mouse
  100. '   - mouse movement controls cursor x,y position
  101. '   - mouse wheel controls z position
  102. '   - left click draws a tile
  103. '   - right click erases a tile
  104. '   - ENTER records a frame
  105. '   - Add animation playback command:
  106. '          [n][0] = command
  107. '                   -8 = enable user to rotate image in realtime with mouse? "mouse=on"
  108.  
  109. ' -----------------------------------------------------------------------------
  110. ' TO DO (LATER):
  111. ' * local multiplayer (2-4 players)
  112. '   - split screen (x2 or x4)
  113.  
  114. ' * fix/control screen placement/rendering/scroll boundaries for grid sizes
  115. '   (to not overwrite other players, go off screen, etc., when grid size changes)
  116.  
  117. ' * auto-rotate view depending on direction player is facing
  118.  
  119. ' * control the x/y/z slice axis, for a cutaway view
  120.  
  121. ' * gravity (players stay on ground, can fall)
  122. ' * player can climb up to next level if it is 1 tile higher
  123. ' * add ability to jump over 1 space
  124.  
  125. ' * option to remap keys
  126. ' * support game controllers
  127. ' * game controller calibration/mapping function
  128.  
  129. ' * option to hide objects out of player's line-of-sight
  130.  
  131. ' * show player as a stick figure (like "Realm of Impossibility")
  132. ' * walking movement
  133.  
  134. ' * add tiles (water, ladders, steps, ropes, windows, doors, etc.)
  135. ' * add toggle tiles - door "opens" when triggered
  136. ' * triggers
  137. ' * add tiles
  138. '   - Water = transparent blue)
  139. '   - Window = more transparent cyan)
  140.  
  141. ' * add directional tiles (can be rotated?)
  142. '   - ladder
  143. '   - bridge
  144. '   - hand-over-hand bars?
  145. '   - Slope45 = 45° slope <- 4 or 6 directions?
  146. '   - InvSlope45 = 45° inverted slope <- 4 or 6 directions?
  147. '   - Pyramid45 = 45° pyramid "cap stone" <- 4 or 6 directions?
  148. '   - ramp (player can walk up/down slope45)
  149.  
  150. ' * add ability to climb ladders + climbing animation
  151. ' * add ability to walk up ramps with smooth z-movement inbetween tiles
  152. ' * add ability to climb monkey bars (animation like lode runner)
  153.  
  154. ' * simultaneously show additional 1st person view
  155. ' * add ability for tilting head up/down in first person
  156.  
  157. ' * simple open world (players can add/remove tiles, build in real time)
  158. ' * make simple games (maze craze, capture the flag, snake, surround, 2.5d pong)
  159. ' * make more complex games (berzerk, lode runner, atari combat / tank)
  160. ' * make awesome complex games (2.5d lunar lander, atari adventure, asteroids, gravitar, Zaxxon meets Atari 2600 Superman, Isometric Atari 2600 Raiders of the Lost Ark, etc.)
  161. ' * text adventure features (to create graphic Infocom or Scott Adams style games)
  162.  
  163. ' * for 2.5D animation program: independent animated objects?
  164. '   - 2.5D sprites?
  165. '     + animation sequence
  166. '     + motion path / algorithm
  167. '     + storage / library
  168. '     + multiple instances?
  169. '   - gravity? (tile falls if no tiles underneath)
  170.  
  171. ' ################################################################################################################################################################
  172.  
  173. ' =============================================================================
  174. ' SOME USEFUL STUFF FOR REFERENCE:
  175.  
  176. ' Type Name               Type suffix symbol   Minimum value                  Maximum value                Size in Bytes
  177. ' ---------------------   ------------------   ----------------------------   --------------------------   -------------
  178. ' _BIT                    `                    -1                             0                            1/8
  179. ' _BIT * n                `n                   -128                           127                          n/8
  180. ' _UNSIGNED _BIT          ~`                   0                              1                            1/8
  181. ' _BYTE                   %%                   -128                           127                          1
  182. ' _UNSIGNED _BYTE         ~%%                  0                              255                          1
  183. ' INTEGER                 %                    -32,768                        32,767                       2
  184. ' _UNSIGNED INTEGER       ~%                   0                              65,535                       2
  185. ' LONG                    &                    -2,147,483,648                 2,147,483,647                4
  186. ' _UNSIGNED LONG          ~&                   0                              4,294,967,295                4
  187. ' _INTEGER64              &&                   -9,223,372,036,854,775,808     9,223,372,036,854,775,807    8
  188. ' _UNSIGNED _INTEGER64    ~&&                  0                              18,446,744,073,709,551,615   8
  189. ' SINGLE                  ! or none            -2.802597E-45                  +3.402823E+38                4
  190. ' DOUBLE                  #                    -4.490656458412465E-324        +1.797693134862310E+308      8
  191. ' _FLOAT                  ##                   -1.18E-4932                    +1.18E+4932                  32(10 used)
  192. ' _OFFSET                 %&                   -9,223,372,036,854,775,808     9,223,372,036,854,775,807    Use LEN
  193. ' _UNSIGNED _OFFSET       ~%&                  0                              18,446,744,073,709,551,615   Use LEN
  194. ' _MEM                    none                 combined memory variable type  N/A                          Use LEN
  195.  
  196. ' div: int1% = num1% \ den1%
  197. ' mod: rem1% = num1% MOD den1%
  198.  
  199. ' =============================================================================
  200. ' GLOBAL DECLARATIONS
  201.  
  202. ' -----------------------------------------------------------------------------
  203. ' boolean constants
  204. ' -----------------------------------------------------------------------------
  205. Const FALSE = 0
  206. Const TRUE = Not FALSE
  207.  
  208. ' -----------------------------------------------------------------------------
  209. ' KeyDownConstants
  210. ' -----------------------------------------------------------------------------
  211. Const c_iKeyDown_Esc = 27
  212. Const c_iKeyDown_F1 = 15104
  213. Const c_iKeyDown_F2 = 15360
  214. Const c_iKeyDown_F3 = 15616
  215. Const c_iKeyDown_F4 = 15872
  216. Const c_iKeyDown_F5 = 16128
  217. Const c_iKeyDown_F6 = 16384
  218. Const c_iKeyDown_F7 = 16640
  219. Const c_iKeyDown_F8 = 16896
  220. Const c_iKeyDown_F9 = 17152
  221. Const c_iKeyDown_F10 = 17408
  222. Const c_iKeyDown_Tilde = 96
  223. Const c_iKeyDown_1 = 49
  224. Const c_iKeyDown_2 = 50
  225. Const c_iKeyDown_3 = 51
  226. Const c_iKeyDown_4 = 52
  227. Const c_iKeyDown_5 = 53
  228. Const c_iKeyDown_6 = 54
  229. Const c_iKeyDown_7 = 55
  230. Const c_iKeyDown_8 = 56
  231. Const c_iKeyDown_9 = 57
  232. Const c_iKeyDown_0 = 48
  233. Const c_iKeyDown_Minus = 45
  234. Const c_iKeyDown_EqualPlus = 61
  235. Const c_iKeyDown_BkSp = 8
  236. Const c_iKeyDown_Ins = 20992
  237. Const c_iKeyDown_Home = 18176
  238. Const c_iKeyDown_PgUp = 18688
  239. Const c_iKeyDown_Del = 21248
  240. Const c_iKeyDown_End = 20224
  241. Const c_iKeyDown_PgDn = 20736
  242. Const c_iKeyDown_KEYPAD_7_Home = 18176
  243. Const c_iKeyDown_KEYPAD_8_Up = 18432
  244. Const c_iKeyDown_KEYPAD_9_PgUp = 18688
  245. Const c_iKeyDown_KEYPAD_4_Left = 19200
  246. Const c_iKeyDown_KEYPAD_6_Right = 19712
  247. Const c_iKeyDown_KEYPAD_1_End = 20224
  248. Const c_iKeyDown_KEYPAD_2_Down = 20480
  249. Const c_iKeyDown_KEYPAD_3_PgDn = 20736
  250. Const c_iKeyDown_KEYPAD_0_Ins = 20992
  251. Const c_iKeyDown_KEYPAD_Period_Del = 21248
  252. Const c_iKeyDown_Tab = 9
  253. Const c_iKeyDown_Q = 113
  254. Const c_iKeyDown_W = 119
  255. Const c_iKeyDown_E = 101
  256. Const c_iKeyDown_R = 114
  257. Const c_iKeyDown_T = 116
  258. Const c_iKeyDown_Y = 121
  259. Const c_iKeyDown_U = 117
  260. Const c_iKeyDown_Pipe = 105
  261. Const c_iKeyDown_O = 111
  262. Const c_iKeyDown_P = 112
  263. Const c_iKeyDown_BracketLeft = 91
  264. Const c_iKeyDown_BracketRight = 93
  265. Const c_iKeyDown_Backslash = 92
  266. Const c_iKeyDown_A = 97
  267. Const c_iKeyDown_S = 115
  268. Const c_iKeyDown_D = 100
  269. Const c_iKeyDown_F = 102
  270. Const c_iKeyDown_G = 103
  271. Const c_iKeyDown_H = 104
  272. Const c_iKeyDown_J = 106
  273. Const c_iKeyDown_K = 107
  274. Const c_iKeyDown_L = 108
  275. Const c_iKeyDown_SemiColon = 59
  276. Const c_iKeyDown_Apostrophe = 39
  277. Const c_iKeyDown_Enter = 13
  278. Const c_iKeyDown_Z = 22
  279. Const c_iKeyDown_X = 120
  280. Const c_iKeyDown_C = 99
  281. Const c_iKeyDown_V = 118
  282. Const c_iKeyDown_B = 98
  283. Const c_iKeyDown_N = 110
  284. Const c_iKeyDown_M = 109
  285. Const c_iKeyDown_Comma = 44
  286. Const c_iKeyDown_Period = 46
  287. Const c_iKeyDown_Slash = 47
  288. Const c_iKeyDown_Up = 18432
  289. Const c_iKeyDown_Left = 19200
  290. Const c_iKeyDown_Down = 20480
  291. Const c_iKeyDown_Right = 19712
  292. Const c_iKeyDown_Spacebar = 32
  293.  
  294. ' -----------------------------------------------------------------------------
  295. ' Constants for layers
  296. ' -----------------------------------------------------------------------------
  297. Const cTerrainType = 1
  298. Const cObjectsType = 2
  299. Const cPlayersType = 3
  300.  
  301. ' -----------------------------------------------------------------------------
  302. ' Tile value constants for map (MapTileType.Typ)
  303. ' -----------------------------------------------------------------------------
  304. Const c_iTile_Empty = 0
  305. Const c_iTile_Floor = 1
  306. Const c_iTile_Wall = 2
  307. Const c_iTile_Water = 3
  308. Const c_iTile_Window = 4
  309. Const c_iTile_Player1 = 5
  310. Const c_iTile_Player2 = 6
  311. Const c_iTile_Player3 = 7
  312. Const c_iTile_Player4 = 8
  313. Const c_iTile_Blinking = 9
  314. Const c_iTile_Snow = 10
  315. Const c_iTile_Slope45 = 11
  316. Const c_iTile_InvSlope45 = 12
  317.  
  318. ' -----------------------------------------------------------------------------
  319. ' constants for 2.5D movement
  320. ' -----------------------------------------------------------------------------
  321. Const c_iDir_Down = 1
  322. Const c_iDir_Up = 2
  323. Const c_iDir_Left = 3
  324. Const c_iDir_Right = 4
  325. Const c_iDir_Back = 5
  326. Const c_iDir_Forward = 6
  327. Const c_iDir_Min = 1
  328. Const c_iDir_Max = 6
  329.  
  330. ' -----------------------------------------------------------------------------
  331. ' constants for drawing the 2.5D screen
  332. ' -----------------------------------------------------------------------------
  333. Const cGridOffsetX = 50
  334. Const cGridOffsetY = 50
  335. Const cGridOffsetZ = 0
  336. Const cScreenOffsetX = 500
  337. Const cScreenOffsetY = 300
  338. Const cScreenOffsetZ = 0
  339.  
  340. ' =============================================================================
  341. ' USER DEFINED TYPES
  342. ' =============================================================================
  343. Type MapTileType
  344.     Typ As Integer ' c_iTile_Empty, c_iTile_Floor, c_iTile_Wall, etc.
  345.     'Vis As Integer ' TRUE = visible, FALSE = don't render
  346.     'Lit As Long ' light offset
  347.     Color1 As _Unsigned Long ' main color
  348.     Color2 As _Unsigned Long ' secondary color if needed
  349.     Color3 As _Unsigned Long ' third color if needed
  350.     Alpha1 As Integer ' transparency of tile Color1
  351.     Alpha2 As Integer ' transparency of tile Color2
  352.     Alpha3 As Integer ' transparency of tile Color3
  353.     AlphaOverride As Integer ' can be used to override alpha (255 treated as opaque)
  354. End Type ' MapTileType
  355.  
  356. Type MapUndoType
  357.     x As Integer
  358.     y As Integer
  359.     z As Integer
  360.     Typ As Integer ' c_iTile_Empty, c_iTile_Floor, c_iTile_Wall, etc.
  361.     Color1 As _Unsigned Long ' main color
  362.     Alpha1 As Integer ' transparency of tile Color1
  363. End Type ' MapUndoType
  364.  
  365. Type RecordType
  366.     Command As String ' "draw"
  367.     intParam1 As Integer ' x
  368.     intParam2 As Integer ' y
  369.     intParam3 As Integer ' z
  370.     intParam4 As Integer ' tile #
  371.     ulngParam1 As _Unsigned Long ' color1
  372. End Type ' RecordType
  373.  
  374. ' UDT TO HOLD THE INFO FOR A PLAYER
  375. Type PlayerType
  376.     IsEnabled As Integer ' TRUE or FALSE
  377.     x As Integer ' player x position
  378.     y As Integer ' player y position
  379.     z As Integer ' player z position
  380.     Direction As Integer ' direction player is moving: c_iDir_Left, c_iDir_Right, c_iDir_Back, c_iDir_Forward; not used: c_iDir_Down, c_iDir_Up
  381.     View As Integer ' player's viewing orientation (direction screen is being looked at from), can be: c_iDir_Left, c_iDir_Right, c_iDir_Back, c_iDir_Forward, c_iDir_Down, c_iDir_Up
  382.     Tile1 As Long ' later we will instead use directional animation sequences
  383.  
  384.     Color1 As _Unsigned Long ' main color
  385.     'Color2 As _Unsigned Long ' secondary color if needed
  386.     'Color3 As _Unsigned Long ' third color if needed
  387.  
  388.     Alpha1 As Integer ' transparency of player Color1
  389.     'Alpha2 As Integer ' transparency of player Color2
  390.     'Alpha3 As Integer ' transparency of player Color3
  391.  
  392.     ColorScheme1 As Long ' for cycling colors
  393.     ColorSchemeSpeed1 As Long
  394.     ColorSchemeCount1 As Long
  395.  
  396.     'ColorScheme2 As Long ' for cycling colors
  397.     'ColorSchemeSpeed2 As Long
  398.     'ColorSchemeCount2 As Long
  399.  
  400.     'ColorScheme3 As Long ' for cycling colors
  401.     'ColorSchemeSpeed3 As Long
  402.     'ColorSchemeCount3 As Long
  403.  
  404.     AlphaOverride As Integer ' can be used to override alpha (0 treated as opaque)
  405.  
  406.     IsMoving As Integer ' TRUE/FALSE
  407.     IsMoved As Integer ' TRUE/FALSE
  408.  
  409.     GridSize As Integer
  410.     MapSize As Integer
  411.  
  412.     'hx AS Integer ' home base x position
  413.     'hy AS Integer ' home base y position
  414.     'ex AS Integer ' exit x position
  415.     'ey AS Integer ' exit y position
  416.     'wins AS Integer ' count # of wins
  417.     'points AS Long ' count points (more points for harder)
  418.     'difficulty AS Integer ' 1-5, from 1 (easiest, maze width 5) to 5 (hardest, maze width 1). Each win awards {difficulty} # of points.
  419.     'speed AS Integer ' the higher the faster
  420.     'delay AS Integer ' counter, player can move based on speed
  421.     'bit AS Integer ' bit value for masking player in map
  422.     'rows AS Integer ' # of rows in player's maze
  423.     'cols AS Integer ' # of columns in player's maze
  424. End Type ' PlayerType
  425.  
  426. ' KEY MAPPING v1
  427. ' UDT TO HOLD THE KEY MAPPINGS
  428. Type DirKeyMapType
  429.     KeyBack As Long
  430.     KeyForward As Long
  431.     KeyLeft As Long
  432.     KeyRight As Long
  433.     KeyUp As Long
  434.     KeyDown As Long
  435. End Type ' DirKeyMapType
  436.  
  437. ' SPLIT SCREEN OFFSETS
  438. Type SplitScreenType
  439.     ' WHERE TO SHOW THE SPLIT SCREENS
  440.     GridOffsetX As Integer
  441.     GridOffsetY As Integer
  442.     GridOffsetZ As Integer
  443.     ScreenOffsetX As Integer
  444.     ScreenOffsetY As Integer
  445.     ScreenOffsetZ As Integer
  446.  
  447.     ' WHERE TO DRAW THE PLAYER'S MINI MAPS
  448.     MiniMapTopDownX As Integer
  449.     MiniMapTopDownY As Integer
  450.     MiniMapFrontBackX As Integer
  451.     MiniMapFrontBackY As Integer
  452.     MiniMapRightLeftX As Integer
  453.     MiniMapRightLeftY As Integer
  454.     MiniMapFirstPersonX As Integer
  455.     MiniMapFirstPersonY As Integer
  456.  
  457.     ' WHERE TO LOCATE(Y,X) THE PLAYER'S MINI MAP TEXT LABELS
  458.     ' TODO: later this will probably be bitmap text
  459.     MiniMapTopDownTextX As Integer
  460.     MiniMapTopDownTextY As Integer
  461.     MiniMapFrontBackTextX As Integer
  462.     MiniMapFrontBackTextY As Integer
  463.     MiniMapRightLeftTextX As Integer
  464.     MiniMapRightLeftTextY As Integer
  465.     MiniMapFirstPersonTextX As Integer
  466.     MiniMapFirstPersonTextY As Integer
  467.  
  468. End Type ' SplitScreenType
  469.  
  470. ' =============================================================================
  471. ' GLOBAL VARIABLES
  472. Dim Shared m_ProgramPath$: m_ProgramPath$ = Left$(Command$(0), _InStrRev(Command$(0), "\"))
  473. Dim Shared m_ProgramName$: m_ProgramName$ = Mid$(Command$(0), _InStrRev(Command$(0), "\") + 1)
  474. Dim Shared m_SaveFileName$: m_SaveFileName$ = Left$(m_ProgramName$, _InStrRev(m_ProgramName$, ".")) + "txt"
  475. Dim Shared m_iGridSize As Integer: m_iGridSize = 8 ' BEFORE, < 10 wass causing problems with PAINT, but new method doesn't use PAINT, so nyah!
  476. Dim Shared m_iGridSizeMin As Integer: m_iGridSizeMin = 1
  477. Dim Shared m_iGridSizeMax As Integer: m_iGridSizeMax = 128
  478.  
  479. Dim Shared m_iMapMinX As Integer: m_iMapMinX = 0
  480. Dim Shared m_iMapMaxX As Integer: m_iMapMaxX = 32
  481. Dim Shared m_iMapMidX As Integer: m_iMapMidX = (m_iMapMaxX - m_iMapMinX) \ 2
  482. Dim Shared m_iMapMinY As Integer: m_iMapMinY = 0
  483. Dim Shared m_iMapMaxY As Integer: m_iMapMaxY = 32
  484. Dim Shared m_iMapMidY As Integer: m_iMapMidY = (m_iMapMaxY - m_iMapMinY) \ 2
  485. Dim Shared m_iMapMinZ As Integer: m_iMapMinZ = 0
  486. Dim Shared m_iMapMaxZ As Integer: m_iMapMaxZ = 32
  487. Dim Shared m_iMapMidZ As Integer: m_iMapMidZ = (m_iMapMaxZ - m_iMapMinZ) \ 2
  488.  
  489. Dim Shared m_iPlayerMin As Integer: m_iPlayerMin = 1
  490. Dim Shared m_iPlayerMax As Integer: m_iPlayerMax = 4
  491. Dim Shared m_iPlayerCount As Integer: m_iPlayerCount = 0
  492. Dim Shared m_iObjectCount As Integer: m_iObjectCount = 0 ' <- TO BE USED WHEN WE HAVE OBJECTS
  493.  
  494. Dim Shared m_arrMap(m_iMapMinX To m_iMapMaxX, m_iMapMinY To m_iMapMaxY, m_iMapMinZ To m_iMapMaxZ) As MapTileType
  495. Dim Shared m_arrRender1(m_iMapMinX To m_iMapMaxX, m_iMapMinY To m_iMapMaxY, m_iMapMinZ To m_iMapMaxZ) As MapTileType
  496. Dim Shared m_arrRender2(m_iMapMinX To m_iMapMaxX, m_iMapMinY To m_iMapMaxY, m_iMapMinZ To m_iMapMaxZ) As MapTileType
  497. Dim Shared m_arrPlayer(m_iPlayerMin To m_iPlayerMax) As PlayerType
  498.  
  499. ' TODO: ADD UNLIMITED UNDO, FOR NOW ONE LEVEL IS BETTER THAN NONE!
  500. Dim Shared m_MapTileUndo As MapUndoType
  501.  
  502. ' This array is used to hold user's drawing actions,
  503. ' to save drawings and for playback, and later for Undo/Redo.
  504. ' How big will the recording get?
  505. ' Max # tiles in (32x32x32) world = 32,768
  506. ' Max # tiles for 16 (32x32x32) worlds = 524,288
  507. ' Max # tiles for 256 (32x32x32) worlds = 8,388,608
  508. ReDim Shared m_arrRecord(-1) As RecordType
  509.  
  510. ' For each player, map the 6 directional keys differently for each of the 6 directional orientations!
  511. Dim Shared m_arrDirKeyMap(m_iPlayerMin To m_iPlayerMax, c_iDir_Min To c_iDir_Max) As DirKeyMapType
  512.  
  513. ' Store offsets for splitscreen
  514. Dim Shared m_arrSplitScreen(m_iPlayerMin To m_iPlayerMax) As SplitScreenType
  515.  
  516. ' Store colors in an array
  517. Dim Shared m_arrColors(0 To 25) As Long
  518.  
  519. Dim Shared m_bTesting As Integer
  520.  
  521. ' TODO: REPLACE THIS HACK WAY OF TRACKING KEY UP/DOWN
  522. Dim Shared m_bButton_LeftCtrl As Integer: m_bButton_LeftCtrl = FALSE
  523. Dim Shared m_bButton_RightCtrl As Integer: m_bButton_RightCtrl = FALSE
  524. Dim Shared m_bButton_Y As Integer: m_bButton_Y = FALSE
  525. Dim Shared m_bButton_Z As Integer: m_bButton_Z = FALSE
  526.  
  527.  
  528. ' =============================================================================
  529. ' LOCAL VARIABLES
  530. Dim in$
  531.  
  532. ' ****************************************************************************************************************************************************************
  533. ' ACTIVATE DEBUGGING WINDOW
  534. _Echo "Started " + m_ProgramName$
  535. _Echo "Debugging on..."
  536. ' ****************************************************************************************************************************************************************
  537.  
  538. ' =============================================================================
  539. ' START THE MAIN ROUTINE
  540. main
  541.  
  542. ' =============================================================================
  543. ' FINISH
  544. System ' return control to the operating system
  545. Print m_ProgramName$ + " finished."
  546. Input "Press <ENTER> to continue", in$
  547.  
  548. ' ****************************************************************************************************************************************************************
  549. ' DEACTIVATE DEBUGGING WINDOW
  550. ' ****************************************************************************************************************************************************************
  551.  
  552.  
  553. ' /////////////////////////////////////////////////////////////////////////////
  554.  
  555. Sub main
  556.     Dim RoutineName As String: RoutineName = "main"
  557.     Dim in$
  558.     Dim result$
  559.  
  560.     Screen 0
  561.  
  562.     Do
  563.         Cls
  564.         Print m_ProgramName$
  565.         Print
  566.         Print "Isomatric Mapping Demo Re-visited"
  567.         Print "v3.00, by Softintheheadware (Dec, 2021)"
  568.         Print
  569.         'PRINT "CONTROLS: PRESS <ESC> TO RETURN TO MENU"
  570.         'PRINT "PLAYER  LEFT       RIGHT       UP        DOWN       "
  571.         'PRINT "1       CRSR LEFT  CRSR RIGHT  CRSR UP   CRSR DOWN  "
  572.         'PRINT "2       KEYPAD 4   KEYPAD 6    KEYPAD 8  KEYPAD 2   "
  573.         'PRINT "3       A          S           W         Z          "
  574.         'PRINT "4       J          K           I         M          "
  575.         'PRINT
  576.  
  577.         Print "1. (TBD)"
  578.         Print "2. (TBD)"
  579.         Print "3. (TBD)"
  580.         Print "4. BoxDrawTest1$"
  581.         Print "5. Draw in 2.5D! <- now with the color white working!"
  582.         Print
  583.         Print "What to do? ('q' to exit)"
  584.  
  585.         Input in$: in$ = LCase$(Left$(in$, 1))
  586.  
  587.         If in$ = "1" Then
  588.             result$ = IsometricDemo1$
  589.         ElseIf in$ = "2" Then
  590.             result$ = IsometricDemo2$
  591.         ElseIf in$ = "3" Then
  592.             result$ = IsometricDemo3$
  593.         ElseIf in$ = "4" Then
  594.             result$ = BoxDrawTest1$
  595.         ElseIf in$ = "5" Then
  596.             result$ = IsometricDraw1$
  597.         End If
  598.  
  599.         If Len(result$) > 0 Then
  600.             Print result$
  601.         End If
  602.  
  603.     Loop Until in$ = "q"
  604. End Sub ' main
  605.  
  606. ' /////////////////////////////////////////////////////////////////////////////
  607.  
  608. Function IsometricDemo1$
  609.     IsometricDemo1$ = "(TBD)"
  610. End Function ' IsometricDemo1
  611.  
  612. ' /////////////////////////////////////////////////////////////////////////////
  613.  
  614. Function IsometricDemo2$
  615.     IsometricDemo2$ = "(TBD)"
  616. End Function ' IsometricDemo2
  617.  
  618. ' /////////////////////////////////////////////////////////////////////////////
  619.  
  620. Function IsometricDemo3$
  621.     IsometricDemo3$ = "(TBD)"
  622. End Function ' IsometricDemo3
  623.  
  624. ' /////////////////////////////////////////////////////////////////////////////
  625. ' Test all the values 0-255 for style
  626. ' The style% signed INTEGER value sets a dotted pattern to draw the line or rectangle outline.
  627.  
  628. Function BoxDrawTest1$
  629.     Dim in$
  630.     Dim iSize%
  631.     Dim iDrawX%
  632.     Dim iDrawY%
  633.     Dim iFromX%
  634.     Dim iFromY%
  635.     Dim iToX%
  636.     Dim iToY%
  637.     Dim iNextColor~&
  638.     Dim iLoop As Integer
  639.     Dim iSpace%
  640.     Dim sError As String: sError = ""
  641.  
  642.     iSize% = 48 ' {n}x{n} pixels square
  643.     iDrawX% = 10
  644.     iDrawY% = 10
  645.     iNextColor~& = cWhite
  646.     iSpace% = 8
  647.     Screen _NewImage(1280, 1024, 32): _ScreenMove 0, 0
  648.     For iLoop = 0 To 255
  649.         DrawStyledOutlineBox iDrawX%, iDrawY%, iSize%, iNextColor~&, iLoop
  650.         'DrawOutlineBox iDrawX%+1, iDrawY%+1, iSize%-2, iNextColor~&, iLoop
  651.  
  652.         iDrawX% = iDrawX% + iSize% + iSpace%
  653.         If iDrawX% > (1280 - (iSize% * 2)) Then
  654.             iDrawX% = 10
  655.             iDrawY% = iDrawY% + iSize% + iSpace%
  656.  
  657.             If iDrawY% > (1024 - (iSize% * 2)) Then
  658.                 sError = "Ran out of Y space."
  659.                 Exit For
  660.             End If
  661.         End If
  662.     Next iLoop
  663.  
  664.     If Len(sError) = 0 Then
  665.         For iLoop = 1 To (iSize% \ 2)
  666.             DrawOutlineBox iDrawX%, iDrawY%, iSize%, iNextColor~&, iLoop
  667.             iDrawX% = iDrawX% + iSize% + iSpace%
  668.             If iDrawX% > (1280 - (iSize% * 2)) Then
  669.                 iDrawX% = 10
  670.                 iDrawY% = iDrawY% + iSize% + iSpace%
  671.                 If iDrawY% > (1024 - (iSize% * 2)) Then
  672.                     sError = "Ran out of Y space."
  673.                     Exit For
  674.                 End If
  675.             End If
  676.         Next iLoop
  677.     End If
  678.  
  679.     Locate 58, 1
  680.     If Len(sError) > 0 Then
  681.         Print sError
  682.     End If
  683.     Input "PRESS <ENTER> TO CONTINUE"; in$
  684.  
  685.     _KeyClear
  686.     Screen 0
  687.  
  688.     BoxDrawTest1$ = ""
  689. End Function ' BoxDrawTest1$
  690.  
  691. ' /////////////////////////////////////////////////////////////////////////////
  692. ' Lets you draw a scene in 2.5D and save it to a file. Woo hoo!
  693.  
  694. ' Version 1 only supports 2 tile types:
  695. ' c_iTile_Empty
  696. ' c_iTile_Wall
  697.  
  698. Function IsometricDraw1$
  699.     Dim RoutineName As String: RoutineName = "IsometricDraw1"
  700.     Dim sResult As String: sResult = ""
  701.     Dim sError As String: sError = ""
  702.     Dim iX%
  703.     Dim iY%
  704.     Dim iZ%
  705.     Dim iNewX%
  706.     Dim iNewY%
  707.     Dim iNewZ%
  708.     Dim iMyColor~&
  709.     Dim iColorScheme%
  710.     Dim iDirection%
  711.     Dim bFound As Integer
  712.     Dim bDone As Integer
  713.     Dim in$
  714.     Dim iTotal% ' compute total available spaces
  715.     Dim iCount% ' count # of spaces searched
  716.     Dim bEnableRepeatingKeys As Integer
  717.     Dim iLastKey As Integer ' USED WHEN REPEATING KEYS DISABLED
  718.     Dim iLoop1 As Integer
  719.     Dim iLoop2 As Integer
  720.  
  721.     Dim iPosX1%
  722.     Dim iPosX2%
  723.     Dim iPosY1%
  724.     Dim iPosY2%
  725.     Dim iNextColor~&
  726.     Dim iFirstColor~&
  727.     Dim bContinue As Integer
  728.     Dim iLoopX%
  729.     Dim iLoopY%
  730.     Dim iLoopZ%
  731.     Dim iLevelCount%
  732.     Dim iLevelSize%
  733.  
  734.     Dim iDrawX%
  735.     Dim iDrawY%
  736.     Dim iSize%
  737.     Dim iOffsetY%
  738.  
  739.     Dim iPlayerLoop As Integer
  740.     Dim iDirLoop As Integer
  741.     Dim iNextX As Integer
  742.     Dim iNextY As Integer
  743.  
  744.     Dim iDrawColor%
  745.     Dim iCursorColor~&
  746.  
  747.     Dim bIgnoreTerrain As Integer ' If TRUE, player can move through walls, etc.
  748.     Dim iIndex As Long
  749.     Dim sNextErr As String: sNextErr = ""
  750.     Dim MapTileTempUndo As MapUndoType
  751.  
  752.     ' =============================================================================
  753.     ' GET OPTIONS
  754.     m_iPlayerCount = 1
  755.     'm_iPlayerCount = PromptForIntegerInRange%("How many players ({min}-{max} or blank to quit)?", 1, 4, 0)
  756.     'IF m_iPlayerCount = 0 THEN Goto CleanupAndExit
  757.     bEnableRepeatingKeys = FALSE
  758.  
  759.     ' =============================================================================
  760.     ' INITIALIZE GRAPHIC SCREEN
  761.     'Screen _NewImage(1024, 720, 32) : _ScreenMove _Middle
  762.     Screen _NewImage(1280, 1024, 32): _ScreenMove 0, 0
  763.  
  764.     m_arrSplitScreen(1).GridOffsetX = 50
  765.     m_arrSplitScreen(1).GridOffsetY = 50
  766.     m_arrSplitScreen(1).GridOffsetZ = 0
  767.     m_arrSplitScreen(1).ScreenOffsetX = 450
  768.     m_arrSplitScreen(1).ScreenOffsetY = 200
  769.     m_arrSplitScreen(1).ScreenOffsetZ = 0
  770.  
  771.     m_arrSplitScreen(1).MiniMapTopDownX = 50
  772.     m_arrSplitScreen(1).MiniMapTopDownY = 560
  773.     m_arrSplitScreen(1).MiniMapFrontBackX = 50
  774.     m_arrSplitScreen(1).MiniMapFrontBackY = 720
  775.     m_arrSplitScreen(1).MiniMapRightLeftX = 50
  776.     m_arrSplitScreen(1).MiniMapRightLeftY = 880
  777.     m_arrSplitScreen(1).MiniMapFirstPersonX = 70
  778.     m_arrSplitScreen(1).MiniMapFirstPersonY = 450
  779.  
  780.     m_arrSplitScreen(1).MiniMapTopDownTextX = 8
  781.     m_arrSplitScreen(1).MiniMapTopDownTextY = 35
  782.     m_arrSplitScreen(1).MiniMapFrontBackTextX = 8
  783.     m_arrSplitScreen(1).MiniMapFrontBackTextY = 45
  784.     m_arrSplitScreen(1).MiniMapRightLeftTextX = 8
  785.     m_arrSplitScreen(1).MiniMapRightLeftTextY = 55
  786.     m_arrSplitScreen(1).MiniMapFirstPersonTextX = 8
  787.     m_arrSplitScreen(1).MiniMapFirstPersonTextY = 31
  788.  
  789.     m_arrSplitScreen(2).GridOffsetX = 50
  790.     m_arrSplitScreen(2).GridOffsetY = 50
  791.     m_arrSplitScreen(2).GridOffsetZ = 0
  792.     m_arrSplitScreen(2).ScreenOffsetX = 1000
  793.     m_arrSplitScreen(2).ScreenOffsetY = 200
  794.     m_arrSplitScreen(2).ScreenOffsetZ = 0
  795.     'TODO: add minimap parameters for player 2
  796.  
  797.     m_arrSplitScreen(3).GridOffsetX = 50
  798.     m_arrSplitScreen(3).GridOffsetY = 50
  799.     m_arrSplitScreen(3).GridOffsetZ = 0
  800.     m_arrSplitScreen(3).ScreenOffsetX = 450
  801.     m_arrSplitScreen(3).ScreenOffsetY = 700
  802.     m_arrSplitScreen(3).ScreenOffsetZ = 0
  803.     'TODO: add minimap parameters for player 3
  804.  
  805.     m_arrSplitScreen(4).GridOffsetX = 50
  806.     m_arrSplitScreen(4).GridOffsetY = 50
  807.     m_arrSplitScreen(4).GridOffsetZ = 0
  808.     m_arrSplitScreen(4).ScreenOffsetX = 1000
  809.     m_arrSplitScreen(4).ScreenOffsetY = 700
  810.     m_arrSplitScreen(4).ScreenOffsetZ = 0
  811.     'TODO: add minimap parameters for player 4
  812.  
  813.     ' -----------------------------------------------------------------------------
  814.     ' INITIALIZE MAP TO EMPTY
  815.     ClearIsometricMap
  816.     ReDim m_arrRecord(-1) As RecordType
  817.  
  818.     ' -----------------------------------------------------------------------------
  819.     ' INITIALIZE COLOR ARRAY
  820.     m_arrColors(0) = cEmpty
  821.     m_arrColors(1) = cBlack
  822.     m_arrColors(2) = cDarkGray
  823.     m_arrColors(3) = cDimGray
  824.     m_arrColors(4) = cGray
  825.     m_arrColors(5) = cLightGray
  826.     m_arrColors(6) = cSilver
  827.     m_arrColors(7) = cWhite
  828.     m_arrColors(8) = cRed
  829.     m_arrColors(9) = cOrangeRed
  830.     m_arrColors(10) = cDarkOrange
  831.     m_arrColors(11) = cOrange
  832.     m_arrColors(12) = cGold
  833.     m_arrColors(13) = cYellow
  834.     m_arrColors(14) = cOliveDrab1
  835.     m_arrColors(15) = cLime
  836.     m_arrColors(16) = cMediumSpringGreen
  837.     m_arrColors(17) = cCyan
  838.     m_arrColors(18) = cDeepSkyBlue
  839.     m_arrColors(19) = cDodgerBlue
  840.     m_arrColors(20) = cSeaBlue
  841.     m_arrColors(21) = cBlue
  842.     m_arrColors(22) = cBluePurple
  843.     m_arrColors(23) = cDeepPurple
  844.     m_arrColors(24) = cPurple
  845.     m_arrColors(25) = cPurpleRed
  846.  
  847.     ' -----------------------------------------------------------------------------
  848.     ' INITIALIZE OTHER VARIABLES
  849.     bIgnoreTerrain = TRUE
  850.  
  851.     ' -----------------------------------------------------------------------------
  852.     ' DRAW FLOOR
  853.     For iLoopZ% = m_iMapMinZ To m_iMapMinZ
  854.         For iLoopX% = m_iMapMinX To m_iMapMaxX
  855.             For iLoopY% = m_iMapMinY To m_iMapMaxY
  856.                 ' ALTERNATE TILE COLORS
  857.                 If IsEven%(iLoopX%) = TRUE Then
  858.                     If IsEven%(iLoopY%) = TRUE Then
  859.                         PlotTile iLoopX%, iLoopY%, iLoopZ%, c_iTile_Wall, cGray
  860.                     Else
  861.                         PlotTile iLoopX%, iLoopY%, iLoopZ%, c_iTile_Wall, cWhite
  862.                     End If
  863.                 Else
  864.                     If IsEven%(iLoopY%) = TRUE Then
  865.                         PlotTile iLoopX%, iLoopY%, iLoopZ%, c_iTile_Wall, cWhite
  866.                     Else
  867.                         PlotTile iLoopX%, iLoopY%, iLoopZ%, c_iTile_Wall, cGray
  868.                     End If
  869.                 End If
  870.             Next iLoopY%
  871.         Next iLoopX%
  872.     Next iLoopZ%
  873.  
  874.     ' -----------------------------------------------------------------------------
  875.     ' DRAW A TALL HOLLOW PYRAMID
  876.     If TRUE = TRUE Then
  877.         iX% = 5
  878.         iY% = 10
  879.         iZ% = 1
  880.         iLevelSize% = 4
  881.  
  882.         iPosX1% = iX%
  883.         iPosX2% = iX% + 7
  884.         iPosY1% = iY%
  885.         iPosY2% = iY% + 7
  886.  
  887.         iNextColor~& = cRed
  888.         iColorScheme% = 1 ' 1 = Rainbow6 #1, 9 = Rainbow6 #2, etc.
  889.  
  890.         'iNextColor~& = cWhite
  891.         'iColorScheme% = 3 ' 3, 11 = grayscale, ascending
  892.  
  893.         iLevelCount% = 0
  894.  
  895.         bContinue = TRUE
  896.         Do
  897.             ' Draw front/back walls
  898.             For iLoopX% = iPosX1% To iPosX2%
  899.                 iLoopY% = iPosY1%
  900.                 PlotTile iLoopX%, iLoopY%, iZ%, c_iTile_Wall, iNextColor~&
  901.  
  902.                 iLoopY% = iPosY2%
  903.                 PlotTile iLoopX%, iLoopY%, iZ%, c_iTile_Wall, iNextColor~&
  904.             Next iLoopX%
  905.  
  906.             ' Draw left/right walls
  907.             For iLoopY% = iPosY1% To iPosY2%
  908.                 iLoopX% = iPosX1%
  909.                 PlotTile iLoopX%, iLoopY%, iZ%, c_iTile_Wall, iNextColor~&
  910.  
  911.                 iLoopX% = iPosX2%
  912.                 PlotTile iLoopX%, iLoopY%, iZ%, c_iTile_Wall, iNextColor~&
  913.             Next iLoopY%
  914.  
  915.             ' Add a door to middle of right wall
  916.             iX% = iPosX1% + ((iPosX2% - iPosX1%) \ 2)
  917.             PlotTile iX%, iPosY2%, iZ%, c_iTile_Empty, iNextColor~&
  918.  
  919.             ' Add a door to middle of front wall
  920.             iY% = iPosY1% + ((iPosY2% - iPosY1%) \ 2)
  921.             PlotTile iPosX2%, iY%, iZ%, c_iTile_Empty, iNextColor~&
  922.  
  923.             ' MOVE UP A LEVEL
  924.             iLevelCount% = iLevelCount% + 1
  925.             If iLevelCount% > iLevelSize% Then
  926.                 iLevelCount% = 0
  927.                 iPosX1% = iPosX1% + 1
  928.                 iPosX2% = iPosX2% - 1
  929.                 iPosY1% = iPosY1% + 1
  930.                 iPosY2% = iPosY2% - 1
  931.             End If
  932.  
  933.             ' QUIT AFTER WE REACH THE TOP
  934.             If (iPosX1% <= iPosX2%) And (iPosY1% <= iPosY2%) Then
  935.                 iZ% = iZ% + 1
  936.                 DoCycleColor iColorScheme%, iNextColor~&
  937.                 If iZ% > m_iMapMaxZ Then
  938.                     bContinue = FALSE
  939.                 End If
  940.             Else
  941.                 bContinue = FALSE
  942.             End If
  943.  
  944.         Loop Until bContinue = FALSE
  945.     End If
  946.  
  947.     ' -----------------------------------------------------------------------------
  948.     ' DRAW FRAME AROUND ENTIRE SPACE (TOP)
  949.  
  950.     For iLoopX% = m_iMapMinX + 3 To m_iMapMaxX - 3
  951.         PlotTile iLoopX%, m_iMapMaxY - 3, m_iMapMaxZ, c_iTile_Wall, cPurple
  952.         PlotTile iLoopX%, m_iMapMinY + 3, m_iMapMaxZ, c_iTile_Wall, cCyan
  953.     Next iLoopX%
  954.  
  955.     For iLoopY% = m_iMapMinY + 3 To m_iMapMaxY - 3
  956.         PlotTile m_iMapMinX + 3, iLoopY%, m_iMapMaxZ, c_iTile_Wall, cOrange
  957.         PlotTile m_iMapMaxX - 3, iLoopY%, m_iMapMaxZ, c_iTile_Wall, cLime
  958.     Next iLoopY%
  959.  
  960.     ' -----------------------------------------------------------------------------
  961.     ' DRAW FRAME AROUND ENTIRE SPACE (MIDDLE)
  962.  
  963.     For iLoopX% = m_iMapMinX + 2 To m_iMapMaxX - 2
  964.         PlotTile iLoopX%, m_iMapMaxY - 2, m_iMapMidZ, c_iTile_Wall, cDodgerBlue
  965.         PlotTile iLoopX%, m_iMapMinY + 2, m_iMapMidZ, c_iTile_Wall, cDeepPurple
  966.     Next iLoopX%
  967.  
  968.     For iLoopY% = m_iMapMinY + 2 To m_iMapMaxY - 2
  969.         PlotTile m_iMapMinX + 2, iLoopY%, m_iMapMidZ, c_iTile_Wall, cDarkRed
  970.         PlotTile m_iMapMaxX - 2, iLoopY%, m_iMapMidZ, c_iTile_Wall, cGold
  971.     Next iLoopY%
  972.  
  973.     ' -----------------------------------------------------------------------------
  974.     ' DRAW FRAME AROUND ENTIRE SPACE (BOTTOM)
  975.  
  976.     For iLoopX% = m_iMapMinX + 1 To m_iMapMaxX - 1
  977.         PlotTile iLoopX%, m_iMapMaxY - 1, m_iMapMinZ + 1, c_iTile_Wall, cSeaBlue
  978.         PlotTile iLoopX%, m_iMapMinY + 1, m_iMapMinZ + 1, c_iTile_Wall, cChartreuse
  979.     Next iLoopX%
  980.  
  981.     For iLoopY% = m_iMapMinY + 1 To m_iMapMaxY - 1
  982.         PlotTile m_iMapMinX + 1, iLoopY%, m_iMapMinZ + 1, c_iTile_Wall, cOrangeRed
  983.         PlotTile m_iMapMaxX - 1, iLoopY%, m_iMapMinZ + 1, c_iTile_Wall, cDeepSkyBlue
  984.     Next iLoopY%
  985.  
  986.     ' =============================================================================
  987.     ' PLACE PLAYER(S) <- ONLY ONE FOR THIS DEMO
  988.  
  989.     For iPlayerLoop = 1 To m_iPlayerCount
  990.  
  991.         ' -----------------------------------------------------------------------------
  992.         ' BEGIN Map the 6 directional keys
  993.         ' -----------------------------------------------------------------------------
  994.         '*** CURRENTLY THIS IS NOT USED ***
  995.         'TODO: GET THIS WORKING (CURRENTLY IT'S ALL WEIRD)
  996.         'TODO: WHATEVER THE KEYS MAPPED ARE, SWAP THEM NON-HARDCODED
  997.  
  998.         ' differently for each of the 6 directional orientations!
  999.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Down).KeyBack = c_iKeyDown_Down
  1000.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Down).KeyForward = c_iKeyDown_Up
  1001.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Down).KeyLeft = c_iKeyDown_Left
  1002.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Down).KeyRight = c_iKeyDown_Right
  1003.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Down).KeyUp = c_iKeyDown_PgDn
  1004.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Down).KeyDown = c_iKeyDown_PgUp
  1005.  
  1006.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Up).KeyBack = c_iKeyDown_PgDn
  1007.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Up).KeyForward = c_iKeyDown_PgUp
  1008.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Up).KeyLeft = c_iKeyDown_Left
  1009.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Up).KeyRight = c_iKeyDown_Right
  1010.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Up).KeyUp = c_iKeyDown_Up
  1011.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Up).KeyDown = c_iKeyDown_Down
  1012.  
  1013.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Left).KeyBack = c_iKeyDown_Right
  1014.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Left).KeyForward = c_iKeyDown_Left
  1015.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Left).KeyLeft = c_iKeyDown_Down
  1016.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Left).KeyRight = c_iKeyDown_Up
  1017.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Left).KeyUp = c_iKeyDown_PgUp
  1018.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Left).KeyDown = c_iKeyDown_PgDn
  1019.  
  1020.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Right).KeyBack = c_iKeyDown_Left
  1021.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Right).KeyForward = c_iKeyDown_Right
  1022.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Right).KeyLeft = c_iKeyDown_Up
  1023.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Right).KeyRight = c_iKeyDown_Down
  1024.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Right).KeyUp = c_iKeyDown_PgUp
  1025.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Right).KeyDown = c_iKeyDown_PgDn
  1026.  
  1027.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Back).KeyBack = c_iKeyDown_Down
  1028.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Back).KeyForward = c_iKeyDown_Up
  1029.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Back).KeyLeft = c_iKeyDown_Right
  1030.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Back).KeyRight = c_iKeyDown_Left
  1031.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Back).KeyUp = c_iKeyDown_PgUp
  1032.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Back).KeyDown = c_iKeyDown_PgDn
  1033.  
  1034.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Forward).KeyBack = c_iKeyDown_Up
  1035.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Forward).KeyForward = c_iKeyDown_Down
  1036.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Forward).KeyLeft = c_iKeyDown_Left
  1037.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Forward).KeyRight = c_iKeyDown_Right
  1038.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Forward).KeyUp = c_iKeyDown_PgUp
  1039.         m_arrDirKeyMap(iPlayerLoop, c_iDir_Forward).KeyDown = c_iKeyDown_PgDn
  1040.         ' -----------------------------------------------------------------------------
  1041.         ' END Map the 6 directional keys
  1042.         ' -----------------------------------------------------------------------------
  1043.  
  1044.         ' FIND START POSITION
  1045.         iX% = RandomNumber(m_iMapMinX, m_iMapMaxX)
  1046.         iY% = RandomNumber(m_iMapMinY, m_iMapMaxY)
  1047.         iZ% = 1 ' RandomNumber(m_iMapMinZ, m_iMapMaxZ)
  1048.  
  1049.         ' MAKE SURE IT'S EMPTY
  1050.         If m_arrMap(iX%, iY%, iZ%).Typ = c_iTile_Empty Then
  1051.             bFound = TRUE
  1052.         Else
  1053.             ' IF NOT EMPTY THEN TRY TO FIND AN EMPTY SPOT
  1054.             iTotal% = ((m_iMapMaxX - m_iMapMinX) + 1) * ((m_iMapMaxY - m_iMapMinY) + 1) * ((m_iMapMaxZ - m_iMapMinZ) + 1)
  1055.             iCount% = 0
  1056.             bFound = FALSE
  1057.             Do
  1058.                 iX% = iX% + 1
  1059.                 If iX% > m_iMapMaxX Then
  1060.                     ' reset x and move to next y
  1061.                     iX% = m_iMapMinX
  1062.                     iY% = iY% + 1
  1063.                     If iY% > m_iMapMaxY Then
  1064.                         ' reset y and move to next z
  1065.                         iY% = m_iMapMinY
  1066.                         iZ% = iZ% + 1
  1067.                         If iZ% > m_iMapMaxZ Then
  1068.                             ' RESET Z AND SEE IF WE HAVE CHECKED EVERYTHING
  1069.                             iZ% = m_iMapMinZ
  1070.                             iCount% = iCount% + 1
  1071.                             If iCount% >= iTotal% Then
  1072.                                 ' NONE FOUND, EXIT
  1073.                                 Exit Do
  1074.                             End If
  1075.                         Else
  1076.                             iCount% = iCount% + 1
  1077.                         End If
  1078.                     Else
  1079.                         iCount% = iCount% + 1
  1080.                     End If
  1081.                 Else
  1082.                     iCount% = iCount% + 1
  1083.                 End If
  1084.                 If m_arrMap(iX%, iY%, iZ%).Typ = c_iTile_Empty Then
  1085.                     ' FOUND AN EMPTY SPACE, EXIT
  1086.                     bFound = TRUE
  1087.                     Exit Do
  1088.                 End If
  1089.             Loop
  1090.         End If
  1091.  
  1092.         If bFound = TRUE Then
  1093.             ' PICK A DIRECTION (SIMPLE FOR NOW, LEFT OR RIGHT)
  1094.             If iX% <= m_iMapMidX Then
  1095.                 m_arrPlayer(iPlayerLoop).Direction = c_iDir_Right
  1096.             Else
  1097.                 m_arrPlayer(iPlayerLoop).Direction = c_iDir_Left
  1098.             End If
  1099.  
  1100.             m_arrPlayer(iPlayerLoop).Tile1 = c_iTile_Player1
  1101.  
  1102.             ' SAVE COORDINATES TO PLAYER
  1103.             ' ****************************************************************************************************************************************************************
  1104.             ' for this demo we'll just use iX% instead of m_arrPlayer(iPlayerLoop).x, etc.
  1105.             ' to make it more readable
  1106.             ' ****************************************************************************************************************************************************************
  1107.             m_arrPlayer(iPlayerLoop).x = iX%
  1108.             m_arrPlayer(iPlayerLoop).y = iY%
  1109.             m_arrPlayer(iPlayerLoop).z = iZ%
  1110.             m_arrPlayer(iPlayerLoop).View = c_iDir_Forward
  1111.             m_arrPlayer(iPlayerLoop).Color1 = cRed
  1112.             m_arrPlayer(iPlayerLoop).Alpha1 = 255
  1113.             m_arrPlayer(iPlayerLoop).AlphaOverride = 255
  1114.             m_arrPlayer(iPlayerLoop).ColorScheme1 = 2
  1115.             m_arrPlayer(iPlayerLoop).ColorSchemeSpeed1 = 5 ' change color every 5 frames
  1116.             m_arrPlayer(iPlayerLoop).ColorSchemeCount1 = 0
  1117.  
  1118.             ' DISPLAY OPTIONS
  1119.             m_arrPlayer(iPlayerLoop).GridSize = 8
  1120.             m_arrPlayer(iPlayerLoop).MapSize = 4
  1121.  
  1122.             ' RESET MOVEMENT VARIABLES
  1123.             m_arrPlayer(iPlayerLoop).IsMoving = FALSE
  1124.             m_arrPlayer(iPlayerLoop).IsMoved = FALSE
  1125.  
  1126.             ' ********************************************************************************
  1127.             ' *** THIS IS NOW DONE AT THE RENDERING LEVEL FOR PLAYERS AND NON-TERRAIN OBJECTS
  1128.             ' ********************************************************************************
  1129.             '' DRAW PLAYER
  1130.             'm_arrMap(iX%, iY%, iZ%).Typ = m_arrPlayer(iPlayerLoop).Tile1
  1131.             'm_arrMap(iX%, iY%, iZ%).Color1 = m_arrPlayer(iPlayerLoop).Color1
  1132.             'm_arrMap(iX%, iY%, iZ%).AlphaOverride = m_arrPlayer(iPlayerLoop).Alpha1
  1133.  
  1134.         Else
  1135.             sError = "Could not find an empty space to start player."
  1136.             Exit For
  1137.         End If
  1138.  
  1139.     Next iPlayerLoop
  1140.  
  1141.     ' =============================================================================
  1142.     ' OTHER SETUP
  1143.     If Len(sError) = 0 Then
  1144.         ' RESET INPUT
  1145.         _KeyClear
  1146.         iLastKey = c_iKeyDown_Enter
  1147.     End If
  1148.  
  1149.     ' INIT UNDO INFO:
  1150.     m_MapTileUndo.x = iX%
  1151.     m_MapTileUndo.y = iY%
  1152.     m_MapTileUndo.z = iZ%
  1153.     m_MapTileUndo.Typ = m_arrMap(iX%, iY%, iZ%).Typ
  1154.     m_MapTileUndo.Color1 = m_arrMap(iX%, iY%, iZ%).Color1
  1155.     m_MapTileUndo.Alpha1 = m_arrMap(iX%, iY%, iZ%).Alpha1
  1156.  
  1157.     ' =============================================================================
  1158.     ' MAIN LOOP
  1159.     If Len(sError) = 0 Then
  1160.         iDrawColor% = 8 ' RED
  1161.         iCursorColor~& = cRed
  1162.         bFinished = FALSE
  1163.         Do
  1164.             Cls ' is cls necessary?
  1165.  
  1166.             ' SHOW INSTRUCTIONS / COORDINATES ON SCREEN
  1167.             Locate 1, 3: Print "IsometricDraw1"
  1168.             Locate 3, 3: Print "CRSR RT/LF MOVES X = " + cstr$(iX%)
  1169.             Locate 4, 3: Print "CRSR UP/DN MOVES Y = " + cstr$(iY%)
  1170.             Locate 5, 3: Print "PAGE UP/DN MOVES Z = " + cstr$(iZ%)
  1171.             Locate 6, 3: Print "=    / -   CHANGES GRID SIZE     = " + cstr$(m_arrPlayer(1).GridSize)
  1172.             Locate 7, 3: Print "[    / ]   TOGGLES MOVEMENT      = " + IIFSTR$(m_arrPlayer(1).IsMoving, "TRUE", "FALSE")
  1173.             Locate 8, 3: Print "INS  / DEL TOGGLES REPEAT KEYS   = " + IIFSTR$(bEnableRepeatingKeys, "TRUE", "FALSE")
  1174.             Locate 9, 3: Print ",    / .   CHANGES MINI MAP SIZE = " + cstr$(m_arrPlayer(1).MapSize)
  1175.             Locate 10, 3: Print "a    / b   FOR UNDO / REDO"
  1176.             Locate 12, 3: Print "PRESS <ESC> TO QUIT"
  1177.  
  1178.             Locate 25, 10: Print "1 color-"
  1179.             Locate 26, 10: Print "2 color+"
  1180.             Locate 27, 10: Print "3 draw"
  1181.             Locate 28, 10: Print "4 erase"
  1182.             Locate 29, 10: Print "5 toggle"
  1183.             Locate 30, 10: Print "6 eyedropper"
  1184.             Locate 31, 10: Print "7 clear"
  1185.             Locate 32, 10: Print "8 open"
  1186.             Locate 33, 10: Print "9 save"
  1187.  
  1188.             ' ****************************************************************************************************************************************************************
  1189.             ' BEGIN DRAW PALETTE
  1190.             ' ****************************************************************************************************************************************************************
  1191.             'TODO: support variable screen resolutions instead of hardcoded 1280x1024
  1192.             iSize% = 24 ' {n}x{n} pixels square
  1193.             iDrawX% = 10
  1194.             iOffsetY% = 350
  1195.             For iLoop1 = 0 To 25
  1196.                 iDrawY% = iOffsetY% + (iLoop1 * iSize%)
  1197.                 If iLoop1 = 0 Then
  1198.                     ' COLOR = TRANSPARENT
  1199.  
  1200.                     ' DRAW A CHECKERBOARD PATTERN FOR TRANSPARENT
  1201.                     iFirstColor~& = cDarkGray
  1202.                     For iLoopY% = iDrawY% To ((iDrawY% + iSize%) - 4) Step 4
  1203.                         If iFirstColor~& = cDarkGray Then
  1204.                             iFirstColor~& = cGray
  1205.                         Else
  1206.                             iFirstColor~& = cDarkGray
  1207.                         End If
  1208.                         iNextColor~& = iFirstColor~&
  1209.                         For iLoopX% = iDrawX% To ((iDrawX% + iSize%) - 4) Step 4
  1210.                             DrawBox iLoopX%, iLoopY%, 4, iNextColor~&
  1211.                             If iNextColor~& = cDarkGray Then
  1212.                                 iNextColor~& = cGray
  1213.                             Else
  1214.                                 iNextColor~& = cDarkGray
  1215.                             End If
  1216.                         Next iLoopX%
  1217.                     Next iLoopY%
  1218.                 ElseIf iLoop1 = 1 Then
  1219.                     ' COLOR = BLACK
  1220.                 Else
  1221.                     iNextColor~& = m_arrColors(iLoop1)
  1222.                     DrawBox iDrawX%, iDrawY%, iSize%, iNextColor~&
  1223.                 End If
  1224.  
  1225.                 ' DRAW A BORDER AROUND IT
  1226.                 iNextColor~& = cDarkGray
  1227.                 DrawOutlineBox iDrawX%, iDrawY%, iSize%, iNextColor~&, 1
  1228.             Next iLoop1
  1229.  
  1230.             ' DRAW WHITE BOX AROUND CURRENT COLOR
  1231.             DoCycleColor 1, iCursorColor~&
  1232.             iDrawY% = iOffsetY% + (iDrawColor% * iSize%)
  1233.             DrawOutlineBox iDrawX%, iDrawY%, iSize%, iCursorColor~&, 1
  1234.             ' ****************************************************************************************************************************************************************
  1235.             ' END DRAW PALETTE
  1236.             ' ****************************************************************************************************************************************************************
  1237.  
  1238.  
  1239.  
  1240.  
  1241.  
  1242.             ' ****************************************************************************************************************************************************************
  1243.             ' BEGIN PLAYER LOOP
  1244.             ' ****************************************************************************************************************************************************************
  1245.             DrawScreen c_iDir_Forward, m_arrSplitScreen(1).ScreenOffsetX, m_arrSplitScreen(1).ScreenOffsetY, m_arrPlayer(1).GridSize, iX%, iY%, iZ%
  1246.             DrawScreen c_iDir_Back, m_arrSplitScreen(2).ScreenOffsetX, m_arrSplitScreen(2).ScreenOffsetY, m_arrPlayer(1).GridSize, iX%, iY%, iZ%
  1247.             DrawScreen c_iDir_Left, m_arrSplitScreen(3).ScreenOffsetX, m_arrSplitScreen(3).ScreenOffsetY, m_arrPlayer(1).GridSize, iX%, iY%, iZ%
  1248.             DrawScreen c_iDir_Right, m_arrSplitScreen(4).ScreenOffsetX, m_arrSplitScreen(4).ScreenOffsetY, m_arrPlayer(1).GridSize, iX%, iY%, iZ%
  1249.  
  1250.             For iPlayerLoop = 1 To m_iPlayerCount
  1251.                 'DrawScreen m_arrPlayer(iPlayerLoop).View, cScreenOffsetX, cScreenOffsetY, iX%, iY%, iZ%
  1252.  
  1253.                 ' -----------------------------------------------------------------------------
  1254.                 ' BEGIN SHOW TOP-DOWN X/Y 2D MINI MAP ON SCREEN
  1255.                 ' -----------------------------------------------------------------------------
  1256.                 ' TODO: FOR MULTIPLAYER, DRAW A SEPARATE MAP PER PLAYER TO SPLIT SCREEN
  1257.                 ' ADD TEXT LABEL
  1258.                 Locate m_arrSplitScreen(iPlayerLoop).MiniMapTopDownTextY, m_arrSplitScreen(iPlayerLoop).MiniMapTopDownTextX: Print "Top dn (Z-slice):"
  1259.                 ' DRAW MAP
  1260.                 For iLoopX% = m_iMapMinX To m_iMapMaxX
  1261.                     For iLoopY% = m_iMapMinY To m_iMapMaxY
  1262.                         iDrawX% = (iLoopX% * m_arrPlayer(1).MapSize) + m_arrSplitScreen(iPlayerLoop).MiniMapTopDownX
  1263.                         iDrawY% = (iLoopY% * m_arrPlayer(1).MapSize) + m_arrSplitScreen(iPlayerLoop).MiniMapTopDownY
  1264.                         If m_arrMap(iLoopX%, iLoopY%, iZ%).Typ = c_iTile_Wall Then
  1265.                             DrawBox iDrawX%, iDrawY%, m_arrPlayer(1).MapSize, m_arrMap(iLoopX%, iLoopY%, iZ%).Color1
  1266.                         ElseIf m_arrMap(iLoopX%, iLoopY%, iZ%).Typ = c_iTile_Player1 Then
  1267.                             DrawBox iDrawX%, iDrawY%, m_arrPlayer(1).MapSize, m_arrMap(iLoopX%, iLoopY%, iZ%).Color1
  1268.                         ElseIf m_arrMap(iLoopX%, iLoopY%, iZ%).Typ = c_iTile_Player2 Then
  1269.                             DrawBox iDrawX%, iDrawY%, m_arrPlayer(1).MapSize, m_arrMap(iLoopX%, iLoopY%, iZ%).Color1
  1270.                         ElseIf m_arrMap(iLoopX%, iLoopY%, iZ%).Typ = c_iTile_Player3 Then
  1271.                             DrawBox iDrawX%, iDrawY%, m_arrPlayer(1).MapSize, m_arrMap(iLoopX%, iLoopY%, iZ%).Color1
  1272.                         ElseIf m_arrMap(iLoopX%, iLoopY%, iZ%).Typ = c_iTile_Player4 Then
  1273.                             DrawBox iDrawX%, iDrawY%, m_arrPlayer(1).MapSize, m_arrMap(iLoopX%, iLoopY%, iZ%).Color1
  1274.                             'TODO: ADD OTHER TYPES
  1275.                         Else
  1276.                             DrawBox iDrawX%, iDrawY%, m_arrPlayer(1).MapSize, cKhaki
  1277.                         End If
  1278.                     Next iLoopY%
  1279.                 Next iLoopX%
  1280.                 ' DRAW THE PLAYERS ON THE MINI MAP
  1281.                 For iLoop1 = m_iPlayerMin To m_iPlayerCount
  1282.                     iDrawX% = (m_arrPlayer(iLoop1).x * m_arrPlayer(1).MapSize) + m_arrSplitScreen(iPlayerLoop).MiniMapTopDownX
  1283.                     iDrawY% = (m_arrPlayer(iLoop1).y * m_arrPlayer(1).MapSize) + m_arrSplitScreen(iPlayerLoop).MiniMapTopDownY
  1284.                     ' TODO: ADD Alpha PARAMETER TO DrawBox
  1285.                     DrawBox iDrawX%, iDrawY%, m_arrPlayer(1).MapSize, m_arrPlayer(iLoop1).Color1
  1286.                 Next iLoop1
  1287.                 ' DRAW THE OBJECTS ON THE MINI MAP
  1288.                 ' (TO DO WHEN WE ADD OBJECTS)
  1289.                 ' -----------------------------------------------------------------------------
  1290.                 ' END SHOW TOP-DOWN X/Y 2D MINI MAP ON SCREEN
  1291.                 ' -----------------------------------------------------------------------------
  1292.  
  1293.  
  1294.  
  1295.  
  1296.  
  1297.                 ' -----------------------------------------------------------------------------
  1298.                 ' BEGIN SHOW FRONT-BACK X/Z 2D MINI MAP ON SCREEN
  1299.                 ' -----------------------------------------------------------------------------
  1300.                 ' TODO: FOR MULTIPLAYER, DRAW A SEPARATE MAP PER PLAYER TO SPLIT SCREEN
  1301.                 ' ADD TEXT LABEL
  1302.                 Locate m_arrSplitScreen(iPlayerLoop).MiniMapFrontBackTextY, m_arrSplitScreen(iPlayerLoop).MiniMapFrontBackTextX: Print "Frnt-bk (Y-slice):"
  1303.                 ' DRAW MAP
  1304.                 For iLoopZ% = m_iMapMaxZ To m_iMapMinZ Step -1
  1305.                     For iLoopX% = m_iMapMinX To m_iMapMaxX
  1306.                         iDrawX% = (iLoopX% * m_arrPlayer(1).MapSize) + m_arrSplitScreen(iPlayerLoop).MiniMapFrontBackX
  1307.                         iDrawY% = ((m_iMapMaxZ - iLoopZ%) * m_arrPlayer(1).MapSize) + m_arrSplitScreen(iPlayerLoop).MiniMapFrontBackY
  1308.                         If m_arrMap(iLoopX%, iY%, iLoopZ%).Typ = c_iTile_Wall Then
  1309.                             DrawBox iDrawX%, iDrawY%, m_arrPlayer(1).MapSize, m_arrMap(iLoopX%, iY%, iLoopZ%).Color1
  1310.                         ElseIf m_arrMap(iLoopX%, iY%, iLoopZ%).Typ = c_iTile_Player1 Then
  1311.                             DrawBox iDrawX%, iDrawY%, m_arrPlayer(1).MapSize, m_arrMap(iLoopX%, iY%, iLoopZ%).Color1
  1312.                         ElseIf m_arrMap(iLoopX%, iY%, iLoopZ%).Typ = c_iTile_Player2 Then
  1313.                             DrawBox iDrawX%, iDrawY%, m_arrPlayer(1).MapSize, m_arrMap(iLoopX%, iY%, iLoopZ%).Color1
  1314.                         ElseIf m_arrMap(iLoopX%, iY%, iLoopZ%).Typ = c_iTile_Player3 Then
  1315.                             DrawBox iDrawX%, iDrawY%, m_arrPlayer(1).MapSize, m_arrMap(iLoopX%, iY%, iLoopZ%).Color1
  1316.                         ElseIf m_arrMap(iLoopX%, iY%, iLoopZ%).Typ = c_iTile_Player4 Then
  1317.                             DrawBox iDrawX%, iDrawY%, m_arrPlayer(1).MapSize, m_arrMap(iLoopX%, iY%, iLoopZ%).Color1
  1318.                             'TODO: ADD OTHER TYPES
  1319.                         Else
  1320.                             DrawBox iDrawX%, iDrawY%, m_arrPlayer(1).MapSize, cKhaki
  1321.                         End If
  1322.                     Next iLoopX%
  1323.                 Next iLoopZ%
  1324.                 ' DRAW THE PLAYERS ON THE MINI MAP
  1325.                 For iLoop1 = m_iPlayerMin To m_iPlayerCount
  1326.                     iDrawX% = (m_arrPlayer(iLoop1).x * m_arrPlayer(1).MapSize) + m_arrSplitScreen(iPlayerLoop).MiniMapFrontBackX
  1327.                     iDrawY% = ((m_iMapMaxZ - m_arrPlayer(iLoop1).z) * m_arrPlayer(1).MapSize) + m_arrSplitScreen(iPlayerLoop).MiniMapFrontBackY
  1328.                     ' TODO: ADD Alpha PARAMETER TO DrawBox
  1329.                     DrawBox iDrawX%, iDrawY%, m_arrPlayer(1).MapSize, m_arrPlayer(iLoop1).Color1
  1330.                 Next iLoop1
  1331.                 ' DRAW THE OBJECTS ON THE MINI MAP
  1332.                 ' (TO DO WHEN WE ADD OBJECTS)
  1333.                 ' -----------------------------------------------------------------------------
  1334.                 ' END SHOW FRONT-BACK X/Z 2D MINI MAP ON SCREEN
  1335.                 ' -----------------------------------------------------------------------------
  1336.  
  1337.  
  1338.  
  1339.  
  1340.  
  1341.                 ' -----------------------------------------------------------------------------
  1342.                 ' BEGIN SHOW RIGHT/LEFT Y/Z 2D MINI MAP ON SCREEN
  1343.                 ' -----------------------------------------------------------------------------
  1344.                 ' TODO: FOR MULTIPLAYER, DRAW A SEPARATE MAP PER PLAYER TO SPLIT SCREEN
  1345.                 ' ADD TEXT LABEL
  1346.                 Locate m_arrSplitScreen(iPlayerLoop).MiniMapRightLeftTextY, m_arrSplitScreen(iPlayerLoop).MiniMapRightLeftTextX: Print "Rt-left (X-slice):"
  1347.                 ' DRAW MAP
  1348.                 For iLoopZ% = m_iMapMaxZ To m_iMapMinZ Step -1
  1349.                     For iLoopY% = m_iMapMinY To m_iMapMaxY
  1350.                         iDrawX% = ((m_iMapMaxY - iLoopY%) * m_arrPlayer(1).MapSize) + m_arrSplitScreen(iPlayerLoop).MiniMapRightLeftX
  1351.                         iDrawY% = ((m_iMapMaxZ - iLoopZ%) * m_arrPlayer(1).MapSize) + m_arrSplitScreen(iPlayerLoop).MiniMapRightLeftY
  1352.                         If m_arrMap(iX%, iLoopY%, iLoopZ%).Typ = c_iTile_Wall Then
  1353.                             DrawBox iDrawX%, iDrawY%, m_arrPlayer(1).MapSize, m_arrMap(iX%, iLoopY%, iLoopZ%).Color1
  1354.                         ElseIf m_arrMap(iX%, iLoopY%, iLoopZ%).Typ = c_iTile_Player1 Then
  1355.                             DrawBox iDrawX%, iDrawY%, m_arrPlayer(1).MapSize, m_arrMap(iX%, iLoopY%, iLoopZ%).Color1
  1356.                         ElseIf m_arrMap(iX%, iLoopY%, iLoopZ%).Typ = c_iTile_Player2 Then
  1357.                             DrawBox iDrawX%, iDrawY%, m_arrPlayer(1).MapSize, m_arrMap(iX%, iLoopY%, iLoopZ%).Color1
  1358.                         ElseIf m_arrMap(iX%, iLoopY%, iLoopZ%).Typ = c_iTile_Player3 Then
  1359.                             DrawBox iDrawX%, iDrawY%, m_arrPlayer(1).MapSize, m_arrMap(iX%, iLoopY%, iLoopZ%).Color1
  1360.                         ElseIf m_arrMap(iX%, iLoopY%, iLoopZ%).Typ = c_iTile_Player4 Then
  1361.                             DrawBox iDrawX%, iDrawY%, m_arrPlayer(1).MapSize, m_arrMap(iX%, iLoopY%, iLoopZ%).Color1
  1362.                             'TODO: ADD OTHER TYPES
  1363.                         Else
  1364.                             DrawBox iDrawX%, iDrawY%, m_arrPlayer(1).MapSize, cKhaki
  1365.                         End If
  1366.                     Next iLoopY%
  1367.                 Next iLoopZ%
  1368.                 ' DRAW THE PLAYERS ON THE MINI MAP
  1369.                 For iLoop1 = m_iPlayerMin To m_iPlayerCount
  1370.                     iDrawX% = ((m_iMapMaxY - m_arrPlayer(iLoop1).y) * m_arrPlayer(1).MapSize) + m_arrSplitScreen(iPlayerLoop).MiniMapRightLeftX
  1371.                     iDrawY% = ((m_iMapMaxZ - m_arrPlayer(iLoop1).z) * m_arrPlayer(1).MapSize) + m_arrSplitScreen(iPlayerLoop).MiniMapRightLeftY
  1372.                     ' TODO: ADD Alpha PARAMETER TO DrawBox
  1373.                     DrawBox iDrawX%, iDrawY%, m_arrPlayer(1).MapSize, m_arrPlayer(iLoop1).Color1
  1374.                 Next iLoop1
  1375.                 ' DRAW THE OBJECTS ON THE MINI MAP
  1376.                 ' (TO DO WHEN WE ADD OBJECTS)
  1377.                 ' -----------------------------------------------------------------------------
  1378.                 ' END SHOW RIGHT/LEFT Y/Z 2D MINI MAP ON SCREEN
  1379.                 ' -----------------------------------------------------------------------------
  1380.  
  1381.  
  1382.  
  1383.  
  1384.                 ' -----------------------------------------------------------------------------
  1385.                 ' TODO: SHOW SIMPLE FIRST-PERSON MINI-DISPLAY ON SCREEN
  1386.                 '       POINTING WHICHEVER WAY USER MOVED LAST
  1387.                 ' -----------------------------------------------------------------------------
  1388.  
  1389.  
  1390.  
  1391.                 ' =============================================================================
  1392.                 ' BEGIN GET KEYBOARD INPUT WITH _BUTTON
  1393.                 ' =============================================================================
  1394.                 ' *** HEY WHY HAS _BUTTON STOPPED WORKING? DID I NOT GET A MEMO? ***
  1395.                 ' -----------------------------------------------------------------------------
  1396.                 ' BEGIN UNDO v1
  1397.                 ' TODO: unlimited levels of undo, for now just 1
  1398.                 ' -----------------------------------------------------------------------------
  1399.                 'IF _BUTTON(KeyCode_CtrlLeft%) OR _BUTTON(KeyCode_CtrlRight%) THEN
  1400.                 '   IF _BUTTON(KeyCode_Z%) THEN
  1401.                 '       IF Not m_bButton_Z THEN
  1402.                 '           m_bButton_Z = TRUE
  1403.                 '           ' UNDO!
  1404.                 '       END IF
  1405.                 '   ELSEIF _BUTTON(KeyCode_Y%) THEN
  1406.                 '       IF Not m_bButton_Y THEN
  1407.                 '           m_bButton_Y = TRUE
  1408.                 '           ' REDO!
  1409.                 '       END IF
  1410.                 '   END IF
  1411.                 'END IF
  1412.                 '
  1413.                 ' TRACK WHEN KEYS ARE RELEASED (DISABLES REPEATING KEYS)
  1414.                 'IF Not _BUTTON(KeyCode_Z%) THEN
  1415.                 '   m_bButton_Z = FALSE
  1416.                 'END IF
  1417.                 'IF Not _BUTTON(KeyCode_Y%) THEN
  1418.                 '   m_bButton_Y = FALSE
  1419.                 'END IF
  1420.                 ' -----------------------------------------------------------------------------
  1421.                 ' END UNDO v1
  1422.                 ' -----------------------------------------------------------------------------
  1423.  
  1424.                 ' =============================================================================
  1425.                 ' END GET KEYBOARD INPUT WITH _BUTTON
  1426.                 ' =============================================================================
  1427.  
  1428.  
  1429.                 ' =============================================================================
  1430.                 ' BEGIN GET DIRECTIONAL KEYBOARD INPUT
  1431.                 ' =============================================================================
  1432.                 If _KeyDown(c_iKeyDown_Up) Then
  1433.                     If iLastKey <> c_iKeyDown_Up Or bEnableRepeatingKeys = TRUE Then
  1434.                         iLastKey = c_iKeyDown_Up
  1435.                         m_arrPlayer(iPlayerLoop).Direction = c_iDir_Back
  1436.                         bMoved = TRUE
  1437.                     End If
  1438.                 ElseIf _KeyDown(c_iKeyDown_Down) Then
  1439.                     If iLastKey <> c_iKeyDown_Down Or bEnableRepeatingKeys = TRUE Then
  1440.                         iLastKey = c_iKeyDown_Down
  1441.                         m_arrPlayer(iPlayerLoop).Direction = c_iDir_Forward
  1442.                         bMoved = TRUE
  1443.                     End If
  1444.                 ElseIf _KeyDown(c_iKeyDown_Left) Then
  1445.                     If iLastKey <> c_iKeyDown_Left Or bEnableRepeatingKeys = TRUE Then
  1446.                         iLastKey = c_iKeyDown_Left
  1447.                         m_arrPlayer(iPlayerLoop).Direction = c_iDir_Left
  1448.                         bMoved = TRUE
  1449.                     End If
  1450.                 ElseIf _KeyDown(c_iKeyDown_Right) Then
  1451.                     If iLastKey <> c_iKeyDown_Right Or bEnableRepeatingKeys = TRUE Then
  1452.                         iLastKey = c_iKeyDown_Right
  1453.                         m_arrPlayer(iPlayerLoop).Direction = c_iDir_Right
  1454.                         bMoved = TRUE
  1455.                     End If
  1456.                 ElseIf _KeyDown(c_iKeyDown_PgUp) Then
  1457.                     If iLastKey <> c_iKeyDown_PgUp Or bEnableRepeatingKeys = TRUE Then
  1458.                         iLastKey = c_iKeyDown_PgUp
  1459.                         m_arrPlayer(iPlayerLoop).Direction = c_iDir_Up
  1460.                         bMoved = TRUE
  1461.                     End If
  1462.                 ElseIf _KeyDown(c_iKeyDown_PgDn) Then
  1463.                     If iLastKey <> c_iKeyDown_PgDn Or bEnableRepeatingKeys = TRUE Then
  1464.                         iLastKey = c_iKeyDown_PgDn
  1465.                         m_arrPlayer(iPlayerLoop).Direction = c_iDir_Down
  1466.                         bMoved = TRUE
  1467.                     End If
  1468.                     ' =============================================================================
  1469.                     ' END GET DIRECTIONAL KEYBOARD INPUT
  1470.                     ' =============================================================================
  1471.  
  1472.  
  1473.  
  1474.                     ' =============================================================================
  1475.                     ' BEGIN GET UNDO/REDO INPUT
  1476.                     ' =============================================================================
  1477.                 ElseIf _KeyDown(c_iKeyDown_A) Then
  1478.                     If iLastKey <> c_iKeyDown_A Then
  1479.                         iLastKey = c_iKeyDown_A
  1480.  
  1481.                         ' UNDO!
  1482.                         MapTileTempUndo.Typ = m_arrMap(m_MapTileUndo.x, m_MapTileUndo.y, m_MapTileUndo.z).Typ
  1483.                         MapTileTempUndo.Color1 = m_arrMap(m_MapTileUndo.x, m_MapTileUndo.y, m_MapTileUndo.z).Color1
  1484.                         MapTileTempUndo.Alpha1 = m_arrMap(m_MapTileUndo.x, m_MapTileUndo.y, m_MapTileUndo.z).Alpha1
  1485.  
  1486.                         m_arrMap(m_MapTileUndo.x, m_MapTileUndo.y, m_MapTileUndo.z).Typ = m_MapTileUndo.Typ
  1487.                         m_arrMap(m_MapTileUndo.x, m_MapTileUndo.y, m_MapTileUndo.z).Color1 = m_MapTileUndo.Color1
  1488.                         m_arrMap(m_MapTileUndo.x, m_MapTileUndo.y, m_MapTileUndo.z).Alpha1 = m_MapTileUndo.Alpha1
  1489.  
  1490.                         m_MapTileUndo.Typ = MapTileTempUndo.Typ
  1491.                         m_MapTileUndo.Color1 = MapTileTempUndo.Color1
  1492.                         m_MapTileUndo.Alpha1 = MapTileTempUndo.Alpha1
  1493.                     End If
  1494.                 ElseIf _KeyDown(c_iKeyDown_B) Then
  1495.                     If iLastKey <> c_iKeyDown_B Or bEnableRepeatingKeys = TRUE Then
  1496.                         iLastKey = c_iKeyDown_B
  1497.  
  1498.                         ' REDO! *** FOR NOW IT'S THE SAME AS UNDO, JUST SWAPS CURRENT WITH UNDO INFO ***
  1499.                         MapTileTempUndo.Typ = m_arrMap(m_MapTileUndo.x, m_MapTileUndo.y, m_MapTileUndo.z).Typ
  1500.                         MapTileTempUndo.Color1 = m_arrMap(m_MapTileUndo.x, m_MapTileUndo.y, m_MapTileUndo.z).Color1
  1501.                         MapTileTempUndo.Alpha1 = m_arrMap(m_MapTileUndo.x, m_MapTileUndo.y, m_MapTileUndo.z).Alpha1
  1502.  
  1503.                         m_arrMap(m_MapTileUndo.x, m_MapTileUndo.y, m_MapTileUndo.z).Typ = m_MapTileUndo.Typ
  1504.                         m_arrMap(m_MapTileUndo.x, m_MapTileUndo.y, m_MapTileUndo.z).Color1 = m_MapTileUndo.Color1
  1505.                         m_arrMap(m_MapTileUndo.x, m_MapTileUndo.y, m_MapTileUndo.z).Alpha1 = m_MapTileUndo.Alpha1
  1506.  
  1507.                         m_MapTileUndo.Typ = MapTileTempUndo.Typ
  1508.                         m_MapTileUndo.Color1 = MapTileTempUndo.Color1
  1509.                         m_MapTileUndo.Alpha1 = MapTileTempUndo.Alpha1
  1510.                     End If
  1511.                     ' =============================================================================
  1512.                     ' END GET UNDO/REDO INPUT
  1513.                     ' =============================================================================
  1514.  
  1515.  
  1516.  
  1517.  
  1518.  
  1519.  
  1520.  
  1521.                     ' =============================================================================
  1522.                     ' BEGIN GET DRAWING INPUT
  1523.                     ' =============================================================================
  1524.  
  1525.                     ' -----------------------------------------------------------------------------
  1526.                     ' 1 color-
  1527.                 ElseIf _KeyDown(c_iKeyDown_1) Then
  1528.                     If iLastKey <> c_iKeyDown_1 Or bEnableRepeatingKeys = TRUE Then
  1529.                         iLastKey = c_iKeyDown_1
  1530.  
  1531.                         iDrawColor% = iDrawColor% - 1
  1532.                         If iDrawColor% < 0 Then
  1533.                             iDrawColor% = 25
  1534.                         End If
  1535.                     End If
  1536.  
  1537.                     ' -----------------------------------------------------------------------------
  1538.                     ' 2 color+
  1539.                 ElseIf _KeyDown(c_iKeyDown_2) Then
  1540.                     If iLastKey <> c_iKeyDown_2 Or bEnableRepeatingKeys = TRUE Then
  1541.                         iLastKey = c_iKeyDown_2
  1542.  
  1543.                         iDrawColor% = iDrawColor% + 1
  1544.                         If iDrawColor% > 25 Then
  1545.                             iDrawColor% = 0
  1546.                         End If
  1547.                     End If
  1548.  
  1549.                     ' -----------------------------------------------------------------------------
  1550.                     ' 3 draw
  1551.                 ElseIf _KeyDown(c_iKeyDown_3) Then
  1552.                     If iLastKey <> c_iKeyDown_3 Or bEnableRepeatingKeys = TRUE Then
  1553.                         iLastKey = c_iKeyDown_3
  1554.  
  1555.                         ' SAVE UNDO INFO:
  1556.                         m_MapTileUndo.x = iX%
  1557.                         m_MapTileUndo.y = iY%
  1558.                         m_MapTileUndo.z = iZ%
  1559.                         m_MapTileUndo.Typ = m_arrMap(iX%, iY%, iZ%).Typ
  1560.                         m_MapTileUndo.Color1 = m_arrMap(iX%, iY%, iZ%).Color1
  1561.                         m_MapTileUndo.Alpha1 = m_arrMap(iX%, iY%, iZ%).Alpha1
  1562.  
  1563.                         ' DRAW CURRENT COLOR (OR ERASE IF COLOR=TRANSPARENT)
  1564.                         If iDrawColor% > 0 Then
  1565.                             PlotTile iX%, iY%, iZ%, c_iTile_Wall, m_arrColors(iDrawColor%)
  1566.                         Else
  1567.                             PlotTile iX%, iY%, iZ%, c_iTile_Empty, m_arrColors(iDrawColor%)
  1568.                         End If
  1569.  
  1570.                         '' ADD TO RECORDING
  1571.                         'ReDim _Preserve m_arrRecord(0 To UBound(m_arrRecord) + 1) As RecordType
  1572.                         'iIndex = UBound(m_arrRecord)
  1573.                         'm_arrRecord(iIndex).Command = "plot"
  1574.                         'm_arrRecord(iIndex).intParam1 = iX%
  1575.                         'm_arrRecord(iIndex).intParam2 = iY%
  1576.                         'm_arrRecord(iIndex).intParam3 = iZ%
  1577.                         'm_arrRecord(iIndex).intParam4 = m_arrMap(iX%, iY%, iZ%).Typ
  1578.                         'm_arrRecord(iIndex).ulngParam1 = m_arrMap(iX%, iY%, iZ%).Color1
  1579.                     End If
  1580.  
  1581.                     ' -----------------------------------------------------------------------------
  1582.                     ' 4 erase
  1583.                 ElseIf _KeyDown(c_iKeyDown_4) Then
  1584.                     If iLastKey <> c_iKeyDown_4 Or bEnableRepeatingKeys = TRUE Then
  1585.                         iLastKey = c_iKeyDown_4
  1586.  
  1587.                         ' SAVE UNDO INFO:
  1588.                         m_MapTileUndo.x = iX%
  1589.                         m_MapTileUndo.y = iY%
  1590.                         m_MapTileUndo.z = iZ%
  1591.                         m_MapTileUndo.Typ = m_arrMap(iX%, iY%, iZ%).Typ
  1592.                         m_MapTileUndo.Color1 = m_arrMap(iX%, iY%, iZ%).Color1
  1593.                         m_MapTileUndo.Alpha1 = m_arrMap(iX%, iY%, iZ%).Alpha1
  1594.  
  1595.                         ' ERASE CURRENT TILE
  1596.                         PlotTile iX%, iY%, iZ%, c_iTile_Empty, m_arrColors(iDrawColor%)
  1597.  
  1598.                         '' ADD TO RECORDING
  1599.                         'ReDim _Preserve m_arrRecord(0 To UBound(m_arrRecord) + 1) As RecordType
  1600.                         'iIndex = UBound(m_arrRecord)
  1601.                         'm_arrRecord(iIndex).Command = "plot"
  1602.                         'm_arrRecord(iIndex).intParam1 = iX%
  1603.                         'm_arrRecord(iIndex).intParam2 = iY%
  1604.                         'm_arrRecord(iIndex).intParam3 = iZ%
  1605.                         'm_arrRecord(iIndex).intParam4 = m_arrMap(iX%, iY%, iZ%).Typ
  1606.                         'm_arrRecord(iIndex).ulngParam1 = m_arrMap(iX%, iY%, iZ%).Color1
  1607.                     End If
  1608.  
  1609.                     ' -----------------------------------------------------------------------------
  1610.                     ' 5 toggle
  1611.                 ElseIf _KeyDown(c_iKeyDown_5) Then
  1612.                     If iLastKey <> c_iKeyDown_5 Or bEnableRepeatingKeys = TRUE Then
  1613.                         iLastKey = c_iKeyDown_5
  1614.  
  1615.                         ' SAVE UNDO INFO:
  1616.                         m_MapTileUndo.x = iX%
  1617.                         m_MapTileUndo.y = iY%
  1618.                         m_MapTileUndo.z = iZ%
  1619.                         m_MapTileUndo.Typ = m_arrMap(iX%, iY%, iZ%).Typ
  1620.                         m_MapTileUndo.Color1 = m_arrMap(iX%, iY%, iZ%).Color1
  1621.                         m_MapTileUndo.Alpha1 = m_arrMap(iX%, iY%, iZ%).Alpha1
  1622.  
  1623.                         ' TOGGLE CURRENT TILE:
  1624.                         If m_arrMap(iX%, iY%, iZ%).Typ = c_iTile_Empty Then
  1625.                             If iDrawColor% > 0 Then
  1626.                                 'm_arrMap(iX%, iY%, iZ%).Typ = c_iTile_Wall
  1627.                                 PlotTile iX%, iY%, iZ%, c_iTile_Wall, m_arrColors(iDrawColor%)
  1628.                             Else
  1629.                                 'm_arrMap(iX%, iY%, iZ%).Typ = c_iTile_Empty
  1630.                                 PlotTile iX%, iY%, iZ%, c_iTile_Empty, m_arrColors(iDrawColor%)
  1631.                             End If
  1632.                         Else
  1633.                             'm_arrMap(iX%, iY%, iZ%).Typ = c_iTile_Empty
  1634.                             PlotTile iX%, iY%, iZ%, c_iTile_Empty, m_arrColors(iDrawColor%)
  1635.                         End If
  1636.  
  1637.                         '' ADD TO RECORDING
  1638.                         'ReDim _Preserve m_arrRecord(0 To UBound(m_arrRecord) + 1) As RecordType
  1639.                         'iIndex = UBound(m_arrRecord)
  1640.                         'm_arrRecord(iIndex).Command = "plot"
  1641.                         'm_arrRecord(iIndex).intParam1 = iX%
  1642.                         'm_arrRecord(iIndex).intParam2 = iY%
  1643.                         'm_arrRecord(iIndex).intParam3 = iZ%
  1644.                         'm_arrRecord(iIndex).intParam4 = m_arrMap(iX%, iY%, iZ%).Typ
  1645.                         'm_arrRecord(iIndex).ulngParam1 = m_arrMap(iX%, iY%, iZ%).Color1
  1646.                     End If
  1647.  
  1648.                     ' -----------------------------------------------------------------------------
  1649.                     ' 6 eyedropper
  1650.                 ElseIf _KeyDown(c_iKeyDown_6) Then
  1651.                     If iLastKey <> c_iKeyDown_6 Or bEnableRepeatingKeys = TRUE Then
  1652.                         iLastKey = c_iKeyDown_6
  1653.  
  1654.                         iDrawColor% = GetPaletteFromColor%(m_arrMap(iX%, iY%, iZ%).Color1)
  1655.                     End If
  1656.  
  1657.                     ' -----------------------------------------------------------------------------
  1658.                     ' 7 clear all
  1659.                 ElseIf _KeyDown(c_iKeyDown_7) Then
  1660.                     If iLastKey <> c_iKeyDown_7 Or bEnableRepeatingKeys = TRUE Then
  1661.                         iLastKey = c_iKeyDown_7
  1662.  
  1663.                         ReDim m_arrRecord(-1) As RecordType
  1664.                         ClearIsometricMap
  1665.                         'For iLoopX% = m_iMapMinX To m_iMapMaxX
  1666.                         '    For iLoopY% = m_iMapMinY To m_iMapMaxY
  1667.                         '        For iLoopZ% = m_iMapMinZ To m_iMapMaxZ
  1668.                         '            m_arrMap(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iTile_Empty
  1669.                         '            m_arrMap(iLoopX%, iLoopY%, iLoopZ%).Color1 = cEmpty
  1670.                         '            m_arrMap(iLoopX%, iLoopY%, iLoopZ%).Alpha1 = 255
  1671.                         '            m_arrMap(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride = 255
  1672.                         '        Next iLoopZ%
  1673.                         '    Next iLoopY%
  1674.                         'Next iLoopX%
  1675.  
  1676.                     End If
  1677.  
  1678.                     ' -----------------------------------------------------------------------------
  1679.                     ' 8 open
  1680.                 ElseIf _KeyDown(c_iKeyDown_8) Then
  1681.                     If iLastKey <> c_iKeyDown_8 Or bEnableRepeatingKeys = TRUE Then
  1682.                         iLastKey = c_iKeyDown_8
  1683.                         _KeyClear
  1684.                         sNextErr = LoadIsometricDrawing$
  1685.                     End If
  1686.  
  1687.                     ' -----------------------------------------------------------------------------
  1688.                     ' 9 save
  1689.                 ElseIf _KeyDown(c_iKeyDown_9) Then
  1690.                     If iLastKey <> c_iKeyDown_9 Or bEnableRepeatingKeys = TRUE Then
  1691.                         iLastKey = c_iKeyDown_9
  1692.                         _KeyClear
  1693.                         sNextErr = SaveIsometricDrawing$
  1694.                     End If
  1695.                     ' =============================================================================
  1696.                     ' END GET DRAWING INPUT
  1697.                     ' =============================================================================
  1698.  
  1699.  
  1700.  
  1701.  
  1702.                     ' =============================================================================
  1703.                     ' BEGIN GET OTHER KEYBOARD INPUT
  1704.                     ' =============================================================================
  1705.                 ElseIf _KeyDown(c_iKeyDown_BracketLeft) Then
  1706.                     If iLastKey <> c_iKeyDown_BracketLeft Or bEnableRepeatingKeys = TRUE Then
  1707.                         iLastKey = c_iKeyDown_BracketLeft
  1708.                         m_arrPlayer(iPlayerLoop).IsMoving = TRUE
  1709.                     End If
  1710.                 ElseIf _KeyDown(c_iKeyDown_BracketRight) Then
  1711.                     If iLastKey <> c_iKeyDown_BracketRight Or bEnableRepeatingKeys = TRUE Then
  1712.                         iLastKey = c_iKeyDown_BracketRight
  1713.                         m_arrPlayer(iPlayerLoop).IsMoving = FALSE
  1714.                     End If
  1715.  
  1716.                 ElseIf _KeyDown(c_iKeyDown_Comma) Then
  1717.                     If iLastKey <> c_iKeyDown_Comma Or bEnableRepeatingKeys = TRUE Then
  1718.                         iLastKey = c_iKeyDown_Comma
  1719.                         ' TODO: HAVE MAP SIZE PER PLAYER
  1720.                         m_arrPlayer(iPlayerLoop).MapSize = m_arrPlayer(iPlayerLoop).MapSize - 1
  1721.                         If m_arrPlayer(iPlayerLoop).MapSize < 1 Then
  1722.                             m_arrPlayer(iPlayerLoop).MapSize = 1
  1723.                         Else
  1724.                             bMoved = TRUE
  1725.                         End If
  1726.                     End If
  1727.                 ElseIf _KeyDown(c_iKeyDown_Period) Then
  1728.                     If iLastKey <> c_iKeyDown_Period Or bEnableRepeatingKeys = TRUE Then
  1729.                         iLastKey = c_iKeyDown_Period
  1730.                         m_arrPlayer(iPlayerLoop).MapSize = m_arrPlayer(iPlayerLoop).MapSize + 1
  1731.                         If m_arrPlayer(iPlayerLoop).MapSize > m_iGridSizeMax Then
  1732.                             m_arrPlayer(iPlayerLoop).MapSize = m_iGridSizeMax
  1733.                         Else
  1734.                             bMoved = TRUE
  1735.                         End If
  1736.                     End If
  1737.  
  1738.                 ElseIf _KeyDown(c_iKeyDown_Minus) Then
  1739.                     If iLastKey <> c_iKeyDown_Minus Or bEnableRepeatingKeys = TRUE Then
  1740.                         iLastKey = c_iKeyDown_Minus
  1741.                         ' TODO: HAVE SEPARATE GRID SIZE PER PLAYER / SPLIT SCREEN?
  1742.                         m_arrPlayer(iPlayerLoop).GridSize = m_arrPlayer(iPlayerLoop).GridSize - 1
  1743.                         If m_arrPlayer(iPlayerLoop).GridSize < m_iGridSizeMin Then
  1744.                             m_arrPlayer(iPlayerLoop).GridSize = m_iGridSizeMin
  1745.                         Else
  1746.                             bMoved = TRUE
  1747.                         End If
  1748.                     End If
  1749.                 ElseIf _KeyDown(c_iKeyDown_EqualPlus) Then
  1750.                     If iLastKey <> c_iKeyDown_EqualPlus Or bEnableRepeatingKeys = TRUE Then
  1751.                         iLastKey = c_iKeyDown_EqualPlus
  1752.                         m_arrPlayer(iPlayerLoop).GridSize = m_arrPlayer(iPlayerLoop).GridSize + 1
  1753.                         If m_arrPlayer(iPlayerLoop).GridSize > m_iGridSizeMax Then
  1754.                             m_arrPlayer(iPlayerLoop).GridSize = m_iGridSizeMax
  1755.                         Else
  1756.                             bMoved = TRUE
  1757.                         End If
  1758.                     End If
  1759.  
  1760.                 ElseIf _KeyDown(c_iKeyDown_Home) Then
  1761.                     If iLastKey <> c_iKeyDown_Home Or bEnableRepeatingKeys = TRUE Then
  1762.                         iLastKey = c_iKeyDown_Home
  1763.                         ' c_iDir_Left, c_iDir_Right, c_iDir_Back, c_iDir_Forward, c_iDir_Down, c_iDir_Up
  1764.                         m_arrPlayer(iPlayerLoop).View = m_arrPlayer(iPlayerLoop).View - 1
  1765.                         If m_arrPlayer(iPlayerLoop).View < c_iDir_Min Then
  1766.                             m_arrPlayer(iPlayerLoop).View = c_iDir_Max
  1767.                         End If
  1768.                     End If
  1769.                 ElseIf _KeyDown(c_iKeyDown_End) Then
  1770.                     If iLastKey <> c_iKeyDown_End Or bEnableRepeatingKeys = TRUE Then
  1771.                         iLastKey = c_iKeyDown_End
  1772.                         ' c_iDir_Left, c_iDir_Right, c_iDir_Back, c_iDir_Forward, c_iDir_Down, c_iDir_Up
  1773.                         m_arrPlayer(iPlayerLoop).View = m_arrPlayer(iPlayerLoop).View + 1
  1774.                         If m_arrPlayer(iPlayerLoop).View > c_iDir_Max Then
  1775.                             m_arrPlayer(iPlayerLoop).View = c_iDir_Min
  1776.                         End If
  1777.                     End If
  1778.  
  1779.                 ElseIf _KeyDown(c_iKeyDown_Ins) Then
  1780.                     ' TODO: DO WE NEED TO HANDLE REPEATING KEYS FOR MULTIPLAYER?
  1781.                     If iLastKey <> c_iKeyDown_Ins Or bEnableRepeatingKeys = TRUE Then
  1782.                         iLastKey = c_iKeyDown_Ins
  1783.                         bEnableRepeatingKeys = TRUE
  1784.                     End If
  1785.  
  1786.                 ElseIf _KeyDown(c_iKeyDown_Del) Then
  1787.                     ' TODO: DO WE NEED TO HANDLE REPEATING KEYS FOR MULTIPLAYER?
  1788.                     If iLastKey <> c_iKeyDown_Del Or bEnableRepeatingKeys = TRUE Then
  1789.                         iLastKey = c_iKeyDown_Del
  1790.                         bEnableRepeatingKeys = FALSE
  1791.                     End If
  1792.  
  1793.                 ElseIf _KeyDown(c_iKeyDown_Esc) Then
  1794.                     Exit Do
  1795.                 Else
  1796.                     iLastKey = -1
  1797.                 End If
  1798.                 ' =============================================================================
  1799.                 ' END GET OTHER KEYBOARD INPUT
  1800.                 ' =============================================================================
  1801.  
  1802.  
  1803.  
  1804.                 ' =============================================================================
  1805.                 ' BEGIN MOVE PLAYER BASED ON DIRECTION
  1806.                 ' =============================================================================
  1807.                 If m_arrPlayer(iPlayerLoop).IsMoving = TRUE Or bMoved = TRUE Then
  1808.                     bMoved = FALSE
  1809.  
  1810.                     Select Case m_arrPlayer(iPlayerLoop).Direction
  1811.                         Case c_iDir_Down:
  1812.                             iNewX% = iX%
  1813.                             iNewY% = iY%
  1814.                             iNewZ% = iZ% - 1
  1815.                             If iNewZ% < m_iMapMinZ Then
  1816.                                 iNewZ% = m_iMapMaxZ
  1817.                             End If
  1818.                             If (m_arrMap(iNewX%, iNewY%, iNewZ%).Typ <> c_iTile_Empty) And (bIgnoreTerrain = FALSE) Then
  1819.                                 m_arrPlayer(iPlayerLoop).Direction = c_iDir_Up
  1820.                                 iNewZ% = iZ%
  1821.                             End If
  1822.  
  1823.                         Case c_iDir_Up:
  1824.                             iNewX% = iX%
  1825.                             iNewY% = iY%
  1826.                             iNewZ% = iZ% + 1
  1827.                             If iNewZ% > m_iMapMaxZ Then
  1828.                                 iNewZ% = m_iMapMinZ
  1829.                             End If
  1830.                             If (m_arrMap(iNewX%, iNewY%, iNewZ%).Typ <> c_iTile_Empty) And (bIgnoreTerrain = FALSE) Then
  1831.                                 m_arrPlayer(iPlayerLoop).Direction = c_iDir_Down
  1832.                                 iNewZ% = iZ%
  1833.                             End If
  1834.  
  1835.                         Case c_iDir_Left:
  1836.                             iNewX% = iX% - 1
  1837.                             iNewY% = iY%
  1838.                             iNewZ% = iZ%
  1839.                             If iNewX% < m_iMapMinX Then
  1840.                                 iNewX% = m_iMapMaxX
  1841.                             End If
  1842.                             If (m_arrMap(iNewX%, iNewY%, iNewZ%).Typ <> c_iTile_Empty) And (bIgnoreTerrain = FALSE) Then
  1843.                                 m_arrPlayer(iPlayerLoop).Direction = c_iDir_Right
  1844.                                 iNewX% = iX%
  1845.                             End If
  1846.  
  1847.                         Case c_iDir_Right:
  1848.                             iNewX% = iX% + 1
  1849.                             iNewY% = iY%
  1850.                             iNewZ% = iZ%
  1851.                             If iNewX% > m_iMapMaxX Then
  1852.                                 iNewX% = m_iMapMinX
  1853.                             End If
  1854.                             If (m_arrMap(iNewX%, iNewY%, iNewZ%).Typ <> c_iTile_Empty) And (bIgnoreTerrain = FALSE) Then
  1855.                                 m_arrPlayer(iPlayerLoop).Direction = c_iDir_Left
  1856.                                 iNewX% = iX%
  1857.                             End If
  1858.  
  1859.                         Case c_iDir_Back:
  1860.                             iNewX% = iX%
  1861.                             iNewY% = iY% - 1
  1862.                             iNewZ% = iZ%
  1863.                             If iNewY% < m_iMapMinY Then
  1864.                                 iNewY% = m_iMapMaxY
  1865.                             End If
  1866.                             If (m_arrMap(iNewX%, iNewY%, iNewZ%).Typ <> c_iTile_Empty) And (bIgnoreTerrain = FALSE) Then
  1867.                                 m_arrPlayer(iPlayerLoop).Direction = c_iDir_Forward
  1868.                                 iNewY% = iY%
  1869.                             End If
  1870.  
  1871.                         Case c_iDir_Forward:
  1872.                             iNewX% = iX%
  1873.                             iNewY% = iY% + 1
  1874.                             iNewZ% = iZ%
  1875.                             If iNewY% > m_iMapMaxY Then
  1876.                                 iNewY% = m_iMapMinY
  1877.                             End If
  1878.                             If (m_arrMap(iNewX%, iNewY%, iNewZ%).Typ <> c_iTile_Empty) And (bIgnoreTerrain = FALSE) Then
  1879.                                 m_arrPlayer(iPlayerLoop).Direction = c_iDir_Back
  1880.                                 iNewY% = iY%
  1881.                             End If
  1882.  
  1883.                         Case Else:
  1884.                             ' (DO NOTHING)
  1885.                             'iNewX% = iX%
  1886.                             'iNewY% = iY%
  1887.                             'iNewZ% = iZ%
  1888.                     End Select
  1889.  
  1890.                     ' SAVE NEW POSITION
  1891.                     iX% = iNewX%
  1892.                     iY% = iNewY%
  1893.                     iZ% = iNewZ%
  1894.  
  1895.                     ' FOR MULTIPLAYER WE WOULD USE:
  1896.                     m_arrPlayer(iPlayerLoop).x = iNewX%
  1897.                     m_arrPlayer(iPlayerLoop).y = iNewY%
  1898.                     m_arrPlayer(iPlayerLoop).z = iNewZ%
  1899.  
  1900.                 End If
  1901.                 ' =============================================================================
  1902.                 ' END MOVE PLAYER BASED ON DIRECTION
  1903.                 ' =============================================================================
  1904.  
  1905.  
  1906.                 ' =============================================================================
  1907.                 ' BEGIN CYCLE COLOR
  1908.                 ' =============================================================================
  1909.                 If m_arrPlayer(iPlayerLoop).ColorScheme1 > 0 Then
  1910.                     m_arrPlayer(iPlayerLoop).ColorSchemeCount1 = m_arrPlayer(iPlayerLoop).ColorSchemeCount1 + 1
  1911.                     If m_arrPlayer(iPlayerLoop).ColorSchemeCount1 > m_arrPlayer(iPlayerLoop).ColorSchemeSpeed1 Then
  1912.                         m_arrPlayer(iPlayerLoop).ColorSchemeCount1 = 0
  1913.                         DoCycleColor m_arrPlayer(iPlayerLoop).ColorScheme1, m_arrPlayer(iPlayerLoop).Color1
  1914.                     End If
  1915.                 End If
  1916.                 ' =============================================================================
  1917.                 ' END CYCLE COLOR
  1918.                 ' =============================================================================
  1919.  
  1920.  
  1921.             Next iPlayerLoop
  1922.  
  1923.             ' ****************************************************************************************************************************************************************
  1924.             ' END PLAYER LOOP
  1925.             ' ****************************************************************************************************************************************************************
  1926.  
  1927.             _Limit 30
  1928.             _Display
  1929.  
  1930.         Loop
  1931.     End If
  1932.  
  1933.     CleanupAndExit:
  1934.     ' FINISH UP AND EXIT
  1935.     _KeyClear
  1936.     Screen 0
  1937.     IsometricDraw1$ = sResult
  1938. End Function ' IsometricDraw1$
  1939.  
  1940. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1941. ' BEGIN FILE FUNCTIONS
  1942. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1943.  
  1944. ' /////////////////////////////////////////////////////////////////////////////
  1945. ' PLOT TILE TO MAP AND SAVE TO RECORDING
  1946.  
  1947. 'PlotTile iX, iY, iZ, iTile, ulngColor1
  1948. Sub PlotTile (iX As Integer, iY As Integer, iZ As Integer, iTile As Integer, ulngColor1 As _Unsigned Long)
  1949.     m_arrMap(iX, iY, iZ).Typ = iTile
  1950.     m_arrMap(iX, iY, iZ).Color1 = ulngColor1
  1951.     m_arrMap(iX, iY, iZ).Alpha1 = 255
  1952.     m_arrMap(iX, iY, iZ).AlphaOverride = 255
  1953.     LogPlotTile iX, iY, iZ, iTile, ulngColor1
  1954. End Sub ' PlotTile
  1955.  
  1956. ' /////////////////////////////////////////////////////////////////////////////
  1957. ' SAVE PLOT COMMAND TO RECORDING
  1958.  
  1959. 'LogPlotTile iX, iY, iZ, iTile, ulngColor1
  1960. Sub LogPlotTile (iX As Integer, iY As Integer, iZ As Integer, iTile As Integer, ulngColor1 As _Unsigned Long)
  1961.     Dim iIndex As Long
  1962.     ReDim _Preserve m_arrRecord(0 To UBound(m_arrRecord) + 1) As RecordType
  1963.     iIndex = UBound(m_arrRecord)
  1964.     m_arrRecord(iIndex).Command = "plot"
  1965.     m_arrRecord(iIndex).intParam1 = iX
  1966.     m_arrRecord(iIndex).intParam2 = iY
  1967.     m_arrRecord(iIndex).intParam3 = iZ
  1968.     m_arrRecord(iIndex).intParam4 = iTile
  1969.     m_arrRecord(iIndex).ulngParam1 = ulngColor1
  1970. End Sub ' LogPlotTile
  1971.  
  1972. ' /////////////////////////////////////////////////////////////////////////////
  1973. '   - save screens to file (stored as editable text)
  1974. '     + FORMAT: [tile=t][color@x,y,z][color@x,y,z][color@x,y,z]...
  1975.  
  1976. Function SaveIsometricDrawing$
  1977.     Dim RoutineName As String:: RoutineName = "SaveIsometricDrawing$"
  1978.     Dim sError As String: sError = ""
  1979.     Dim sFile As String
  1980.     Dim in$
  1981.     Dim iX As Integer
  1982.     Dim iY As Integer
  1983.     Dim iZ As Integer
  1984.     Dim iTile As Integer
  1985.     Dim ulngColor1 As _Unsigned Long
  1986.     Dim iIndex As Long
  1987.     Dim sLine As String
  1988.     Dim iCount As Long: iCount = 0
  1989.     Dim iError As Long: iError = 0
  1990.     '_echo "--------------------------------------------------------------------------------"
  1991.     '_echo "Started " + RoutineName
  1992.     '_echo "--------------------------------------------------------------------------------"
  1993.  
  1994.     _KeyClear
  1995.  
  1996.     ' Get file name
  1997.     Cls
  1998.     If Len(m_SaveFileName$) = 0 Then
  1999.         m_SaveFileName$ = Left$(m_ProgramName$, _InStrRev(m_ProgramName$, ".")) + "txt"
  2000.     End If
  2001.     Print "SAVE DRAWING:"
  2002.     Print "Default file name is " + Chr$(34) + m_SaveFileName$ + Chr$(34) + "."
  2003.     Input "Type save file name, or blank for default: ", in$
  2004.     in$ = _Trim$(in$)
  2005.     If Len(in$) > 0 Then
  2006.         m_SaveFileName$ = in$
  2007.     End If
  2008.     sFile = m_ProgramPath$ + m_SaveFileName$
  2009.  
  2010.     '_echo "sFile=" + CHR$(34) + sFile + CHR$(34)
  2011.  
  2012.     ' Save recording to file
  2013.     Open sFile For Output As #1
  2014.  
  2015.     '[tile=t][color@x,y,z][color@x,y,z][color@x,y,z]
  2016.     For iIndex = 0 To UBound(m_arrRecord)
  2017.         If m_arrRecord(iIndex).Command = "plot" Then
  2018.             sLine = ""
  2019.             sLine = sLine + "plot,"
  2020.             sLine = sLine + "tile=" + _Trim$(Str$(m_arrRecord(iIndex).intParam4)) + ","
  2021.             sLine = sLine + "color=" + _Trim$(Str$(m_arrRecord(iIndex).ulngParam1)) + ","
  2022.             sLine = sLine + "x=" + _Trim$(Str$(m_arrRecord(iIndex).intParam1)) + ","
  2023.             sLine = sLine + "y=" + _Trim$(Str$(m_arrRecord(iIndex).intParam2)) + ","
  2024.             sLine = sLine + "z=" + _Trim$(Str$(m_arrRecord(iIndex).intParam3))
  2025.             Print #1, sLine
  2026.             iCount = iCount + 1
  2027.         Else
  2028.             '_echo "SKIPPED m_arrRecord(" + _Trim$(Str$(iIndex)) + ") INVALID .Command=" + CHR$(34) + m_arrRecord(iIndex).Command + CHR$(34)
  2029.             iError = iError + 1
  2030.         End If
  2031.     Next iIndex
  2032.  
  2033.     Close #1
  2034.  
  2035.     Print "Wrote   " + _Trim$(Str$(iCount)) + " lines."
  2036.     Print "Skipped " + _Trim$(Str$(iError)) + " lines."
  2037.     Print
  2038.     Input "PRESS <ENTER> TO CONTINUE", in$
  2039.  
  2040.     SaveIsometricDrawing$ = sError
  2041. End Function ' SaveIsometricDrawing$
  2042.  
  2043. ' /////////////////////////////////////////////////////////////////////////////
  2044. '   - load screens into array m_arrRecord
  2045. '     + PARSER:
  2046. '       1. replace all ][ with [
  2047. '       2. split by "[" into simple 1D array
  2048. '       3. each element is either "tile=t" or "plot=color@x,y,z"
  2049. '       4. parse data into array to playback recording
  2050. '          [n][0] = command$ = "draw"
  2051. '          [n][1] = intParam1 = x
  2052. '          [n][2] = intValue2 = y
  2053. '          [n][3] = intValue3 = z
  2054. '          [n][4] = intParam4 = tile #
  2055. '          [n][5] = intValue5 = alpha1
  2056. '          [n][6] = ulngValue1 = color1
  2057.  
  2058. Function LoadIsometricDrawing$
  2059.     Dim RoutineName As String:: RoutineName = "LoadIsometricDrawing$"
  2060.     Dim sError As String: sError = ""
  2061.     Dim sFile As String
  2062.     Dim iIndex As Long
  2063.     Dim iLine As Long
  2064.     Dim iPair As Long
  2065.     Dim sText As String
  2066.     Dim sLine As String
  2067.     Dim sPair As String
  2068.     Dim iTotal As Long: iTotal = 0
  2069.     Dim iRead As Long: iRead = 0
  2070.     Dim iKnown As Long: iKnown = 0
  2071.     Dim iSkipped As Long: iSkipped = 0
  2072.     Dim iErrors As Long: iErrors = 0
  2073.     Dim iValid As Long: iValid = 0
  2074.     Dim iUnknown As Long: iUnknown = 0
  2075.     ReDim arrLines(-1) As String
  2076.     ReDim m_arrRecord(-1) As RecordType
  2077.     ReDim arrNextLine(-1) As String
  2078.     ReDim arrNameValue(-1) As String
  2079.     Dim sName As String
  2080.     Dim sValue As String
  2081.     Dim iX As Integer
  2082.     Dim iY As Integer
  2083.     Dim iZ As Integer
  2084.     Dim iTile As Integer
  2085.     Dim ulngColor1 As _Unsigned Long
  2086.     Dim sNextErr As String
  2087.     Dim sCommand As String
  2088.     'Dim sDebugLine As String
  2089.     Dim iPercent As Long
  2090.     Dim iStatusEvery As Long
  2091.     Dim iStatusCount As Long
  2092.  
  2093.     '_echo "--------------------------------------------------------------------------------"
  2094.     '_echo "Started " + RoutineName
  2095.     '_echo "--------------------------------------------------------------------------------"
  2096.  
  2097.     _KeyClear
  2098.  
  2099.     ' Get file name
  2100.     If Len(sError) = 0 Then
  2101.         Cls
  2102.         If Len(m_SaveFileName$) = 0 Then
  2103.             m_SaveFileName$ = Left$(m_ProgramName$, _InStrRev(m_ProgramName$, ".")) + "txt"
  2104.         End If
  2105.         Print "LOAD DRAWING:"
  2106.         Print "Default file name is " + Chr$(34) + m_SaveFileName$ + Chr$(34) + "."
  2107.         Input "Type name of file to open, or blank for default: ", in$
  2108.         in$ = _Trim$(in$)
  2109.         If Len(in$) > 0 Then
  2110.             m_SaveFileName$ = in$
  2111.         End If
  2112.         sFile = m_ProgramPath$ + m_SaveFileName$
  2113.     End If
  2114.  
  2115.     ' Make sure file exists
  2116.     If Len(sError) = 0 Then
  2117.         If _FileExists(sFile) = FALSE Then
  2118.             sError = "File not found: " + Chr$(34) + sFile + Chr$(34)
  2119.         Else
  2120.             '_echo "Found file: " + chr$(34) + sFile + chr$(34)
  2121.         End If
  2122.     End If
  2123.  
  2124.     ' Load recording from file
  2125.     If Len(sError) = 0 Then
  2126.         ClearIsometricMap
  2127.         ReDim m_arrRecord(-1) As RecordType
  2128.  
  2129.         '_echo "OPEN sFile FOR BINARY AS #1"
  2130.         Open sFile For Binary As #1
  2131.         sText = Space$(LOF(1))
  2132.         Get #1, , sText
  2133.         Close #1
  2134.         iTotal = Len(sText) - Len(Replace$(sText, Chr$(13), ""))
  2135.         sText = ""
  2136.  
  2137.         ' SPLIT IS TOO SLOW!
  2138.         '_echo "split sText, CHR$(13), arrLines()"
  2139.         'split sText, CHR$(13), arrLines()
  2140.         'iTotal = ubound(arrLines)-1
  2141.  
  2142.         ' PARSE LINES: plot,tile=2,color=4294901760,x=10,y=10,z=10
  2143.         iStatusCount = 0
  2144.         iStatusEvery = iTotal / 100
  2145.  
  2146.         'Print "iTotal      =" + _Trim$(Str$(iTotal))
  2147.         'Print "iStatusEvery=" + _Trim$(Str$(iStatusEvery))
  2148.         'Input "PRESS <ENTER> TO CONTINUE",in$
  2149.  
  2150.         'FOR iLine = lbound(arrLines) TO ubound(arrLines)-1
  2151.         'sLine = arrLines(iLine)
  2152.         Open sFile For Input As #1
  2153.         While Not EOF(1)
  2154.             'INPUT #1, sLine
  2155.             Line Input #1, sLine ' read entire text file line
  2156.  
  2157.             iRead = iRead + 1
  2158.             '_echo "Parsing line " + _Trim$(Str$(iRead))
  2159.  
  2160.             ' SHOW STATUS
  2161.             ' TODO: FIX <- DOESN'T SEEM TO DISPLAY UNTIL THE END, ALL AT ONCE
  2162.             iStatusCount = iStatusCount + 1
  2163.             If iStatusCount > iStatusEvery Then
  2164.                 iStatusCount = 0
  2165.                 iPercent = 100 * (iRead / iTotal)
  2166.                 Print _Trim$(Str$(iPercent)) + "%"
  2167.                 '_echo _Trim$(Str$(iPercent)) + "%"
  2168.             End If
  2169.  
  2170.             'sDebugLine = sLine
  2171.             'sDebugLine = Replace$(sDebugLine, CHR$(9), "\t")
  2172.             'sDebugLine = Replace$(sDebugLine, CHR$(13), "\n")
  2173.             'sDebugLine = Replace$(sDebugLine, CHR$(10), "\r")
  2174.             '_echo "    Raw    =" + chr$(34) + sDebugLine + chr$(34)
  2175.             ''_echo "    Raw    =" + chr$(34) + arrLines(iLine) + chr$(34)
  2176.  
  2177.             sLine = Replace$(sLine, " ", "") ' Remove spaces
  2178.             sLine = Replace$(sLine, Chr$(9), "") ' Remove tabs
  2179.             sLine = Replace$(sLine, Chr$(10), "") ' Remove line breaks
  2180.             sLine = Replace$(sLine, Chr$(13), "") ' Remove carriage returns
  2181.             '_echo "    Trimmed=" + chr$(34) + sLine + chr$(34)
  2182.  
  2183.             If Len(sLine) > 0 Then
  2184.                 split sLine, ",", arrNextLine()
  2185.                 '_echo "    lbound =" + _Trim$(Str$(lbound(arrNextLine))) '+ CHR$(10)
  2186.                 '_echo "    ubound =" + _Trim$(Str$(ubound(arrNextLine))) '+ CHR$(10)
  2187.  
  2188.                 sCommand = arrNextLine(LBound(arrNextLine))
  2189.                 sCommand = LCase$(sCommand)
  2190.                 '_echo "    Command=" + chr$(34) + sCommand + chr$(34)
  2191.  
  2192.                 If sCommand = "plot" Then
  2193.                     iKnown = iKnown + 1
  2194.  
  2195.                     For iPair = LBound(arrNextLine) + 1 To UBound(arrNextLine)
  2196.                         sPair = arrNextLine(iPair)
  2197.                         If InStr(1, sPair, "=") > 0 Then
  2198.                             split sPair, "=", arrNameValue()
  2199.                             sName = LCase$(arrNameValue(LBound(arrNameValue)))
  2200.                             If UBound(arrNameValue) > LBound(arrNameValue) Then
  2201.                                 sValue = arrNameValue(LBound(arrNameValue) + 1)
  2202.                             Else
  2203.                                 sValue = ""
  2204.                             End If
  2205.                         Else
  2206.                             sName = ""
  2207.                         End If
  2208.                         sNextErr = ""
  2209.                         Select Case sName
  2210.                             Case "tile":
  2211.                                 If IsNum%(sValue) Then
  2212.                                     iTile = Val(sValue)
  2213.                                 Else
  2214.                                     sNextErr = "Invalid value: " + sName + " = " + Chr$(34) + sValue + Chr$(34)
  2215.                                 End If
  2216.                             Case "color":
  2217.                                 If IsNum%(sValue) Then
  2218.                                     ulngColor1 = Val(sValue)
  2219.                                 Else
  2220.                                     sNextErr = "Invalid value: " + sName + " = " + Chr$(34) + sValue + Chr$(34)
  2221.                                 End If
  2222.                             Case "x":
  2223.                                 If IsNum%(sValue) Then
  2224.                                     iX = Val(sValue)
  2225.                                 Else
  2226.                                     sNextErr = "Invalid value: " + sName + " = " + Chr$(34) + sValue + Chr$(34)
  2227.                                 End If
  2228.                             Case "y":
  2229.                                 If IsNum%(sValue) Then
  2230.                                     iY = Val(sValue)
  2231.                                 Else
  2232.                                     sNextErr = "Invalid value: " + sName + " = " + Chr$(34) + sValue + Chr$(34)
  2233.                                 End If
  2234.                             Case "z":
  2235.                                 If IsNum%(sValue) Then
  2236.                                     iZ = Val(sValue)
  2237.                                 Else
  2238.                                     sNextErr = "Invalid value: " + sName + " = " + Chr$(34) + sValue + Chr$(34)
  2239.                                 End If
  2240.                             Case Else:
  2241.                                 sNextErr = "Unknown parameter: " + Chr$(34) + sName + Chr$(34) + "," + Chr$(34) + sValue + Chr$(34)
  2242.                         End Select
  2243.                     Next iPair
  2244.                     If Len(sNextErr) = 0 Then
  2245.                         iValid = iValid + 1
  2246.  
  2247.                         '_echo "READ VALUES SUCCESSFULLY:" + CHR$(13)
  2248.                         '_echo "iTile     =" + _Trim$(Str$(iTile)) + CHR$(13)
  2249.                         '_echo "ulngColor1=" + _Trim$(Str$(ulngColor1)) + CHR$(13)
  2250.                         '_echo "iX        =" + _Trim$(Str$(iX)) + CHR$(13)
  2251.                         '_echo "iY        =" + _Trim$(Str$(iY)) + CHR$(13)
  2252.                         '_echo "iZ        =" + _Trim$(Str$(iZ)) + CHR$(13)
  2253.                         ''EXIT FOR
  2254.  
  2255.                         PlotTile iX, iY, iZ, iTile, ulngColor1
  2256.                     Else
  2257.                         iErrors = iErrors + 1
  2258.  
  2259.                         Print "Line " + _Trim$(Str$(iRead)) + "=" + Chr$(34) + sLine + Chr$(34) + Chr$(10)
  2260.                         Print "    ERROR: " + sNextErr
  2261.  
  2262.                         ''_echo "Line " + _Trim$(Str$(iRead)) + "=" + CHR$(34) + sLine + CHR$(34) + CHR$(10)
  2263.                         '_echo "    ERROR: " + sNextErr
  2264.                         ''EXIT FOR
  2265.                     End If
  2266.                 Else
  2267.                     ''_echo "Line " + _Trim$(Str$(iRead)) + "=" + CHR$(34) + sLine + CHR$(34) + CHR$(10)
  2268.                     '_echo "    command not recognized: skipped"
  2269.                     iUnknown = iUnknown + 1
  2270.                 End If
  2271.  
  2272.             Else
  2273.                 ''_echo "Line " + _Trim$(Str$(iRead)) + "=" + CHR$(34) + sLine + CHR$(34) + CHR$(10)
  2274.                 '_echo "    Line is blank: skipped"
  2275.                 iSkipped = iSkipped + 1
  2276.             End If ' LEN(sLine) > 0
  2277.  
  2278.         Wend
  2279.         Close #1
  2280.         'NEXT iLine
  2281.     End If
  2282.  
  2283.     Print
  2284.     Print "Total lines read: " + _Trim$(Str$(iRead))
  2285.     Print "Known commands  : " + _Trim$(Str$(iKnown))
  2286.     Print "       -> Good  : " + _Trim$(Str$(iValid))
  2287.     Print "       ->  Bad  : " + _Trim$(Str$(iErrors))
  2288.     Print "Not recognized  : " + _Trim$(Str$(iUnknown))
  2289.     Print "Skipped blank   : " + _Trim$(Str$(iSkipped))
  2290.     Print
  2291.     Input "PRESS <ENTER> TO CONTINUE", in$
  2292.  
  2293.     LoadIsometricDrawing$ = sError
  2294. End Function ' LoadIsometricDrawing$
  2295.  
  2296. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2297. ' END FILE FUNCTIONS
  2298. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2299.  
  2300. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2301. ' BEGIN GRAPHICS FUNCTIONS
  2302. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2303.  
  2304. ' =============================================================================
  2305. ' LET'S GET THE COORDINATES STRAIGHT!
  2306. ' Coordinates are m_arrMap(x,y,z)
  2307. '           ________________
  2308. '          /|e            /|e
  2309. '         / |            / |
  2310. '        /  |           /  |z-axis
  2311. '       /   |          /   |
  2312. '      /    /---------/----/
  2313. '     /    / a       /   b/
  2314. '    /    /         /    /
  2315. '   |--------------|    /
  2316. '   |f  /         g|   / y-axis
  2317. '   |  /           |  /
  2318. '   | /            | /
  2319. '   |/c           d|/
  2320. '   ----------------
  2321. '      x-axis
  2322. '
  2323. ' POINT    ( X, Y, Z)
  2324. ' a        ( 0, 0, 0)
  2325. ' b        (32, 0, 0)
  2326. ' c        ( 0,32, 0)
  2327. ' d        (32,32, 0)
  2328. ' e        ( 0, 0,32)
  2329. ' f        ( 0,32,32)
  2330. ' g        (32,32,32)
  2331. ' =============================================================================
  2332.  
  2333. ' /////////////////////////////////////////////////////////////////////////////
  2334. ' INITIALIZE MAP TO EMPTY
  2335.  
  2336. ' Requires shared global variable:
  2337. ' m_arrMap(m_iMapMinX To m_iMapMaxX, m_iMapMinY To m_iMapMaxY, m_iMapMinZ To m_iMapMaxZ) As MapTileType
  2338. Sub ClearIsometricMap
  2339.     Dim RoutineName As String: RoutineName = "ClearIsometricMap"
  2340.     Dim iLoopX%
  2341.     Dim iLoopY%
  2342.     Dim iLoopZ%
  2343.  
  2344.     For iLoopZ% = m_iMapMinZ To m_iMapMaxZ
  2345.         For iLoopX% = m_iMapMinX To m_iMapMaxX
  2346.             For iLoopY% = m_iMapMinY To m_iMapMaxY
  2347.                 m_arrMap(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iTile_Empty
  2348.                 m_arrMap(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride = 255
  2349.             Next iLoopY%
  2350.         Next iLoopX%
  2351.     Next iLoopZ%
  2352. End Sub ' ClearIsometricMap
  2353.  
  2354. ' /////////////////////////////////////////////////////////////////////////////
  2355. ' INITIALIZE RENDERING MAP #1 TO EMPTY
  2356.  
  2357. ' Requires shared global variable:
  2358. ' m_arrRender1(m_iMapMinX To m_iMapMaxX, m_iMapMinY To m_iMapMaxY, m_iMapMinZ To m_iMapMaxZ) As MapTileType
  2359.  
  2360. Sub ClearRenderMap1
  2361.     Dim RoutineName As String: RoutineName = "ClearRenderMap1"
  2362.     Dim iLoopX%
  2363.     Dim iLoopY%
  2364.     Dim iLoopZ%
  2365.  
  2366.     For iLoopZ% = m_iMapMinZ To m_iMapMaxZ
  2367.         For iLoopX% = m_iMapMinX To m_iMapMaxX
  2368.             For iLoopY% = m_iMapMinY To m_iMapMaxY
  2369.                 m_arrRender1(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iTile_Empty
  2370.                 m_arrRender1(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride = 255
  2371.             Next iLoopY%
  2372.         Next iLoopX%
  2373.     Next iLoopZ%
  2374. End Sub ' ClearRenderMap1
  2375.  
  2376. ' /////////////////////////////////////////////////////////////////////////////
  2377. ' INITIALIZE RENDERING MAP #2 TO EMPTY
  2378.  
  2379. ' Requires shared global variable:
  2380. ' m_arrRender2(m_iMapMinX To m_iMapMaxX, m_iMapMinY To m_iMapMaxY, m_iMapMinZ To m_iMapMaxZ) As MapTileType
  2381.  
  2382. Sub ClearRenderMap2
  2383.     Dim RoutineName As String: RoutineName = "ClearRenderMap2"
  2384.     Dim iLoopX%
  2385.     Dim iLoopY%
  2386.     Dim iLoopZ%
  2387.  
  2388.     For iLoopZ% = m_iMapMinZ To m_iMapMaxZ
  2389.         For iLoopX% = m_iMapMinX To m_iMapMaxX
  2390.             For iLoopY% = m_iMapMinY To m_iMapMaxY
  2391.                 m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iTile_Empty
  2392.                 m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride = 255
  2393.             Next iLoopY%
  2394.         Next iLoopX%
  2395.     Next iLoopZ%
  2396. End Sub ' ClearRenderMap2
  2397.  
  2398. ' /////////////////////////////////////////////////////////////////////////////
  2399. ' Determine which squares are visible in isometric map
  2400.  
  2401. ' Original operates directly on the main map array m_arrMap
  2402. ' and not the copy (m_arrRender2) used to rotate the perspective.
  2403.  
  2404. ' Requires shared global variable (3D array of map):
  2405. ' m_arrMap(x,y,z) = 3D array map of world
  2406. ' m_arrMap(m_iMapMinX To m_iMapMaxX, m_iMapMinY To m_iMapMaxY, m_iMapMinZ To m_iMapMaxZ) As MapTileType
  2407.  
  2408. ' RECEIVES:
  2409. ' iX% = player's X positon
  2410. ' iY% = player's Y position
  2411. ' iZ% = player's Z position
  2412.  
  2413. ' Direction is assumed to be c_iDir_Forward.
  2414.  
  2415. ' If iX% < 0 then we just render everything with its normal alpha value.
  2416.  
  2417. Sub ComputeVisible (iX%, iY%, iZ%, iGridSize)
  2418.     Dim RoutineName As String: RoutineName = "ComputeVisible"
  2419.     Dim iLoopX%
  2420.     Dim iLoopY%
  2421.     Dim iLoopZ%
  2422.  
  2423.     Dim iPX1%
  2424.     Dim iPY1%
  2425.     Dim iPZ1%
  2426.     Dim iPlayer2Dx As Integer
  2427.     Dim iPlayer2Dy As Integer
  2428.     Dim iTile2Dx As Integer
  2429.     Dim iTile2Dy As Integer
  2430.  
  2431.     If iX% > -1 Then
  2432.         ' CALCULATE PLAYER'S 2-D POSITION
  2433.         iPX1% = iX% * iGridSize + cGridOffsetX
  2434.         iPY1% = iY% * iGridSize + cGridOffsetY
  2435.         iPZ1% = iZ% * iGridSize + cGridOffsetZ
  2436.         iPlayer2Dx = CX2I(iPX1%, iPY1%) + cScreenOffsetX
  2437.         iPlayer2Dy = (CY2I(iPX1%, iPY1%) + cScreenOffsetY) - iPZ1%
  2438.         'fquad TempX1, TempY1 - z, TempX2, TempY2 - z, TempX3, TempY3 - z, TempX4, TempY4 - z, _RGB32(r, g, b, alpha&)
  2439.  
  2440.         ' LOOK AT EACH TILE
  2441.         For iLoopX% = m_iMapMinX To m_iMapMaxX
  2442.             For iLoopY% = m_iMapMinY To m_iMapMaxY
  2443.                 For iLoopZ% = m_iMapMinZ To m_iMapMaxZ
  2444.  
  2445.                     ' *****************************************************************************
  2446.                     ' IF SPACE HAS A TILE
  2447.                     ' AND ITS 2D (X,Y) IS > PLAYER'S 2D (X,Y)
  2448.                     ' THEN MAKE THE TILE TRANSPARENT
  2449.                     ' *****************************************************************************
  2450.                     ' TODO: COMPARE AGAINST ALL TYPES OF TILES NOT JUST WALL/FLOOR
  2451.                     If m_arrMap(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iTile_Wall Or m_arrMap(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iTile_Floor Then
  2452.                         ' CALCULATE TILE'S 2-D POSITION
  2453.                         iPX1% = iLoopX% * iGridSize + cGridOffsetX
  2454.                         iPY1% = iLoopY% * iGridSize + cGridOffsetY
  2455.                         iPZ1% = iLoopZ% * iGridSize + cGridOffsetZ
  2456.                         iTile2Dx = CX2I(iPX1%, iPY1%) + cScreenOffsetX
  2457.                         iTile2Dy = (CY2I(iPX1%, iPY1%) + cScreenOffsetY) - iPZ1%
  2458.                         'fquad TempX1, TempY1 - z, TempX2, TempY2 - z, TempX3, TempY3 - z, TempX4, TempY4 - z, _RGB32(r, g, b, alpha&)
  2459.  
  2460.                         'If iLoopZ% >= iZ% Then
  2461.                         'If iLoopX% >= iX% Then
  2462.  
  2463.                         ' FOR TILES FORWARD OF PLAYER
  2464.                         If iLoopY% > iY% Then
  2465.  
  2466.                             ' IF PLAYER'S 2D Y POSITION IS WITHIN RANGE OF TILE'S 2D Y POSITION
  2467.                             If (iPlayer2Dy >= (iTile2Dy - iGridSize)) And (iPlayer2Dy <= (iTile2Dy + iGridSize)) Then
  2468.  
  2469.                                 ' AND IF PLAYER'S 2D X POSITION IS WITHIN RANGE OF TILE'S 2D X POSITION
  2470.                                 If (iPlayer2Dx >= (iTile2Dx - iGridSize)) And (iPlayer2Dx <= (iTile2Dx + iGridSize)) Then
  2471.                                     ' RENDER THE TILE TRANSPARENT SO WE CAN SEE THE PLAYER
  2472.                                     ' TODO: CHANGE AlphaOverride TO BE RELATIVE TO ORIGINAL Alpha VALUE
  2473.                                     m_arrMap(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride = 86
  2474.                                 Else
  2475.                                     ' LEAVE THE TILE OPAQUE
  2476.                                     ' TODO: CHANGE 255 TO ORIGINAL Alpha VALUE
  2477.                                     m_arrMap(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride = 255
  2478.                                 End If
  2479.                             Else
  2480.                                 ' LEAVE THE TILE OPAQUE
  2481.                                 ' TODO: CHANGE 255 TO ORIGINAL Alpha VALUE
  2482.                                 m_arrMap(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride = 255
  2483.                             End If
  2484.                         Else
  2485.                             ' LEAVE THE TILE OPAQUE
  2486.                             ' TODO: CHANGE 255 TO ORIGINAL Alpha VALUE
  2487.                             m_arrMap(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride = 255
  2488.                         End If
  2489.                         'End If
  2490.                         'End If
  2491.                     Else
  2492.                         ' LEAVE THE TILE OPAQUE
  2493.                         ' TODO: CHANGE 255 TO ORIGINAL Alpha VALUE
  2494.                         m_arrMap(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride = 255
  2495.                     End If
  2496.                 Next iLoopZ%
  2497.             Next iLoopY%
  2498.         Next iLoopX%
  2499.     Else
  2500.         ' JUST MAKE ALL TILES VISIBLE
  2501.         For iLoopX% = m_iMapMinX To m_iMapMaxX
  2502.             For iLoopY% = m_iMapMinY To m_iMapMaxY
  2503.                 For iLoopZ% = m_iMapMinZ To m_iMapMaxZ
  2504.                     ' LEAVE THE TILE OPAQUE
  2505.                     m_arrMap(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride = 255
  2506.  
  2507.                     'TODO: CHANGE 255 TO ORIGINAL Alpha VALUE
  2508.                     'TODO: SUPPORT CUSTOM ALPHA FOR COLORS (EVENTUALLY 3-COLOR TILES .Alpha1, .Alpha2, .Alpha3)
  2509.                     'm_arrMap(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride = m_arrMap(iLoopX%, iLoopY%, iLoopZ%).Alpha1
  2510.  
  2511.                 Next iLoopZ%
  2512.             Next iLoopY%
  2513.         Next iLoopX%
  2514.     End If
  2515. End Sub ' ComputeVisible
  2516.  
  2517. ' /////////////////////////////////////////////////////////////////////////////
  2518. ' Determine which squares are visible in isometric map
  2519.  
  2520. ' Same as ComputeVisible except uses the rotated copy
  2521. ' (m_arrRender2 instead of m_arrMap)
  2522.  
  2523. ' Requires shared global variable (3D array of map):
  2524. ' m_arrRender2(x,y,z) = rotated copy of 3D array map of world
  2525. ' m_arrRender2(m_iMapMinX To m_iMapMaxX, m_iMapMinY To m_iMapMaxY, m_iMapMinZ To m_iMapMaxZ) As MapTileType
  2526.  
  2527. ' RECEIVES:
  2528. ' iX% = player's X positon
  2529. ' iY% = player's Y position
  2530. ' iZ% = player's Z position
  2531.  
  2532. ' If iX% < 0 then we just render everything with its normal alpha value.
  2533.  
  2534. ' TODO: FIX FOR c_iDir_Down and c_iDir_Up DIRECTIONS
  2535. '       "FOR TILES FORWARD OF PLAYER" SECTION BELOW
  2536. '       NEEDS TO LOOK AT Z AXIS INSTEAD OF Y ?
  2537.  
  2538. Sub ComputeRenderVisible (iX%, iY%, iZ%, iGridSize)
  2539.     Dim RoutineName As String: RoutineName = "ComputeRenderVisible"
  2540.     Dim iLoopX%
  2541.     Dim iLoopY%
  2542.     Dim iLoopZ%
  2543.  
  2544.     Dim iPX1%
  2545.     Dim iPY1%
  2546.     Dim iPZ1%
  2547.     Dim iPlayer2Dx As Integer
  2548.     Dim iPlayer2Dy As Integer
  2549.     Dim iTile2Dx As Integer
  2550.     Dim iTile2Dy As Integer
  2551.  
  2552.     If iX% > -1 Then
  2553.         ' CALCULATE PLAYER'S 2-D POSITION
  2554.         iPX1% = iX% * iGridSize + cGridOffsetX
  2555.         iPY1% = iY% * iGridSize + cGridOffsetY
  2556.         iPZ1% = iZ% * iGridSize + cGridOffsetZ
  2557.         iPlayer2Dx = CX2I(iPX1%, iPY1%) + cScreenOffsetX
  2558.         iPlayer2Dy = (CY2I(iPX1%, iPY1%) + cScreenOffsetY) - iPZ1%
  2559.         'fquad TempX1, TempY1 - z, TempX2, TempY2 - z, TempX3, TempY3 - z, TempX4, TempY4 - z, _RGB32(r, g, b, alpha&)
  2560.  
  2561.         ' LOOK AT EACH TILE
  2562.         For iLoopX% = m_iMapMinX To m_iMapMaxX
  2563.             For iLoopY% = m_iMapMinY To m_iMapMaxY
  2564.                 For iLoopZ% = m_iMapMinZ To m_iMapMaxZ
  2565.  
  2566.                     ' *****************************************************************************
  2567.                     ' IF SPACE HAS A TILE
  2568.                     ' AND ITS 2D (X,Y) IS > PLAYER'S 2D (X,Y)
  2569.                     ' THEN MAKE THE TILE TRANSPARENT
  2570.                     ' *****************************************************************************
  2571.                     ' TODO: COMPARE AGAINST ALL TYPES OF TILES NOT JUST WALL/FLOOR
  2572.                     If m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iTile_Wall Or m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iTile_Floor Then
  2573.                         ' CALCULATE TILE'S 2-D POSITION
  2574.                         iPX1% = iLoopX% * iGridSize + cGridOffsetX
  2575.                         iPY1% = iLoopY% * iGridSize + cGridOffsetY
  2576.                         iPZ1% = iLoopZ% * iGridSize + cGridOffsetZ
  2577.                         iTile2Dx = CX2I(iPX1%, iPY1%) + cScreenOffsetX
  2578.                         iTile2Dy = (CY2I(iPX1%, iPY1%) + cScreenOffsetY) - iPZ1%
  2579.                         'fquad TempX1, TempY1 - z, TempX2, TempY2 - z, TempX3, TempY3 - z, TempX4, TempY4 - z, _RGB32(r, g, b, alpha&)
  2580.  
  2581.                         'If iLoopZ% >= iZ% Then
  2582.                         'If iLoopX% >= iX% Then
  2583.  
  2584.                         ' FOR TILES FORWARD OF PLAYER
  2585.                         If iLoopY% > iY% Then
  2586.  
  2587.                             ' IF PLAYER'S 2D Y POSITION IS WITHIN RANGE OF TILE'S 2D Y POSITION
  2588.                             If (iPlayer2Dy >= (iTile2Dy - iGridSize)) And (iPlayer2Dy <= (iTile2Dy + iGridSize)) Then
  2589.  
  2590.                                 ' AND IF PLAYER'S 2D X POSITION IS WITHIN RANGE OF TILE'S 2D X POSITION
  2591.                                 If (iPlayer2Dx >= (iTile2Dx - iGridSize)) And (iPlayer2Dx <= (iTile2Dx + iGridSize)) Then
  2592.                                     ' RENDER THE TILE TRANSPARENT SO WE CAN SEE THE PLAYER
  2593.                                     'TODO: CHANGE AlphaOverride TO BE RELATIVE TO ORIGINAL Alpha VALUE?
  2594.                                     m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride = 86
  2595.                                 Else
  2596.                                     ' LEAVE THE TILE OPAQUE
  2597.                                     m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride = 255
  2598.  
  2599.                                     'TODO: CHANGE 255 TO ORIGINAL Alpha VALUE
  2600.                                     'TODO: SUPPORT CUSTOM ALPHA FOR COLORS (EVENTUALLY 3-COLOR TILES .Alpha1, .Alpha2, .Alpha3)
  2601.                                     'm_arrRender2(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride = m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).Alpha1
  2602.                                 End If
  2603.                             Else
  2604.                                 ' LEAVE THE TILE OPAQUE
  2605.                                 m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride = 255
  2606.  
  2607.                                 'TODO: CHANGE 255 TO ORIGINAL Alpha VALUE
  2608.                                 'TODO: SUPPORT CUSTOM ALPHA FOR COLORS (EVENTUALLY 3-COLOR TILES .Alpha1, .Alpha2, .Alpha3)
  2609.                                 'm_arrRender2(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride = m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).Alpha1
  2610.                             End If
  2611.                         Else
  2612.                             ' LEAVE THE TILE OPAQUE
  2613.                             m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride = 255
  2614.  
  2615.                             'TODO: CHANGE 255 TO ORIGINAL Alpha VALUE
  2616.                             'TODO: SUPPORT CUSTOM ALPHA FOR COLORS (EVENTUALLY 3-COLOR TILES .Alpha1, .Alpha2, .Alpha3)
  2617.                             'm_arrRender2(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride = m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).Alpha1
  2618.                         End If
  2619.                         'End If
  2620.                         'End If
  2621.                     Else
  2622.                         m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride = 255
  2623.  
  2624.                         'TODO: SUPPORT CUSTOM ALPHA FOR COLORS (EVENTUALLY 3-COLOR TILES .Alpha1, .Alpha2, .Alpha3)
  2625.                         'm_arrRender2(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride = m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).Alpha1
  2626.                     End If
  2627.                 Next iLoopZ%
  2628.             Next iLoopY%
  2629.         Next iLoopX%
  2630.     Else
  2631.         ' JUST MAKE ALL TILES VISIBLE
  2632.         For iLoopX% = m_iMapMinX To m_iMapMaxX
  2633.             For iLoopY% = m_iMapMinY To m_iMapMaxY
  2634.                 For iLoopZ% = m_iMapMinZ To m_iMapMaxZ
  2635.                     m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride = 255
  2636.  
  2637.                     'TODO: CHANGE 255 TO ORIGINAL Alpha VALUE
  2638.                     'TODO: SUPPORT CUSTOM ALPHA FOR COLORS (EVENTUALLY 3-COLOR TILES .Alpha1, .Alpha2, .Alpha3)
  2639.                     'm_arrRender2(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride = m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).Alpha1
  2640.                 Next iLoopZ%
  2641.             Next iLoopY%
  2642.         Next iLoopX%
  2643.     End If
  2644. End Sub ' ComputeRenderVisible
  2645.  
  2646. ' /////////////////////////////////////////////////////////////////////////////
  2647. ' Draw the map in 3D Isometic Perspective
  2648. ' from the forward (default) perspective.
  2649.  
  2650. ' Requires shared global variable
  2651. ' m_arrMap(x,y,z) = 3D array map of world
  2652. ' m_arrMap(m_iMapMinX To m_iMapMaxX, m_iMapMinY To m_iMapMaxY, m_iMapMinZ To m_iMapMaxZ) As MapTileType
  2653.  
  2654. ' TODO: ADD OFFSET PARAMETERS FOR WHERE TO DRAW ON SCREEN (FOR SPLIT SCREEN)
  2655. ' params instead of constants:
  2656. ' Const cScreenOffsetX = 500 ' 450
  2657. ' Const cScreenOffsetY = 300 ' 50
  2658. ' Const cScreenOffsetZ = 0
  2659.  
  2660. ' what about?
  2661. ' Const cGridOffsetX = 50
  2662. ' Const cGridOffsetY = 50
  2663. ' Const cGridOffsetZ = 0
  2664.  
  2665. Sub DrawIsometricScreen (iScreenOffsetX, iScreenOffsetY, iGridSize)
  2666.     Dim RoutineName As String: RoutineName = "DrawIsometricScreen"
  2667.     Dim bTile As Integer
  2668.     Dim iLoopX%
  2669.     Dim iLoopY%
  2670.     Dim iLoopZ%
  2671.     Dim iColor As _Unsigned Long
  2672.     Dim iPosX1%
  2673.     Dim iPosX2%
  2674.     Dim iPosY1%
  2675.     Dim iPosY2%
  2676.     Dim iPosZ1%
  2677.     Dim alpha&
  2678.  
  2679.     alpha& = 255
  2680.     bTile = FALSE
  2681.     For iLoopZ% = m_iMapMinZ To m_iMapMaxZ
  2682.         For iLoopX% = m_iMapMinX To m_iMapMaxX
  2683.             For iLoopY% = m_iMapMinY To m_iMapMaxY
  2684.  
  2685.                 ' CALCULATE POSITION
  2686.                 iPosZ1% = iLoopZ% * iGridSize + cGridOffsetZ
  2687.                 iPosX1% = iLoopX% * iGridSize + cGridOffsetX
  2688.                 iPosY1% = iLoopY% * iGridSize + cGridOffsetY
  2689.                 iPosX2% = iPosX1% + iGridSize
  2690.                 iPosY2% = iPosY1% + iGridSize
  2691.  
  2692.                 ' DETERMINE COLOR
  2693.                 If m_arrMap(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iTile_Floor Then
  2694.                     If bTile = TRUE Then
  2695.                         iColor = m_arrMap(iLoopX%, iLoopY%, iLoopZ%).Color1
  2696.                         bTile = FALSE
  2697.                     Else
  2698.                         iColor = m_arrMap(iLoopX%, iLoopY%, iLoopZ%).Color2
  2699.                         bTile = TRUE
  2700.                     End If
  2701.                 ElseIf m_arrMap(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iTile_Wall Then
  2702.                     iColor = m_arrMap(iLoopX%, iLoopY%, iLoopZ%).Color1
  2703.                     alpha& = m_arrMap(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride
  2704.  
  2705.                 ElseIf m_arrMap(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iTile_Player1 Then
  2706.                     iColor = m_arrMap(iLoopX%, iLoopY%, iLoopZ%).Color1
  2707.                     alpha& = 255
  2708.  
  2709.                 ElseIf m_arrMap(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iTile_Player2 Then
  2710.                     iColor = m_arrMap(iLoopX%, iLoopY%, iLoopZ%).Color1
  2711.                     alpha& = 255
  2712.  
  2713.                 ElseIf m_arrMap(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iTile_Player3 Then
  2714.                     iColor = m_arrMap(iLoopX%, iLoopY%, iLoopZ%).Color1
  2715.                     alpha& = 255
  2716.  
  2717.                 ElseIf m_arrMap(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iTile_Player4 Then
  2718.                     iColor = m_arrMap(iLoopX%, iLoopY%, iLoopZ%).Color1
  2719.                     alpha& = 255
  2720.  
  2721.                 ElseIf m_arrMap(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iTile_Water Then
  2722.                     'TODO: transparent for water
  2723.                     iColor = cEmpty
  2724.                     alpha& = 64
  2725.  
  2726.                 ElseIf m_arrMap(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iTile_Window Then
  2727.                     'TODO: transparent for windows
  2728.                     iColor = cEmpty
  2729.                     alpha& = 64
  2730.  
  2731.                 Else
  2732.                     iColor = cEmpty
  2733.                 End If
  2734.  
  2735.                 ' PLOT NEXT TILE
  2736.                 If iColor <> cEmpty Then
  2737.                     'IsoLine3D(x,      y,       x2,      y2,      z,       iHeight,     xoffset,        yoffset,        iColor As _Unsigned Long, alpha&)
  2738.                     'IsoLine3D iPosX1%, iPosY1%, iPosX2%, iPosY2%, iPosZ1%, m_iGridSize, cScreenOffsetX, cScreenOffsetY, iColor, alpha&
  2739.                     IsoLine3D iPosX1%, iPosY1%, iPosX2%, iPosY2%, iPosZ1%, iGridSize, iScreenOffsetX, iScreenOffsetY, iColor, alpha&
  2740.                 End If
  2741.  
  2742.             Next iLoopY%
  2743.         Next iLoopX%
  2744.     Next iLoopZ%
  2745. End Sub ' DrawIsometricScreen
  2746.  
  2747. ' /////////////////////////////////////////////////////////////////////////////
  2748. ' Draw the map in 3D Isometic Perspective.
  2749.  
  2750. ' Requires shared global variable
  2751. ' m_arrRender2(x,y,z) = 3D array map of world
  2752. ' m_arrRender2(m_iMapMinX To m_iMapMaxX, m_iMapMinY To m_iMapMaxY, m_iMapMinZ To m_iMapMaxZ) As MapTileType
  2753.  
  2754. Sub DrawRenderScreen (iScreenOffsetX, iScreenOffsetY, iGridSize)
  2755.     Dim RoutineName As String: RoutineName = "DrawRenderScreen"
  2756.     Dim bTile As Integer
  2757.     Dim iLoopX%
  2758.     Dim iLoopY%
  2759.     Dim iLoopZ%
  2760.     Dim iColor As _Unsigned Long
  2761.     Dim iPosX1%
  2762.     Dim iPosX2%
  2763.     Dim iPosY1%
  2764.     Dim iPosY2%
  2765.     Dim iPosZ1%
  2766.     Dim alpha&
  2767.  
  2768.     alpha& = 255
  2769.     bTile = FALSE
  2770.     For iLoopZ% = m_iMapMinZ To m_iMapMaxZ
  2771.         For iLoopX% = m_iMapMinX To m_iMapMaxX
  2772.             For iLoopY% = m_iMapMinY To m_iMapMaxY
  2773.  
  2774.                 ' CALCULATE POSITION
  2775.                 iPosZ1% = iLoopZ% * iGridSize + cGridOffsetZ
  2776.                 iPosX1% = iLoopX% * iGridSize + cGridOffsetX
  2777.                 iPosY1% = iLoopY% * iGridSize + cGridOffsetY
  2778.                 iPosX2% = iPosX1% + iGridSize
  2779.                 iPosY2% = iPosY1% + iGridSize
  2780.  
  2781.                 ' DETERMINE COLOR
  2782.                 If m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iTile_Floor Then
  2783.                     If bTile = TRUE Then
  2784.                         iColor = m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).Color1
  2785.                         bTile = FALSE
  2786.                     Else
  2787.                         iColor = m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).Color2
  2788.                         bTile = TRUE
  2789.                     End If
  2790.  
  2791.                 ElseIf m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iTile_Wall Then
  2792.                     iColor = m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).Color1
  2793.                     alpha& = m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).AlphaOverride
  2794.  
  2795.                 ElseIf m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iTile_Player1 Then
  2796.                     iColor = m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).Color1
  2797.                     alpha& = 255
  2798.  
  2799.                 ElseIf m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iTile_Player2 Then
  2800.                     iColor = m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).Color1
  2801.                     alpha& = 255
  2802.  
  2803.                 ElseIf m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iTile_Player3 Then
  2804.                     iColor = m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).Color1
  2805.                     alpha& = 255
  2806.  
  2807.                 ElseIf m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iTile_Player4 Then
  2808.                     iColor = m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).Color1
  2809.                     alpha& = 255
  2810.  
  2811.                 ElseIf m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iTile_Water Then
  2812.                     'TODO: transparent for water
  2813.                     iColor = cEmpty
  2814.                     alpha& = 64
  2815.  
  2816.                 ElseIf m_arrRender2(iLoopX%, iLoopY%, iLoopZ%).Typ = c_iTile_Window Then
  2817.                     'TODO: transparent for windows
  2818.                     iColor = cEmpty
  2819.                     alpha& = 64
  2820.  
  2821.                 Else
  2822.                     iColor = cEmpty
  2823.                 End If
  2824.  
  2825.                 ' PLOT NEXT TILE
  2826.                 If iColor <> cEmpty Then
  2827.                     'IsoLine3D(x,      y,       x2,      y2,      z,       iHeight,     xoffset,        yoffset,        iColor As _Unsigned Long, alpha&)
  2828.                     'IsoLine3D iPosX1%, iPosY1%, iPosX2%, iPosY2%, iPosZ1%, m_iGridSize, cScreenOffsetX, cScreenOffsetY, iColor, alpha&
  2829.                     IsoLine3D iPosX1%, iPosY1%, iPosX2%, iPosY2%, iPosZ1%, iGridSize, iScreenOffsetX, iScreenOffsetY, iColor, alpha&
  2830.                 End If
  2831.  
  2832.             Next iLoopY%
  2833.         Next iLoopX%
  2834.     Next iLoopZ%
  2835. End Sub ' DrawRenderScreen
  2836.  
  2837. ' /////////////////////////////////////////////////////////////////////////////
  2838. ' Draw the map in 3D Isometic Perspective
  2839. ' from a different direction.
  2840.  
  2841. ' This is the lazy man's version which simply copies the tiles to
  2842. ' a temporary array, rotated to the specified direction/orientation.
  2843. ' A more efficient + faster method would operate directly on the
  2844. ' main array, but I am too bogged down to figure that out right now!
  2845.  
  2846. ' RECEIVES:
  2847. ' iDirection% = point of view to render from
  2848. '     i.e. the direction we are looking at the scene FROM
  2849. '     iDirection% can be one of the following:
  2850. '     c_iDir_Down
  2851. '     c_iDir_Up
  2852. '     c_iDir_Left
  2853. '     c_iDir_Right
  2854. '     c_iDir_Back
  2855. '     c_iDir_Forward = default
  2856. '
  2857. '     If iDirection% = c_iDir_Forward, just call DrawIsometricScreen instead (faster).
  2858. '
  2859. ' iScreenOffsetX, iScreenOffsetY = where on display to draw
  2860. '
  2861. ' iX%, iY%, iZ% = player's position, used for ComputeRenderVisible
  2862. '     to compute which tiles to hide / make transparent
  2863. '     (tiles that might be hiding the player)
  2864. '     If these are <0, then ComputeRenderVisible uses original alpha values.
  2865.  
  2866. ' TODO: ADD OFFSET PARAMETERS FOR WHERE TO DRAW ON SCREEN (FOR SPLIT SCREEN)
  2867. ' params instead of constants:
  2868. ' Const cScreenOffsetX = 500 ' 450
  2869. ' Const cScreenOffsetY = 300 ' 50
  2870. ' Const cScreenOffsetZ = 0
  2871.  
  2872. ' what about?
  2873. ' Const cGridOffsetX = 50
  2874. ' Const cGridOffsetY = 50
  2875. ' Const cGridOffsetZ = 0
  2876.  
  2877. ' TODO: player layer
  2878. ' m_iPlayerCount
  2879. ' shared for current player #?
  2880. ' first copy world and superimpose player coords?
  2881.  
  2882. Sub DrawScreen (iDirection%, iScreenOffsetX, iScreenOffsetY, iGridSize, iX%, iY%, iZ%)
  2883.     Dim RoutineName As String: RoutineName = "DrawScreen"
  2884.     Dim bTile As Integer
  2885.     Dim iLoopX%
  2886.     Dim iLoopY%
  2887.     Dim iLoopZ%
  2888.     Dim iColor As _Unsigned Long
  2889.     Dim iPosX1%
  2890.     Dim iPosX2%
  2891.     Dim iPosY1%
  2892.     Dim iPosY2%
  2893.     Dim iPosZ1%
  2894.     Dim alpha&
  2895.  
  2896.     ' =============================================================================
  2897.     ' USE FIRST TEMPORARY ARRAY TO STORE SCENE OVERLAID WITH PLAYERS + OBJECTS
  2898.  
  2899.     ' CLEAR THE MAP (NECESSARY?)
  2900.     ClearRenderMap1
  2901.  
  2902.     ' FIRST COPY THE MAP
  2903.     For iLoopZ% = m_iMapMinZ To m_iMapMaxZ
  2904.         For iLoopX% = m_iMapMinX To m_iMapMaxX
  2905.             For iLoopY% = m_iMapMinY To m_iMapMaxY
  2906.                 'm_arrRender1(iLoopX%,iLoopY%,iLoopZ%) = m_arrMap(iLoopX%, iLoopY%, iLoopZ%)
  2907.                 CopyMapTile m_arrMap(iLoopX%, iLoopY%, iLoopZ%), m_arrRender1(iLoopX%, iLoopY%, iLoopZ%)
  2908.             Next iLoopY%
  2909.         Next iLoopX%
  2910.     Next iLoopZ%
  2911.  
  2912.     ' NEXT COPY THE PLAYERS
  2913.     For iLoopX% = m_iPlayerMin To m_iPlayerCount
  2914.         m_arrRender1(m_arrPlayer(iLoopX%).x, m_arrPlayer(iLoopX%).y, m_arrPlayer(iLoopX%).z).Typ = m_arrPlayer(iLoopX%).Tile1
  2915.         m_arrRender1(m_arrPlayer(iLoopX%).x, m_arrPlayer(iLoopX%).y, m_arrPlayer(iLoopX%).z).Color1 = m_arrPlayer(iLoopX%).Color1
  2916.         m_arrRender1(m_arrPlayer(iLoopX%).x, m_arrPlayer(iLoopX%).y, m_arrPlayer(iLoopX%).z).Alpha1 = m_arrPlayer(iLoopX%).Alpha1
  2917.         m_arrRender1(m_arrPlayer(iLoopX%).x, m_arrPlayer(iLoopX%).y, m_arrPlayer(iLoopX%).z).AlphaOverride = m_arrPlayer(iLoopX%).AlphaOverride
  2918.     Next iLoopX%
  2919.  
  2920.     ' NEXT COPY THE OBJECTS
  2921.     ' (TO DO WHEN WE HAVE OBJECTS)
  2922.  
  2923.     ' =============================================================================
  2924.     ' USE SECOND TEMPORARY ARRAY TO STORE ROTATED SCENE THEN DRAW IT
  2925.  
  2926.     ' CLEAR THE MAP (NECESSARY?)
  2927.     ClearRenderMap2
  2928.  
  2929.     ' COPY TILES, ROTATED TO DESIRED VIEWING PERSPECTIVE / ANGLE
  2930.     Select Case iDirection%
  2931.         Case c_iDir_Down:
  2932.             ' SCENE IS FLIPPED UP (TOP FACE NOW FACING AWAY FROM US)
  2933.             For iLoopZ% = m_iMapMinZ To m_iMapMaxZ
  2934.                 For iLoopX% = m_iMapMinX To m_iMapMaxX
  2935.                     For iLoopY% = m_iMapMinY To m_iMapMaxY
  2936.                         m_arrRender2(iLoopX%, m_iMapMaxZ - iLoopZ%, iLoopY%) = m_arrRender1(iLoopX%, iLoopY%, iLoopZ%)
  2937.                     Next iLoopY%
  2938.                 Next iLoopX%
  2939.             Next iLoopZ%
  2940.             ComputeRenderVisible iX%, m_iMapMaxZ - iZ%, iY%, iGridSize
  2941.         Case c_iDir_Up:
  2942.             ' SCENE IS FLIPPED DOWN (TOP FACE NOW FACING TOWARD US)
  2943.             For iLoopZ% = m_iMapMinZ To m_iMapMaxZ
  2944.                 For iLoopX% = m_iMapMinX To m_iMapMaxX
  2945.                     For iLoopY% = m_iMapMinY To m_iMapMaxY
  2946.                         m_arrRender2(iLoopX%, iLoopZ%, m_iMapMaxY - iLoopY%) = m_arrRender1(iLoopX%, iLoopY%, iLoopZ%)
  2947.                     Next iLoopY%
  2948.                 Next iLoopX%
  2949.             Next iLoopZ%
  2950.             ComputeRenderVisible iX%, iZ%, m_iMapMaxY - iY%, iGridSize
  2951.         Case c_iDir_Left:
  2952.             ' SCENE IS ROTATED COUNTER CLOCKWISE FROM TOP (LEFT FACE NOW FACING TOWARD US)
  2953.             For iLoopZ% = m_iMapMinZ To m_iMapMaxZ
  2954.                 For iLoopX% = m_iMapMinX To m_iMapMaxX
  2955.                     For iLoopY% = m_iMapMinY To m_iMapMaxY
  2956.                         m_arrRender2(iLoopY%, m_iMapMaxX - iLoopX%, iLoopZ%) = m_arrRender1(iLoopX%, iLoopY%, iLoopZ%)
  2957.                     Next iLoopY%
  2958.                 Next iLoopX%
  2959.             Next iLoopZ%
  2960.             ComputeRenderVisible iY%, m_iMapMaxX - iX%, iZ%, iGridSize
  2961.         Case c_iDir_Right:
  2962.             ' SCENE IS ROTATED CLOCKWISE FROM TOP (RIGHT FACE NOW FACING TOWARD US)
  2963.             For iLoopZ% = m_iMapMinZ To m_iMapMaxZ
  2964.                 For iLoopX% = m_iMapMinX To m_iMapMaxX
  2965.                     For iLoopY% = m_iMapMinY To m_iMapMaxY
  2966.                         m_arrRender2(m_iMapMaxY - iLoopY%, iLoopX%, iLoopZ%) = m_arrRender1(iLoopX%, iLoopY%, iLoopZ%)
  2967.                     Next iLoopY%
  2968.                 Next iLoopX%
  2969.             Next iLoopZ%
  2970.             ComputeRenderVisible m_iMapMaxY - iY%, iX%, iZ%, iGridSize
  2971.         Case c_iDir_Back:
  2972.             ' SCENE IS TURNED AROUND (FRONT FACE NOW FACING AWAY FROM US)
  2973.             For iLoopZ% = m_iMapMinZ To m_iMapMaxZ
  2974.                 For iLoopX% = m_iMapMinX To m_iMapMaxX
  2975.                     For iLoopY% = m_iMapMinY To m_iMapMaxY
  2976.                         m_arrRender2(m_iMapMaxX - iLoopX%, m_iMapMaxY - iLoopY%, iLoopZ%) = m_arrRender1(iLoopX%, iLoopY%, iLoopZ%)
  2977.                     Next iLoopY%
  2978.                 Next iLoopX%
  2979.             Next iLoopZ%
  2980.             ComputeRenderVisible m_iMapMaxX - iX%, m_iMapMaxY - iY%, iZ%, iGridSize
  2981.         Case Else: ' c_iDir_Forward
  2982.             ' FOR ALL OTHER CASES WE JUST DRAW FORWARD (FACING TOWARD US)
  2983.             For iLoopZ% = m_iMapMinZ To m_iMapMaxZ
  2984.                 For iLoopX% = m_iMapMinX To m_iMapMaxX
  2985.                     For iLoopY% = m_iMapMinY To m_iMapMaxY
  2986.                         m_arrRender2(iLoopX%, iLoopY%, iLoopZ%) = m_arrRender1(iLoopX%, iLoopY%, iLoopZ%)
  2987.                     Next iLoopY%
  2988.                 Next iLoopX%
  2989.             Next iLoopZ%
  2990.             ComputeRenderVisible iX%, iY%, iZ%, iGridSize
  2991.     End Select
  2992.     DrawRenderScreen iScreenOffsetX, iScreenOffsetY, iGridSize
  2993. End Sub ' DrawScreen
  2994.  
  2995. ' /////////////////////////////////////////////////////////////////////////////
  2996. ' Copies a MapTileType user defined type variable, member by member
  2997. ' (not sure if you can just do MyUDT1 = MyUDT2?)
  2998.  
  2999. Sub CopyMapTile (SourceMap As MapTileType, DestMap As MapTileType)
  3000.     DestMap.Typ = SourceMap.Typ
  3001.     DestMap.Color1 = SourceMap.Color1
  3002.     DestMap.Color2 = SourceMap.Color2
  3003.     DestMap.Color3 = SourceMap.Color3
  3004.     DestMap.Alpha1 = SourceMap.Alpha1
  3005.     DestMap.Alpha2 = SourceMap.Alpha2
  3006.     DestMap.Alpha3 = SourceMap.Alpha3
  3007.     DestMap.AlphaOverride = SourceMap.AlphaOverride
  3008. End Sub ' CopyMapTile
  3009.  
  3010. ' /////////////////////////////////////////////////////////////////////////////
  3011. ' RETURNS MAP AS TEXT
  3012.  
  3013. ' Requires shared global variable
  3014. ' m_arrMap(x,y,z) = 3D array map of world
  3015. ' m_arrMap(m_iMapMinX To m_iMapMaxX, m_iMapMinY To m_iMapMaxY, m_iMapMinZ To m_iMapMaxZ) As MapTileType
  3016.  
  3017. ' USAGE:
  3018. 'Input "See a text dump (y/n)? ", in$
  3019. 'If LCase$(in$) = LCase$("y") Then
  3020. '    Print MapToText$
  3021. 'End If
  3022.  
  3023. Function MapToText$
  3024.     Dim RoutineName As String: RoutineName = "MapToText$"
  3025.     Dim sResult As String
  3026.     Dim iLoopX%
  3027.     Dim iLoopY%
  3028.     Dim iLoopZ%
  3029.     Dim iMinX%
  3030.     Dim iMaxX%
  3031.     Dim iMinY%
  3032.     Dim iMaxY%
  3033.     Dim iMinZ%
  3034.     Dim iMaxZ%
  3035.     Dim sLine As String
  3036.     Dim iType%
  3037.     Dim iColor1&
  3038.     Dim iColor2&
  3039.     Dim iColor3&
  3040.     Dim in$
  3041.  
  3042.     sResult = ""
  3043.  
  3044.     ' FIND USED BOUNDARIES OF MAP
  3045.     iMinX% = -1
  3046.     iMaxX% = -1
  3047.     iMinY% = -1
  3048.     iMaxY% = -1
  3049.     iMinZ% = -1
  3050.     iMaxZ% = -1
  3051.     For iLoopZ% = 0 To 32
  3052.         For iLoopX% = 0 To 32
  3053.             For iLoopY% = 0 To 32
  3054.                 iType% = m_arrMap(iLoopX%, iLoopY%, iLoopZ%).Typ
  3055.                 If iType% <> c_iTile_Empty And iType% <> c_iTile_Floor Then
  3056.                     If iMinX% = -1 Then
  3057.                         iMinX% = iLoopX%
  3058.                     End If
  3059.                     If iMinY% = -1 Then
  3060.                         iMinY% = iLoopY%
  3061.                     End If
  3062.                     If iMinZ% = -1 Then
  3063.                         iMinZ% = iLoopZ%
  3064.                     End If
  3065.                     If iLoopX% > iMaxX% Then
  3066.                         iMaxX% = iLoopX%
  3067.                     End If
  3068.                     If iLoopY% > iMaxY% Then
  3069.                         iMaxY% = iLoopY%
  3070.                     End If
  3071.                     If iLoopZ% > iMaxZ% Then
  3072.                         iMaxZ% = iLoopZ%
  3073.                     End If
  3074.                 End If
  3075.             Next iLoopY%
  3076.         Next iLoopX%
  3077.     Next iLoopZ%
  3078.  
  3079.     ' GENERATE OUTPUT
  3080.     For iLoopZ% = iMinZ% To iMaxZ%
  3081.         sResult = sResult + "-------------------------------------------------------------------------------" + Chr$(13)
  3082.         sResult = sResult + "Map Z=" + cstr$(iLoopZ%) + ":" + Chr$(13)
  3083.         sResult = sResult + "-------------------------------------------------------------------------------" + Chr$(13)
  3084.         For iLoopY% = iMinY% To iMaxY%
  3085.             sLine = ""
  3086.             For iLoopX% = iMinX% To iMaxX%
  3087.                 iType% = m_arrMap(iLoopX%, iLoopY%, iLoopZ%).Typ
  3088.                 iColor1& = m_arrMap(iLoopX%, iLoopY%, iLoopZ%).Color1
  3089.                 iColor2& = m_arrMap(iLoopX%, iLoopY%, iLoopZ%).Color2
  3090.                 iColor3& = m_arrMap(iLoopX%, iLoopY%, iLoopZ%).Color3
  3091.  
  3092.                 If iType% = c_iTile_Empty Then
  3093.                     sLine = sLine + " "
  3094.                 Else
  3095.                     If iColor1& = cEmpty Then
  3096.                         sLine = sLine + " "
  3097.                     Else
  3098.                         sLine = sLine + "#"
  3099.                     End If
  3100.                 End If
  3101.             Next iLoopX%
  3102.             sResult = sResult + sLine + Chr$(13)
  3103.         Next iLoopY%
  3104.  
  3105.         sResult = sResult + Chr$(13)
  3106.     Next iLoopZ%
  3107.  
  3108.     MapToText$ = sResult
  3109. End Function ' MapToText$
  3110.  
  3111. ' /////////////////////////////////////////////////////////////////////////////
  3112. ' Return string description for 2.5D movement constants
  3113.  
  3114. Function GetDirection$ (iDir As Integer)
  3115.     Dim sDir As String
  3116.     Select Case iDir
  3117.         Case c_iDir_Down:
  3118.             sDir = "Down"
  3119.         Case c_iDir_Up:
  3120.             sDir = "Up"
  3121.         Case c_iDir_Left:
  3122.             sDir = "Left"
  3123.         Case c_iDir_Right:
  3124.             sDir = "Right"
  3125.         Case c_iDir_Back:
  3126.             sDir = "Back"
  3127.         Case c_iDir_Forward:
  3128.             sDir = "Forward"
  3129.         Case Else:
  3130.             sDir = "Unknown"
  3131.     End Select
  3132.     GetDirection$ = sDir
  3133. End Function ' GetDirection$
  3134.  
  3135. ' /////////////////////////////////////////////////////////////////////////////
  3136.  
  3137. Function CX2I (x As Long, y As Long) 'Convert Cartesian X To Isometic coordinates
  3138.     CX2I = x - y
  3139. End Function ' CX2I
  3140.  
  3141. ' /////////////////////////////////////////////////////////////////////////////
  3142.  
  3143. Function CY2I (x As Long, y As Long) 'Convert Cartesian Y To Isometic coordinates
  3144.     CY2I = (x + y) / 2
  3145. End Function ' CY2I
  3146.  
  3147. ' /////////////////////////////////////////////////////////////////////////////
  3148. ' since we're drawing a diamond and not a square box, we can't use Line BF.
  3149. ' We have to manually down the 4 points of the line.
  3150.  
  3151. Sub IsoLine (x, y, x2, y2, xoffset, yoffset, iColor As _Unsigned Long)
  3152.     Line (CX2I(x, y) + xoffset, CY2I(x, y) + yoffset)-(CX2I(x2, y) + xoffset, CY2I(x2, y) + yoffset), iColor
  3153.     Line -(CX2I(x2, y2) + xoffset, CY2I(x2, y2) + yoffset), iColor
  3154.     Line -(CX2I(x, y2) + xoffset, CY2I(x, y2) + yoffset), iColor
  3155.     Line -(CX2I(x, y) + xoffset, CY2I(x, y) + yoffset), iColor
  3156.     Paint (CX2I(x, y) + xoffset, CY2I(x, y) + 4), iColor 'and fill the diamond solid
  3157.     Line (CX2I(x, y) + xoffset, CY2I(x, y) + yoffset)-(CX2I(x2, y) + xoffset, CY2I(x2, y) + yoffset), &HFFFFFFFF
  3158.     Line -(CX2I(x2, y2) + xoffset, CY2I(x2, y2) + yoffset), &HFFFFFFFF
  3159.     Line -(CX2I(x, y2) + xoffset, CY2I(x, y2) + yoffset), &HFFFFFFFF
  3160.     Line -(CX2I(x, y) + xoffset, CY2I(x, y) + yoffset), &HFFFFFFFF
  3161. End Sub ' IsoLine
  3162.  
  3163. ' /////////////////////////////////////////////////////////////////////////////
  3164. ' Like IsoLine, we're going to have to draw our lines manually.
  3165. ' only in this case, we also need a Z coordinate to tell us how
  3166. ' THICK/TALL/HIGH to make our tile
  3167.  
  3168. ' MODIFIED by madscijr to draw a single tile of height iHeight at Z axis
  3169. ' MODIFIED by madscijr to accept an alpha& value to control transparency (where 0=fully transparent, 255=opaque)
  3170.  
  3171. ''Sub IsoLine3D (x, y, x2, y2, z, xoffset, yoffset, iColor As _Unsigned Long)
  3172. 'Sub IsoLine3D (x, y, x2, y2, z, iHeight, xoffset, yoffset, iColor As _Unsigned Long)
  3173. Sub IsoLine3D (x, y, x2, y2, z, iHeight, xoffset, yoffset, iColor As _Unsigned Long, alpha&)
  3174.     Dim r 'as integer
  3175.     Dim g 'as integer
  3176.     Dim b 'as integer
  3177.  
  3178.     r = _Red32(iColor)
  3179.     g = _Green32(iColor)
  3180.     b = _Blue32(iColor)
  3181.  
  3182.     ' Let's just do all the math first this time.
  3183.     ' We need to turn those 4 normal points into 4 isometric points (x, y, x1, y1)
  3184.     TempX1 = CX2I(x, y) + xoffset
  3185.     TempY1 = CY2I(x, y) + yoffset
  3186.     TempX2 = CX2I(x2, y) + xoffset
  3187.     TempY2 = CY2I(x2, y) + yoffset
  3188.     TempX3 = CX2I(x2, y2) + xoffset
  3189.     TempY3 = CY2I(x2, y2) + yoffset
  3190.     TempX4 = CX2I(x, y2) + xoffset
  3191.     TempY4 = CY2I(x, y2) + yoffset
  3192.  
  3193.     ' The top
  3194.     'fquad TempX1, TempY1 - z, TempX2, TempY2 - z, TempX3, TempY3 - z, TempX4, TempY4 - z, iColor
  3195.     fquad TempX1, TempY1 - z, TempX2, TempY2 - z, TempX3, TempY3 - z, TempX4, TempY4 - z, _RGB32(r, g, b, alpha&)
  3196.  
  3197.     If z <> 0 Then
  3198.         ' TODO: maybe change which sides gets shaded depending on the direction of the light source?
  3199.  
  3200.         ' draw the left side, shaded 75%
  3201.         'fquad TempX4, TempY4 - z, TempX4, TempY4 - z + iHeight, TempX3, TempY3 - z + iHeight, TempX3, TempY3 - z, _RGB32(.75 * r, .75 * g, .75 * b)
  3202.         fquad TempX4, TempY4 - z, TempX4, TempY4 - z + iHeight, TempX3, TempY3 - z + iHeight, TempX3, TempY3 - z, _RGB32(.75 * r, .75 * g, .75 * b, alpha&)
  3203.  
  3204.         ' draw the right side,s haded 50%
  3205.         'fquad TempX3, TempY3 - z, TempX3, TempY3 - z + iHeight, TempX2, TempY2 - z + iHeight, TempX2, TempY2 - z, _RGB32(.5 * r, .5 * g, .5 * b)
  3206.         fquad TempX3, TempY3 - z, TempX3, TempY3 - z + iHeight, TempX2, TempY2 - z + iHeight, TempX2, TempY2 - z, _RGB32(.5 * r, .5 * g, .5 * b, alpha&)
  3207.     Else
  3208.         ' no need to draw any height, if there isn't any.
  3209.     End If
  3210. End Sub ' IsoLine3D
  3211.  
  3212. ' /////////////////////////////////////////////////////////////////////////////
  3213. ' found at abandoned, outdated and now likely malicious qb64 dot net website
  3214. ' don't go there: http://www.qb64.[net]/forum/index.php?topic=14425.0
  3215.  
  3216. Sub ftri (x1, y1, x2, y2, x3, y3, K As _Unsigned Long)
  3217.     Dim D As Long
  3218.     Dim a&
  3219.  
  3220.     D = _Dest
  3221.     a& = _NewImage(1, 1, 32)
  3222.     _Dest a&
  3223.     PSet (0, 0), K
  3224.     _Dest D
  3225.     _MapTriangle _Seamless(0, 0)-(0, 0)-(0, 0), a& To(x1, y1)-(x2, y2)-(x3, y3)
  3226.     _FreeImage a& ' <<< this is important!
  3227. End Sub ' ftri
  3228.  
  3229. ' /////////////////////////////////////////////////////////////////////////////
  3230. ' 2019-11-20 Steve saves some time with STATIC
  3231. ' and saves and restores last dest
  3232.  
  3233. Sub ftri1 (x1, y1, x2, y2, x3, y3, K As _Unsigned Long)
  3234.     Dim D As Long
  3235.     Static a&
  3236.  
  3237.     D = _Dest
  3238.     If a& = 0 Then
  3239.         a& = _NewImage(1, 1, 32)
  3240.     End If
  3241.     _Dest a&
  3242.     _DontBlend a&
  3243.     PSet (0, 0), K
  3244.     _Blend a&
  3245.     _Dest D
  3246.     _MapTriangle _Seamless(0, 0)-(0, 0)-(0, 0), a& To(x1, y1)-(x2, y2)-(x3, y3)
  3247. End Sub ' ftri1
  3248.  
  3249. ' /////////////////////////////////////////////////////////////////////////////
  3250. ' original fill quad that may be at fault using Steve's fTri version
  3251. ' need 4 non linear points (not all on 1 line) list them clockwise
  3252. ' so x2, y2 is opposite of x4, y4
  3253.  
  3254. Sub fquad1 (x1, y1, x2, y2, x3, y3, x4, y4, K As _Unsigned Long)
  3255.     ftri1 x1, y1, x2, y2, x4, y4, K
  3256.     ftri1 x3, y3, x2, y2, x4, y4, K
  3257. End Sub ' fquad1
  3258.  
  3259. ' /////////////////////////////////////////////////////////////////////////////
  3260. ' update 2019-12-16 needs orig fTri
  3261. ' need 4 non linear points (not all on 1 line)
  3262. ' list them clockwise so x2, y2 is opposite of x4, y4
  3263.  
  3264. Sub fquad (x1, y1, x2, y2, x3, y3, x4, y4, K As _Unsigned Long)
  3265.     ftri x1, y1, x2, y2, x3, y3, K
  3266.     ftri x3, y3, x4, y4, x1, y1, K
  3267. End Sub ' fquad
  3268.  
  3269. ' /////////////////////////////////////////////////////////////////////////////
  3270. ' DRAW A 2-D BOX (SOLID)
  3271. ' https://www.qb64.org/wiki/LINE
  3272.  
  3273. 'SUB DrawBox (iX%, iY%, iSize%, iColor%)
  3274. Sub DrawBox (iX%, iY%, iSize%, iColor~&)
  3275.     Line (iX%, iY%)-(iX% + iSize%, iY% + iSize%), iColor~&, BF ' Draw a solid box
  3276.     'LINE (iX%, iY%)-(iX% + iSize%, iY% + iSize%), iColor%, BF ' Draw a solid box
  3277.     'LINE (60, 60)-(130, 100), iColor%, B ' Draw a box outline
  3278. End Sub ' DrawBox
  3279.  
  3280. ' /////////////////////////////////////////////////////////////////////////////
  3281. ' DRAW A 2-D BOX (OUTLINE)
  3282. ' https://www.qb64.org/wiki/LINE
  3283.  
  3284. ' The style parameter 0-255 doesn't seemt to have a solid line?
  3285.  
  3286. 'SUB DrawStyledOutlineBox (iX%, iY%, iSize%, iColor%, iStyle%)
  3287. Sub DrawStyledOutlineBox (iX%, iY%, iSize%, iColor~&, iStyle%)
  3288.     ' LINE [STEP] [(column1, row1)]-[STEP] (column2, row2), color[, [{B|BF}], style%]
  3289.     ' B creates a box outline with each side parallel to the program screen sides. BF creates a filled box.
  3290.     ' The style% signed INTEGER value sets a dotted pattern to draw the line or rectangle outline.
  3291.  
  3292.     Line (iX%, iY%)-(iX% + iSize%, iY% + iSize%), iColor~&, B , iStyle%
  3293. End Sub ' DrawStyledOutlineBox
  3294.  
  3295. ' /////////////////////////////////////////////////////////////////////////////
  3296. ' DRAW A 2-D BOX (OUTLINE) WITH A SOLID LINE
  3297.  
  3298. Sub DrawOutlineBox (iX%, iY%, iSize2%, iColor~&, iWeight2%)
  3299.     Dim iFromX%
  3300.     Dim iFromY%
  3301.     Dim iToX%
  3302.     Dim iToY%
  3303.     iSize% = iSize2% - 1
  3304.     iWeight% = iWeight2% - 1
  3305.     If iWeight% = 0 Then
  3306.         ' TOP LINE
  3307.         iFromX% = iX%
  3308.         iFromY% = iY%
  3309.         iToX% = iX% + iSize%
  3310.         iToY% = iY%
  3311.         Line (iFromX%, iFromY%)-(iToX%, iToY%), iColor~&, BF
  3312.  
  3313.         ' BOTTOM LINE
  3314.         iFromX% = iX%
  3315.         iFromY% = iY% + iSize%
  3316.         iToX% = iX% + iSize%
  3317.         iToY% = iY% + iSize%
  3318.         Line (iFromX%, iFromY%)-(iToX%, iToY%), iColor~&, BF
  3319.  
  3320.         ' LEFT LINE
  3321.         iFromX% = iX%
  3322.         iFromY% = iY%
  3323.         iToX% = iX%
  3324.         iToY% = iY% + iSize%
  3325.         Line (iFromX%, iFromY%)-(iToX%, iToY%), iColor~&, BF
  3326.  
  3327.         ' RIGHT LINE
  3328.         iFromX% = iX% + iSize%
  3329.         iFromY% = iY%
  3330.         iToX% = iX% + iSize%
  3331.         iToY% = iY% + iSize%
  3332.         Line (iFromX%, iFromY%)-(iToX%, iToY%), iColor~&, BF
  3333.     ElseIf iWeight% > 0 Then
  3334.         ' TOP LINE
  3335.         For iFromY% = iY% To (iY% + iWeight%)
  3336.             iFromX% = iX%
  3337.             'iFromY% = iY%
  3338.             iToX% = iX% + iSize%
  3339.             iToY% = iFromY%
  3340.             Line (iFromX%, iFromY%)-(iToX%, iToY%), iColor~&, BF
  3341.         Next iFromY%
  3342.  
  3343.         ' BOTTOM LINE
  3344.         For iFromY% = ((iY% + iSize%) - iWeight%) To (iY% + iSize%)
  3345.             iFromX% = iX%
  3346.             'iFromY% = iY% + iSize%
  3347.             iToX% = iX% + iSize%
  3348.             iToY% = iFromY%
  3349.             Line (iFromX%, iFromY%)-(iToX%, iToY%), iColor~&, BF
  3350.         Next iFromY%
  3351.  
  3352.         ' LEFT LINE
  3353.         For iFromX% = iX% To (iX% + iWeight%)
  3354.             'iFromX% = iX%
  3355.             iFromY% = iY%
  3356.             iToX% = iFromX%
  3357.             iToY% = iY% + iSize%
  3358.             Line (iFromX%, iFromY%)-(iToX%, iToY%), iColor~&, BF
  3359.         Next iFromX%
  3360.  
  3361.         ' RIGHT LINE
  3362.         For iFromX% = ((iX% + iSize%) - iWeight%) To (iX% + iSize%)
  3363.             'iFromX% = iX% + iSize%
  3364.             iFromY% = iY%
  3365.             iToX% = iFromX%
  3366.             iToY% = iY% + iSize%
  3367.             Line (iFromX%, iFromY%)-(iToX%, iToY%), iColor~&, BF
  3368.         Next iFromX%
  3369.     End If
  3370. End Sub ' DrawOutlineBox
  3371.  
  3372. ' /////////////////////////////////////////////////////////////////////////////
  3373.  
  3374. Function GetPaletteFromColor% (iColor~&)
  3375.     Select Case iColor~&
  3376.         Case cEmpty:
  3377.             GetPaletteFromColor% = 0
  3378.         Case cBlack:
  3379.             GetPaletteFromColor% = 1
  3380.         Case cDarkGray:
  3381.             GetPaletteFromColor% = 2
  3382.         Case cDimGray:
  3383.             GetPaletteFromColor% = 3
  3384.         Case cGray:
  3385.             GetPaletteFromColor% = 4
  3386.         Case cLightGray:
  3387.             GetPaletteFromColor% = 5
  3388.         Case cSilver:
  3389.             GetPaletteFromColor% = 6
  3390.         Case cWhite:
  3391.             GetPaletteFromColor% = 7
  3392.         Case cRed:
  3393.             GetPaletteFromColor% = 8
  3394.         Case cOrangeRed:
  3395.             GetPaletteFromColor% = 9
  3396.         Case cDarkOrange:
  3397.             GetPaletteFromColor% = 10
  3398.         Case cOrange:
  3399.             GetPaletteFromColor% = 11
  3400.         Case cGold:
  3401.             GetPaletteFromColor% = 12
  3402.         Case cYellow:
  3403.             GetPaletteFromColor% = 13
  3404.         Case cOliveDrab1:
  3405.             GetPaletteFromColor% = 14
  3406.         Case cLime:
  3407.             GetPaletteFromColor% = 15
  3408.         Case cMediumSpringGreen:
  3409.             GetPaletteFromColor% = 16
  3410.         Case cCyan:
  3411.             GetPaletteFromColor% = 17
  3412.         Case cDeepSkyBlue:
  3413.             GetPaletteFromColor% = 18
  3414.         Case cDodgerBlue:
  3415.             GetPaletteFromColor% = 19
  3416.         Case cSeaBlue:
  3417.             GetPaletteFromColor% = 20
  3418.         Case cBlue:
  3419.             GetPaletteFromColor% = 21
  3420.         Case cBluePurple:
  3421.             GetPaletteFromColor% = 22
  3422.         Case cDeepPurple:
  3423.             GetPaletteFromColor% = 23
  3424.         Case cPurple:
  3425.             GetPaletteFromColor% = 24
  3426.         Case cPurpleRed:
  3427.             GetPaletteFromColor% = 25
  3428.         Case Else:
  3429.             GetPaletteFromColor% = 0
  3430.     End Select
  3431. End Function ' GetPaletteFromColor%
  3432.  
  3433. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3434. ' END GRAPHICS FUNCTIONS
  3435. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3436.  
  3437. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3438. ' BEGIN GENERAL PURPOSE ROUTINES
  3439. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3440.  
  3441. ' /////////////////////////////////////////////////////////////////////////////
  3442. ' Convert a value to string and trim it (because normal Str$ adds spaces)
  3443.  
  3444. Function cstr$ (myValue)
  3445.     'cstr$ = LTRIM$(RTRIM$(STR$(myValue)))
  3446.     cstr$ = _Trim$(Str$(myValue))
  3447. End Function ' cstr$
  3448.  
  3449. ' /////////////////////////////////////////////////////////////////////////////
  3450. ' Convert a Long value to string and trim it (because normal Str$ adds spaces)
  3451.  
  3452. Function cstrl$ (myValue As Long)
  3453.     cstrl$ = _Trim$(Str$(myValue))
  3454. End Function ' cstrl$
  3455.  
  3456. ' /////////////////////////////////////////////////////////////////////////////
  3457. ' Convert a Single value to string and trim it (because normal Str$ adds spaces)
  3458.  
  3459. Function cstrs$ (myValue As Single)
  3460.     ''cstr$ = LTRIM$(RTRIM$(STR$(myValue)))
  3461.     cstrs$ = _Trim$(Str$(myValue))
  3462. End Function ' cstrs$
  3463.  
  3464. ' /////////////////////////////////////////////////////////////////////////////
  3465. ' Convert an unsigned Long value to string and trim it (because normal Str$ adds spaces)
  3466.  
  3467. Function cstrul$ (myValue As _Unsigned Long)
  3468.     cstrul$ = _Trim$(Str$(myValue))
  3469. End Function ' cstrul$
  3470.  
  3471. ' /////////////////////////////////////////////////////////////////////////////
  3472. ' based on code from:
  3473. ' Qbasic Programs - Download free bas source code
  3474. ' http://www.thedubber.altervista.org/qbsrc.htm
  3475.  
  3476. Sub DrawTextLine (x%, y%, x2%, y2%, c$)
  3477.     'bError% = FALSE
  3478.     'LOCATE 2, 2: PRINT "(" + STR$(x%) + "," + STR$(y%) + ") to (" + STR$(x2%) + "," + STR$(y2%) + ") of " + CHR$(34) + c$ + CHR$(34);
  3479.  
  3480.     i% = 0
  3481.     steep% = 0
  3482.     e1% = 0
  3483.     If (x2% - x%) > 0 Then sx% = 1: Else sx% = -1
  3484.     dx% = Abs(x2% - x%)
  3485.     If (y2% - y%) > 0 Then sy% = 1: Else sy% = -1
  3486.     dy% = Abs(y2% - y%)
  3487.     If (dy% > dx%) Then
  3488.         steep% = 1
  3489.         Swap x%, y%
  3490.         Swap dx%, dy%
  3491.         Swap sx%, sy%
  3492.     End If
  3493.     e1% = 2 * dy% - dx%
  3494.     For i% = 0 To dx% - 1
  3495.         If steep% = 1 Then
  3496.             'PSET (y%, x%), c%:
  3497.             Locate y%, x%
  3498.             Print c$;
  3499.         Else
  3500.             'PSET (x%, y%), c%
  3501.             Locate x%, y%
  3502.             Print c$;
  3503.         End If
  3504.  
  3505.         While E% >= 0
  3506.             y% = y% + sy%: e1% = e1% - 2 * dx%
  3507.         Wend
  3508.         x% = x% + sx%: e1% = e1% + 2 * dy%
  3509.     Next
  3510.     'PSET (x2%, y2%), c%
  3511.     Locate x2%, y2%
  3512.     Print c$;
  3513.  
  3514. End Sub ' DrawTextLine
  3515.  
  3516. ' /////////////////////////////////////////////////////////////////////////////
  3517. ' From: Bitwise Manipulations By Steven Roman
  3518. ' http://www.romanpress.com/Articles/Bitwise_R/Bitwise.htm
  3519.  
  3520. ' Returns the 8-bit binary representation
  3521. ' of an integer iInput where 0 <= iInput <= 255
  3522.  
  3523. Function GetBinary$ (iInput1 As Integer)
  3524.     Dim sResult As String
  3525.     Dim iLoop As Integer
  3526.     Dim iInput As Integer: iInput = iInput1
  3527.  
  3528.     sResult = ""
  3529.  
  3530.     If iInput >= 0 And iInput <= 255 Then
  3531.         For iLoop = 1 To 8
  3532.             sResult = LTrim$(RTrim$(Str$(iInput Mod 2))) + sResult
  3533.             iInput = iInput \ 2
  3534.             'If iLoop = 4 Then sResult = " " + sResult
  3535.         Next iLoop
  3536.     End If
  3537.  
  3538.     GetBinary$ = sResult
  3539. End Function ' GetBinary$
  3540.  
  3541. ' /////////////////////////////////////////////////////////////////////////////
  3542. ' wonderfully inefficient way to read if a bit is set
  3543. ' ival = GetBit256%(int we are comparing, int containing the bits we want to read)
  3544.  
  3545. ' See also: GetBit256%, SetBit256%
  3546.  
  3547. Function GetBit256% (iNum1 As Integer, iBit1 As Integer)
  3548.     Dim iResult As Integer
  3549.     Dim sNum As String
  3550.     Dim sBit As String
  3551.     Dim iLoop As Integer
  3552.     Dim bContinue As Integer
  3553.     'DIM iTemp AS INTEGER
  3554.     Dim iNum As Integer: iNum = iNum1
  3555.     Dim iBit As Integer: iBit = iBit1
  3556.  
  3557.     iResult = FALSE
  3558.     bContinue = TRUE
  3559.  
  3560.     If iNum < 256 And iBit <= 128 Then
  3561.         sNum = GetBinary$(iNum)
  3562.         sBit = GetBinary$(iBit)
  3563.         For iLoop = 1 To 8
  3564.             If Mid$(sBit, iLoop, 1) = "1" Then
  3565.                 'if any of the bits in iBit are false, return false
  3566.                 If Mid$(sNum, iLoop, 1) = "0" Then
  3567.                     iResult = FALSE
  3568.                     bContinue = FALSE
  3569.                     Exit For
  3570.                 End If
  3571.             End If
  3572.         Next iLoop
  3573.         If bContinue = TRUE Then
  3574.             iResult = TRUE
  3575.         End If
  3576.     End If
  3577.  
  3578.     GetBit256% = iResult
  3579. End Function ' GetBit256%
  3580.  
  3581. ' /////////////////////////////////////////////////////////////////////////////
  3582. ' From: Bitwise Manipulations By Steven Roman
  3583. ' http://www.romanpress.com/Articles/Bitwise_R/Bitwise.htm
  3584.  
  3585. ' Returns the integer that corresponds to a binary string of length 8
  3586.  
  3587. Function GetIntegerFromBinary% (sBinary1 As String)
  3588.     Dim iResult As Integer
  3589.     Dim iLoop As Integer
  3590.     Dim strBinary As String
  3591.     Dim sBinary As String: sBinary = sBinary1
  3592.  
  3593.     iResult = 0
  3594.     strBinary = Replace$(sBinary, " ", "") ' Remove any spaces
  3595.     For iLoop = 0 To Len(strBinary) - 1
  3596.         iResult = iResult + 2 ^ iLoop * Val(Mid$(strBinary, Len(strBinary) - iLoop, 1))
  3597.     Next iLoop
  3598.  
  3599.     GetIntegerFromBinary% = iResult
  3600. End Function ' GetIntegerFromBinary%
  3601.  
  3602. ' /////////////////////////////////////////////////////////////////////////////
  3603.  
  3604. Function IIF (Condition, IfTrue, IfFalse)
  3605.     If Condition Then IIF = IfTrue Else IIF = IfFalse
  3606.  
  3607. ' /////////////////////////////////////////////////////////////////////////////
  3608.  
  3609. Function IIFSTR$ (Condition, IfTrue$, IfFalse$)
  3610.     If Condition Then IIFSTR$ = IfTrue$ Else IIFSTR$ = IfFalse$
  3611.  
  3612. ' /////////////////////////////////////////////////////////////////////////////
  3613. ' https://slaystudy.com/qbasic-program-to-check-if-number-is-even-or-odd/
  3614.  
  3615. Function IsEven% (n)
  3616.     If n Mod 2 = 0 Then
  3617.         IsEven% = TRUE
  3618.     Else
  3619.         IsEven% = FALSE
  3620.     End If
  3621. End Function ' IsEven%
  3622.  
  3623. ' /////////////////////////////////////////////////////////////////////////////
  3624. ' https://slaystudy.com/qbasic-program-to-check-if-number-is-even-or-odd/
  3625.  
  3626. Function IsOdd% (n)
  3627.     If n Mod 2 = 1 Then
  3628.         IsOdd% = TRUE
  3629.     Else
  3630.         IsOdd% = FALSE
  3631.     End If
  3632. End Function ' IsOdd%
  3633.  
  3634. ' /////////////////////////////////////////////////////////////////////////////
  3635. ' By sMcNeill from https://www.qb64.org/forum/index.php?topic=896.0
  3636.  
  3637. Function IsNum% (text$)
  3638.     Dim a$
  3639.     Dim b$
  3640.     a$ = _Trim$(text$)
  3641.     b$ = _Trim$(Str$(Val(text$)))
  3642.     If a$ = b$ Then
  3643.         IsNum% = TRUE
  3644.     Else
  3645.         IsNum% = FALSE
  3646.     End If
  3647. End Function ' IsNum%
  3648.  
  3649. ' /////////////////////////////////////////////////////////////////////////////
  3650. ' Re: Does a Is Number function exist in QB64?
  3651. ' https://www.qb64.org/forum/index.php?topic=896.15
  3652.  
  3653. ' MWheatley
  3654. ' « Reply #18 on: January 01, 2019, 11:24:30 AM »
  3655.  
  3656. ' returns 1 if string is an integer, 0 if not
  3657. Function IsNumber (text$)
  3658.     Dim i As Integer
  3659.  
  3660.     IsNumber = 1
  3661.     For i = 1 To Len(text$)
  3662.         If Asc(Mid$(text$, i, 1)) < 45 Or Asc(Mid$(text$, i, 1)) >= 58 Then
  3663.             IsNumber = 0
  3664.             Exit For
  3665.         ElseIf Asc(Mid$(text$, i, 1)) = 47 Then
  3666.             IsNumber = 0
  3667.             Exit For
  3668.         End If
  3669.     Next i
  3670. End Function ' IsNumber
  3671.  
  3672. ' /////////////////////////////////////////////////////////////////////////////
  3673. ' Split and join strings
  3674. ' https://www.qb64.org/forum/index.php?topic=1073.0
  3675.  
  3676. 'Combine all elements of in$() into a single string with delimiter$ separating the elements.
  3677.  
  3678. Function join$ (in$(), delimiter$)
  3679.     Dim result$
  3680.     Dim i As Long
  3681.     result$ = in$(LBound(in$))
  3682.     For i = LBound(in$) + 1 To UBound(in$)
  3683.         result$ = result$ + delimiter$ + in$(i)
  3684.     Next i
  3685.     join$ = result$
  3686. End Function ' join$
  3687.  
  3688. ' /////////////////////////////////////////////////////////////////////////////
  3689. ' ABS was returning strange values with type LONG
  3690. ' so I created this which does not.
  3691.  
  3692. Function LongABS& (lngValue As Long)
  3693.     If Sgn(lngValue) = -1 Then
  3694.         LongABS& = 0 - lngValue
  3695.     Else
  3696.         LongABS& = lngValue
  3697.     End If
  3698. End Function ' LongABS&
  3699.  
  3700. ' /////////////////////////////////////////////////////////////////////////////
  3701. ' Writes sText to a debug file in the EXE folder.
  3702. ' Debug file is named the same thing as the program EXE name with ".txt" at the end.
  3703. ' For example the program "C:\QB64\MyProgram.BAS" running as
  3704. ' "C:\QB64\MyProgram.EXE" would have an output file "C:\QB64\MyProgram.EXE.txt".
  3705. ' If the file doesn't exist, it is created, otherwise it is appended to.
  3706.  
  3707. Sub PrintDebugFile (sText As String)
  3708.     Dim sFileName As String
  3709.     Dim sError As String
  3710.     Dim sOut As String
  3711.  
  3712.     sFileName = ProgramPath$ + ProgramName$ + ".txt"
  3713.     sError = ""
  3714.     If _FileExists(sFileName) = FALSE Then
  3715.         sOut = ""
  3716.         sOut = sOut + "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" + Chr$(13) + Chr$(10)
  3717.         sOut = sOut + "PROGRAM : " + ProgramName$ + Chr$(13) + Chr$(10)
  3718.         sOut = sOut + "RUN DATE: " + CurrentDateTime$ + Chr$(13) + Chr$(10)
  3719.         sOut = sOut + "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" + Chr$(13) + Chr$(10)
  3720.         sError = PrintFile$(sFileName, sOut, FALSE)
  3721.     End If
  3722.     If Len(sError) = 0 Then
  3723.         sError = PrintFile$(sFileName, sText, TRUE)
  3724.     End If
  3725.     If Len(sError) <> 0 Then
  3726.         Print CurrentDateTime$ + " PrintDebugFile FAILED: " + sError
  3727.     End If
  3728. End Sub ' PrintDebugFile
  3729.  
  3730. ' /////////////////////////////////////////////////////////////////////////////
  3731. ' Returns blank if successful else returns error message.
  3732.  
  3733. Function PrintFile$ (sFileName As String, sText As String, bAppend As Integer)
  3734.     'x = 1: y = 2: z$ = "Three"
  3735.  
  3736.     Dim sError As String: sError = ""
  3737.  
  3738.     If Len(sError) = 0 Then
  3739.         If (bAppend = TRUE) Then
  3740.             If _FileExists(sFileName) Then
  3741.                 Open sFileName For Append As #1 ' opens an existing file for appending
  3742.             Else
  3743.                 sError = "Error in PrintFile$ : File not found. Cannot append."
  3744.             End If
  3745.         Else
  3746.             Open sFileName For Output As #1 ' opens and clears an existing file or creates new empty file
  3747.         End If
  3748.     End If
  3749.     If Len(sError) = 0 Then
  3750.         ' WRITE places text in quotes in the file
  3751.         'WRITE #1, x, y, z$
  3752.         'WRITE #1, sText
  3753.  
  3754.         ' PRINT does not put text inside quotes
  3755.         Print #1, sText
  3756.  
  3757.         Close #1
  3758.  
  3759.         'PRINT "File created with data. Press a key!"
  3760.         'K$ = INPUT$(1) 'press a key
  3761.  
  3762.         'OPEN sFileName FOR INPUT AS #2 ' opens a file to read it
  3763.         'INPUT #2, a, b, c$
  3764.         'CLOSE #2
  3765.  
  3766.         'PRINT a, b, c$
  3767.         'WRITE a, b, c$
  3768.     End If
  3769.  
  3770.     PrintFile$ = sError
  3771. End Function ' PrintFile$
  3772.  
  3773. ' /////////////////////////////////////////////////////////////////////////////
  3774. ' iNum% = PromptForIntegerInRange%("Please type a number between {min} and {max} (or blank to quit).", 1, 4, 0)
  3775.  
  3776. Function PromptForIntegerInRange% (sPrompt$, iMin%, iMax%, iDefault%)
  3777.     Dim iValue%
  3778.     Dim bFinished%
  3779.     Dim sPrompt1$
  3780.     Dim in$
  3781.  
  3782.     If Len(sPrompt$) > 0 Then
  3783.         sPrompt1$ = sPrompt$
  3784.     Else
  3785.         sPrompt1$ = "Please type a number between {min} and {max} (or blank to quit)."
  3786.     End If
  3787.  
  3788.     sPrompt1$ = Replace$(sPrompt1$, "{min}", cstr$(iMin%))
  3789.     sPrompt1$ = Replace$(sPrompt1$, "{max}", cstr$(iMax%))
  3790.  
  3791.     bFinished% = FALSE
  3792.     Do
  3793.         Print sPrompt1$
  3794.  
  3795.         Input in$
  3796.         in$ = _Trim$(in$)
  3797.         If Len(in$) > 0 Then
  3798.             If IsNumber(in$) Then
  3799.                 iValue% = Val(in$)
  3800.                 If iValue% >= iMin% And iValue% <= iMax% Then
  3801.                     'bFinished% = TRUE
  3802.                     Exit Do
  3803.                 Else
  3804.                     Print "Number out of range."
  3805.                     Print
  3806.                 End If
  3807.             Else
  3808.                 Print "Not a valid number."
  3809.                 Print
  3810.             End If
  3811.         Else
  3812.             iValue% = iDefault%
  3813.             Exit Do
  3814.             'bFinished% = TRUE
  3815.         End If
  3816.     Loop Until bFinished% = TRUE
  3817.  
  3818.     PromptForIntegerInRange% = iValue%
  3819. End Function ' PromptForIntegerInRange%
  3820.  
  3821. ' /////////////////////////////////////////////////////////////////////////////
  3822. ' iNum& = PromptForLongInRange&("Please type a number between {min} and {max} (or blank to quit).", 1, 4, 0)
  3823.  
  3824. Function PromptForLongInRange& (sPrompt$, iMin&, iMax&, iDefault&)
  3825.     Dim iValue&
  3826.     Dim bFinished&
  3827.     Dim sPrompt1$
  3828.     Dim in$
  3829.  
  3830.     bFinished& = FALSE
  3831.     Do
  3832.         If Len(sPrompt$) > 0 Then
  3833.             sPrompt1$ = sPrompt$
  3834.         Else
  3835.             sPrompt1$ = "Please type a number between {min} and {max} (or blank to quit)."
  3836.         End If
  3837.  
  3838.         sPrompt1$ = Replace$(sPrompt1$, "{min}", cstrl$(iMin&))
  3839.         sPrompt1$ = Replace$(sPrompt1$, "{max}", cstrl$(iMax&))
  3840.  
  3841.         Input in$
  3842.         in$ = _Trim$(in$)
  3843.         If Len(in$) > 0 Then
  3844.             If IsNumber(in$) Then
  3845.                 iValue& = Val(in$)
  3846.                 If iValue& >= iMin& And iValue& <= iMax& Then
  3847.                     bFinished& = TRUE
  3848.                 Else
  3849.                     Print "Number out of range."
  3850.                     Print
  3851.                 End If
  3852.             Else
  3853.                 Print "Not a valid number."
  3854.                 Print
  3855.             End If
  3856.         Else
  3857.             iValue& = iDefault&
  3858.             bFinished& = TRUE
  3859.         End If
  3860.     Loop Until bFinished&
  3861.  
  3862.     PromptForLongInRange& = iValue&
  3863. End Function ' PromptForLongInRange&
  3864.  
  3865. ' /////////////////////////////////////////////////////////////////////////////
  3866. ' Generate random value between Min and Max.
  3867. Function RandomNumber% (Min%, Max%)
  3868.     Dim NumSpread%
  3869.  
  3870.     ' SET RANDOM SEED
  3871.     'Randomize ' Initialize random-number generator.
  3872.  
  3873.     ' GET RANDOM # Min%-Max%
  3874.     'RandomNumber = Int((Max * Rnd) + Min) ' generate number
  3875.  
  3876.     NumSpread% = (Max% - Min%) + 1
  3877.  
  3878.     RandomNumber% = Int(Rnd * NumSpread%) + Min% ' GET RANDOM # BETWEEN Max% AND Min%
  3879.  
  3880. End Function ' RandomNumber%
  3881.  
  3882. ' /////////////////////////////////////////////////////////////////////////////
  3883.  
  3884. Sub RandomNumberTest
  3885.     Dim iCols As Integer: iCols = 10
  3886.     Dim iRows As Integer: iRows = 20
  3887.     Dim iLoop As Integer
  3888.     Dim iX As Integer
  3889.     Dim iY As Integer
  3890.     Dim sError As String
  3891.     Dim sFileName As String
  3892.     Dim sText As String
  3893.     Dim bAppend As Integer
  3894.     Dim iMin As Integer
  3895.     Dim iMax As Integer
  3896.     Dim iNum As Integer
  3897.     Dim iErrorCount As Integer
  3898.     Dim sInput$
  3899.  
  3900.     sFileName = "c:\temp\maze_test_1.txt"
  3901.     sText = "Count" + Chr$(9) + "Min" + Chr$(9) + "Max" + Chr$(9) + "Random"
  3902.     bAppend = FALSE
  3903.     sError = PrintFile$(sFileName, sText, bAppend)
  3904.     If Len(sError) = 0 Then
  3905.         bAppend = TRUE
  3906.         iErrorCount = 0
  3907.  
  3908.         iMin = 0
  3909.         iMax = iCols - 1
  3910.         For iLoop = 1 To 100
  3911.             iNum = RandomNumber%(iMin, iMax)
  3912.             sText = Str$(iLoop) + Chr$(9) + Str$(iMin) + Chr$(9) + Str$(iMax) + Chr$(9) + Str$(iNum)
  3913.             sError = PrintFile$(sFileName, sText, bAppend)
  3914.             If Len(sError) > 0 Then
  3915.                 iErrorCount = iErrorCount + 1
  3916.                 Print Str$(iLoop) + ". ERROR"
  3917.                 Print "    " + "iMin=" + Str$(iMin)
  3918.                 Print "    " + "iMax=" + Str$(iMax)
  3919.                 Print "    " + "iNum=" + Str$(iNum)
  3920.                 Print "    " + "Could not write to file " + Chr$(34) + sFileName + Chr$(34) + "."
  3921.                 Print "    " + sError
  3922.             End If
  3923.         Next iLoop
  3924.  
  3925.         iMin = 0
  3926.         iMax = iRows - 1
  3927.         For iLoop = 1 To 100
  3928.             iNum = RandomNumber%(iMin, iMax)
  3929.             sText = Str$(iLoop) + Chr$(9) + Str$(iMin) + Chr$(9) + Str$(iMax) + Chr$(9) + Str$(iNum)
  3930.             sError = PrintFile$(sFileName, sText, bAppend)
  3931.             If Len(sError) > 0 Then
  3932.                 iErrorCount = iErrorCount + 1
  3933.                 Print Str$(iLoop) + ". ERROR"
  3934.                 Print "    " + "iMin=" + Str$(iMin)
  3935.                 Print "    " + "iMax=" + Str$(iMax)
  3936.                 Print "    " + "iNum=" + Str$(iNum)
  3937.                 Print "    " + "Could not write to file " + Chr$(34) + sFileName + Chr$(34) + "."
  3938.                 Print "    " + sError
  3939.             End If
  3940.         Next iLoop
  3941.  
  3942.         Print "Finished generating numbers. Errors: " + Str$(iErrorCount)
  3943.     Else
  3944.         Print "Error creating file " + Chr$(34) + sFileName + Chr$(34) + "."
  3945.         Print sError
  3946.     End If
  3947.  
  3948.     Input "Press <ENTER> to continue", sInput$
  3949. End Sub ' RandomNumberTest
  3950.  
  3951. ' /////////////////////////////////////////////////////////////////////////////
  3952. ' FROM: String Manipulation
  3953. ' found at abandoned, outdated and now likely malicious qb64 dot net website
  3954. ' http://www.qb64.[net]/forum/index_topic_5964-0/
  3955. '
  3956. 'SUMMARY:
  3957. '   Purpose:  A library of custom functions that transform strings.
  3958. '   Author:   Dustinian Camburides (dustinian@gmail.com)
  3959. '   Platform: QB64 (www.qb64.org)
  3960. '   Revision: 1.6
  3961. '   Updated:  5/28/2012
  3962.  
  3963. 'SUMMARY:
  3964. '[Replace$] replaces all instances of the [Find] sub-string with the [Add] sub-string within the [Text] string.
  3965. 'INPUT:
  3966. 'Text: The input string; the text that's being manipulated.
  3967. 'Find: The specified sub-string; the string sought within the [Text] string.
  3968. 'Add: The sub-string that's being added to the [Text] string.
  3969.  
  3970. Function Replace$ (Text1 As String, Find1 As String, Add1 As String)
  3971.     ' VARIABLES:
  3972.     Dim Text2 As String
  3973.     Dim Find2 As String
  3974.     Dim Add2 As String
  3975.     Dim lngLocation As Long ' The address of the [Find] substring within the [Text] string.
  3976.     Dim strBefore As String ' The characters before the string to be replaced.
  3977.     Dim strAfter As String ' The characters after the string to be replaced.
  3978.  
  3979.     ' INITIALIZE:
  3980.     ' MAKE COPIESSO THE ORIGINAL IS NOT MODIFIED (LIKE ByVal IN VBA)
  3981.     Text2 = Text1
  3982.     Find2 = Find1
  3983.     Add2 = Add1
  3984.  
  3985.     lngLocation = InStr(1, Text2, Find2)
  3986.  
  3987.     ' PROCESSING:
  3988.     ' While [Find2] appears in [Text2]...
  3989.     While lngLocation
  3990.         ' Extract all Text2 before the [Find2] substring:
  3991.         strBefore = Left$(Text2, lngLocation - 1)
  3992.  
  3993.         ' Extract all text after the [Find2] substring:
  3994.         strAfter = Right$(Text2, ((Len(Text2) - (lngLocation + Len(Find2) - 1))))
  3995.  
  3996.         ' Return the substring:
  3997.         Text2 = strBefore + Add2 + strAfter
  3998.  
  3999.         ' Locate the next instance of [Find2]:
  4000.         lngLocation = InStr(1, Text2, Find2)
  4001.  
  4002.         ' Next instance of [Find2]...
  4003.     Wend
  4004.  
  4005.     ' OUTPUT:
  4006.     Replace$ = Text2
  4007. End Function ' Replace$
  4008.  
  4009. ' /////////////////////////////////////////////////////////////////////////////
  4010.  
  4011. Sub ReplaceTest
  4012.     Dim in$
  4013.  
  4014.     Print "-------------------------------------------------------------------------------"
  4015.     Print "ReplaceTest"
  4016.     Print
  4017.  
  4018.     Print "Original value"
  4019.     in$ = "Thiz iz a teZt."
  4020.     Print "in$ = " + Chr$(34) + in$ + Chr$(34)
  4021.     Print
  4022.  
  4023.     Print "Replacing lowercase " + Chr$(34) + "z" + Chr$(34) + " with " + Chr$(34) + "s" + Chr$(34) + "..."
  4024.     in$ = Replace$(in$, "z", "s")
  4025.     Print "in$ = " + Chr$(34) + in$ + Chr$(34)
  4026.     Print
  4027.  
  4028.     Print "Replacing uppercase " + Chr$(34) + "Z" + Chr$(34) + " with " + Chr$(34) + "s" + Chr$(34) + "..."
  4029.     in$ = Replace$(in$, "Z", "s")
  4030.     Print "in$ = " + Chr$(34) + in$ + Chr$(34)
  4031.     Print
  4032.  
  4033.     Print "ReplaceTest finished."
  4034. End Sub ' ReplaceTest
  4035.  
  4036. ' /////////////////////////////////////////////////////////////////////////////
  4037. ' fantastically inefficient way to set a bit
  4038.  
  4039. ' example use: arrMaze(iX, iY) = SetBit256%(arrMaze(iX, iY), cS, FALSE)
  4040.  
  4041. ' See also: GetBit256%, SetBit256%
  4042.  
  4043. ' newint=SetBit256%(oldint, int containing the bits we want to set, value to set them to)
  4044. Function SetBit256% (iNum1 As Integer, iBit1 As Integer, bVal1 As Integer)
  4045.     Dim sNum As String
  4046.     Dim sBit As String
  4047.     Dim sVal As String
  4048.     Dim iLoop As Integer
  4049.     Dim strResult As String
  4050.     Dim iResult As Integer
  4051.     Dim iNum As Integer: iNum = iNum1
  4052.     Dim iBit As Integer: iBit = iBit1
  4053.     Dim bVal As Integer: bVal = bVal1
  4054.  
  4055.     If iNum < 256 And iBit <= 128 Then
  4056.         sNum = GetBinary$(iNum)
  4057.         sBit = GetBinary$(iBit)
  4058.         If bVal = TRUE Then
  4059.             sVal = "1"
  4060.         Else
  4061.             sVal = "0"
  4062.         End If
  4063.         strResult = ""
  4064.         For iLoop = 1 To 8
  4065.             If Mid$(sBit, iLoop, 1) = "1" Then
  4066.                 strResult = strResult + sVal
  4067.             Else
  4068.                 strResult = strResult + Mid$(sNum, iLoop, 1)
  4069.             End If
  4070.         Next iLoop
  4071.         iResult = GetIntegerFromBinary%(strResult)
  4072.     Else
  4073.         iResult = iNum
  4074.     End If
  4075.  
  4076.     SetBit256% = iResult
  4077. End Function ' SetBit256%
  4078.  
  4079. ' /////////////////////////////////////////////////////////////////////////////
  4080. ' Split and join strings
  4081. ' https://www.qb64.org/forum/index.php?topic=1073.0
  4082. '
  4083. ' FROM luke, QB64 Developer
  4084. ' Date: February 15, 2019, 04:11:07 AM »
  4085. '
  4086. ' Given a string of words separated by spaces (or any other character),
  4087. ' splits it into an array of the words. I've no doubt many people have
  4088. ' written a version of this over the years and no doubt there's a million
  4089. ' ways to do it, but I thought I'd put mine here so we have at least one
  4090. ' version. There's also a join function that does the opposite
  4091. ' array -> single string.
  4092. '
  4093. ' Code is hopefully reasonably self explanatory with comments and a little demo.
  4094. ' Note, this is akin to Python/JavaScript split/join, PHP explode/implode.
  4095.  
  4096. 'Split in$ into pieces, chopping at every occurrence of delimiter$. Multiple consecutive occurrences
  4097. 'of delimiter$ are treated as a single instance. The chopped pieces are stored in result$().
  4098. '
  4099. 'delimiter$ must be one character long.
  4100. 'result$() must have been REDIMmed previously.
  4101.  
  4102. ' Modified to handle multi-character delimiters
  4103.  
  4104. Sub split (in$, delimiter$, result$())
  4105.     Dim start As Integer
  4106.     Dim finish As Integer
  4107.     Dim iDelimLen As Integer
  4108.     ReDim result$(-1)
  4109.  
  4110.     iDelimLen = Len(delimiter$)
  4111.  
  4112.     start = 1
  4113.     Do
  4114.         'While Mid$(in$, start, 1) = delimiter$
  4115.         While Mid$(in$, start, iDelimLen) = delimiter$
  4116.             'start = start + 1
  4117.             start = start + iDelimLen
  4118.             If start > Len(in$) Then
  4119.                 Exit Sub
  4120.             End If
  4121.         Wend
  4122.         finish = InStr(start, in$, delimiter$)
  4123.         If finish = 0 Then
  4124.             finish = Len(in$) + 1
  4125.         End If
  4126.  
  4127.         ReDim _Preserve result$(0 To UBound(result$) + 1)
  4128.  
  4129.         result$(UBound(result$)) = Mid$(in$, start, finish - start)
  4130.         start = finish + 1
  4131.     Loop While start <= Len(in$)
  4132. End Sub ' split
  4133.  
  4134. ' /////////////////////////////////////////////////////////////////////////////
  4135.  
  4136. Sub SplitTest
  4137.     Dim in$
  4138.     Dim delim$
  4139.     ReDim arrTest$(0)
  4140.     Dim iLoop%
  4141.  
  4142.     delim$ = Chr$(10)
  4143.     in$ = "this" + delim$ + "is" + delim$ + "a" + delim$ + "test"
  4144.     Print "in$ = " + Chr$(34) + in$ + Chr$(34)
  4145.     Print "delim$ = " + Chr$(34) + delim$ + Chr$(34)
  4146.     split in$, delim$, arrTest$()
  4147.  
  4148.     For iLoop% = LBound(arrTest$) To UBound(arrTest$)
  4149.         Print "arrTest$(" + LTrim$(RTrim$(Str$(iLoop%))) + ") = " + Chr$(34) + arrTest$(iLoop%) + Chr$(34)
  4150.     Next iLoop%
  4151.     Print
  4152.     Print "Split test finished."
  4153. End Sub ' SplitTest
  4154.  
  4155. ' /////////////////////////////////////////////////////////////////////////////
  4156.  
  4157. Sub SplitAndReplaceTest
  4158.     Dim in$
  4159.     Dim out$
  4160.     Dim iLoop%
  4161.     ReDim arrTest$(0)
  4162.  
  4163.     Print "-------------------------------------------------------------------------------"
  4164.     Print "SplitAndReplaceTest"
  4165.     Print
  4166.  
  4167.     Print "Original value"
  4168.     in$ = "This line 1 " + Chr$(13) + Chr$(10) + "and line 2" + Chr$(10) + "and line 3 " + Chr$(13) + "finally THE END."
  4169.     out$ = in$
  4170.     out$ = Replace$(out$, Chr$(13), "\r")
  4171.     out$ = Replace$(out$, Chr$(10), "\n")
  4172.     out$ = Replace$(out$, Chr$(9), "\t")
  4173.     Print "in$ = " + Chr$(34) + out$ + Chr$(34)
  4174.     Print
  4175.  
  4176.     Print "Fixing linebreaks..."
  4177.     in$ = Replace$(in$, Chr$(13) + Chr$(10), Chr$(13))
  4178.     in$ = Replace$(in$, Chr$(10), Chr$(13))
  4179.     out$ = in$
  4180.     out$ = Replace$(out$, Chr$(13), "\r")
  4181.     out$ = Replace$(out$, Chr$(10), "\n")
  4182.     out$ = Replace$(out$, Chr$(9), "\t")
  4183.     Print "in$ = " + Chr$(34) + out$ + Chr$(34)
  4184.     Print
  4185.  
  4186.     Print "Splitting up..."
  4187.     split in$, Chr$(13), arrTest$()
  4188.  
  4189.     For iLoop% = LBound(arrTest$) To UBound(arrTest$)
  4190.         out$ = arrTest$(iLoop%)
  4191.         out$ = Replace$(out$, Chr$(13), "\r")
  4192.         out$ = Replace$(out$, Chr$(10), "\n")
  4193.         out$ = Replace$(out$, Chr$(9), "\t")
  4194.         Print "arrTest$(" + cstr$(iLoop%) + ") = " + Chr$(34) + out$ + Chr$(34)
  4195.     Next iLoop%
  4196.     Print
  4197.  
  4198.     Print "SplitAndReplaceTest finished."
  4199. End Sub ' SplitAndReplaceTest
  4200.  
  4201. ' /////////////////////////////////////////////////////////////////////////////
  4202.  
  4203. Sub WaitForEnter
  4204.     Dim in$
  4205.     Input "Press <ENTER> to continue", in$
  4206. End Sub ' WaitForEnter
  4207.  
  4208. ' /////////////////////////////////////////////////////////////////////////////
  4209. ' WaitForKey "Press <ESC> to continue", 27, 0
  4210. ' WaitForKey "Press <ENTER> to begin;", 13, 0
  4211. ' waitforkey "", 65, 5
  4212.  
  4213. Sub WaitForKey (prompt$, KeyCode&, DelaySeconds%)
  4214.     ' SHOW PROMPT (IF SPECIFIED)
  4215.     If Len(prompt$) > 0 Then
  4216.         If Right$(prompt$, 1) <> ";" Then
  4217.             Print prompt$
  4218.         Else
  4219.             Print Right$(prompt$, Len(prompt$) - 1);
  4220.         End If
  4221.     End If
  4222.  
  4223.     ' WAIT FOR KEY
  4224.     Do: Loop Until _KeyDown(KeyCode&) ' leave loop when specified key pressed
  4225.  
  4226.     ' PAUSE AFTER (IF SPECIFIED)
  4227.     If DelaySeconds% < 1 Then
  4228.         _KeyClear: '_DELAY 1
  4229.     Else
  4230.         _KeyClear: _Delay DelaySeconds%
  4231.     End If
  4232. End Sub ' WaitForKey
  4233.  
  4234. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4235. ' END GENERAL PURPOSE ROUTINES
  4236. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4237.  
  4238. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4239. ' BEGIN COLOR ROUTINES
  4240. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4241.  
  4242. ' /////////////////////////////////////////////////////////////////////////////
  4243. ' Receives:
  4244. ' cycleColor = determines how foreColor, backColor are modified
  4245. ' foreColor  = the foreground color
  4246. ' backColor  = the background color (if needed)
  4247.  
  4248. ' /////////////////////////////////////////////////////////////////////////////
  4249. ' DoCycleColor colorScheme%, myColor~&
  4250.  
  4251. ' colorScheme = color scheme (value is alternated on subsequent calls)
  4252. ' myColor     = the current color (value is incremented/decremented on subsequent calls)
  4253.  
  4254. ' colorScheme values:
  4255. '  1 Rainbow6 #1
  4256. '  9 Rainbow6 #2
  4257. '  2 Rainbow18 #1
  4258. ' 10 Rainbow18 #2
  4259. '  3 Grayscale #1
  4260. ' 11 Grayscale #2
  4261. '  4 Grayscale #1
  4262. ' 12 Grayscale #2
  4263.  
  4264. Sub DoCycleColor (colorScheme As Integer, myColor As _Unsigned Long)
  4265.     ' ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  4266.     ' CYCLE FORE COLOR
  4267.  
  4268.     ' 1, 9 = simple rainbow
  4269.     If colorScheme = 1 Or colorScheme = 9 Then
  4270.         Select Case myColor
  4271.             Case cRed:
  4272.                 myColor = cOrange
  4273.             Case cOrange:
  4274.                 myColor = cYellow
  4275.             Case cYellow:
  4276.                 myColor = cGreen
  4277.             Case cGreen:
  4278.                 myColor = cBlue
  4279.             Case cBlue:
  4280.                 myColor = cPurple
  4281.             Case Else:
  4282.                 myColor = cRed
  4283.         End Select
  4284.  
  4285.         ' 2, 10 = complex rainbow
  4286.     ElseIf colorScheme = 2 Or colorScheme = 10 Then
  4287.         Select Case myColor
  4288.             Case cRed:
  4289.                 myColor = cOrangeRed
  4290.             Case cOrangeRed:
  4291.                 myColor = cDarkOrange
  4292.             Case cDarkOrange:
  4293.                 myColor = cOrange
  4294.             Case cOrange:
  4295.                 myColor = cGold
  4296.             Case cGold:
  4297.                 myColor = cYellow
  4298.             Case cYellow:
  4299.                 myColor = cOliveDrab1
  4300.             Case cOliveDrab1:
  4301.                 myColor = cLime
  4302.             Case cLime:
  4303.                 myColor = cMediumSpringGreen
  4304.             Case cMediumSpringGreen:
  4305.                 myColor = cCyan
  4306.             Case cCyan:
  4307.                 myColor = cDeepSkyBlue
  4308.             Case cDeepSkyBlue:
  4309.                 myColor = cDodgerBlue
  4310.             Case cDodgerBlue:
  4311.                 myColor = cSeaBlue
  4312.             Case cSeaBlue:
  4313.                 myColor = cBlue
  4314.             Case cBlue:
  4315.                 myColor = cBluePurple
  4316.             Case cBluePurple:
  4317.                 myColor = cDeepPurple
  4318.             Case cDeepPurple:
  4319.                 myColor = cPurple
  4320.             Case cPurple:
  4321.                 myColor = cPurpleRed
  4322.             Case Else:
  4323.                 myColor = cRed
  4324.         End Select
  4325.  
  4326.         ' 3, 11 = grayscale, ascending
  4327.     ElseIf colorScheme = 3 Or colorScheme = 11 Then
  4328.         Select Case myColor
  4329.             Case cBlack:
  4330.                 myColor = cDarkGray
  4331.             Case cDarkGray:
  4332.                 myColor = cDimGray
  4333.             Case cDimGray:
  4334.                 myColor = cGray
  4335.             Case cGray:
  4336.                 myColor = cLightGray
  4337.             Case cLightGray:
  4338.                 myColor = cSilver
  4339.             Case cSilver:
  4340.                 myColor = cWhite
  4341.             Case Else:
  4342.                 'myColor = cBlack
  4343.                 myColor = cSilver
  4344.  
  4345.                 ' go in the other direction!
  4346.                 If colorScheme = 3 Then
  4347.                     colorScheme = 4
  4348.                 Else
  4349.                     colorScheme = 12
  4350.                 End If
  4351.  
  4352.         End Select
  4353.  
  4354.         ' 4, 8, 12 = grayscale, descending
  4355.     ElseIf colorScheme = 4 Or colorScheme = 12 Then
  4356.         Select Case myColor
  4357.             Case cWhite:
  4358.                 myColor = cSilver
  4359.             Case cSilver:
  4360.                 myColor = cLightGray
  4361.             Case cLightGray:
  4362.                 myColor = cGray
  4363.             Case cGray:
  4364.                 myColor = cDimGray
  4365.             Case cDimGray:
  4366.                 myColor = cDarkGray
  4367.             Case cDarkGray:
  4368.                 myColor = cBlack
  4369.             Case Else:
  4370.                 myColor = cDarkGray
  4371.  
  4372.                 ' go in the other direction!
  4373.                 If colorScheme = 4 Then
  4374.                     colorScheme = 3
  4375.                 Else
  4376.                     colorScheme = 11
  4377.                 End If
  4378.         End Select
  4379.  
  4380.     End If
  4381.  
  4382. End Sub ' DoCycleColor
  4383.  
  4384. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4385. ' END COLOR ROUTINES
  4386. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4387.  
  4388. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4389. ' BEGIN COLOR FUNCTIONS
  4390. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4391.  
  4392. ' NOTE: these are mostly negative numbers
  4393. '       and have to be forced to positive
  4394. '       when stored in the dictionary
  4395. '       (only cEmpty should be negative)
  4396.  
  4397. Function cRed~& ()
  4398.     cRed = _RGB32(255, 0, 0)
  4399.  
  4400. Function cOrangeRed~& ()
  4401.     cOrangeRed = _RGB32(255, 69, 0)
  4402. End Function ' cOrangeRed~&
  4403.  
  4404. Function cDarkOrange~& ()
  4405.     cDarkOrange = _RGB32(255, 140, 0)
  4406. End Function ' cDarkOrange~&
  4407.  
  4408. Function cOrange~& ()
  4409.     cOrange = _RGB32(255, 165, 0)
  4410. End Function ' cOrange~&
  4411.  
  4412. Function cGold~& ()
  4413.     cGold = _RGB32(255, 215, 0)
  4414. End Function ' cGold~&
  4415.  
  4416. Function cYellow~& ()
  4417.     cYellow = _RGB32(255, 255, 0)
  4418. End Function ' cYellow~&
  4419.  
  4420. ' LONG-HAIRED FRIENDS OF JESUS OR NOT,
  4421. ' THIS IS NOT YELLOW ENOUGH (TOO CLOSE TO LIME)
  4422. ' TO USE FOR OUR COMPLEX RAINBOW SEQUENCE:
  4423. Function cChartreuse~& ()
  4424.     cChartreuse = _RGB32(127, 255, 0)
  4425. End Function ' cChartreuse~&
  4426.  
  4427. ' WE SUBSTITUTE THIS CSS3 COLOR FOR INBETWEEN LIME AND YELLOW:
  4428. Function cOliveDrab1~& ()
  4429.     cOliveDrab1 = _RGB32(192, 255, 62)
  4430. End Function ' cOliveDrab1~&
  4431.  
  4432. Function cLime~& ()
  4433.     cLime = _RGB32(0, 255, 0)
  4434. End Function ' cLime~&
  4435.  
  4436. Function cMediumSpringGreen~& ()
  4437.     cMediumSpringGreen = _RGB32(0, 250, 154)
  4438. End Function ' cMediumSpringGreen~&
  4439.  
  4440. Function cCyan~& ()
  4441.     cCyan = _RGB32(0, 255, 255)
  4442. End Function ' cCyan~&
  4443.  
  4444. Function cDeepSkyBlue~& ()
  4445.     cDeepSkyBlue = _RGB32(0, 191, 255)
  4446. End Function ' cDeepSkyBlue~&
  4447.  
  4448. Function cDodgerBlue~& ()
  4449.     cDodgerBlue = _RGB32(30, 144, 255)
  4450. End Function ' cDodgerBlue~&
  4451.  
  4452. Function cSeaBlue~& ()
  4453.     cSeaBlue = _RGB32(0, 64, 255)
  4454. End Function ' cSeaBlue~&
  4455.  
  4456. Function cBlue~& ()
  4457.     cBlue = _RGB32(0, 0, 255)
  4458. End Function ' cBlue~&
  4459.  
  4460. Function cBluePurple~& ()
  4461.     cBluePurple = _RGB32(64, 0, 255)
  4462. End Function ' cBluePurple~&
  4463.  
  4464. Function cDeepPurple~& ()
  4465.     cDeepPurple = _RGB32(96, 0, 255)
  4466. End Function ' cDeepPurple~&
  4467.  
  4468. Function cPurple~& ()
  4469.     cPurple = _RGB32(128, 0, 255)
  4470. End Function ' cPurple~&
  4471.  
  4472. Function cPurpleRed~& ()
  4473.     cPurpleRed = _RGB32(128, 0, 192)
  4474. End Function ' cPurpleRed~&
  4475.  
  4476. Function cDarkRed~& ()
  4477.     cDarkRed = _RGB32(160, 0, 64)
  4478. End Function ' cDarkRed~&
  4479.  
  4480. Function cBrickRed~& ()
  4481.     cBrickRed = _RGB32(192, 0, 32)
  4482. End Function ' cBrickRed~&
  4483.  
  4484. Function cDarkGreen~& ()
  4485.     cDarkGreen = _RGB32(0, 100, 0)
  4486. End Function ' cDarkGreen~&
  4487.  
  4488. Function cGreen~& ()
  4489.     cGreen = _RGB32(0, 128, 0)
  4490. End Function ' cGreen~&
  4491.  
  4492. Function cOliveDrab~& ()
  4493.     cOliveDrab = _RGB32(107, 142, 35)
  4494. End Function ' cOliveDrab~&
  4495.  
  4496. Function cLightPink~& ()
  4497.     cLightPink = _RGB32(255, 182, 193)
  4498. End Function ' cLightPink~&
  4499.  
  4500. Function cHotPink~& ()
  4501.     cHotPink = _RGB32(255, 105, 180)
  4502. End Function ' cHotPink~&
  4503.  
  4504. Function cDeepPink~& ()
  4505.     cDeepPink = _RGB32(255, 20, 147)
  4506. End Function ' cDeepPink~&
  4507.  
  4508. Function cMagenta~& ()
  4509.     cMagenta = _RGB32(255, 0, 255)
  4510. End Function ' cMagenta~&
  4511.  
  4512. Function cBlack~& ()
  4513.     cBlack = _RGB32(0, 0, 0)
  4514. End Function ' cBlack~&
  4515.  
  4516. Function cDimGray~& ()
  4517.     cDimGray = _RGB32(105, 105, 105)
  4518. End Function ' cDimGray~&
  4519.  
  4520. Function cGray~& ()
  4521.     cGray = _RGB32(128, 128, 128)
  4522. End Function ' cGray~&
  4523.  
  4524. Function cDarkGray~& ()
  4525.     cDarkGray = _RGB32(169, 169, 169)
  4526. End Function ' cDarkGray~&
  4527.  
  4528. Function cSilver~& ()
  4529.     cSilver = _RGB32(192, 192, 192)
  4530. End Function ' cSilver~&
  4531.  
  4532. Function cLightGray~& ()
  4533.     cLightGray = _RGB32(211, 211, 211)
  4534. End Function ' cLightGray~&
  4535.  
  4536. Function cGainsboro~& ()
  4537.     cGainsboro = _RGB32(220, 220, 220)
  4538. End Function ' cGainsboro~&
  4539.  
  4540. Function cWhiteSmoke~& ()
  4541.     cWhiteSmoke = _RGB32(245, 245, 245)
  4542. End Function ' cWhiteSmoke~&
  4543.  
  4544. Function cWhite~& ()
  4545.     cWhite = _RGB32(255, 255, 255)
  4546.     'cWhite = _RGB32(254, 254, 254)
  4547. End Function ' cWhite~&
  4548.  
  4549. Function cDarkBrown~& ()
  4550.     cDarkBrown = _RGB32(128, 64, 0)
  4551. End Function ' cDarkBrown~&
  4552.  
  4553. Function cLightBrown~& ()
  4554.     cLightBrown = _RGB32(196, 96, 0)
  4555. End Function ' cLightBrown~&
  4556.  
  4557. Function cKhaki~& ()
  4558.     cKhaki = _RGB32(240, 230, 140)
  4559. End Function ' cKhaki~&
  4560.  
  4561. Function cEmpty~& ()
  4562.     'cEmpty~& = -1
  4563.     cEmpty = _RGB32(0, 0, 0, 0)
  4564. End Function ' cEmpty~&
  4565.  
  4566. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4567. ' END COLOR FUNCTIONS
  4568. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4569.  
  4570. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4571. ' BEGIN KEYBOARD CODE FUNCTIONS
  4572. ' NOTE: ALL CODES ARE FOR _BUTTON
  4573. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4574.  
  4575. Function KeyCode_CtrlLeft% ()
  4576.     KeyCode_CtrlLeft% = 30
  4577.  
  4578. Function KeyCode_CtrlRight% ()
  4579.     KeyCode_CtrlRight% = 286
  4580.  
  4581. Function KeyCode_Y% ()
  4582.     KeyCode_Y% = 22
  4583.  
  4584. Function KeyCode_Z% ()
  4585.     KeyCode_Z% = 45
  4586.  
  4587. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4588. ' END KEYBOARD CODE FUNCTIONS
  4589. ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4590.  
  4591. ' #END
  4592. ' ################################################################################################################################################################
« Last Edit: December 16, 2021, 03:00:57 pm by madscijr »