203 lines
5.6 KiB
Lua
203 lines
5.6 KiB
Lua
-- actor2D.lua :: the implementation of a 2D actor. It contain every element
|
|
-- needed to create your own 2D actors.
|
|
|
|
--[[
|
|
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 cwd = (...):gsub('%.actor2D$', '') .. "."
|
|
local BaseActor = require(cwd .. "baseactor")
|
|
local Actor2D = BaseActor:extend()
|
|
|
|
-- INIT FUNCTIONS
|
|
-- Initialise the actor and its base functions
|
|
|
|
function Actor2D:new(world, type, x, y, w, h, isSolid)
|
|
self:initHitbox(x, y, w, h)
|
|
Actor2D.super.new(self, world, type, isSolid)
|
|
end
|
|
|
|
-- MOVEMENT FUNCTIONS
|
|
-- Basic functions from the movement.
|
|
|
|
function Actor2D:initMovement()
|
|
self.xsp = 0
|
|
self.ysp = 0
|
|
|
|
self.xfrc = 0
|
|
self.yfrc = 0
|
|
end
|
|
|
|
function Actor2D:autoMove(dt)
|
|
self.onGround = false
|
|
self:applyGravity(dt)
|
|
|
|
local newx, newy, cols, colNumber = self:move(self.x + self.xsp * dt, self.y + self.ysp * dt)
|
|
|
|
-- apply after the movement the friction, until the player stop
|
|
-- note: the friction is applied according to the delta time,
|
|
-- thus the friction should be how much speed is substracted in 1 second
|
|
|
|
self:solveAllCollisions(cols)
|
|
|
|
self.xsp = utils.math.toZero(self.xsp, self.xfrc * dt)
|
|
self.ysp = utils.math.toZero(self.ysp, self.yfrc * dt)
|
|
end
|
|
|
|
function Actor2D:solveAllCollisions(cols)
|
|
for i, col in ipairs(cols) do
|
|
self:collisionResponse(col)
|
|
if (col.type == "touch") or (col.type == "bounce") or (col.type == "slide") then
|
|
self:changeSpeedToCollisionNormal(col.normal.x, col.normal.y)
|
|
end
|
|
end
|
|
end
|
|
|
|
function Actor2D:collisionResponse(collision)
|
|
-- here come the response to the collision
|
|
end
|
|
|
|
function Actor2D:changeSpeedToCollisionNormal(nx, ny)
|
|
local xsp, ysp = self.xsp, self.ysp
|
|
|
|
if (nx < 0 and xsp > 0) or (nx > 0 and xsp < 0) then
|
|
xsp = -xsp * self.bounceFactor
|
|
end
|
|
|
|
if (ny < 0 and ysp > 0) or (ny > 0 and ysp < 0) then
|
|
ysp = -ysp * self.bounceFactor
|
|
end
|
|
|
|
self.xsp, self.ysp = xsp, ysp
|
|
end
|
|
|
|
function Actor2D:checkGroundX()
|
|
local dx, dy = self.x + utils.math.sign(self.xgrav), self.y
|
|
local newx, newy, cols, colNumber = self:checkCollision(dx, dy)
|
|
|
|
for i, col in ipairs(cols) do
|
|
if (col.type == "touch") or (col.type == "bounce") or (col.type == "slide") then
|
|
if not (self.ygrav == 0) then
|
|
if col.normal.x ~= utils.math.sign(self.xgrav) then self.onGround = true end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function Actor2D:checkGroundY()
|
|
local dx, dy = self.x, self.y + utils.math.sign(self.ygrav)
|
|
local newx, newy, cols, colNumber = self:checkCollision(dx, dy)
|
|
|
|
for i, col in ipairs(cols) do
|
|
if (col.type == "touch") or (col.type == "bounce") or (col.type == "slide") then
|
|
if not (self.ygrav == 0) then
|
|
if col.normal.y ~= utils.math.sign(self.ygrav) then self.onGround = true end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function Actor2D:move(dx, dy)
|
|
local cols, colNumber = {}, 0
|
|
if (self.isDestroyed == false) then
|
|
self.x, self.y, cols, colNumber = self.world:moveActor(self, dx, dy, self.filter)
|
|
end
|
|
return self.x, self.y, cols, colNumber
|
|
end
|
|
|
|
function Actor2D:checkCollision(dx, dy)
|
|
local x, y, cols, colNumber = dx, dy, {}, 0
|
|
if (self.isDestroyed == false) then
|
|
x, y, cols, colNumber = self.world:moveActor(self, dx, dy, self.filter)
|
|
end
|
|
return self.x, self.y, cols, colNumber
|
|
end
|
|
|
|
function Actor2D:initGravity()
|
|
local xgrav, ygrav
|
|
|
|
if (self.world.gravity.isDefault) then
|
|
self.xgrav = self.world.gravity.xgrav
|
|
self.ygrav = self.world.gravity.ygrav
|
|
else
|
|
self.xgrav = 0
|
|
self.ygrav = 0
|
|
end
|
|
|
|
self.onGround = false
|
|
end
|
|
|
|
function Actor2D:setXGravity(grav)
|
|
self.xgrav = grav
|
|
end
|
|
|
|
function Actor2D:setYGravity(grav)
|
|
self.ygrav = grav
|
|
end
|
|
|
|
function Actor2D:applyGravity(dt)
|
|
self.xsp = self.xsp + self.xgrav * dt
|
|
self.ysp = self.ysp + self.ygrav * dt
|
|
|
|
if utils.math.sign(self.ysp) == utils.math.sign(self.ygrav) then
|
|
self:checkGroundY( )
|
|
end
|
|
|
|
if utils.math.sign(self.xsp) == utils.math.sign(self.xgrav) then
|
|
self:checkGroundX( )
|
|
end
|
|
end
|
|
|
|
-- COORDINATE FUNCTIONS
|
|
-- Functions related to coordinate and hitbox
|
|
|
|
function Actor2D:initHitbox(x, y, w, h)
|
|
self.x = x or 0
|
|
self.y = y or 0
|
|
self.w = w or 0
|
|
self.h = h or 0
|
|
end
|
|
|
|
function Actor2D:getCenter()
|
|
return (self.x + (self.w / 2)), (self.y + (self.h / 2))
|
|
end
|
|
|
|
function Actor2D:getViewCenter()
|
|
return self:getCenter()
|
|
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 the actors.
|
|
|
|
function Actor2D:draw()
|
|
self:drawStart()
|
|
local x, y = math.floor(self.x), math.floor(self.y)
|
|
self:drawSprite(x, y)
|
|
self:drawEnd()
|
|
end
|
|
|
|
return Actor2D
|