From 5b81a67f32f568d44c68fdbc86462c6cd0a10f99 Mon Sep 17 00:00:00 2001 From: erick Date: Sat, 23 Nov 2024 22:07:42 -0300 Subject: [PATCH 1/5] collision classe implemented --- collider.lua | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++ world.lua | 21 ++++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/collider.lua b/collider.lua index f78d949..28df03d 100644 --- a/collider.lua +++ b/collider.lua @@ -75,4 +75,58 @@ function Collider:collider_contacts() return colliders end +--- Sets a collision class to the collider. +---@param name string +function Collider:setCollisionClass(name) + local cls = self._world.collision_classes[name] + + assert(cls, "collision class '" .. tostring(name) .. "' does not exist") + + local cls_id = cls.id + local cls_info = cls.info + + self.fixture:setCategory(cls_id) + + -- classes to be not inserted + local doesnot_insert = {} + + if cls_info.except then + for i=1, #cls_info.except do + doesnot_insert[cls_info.except[i]] = true + end + end + + local to_ignore = {} + if cls_info.ignores then + -- if it's All then expand to every collision class that exist + if cls_info.ignores == "All" then + cls_info.ignores = {} + for cls_name in pairs(self._world.collision_classes) do + if cls_name ~= name then + cls_info.ignores[#cls_info.ignores+1] = cls_name + end + end + end + + for i=1, #cls_info.ignores do + local ignore_cls = cls_info.ignores[i] + + if not doesnot_insert[ignore_cls] then + local id = self._world.collision_classes[ignore_cls].id + + table.insert(to_ignore, id) + end + end + end + + self.collision_class = name + + self.fixture:setMask(unpack(to_ignore)) +end + +-- returns the collision class of the object +function Collider:getClass() + return self.collision_class +end + return Collider diff --git a/world.lua b/world.lua index aa60b5d..196a693 100644 --- a/world.lua +++ b/world.lua @@ -35,6 +35,12 @@ function World:new(...) w.update = nil -- to use our custom update w.colliders = {} + + w.collision_classes = {} + + -- starts at 1 and go to 16 + w._classes_id = 1 + -- some functions defined here to use w without being passed it function w.collide(obja, objb, coll_type, ...) @@ -330,4 +336,19 @@ function World:newCollider(collider_type, shape_arguments, table_to_use) return o end +--- Adds a collision class to the world +---@param name string +---@param info { ignores: {integer: string} | "All", except?: {integer: string}} +function World:addCollisionClass(name, info) + assert(type(name) == "string", "invalid collision class name") + assert(self._classes_id <= 16, "limit of collision classes was exceeded") + + self.collision_classes[name] = { + info = info or {}, + id = self._classes_id + } + + self._classes_id = self._classes_id + 1 +end + return World From ba35b049dc20733d974af538da6d05b0e53b0fdb Mon Sep 17 00:00:00 2001 From: erick Date: Sat, 23 Nov 2024 22:08:22 -0300 Subject: [PATCH 2/5] test for collision classes --- test/test_collisionclass/main.lua | 58 +++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 test/test_collisionclass/main.lua diff --git a/test/test_collisionclass/main.lua b/test/test_collisionclass/main.lua new file mode 100644 index 0000000..9bc39b4 --- /dev/null +++ b/test/test_collisionclass/main.lua @@ -0,0 +1,58 @@ +local bf = require "breezefield" + +local world = bf.newWorld(0,100,true) + +world:addCollisionClass("GroundA") +world:addCollisionClass("GroundB") +world:addCollisionClass("GroundC") + +world:addCollisionClass("CircleA", { + ignores = "All", + except = {"GroundA"} +}) + +world:addCollisionClass("CircleB", { + ignores = "All", + except = {"GroundB"} +}) + +world:addCollisionClass("CircleC", { + ignores = "All", + except = {"GroundC"} +}) + + +local groundA, groundB, groundC +local circleA, circleB, circleC + +function love.load() + local w_width = love.graphics.getWidth() + local w_height = love.graphics.getHeight() + groundA = world:newCollider("Rectangle", {w_width/2, 50, w_width, 5}) + groundB = world:newCollider("Rectangle", {w_width/2, 100, w_width, 5}) + groundC = world:newCollider("Rectangle", {w_width/2, 150, w_width, 5}) + groundA:setCollisionClass("GroundA") + groundB:setCollisionClass("GroundB") + groundC:setCollisionClass("GroundC") + + groundA:setType("static") + groundB:setType("static") + groundC:setType("static") + + circleA = world:newCollider("Circle", {100, 10, 10}) + circleA:setCollisionClass("CircleA") + + circleB = world:newCollider("Circle", {200, 10, 10}) + circleB:setCollisionClass("CircleB") + + circleA = world:newCollider("Circle", {300, 10, 10}) + circleA:setCollisionClass("CircleC") +end + +function love.update(dt) + world:update(dt) +end + +function love.draw() + world:draw() +end From ca96cbe0d2f4e6e1e40713b3415ab0a692889510 Mon Sep 17 00:00:00 2001 From: erick Date: Sat, 23 Nov 2024 22:08:48 -0300 Subject: [PATCH 3/5] README updated --- README.org | 50 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/README.org b/README.org index b06b179..c6ee4fb 100644 --- a/README.org +++ b/README.org @@ -79,6 +79,42 @@ if there are any issues in breezefields implementation that complicates using love.physics together with it, let me know, or better yet, send a pull request +** Collision classes + +Collision classes allow you to set filters to some colliders. +Collision classes in breezelfield is just like windfield. +If you want to the colldier A ignores collider B, you would do: + +#+BEGIN_SRC lua +local bf = require "breezefield" + +local world = bf.newWorld(0, 100) + +-- creating collision classes -- +world:addCollisionClass("ColliderB") +world:addCollisionClass("ColliderA", { + ignores = {"ColliderB"}, +}) + +-- creating colliders +local colliderA = world:newCollider("Rectangle", {100, 100, 32, 32}) +local colliderB = world:newCollider("Rectangle", {120, 100, 32, 32}) + +-- adding to colliders -- +colliderA:setCollisionClass("ColliderA") +colliderB:setCollisionClass("ColliderB") + +function love.update(dt) + world:update(dt) +end + +function love.draw() + world:draw() +end +#+END_SRC + +See the folder tests/test_collisionclass for deep undestanding. + * Installation I reccomend you ensure you understand love.physics, as breezefield mostly just wraps that. You can start [[https://love2d.org/wiki/Tutorial:Physics][here]]. To install simply clone or download the repository and place breezefield anywhere in your lua path or in your project directory. @@ -95,14 +131,14 @@ function love.load() -- any function of love.physics.world should work on World print(world:getGravity()) - ground = bf.Collider.new(world, "Polygon", + ground = world:newCollider("Polygon", {0, 550, 650, 550 , 650, 650, 0, 650}) ground:setType("static") - ball = bf.Collider.new(world, "Circle", 325, 325, 20) + ball = world:newCollider("Circle", 325, 325, 20) ball:setRestitution(0.8) -- any function of shape/body/fixture works - block1 = bf.Collider.new(world, "Polygon", {150, 375, 250, 375, + block1 = world:newCollider("Polygon", {150, 375, 250, 375, 250, 425, 150, 425}) end @@ -148,7 +184,7 @@ function spawn_random_ball() end function little_ball.new(x, y) - local n = bf.Collider.new(world, 'Circle', x, y, 5) + local n = world:newCollider('Circle', x, y, 5) setmetatable(n, little_ball) return n end @@ -201,13 +237,7 @@ and after little_ball's declaration #+BEGIN_SRC lua little_ball.identity = little_ball #+END_SRC -** TODO define some form of collision filtering - for now, see: - [[https://love2d.org/wiki/Contact:setEnabled]] - [[https://love2d.org/wiki/Fixture:setFilterData]] - - * links ** forum [[https://love2d.org/forums/viewtopic.php?f=5&t=86113&p=224718#p224718][forum]] From b27403b7ce921f389f3e928818131dfc100338b6 Mon Sep 17 00:00:00 2001 From: erick Date: Sat, 23 Nov 2024 22:38:09 -0300 Subject: [PATCH 4/5] executing test_collisionclass --- test.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) mode change 100644 => 100755 test.sh diff --git a/test.sh b/test.sh old mode 100644 new mode 100755 index 9b1b0f2..3458890 --- a/test.sh +++ b/test.sh @@ -14,4 +14,8 @@ love test/test_rendering mkdir test/test_queryareas/breezefield cp * test/test_queryareas/breezefield -love test/test_queryareas \ No newline at end of file +love test/test_queryareas + +mkdir test/test_collisionclass/breezefield +cp * test/test_collisionclass/breezefield +love test/test_collisionclass \ No newline at end of file From 773e5e9f856e878215557503b8a66afc44a2f8a6 Mon Sep 17 00:00:00 2001 From: erick Date: Sun, 24 Nov 2024 10:00:52 -0300 Subject: [PATCH 5/5] README improved a bit --- README.org | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.org b/README.org index c6ee4fb..fd8cd47 100644 --- a/README.org +++ b/README.org @@ -81,9 +81,9 @@ ** Collision classes -Collision classes allow you to set filters to some colliders. -Collision classes in breezelfield is just like windfield. -If you want to the colldier A ignores collider B, you would do: +Collision classes allow you to set filters to colliders. +Collision classes in breezefield is just like windfield. +If you want to the collider A ignores collider B (or collider B ignores collider A), you would do: #+BEGIN_SRC lua local bf = require "breezefield"