Grid.lua 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. -- Copyright (c) 2011-2012 Casey Baxter
  2. -- See LICENSE file for details
  3. ---------------------------------------------------------------------------------------------------
  4. -- -= Grid =-
  5. ---------------------------------------------------------------------------------------------------
  6. local Grid = {class = "Grid"}
  7. Grid.__index = Grid
  8. ---------------------------------------------------------------------------------------------------
  9. -- Creates and returns a new grid
  10. function Grid:new()
  11. local grid = {}
  12. grid.cells = {}
  13. return setmetatable(grid, Grid)
  14. end
  15. ---------------------------------------------------------------------------------------------------
  16. -- Gets the value of a single cell
  17. function Grid:get(x,y)
  18. return self.cells[x] and self.cells[x][y]
  19. end
  20. ---------------------------------------------------------------------------------------------------
  21. -- Sets the value of a single cell
  22. function Grid:set(x,y,value)
  23. if not self.cells[x] then self.cells[x] = {} end
  24. self.cells[x][y] = value
  25. end
  26. ---------------------------------------------------------------------------------------------------
  27. -- Iterate over all values
  28. local x, y, row, val
  29. function Grid:iterate()
  30. x, y, row, val = nil, nil, nil, nil
  31. return function()
  32. repeat
  33. if not y then
  34. x, row = next(self.cells, x)
  35. if not row then return end
  36. end
  37. y, val = next(row, y)
  38. until y
  39. return x, y, val
  40. end
  41. end
  42. ---------------------------------------------------------------------------------------------------
  43. -- Iterate over a rectangle shape
  44. function Grid:rectangle(startX, startY, width, height, includeNil)
  45. local x, y = startX, startY
  46. return function()
  47. while y <= startY + height do
  48. while x <= startX + width do
  49. x = x+1
  50. if self(x-1,y) ~= nil or includeNil then
  51. return x-1, y, self(x-1,y)
  52. end
  53. end
  54. x = startX
  55. y = y+1
  56. end
  57. return nil
  58. end
  59. end
  60. ---------------------------------------------------------------------------------------------------
  61. -- Iterate over a line. Set noDiag to true to keep from traversing diagonally.
  62. function Grid:line(startX, startY, endX, endY, noDiag, includeNil)
  63. local dx = math.abs(endX - startX)
  64. local dy = math.abs(endY - startY)
  65. local x = startX
  66. local y = startY
  67. local incrX = endX > startX and 1 or -1
  68. local incrY = endY > startY and 1 or -1
  69. local err = dx - dy
  70. local err2 = err*2
  71. local i = 1+dx+dy
  72. local rx,ry,rv
  73. local checkX = false
  74. return function()
  75. while i>0 do
  76. rx,ry,rv = x,y,self(x,y)
  77. err2 = err*2
  78. while true do
  79. checkX = not checkX
  80. if checkX == true or not noDiag then
  81. if err2 > -dy then
  82. err = err - dy
  83. x = x + incrX
  84. i = i-1
  85. if noDiag then break end
  86. end
  87. end
  88. if checkX == false or not noDiag then
  89. if err2 < dx then
  90. err = err + dx
  91. y = y + incrY
  92. i = i-1
  93. if noDiag then break end
  94. end
  95. end
  96. if not noDiag then break end
  97. end
  98. if rx == endX and ry == endY then i = 0 end
  99. if rv ~= nil or includeNil then return rx,ry,rv end
  100. end
  101. return nil
  102. end
  103. end
  104. ---------------------------------------------------------------------------------------------------
  105. -- Iterates over a circle of cells
  106. function Grid:circle(cx, cy, r, includeNil)
  107. local x,y
  108. x = x or cx-r
  109. return function()
  110. repeat
  111. y = y == nil and cy or y <= cy and y-1 or y+1
  112. while ((cx-x)*(cx-x)+(cy-y)*(cy-y)) >= r*r do
  113. if x > cx+r then return nil end
  114. x = x + (y < cy and 0 or 1)
  115. y = cy + (y < cy and 1 or 0)
  116. end
  117. until self(x,y) ~= nil or includeNil
  118. return x,y,self(x,y)
  119. end
  120. end
  121. ---------------------------------------------------------------------------------------------------
  122. -- Cleans the grid of empty rows.
  123. function Grid:clean()
  124. for key,row in pairs(self.cells) do
  125. if not next(row) then self.cells[key] = nil end
  126. end
  127. end
  128. ---------------------------------------------------------------------------------------------------
  129. -- Clears the grid
  130. function Grid:clear()
  131. self.cells = {}
  132. end
  133. ---------------------------------------------------------------------------------------------------
  134. -- This makes calling the grid as a function act like Grid.get.
  135. Grid.__call = Grid.get
  136. ---------------------------------------------------------------------------------------------------
  137. -- Returns the grid class
  138. return Grid