Merge branch 'new-hitbox-system' of game-projects/gamecore into master
This commit is contained in:
commit
961c7816c1
13 changed files with 492 additions and 60 deletions
22
CHANGELOG.md
22
CHANGELOG.md
|
@ -7,6 +7,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- **actor2D:** Make hitbox modifiable.
|
||||||
|
|
||||||
|
- **actor2D:** Add multiple hitbox support.
|
||||||
|
|
||||||
|
- **assets:** Add a way to get current relative frame
|
||||||
|
|
||||||
|
- **assets:** Add more wrapper around animator functions in Sprite
|
||||||
|
|
||||||
|
- **world:** Add more wrapper around sprite functions in BaseActor
|
||||||
|
|
||||||
|
- **assets:** Add a new getCurrentAnimation function
|
||||||
|
|
||||||
|
- **world:** Add a way to automatically load hitbox from a file
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **world2D:** Use a list for bodies (hitboxes, etc) and one other for actors
|
||||||
|
|
||||||
|
- **world2D:** Make the hitbox an object, owned by the actor
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- **world:** Remove a forgotten camera debug function
|
- **world:** Remove a forgotten camera debug function
|
||||||
|
|
|
@ -7,7 +7,7 @@ function Parent:new(world, type, x, y, w, h, isSolid)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Parent:draw()
|
function Parent:draw()
|
||||||
self:drawHitbox()
|
self:drawMainHitbox()
|
||||||
end
|
end
|
||||||
|
|
||||||
return Parent
|
return Parent
|
||||||
|
|
|
@ -7,7 +7,7 @@ function Wall:new(world, x, y, w, h)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Wall:draw()
|
function Wall:draw()
|
||||||
self:drawHitbox()
|
self:drawMainHitbox()
|
||||||
utils.graphics.resetColor( )
|
utils.graphics.resetColor( )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,12 @@ function Player:new(world, x, y, id)
|
||||||
self:setSprite("player", 8, 12)
|
self:setSprite("player", 8, 12)
|
||||||
self:cloneSprite()
|
self:cloneSprite()
|
||||||
self:setYGravity(480)
|
self:setYGravity(480)
|
||||||
|
|
||||||
|
self.isPunching = false
|
||||||
|
self.direction = 1
|
||||||
|
|
||||||
|
self.punchName = ""
|
||||||
|
self:setHitboxFile("examples.gameplay.plateform.assets.playerhitbox")
|
||||||
end
|
end
|
||||||
|
|
||||||
function Player:updateStart(dt)
|
function Player:updateStart(dt)
|
||||||
|
@ -15,15 +21,27 @@ function Player:updateStart(dt)
|
||||||
self.ysp = -280
|
self.ysp = -280
|
||||||
end
|
end
|
||||||
if self.keys["down"].isDown then
|
if self.keys["down"].isDown then
|
||||||
--self.ysp = 120
|
self.mainHitbox:modify(0, 8, 16, 16)
|
||||||
|
else
|
||||||
|
self.mainHitbox:modify(0, 0, 16, 24)
|
||||||
end
|
end
|
||||||
if self.keys["left"].isDown then
|
if self.keys["left"].isDown and (not self.isPunching) then
|
||||||
self.xsp = -120
|
self.xsp = -120
|
||||||
end
|
end
|
||||||
if self.keys["right"].isDown then
|
if self.keys["right"].isDown and (not self.isPunching) then
|
||||||
self.xsp = 120
|
self.xsp = 120
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if self.keys["A"].isDown then
|
||||||
|
self.isPunching = true
|
||||||
|
else
|
||||||
|
self.isPunching = false
|
||||||
|
end
|
||||||
|
|
||||||
|
if (self.isPunching) then
|
||||||
|
self:checkHitboxesCollisions()
|
||||||
|
end
|
||||||
|
|
||||||
if self.keys["start"].isPressed then
|
if self.keys["start"].isPressed then
|
||||||
--self.world:switchActivity()
|
--self.world:switchActivity()
|
||||||
--self.assets:switchActivity()
|
--self.assets:switchActivity()
|
||||||
|
@ -41,6 +59,9 @@ end
|
||||||
|
|
||||||
function Player:setAnimation()
|
function Player:setAnimation()
|
||||||
self:setCustomSpeed(math.abs(self.xsp) / 12)
|
self:setCustomSpeed(math.abs(self.xsp) / 12)
|
||||||
|
if (self.isPunching) then
|
||||||
|
self:changeAnimation("punch", false)
|
||||||
|
else
|
||||||
if (self.onGround) then
|
if (self.onGround) then
|
||||||
if math.abs(self.xsp) > 0 then
|
if math.abs(self.xsp) > 0 then
|
||||||
self:changeAnimation("walk", false)
|
self:changeAnimation("walk", false)
|
||||||
|
@ -50,22 +71,36 @@ function Player:setAnimation()
|
||||||
else
|
else
|
||||||
self:changeAnimation("jump", true)
|
self:changeAnimation("jump", true)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Player:setDirection(direction)
|
function Player:setDirection(direction)
|
||||||
direction = direction or 0
|
direction = direction or 0
|
||||||
if direction ~= 0 then
|
if direction ~= 0 then
|
||||||
direction = utils.math.sign(direction)
|
direction = utils.math.sign(direction)
|
||||||
|
self.direction = direction
|
||||||
self:setSpriteScallingX(direction)
|
self:setSpriteScallingX(direction)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Player:collisionResponse(collision)
|
function Player:collisionResponse(collision)
|
||||||
if collision.other.type == "coin" then
|
if collision.other.type == "coin" then
|
||||||
collision.other:takeCoin(self)
|
collision.other.owner:takeCoin(self)
|
||||||
end
|
end
|
||||||
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:drawHitboxes()
|
||||||
|
utils.graphics.resetColor()
|
||||||
|
end
|
||||||
|
|
||||||
function Player:drawHUD(id)
|
function Player:drawHUD(id)
|
||||||
love.graphics.print(id .. " test", 4, 4)
|
love.graphics.print(id .. " test", 4, 4)
|
||||||
end
|
end
|
||||||
|
|
|
@ -43,8 +43,8 @@ return {
|
||||||
pauseAtEnd = false,
|
pauseAtEnd = false,
|
||||||
},
|
},
|
||||||
["punch"] = {
|
["punch"] = {
|
||||||
startAt = 10,
|
startAt = 11,
|
||||||
endAt = 10,
|
endAt = 11,
|
||||||
loop = 1,
|
loop = 1,
|
||||||
speed = 0,
|
speed = 0,
|
||||||
pauseAtEnd = false,
|
pauseAtEnd = false,
|
||||||
|
|
13
examples/gameplay/plateform/assets/playerhitbox.lua
Normal file
13
examples/gameplay/plateform/assets/playerhitbox.lua
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
return {
|
||||||
|
["idle"] = {
|
||||||
|
{
|
||||||
|
{"main", 0, 0, 16, 24, true}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
["punch"] = {
|
||||||
|
{
|
||||||
|
{"main", 0, 0, 16, 24, true},
|
||||||
|
{"punch", 16, 6, 12, 12, false}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -94,6 +94,10 @@ end
|
||||||
-- INFO FUNCTIONS
|
-- INFO FUNCTIONS
|
||||||
-- get information with these functions
|
-- get information with these functions
|
||||||
|
|
||||||
|
function Animator:getCurrentAnimation()
|
||||||
|
return self.currentAnimation
|
||||||
|
end
|
||||||
|
|
||||||
function Animator:getAnimationDuration(animation)
|
function Animator:getAnimationDuration(animation)
|
||||||
return (self.animationData.endAt - self.animationData.startAt) / self.animationData.speed
|
return (self.animationData.endAt - self.animationData.startAt) / self.animationData.speed
|
||||||
end
|
end
|
||||||
|
@ -102,6 +106,10 @@ function Animator:getFrame()
|
||||||
return self.frame
|
return self.frame
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Animator:getRelativeFrame()
|
||||||
|
return self.frame - (self.animationData.startAt) + 1
|
||||||
|
end
|
||||||
|
|
||||||
function Animator:animationExist(name)
|
function Animator:animationExist(name)
|
||||||
return (self.sprite.data.animations[self.currentAnimation] ~= nil)
|
return (self.sprite.data.animations[self.currentAnimation] ~= nil)
|
||||||
end
|
end
|
||||||
|
|
|
@ -66,6 +66,10 @@ end
|
||||||
-- INFO FUNCTIONS
|
-- INFO FUNCTIONS
|
||||||
-- get information with these functions
|
-- get information with these functions
|
||||||
|
|
||||||
|
function Sprite:getCurrentAnimation()
|
||||||
|
return self.animator:getCurrentAnimation()
|
||||||
|
end
|
||||||
|
|
||||||
function Sprite:animationExist(name)
|
function Sprite:animationExist(name)
|
||||||
return self.animator:animationExist(name)
|
return self.animator:animationExist(name)
|
||||||
end
|
end
|
||||||
|
@ -74,6 +78,18 @@ function Sprite:getDimensions()
|
||||||
return self.tileset:getDimensions()
|
return self.tileset:getDimensions()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Sprite:getFrame()
|
||||||
|
return self.animator:getFrame()
|
||||||
|
end
|
||||||
|
|
||||||
|
function Sprite:getAnimationDuration(animation)
|
||||||
|
return self.animator:getAnimationDuration(animation)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Sprite:getRelativeFrame()
|
||||||
|
return self.animator:getRelativeFrame()
|
||||||
|
end
|
||||||
|
|
||||||
-- DRAW FUNCTIONS
|
-- DRAW FUNCTIONS
|
||||||
-- Draw sprites using these functions
|
-- Draw sprites using these functions
|
||||||
|
|
||||||
|
|
|
@ -26,12 +26,21 @@ local cwd = (...):gsub('%.actor2D$', '') .. "."
|
||||||
local BaseActor = require(cwd .. "baseactor")
|
local BaseActor = require(cwd .. "baseactor")
|
||||||
local Actor2D = BaseActor:extend()
|
local Actor2D = BaseActor:extend()
|
||||||
|
|
||||||
|
local Hitbox = require(cwd .. "utils.hitbox2D")
|
||||||
|
|
||||||
-- INIT FUNCTIONS
|
-- INIT FUNCTIONS
|
||||||
-- Initialise the actor and its base functions
|
-- Initialise the actor and its base functions
|
||||||
|
|
||||||
function Actor2D:new(world, type, x, y, w, h, isSolid)
|
function Actor2D:new(world, type, x, y, w, h, isSolid)
|
||||||
self:initHitbox(x, y, w, h)
|
self:setCoordinate(x, y)
|
||||||
Actor2D.super.new(self, world, type, isSolid)
|
Actor2D.super.new(self, world, type, isSolid)
|
||||||
|
self:initHitboxes(w, h)
|
||||||
|
end
|
||||||
|
|
||||||
|
function BaseActor:destroy()
|
||||||
|
self.world:removeActor(self)
|
||||||
|
self.world:removeBody(self.mainHitbox)
|
||||||
|
self.isDestroyed = true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- MOVEMENT FUNCTIONS
|
-- MOVEMENT FUNCTIONS
|
||||||
|
@ -46,6 +55,7 @@ function Actor2D:initMovement()
|
||||||
end
|
end
|
||||||
|
|
||||||
function Actor2D:autoMove(dt)
|
function Actor2D:autoMove(dt)
|
||||||
|
self:updateHitboxes()
|
||||||
self.onGround = false
|
self.onGround = false
|
||||||
self:applyGravity(dt)
|
self:applyGravity(dt)
|
||||||
|
|
||||||
|
@ -117,7 +127,8 @@ end
|
||||||
function Actor2D:move(dx, dy)
|
function Actor2D:move(dx, dy)
|
||||||
local cols, colNumber = {}, 0
|
local cols, colNumber = {}, 0
|
||||||
if (self.isDestroyed == false) then
|
if (self.isDestroyed == false) then
|
||||||
self.x, self.y, cols, colNumber = self.world:moveActor(self, dx, dy, self.filter)
|
self.x, self.y, cols, colNumber = self.mainHitbox:checkCollision(dx, dy, self.filter)
|
||||||
|
self.mainHitbox:updatePosition()
|
||||||
end
|
end
|
||||||
return self.x, self.y, cols, colNumber
|
return self.x, self.y, cols, colNumber
|
||||||
end
|
end
|
||||||
|
@ -125,7 +136,7 @@ end
|
||||||
function Actor2D:checkCollision(dx, dy)
|
function Actor2D:checkCollision(dx, dy)
|
||||||
local x, y, cols, colNumber = dx, dy, {}, 0
|
local x, y, cols, colNumber = dx, dy, {}, 0
|
||||||
if (self.isDestroyed == false) then
|
if (self.isDestroyed == false) then
|
||||||
x, y, cols, colNumber = self.world:moveActor(self, dx, dy, self.filter)
|
x, y, cols, colNumber = self.mainHitbox:checkCollision(dx, dy, self.filter)
|
||||||
end
|
end
|
||||||
return self.x, self.y, cols, colNumber
|
return self.x, self.y, cols, colNumber
|
||||||
end
|
end
|
||||||
|
@ -165,14 +176,167 @@ function Actor2D:applyGravity(dt)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- COORDINATE FUNCTIONS
|
-- HITBOXES FUNCTIONS
|
||||||
-- Functions related to coordinate and hitbox
|
-- Functions related to actor hitboxes
|
||||||
|
|
||||||
function Actor2D:initHitbox(x, y, w, h)
|
function Actor2D:initHitboxes(w, h)
|
||||||
self.x = x or 0
|
|
||||||
self.y = y or 0
|
|
||||||
self.w = w or 0
|
self.w = w or 0
|
||||||
self.h = h or 0
|
self.h = h or 0
|
||||||
|
|
||||||
|
self:initMainHitbox()
|
||||||
|
|
||||||
|
self.hitboxes = {}
|
||||||
|
self.hitboxListFile = ""
|
||||||
|
self.hitboxList = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function Actor2D:setHitboxFile(file)
|
||||||
|
self.hitboxList = require(file)
|
||||||
|
self.hitboxListFile = file
|
||||||
|
end
|
||||||
|
|
||||||
|
function Actor2D:getAutomaticHitboxLoading()
|
||||||
|
return (self.hitboxList ~= nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Actor2D:getHitboxFile()
|
||||||
|
return self.hitboxListFile
|
||||||
|
end
|
||||||
|
|
||||||
|
function Actor2D:getHitboxList(animation, frame)
|
||||||
|
if (animation == nil) or (self.hitboxList == nil) then
|
||||||
|
return self.hitboxList
|
||||||
|
else
|
||||||
|
local list = self.hitboxList[animation]
|
||||||
|
|
||||||
|
if (frame == nil) or (list == nil) then
|
||||||
|
return list
|
||||||
|
else
|
||||||
|
return list[frame]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Actor2D:updateHitboxes()
|
||||||
|
if (self.hitboxList ~= nil) then
|
||||||
|
self:purgeHitbox()
|
||||||
|
local animation, frame
|
||||||
|
animation = self:getCurrentAnimation()
|
||||||
|
frame = self:getRelativeFrame()
|
||||||
|
local hitboxList = self:getHitboxList(animation, frame)
|
||||||
|
|
||||||
|
if (hitboxList ~= nil) then
|
||||||
|
for i,v in ipairs(hitboxList) do
|
||||||
|
self:addHitboxFromFrameData(v, animation, frame, i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Actor2D:addHitboxFromFrameData(framedata, animationID, frameID, hitboxID)
|
||||||
|
local sx, sy = self:getSpriteScalling()
|
||||||
|
local type = framedata[1]
|
||||||
|
local ox = framedata[2]
|
||||||
|
local oy = framedata[3]
|
||||||
|
local w = framedata[4]
|
||||||
|
local h = framedata[5]
|
||||||
|
local isSolid = framedata[6] or false
|
||||||
|
local anim = animationID or "null"
|
||||||
|
local frame = frameID or 0
|
||||||
|
local id = hitboxID or 0
|
||||||
|
if (sx < 0) then
|
||||||
|
ox = self.w - ox - w
|
||||||
|
end
|
||||||
|
if (sy < 0) then
|
||||||
|
oy = self.h - oy - h
|
||||||
|
end
|
||||||
|
|
||||||
|
if (type == "main") then
|
||||||
|
self.mainHitbox:modify(ox, oy, w, h)
|
||||||
|
else
|
||||||
|
local hitboxName = anim .. frame .. type .. id
|
||||||
|
self:addHitbox(hitboxName, type, ox, oy, w, h, isSolid)
|
||||||
|
return hitboxName
|
||||||
|
end
|
||||||
|
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:checkHitboxesCollisions(filter)
|
||||||
|
for k,v in pairs(self.hitboxes) do
|
||||||
|
self:checkHitboxCollisionsAtPoint(k, self.x, self.y, filter)
|
||||||
|
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
|
||||||
|
|
||||||
|
-- COORDINATE FUNCTION
|
||||||
|
-- Handle the coordinate system
|
||||||
|
|
||||||
|
function Actor2D:setCoordinate(x, y)
|
||||||
|
self.x = x or self.x
|
||||||
|
self.y = y or self.y
|
||||||
end
|
end
|
||||||
|
|
||||||
function Actor2D:getCenter()
|
function Actor2D:getCenter()
|
||||||
|
@ -183,12 +347,6 @@ function Actor2D:getViewCenter()
|
||||||
return self:getCenter()
|
return self:getCenter()
|
||||||
end
|
end
|
||||||
|
|
||||||
function Actor2D:drawHitbox()
|
|
||||||
local x, y = math.floor(self.x), math.floor(self.y)
|
|
||||||
love.graphics.setColor(self.debug.r, self.debug.g, self.debug.b, 1)
|
|
||||||
utils.graphics.box(x, y, self.w, self.h)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- DRAW FUNCTIONS
|
-- DRAW FUNCTIONS
|
||||||
-- Draw the actors.
|
-- Draw the actors.
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,10 @@ end
|
||||||
function BaseActor:setFilter()
|
function BaseActor:setFilter()
|
||||||
-- Init the bump filter
|
-- Init the bump filter
|
||||||
self.filter = function(item, other)
|
self.filter = function(item, other)
|
||||||
if (other.isSolid) then
|
if (other.owner == self) then
|
||||||
|
-- ignore every collision with our own hitboxes
|
||||||
|
return nil
|
||||||
|
elseif (other.isSolid) then
|
||||||
return "slide"
|
return "slide"
|
||||||
else
|
else
|
||||||
return "cross"
|
return "cross"
|
||||||
|
@ -236,6 +239,49 @@ function BaseActor:setSpriteScallingY(sy)
|
||||||
self.sprite.sy = sy
|
self.sprite.sy = sy
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function BaseActor:getCurrentAnimation()
|
||||||
|
if (self.sprite.clone == nil) then
|
||||||
|
return self.assets.sprites[self.sprite.name]:getCurrentAnimation()
|
||||||
|
else
|
||||||
|
return self.sprite.clone:getCurrentAnimation()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function BaseActor:getSpriteScalling()
|
||||||
|
return self.sprite.sx, self.sprite.sy
|
||||||
|
end
|
||||||
|
|
||||||
|
function BaseActor:getFrame()
|
||||||
|
if (self.sprite.name ~= nil) then
|
||||||
|
if (self.sprite.clone ~= nil) then
|
||||||
|
return self.sprite.clone:getFrame()
|
||||||
|
else
|
||||||
|
return self.assets.sprites[self.sprite.name]:getFrame()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function BaseActor:getRelativeFrame()
|
||||||
|
if (self.sprite.name ~= nil) then
|
||||||
|
if (self.sprite.clone ~= nil) then
|
||||||
|
return self.sprite.clone:getRelativeFrame()
|
||||||
|
else
|
||||||
|
return self.assets.sprites[self.sprite.name]:getRelativeFrame()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function BaseActor:getAnimationDuration()
|
||||||
|
if (self.sprite.name ~= nil) then
|
||||||
|
if (self.sprite.clone ~= nil) then
|
||||||
|
return self.sprite.clone:getAnimationDuration()
|
||||||
|
else
|
||||||
|
return self.assets.sprites[self.sprite.name]:getAnimationDuration()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function BaseActor:drawSprite(x, y, r, sx, sy, ox, oy, kx, ky)
|
function BaseActor:drawSprite(x, y, r, sx, sy, ox, oy, kx, ky)
|
||||||
if (self.sprite.name ~= nil) then
|
if (self.sprite.name ~= nil) then
|
||||||
local x = x + self.sprite.ox
|
local x = x + self.sprite.ox
|
||||||
|
|
108
gamecore/modules/world/actors/utils/hitbox2D.lua
Normal file
108
gamecore/modules/world/actors/utils/hitbox2D.lua
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
-- hitbox2D.lua :: a basic 2D hitbox object. It's used by the actors to check
|
||||||
|
-- collisions and to handle different type of responses.
|
||||||
|
|
||||||
|
--[[
|
||||||
|
Copyright © 2019 Kazhnuz
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
]]
|
||||||
|
|
||||||
|
local Hitbox2D = Object:extend()
|
||||||
|
|
||||||
|
-- INIT FUNCTIONS
|
||||||
|
-- Initialise the actor and its base functions
|
||||||
|
|
||||||
|
function Hitbox2D:new(owner, type, ox, oy, w, h, isSolid)
|
||||||
|
self.owner = owner
|
||||||
|
self.world = owner.world
|
||||||
|
|
||||||
|
self.type = type
|
||||||
|
self.ox = ox
|
||||||
|
self.oy = oy
|
||||||
|
self.x, self.y = self:getPosition()
|
||||||
|
self.w = w
|
||||||
|
self.h = h
|
||||||
|
self.isSolid = isSolid
|
||||||
|
|
||||||
|
self:setDebugColor(0,0,0)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Hitbox2D:modify(ox, oy, w, h)
|
||||||
|
self.ox = ox
|
||||||
|
self.oy = oy
|
||||||
|
self.x, self.y = self:getPosition()
|
||||||
|
self.w = w
|
||||||
|
self.h = h
|
||||||
|
end
|
||||||
|
|
||||||
|
function Hitbox2D:setDebugColor(r,g,b)
|
||||||
|
self.debug = {}
|
||||||
|
self.debug.r = r
|
||||||
|
self.debug.g = g
|
||||||
|
self.debug.b = b
|
||||||
|
end
|
||||||
|
|
||||||
|
-- COORDINATE FUNCTIONS
|
||||||
|
-- Handle Hitbox position
|
||||||
|
|
||||||
|
function Hitbox2D:updatePosition()
|
||||||
|
self.x, self.y = self:getPosition()
|
||||||
|
self.world:updateBody(self)
|
||||||
|
return self.x, self.y
|
||||||
|
end
|
||||||
|
|
||||||
|
function Hitbox2D:getPosition()
|
||||||
|
return self.ox + self.owner.x, self.oy + self.owner.y
|
||||||
|
end
|
||||||
|
|
||||||
|
function Hitbox2D:getOwnerPosition()
|
||||||
|
return self.x - self.ox, self.y - self.oy
|
||||||
|
end
|
||||||
|
|
||||||
|
function Hitbox2D:getNewOwnerPosition(x, y)
|
||||||
|
return x - self.ox, y - self.oy
|
||||||
|
end
|
||||||
|
|
||||||
|
function Hitbox2D:getCenter()
|
||||||
|
return self.x + (self.w/2), self.y + (self.h/2)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- COLLISION FUNCTIONS
|
||||||
|
-- Handle Hitbox position
|
||||||
|
|
||||||
|
function Hitbox2D:checkCollision(dx, dy, filter)
|
||||||
|
self:updatePosition()
|
||||||
|
|
||||||
|
local dx, dy = self.ox + dx, self.oy + dy
|
||||||
|
local x, y, cols, colNumber = self.world:checkCollision(self, dx, dy, filter)
|
||||||
|
local newx, newy = self:getNewOwnerPosition(x, y)
|
||||||
|
|
||||||
|
return newx, newy, cols, colNumber
|
||||||
|
end
|
||||||
|
|
||||||
|
-- DRAW FUNCTIONS
|
||||||
|
-- Just some debug function to draw hitbox
|
||||||
|
|
||||||
|
function Hitbox2D:draw()
|
||||||
|
local x, y = self:getPosition()
|
||||||
|
love.graphics.setColor(self.debug.r, self.debug.g, self.debug.b, 1)
|
||||||
|
utils.graphics.box(x, y, self.w, self.h)
|
||||||
|
utils.graphics.resetColor()
|
||||||
|
end
|
||||||
|
|
||||||
|
return Hitbox2D
|
|
@ -121,6 +121,49 @@ function BaseWorld:removeActor(actor)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function BaseWorld:countActors()
|
||||||
|
return #self.actors
|
||||||
|
end
|
||||||
|
|
||||||
|
function BaseWorld:getActors()
|
||||||
|
return self.actors
|
||||||
|
end
|
||||||
|
|
||||||
|
function BaseWorld:getVisibleActors(id)
|
||||||
|
local camx, camy, camw, camh = self.cameras:getViewCoordinate(id)
|
||||||
|
local paddingw = camw * PADDING_VALUE
|
||||||
|
local paddingh = camh * PADDING_VALUE
|
||||||
|
local x = camx - paddingw
|
||||||
|
local y = camy - paddingh
|
||||||
|
local w = camw + paddingw * 2
|
||||||
|
local h = camh + paddingh * 2
|
||||||
|
|
||||||
|
local query = self:queryRect(x, y, w, h)
|
||||||
|
local returnquery = {}
|
||||||
|
|
||||||
|
for i,v in ipairs(query) do
|
||||||
|
table.insert(returnquery, v.owner)
|
||||||
|
end
|
||||||
|
|
||||||
|
return returnquery
|
||||||
|
end
|
||||||
|
|
||||||
|
-- BODIES MANAGEMENT FUNCTIONS
|
||||||
|
-- Basic function to handle bodies. Empty function here as baseworld doesn't
|
||||||
|
-- handle bodies
|
||||||
|
|
||||||
|
function BaseWorld:registerBody(body)
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function BaseWorld:updateBody(body)
|
||||||
|
return x, y, {}, 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function BaseWorld:removeBody(body)
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
function BaseWorld:moveActor(actor, x, y, filter)
|
function BaseWorld:moveActor(actor, x, y, filter)
|
||||||
-- as the baseworld have no collision function, we return empty collision
|
-- as the baseworld have no collision function, we return empty collision
|
||||||
-- datas, but from the same type than bump2D will return
|
-- datas, but from the same type than bump2D will return
|
||||||
|
@ -147,25 +190,6 @@ function BaseWorld:queryRect(x, y, w, h)
|
||||||
return v
|
return v
|
||||||
end
|
end
|
||||||
|
|
||||||
function BaseWorld:countActors()
|
|
||||||
return #self.actors
|
|
||||||
end
|
|
||||||
|
|
||||||
function BaseWorld:getActors()
|
|
||||||
return self.actors
|
|
||||||
end
|
|
||||||
|
|
||||||
function BaseWorld:getVisibleActors(id)
|
|
||||||
local camx, camy, camw, camh = self.cameras:getViewCoordinate(id)
|
|
||||||
local paddingw = camw * PADDING_VALUE
|
|
||||||
local paddingh = camh * PADDING_VALUE
|
|
||||||
local x = camx - paddingw
|
|
||||||
local y = camy - paddingh
|
|
||||||
local w = camw + paddingw * 2
|
|
||||||
local h = camh + paddingh * 2
|
|
||||||
return self:queryRect(x, y, w, h)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- INFO FUNCTIONS
|
-- INFO FUNCTIONS
|
||||||
-- Give infos about the world
|
-- Give infos about the world
|
||||||
|
|
||||||
|
|
|
@ -35,41 +35,43 @@ function World2D:new(scene, actorlist, mapfile)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ACTORS FUNCTIONS
|
-- ACTORS FUNCTIONS
|
||||||
-- Wrappers around Bump2D functions
|
-- Add support for bodies in Actor functions
|
||||||
|
|
||||||
function World2D:initActors()
|
function World2D:initActors()
|
||||||
self.currentCreationID = 0
|
self.currentCreationID = 0
|
||||||
self.actors = Bump.newWorld(50)
|
self.actors = {}
|
||||||
|
self.bodies = Bump.newWorld(50)
|
||||||
end
|
end
|
||||||
|
|
||||||
function World2D:registerActor(actor)
|
function World2D:registerActor(actor)
|
||||||
actor.creationID = self.currentCreationID
|
World2D.super.registerActor(self, actor)
|
||||||
self.currentCreationID = self.currentCreationID + 1
|
|
||||||
return self.actors:add(actor, actor.x, actor.y, actor.w, actor.h)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function World2D:removeActor(actor)
|
function World2D:registerBody(body)
|
||||||
return self.actors:remove(actor)
|
return self.bodies:add(body, body.x, body.y, body.w, body.h)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ACTORS FUNCTIONS
|
||||||
|
-- Wrappers around Bump2D functions
|
||||||
|
|
||||||
|
function World2D:updateBody(body)
|
||||||
|
return self.bodies:update(body, body.x, body.y, body.w, body.h)
|
||||||
|
end
|
||||||
|
|
||||||
|
function World2D:removeBody(body)
|
||||||
|
return self.bodies:remove(body)
|
||||||
end
|
end
|
||||||
|
|
||||||
function World2D:moveActor(actor, x, y, filter)
|
function World2D:moveActor(actor, x, y, filter)
|
||||||
return self.actors:move(actor, x, y, filter)
|
return self.bodies:move(actor, x, y, filter)
|
||||||
end
|
end
|
||||||
|
|
||||||
function World2D:checkCollision(actor, x, y, filter)
|
function World2D:checkCollision(actor, x, y, filter)
|
||||||
return self.actors:check(actor, x, y, filter)
|
return self.bodies:check(actor, x, y, filter)
|
||||||
end
|
end
|
||||||
|
|
||||||
function World2D:queryRect(x, y, w, h)
|
function World2D:queryRect(x, y, w, h)
|
||||||
return self.actors:queryRect(x, y, w, h)
|
return self.bodies:queryRect(x, y, w, h)
|
||||||
end
|
|
||||||
|
|
||||||
function World2D:countActors()
|
|
||||||
return self.actors:countItems()
|
|
||||||
end
|
|
||||||
|
|
||||||
function World2D:getActors()
|
|
||||||
return self.actors:getItems()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return World2D
|
return World2D
|
||||||
|
|
Loading…
Reference in a new issue