grid.lua 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. Grid = class()
  2. function Grid:init()
  3. for y = 1, HEIGHT do
  4. self[y] = {}
  5. end
  6. end
  7. function Grid:set(x, y, c, char, room)
  8. if not room then
  9. room = self[y][x].room
  10. end
  11. self[y][x] = c(x, y, char, room)
  12. end
  13. function Grid:update(world, key)
  14. for y = 1, HEIGHT do
  15. for x = 1, WIDTH do
  16. self[y][x]:update(world)
  17. end
  18. end
  19. end
  20. function Grid:draw(text)
  21. for y = 1, HEIGHT do
  22. for x = 1, WIDTH do
  23. if self[y][x].lit then
  24. text[y][x] = self[y][x]
  25. end
  26. end
  27. end
  28. end
  29. -- draws
  30. function Grid:room(r)
  31. local room = {}
  32. a, b = r[1], r[2]
  33. for y = a.y + 1, b.y - 1 do
  34. for x = a.x + 1, b.x - 1 do
  35. self:set(x, y, Air, '.', room)
  36. room[#room + 1] = {x = x, y = y}
  37. end
  38. end
  39. for y = a.y, b.y do
  40. for x = a.x, b.x do
  41. if not self[y][x] then
  42. self:set(x, y, Wall, '#', {})
  43. end
  44. end
  45. end
  46. end
  47. function rectIntersects(a, b)
  48. return a[1].x <= b[2].x and b[1].x <= a[2].x and a[1].y <= b[2].y and b[1].y <= a[2].y
  49. end
  50. function roomAround(v)
  51. return {
  52. {
  53. x = math.max(1, v.x - love.math.random(3, 6)),
  54. y = math.max(1, v.y - love.math.random(3, 6))
  55. },
  56. {
  57. x = math.min(WIDTH - 1, v.x + love.math.random(3, 6)),
  58. y = math.min(HEIGHT - 1, v.y + love.math.random(3, 6))
  59. }
  60. }
  61. end
  62. function randomRoom()
  63. return roomAround(randomPoint())
  64. end
  65. function Grid:emptySpace()
  66. for y = 1, HEIGHT do
  67. for x = 1, WIDTH do
  68. if not self[y][x] then
  69. self[y][x] = Wall(x, y, ' ', {})
  70. end
  71. end
  72. end
  73. end
  74. function Grid:lightAll()
  75. for y = 1, HEIGHT do
  76. for x = 1, WIDTH do
  77. self[y][x].lit = true
  78. end
  79. end
  80. end
  81. -- straight line (has to be along a direct cardinal or whatever you call it)
  82. function Grid:line(a, b)
  83. local x, y = a.x, a.y
  84. local vx, vy = 0, 0
  85. local out = {a}
  86. if b.x > a.x then
  87. vx = 1
  88. elseif b.x < a.x then
  89. vx = -1
  90. end
  91. if b.y > a.y then
  92. vy = 1
  93. elseif b.y < a.y then
  94. vy = -1
  95. end
  96. while x ~= b.x or y ~= b.y do
  97. x = x + vx
  98. y = y + vy
  99. out[#out + 1] = {x = x, y = y}
  100. end
  101. return out
  102. end
  103. function Grid:lineAir(a, b)
  104. l = self:line(a, b)
  105. for _, v in pairs(l) do
  106. self:set(v.x, v.y, Air, '.', {})
  107. end
  108. end
  109. -- random, maze-y path to an area
  110. function Grid:path(a, b)
  111. local v = cloneVec(a) -- Lua pls
  112. local vx, vy = 0, 0
  113. local out = {}
  114. if b.x > a.x then
  115. vx = 1
  116. elseif b.x < a.x then
  117. vx = -1
  118. end
  119. if b.y > a.y then
  120. vy = 1
  121. elseif b.y < a.y then
  122. vy = -1
  123. end
  124. while v.x ~= b.x or v.y ~= b.y do
  125. local line
  126. if love.math.random(1, 2) == 1 and b.x ~= v.x then
  127. local amount = math.min(love.math.random(5), math.abs(b.x - v.x))
  128. line = self:line(v, {x = v.x + math.max(0, amount - 1) * vx, y = v.y})
  129. v.x = v.x + amount * vx
  130. else
  131. local amount = math.min(love.math.random(5), math.abs(b.y - v.y))
  132. line = self:line(v, {y = v.y + math.max(0, amount - 1) * vy, x = v.x})
  133. v.y = v.y + amount * vy
  134. end
  135. for _, v in pairs(line) do
  136. out[#out + 1] = cloneVec(v)
  137. end
  138. end
  139. out[#out + 1] = cloneVec(v)
  140. return out
  141. end
  142. function Grid:pathAir(a, b)
  143. l = self:path(a, b)
  144. for _, v in pairs(l) do
  145. self:set(v.x, v.y, Air, '.', {})
  146. end
  147. end
  148. function randomInRoom(r)
  149. return {
  150. x = love.math.random(r[1].x + 1, r[2].x - 1),
  151. y = love.math.random(r[1].y + 1, r[2].y - 1)
  152. }
  153. end
  154. function randomPoint()
  155. return {
  156. x = love.math.random(1, WIDTH - 1),
  157. y = love.math.random(1, HEIGHT - 1)
  158. }
  159. end
  160. function Grid:generateLevel(start)
  161. local rooms = {roomAround(start)}
  162. for i = 1, love.math.random(5, 10) do
  163. local newRoom
  164. local collide = true
  165. while collide do
  166. newRoom = randomRoom()
  167. collide = false
  168. for _, r in pairs(rooms) do
  169. if rectIntersects(newRoom, r) then
  170. collide = true
  171. end
  172. end
  173. end
  174. local oldRoom = rooms[love.math.random(#rooms)]
  175. self:pathAir(randomInRoom(oldRoom), randomInRoom(newRoom))
  176. rooms[#rooms + 1] = newRoom
  177. end
  178. for _, r in pairs(rooms) do
  179. self:room(r)
  180. end
  181. for i = 1, self.level == 1 and 6 or love.math.random(1, 3) do
  182. p = randomInRoom(rooms[love.math.random(2, #rooms)])
  183. self:set(p.x, p.y, Stair, '>')
  184. end
  185. for i = 1, self.level == 1 and 6 or love.math.random(1, 6) do
  186. p = randomInRoom(rooms[love.math.random(1, #rooms)])
  187. self:set(p.x, p.y, Chest, 'C')
  188. end
  189. self:emptySpace()
  190. end