bump.lua 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. --- Bump.lua plugin for STI
  2. -- @module bump.lua
  3. -- @author David Serrano (BobbyJones|FrenchFryLord)
  4. -- @copyright 2019
  5. -- @license MIT/X11
  6. local lg = require((...):gsub('plugins.bump', 'graphics'))
  7. return {
  8. bump_LICENSE = "MIT/X11",
  9. bump_URL = "https://github.com/karai17/Simple-Tiled-Implementation",
  10. bump_VERSION = "3.1.7.1",
  11. bump_DESCRIPTION = "Bump hooks for STI.",
  12. --- Adds each collidable tile to the Bump world.
  13. -- @param world The Bump world to add objects to.
  14. -- @return collidables table containing the handles to the objects in the Bump world.
  15. bump_init = function(map, world)
  16. local collidables = {}
  17. for _, tileset in ipairs(map.tilesets) do
  18. for _, tile in ipairs(tileset.tiles) do
  19. local gid = tileset.firstgid + tile.id
  20. if map.tileInstances[gid] then
  21. for _, instance in ipairs(map.tileInstances[gid]) do
  22. -- Every object in every instance of a tile
  23. if tile.objectGroup then
  24. for _, object in ipairs(tile.objectGroup.objects) do
  25. if object.properties.collidable == true then
  26. local t = {
  27. name = object.name,
  28. type = object.type,
  29. x = instance.x + map.offsetx + object.x,
  30. y = instance.y + map.offsety + object.y,
  31. width = object.width,
  32. height = object.height,
  33. layer = instance.layer,
  34. properties = object.properties
  35. }
  36. world:add(t, t.x, t.y, t.width, t.height)
  37. table.insert(collidables, t)
  38. end
  39. end
  40. end
  41. -- Every instance of a tile
  42. if tile.properties and tile.properties.collidable == true then
  43. local t = {
  44. x = instance.x + map.offsetx,
  45. y = instance.y + map.offsety,
  46. width = map.tilewidth,
  47. height = map.tileheight,
  48. layer = instance.layer,
  49. type = tile.type,
  50. properties = tile.properties
  51. }
  52. world:add(t, t.x, t.y, t.width, t.height)
  53. table.insert(collidables, t)
  54. end
  55. end
  56. end
  57. end
  58. end
  59. for _, layer in ipairs(map.layers) do
  60. -- Entire layer
  61. if layer.properties.collidable == true then
  62. if layer.type == "tilelayer" then
  63. for y, tiles in ipairs(layer.data) do
  64. for x, tile in pairs(tiles) do
  65. if tile.objectGroup then
  66. for _, object in ipairs(tile.objectGroup.objects) do
  67. if object.properties.collidable == true then
  68. local t = {
  69. name = object.name,
  70. type = object.type,
  71. x = ((x-1) * map.tilewidth + tile.offset.x + map.offsetx) + object.x,
  72. y = ((y-1) * map.tileheight + tile.offset.y + map.offsety) + object.y,
  73. width = object.width,
  74. height = object.height,
  75. layer = layer,
  76. properties = object.properties
  77. }
  78. world:add(t, t.x, t.y, t.width, t.height)
  79. table.insert(collidables, t)
  80. end
  81. end
  82. end
  83. local t = {
  84. x = (x-1) * map.tilewidth + tile.offset.x + map.offsetx,
  85. y = (y-1) * map.tileheight + tile.offset.y + map.offsety,
  86. width = tile.width,
  87. height = tile.height,
  88. layer = layer,
  89. type = tile.type,
  90. properties = tile.properties
  91. }
  92. world:add(t, t.x, t.y, t.width, t.height)
  93. table.insert(collidables, t)
  94. end
  95. end
  96. elseif layer.type == "imagelayer" then
  97. world:add(layer, layer.x, layer.y, layer.width, layer.height)
  98. table.insert(collidables, layer)
  99. end
  100. end
  101. -- individual collidable objects in a layer that is not "collidable"
  102. -- or whole collidable objects layer
  103. if layer.type == "objectgroup" then
  104. for _, obj in ipairs(layer.objects) do
  105. if layer.properties.collidable == true or obj.properties.collidable == true then
  106. if obj.shape == "rectangle" then
  107. local t = {
  108. name = obj.name,
  109. type = obj.type,
  110. x = obj.x + map.offsetx,
  111. y = obj.y + map.offsety,
  112. width = obj.width,
  113. height = obj.height,
  114. layer = layer,
  115. properties = obj.properties
  116. }
  117. if obj.gid then
  118. t.y = t.y - obj.height
  119. end
  120. world:add(t, t.x, t.y, t.width, t.height)
  121. table.insert(collidables, t)
  122. end -- TODO implement other object shapes?
  123. end
  124. end
  125. end
  126. end
  127. map.bump_world = world
  128. map.bump_collidables = collidables
  129. end,
  130. --- Remove layer
  131. -- @param index to layer to be removed
  132. bump_removeLayer = function(map, index)
  133. local layer = assert(map.layers[index], "Layer not found: " .. index)
  134. local collidables = map.bump_collidables
  135. -- Remove collision objects
  136. for i = #collidables, 1, -1 do
  137. local obj = collidables[i]
  138. if obj.layer == layer
  139. and (
  140. layer.properties.collidable == true
  141. or obj.properties.collidable == true
  142. ) then
  143. map.bump_world:remove(obj)
  144. table.remove(collidables, i)
  145. end
  146. end
  147. end,
  148. --- Draw bump collisions world.
  149. -- @param world bump world holding the tiles geometry
  150. -- @param tx Translate on X
  151. -- @param ty Translate on Y
  152. -- @param sx Scale on X
  153. -- @param sy Scale on Y
  154. bump_draw = function(map, tx, ty, sx, sy)
  155. lg.push()
  156. lg.scale(sx or 1, sy or sx or 1)
  157. lg.translate(math.floor(tx or 0), math.floor(ty or 0))
  158. local items = map.bump_world:getItems()
  159. for _, item in ipairs(items) do
  160. lg.rectangle("line", map.bump_world:getRect(item))
  161. end
  162. lg.pop()
  163. end
  164. }
  165. --- Custom Properties in Tiled are used to tell this plugin what to do.
  166. -- @table Properties
  167. -- @field collidable set to true, can be used on any Layer, Tile, or Object