diff --git a/CHANGELOG.md b/CHANGELOG.md index d268b70..4cfdb3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **actor2D:** Make hitbox modifiable. +- **actor2D:** Add multiple hitbox support. + ### Changed - **world2D:** Use a list for bodies (hitboxes, etc) and one other for actors diff --git a/examples/gameplay/plateform/actors/player.lua b/examples/gameplay/plateform/actors/player.lua index cc892f6..80eb06b 100644 --- a/examples/gameplay/plateform/actors/player.lua +++ b/examples/gameplay/plateform/actors/player.lua @@ -6,6 +6,9 @@ function Player:new(world, x, y, id) self:setSprite("player", 8, 12) self:cloneSprite() self:setYGravity(480) + + self.isPunching = false + self.direction = 1 end function Player:updateStart(dt) @@ -19,13 +22,29 @@ function Player:updateStart(dt) else self.mainHitbox:modify(0, 0, 16, 24) end - if self.keys["left"].isDown then + if self.keys["left"].isDown and (not self.isPunching) then self.xsp = -120 end - if self.keys["right"].isDown then + if self.keys["right"].isDown and (not self.isPunching) then self.xsp = 120 end + if self.keys["A"].isDown then + self.isPunching = true + if (self.direction == 1) then + self:addHitbox("punch", "punch", 16, 6, 12, 12, false) + else + self:addHitbox("punch", "punch", -12, 6, 12, 12, false) + end + else + self.isPunching = false + self:removeHitbox("punch") + end + + if (self.isPunching) then + self:checkHitboxCollisions("punch") + end + if self.keys["start"].isPressed then --self.world:switchActivity() --self.assets:switchActivity() @@ -43,6 +62,9 @@ end function Player:setAnimation() self:setCustomSpeed(math.abs(self.xsp) / 12) + if (self.isPunching) then + self:changeAnimation("punch", false) + else if (self.onGround) then if math.abs(self.xsp) > 0 then self:changeAnimation("walk", false) @@ -52,12 +74,14 @@ function Player:setAnimation() else self:changeAnimation("jump", true) end + end end function Player:setDirection(direction) direction = direction or 0 if direction ~= 0 then direction = utils.math.sign(direction) + self.direction = direction self:setSpriteScallingX(direction) end end @@ -68,9 +92,15 @@ function Player:collisionResponse(collision) end end +function Player:hitboxResponse(name, type, collision) + if (collision.other.type == "coin") and (type == "punch") then + collision.other.owner:takeCoin(self) + end +end + function Player:draw() Player.super.draw(self) - self:drawMainHitbox() + self:drawHitboxes() utils.graphics.resetColor() end diff --git a/examples/gameplay/plateform/assets/monkey_lad.lua b/examples/gameplay/plateform/assets/monkey_lad.lua index a854bdd..89bced3 100644 --- a/examples/gameplay/plateform/assets/monkey_lad.lua +++ b/examples/gameplay/plateform/assets/monkey_lad.lua @@ -43,8 +43,8 @@ return { pauseAtEnd = false, }, ["punch"] = { - startAt = 10, - endAt = 10, + startAt = 11, + endAt = 11, loop = 1, speed = 0, pauseAtEnd = false, diff --git a/gamecore/modules/world/actors/actor2D.lua b/gamecore/modules/world/actors/actor2D.lua index 669f697..0ffeffd 100644 --- a/gamecore/modules/world/actors/actor2D.lua +++ b/gamecore/modules/world/actors/actor2D.lua @@ -34,7 +34,7 @@ local Hitbox = require(cwd .. "utils.hitbox2D") function Actor2D:new(world, type, x, y, w, h, isSolid) self:setCoordinate(x, y) Actor2D.super.new(self, world, type, isSolid) - self:initMainHitbox(w, h) + self:initHitboxes(w, h) end function BaseActor:destroy() @@ -178,14 +178,76 @@ end -- HITBOXES FUNCTIONS -- Functions related to actor hitboxes -function Actor2D:initMainHitbox(w, h) +function Actor2D:initHitboxes(w, h) self.w = w or 0 self.h = h or 0 + self:initMainHitbox() + + self.hitboxes = {} +end + +function Actor2D:initMainHitbox() self.mainHitbox = Hitbox(self, self.type, 0, 0, self.w, self.h, self.isSolid) self.world:registerBody(self.mainHitbox) end +function Actor2D:addHitbox(name, type, ox, oy, w, h, isSolid) + if (self.hitboxes[name] ~= nil) then + print("ERROR:", "The hitbox " .. name .. " already exists") + else + local hitbox = Hitbox(self, type, ox, oy, w, h, isSolid) + self.hitboxes[name] = hitbox + self.world:registerBody(self.hitboxes[name]) + return hitbox + end +end + +function Actor2D:checkHitboxCollisions(name, filter) + self:checkHitboxCollisionsAtPoint(name, self.x, self.y, filter) +end + +function Actor2D:checkHitboxCollisionsAtPoint(name, dx, dy, filter) + local x, y, cols, colNumber = dx, dy, {}, 0 + local filter = filter or self.filter + if (self.isDestroyed == false) and (self.hitboxes[name] ~= nil) then + x, y, cols, colNumber = self.hitboxes[name]:checkCollision(dx, dy, filter) + local type = self.hitboxes[name].type + + for i, col in ipairs(cols) do + self:hitboxResponse(name, type, col) + end + end + + return x, y, cols, colNumber +end + +function Actor2D:hitboxResponse(name, type, collision) + -- just a blank placeholder function +end + +function Actor2D:removeHitbox(name) + if (self.hitboxes[name] ~= nil) then + self.world:removeBody(self.hitboxes[name]) + self.hitboxes[name] = nil + end +end + +function Actor2D:purgeHitbox() + for k,v in pairs(self.hitboxes) do + self.world:removeBody(v) + end + self.hitboxes = {} +end + +function Actor2D:drawHitboxes() + for k,v in pairs(self.hitboxes) do + v:draw() + end + self.mainHitbox:draw() +end + + function Actor2D:drawMainHitbox() self.mainHitbox:draw() end