RAYCAST.C 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. /*
  2. * Raycaster, based on lodev engine tutorial
  3. */
  4. #define word char
  5. #include "LIB/MATH.C"
  6. #include "LIB/STDLIB.C"
  7. #include "LIB/SYS.C"
  8. #include "LIB/GFX.C"
  9. #include "LIB/FP.C"
  10. #define screenWidth 320
  11. #define screenHeight 240
  12. #define mapWidth 24
  13. #define mapHeight 24
  14. #define BTN_LEFT 256
  15. #define BTN_RIGHT 257
  16. #define BTN_UP 258
  17. #define BTN_DOWN 259
  18. // Colors
  19. #define COLOR_RED 224
  20. #define COLOR_DARK_RED 96
  21. #define COLOR_GREEN 28
  22. #define COLOR_DARK_GREEN 12
  23. #define COLOR_BLUE 3
  24. #define COLOR_DARK_BLUE 2
  25. #define COLOR_WHITE 0xFF
  26. #define COLOR_GREY 0xB6
  27. #define COLOR_YELLOW 0xFC
  28. #define COLOR_DARK_YELLOW 0x90
  29. #define FB_ADDR 0xD00000
  30. // Framebuffer. fb[Y][X] (bottom right is [239][319])
  31. char (*fb)[screenWidth] = (char (*)[screenWidth]) FB_ADDR;
  32. word quitGame = 0;
  33. word LUTdirX[360] = {
  34. -65526, -65496, -65446, -65376, -65287, -65177, -65048, -64898, -64729, -64540, -64332, -64104,
  35. -63856, -63589, -63303, -62997, -62672, -62328, -61966, -61584, -61183, -60764, -60326, -59870,
  36. -59396, -58903, -58393, -57865, -57319, -56756, -56175, -55578, -54963, -54332, -53684, -53020,
  37. -52339, -51643, -50931, -50203, -49461, -48703, -47930, -47143, -46341, -45525, -44695, -43852,
  38. -42995, -42126, -41243, -40348, -39441, -38521, -37590, -36647, -35693, -34729, -33754, -32768,
  39. -31772, -30767, -29753, -28729, -27697, -26656, -25607, -24550, -23486, -22415, -21336, -20252,
  40. -19161, -18064, -16962, -15855, -14742, -13626, -12505, -11380, -10252, -9121, -7987, -6850,
  41. -5712, -4572, -3430, -2287, -1144, 0, 1144, 2287, 3430, 4572, 5712, 6850,
  42. 7987, 9121, 10252, 11380, 12505, 13626, 14742, 15855, 16962, 18064, 19161, 20252,
  43. 21336, 22415, 23486, 24550, 25607, 26656, 27697, 28729, 29753, 30767, 31772, 32768,
  44. 33754, 34729, 35693, 36647, 37590, 38521, 39441, 40348, 41243, 42126, 42995, 43852,
  45. 44695, 45525, 46341, 47143, 47930, 48703, 49461, 50203, 50931, 51643, 52339, 53020,
  46. 53684, 54332, 54963, 55578, 56175, 56756, 57319, 57865, 58393, 58903, 59396, 59870,
  47. 60326, 60764, 61183, 61584, 61966, 62328, 62672, 62997, 63303, 63589, 63856, 64104,
  48. 64332, 64540, 64729, 64898, 65048, 65177, 65287, 65376, 65446, 65496, 65526, 65536,
  49. 65526, 65496, 65446, 65376, 65287, 65177, 65048, 64898, 64729, 64540, 64332, 64104,
  50. 63856, 63589, 63303, 62997, 62672, 62328, 61966, 61584, 61183, 60764, 60326, 59870,
  51. 59396, 58903, 58393, 57865, 57319, 56756, 56175, 55578, 54963, 54332, 53684, 53020,
  52. 52339, 51643, 50931, 50203, 49461, 48703, 47930, 47143, 46341, 45525, 44695, 43852,
  53. 42995, 42126, 41243, 40348, 39441, 38521, 37590, 36647, 35693, 34729, 33754, 32768,
  54. 31772, 30767, 29753, 28729, 27697, 26656, 25607, 24550, 23486, 22415, 21336, 20252,
  55. 19161, 18064, 16962, 15855, 14742, 13626, 12505, 11380, 10252, 9121, 7987, 6850,
  56. 5712, 4572, 3430, 2287, 1144, 0, -1144, -2287, -3430, -4572, -5712, -6850,
  57. -7987, -9121, -10252, -11380, -12505, -13626, -14742, -15855, -16962, -18064, -19161, -20252,
  58. -21336, -22415, -23486, -24550, -25607, -26656, -27697, -28729, -29753, -30767, -31772, -32768,
  59. -33754, -34729, -35693, -36647, -37590, -38521, -39441, -40348, -41243, -42126, -42995, -43852,
  60. -44695, -45525, -46341, -47143, -47930, -48703, -49461, -50203, -50931, -51643, -52339, -53020,
  61. -53684, -54332, -54963, -55578, -56175, -56756, -57319, -57865, -58393, -58903, -59396, -59870,
  62. -60326, -60764, -61183, -61584, -61966, -62328, -62672, -62997, -63303, -63589, -63856, -64104,
  63. -64332, -64540, -64729, -64898, -65048, -65177, -65287, -65376, -65446, -65496, -65526, -65536
  64. };
  65. word LUTdirY[360] = {
  66. 1144, 2287, 3430, 4572, 5712, 6850, 7987, 9121, 10252, 11380, 12505, 13626,
  67. 14742, 15855, 16962, 18064, 19161, 20252, 21336, 22415, 23486, 24550, 25607, 26656,
  68. 27697, 28729, 29753, 30767, 31772, 32768, 33754, 34729, 35693, 36647, 37590, 38521,
  69. 39441, 40348, 41243, 42126, 42995, 43852, 44695, 45525, 46341, 47143, 47930, 48703,
  70. 49461, 50203, 50931, 51643, 52339, 53020, 53684, 54332, 54963, 55578, 56175, 56756,
  71. 57319, 57865, 58393, 58903, 59396, 59870, 60326, 60764, 61183, 61584, 61966, 62328,
  72. 62672, 62997, 63303, 63589, 63856, 64104, 64332, 64540, 64729, 64898, 65048, 65177,
  73. 65287, 65376, 65446, 65496, 65526, 65536, 65526, 65496, 65446, 65376, 65287, 65177,
  74. 65048, 64898, 64729, 64540, 64332, 64104, 63856, 63589, 63303, 62997, 62672, 62328,
  75. 61966, 61584, 61183, 60764, 60326, 59870, 59396, 58903, 58393, 57865, 57319, 56756,
  76. 56175, 55578, 54963, 54332, 53684, 53020, 52339, 51643, 50931, 50203, 49461, 48703,
  77. 47930, 47143, 46341, 45525, 44695, 43852, 42995, 42126, 41243, 40348, 39441, 38521,
  78. 37590, 36647, 35693, 34729, 33754, 32768, 31772, 30767, 29753, 28729, 27697, 26656,
  79. 25607, 24550, 23486, 22415, 21336, 20252, 19161, 18064, 16962, 15855, 14742, 13626,
  80. 12505, 11380, 10252, 9121, 7987, 6850, 5712, 4572, 3430, 2287, 1144, 0,
  81. -1144, -2287, -3430, -4572, -5712, -6850, -7987, -9121, -10252, -11380, -12505, -13626,
  82. -14742, -15855, -16962, -18064, -19161, -20252, -21336, -22415, -23486, -24550, -25607, -26656,
  83. -27697, -28729, -29753, -30767, -31772, -32768, -33754, -34729, -35693, -36647, -37590, -38521,
  84. -39441, -40348, -41243, -42126, -42995, -43852, -44695, -45525, -46341, -47143, -47930, -48703,
  85. -49461, -50203, -50931, -51643, -52339, -53020, -53684, -54332, -54963, -55578, -56175, -56756,
  86. -57319, -57865, -58393, -58903, -59396, -59870, -60326, -60764, -61183, -61584, -61966, -62328,
  87. -62672, -62997, -63303, -63589, -63856, -64104, -64332, -64540, -64729, -64898, -65048, -65177,
  88. -65287, -65376, -65446, -65496, -65526, -65536, -65526, -65496, -65446, -65376, -65287, -65177,
  89. -65048, -64898, -64729, -64540, -64332, -64104, -63856, -63589, -63303, -62997, -62672, -62328,
  90. -61966, -61584, -61183, -60764, -60326, -59870, -59396, -58903, -58393, -57865, -57319, -56756,
  91. -56175, -55578, -54963, -54332, -53684, -53020, -52339, -51643, -50931, -50203, -49461, -48703,
  92. -47930, -47143, -46341, -45525, -44695, -43852, -42995, -42126, -41243, -40348, -39441, -38521,
  93. -37590, -36647, -35693, -34729, -33754, -32768, -31772, -30767, -29753, -28729, -27697, -26656,
  94. -25607, -24550, -23486, -22415, -21336, -20252, -19161, -18064, -16962, -15855, -14742, -13626,
  95. -12505, -11380, -10252, -9121, -7987, -6850, -5712, -4572, -3430, -2287, -1144, 0
  96. };
  97. word LUTplaneX[360] = {
  98. 755, 1510, 2264, 3017, 3770, 4521, 5271, 6020, 6766, 7511, 8253, 8993,
  99. 9730, 10464, 11195, 11922, 12646, 13366, 14082, 14794, 15501, 16203, 16901, 17593,
  100. 18280, 18961, 19637, 20306, 20970, 21627, 22277, 22921, 23558, 24187, 24809, 25424,
  101. 26031, 26630, 27220, 27803, 28377, 28942, 29499, 30047, 30585, 31114, 31634, 32144,
  102. 32644, 33134, 33614, 34084, 34544, 34993, 35431, 35859, 36276, 36681, 37076, 37459,
  103. 37831, 38191, 38539, 38876, 39201, 39514, 39815, 40104, 40381, 40645, 40897, 41137,
  104. 41364, 41578, 41780, 41969, 42145, 42309, 42459, 42597, 42721, 42833, 42931, 43017,
  105. 43089, 43148, 43194, 43227, 43247, 43254, 43247, 43227, 43194, 43148, 43089, 43017,
  106. 42931, 42833, 42721, 42597, 42459, 42309, 42145, 41969, 41780, 41578, 41364, 41137,
  107. 40897, 40645, 40381, 40104, 39815, 39514, 39201, 38876, 38539, 38191, 37831, 37459,
  108. 37076, 36681, 36276, 35859, 35431, 34993, 34544, 34084, 33614, 33134, 32644, 32144,
  109. 31634, 31114, 30585, 30047, 29499, 28942, 28377, 27803, 27220, 26630, 26031, 25424,
  110. 24809, 24187, 23558, 22921, 22277, 21627, 20970, 20306, 19637, 18961, 18280, 17593,
  111. 16901, 16203, 15501, 14794, 14082, 13366, 12646, 11922, 11195, 10464, 9730, 8993,
  112. 8253, 7511, 6766, 6020, 5271, 4521, 3770, 3017, 2264, 1510, 755, 0,
  113. -755, -1510, -2264, -3017, -3770, -4521, -5271, -6020, -6766, -7511, -8253, -8993,
  114. -9730, -10464, -11195, -11922, -12646, -13366, -14082, -14794, -15501, -16203, -16901, -17593,
  115. -18280, -18961, -19637, -20306, -20970, -21627, -22277, -22921, -23558, -24187, -24809, -25424,
  116. -26031, -26630, -27220, -27803, -28377, -28942, -29499, -30047, -30585, -31114, -31634, -32144,
  117. -32644, -33134, -33614, -34084, -34544, -34993, -35431, -35859, -36276, -36681, -37076, -37459,
  118. -37831, -38191, -38539, -38876, -39201, -39514, -39815, -40104, -40381, -40645, -40897, -41137,
  119. -41364, -41578, -41780, -41969, -42145, -42309, -42459, -42597, -42721, -42833, -42931, -43017,
  120. -43089, -43148, -43194, -43227, -43247, -43254, -43247, -43227, -43194, -43148, -43089, -43017,
  121. -42931, -42833, -42721, -42597, -42459, -42309, -42145, -41969, -41780, -41578, -41364, -41137,
  122. -40897, -40645, -40381, -40104, -39815, -39514, -39201, -38876, -38539, -38191, -37831, -37459,
  123. -37076, -36681, -36276, -35859, -35431, -34993, -34544, -34084, -33614, -33134, -32644, -32144,
  124. -31634, -31114, -30585, -30047, -29499, -28942, -28377, -27803, -27220, -26630, -26031, -25424,
  125. -24809, -24187, -23558, -22921, -22277, -21627, -20970, -20306, -19637, -18961, -18280, -17593,
  126. -16901, -16203, -15501, -14794, -14082, -13366, -12646, -11922, -11195, -10464, -9730, -8993,
  127. -8253, -7511, -6766, -6020, -5271, -4521, -3770, -3017, -2264, -1510, -755, 0
  128. };
  129. word LUTplaneY[360] = {
  130. 43247, 43227, 43194, 43148, 43089, 43017, 42931, 42833, 42721, 42597, 42459, 42309,
  131. 42145, 41969, 41780, 41578, 41364, 41137, 40897, 40645, 40381, 40104, 39815, 39514,
  132. 39201, 38876, 38539, 38191, 37831, 37459, 37076, 36681, 36276, 35859, 35431, 34993,
  133. 34544, 34084, 33614, 33134, 32644, 32144, 31634, 31114, 30585, 30047, 29499, 28942,
  134. 28377, 27803, 27220, 26630, 26031, 25424, 24809, 24187, 23558, 22921, 22277, 21627,
  135. 20970, 20306, 19637, 18961, 18280, 17593, 16901, 16203, 15501, 14794, 14082, 13366,
  136. 12646, 11922, 11195, 10464, 9730, 8993, 8253, 7511, 6766, 6020, 5271, 4521,
  137. 3770, 3017, 2264, 1510, 755, 0, -755, -1510, -2264, -3017, -3770, -4521,
  138. -5271, -6020, -6766, -7511, -8253, -8993, -9730, -10464, -11195, -11922, -12646, -13366,
  139. -14082, -14794, -15501, -16203, -16901, -17593, -18280, -18961, -19637, -20306, -20970, -21627,
  140. -22277, -22921, -23558, -24187, -24809, -25424, -26031, -26630, -27220, -27803, -28377, -28942,
  141. -29499, -30047, -30585, -31114, -31634, -32144, -32644, -33134, -33614, -34084, -34544, -34993,
  142. -35431, -35859, -36276, -36681, -37076, -37459, -37831, -38191, -38539, -38876, -39201, -39514,
  143. -39815, -40104, -40381, -40645, -40897, -41137, -41364, -41578, -41780, -41969, -42145, -42309,
  144. -42459, -42597, -42721, -42833, -42931, -43017, -43089, -43148, -43194, -43227, -43247, -43254,
  145. -43247, -43227, -43194, -43148, -43089, -43017, -42931, -42833, -42721, -42597, -42459, -42309,
  146. -42145, -41969, -41780, -41578, -41364, -41137, -40897, -40645, -40381, -40104, -39815, -39514,
  147. -39201, -38876, -38539, -38191, -37831, -37459, -37076, -36681, -36276, -35859, -35431, -34993,
  148. -34544, -34084, -33614, -33134, -32644, -32144, -31634, -31114, -30585, -30047, -29499, -28942,
  149. -28377, -27803, -27220, -26630, -26031, -25424, -24809, -24187, -23558, -22921, -22277, -21627,
  150. -20970, -20306, -19637, -18961, -18280, -17593, -16901, -16203, -15501, -14794, -14082, -13366,
  151. -12646, -11922, -11195, -10464, -9730, -8993, -8253, -7511, -6766, -6020, -5271, -4521,
  152. -3770, -3017, -2264, -1510, -755, 0, 755, 1510, 2264, 3017, 3770, 4521,
  153. 5271, 6020, 6766, 7511, 8253, 8993, 9730, 10464, 11195, 11922, 12646, 13366,
  154. 14082, 14794, 15501, 16203, 16901, 17593, 18280, 18961, 19637, 20306, 20970, 21627,
  155. 22277, 22921, 23558, 24187, 24809, 25424, 26031, 26630, 27220, 27803, 28377, 28942,
  156. 29499, 30047, 30585, 31114, 31634, 32144, 32644, 33134, 33614, 34084, 34544, 34993,
  157. 35431, 35859, 36276, 36681, 37076, 37459, 37831, 38191, 38539, 38876, 39201, 39514,
  158. 39815, 40104, 40381, 40645, 40897, 41137, 41364, 41578, 41780, 41969, 42145, 42309,
  159. 42459, 42597, 42721, 42833, 42931, 43017, 43089, 43148, 43194, 43227, 43247, 43254
  160. };
  161. word worldMap[mapWidth][mapHeight]=
  162. {
  163. {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
  164. {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  165. {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  166. {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  167. {1,0,0,0,0,0,2,2,2,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1},
  168. {1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1},
  169. {1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,3,0,0,0,3,0,0,0,1},
  170. {1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1},
  171. {1,0,0,0,0,0,2,2,0,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1},
  172. {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  173. {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  174. {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  175. {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  176. {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  177. {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  178. {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  179. {1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,5,0,0,0,0,0,0,1},
  180. {1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  181. {1,4,0,0,0,0,5,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  182. {1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  183. {1,4,0,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  184. {1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  185. {1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  186. {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
  187. };
  188. // Render vertical line in pixel plane
  189. // INPUT:
  190. // r4 = x (which vertical line)
  191. // r5 = y when to start drawing line
  192. // r6 = y when to stop drawing line
  193. // r7 = color of line
  194. void RAYFX_drawVertLine(word x, word start, word end, char color)
  195. {
  196. // reg 4 5 6 7 and 2 (retval) are safe
  197. asm(
  198. "; backup registers\n"
  199. "push r9\n"
  200. );
  201. asm(
  202. "load32 0xD00000 r9 ; r9 = framebuffer addr\n"
  203. "add r9 r4 r4 ; r4 = first pixel in line\n"
  204. "multu r5 320 r9 ; r9 = start with line offset\n"
  205. "add r9 r4 r5 ; r5 = fb addr of start\n"
  206. "multu r6 320 r9 ; r9 = end with line offset\n"
  207. "add r9 r4 r6 ; r6 = fb addr of start\n"
  208. "load 239 r2 ; r2 = y endloop\n"
  209. "multu r2 320 r9 ; r9 = start line offset\n"
  210. "add r9 r4 r2 ; r2 = fb addr of final pixel\n"
  211. "; draw until start\n"
  212. "RAYFX_drawVlineLoopCeiling:\n"
  213. " write 0 r4 r0 ; write black pixel\n"
  214. " add r4 320 r4 ; go to next line pixel\n"
  215. " bge r4 r5 2 ; keep looping until reached start\n"
  216. " jump RAYFX_drawVlineLoopCeiling\n"
  217. "; draw until end\n"
  218. "RAYFX_drawVlineLoopWall:\n"
  219. " write 0 r4 r7 ; write color pixel\n"
  220. " add r4 320 r4 ; go to next line pixel\n"
  221. " bge r4 r6 2 ; keep looping until reached end\n"
  222. " jump RAYFX_drawVlineLoopWall\n"
  223. "; draw until final pixel\n"
  224. "RAYFX_drawVlineLoopFloor:\n"
  225. " write 0 r4 r0 ; write black pixel\n"
  226. " add r4 320 r4 ; go to next line pixel\n"
  227. " bge r4 r2 2 ; keep looping until reached end of screen\n"
  228. " jump RAYFX_drawVlineLoopFloor\n"
  229. );
  230. asm(
  231. "; restore registers\n"
  232. "pop r9\n"
  233. );
  234. }
  235. int main()
  236. {
  237. // clear screen from text
  238. GFX_clearWindowtileTable();
  239. GFX_clearWindowpaletteTable();
  240. GFX_clearBGtileTable();
  241. GFX_clearBGpaletteTable();
  242. //x and y start position
  243. fixed_point_t posX = FP_intToFP(12);
  244. fixed_point_t posY = FP_intToFP(12);
  245. //initial direction vector
  246. fixed_point_t dirX = LUTdirX[0];
  247. fixed_point_t dirY = LUTdirY[0];
  248. //the 2d raycaster version of camera plane
  249. fixed_point_t planeX = LUTplaneX[0];
  250. fixed_point_t planeY = LUTplaneY[0];
  251. // rotation angle (loops at 360)
  252. word rotationAngle = 0;
  253. word rotationSpeed = 3; // degrees per frame
  254. fixed_point_t moveSpeed = FP_StringToFP("0.15");
  255. while(!quitGame)
  256. {
  257. word x;
  258. for(x = 0; x < screenWidth; x++)
  259. {
  260. //calculate ray position and direction
  261. fixed_point_t cameraX = FP_Div(FP_intToFP(x<<1), FP_intToFP(screenWidth)) - FP_intToFP(1); //x-coordinate in camera space
  262. fixed_point_t rayDirX = dirX + FP_Mult(planeX, cameraX);
  263. fixed_point_t rayDirY = dirY + FP_Mult(planeY, cameraX);
  264. //which box of the map we are in
  265. word mapX = FP_FPtoInt(posX);
  266. word mapY = FP_FPtoInt(posY);
  267. //length of ray from current position to next x or y-side
  268. fixed_point_t sideDistX;
  269. fixed_point_t sideDistY;
  270. //length of ray from one x or y-side to next x or y-side
  271. //these are derived as:
  272. //deltaDistX = sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX))
  273. //deltaDistY = sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY))
  274. //which can be simplified to abs(|rayDir| / rayDirX) and abs(|rayDir| / rayDirY)
  275. //where |rayDir| is the length of the vector (rayDirX, rayDirY). Its length,
  276. //unlike (dirX, dirY) is not 1, however this does not matter, only the
  277. //ratio between deltaDistX and deltaDistY matters, due to the way the DDA
  278. //stepping further below works. So the values can be computed as below.
  279. // Division through zero is prevented by setting the result to a very high value
  280. fixed_point_t deltaDistX = (rayDirX == 0) ? 1<<30 : MATH_abs( FP_Div(FP_intToFP(1), rayDirX));
  281. fixed_point_t deltaDistY = (rayDirY == 0) ? 1<<30 : MATH_abs( FP_Div(FP_intToFP(1), rayDirY));
  282. fixed_point_t perpWallDist;
  283. //what direction to step in x or y-direction (either +1 or -1)
  284. word stepX;
  285. word stepY;
  286. word hit = 0; //was there a wall hit?
  287. word side; //was a NS or a EW wall hit?
  288. //calculate step and initial sideDist
  289. if(rayDirX < 0)
  290. {
  291. stepX = -1;
  292. sideDistX = FP_Mult((posX - FP_intToFP(mapX)), deltaDistX);
  293. }
  294. else
  295. {
  296. stepX = 1;
  297. sideDistX = FP_Mult((FP_intToFP(mapX + 1) - posX), deltaDistX);
  298. }
  299. if(rayDirY < 0)
  300. {
  301. stepY = -1;
  302. sideDistY = FP_Mult((posY - FP_intToFP(mapY)), deltaDistY);
  303. }
  304. else
  305. {
  306. stepY = 1;
  307. sideDistY = FP_Mult((FP_intToFP(mapY + 1) - posY), deltaDistY);
  308. }
  309. //perform DDA
  310. while(hit == 0)
  311. {
  312. //jump to next map square, either in x-direction, or in y-direction
  313. if(sideDistX < sideDistY)
  314. {
  315. sideDistX += deltaDistX;
  316. mapX += stepX;
  317. side = 0;
  318. }
  319. else
  320. {
  321. sideDistY += deltaDistY;
  322. mapY += stepY;
  323. side = 1;
  324. }
  325. //Check if ray has hit a wall
  326. if(worldMap[mapX][mapY] > 0) hit = 1;
  327. }
  328. //Calculate distance projected on camera direction. This is the shortest distance from the point where the wall is
  329. //hit to the camera plane. Euclidean to center camera point would give fisheye effect!
  330. //This can be computed as (mapX - posX + (1 - stepX) / 2) / rayDirX for side == 0, or same formula with Y
  331. //for size == 1, but can be simplified to the code below thanks to how sideDist and deltaDist are computed:
  332. //because they were left scaled to |rayDir|. sideDist is the entire length of the ray above after the multiple
  333. //steps, but we subtract deltaDist once because one step more into the wall was taken above.
  334. if(side == 0) perpWallDist = (sideDistX - deltaDistX);
  335. else perpWallDist = (sideDistY - deltaDistY);
  336. //Calculate height of line to draw on screen
  337. word lineHeight = FP_FPtoInt(FP_Div(FP_intToFP(screenHeight), perpWallDist));
  338. //calculate lowest and highest pixel to fill in current stripe
  339. word drawStart = - (lineHeight >> 1) + (screenHeight >> 1);
  340. if(drawStart < 0) drawStart = 0;
  341. word drawEnd = (lineHeight >> 1) + (screenHeight >> 1);
  342. if(drawEnd >= screenHeight) drawEnd = screenHeight - 1;
  343. //choose wall color
  344. //give x and y sides different brightness
  345. char color;
  346. switch(worldMap[mapX][mapY])
  347. {
  348. case 1: color = (side == 1) ? COLOR_DARK_RED : COLOR_RED; break;
  349. case 2: color = (side == 1) ? COLOR_DARK_GREEN : COLOR_GREEN; break;
  350. case 3: color = (side == 1) ? COLOR_DARK_BLUE : COLOR_BLUE; break;
  351. case 4: color = (side == 1) ? COLOR_GREY : COLOR_WHITE; break;
  352. default: color = (side == 1) ? COLOR_DARK_YELLOW : COLOR_YELLOW; break;
  353. }
  354. //draw the pixels of the stripe as a vertical line
  355. // Safity checks beforehand
  356. // Currently skips first line of frame as it does not render properly
  357. if (x != 0 && drawStart >= 0 && drawEnd >= drawStart && drawEnd < screenHeight)
  358. {
  359. RAYFX_drawVertLine(x, drawStart, drawEnd, color);
  360. }
  361. }
  362. // check which button is held
  363. if (BDOS_USBkeyHeld(BTN_LEFT))
  364. {
  365. //both camera direction and camera plane must be rotated
  366. rotationAngle -= rotationSpeed;
  367. if (rotationAngle < 0)
  368. {
  369. rotationAngle += 360;
  370. }
  371. dirX = LUTdirX[rotationAngle];
  372. dirY = LUTdirY[rotationAngle];
  373. planeX = LUTplaneX[rotationAngle];
  374. planeY = LUTplaneY[rotationAngle];
  375. }
  376. else if (BDOS_USBkeyHeld(BTN_RIGHT))
  377. {
  378. //both camera direction and camera plane must be rotated
  379. rotationAngle += rotationSpeed;
  380. if (rotationAngle >= 360)
  381. {
  382. rotationAngle -= 360;
  383. }
  384. dirX = LUTdirX[rotationAngle];
  385. dirY = LUTdirY[rotationAngle];
  386. planeX = LUTplaneX[rotationAngle];
  387. planeY = LUTplaneY[rotationAngle];
  388. }
  389. if (BDOS_USBkeyHeld(BTN_UP))
  390. {
  391. word worldMapX = FP_FPtoInt(posX + FP_Mult(dirX, moveSpeed));
  392. word worldMapY = FP_FPtoInt(posY);
  393. if(worldMap[worldMapX][worldMapY] == 0)
  394. {
  395. posX += FP_Mult(dirX, moveSpeed);
  396. }
  397. worldMapX = FP_FPtoInt(posX);
  398. worldMapY = FP_FPtoInt(posY + FP_Mult(dirY, moveSpeed));
  399. if(worldMap[worldMapX][worldMapY] == 0)
  400. {
  401. posY += FP_Mult(dirY, moveSpeed);
  402. }
  403. }
  404. else if (BDOS_USBkeyHeld(BTN_DOWN))
  405. {
  406. word worldMapX = FP_FPtoInt(posX - FP_Mult(dirX, moveSpeed));
  407. word worldMapY = FP_FPtoInt(posY);
  408. if(worldMap[worldMapX][worldMapY] == 0)
  409. {
  410. posX -= FP_Mult(dirX, moveSpeed);
  411. }
  412. worldMapX = FP_FPtoInt(posX);
  413. worldMapY = FP_FPtoInt(posY - FP_Mult(dirY, moveSpeed));
  414. if(worldMap[worldMapX][worldMapY] == 0)
  415. {
  416. posY -= FP_Mult(dirY, moveSpeed);
  417. }
  418. }
  419. if (HID_FifoAvailable())
  420. {
  421. word c = HID_FifoRead();
  422. if (c == 27) // escape
  423. {
  424. GFX_clearPXframebuffer();
  425. return 'q';
  426. }
  427. }
  428. }
  429. return 'q';
  430. }
  431. void interrupt()
  432. {
  433. // handle all interrupts
  434. word i = getIntID();
  435. switch(i)
  436. {
  437. case INTID_TIMER1:
  438. timer1Value = 1; // notify ending of timer1
  439. break;
  440. case INTID_TIMER2:
  441. break;
  442. case INTID_UART0:
  443. break;
  444. case INTID_GPU:
  445. break;
  446. case INTID_TIMER3:
  447. break;
  448. case INTID_PS2:
  449. break;
  450. case INTID_UART1:
  451. break;
  452. case INTID_UART2:
  453. break;
  454. }
  455. }