wall.lua 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. local Wall = {}
  2. Wall.name = 'Wall'
  3. Wall.code = 'wall'
  4. Wall.collision = {}
  5. Wall.collision.shape = 'rectangle'
  6. Wall.collision.tag = 'wall'
  7. local function perim(x, y, l, t, w, h)
  8. local r, b = l + w, t + h
  9. x, y = math.clamp(x, l, r), math.clamp(y, t, b)
  10. local dl, dr, dt, db = math.abs(x - l), math.abs(x - r), math.abs(y - t), math.abs(y - b)
  11. local m = math.min(dl, dr, dt, db)
  12. if m == dt then return x, t end
  13. if m == db then return x, b end
  14. if m == dl then return l, y end
  15. return r, y
  16. end
  17. function Wall:activate(map)
  18. if not Wall.texture then
  19. local x, y, w, h = map.textures.wall:getViewport()
  20. Wall.texture = love.graphics.newCanvas(w, h)
  21. Wall.texture:renderTo(function()
  22. love.graphics.setColor(255, 255, 255)
  23. love.graphics.draw(map.atlas, map.textures.wall)
  24. end)
  25. Wall.texture:setWrap('repeat', 'repeat')
  26. end
  27. ctx.event:emit('collision.attach', {object = self})
  28. self.top = love.graphics.newMesh({
  29. {0, 0, 0, 0},
  30. {0, 0, 1, 0},
  31. {0, 0, 1, 1},
  32. {0, 0, 0, 1}
  33. }, self.texture)
  34. self.north = love.graphics.newMesh({
  35. {self.x, self.y, 0, 0, 0, 0, 0},
  36. {self.x + self.width, self.y, 1, 0, 0, 0, 0},
  37. {0, 0, 1, 1},
  38. {0, 0, 0, 1}
  39. }, self.texture)
  40. self.south = love.graphics.newMesh({
  41. {0, 0, 0, 0},
  42. {0, 0, 1, 0},
  43. {self.x + self.width, self.y + self.height, 1, 1, 0, 0, 0},
  44. {self.x, self.y + self.height, 0, 1, 0, 0, 0}
  45. }, self.texture)
  46. self.east = love.graphics.newMesh({
  47. {0, 0, 0, 0},
  48. {self.x + self.width, self.y, 1, 0, 0, 0, 0},
  49. {self.x + self.width, self.y + self.height, 1, 1, 0, 0, 0},
  50. {0, 0, 0, 1}
  51. }, self.texture)
  52. self.west = love.graphics.newMesh({
  53. {self.x, self.y, 0, 0, 0, 0, 0},
  54. {0, 0, 1, 0},
  55. {0, 0, 1, 1},
  56. {self.x, self.y + self.height, 0, 1, 0, 0, 0}
  57. }, self.texture)
  58. self.meshX = self.x
  59. self.meshY = self.y
  60. self.depth = -5
  61. if ctx.view then ctx.view:register(self) end
  62. end
  63. function Wall:deactivate()
  64. ctx.event:emit('collision.detach', {object = self})
  65. if ctx.view then ctx.view:unregister(self) end
  66. end
  67. function Wall:update()
  68. if ctx.view then
  69. if not self:inView() then return end
  70. local x1, y1 = ctx.view.x + ctx.view.width / 2, ctx.view.y + ctx.view.height / 2
  71. local x2, y2 = perim(x1, y1, self.x, self.y, self.width, self.height)
  72. self.depth = math.clamp(math.distance(x1, y1, x2, y2) * ctx.view.scale - 1000 - self.z, -4096, -16)
  73. end
  74. if self.meshX ~= self.x or self.meshY ~= y then
  75. self:updateMesh()
  76. end
  77. end
  78. function Wall:draw()
  79. if not self:inView() then return end
  80. local v = ctx.view
  81. local ulx, uly = v:three(self.x, self.y, self.z)
  82. local urx, ury = v:three(self.x + self.width, self.y, self.z)
  83. local llx, lly = v:three(self.x, self.y + self.height, self.z)
  84. local lrx, lry = v:three(self.x + self.width, self.y + self.height, self.z)
  85. local w, h = self.width / self.texture:getWidth(), self.height / self.texture:getHeight()
  86. self.top:setVertex(1, ulx, uly, 0, 0)
  87. self.top:setVertex(2, urx, ury, w, 0)
  88. self.top:setVertex(3, lrx, lry, w, h)
  89. self.top:setVertex(4, llx, lly, 0, h)
  90. love.graphics.setColor(255, 255, 255)
  91. local y2 = ctx.view.y + (ctx.view.height / 2)
  92. if self.y > y2 then
  93. self.north:setVertex(3, urx, ury, w, h)
  94. self.north:setVertex(4, ulx, uly, 0, h)
  95. love.graphics.draw(self.north, 0, 0)
  96. end
  97. if self.y + self.height < y2 then
  98. self.south:setVertex(1, llx, lly, 0, 0)
  99. self.south:setVertex(2, lrx, lry, w, 0)
  100. love.graphics.draw(self.south, 0, 0)
  101. end
  102. local x2 = ctx.view.x + (ctx.view.width / 2)
  103. if self.x > x2 then
  104. self.west:setVertex(2, ulx, uly, w, 0)
  105. self.west:setVertex(3, llx, lly, w, h)
  106. love.graphics.draw(self.west, 0, 0)
  107. end
  108. if self.x + self.width < x2 then
  109. self.east:setVertex(1, urx, ury, 0, 0)
  110. self.east:setVertex(4, lrx, lry, 0, h)
  111. love.graphics.draw(self.east, 0, 0)
  112. end
  113. love.graphics.draw(self.top, 0, 0)
  114. end
  115. function Wall:inView()
  116. local x, y, w, h = self.x, self.y, self.width, self.height
  117. local v = ctx.view
  118. return x + w >= v.x and x <= v.x + v.width and y + h >= v.y and y <= v.y + v.height
  119. end
  120. function Wall:updateMesh()
  121. local w, h = self.width / self.texture:getWidth(), self.height / self.texture:getHeight()
  122. self.north:setVertex(1, self.x, self.y, 0, 0, 0, 0, 0)
  123. self.north:setVertex(2, self.x + self.width, self.y, w, 0, 0, 0, 0)
  124. self.south:setVertex(3, self.x + self.width, self.y + self.height, w, h, 0, 0, 0)
  125. self.south:setVertex(4, self.x, self.y + self.height, 0, h, 0, 0, 0)
  126. self.east:setVertex(2, self.x + self.width, self.y, w, 0, 0, 0, 0)
  127. self.east:setVertex(3, self.x + self.width, self.y + self.height, w, h, 0, 0, 0)
  128. self.west:setVertex(1, self.x, self.y, 0, 0, 0, 0, 0)
  129. self.west:setVertex(4, self.x, self.y + self.height, 0, h, 0, 0, 0)
  130. self.meshX = self.x
  131. self.meshY = self.y
  132. end
  133. function Wall:__tostring()
  134. return [[{
  135. kind = 'wall',
  136. x = ]] .. self.x .. [[,
  137. y = ]] .. self.y .. [[,
  138. w = ]] .. self.width .. [[,
  139. h = ]] .. self.height .. [[,
  140. z = ]] .. self.z .. [[
  141. }]]
  142. end
  143. return Wall