Compare commits

..

16 commits

Author SHA1 Message Date
Kazhnuz
c3ee812d1a chore: put automove in physics mixin
Fixes #54
2020-11-26 21:08:29 +01:00
Kazhnuz
dcc2965431 chore: simplify hitbox applciation 2020-11-26 20:54:16 +01:00
Kazhnuz
9eb0d321c8 chore: improve semantics
- Use "apply" when you apply collision, and not check
- Use "AtPoint" when you check at a point
2020-11-26 20:41:02 +01:00
Kazhnuz
b2623cdb6a chore: refactor hitbox adding 2020-11-26 20:29:59 +01:00
Kazhnuz
f30fc6346d chore: initialize the hitbox with the physics 2020-11-26 20:18:26 +01:00
Kazhnuz
9993221e0d improvement: use directly a table for box attr 2020-11-26 20:16:19 +01:00
Kazhnuz
b071547630 chore: let the hitbox handle the scaling 2020-11-26 20:12:05 +01:00
Kazhnuz
92c08e30ee chore: pack and unpack the coordinates
It'll allow us to unify the hitbox loading system
2020-11-26 19:41:13 +01:00
Kazhnuz
79902a097f chore: extract physics as a mixins
Fixes #52
2020-11-26 19:16:15 +01:00
Kazhnuz
5393d16007 chore: divide simple target into mixins 2020-11-26 18:40:25 +01:00
Kazhnuz
b97d320dc7 chore: prepare for division in mixins 2020-11-25 13:30:10 +01:00
Kazhnuz
730d89a76c feat: add basic reusable 2D objects
Fixes #51
2020-11-25 13:29:27 +01:00
Kazhnuz
124a228d3b feat: add a 3D middle point function 2020-11-25 13:02:11 +01:00
Kazhnuz
5837fd8b51 feat: add a global asset system 2020-11-13 19:11:09 +01:00
Kazhnuz
c5c9f040bc chore: add asset types to their own folders 2020-11-13 17:51:12 +01:00
Kazhnuz
3b1097c917 chore: make SFX a soundObject too 2020-11-13 17:43:28 +01:00
36 changed files with 1261 additions and 835 deletions

97
birb/core/assets.lua Normal file
View file

@ -0,0 +1,97 @@
-- core/assets :: a simple assets manager, aim to put every assets in a simple
-- serie of table in order to find them easily.
--[[
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 AssetManager = Object:extend()
function AssetManager:new()
self.locals = {}
self.globals = {}
self.updatables = {}
self.isActive = true
end
function AssetManager:update(dt)
if (self.isActive) then
for key, updatable in pairs(self.updatables) do
updatable:update(dt)
end
end
end
function AssetManager:add(name, asset, isGlobal)
if (isGlobal == true) then
self:addGlobal(name, asset)
else
self:addLocal(name, asset)
end
end
function AssetManager:addGlobal(name, asset)
self.globals[name] = asset
end
function AssetManager:addLocal(name, asset)
self.locals[name] = asset
end
function AssetManager:clear()
self.locals = {}
self.globals = {}
collectgarbage()
end
function AssetManager:clearLocal()
self.locals = {}
end
function AssetManager:get(name)
if self.locals[name] ~= nil then
return self.locals[name]
end
return self.globals[name]
end
-- Specific functions
function AssetManager:playSFX(name)
local asset = self:get(name)
asset:play()
end
-- Activity Functions
function AssetManager:setActivity(isActive)
self.isActive = isActive
end
function AssetManager:switchActivity()
self.isActive = (self.isActive == false)
end
function AssetManager:getActivity()
return self.isActive
end
return AssetManager

View file

@ -34,6 +34,7 @@ local Screen = require(cwd .. "screen")
local Lang = require(cwd .. "lang") local Lang = require(cwd .. "lang")
local SceneManager = require(cwd .. "scenemanager") local SceneManager = require(cwd .. "scenemanager")
local MusicManager = require(cwd .. "music") local MusicManager = require(cwd .. "music")
local Assets = require(cwd .. "assets")
-- INIT FUNCTIONS -- INIT FUNCTIONS
-- Initialize and configure the core object -- Initialize and configure the core object
@ -51,6 +52,7 @@ function CoreSystem:new(debugLevel)
self.scenemanager = SceneManager(self) self.scenemanager = SceneManager(self)
self.lang = Lang(self) self.lang = Lang(self)
self.music = MusicManager(self) self.music = MusicManager(self)
self.assets = Assets(self)
self.debug:logDebug("birbcore","Birb initialized") self.debug:logDebug("birbcore","Birb initialized")
end end
@ -106,6 +108,7 @@ function CoreSystem:update(dt)
self.input:update(dt) self.input:update(dt)
self.screen:update(dt) self.screen:update(dt)
self.music:update(dt) self.music:update(dt)
self.assets:update(dt)
if (self.game ~= nil) then if (self.game ~= nil) then
self.game:update(dt) self.game:update(dt)

View file

@ -75,7 +75,6 @@ function SceneManager:update(dt)
if (self.currentScene ~= nil) then if (self.currentScene ~= nil) then
self.currentScene:updateStart(dt) self.currentScene:updateStart(dt)
self.currentScene:setKeys() self.currentScene:setKeys()
self.currentScene.assets:update(dt)
self.currentScene.menusystem:update(dt) self.currentScene.menusystem:update(dt)
self.currentScene:updateWorld(dt) self.currentScene:updateWorld(dt)
self.currentScene:update(dt) self.currentScene:update(dt)

View file

@ -1,5 +1,5 @@
-- modules/assets :: a simple assets manager, aim to put every assets in a simple -- modules/assets/import :: a simple assets importer, to import easily everything into
-- serie of table in order to find them easily. -- the asset manager.
--[[ --[[
Copyright © 2019 Kazhnuz Copyright © 2019 Kazhnuz
@ -24,7 +24,7 @@
local Assets = Object:extend() local Assets = Object:extend()
local cwd = (...):gsub('%.init$', '') .. "." local cwd = (...):gsub('%.init$', '') .. ".types."
local Texture = require(cwd .. "texture") local Texture = require(cwd .. "texture")
@ -36,32 +36,92 @@ local Tileset = require(cwd .. "tileset")
local Autotile = require(cwd .. "autotile") local Autotile = require(cwd .. "autotile")
local Background = require(cwd .. "background") local Background = require(cwd .. "background")
local SFX = require(cwd .. "sfx")
-- INIT FUNCTIONS -- INIT FUNCTIONS
-- Initilizing and configuring option -- Initilizing and configuring option
function Assets:new() function Assets:new(isGlobal)
self:clear() self.isGlobal = isGlobal
self.isActive = true
end end
function Assets:clear() function Assets:clear()
-- TODO: destroy individually each texture/image when assets are cleared if (self.isGlobal) then
self:clearSprites() core.assets:clear()
self:clearSFX() else
self:clearFonts() core.assets:clearLocal()
self:resetMusic() end
self:clearBackgrounds()
self:clearFonts()
self:clearTileset()
self:clearImages()
end end
function Assets:update(dt) -- WRAPPER FUNCTIONS
if (self.isActive) then -- Basic wrappers to ensure compatibility
self:animationsUpdate(dt)
end function Assets:get(key)
return core.assets:get(key)
end
function Assets:getFont(key)
return self:getWithType(key, "font")
end
function Assets:getWithType(key, type)
return core.assets:get(key)
end
function Assets:draw(name, x, y, r, sx, sy, ox, oy, kx, ky)
core.assets:draw(name, x, y, r, sx, sy, ox, oy, kx, ky)
end
function Assets:newSFX(name, filepath)
self:addSFX(name, filepath)
end
function Assets:addImage(name, filename)
self:addTexture(name, filename)
end
function Assets:playSFX(name)
core.assets:playSFX(name)
end
function Assets:drawImage(name, x, y, r, sx, sy, ox, oy, kx, ky)
self:draw(name, x, y, r, sx, sy, ox, oy, kx, ky)
end
-- Music
function Assets:setMusic(filename, loop)
core.debug:logDebug("assets", "Assets:setMusic is deprecated")
core.music:addMusic(filename, true)
end
function Assets:silence()
core.debug:logDebug("assets", "Assets:silence is deprecated")
core.music:silence()
end
function Assets:resetMusic()
core.debug:logDebug("assets", "Assets:resetMusic is deprecated")
core.music:purge()
end
function Assets:playMusic()
core.debug:logDebug("assets", "Assets:playMusic is deprecated")
core.music:playMusic()
end
-- Activity
function Assets:setActivity(activity)
core.assets:setActivity(activity)
end
function Assets:switchActivity()
core.assets:switchActivity()
end
function Assets:getActivity()
core.assets:getActivity()
end end
-- IMPORT FUNCTIONS -- IMPORT FUNCTIONS
@ -143,150 +203,74 @@ function Assets:importSFX(assets)
end end
end end
-- SFX & MUSICS -- ADD FUNCTIONS
-- Handle sound effects and musics -- Different wrapper to create easily asset objects
function Assets:addSFX(name, filepath) function Assets:add(name, assetObject)
self:newSFX(name, filepath) core.assets:add(name, assetObject, self.isGlobal)
end end
function Assets:newSFX(name, filepath)
self.sfx[name] = love.audio.newSource( filepath, "static" )
end
function Assets:clearSFX()
love.audio.stop( )
self.sfx = {}
end
function Assets:playSFX(filename)
if not (self.sfx[filename] == nil) then
self.sfx[filename]:stop()
self.sfx[filename]:setVolume(core.options.data.audio.sfx / 100)
love.audio.play( self.sfx[filename] )
end
end
function Assets:setMusic(filename, loop)
core.debug:logDebug("assets", "Assets:setMusic is deprecated")
core.music:addMusic(filename, true)
end
function Assets:silence()
core.debug:logDebug("assets", "Assets:silence is deprecated")
core.music:silence()
end
function Assets:resetMusic()
core.debug:logDebug("assets", "Assets:resetMusic is deprecated")
core.music:purge()
end
function Assets:playMusic()
core.debug:logDebug("assets", "Assets:playMusic is deprecated")
core.music:playMusic()
end
-- IMAGES FUNCTIONS
-- Create directly texture items
function Assets:addImage(name, filename)
self.images[name] = Texture(filename)
end
function Assets:drawImage(name, x, y, r, sx, sy, ox, oy, kx, ky)
self.images[name]:draw(x, y, r, sx, sy, ox, oy, kx, ky)
end
function Assets:clearImages()
self.images = {}
end
-- BACKGROUNDS FUNCTIONS
-- Automatic tiling texture
function Assets:addBackground(name, filepath) function Assets:addBackground(name, filepath)
-- TODO: rework entirely background to work at any size self:add(name, Background(filepath))
self.backgrounds[name] = Background(filepath)
end end
function Assets:clearBackgrounds()
self.backgrounds = {}
end
-- SPRITES FUNCTIONS
-- Animated tileset
function Assets:addSprite(name, filepath) function Assets:addSprite(name, filepath)
self.sprites[name] = Sprite(filepath) self:add(name, Sprite(filepath))
end end
function Assets:animationsUpdate(dt)
for i,v in pairs(self.sprites) do
v:update(dt)
end
end
function Assets:clearSprites()
self.sprites = {}
end
-- FONTS FUNCTIONS
-- Handles fonts and imagesfonts
function Assets:addFont(key, filename, size) function Assets:addFont(key, filename, size)
local font = Font(filename, size) self:add(key, Font(filename, size))
self.fonts[key] = font
end end
function Assets:addImageFont(key, filename, extraspacing) function Assets:addImageFont(key, filename, extraspacing)
local font = ImageFont(filename, extraspacing) self:add(key, ImageFont(filename, extraspacing))
self.fonts[key] = font
end end
function Assets:getFont(filename)
return self.fonts[filename]
end
function Assets:clearFonts()
self.fonts = {}
end
-- TILESET FUNCTIONS
-- Automatically create quads for a texture
function Assets:addTileset(name, filepath) function Assets:addTileset(name, filepath)
self.tileset[name] = Tileset(filepath) self:add(name, Tileset(filepath))
end
function Assets:addAutotile(name, tilesize)
self:add(name, Autotile(name, tilesize))
end
function Assets:addSFX(name, filepath)
self:add(name, SFX(filepath))
end
function Assets:addTexture(name, filename)
self:add(name, Texture(filename))
end
-- DEPRECATED FUNCTIONS
-- Don't do anything and will be removed soon
function Assets:clearFonts()
core.debug:logDebug("assets", "Assets:clearFonts is deprecated")
end end
function Assets:clearTileset() function Assets:clearTileset()
self.tileset = {} core.debug:logDebug("assets", "Assets:clearTileset is deprecated")
end
-- AUTOTILE FUNCTIONS
-- Automatically draw tiles
function Assets:addAutotile(name, tilesize)
self.autotile[name] = Autotile(name, tilesize)
end end
function Assets:clearAutotile() function Assets:clearAutotile()
self.autotile = {} core.debug:logDebug("assets", "Assets:clearAutotile is deprecated")
end end
-- ACTIVITY FUNCTIONS function Assets:clearSFX()
-- Handle activity core.debug:logDebug("assets", "Assets:clearSFX is deprecated")
function Assets:setActivity(activity)
self.isActive = activity
end end
function Assets:switchActivity() function Assets:clearBackgrounds()
self.isActive = (self.isActive == false) core.debug:logDebug("assets", "Assets:clearBackgrounds is deprecated")
end end
function Assets:getActivity() function Assets:clearSprites()
return self.isActive core.debug:logDebug("assets", "Assets:clearSprites is deprecated")
end
function Assets:clearImages()
core.debug:logDebug("assets", "Assets:clearImages is deprecated")
end end
return Assets return Assets

View file

@ -0,0 +1,40 @@
-- assets/sfx :: the sfx object, essentially used to be able to just have an sfx
--[[
Copyright © 2020 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 SFX = Object:extend()
-- INIT FUNCTIONS
-- Initilizing and configuring option
function SFX:new(filepath)
self.sound = love.audio.newSource(filepath, "static")
end
function SFX:play()
self.sound:stop()
self.sound:setVolume(core.options.data.audio.sfx / 100)
love.audio.play(self.sound)
end
return SFX

View file

@ -257,7 +257,7 @@ function Menu:resetSound()
end end
function Menu:setSoundFromSceneAssets(name) function Menu:setSoundFromSceneAssets(name)
self:setSound(self.menusystem.scene.assets.sfx[name]) self:setSound(self.menusystem.scene.assets:getWithType(name, "sfx"))
end end
function Menu:setSound(soundasset) function Menu:setSound(soundasset)
@ -267,9 +267,7 @@ end
function Menu:playNavigationSound() function Menu:playNavigationSound()
if self.sound.active == true then if self.sound.active == true then
love.audio.stop( self.sound.asset ) self.sound.asset:play()
self.sound.asset:setVolume(core.options.data.audio.sfx / 100)
love.audio.play( self.sound.asset )
end end
end end

View file

@ -22,18 +22,34 @@
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]] ]]
local cwd = (...):gsub('%.actor2D$', '') .. "." local BaseActor = require("birb.modules.world.actors.mixins.base")
local BaseActor = require(cwd .. "baseactor") local SpritedActor = require("birb.modules.world.actors.mixins.sprites")
local Actor2D = BaseActor:extend() local TimedActor = require("birb.modules.world.actors.mixins.timers")
local InputActor = require("birb.modules.world.actors.mixins.inputs")
local PhysicalActor = require("birb.modules.world.actors.mixins.physics")
local Hitbox = require(cwd .. "utils.hitbox2D") local Actor2D = Object:extend()
Actor2D:implement(BaseActor)
Actor2D:implement(SpritedActor)
Actor2D:implement(TimedActor)
Actor2D:implement(InputActor)
Actor2D:implement(PhysicalActor)
local Hitbox = require("birb.modules.world.actors.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)
Actor2D.super.new(self, world, type, x, y, 0, w, h, 0, isSolid) self:init(world, type)
self:initHitboxes() self:initPhysics(Hitbox, x, y, 0, w, h, 0, isSolid)
self:initTimers()
self:initSprite()
self:initKeys()
end
function Actor2D:packForHitbox()
return {0, 0, self.w, self.h}
end end
function Actor2D:destroy() function Actor2D:destroy()
@ -45,21 +61,10 @@ end
-- PHYSICS FUNCTIONS -- PHYSICS FUNCTIONS
-- Handle movement and collisions. -- Handle movement and collisions.
function Actor2D:autoMove(dt) function Actor2D:moveToFuturePosition(dt)
self:updateHitboxes()
self.onGround = false
self:applyGravity(dt)
local dx, dy = self:getFuturePosition(dt) local dx, dy = self:getFuturePosition(dt)
local newx, newy, cols, colNumber = self:move(dx, dy) local _, _, cols, colNumber = self:move(dx, dy)
return cols, colNumber
-- 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:applyFriction(dt)
end end
function Actor2D:changeSpeedToCollisionNormal(normal) function Actor2D:changeSpeedToCollisionNormal(normal)
@ -80,16 +85,16 @@ 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.mainHitbox:checkCollision(dx, dy, self.filter) self.x, self.y, cols, colNumber = self.mainHitbox:checkCollisionAtPoint(dx, dy, self.filter)
self.mainHitbox:updatePosition() self.mainHitbox:updatePosition()
end end
return self.x, self.y, cols, colNumber return self.x, self.y, cols, colNumber
end end
function Actor2D:checkCollision(dx, dy) function Actor2D:checkCollisionAtPoint(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.mainHitbox:checkCollision(dx, dy, self.filter) x, y, cols, colNumber = self.mainHitbox:checkCollisionAtPoint(dx, dy, self.filter)
end end
return self.x, self.y, cols, colNumber return self.x, self.y, cols, colNumber
end end
@ -107,7 +112,7 @@ end
function Actor2D:checkGround() function Actor2D:checkGround()
local dx, dy = self.x, self.y + utils.math.sign(self.grav) local dx, dy = self.x, self.y + utils.math.sign(self.grav)
local newx, newy, cols, colNumber = self:checkCollision(dx, dy) local newx, newy, cols, colNumber = self:checkCollisionAtPoint(dx, dy)
for i, col in ipairs(cols) do for i, col in ipairs(cols) do
if (col.type == "touch") or (col.type == "bounce") or (col.type == "slide") then if (col.type == "touch") or (col.type == "bounce") or (col.type == "slide") then
@ -126,70 +131,6 @@ function Actor2D:getViewCenter()
return x, y return x, y
end end
-- HITBOXES FUNCTIONS
-- Functions related to actor hitboxes
function Actor2D:addHitboxFromFrameData(framedata, animationID, frameID, hitboxID)
local sx, sy = self.sprite:getScalling()
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.mainHitbox:advertiseAsMainHitbox()
end
function Actor2D:addHitbox(name, type, ox, oy, w, h, isSolid)
if (self.hitboxes[name] ~= nil) then
core.debug:logWarn("actor2D", "the hitbox " .. name .. " already exists")
else
local hitbox = Hitbox(self, type, ox, oy, w, h, isSolid)
self.hitboxes[name] = hitbox
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
-- DRAW FUNCTIONS -- DRAW FUNCTIONS
-- Draw the actors. -- Draw the actors.

View file

@ -23,8 +23,18 @@
]] ]]
local cwd = (...):gsub('%.actor3D$', '') .. "." local cwd = (...):gsub('%.actor3D$', '') .. "."
local BaseActor = require(cwd .. "baseactor") local BaseActor = require("birb.modules.world.actors.mixins.base")
local Actor3D = BaseActor:extend() local SpritedActor = require("birb.modules.world.actors.mixins.sprites")
local TimedActor = require("birb.modules.world.actors.mixins.timers")
local InputActor = require("birb.modules.world.actors.mixins.inputs")
local PhysicalActor = require("birb.modules.world.actors.mixins.physics")
local Actor3D = Object:extend()
Actor3D:implement(BaseActor)
Actor3D:implement(SpritedActor)
Actor3D:implement(TimedActor)
Actor3D:implement(InputActor)
Actor3D:implement(PhysicalActor)
local Hitbox = require(cwd .. "utils.hitbox3D") local Hitbox = require(cwd .. "utils.hitbox3D")
local Boxes = require(cwd .. "utils.boxes") local Boxes = require(cwd .. "utils.boxes")
@ -33,8 +43,10 @@ local Boxes = require(cwd .. "utils.boxes")
-- Initialise the actor and its base functions -- Initialise the actor and its base functions
function Actor3D:new(world, type, x, y, z, w, h, d, isSolid) function Actor3D:new(world, type, x, y, z, w, h, d, isSolid)
Actor3D.super.new(self, world, type, x, y, z, w, h, d, isSolid) self:init(world, type)
self:initHitboxes() self:initPhysics(Hitbox, x, y, z, w, h, d, isSolid)
self:initTimers()
self:initSprite()
self.world:registerShape(self) self.world:registerShape(self)
self.boxes = Boxes self.boxes = Boxes
self.doCastShadows = true self.doCastShadows = true
@ -51,24 +63,18 @@ function Actor3D:destroy()
self.isDestroyed = true self.isDestroyed = true
end end
function Actor3D:packForHitbox()
return {0, 0, 0, self.w, self.h, self.d}
end
-- PHYSICS FUNCTIONS -- PHYSICS FUNCTIONS
-- Handle movement and collisions. -- Handle movement and collisions.
function Actor3D:autoMove(dt) function Actor3D:moveToFuturePosition(dt)
self:updateHitboxes()
self.onGround = false
self:applyGravity(dt)
local dx, dy, dz = self:getFuturePosition(dt) local dx, dy, dz = self:getFuturePosition(dt)
local newx, newy, newz, cols, colNumber = self:move(dx, dy, dz) local _, _, _, cols, colNumber = self:move(dx, dy, dz)
return cols, colNumber
-- 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:applyFriction(dt)
end end
function Actor3D:changeSpeedToCollisionNormal(normal) function Actor3D:changeSpeedToCollisionNormal(normal)
@ -94,7 +100,7 @@ function Actor3D:move(dx, dy, dz)
local cols, colNumber = {}, 0 local cols, colNumber = {}, 0
local oldx, oldy, oldz = self.x, self.y, self.z local oldx, oldy, oldz = self.x, self.y, self.z
if (self.isDestroyed == false) then if (self.isDestroyed == false) then
self.x, self.y, self.z, cols, colNumber = self.mainHitbox:checkCollision(dx, dy, dz, self.filter) self.x, self.y, self.z, cols, colNumber = self.mainHitbox:checkCollisionAtPoint(dx, dy, dz, self.filter)
self.mainHitbox:updatePosition() self.mainHitbox:updatePosition()
self.world:updateShape(self) self.world:updateShape(self)
end end
@ -108,10 +114,10 @@ function Actor3D:move(dx, dy, dz)
return self.x, self.y, self.z, cols, colNumber return self.x, self.y, self.z, cols, colNumber
end end
function Actor3D:checkCollision(dx, dy, dz) function Actor3D:checkCollisionAtPoint(dx, dy, dz)
local x, y, z, cols, colNumber = dx, dy, dz, {}, 0 local x, y, z, cols, colNumber = dx, dy, dz, {}, 0
if (self.isDestroyed == false) then if (self.isDestroyed == false) then
x, y, z, cols, colNumber = self.mainHitbox:checkCollision(dx, dy, dz, self.filter) x, y, z, cols, colNumber = self.mainHitbox:checkCollisionAtPoint(dx, dy, dz, self.filter)
end end
return self.x, self.y, self.z, cols, colNumber return self.x, self.y, self.z, cols, colNumber
end end
@ -130,7 +136,7 @@ end
function Actor3D:checkGround() function Actor3D:checkGround()
local dx, dy, dz = self.x, self.y, self.z - utils.math.sign(self.grav) local dx, dy, dz = self.x, self.y, self.z - utils.math.sign(self.grav)
local newx, newy, newz, cols, colNumber = self:checkCollision(dx, dy, dz) local newx, newy, newz, cols, colNumber = self:checkCollisionAtPoint(dx, dy, dz)
for i, col in ipairs(cols) do for i, col in ipairs(cols) do
if (col.type == "touch") or (col.type == "bounce") or (col.type == "slide") then if (col.type == "touch") or (col.type == "bounce") or (col.type == "slide") then
if not (self.grav == 0) then if not (self.grav == 0) then
@ -148,72 +154,6 @@ function Actor3D:getViewCenter()
return x, y - (self.d/2) return x, y - (self.d/2)
end end
-- HITBOXES FUNCTIONS
-- Functions related to actor hitboxes
function Actor3D:addHitboxFromFrameData(framedata, animationID, frameID, hitboxID)
local sx, sy = self.sprite:getScalling()
local type = framedata[1]
local ox = framedata[2]
local oy = framedata[3]
local oz = framedata[4]
local w = framedata[5]
local h = framedata[6]
local d = framedata[7]
local isSolid = framedata[8] 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
oz = self.d - oz - d
end
if (type == "main") then
self.mainHitbox:modify(ox, oy, oz, w, h, d)
else
local hitboxName = anim .. frame .. type .. id
self:addHitbox(hitboxName, type, ox, oy, oz, w, h, d, isSolid)
return hitboxName
end
end
function Actor3D:initMainHitbox()
self.mainHitbox = Hitbox(self, self.type, 0, 0, 0, self.w, self.h, self.d, self.isSolid)
self.mainHitbox:advertiseAsMainHitbox()
end
function Actor3D:addHitbox(name, type, ox, oy, oz, w, h, d, isSolid)
if (self.hitboxes[name] ~= nil) then
core.debug:logWarn("actor3D", "the hitbox " .. name .. " already exists")
else
local hitbox = Hitbox(self, type, ox, oy, oz, w, h, d, isSolid)
self.hitboxes[name] = hitbox
return hitbox
end
end
function Actor3D:checkHitboxCollisions(name, filter)
self:checkHitboxCollisionsAtPoint(name, self.x, self.y, self.z, filter)
end
function Actor3D:checkHitboxCollisionsAtPoint(name, dx, dy, dz, filter)
local x, y, z, cols, colNumber = dx, dy, dz, {}, 0
local filter = filter or self.filter
if (self.isDestroyed == false) and (self.hitboxes[name] ~= nil) then
x, y, z, cols, colNumber = self.hitboxes[name]:checkCollision(dx, dy, dz, filter)
local type = self.hitboxes[name].type
for i, col in ipairs(cols) do
self:hitboxResponse(name, type, col)
end
end
return x, y, z, cols, colNumber
end
-- SHADOW FUNCTIONS -- SHADOW FUNCTIONS
-- Handle everything related to shadow -- Handle everything related to shadow

View file

@ -1,437 +0,0 @@
-- BaseActor.lua :: the global implementation of an actor. Basically, it abstract
-- everything that isn't only 2D or 3D related to the actor system.
--[[
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('%.baseactor$', '') .. "."
local BaseActor = Object:extend()
local Timer = require(cwd .. "utils.timer")
local Sprite = require(cwd .. "utils.sprites")
-- INIT FUNCTIONS
-- Initialise the actor and its base functions
function BaseActor:new(world, type, x, y, z, w, h, d, isSolid)
self.type = type or ""
self.isSolid = isSolid or false
self.depth = 0
self:setManagers(world)
self:initKeys()
self:initTimers()
self:setSprite()
self:initPhysics(x, y, z, w, h, d)
self:setDebugColor(1, 1, 1)
self:register()
end
function BaseActor:setManagers(world)
self.world = world
self.scene = world.scene
self.obj = world.obj
self.assets = self.scene.assets
end
function BaseActor:setDebugColor(r,g,b)
self.debug = {}
self.debug.r = r
self.debug.g = g
self.debug.b = b
end
function BaseActor:register()
self.world:registerActor(self)
self.isDestroyed = false
end
function BaseActor:destroy()
self.world:removeActor(self)
self.isDestroyed = true
end
-- PHYSICS FUNCTIONS
-- Raw implementation of everything common in physics
function BaseActor:initPhysics(x, y, z, w, h, d)
self:setCoordinate(x, y, z)
self.w = w or 0
self.h = h or 0
self.d = d or 0
self.xsp = 0
self.ysp = 0
self.zsp = 0
self.xfrc = 0
self.yfrc = 0
self.zfrc = 0
self:initGravity()
self:setBounceFactor()
self:setFilter()
end
function BaseActor:setCoordinate(x, y, z, w, h, d)
self.x = x or self.x
self.y = y or self.y
self.z = z or self.z
end
function BaseActor:setBounceFactor(newBounceFactor)
self.bounceFactor = newBounceFactor or 0
end
function BaseActor:setFilter()
-- Init the bump filter
self.filter = function(item, other)
if (other.owner == self) then
-- ignore every collision with our own hitboxes
return nil
elseif (other.isSolid) then
return "slide"
else
return "cross"
end
end
end
function BaseActor:getFuturePosition(dt)
local dx, dy, dz
dx = self.x + self.xsp * dt
dy = self.y + self.ysp * dt
dz = self.z + self.zsp * dt
return dx, dy, dz
end
function BaseActor:applyFriction(dt)
self.xsp = utils.math.toZero(self.xsp, self.xfrc * dt)
self.ysp = utils.math.toZero(self.ysp, self.yfrc * dt)
self.zsp = utils.math.toZero(self.zsp, self.zfrc * dt)
end
function BaseActor: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)
end
end
end
function BaseActor:collisionResponse(collision)
-- here come the response to the collision
end
function BaseActor:changeSpeedToCollisionNormal(normal)
-- Empty function in baseactor
end
-- COORDINATE/MOVEMENT FUNCTIONS
-- Handle coordinate
function BaseActor:getCenter()
return (self.x + (self.w / 2)), (self.y + (self.h / 2)), (self.z + (self.d / 2))
end
function BaseActor:getViewCenter()
return self:getCenter()
end
-- GRAVITY SYSTEM FUNCTIONS
-- All functions related to gravity
function BaseActor:initGravity()
if (self.world.gravity.isDefault) then
self.grav = self.world.gravity.grav
else
self.grav = 0
end
self.onGround = false
end
function BaseActor:setGravity(grav)
-- It's basically now a function with two roles at once :
-- - activate the gravity
-- - use the gravity value the dev want
self.grav = grav or self.world.gravity.grav
end
function BaseActor:applyGravity(dt)
-- Empty function in baseactor
end
function BaseActor:checkGround()
-- Empty function in baseactor
end
-- UPDATE FUNCTIONS
-- Theses functions are activated every steps
function BaseActor:updateStart(dt)
end
function BaseActor:update(dt)
self:updateStart(dt)
self:updateTimers(dt)
self:autoMove(dt)
self:updateSprite(dt)
self:updateEnd(dt)
end
function BaseActor:updateEnd(dt)
end
function BaseActor:autoMove(dt)
-- The base actor don't have coordinate
-- so the autoMove is only usefull to its
-- 2D and 3D childrens
end
-- INPUT FUNCTIONS
-- get input from the world object
function BaseActor:initKeys()
self.keys = core.input.fakekeys
end
function BaseActor:getInput(keys)
self.keys = keys or core.input.fakekeys
end
-- TIMER FUNCTIONS
-- Control the integrated timers of the actor
function BaseActor:initTimers()
self.timers = core.modules.Timers(self)
end
function BaseActor:addTimer(name, t)
core.debug:logWarn("actor", "function actor:addTimer is deprecated, prefer actor.timers:newTimer")
self.timers:newTimer(t, name)
end
function BaseActor:updateTimers(dt)
self.timers:update(dt)
end
function BaseActor:timerResponse(name)
-- here come the timer responses
end
-- HITBOX FUNCTIONS
-- All functions to handle hitboxes
function BaseActor:initHitboxes()
self:initMainHitbox()
self.hitboxes = {}
self.hitboxListFile = ""
self.hitboxList = nil
end
function BaseActor:initMainHitbox()
-- Empty function : don't load ANY real hitbox function into baseactor
end
function BaseActor:setHitboxFile(file)
self.hitboxList = require(file)
self.hitboxListFile = file
end
function BaseActor:getAutomaticHitboxLoading()
return (self.hitboxList ~= nil)
end
function BaseActor:getHitboxFile()
return self.hitboxListFile
end
function BaseActor: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 BaseActor:updateHitboxes()
if (self.hitboxList ~= nil) then
self:purgeHitbox()
local animation, frame
animation = self.sprite:getCurrentAnimation()
frame = self.sprite: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 BaseActor:checkHitboxesCollisions(filter)
for k,v in pairs(self.hitboxes) do
self:checkHitboxCollisions(k, filter)
end
end
function BaseActor:hitboxResponse(name, type, collision)
-- just a blank placeholder function
end
function BaseActor:removeHitbox(name)
if (self.hitboxes[name] ~= nil) then
self.hitboxes[name]:destroy()
self.hitboxes[name] = nil
end
end
function BaseActor:purgeHitbox()
for k,v in pairs(self.hitboxes) do
v:destroy()
end
self.hitboxes = {}
end
function BaseActor:drawHitboxes()
for k,v in pairs(self.hitboxes) do
v:draw()
end
self:drawMainHitbox()
end
function BaseActor:drawMainHitbox()
if (self.mainHitbox ~= nil) then
self.mainHitbox:draw()
end
end
-- DRAW FUNCTIONS
-- Draw the actors.
function BaseActor:drawStart()
end
function BaseActor:draw()
self:drawStart()
self:drawEnd()
end
function BaseActor:drawEnd()
end
function BaseActor:drawHUD(id, height, width)
end
-- SPRITES FUNCTIONS
-- Handle the sprite of the actor
function BaseActor:setSprite(spritename, isClone, ox, oy)
self.sprite = Sprite(self, spritename, ox, oy)
if (isClone) then
self.sprite:clone()
end
end
function BaseActor:changeAnimation(animation, restart)
if (self.sprite ~= nil) then
core.debug:logWarn("actor", "the function BaseActor:changeAnimation is deprecated, prefer BaseActor.sprite:changeAnimation()")
self.sprite:changeAnimation(animation, restart)
end
end
function BaseActor:animationEnded(animation)
-- Empty placeholder function
end
function BaseActor:setCustomSpeed(customSpeed)
if (self.sprite ~= nil) then
core.debug:logWarn("actor", "the function BaseActor:setCustomSpeed is deprecated, prefer BaseActor.sprite:setCustomSpeed()")
self.sprite:setCustomSpeed(customSpeed)
end
end
function BaseActor:updateSprite(dt)
if (self.sprite ~= nil) then
self.sprite:update(dt)
end
end
function BaseActor:getCurrentAnimation()
if (self.sprite ~= nil) then
core.debug:logWarn("actor", "the function BaseActor:getCurrentAnimation is deprecated, prefer BaseActor.sprite:getCurrentAnimation()")
return self.sprite:getCurrentAnimation()
end
end
function BaseActor:getSpriteScalling()
core.debug:logWarn("actor", "the function BaseActor:getSpriteScalling is deprecated, prefer BaseActor.sprite:getScalling()")
return self.sprite:getScalling()
end
function BaseActor:getFrame()
if (self.sprite ~= nil) then
core.debug:logWarn("actor", "the function BaseActor:getFrame is deprecated, prefer BaseActor.sprite:getFrame()")
return self.sprite:getFrame()
end
end
function BaseActor:getRelativeFrame()
if (self.sprite ~= nil) then
core.debug:logWarn("actor", "the function BaseActor:getRelativeFrame is deprecated, prefer BaseActor.sprite:getRelativeFrame()")
return self.sprite:getRelativeFrame()
end
end
function BaseActor:getAnimationDuration()
if (self.sprite ~= nil) then
core.debug:logWarn("actor", "the function BaseActor:getAnimationDuration is deprecated, prefer BaseActor.sprite:getAnimationDuration()")
return self.sprite:getAnimationDuration()
end
end
function BaseActor:drawSprite(x, y, r, sx, sy, ox, oy, kx, ky)
if (self.sprite ~= nil) then
self.sprite:draw(x, y, r, sx, sy, ox, oy, kx, ky)
end
end
return BaseActor

View file

@ -26,7 +26,8 @@ local Actor2D = require(cwd .. "actor2D")
local GFX = Actor2D:extend() local GFX = Actor2D:extend()
function GFX:new(world, x, y, spritename) function GFX:new(world, x, y, spritename)
local width, height = world.scene.assets.sprites[spritename]:getDimensions() local baseSprite = world.scene.assets:getWithType(spritename, "sprite")
local width, height = baseSprite:getDimensions()
GFX.super.new(self, world, "gfx", x - (width/2), y - (height/2), width, height) GFX.super.new(self, world, "gfx", x - (width/2), y - (height/2), width, height)
self:setSprite(spritename, true) self:setSprite(spritename, true)

View file

@ -26,7 +26,8 @@ local Actor3D = require(cwd .. "actor3D")
local GFX = Actor3D:extend() local GFX = Actor3D:extend()
function GFX:new(world, x, y, z, spritename) function GFX:new(world, x, y, z, spritename)
local width, height = world.scene.assets.sprites[spritename]:getDimensions() local baseSprite = world.scene.assets:getWithType(spritename, "sprite")
local width, height = baseSprite:getDimensions()
GFX.super.new(self, world, "gfx", x - (width/2), y - (width/2), z - (height/2), width, width, height) GFX.super.new(self, world, "gfx", x - (width/2), y - (width/2), z - (height/2), width, width, height)
self:setSprite(spritename, true) self:setSprite(spritename, true)

View file

@ -0,0 +1,114 @@
-- BaseActor.lua :: the global implementation of an actor. Basically, it abstract
-- everything that isn't only 2D or 3D related to the actor system.
--[[
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 BaseActor = Object:extend()
-- INIT FUNCTIONS
-- Initialise the actor and its base functions
function BaseActor:init(world, type)
self.type = type or ""
self.depth = 0
self:setManagers(world)
self:initKeys()
self:setDebugColor(1, 1, 1)
self:register()
self.updateFunctions = {}
end
function BaseActor:setManagers(world)
self.world = world
self.scene = world.scene
self.obj = world.obj
self.assets = self.scene.assets
end
function BaseActor:setDebugColor(r,g,b)
self.debug = {}
self.debug.r = r
self.debug.g = g
self.debug.b = b
end
function BaseActor:register()
self.world:registerActor(self)
self.isDestroyed = false
end
function BaseActor:destroy()
self.world:removeActor(self)
self.isDestroyed = true
end
-- UPDATE FUNCTIONS
-- Theses functions are activated every steps
function BaseActor:updateStart(dt)
end
function BaseActor:update(dt)
self:updateStart(dt)
self:applyUpdateFunctions(dt)
self:updateEnd(dt)
end
function BaseActor:addUpdateFunction(func)
table.insert(self.updateFunctions, func)
end
function BaseActor:applyUpdateFunctions(dt)
for key, func in ipairs(self.updateFunctions) do
func(self, dt)
end
end
function BaseActor:updateEnd(dt)
end
-- DRAW FUNCTIONS
-- Draw the actors.
function BaseActor:drawStart()
end
function BaseActor:draw()
self:drawStart()
self:drawEnd()
end
function BaseActor:drawEnd()
end
function BaseActor:drawHUD(id, height, width)
end
return BaseActor

View file

@ -0,0 +1,34 @@
-- SpritedActor.lua :: Get input from the world object.
--[[
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 InputActor = Object:extend()
function InputActor:initKeys()
self.keys = core.input.fakekeys
end
function InputActor:getInput(keys)
self.keys = keys or core.input.fakekeys
end
return InputActor

View file

@ -0,0 +1,289 @@
PhysicalActor = Object:extend()
-- PHYSICS FUNCTIONS
-- Raw implementation of everything common in physics
function PhysicalActor:initPhysics(hitboxObj, x, y, z, w, h, d, isSolid)
self:setCoordinate(x, y, z)
self.isSolid = isSolid or false
self.w = w or 0
self.h = h or 0
self.d = d or 0
self.xsp = 0
self.ysp = 0
self.zsp = 0
self.xfrc = 0
self.yfrc = 0
self.zfrc = 0
self:initGravity()
self:initHitboxes(hitboxObj)
self:setBounceFactor()
self:setFilter()
self:addUpdateFunction(self.autoMove)
end
function PhysicalActor:setCoordinate(x, y, z, w, h, d)
self.x = x or self.x
self.y = y or self.y
self.z = z or self.z
end
function PhysicalActor:setBounceFactor(newBounceFactor)
self.bounceFactor = newBounceFactor or 0
end
function PhysicalActor:setFilter()
-- Init the bump filter
self.filter = function(item, other)
if (other.owner == self) then
-- ignore every collision with our own hitboxes
return nil
elseif (other.isSolid) then
return "slide"
else
return "cross"
end
end
end
function PhysicalActor:getFuturePosition(dt)
local dx, dy, dz
dx = self.x + self.xsp * dt
dy = self.y + self.ysp * dt
dz = self.z + self.zsp * dt
return dx, dy, dz
end
function PhysicalActor:applyFriction(dt)
self.xsp = utils.math.toZero(self.xsp, self.xfrc * dt)
self.ysp = utils.math.toZero(self.ysp, self.yfrc * dt)
self.zsp = utils.math.toZero(self.zsp, self.zfrc * dt)
end
function PhysicalActor: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)
end
end
end
function PhysicalActor:collisionResponse(collision)
-- here come the response to the collision
end
function PhysicalActor:changeSpeedToCollisionNormal(normal)
-- Empty function in PhysicalActor
end
-- COORDINATE/MOVEMENT FUNCTIONS
-- Handle coordinate
-- Will be replaced by functions inside Actors or Rects/Point
function PhysicalActor:getCenter()
return (self.x + (self.w / 2)), (self.y + (self.h / 2)), (self.z + (self.d / 2))
end
function PhysicalActor:getViewCenter()
return self:getCenter()
end
-- GRAVITY SYSTEM FUNCTIONS
-- All functions related to gravity
function PhysicalActor:initGravity()
if (self.world.gravity.isDefault) then
self.grav = self.world.gravity.grav
else
self.grav = 0
end
self.onGround = false
end
function PhysicalActor:setGravity(grav)
-- It's basically now a function with two roles at once :
-- - activate the gravity
-- - use the gravity value the dev want
self.grav = grav or self.world.gravity.grav
end
function PhysicalActor:applyGravity(dt)
-- Empty function in PhysicalActor
end
function PhysicalActor:checkGround()
-- Empty function in PhysicalActor
end
function PhysicalActor:autoMove(dt)
self:updateHitboxes()
self.onGround = false
self:applyGravity(dt)
local cols, colNumber = self:moveToFuturePosition(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:applyFriction(dt)
end
-- HITBOX FUNCTIONS
-- All functions to handle hitboxes
function PhysicalActor:initHitboxes(hitboxObj)
self.Hitbox = hitboxObj
self:initMainHitbox()
self.hitboxes = {}
self.hitboxListFile = ""
self.hitboxList = nil
end
function PhysicalActor:initMainHitbox()
-- Empty function : don't load ANY real hitbox function into PhysicalActor
end
function PhysicalActor:setHitboxFile(file)
self.hitboxList = require(file)
self.hitboxListFile = file
end
function PhysicalActor:getAutomaticHitboxLoading()
return (self.hitboxList ~= nil)
end
function PhysicalActor:getHitboxFile()
return self.hitboxListFile
end
function PhysicalActor: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 PhysicalActor:addHitboxFromFrameData(framedata, animationID, frameID, hitboxID)
local sx, sy = self.sprite:getScalling()
local type = framedata[1]
local box = framedata[2]
local isSolid = framedata[3] or false
local anim = animationID or "null"
local frame = frameID or 0
local id = hitboxID or 0
if (type == "main") then
self.mainHitbox:setFromData(box, sx, sy)
else
local hitboxName = anim .. frame .. type .. id
self:addHitbox(hitboxName, type, box, sx, sy, isSolid)
return hitboxName
end
end
function PhysicalActor:initMainHitbox()
self.mainHitbox = self.Hitbox(self, self.type, self:packForHitbox(), 0, 0, self.isSolid)
self.mainHitbox:advertiseAsMainHitbox()
end
function PhysicalActor:addHitbox(name, type, data, sx, sy, isSolid)
if (self.hitboxes[name] ~= nil) then
core.debug:logWarn("PhysicalActor", "the hitbox " .. name .. " already exists")
else
local hitbox = self.Hitbox(self, type, data, sx, sy, isSolid)
self.hitboxes[name] = hitbox
return hitbox
end
end
function PhysicalActor:updateHitboxes()
if (self.hitboxList ~= nil) then
self:purgeHitbox()
local animation, frame
animation = self.sprite:getCurrentAnimation()
frame = self.sprite: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 PhysicalActor:checkHitboxesCollisions(filter)
for k, v in pairs(self.hitboxes) do
self:applyHitboxCollisions(k, filter)
end
end
function PhysicalActor:applyHitboxCollisions(name, filter)
local cols, colNumber = {}, 0
local filter = filter or self.filter
if (self.isDestroyed == false) and (self.hitboxes[name] ~= nil) then
cols, colNumber = self.hitboxes[name]:checkCollision(filter)
local type = self.hitboxes[name].type
for i, col in ipairs(cols) do
self:hitboxResponse(name, type, col)
end
end
return cols, colNumber
end
function PhysicalActor:hitboxResponse(name, type, collision)
-- just a blank placeholder function
end
function PhysicalActor:removeHitbox(name)
if (self.hitboxes[name] ~= nil) then
self.hitboxes[name]:destroy()
self.hitboxes[name] = nil
end
end
function PhysicalActor:purgeHitbox()
for k, v in pairs(self.hitboxes) do
v:destroy()
end
self.hitboxes = {}
end
function PhysicalActor:drawHitboxes()
for k, v in pairs(self.hitboxes) do
v:draw()
end
self:drawMainHitbox()
end
function PhysicalActor:drawMainHitbox()
if (self.mainHitbox ~= nil) then
self.mainHitbox:draw()
end
end
return PhysicalActor

View file

@ -0,0 +1,101 @@
-- SpritedActor.lua :: Handle the sprite of the actor.
--[[
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 SpritedActor = Object:extend()
local Sprite = require("birb.modules.world.actors.utils.sprites")
function SpritedActor:initSprite()
self:addUpdateFunction(self.updateSprite)
end
function SpritedActor:setSprite(spritename, isClone, ox, oy)
self.sprite = Sprite(self, spritename, ox, oy)
if (isClone) then
self.sprite:clone()
end
end
function SpritedActor:changeAnimation(animation, restart)
if (self.sprite ~= nil) then
core.debug:logWarn("actor", "the function SpritedActor:changeAnimation is deprecated, prefer SpritedActor.sprite:changeAnimation()")
self.sprite:changeAnimation(animation, restart)
end
end
function SpritedActor:animationEnded(animation)
-- Empty placeholder function
end
function SpritedActor:setCustomSpeed(customSpeed)
if (self.sprite ~= nil) then
core.debug:logWarn("actor", "the function SpritedActor:setCustomSpeed is deprecated, prefer SpritedActor.sprite:setCustomSpeed()")
self.sprite:setCustomSpeed(customSpeed)
end
end
function SpritedActor:updateSprite(dt)
if (self.sprite ~= nil) then
self.sprite:update(dt)
end
end
function SpritedActor:getCurrentAnimation()
if (self.sprite ~= nil) then
core.debug:logWarn("actor", "the function SpritedActor:getCurrentAnimation is deprecated, prefer SpritedActor.sprite:getCurrentAnimation()")
return self.sprite:getCurrentAnimation()
end
end
function SpritedActor:getSpriteScalling()
core.debug:logWarn("actor", "the function SpritedActor:getSpriteScalling is deprecated, prefer SpritedActor.sprite:getScalling()")
return self.sprite:getScalling()
end
function SpritedActor:getFrame()
if (self.sprite ~= nil) then
core.debug:logWarn("actor", "the function SpritedActor:getFrame is deprecated, prefer SpritedActor.sprite:getFrame()")
return self.sprite:getFrame()
end
end
function SpritedActor:getRelativeFrame()
if (self.sprite ~= nil) then
core.debug:logWarn("actor", "the function SpritedActor:getRelativeFrame is deprecated, prefer SpritedActor.sprite:getRelativeFrame()")
return self.sprite:getRelativeFrame()
end
end
function SpritedActor:getAnimationDuration()
if (self.sprite ~= nil) then
core.debug:logWarn("actor", "the function SpritedActor:getAnimationDuration is deprecated, prefer SpritedActor.sprite:getAnimationDuration()")
return self.sprite:getAnimationDuration()
end
end
function SpritedActor:drawSprite(x, y, r, sx, sy, ox, oy, kx, ky)
if (self.sprite ~= nil) then
self.sprite:draw(x, y, r, sx, sy, ox, oy, kx, ky)
end
end
return SpritedActor

View file

@ -0,0 +1,47 @@
-- TimedActor.lua :: Handle the sprite of the actor.
--[[
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 TimedActor = Object:extend()
-- TIMER FUNCTIONS
-- Control the integrated timers of the actor
function TimedActor:initTimers()
self.timers = core.modules.Timers(self)
self:addUpdateFunction(self.updateTimers)
end
function TimedActor:addTimer(name, t)
core.debug:logWarn("actor", "function actor:addTimer is deprecated, prefer actor.timers:newTimer")
self.timers:newTimer(t, name)
end
function TimedActor:updateTimers(dt)
self.timers:update(dt)
end
function TimedActor:timerResponse(name)
-- here come the timer responses
end
return TimedActor

View file

@ -29,8 +29,8 @@ local TexturedBox = Box3D:extend()
function TexturedBox:new(owner, w, h, d, topTexture, bottomTexture) function TexturedBox:new(owner, w, h, d, topTexture, bottomTexture)
local bottomTexture = bottomTexture or topTexture local bottomTexture = bottomTexture or topTexture
self.topTexture = owner.assets.images[topTexture] self.topTexture = owner.assets:getWithType(topTexture, "texture")
self.bottomTexture = owner.assets.images[bottomTexture] self.bottomTexture = owner.assets:getWithType(bottomTexture, "texture")
TexturedBox.super.new(self, owner, w, h, d) TexturedBox.super.new(self, owner, w, h, d)
self.haveLine = false self.haveLine = false

View file

@ -27,16 +27,13 @@ local Hitbox2D = Object:extend()
-- INIT FUNCTIONS -- INIT FUNCTIONS
-- Initialise the actor and its base functions -- Initialise the actor and its base functions
function Hitbox2D:new(owner, type, ox, oy, w, h, isSolid) function Hitbox2D:new(owner, type, data, sx, sy, isSolid)
self.owner = owner self.owner = owner
self.world = owner.world self.world = owner.world
self.type = type self.type = type
self.ox = ox self:setFromData(data, sx, sy)
self.oy = oy
self.x, self.y = self:getPosition() self.x, self.y = self:getPosition()
self.w = w
self.h = h
self.isSolid = isSolid self.isSolid = isSolid
self.isMainHitBox = false self.isMainHitBox = false
@ -45,6 +42,24 @@ function Hitbox2D:new(owner, type, ox, oy, w, h, isSolid)
self:register() self:register()
end end
function Hitbox2D:setFromData(data, sx, sy)
local sx = sx or 0
local sy = sy or 0
self.ox = data[1]
self.oy = data[2]
self.w = data[3]
self.h = data[4]
if (sx < 0) then
self.ox = self.owner.w - self.ox - self.w
end
if (sy < 0) then
self.oy = self.owner.h - self.oy - self.h
end
end
function Hitbox2D:advertiseAsMainHitbox() function Hitbox2D:advertiseAsMainHitbox()
self.isMainHitBox = true self.isMainHitBox = true
end end
@ -100,7 +115,12 @@ end
-- COLLISION FUNCTIONS -- COLLISION FUNCTIONS
-- Handle Hitbox position -- Handle Hitbox position
function Hitbox2D:checkCollision(dx, dy, filter) function Hitbox2D:checkCollision(filter)
local _, _, cols, colNumber = self:checkCollisionAtPoint(self.owner.x, self.owner.y, filter)
return cols, colNumber
end
function Hitbox2D:checkCollisionAtPoint(dx, dy, filter)
self:updatePosition() self:updatePosition()
local dx, dy = self.ox + dx, self.oy + dy local dx, dy = self.ox + dx, self.oy + dy
@ -117,6 +137,8 @@ function Hitbox2D:draw()
local x, y = self:getPosition() local x, y = self:getPosition()
love.graphics.setColor(self.debug.r, self.debug.g, self.debug.b, 1) love.graphics.setColor(self.debug.r, self.debug.g, self.debug.b, 1)
utils.graphics.box(x, y, self.w, self.h) utils.graphics.box(x, y, self.w, self.h)
love.graphics.setColor(1, 1, 1, 1)
love.graphics.points(x, y)
utils.graphics.resetColor() utils.graphics.resetColor()
end end

View file

@ -27,18 +27,13 @@ local Hitbox3D = Object:extend()
-- INIT FUNCTIONS -- INIT FUNCTIONS
-- Initialise the actor and its base functions -- Initialise the actor and its base functions
function Hitbox3D:new(owner, type, ox, oy, oz, w, h, d, isSolid) function Hitbox3D:new(owner, type, data, sx, sy, isSolid)
self.owner = owner self.owner = owner
self.world = owner.world self.world = owner.world
self.type = type self.type = type
self.ox = ox self:setFromData(data, sx, sy)
self.oy = oy
self.oz = oz
self.x, self.y, self.z = self:getPosition() self.x, self.y, self.z = self:getPosition()
self.w = w
self.h = h
self.d = d
self.isSolid = isSolid self.isSolid = isSolid
self.isMainHitBox = false self.isMainHitBox = false
@ -47,6 +42,25 @@ function Hitbox3D:new(owner, type, ox, oy, oz, w, h, d, isSolid)
self:register() self:register()
end end
function Hitbox3D:setFromData(data, sx, sy)
local sx = sx or 0
local sy = sy or 0
self.ox = data[1]
self.oy = data[2]
self.oz = data[3]
self.w = data[4]
self.h = data[5]
self.d = data[6]
if (sx < 0) then
self.ox = self.owner.w - self.ox - self.w
end
if (sy < 0) then
self.oz = self.owner.d - self.oz - self.d
end
end
function Hitbox3D:advertiseAsMainHitbox() function Hitbox3D:advertiseAsMainHitbox()
self.isMainHitBox = true self.isMainHitBox = true
end end
@ -104,7 +118,12 @@ end
-- COLLISION FUNCTIONS -- COLLISION FUNCTIONS
-- Handle Hitbox position -- Handle Hitbox position
function Hitbox3D:checkCollision(dx, dy, dz, filter) function Hitbox3D:checkCollision(filter)
local _, _, _, cols, colNumber = self:checkCollisionAtPoint(self.owner.x, self.owner.y, self.owner.z, filter)
return cols, colNumber
end
function Hitbox3D:checkCollisionAtPoint(dx, dy, dz, filter)
self:updatePosition() self:updatePosition()
local dx, dy = self.ox + dx, self.oy + dy, self.oz + dz local dx, dy = self.ox + dx, self.oy + dy, self.oz + dz

View file

@ -17,7 +17,8 @@ end
function Sprite:clone() function Sprite:clone()
if self.name ~= nil then if self.name ~= nil then
self.spriteClone = self.assets.sprites[self.name]:clone() local baseSprite = self.assets:getWithType(self.name, "sprite")
self.spriteClone = baseSprite:clone()
self.spriteClone:setCallbackTarget(self.owner) self.spriteClone:setCallbackTarget(self.owner)
end end
end end
@ -110,7 +111,8 @@ function Sprite:draw(x, y, r, sx, sy, ox, oy, kx, ky)
if (self.spriteClone ~= nil) then if (self.spriteClone ~= nil) then
self.spriteClone:draw(x, y, r, sx, sy, ox, oy, kx, ky) self.spriteClone:draw(x, y, r, sx, sy, ox, oy, kx, ky)
else else
self.assets.sprites[self.name]:drawAnimation(x, y, r, sx, sy, ox, oy, kx, ky) local sprite = self.assets:getWithType(self.name, "sprite")
sprite:drawAnimation(x, y, r, sx, sy, ox, oy, kx, ky)
end end
end end
end end

View file

@ -0,0 +1,68 @@
-- indexedrect.lua :: An indexed rectangle is a rectangle indexed to a point,
-- Basically a rectangle that have its coordinate recalculated from an existing
-- point
--[[
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 Rect = require "birb.objects.2D.rect"
local IndexedRect = Rect:extend()
function IndexedRect:new(origin, ox, oy, w, h)
self.setOrigin(origin)
self.ox = ox
self.oy = oy
local x, y = self:getPosition()
IndexedRect.super.new(self, x, y, w, h)
end
function IndexedRect:setRelativePosition(ox, oy)
self.ox = ox or self.ox
self.oy = oy or self.oy
end
function IndexedRect:setOrigin(origin)
self.origin = origin
-- We should check if the origin is really a point
end
function IndexedRect:getOrigin(origin)
return self.origin
end
function IndexedRect:getPosition()
return self.origin.x + self.ox, self.origin.y + self.oy
end
function IndexedRect:updateRect()
local x, y = self:getPosition()
self:setPosition(x, y)
return x, y, self.w, self.h
end
function IndexedRect:modify(ox, oy, w, h)
self.ox = ox
self.oy = oy
self:setSize(w, h)
self:updateRect()
end
return IndexedRect

71
birb/objects/2D/point.lua Normal file
View file

@ -0,0 +1,71 @@
-- point.lua :: a 2D point.
--[[
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 Point = Object:extend()
function Point:new(x, y)
self.x, self.y = x, y
end
function Point:setPosition(x, y)
self.x, self.y = x, y
end
function Point:move(x, y)
local x = x or 0
local y = y or 0
self:setPosition(self.x + x, self.y + y)
end
function Point:getPosition()
return self.x, self.y
end
function Point:getDistance(x, y)
return utils.math.pointDistance(self.x, self.y, x, y)
end
function Point:getDistanceFromPoint(other)
local x, y = other:getPosition()
self:getDistance(x, y)
end
function Point:getDirection(x, y)
return utils.math.pointDirection(self.x, self.y, x, y)
end
function Point:getDirectionFromPoint(other)
local x, y = other:getPosition()
self:getDirection(x, y)
end
function Point:getMiddlePoint(x, y)
return utils.math.getMiddlePoint(self.x, self.y, x, y)
end
function Point:getDirectionFromPoint(other)
local x, y = other:getPosition()
self:getMiddlePoint(x, y)
end
return Point

65
birb/objects/2D/rect.lua Normal file
View file

@ -0,0 +1,65 @@
-- rect.lua :: a 2D rectangle.
--[[
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 Point = require "birb.objects.2D.point"
local Rect = Point:extend()
function Rect:new(x, y, w, h)
Rect.super.new(self, x, y)
self:setSize(w, h)
end
function Rect:setSize(w, h)
self.w = w or self.w
self.h = h or self.h
end
function Rect:getArea()
local x, y = self:getPosition()
return x, y, self.w, self.h
end
function Rect:getCorners()
local x, y, w, h = self:getArea()
return x, y, x + w, y + h
end
function Rect:getCenter()
local x, y, w, h = self:getArea()
return math.floor(x + (w/2)), math.floor(y + (h/2))
end
function Rect:areCoordInside(dx, dy)
local x, y, w, h = self:getArea()
return ((dx > x) and (dx < x + w) and (dy > y) and (dy < y + h))
end
function Rect:getRelativeCoordinate(dx, dy)
return dx - self.x, dy - self.y
end
function Rect:drawBox()
utils.graphics.box(self.x, self.y, self.w, self.h)
end
return Rect

View file

@ -87,7 +87,6 @@ function Math.pointDistance(x1, y1, x2, y2)
vecy = math.max(y1, y2) - math.min(y1, y2) vecy = math.max(y1, y2) - math.min(y1, y2)
return math.sqrt(vecx^2 + vecy^2) return math.sqrt(vecx^2 + vecy^2)
end end
function Math.pointDirection(x1,y1,x2,y2) function Math.pointDirection(x1,y1,x2,y2)
@ -99,6 +98,34 @@ function Math.pointDirection(x1,y1,x2,y2)
return angle return angle
end end
-- 3D MATH FUNCTIONS
-- Basic math calculations
function Math.getMiddlePoint3D(x1, y1, z1, x2, y2, z2)
local newx, newy, newz, vecx, vecy, vecz
vecx = math.max(x1, x2) - math.min(x1, x2)
vecy = math.max(y1, y2) - math.min(y1, y2)
vecz = math.max(z1, z2) - math.min(z1, z2)
newx = math.min(x1, x2) + (vecx / 2)
newy = math.min(y1, y2) + (vecy / 2)
newz = math.min(z1, z2) + (vecz / 2)
return newx, newy, newz
end
function Math.pointDistance3D(x1, y1, z1, x2, y2, z2)
local vecx, vecy, vecz
vecx = math.max(x1, x2) - math.min(x1, x2)
vecy = math.max(y1, y2) - math.min(y1, y2)
vecz = math.max(z1, z2) - math.min(z1, z2)
return math.sqrt(vecx^2 + vecy^2 + vecz^2)
end
-- STRING FUNCTIONS -- STRING FUNCTIONS
-- Transform into string numbers -- Transform into string numbers

View file

@ -1,13 +1,13 @@
return { return {
["idle"] = { ["idle"] = {
{ {
{"main", 0, 0, 0, 16, 16, 24, true} {"main", {0, 0, 0, 16, 16, 24}, true}
} }
}, },
["punch"] = { ["punch"] = {
{ {
{"main", 0, 0, 0, 16, 16, 24, true}, {"main", {0, 0, 0, 16, 16, 24}, true},
{"punch", 16, 2, 6, 12, 12, 12, false} {"punch", {16, 2, 6, 12, 12, 12}, false}
} }
} }
} }

View file

@ -1,13 +1,13 @@
return { return {
["idle"] = { ["idle"] = {
{ {
{"main", 0, 0, 16, 24, true} {"main", {0, 0, 16, 24}, true}
} }
}, },
["punch"] = { ["punch"] = {
{ {
{"main", 0, 0, 16, 24, true}, {"main", {0, 0, 16, 24}, true},
{"punch", 16, 6, 12, 12, false} {"punch", {16, 6, 12, 12}, false}
} }
} }
} }

View file

@ -24,7 +24,7 @@ end
function ResumeWidget:new(menu) function ResumeWidget:new(menu)
self.scene = menu.scene self.scene = menu.scene
local font = self.scene.assets.fonts["medium"] local font = self.scene.assets:getFont("medium")
local label = "resume" local label = "resume"
ResumeWidget.super.new(self, menu, font, label) ResumeWidget.super.new(self, menu, font, label)
end end
@ -36,7 +36,7 @@ end
function RestartWidget:new(menu) function RestartWidget:new(menu)
self.scene = menu.scene self.scene = menu.scene
local font = self.scene.assets.fonts["medium"] local font = self.scene.assets:getFont("medium")
local label = "restart" local label = "restart"
RestartWidget.super.new(self, menu, font, label) RestartWidget.super.new(self, menu, font, label)
end end
@ -48,7 +48,7 @@ end
function ExitWidget:new(menu) function ExitWidget:new(menu)
self.scene = menu.scene self.scene = menu.scene
local font = self.scene.assets.fonts["medium"] local font = self.scene.assets:getFont("medium")
local label = "exit" local label = "exit"
ExitWidget.super.new(self, menu, font, label) ExitWidget.super.new(self, menu, font, label)
end end

View file

@ -97,7 +97,7 @@ end
function SubMenuWidget:new(scene, menu, newmenu, fullname, order) function SubMenuWidget:new(scene, menu, newmenu, fullname, order)
self.scene = scene self.scene = scene
local widgetmenu = self.scene.menusystem.menus[menu] local widgetmenu = self.scene.menusystem.menus[menu]
local font = self.scene.assets.fonts["medium"] local font = self.scene.assets:getFont("medium")
self.newmenu = newmenu self.newmenu = newmenu
local label = "" local label = ""
if fullname == "back" then if fullname == "back" then
@ -122,7 +122,7 @@ function SceneWidget:new(scene, menu, newscene, fullname, args)
self.scene = scene self.scene = scene
self.args = args self.args = args
local widgetmenu = self.scene.menusystem.menus[menu] local widgetmenu = self.scene.menusystem.menus[menu]
local font = self.scene.assets.fonts["medium"] local font = self.scene.assets:getFont("medium")
self.newscene = newscene self.newscene = newscene
local label = core.lang:translate("mainmenu", fullname) local label = core.lang:translate("mainmenu", fullname)
SceneWidget.super.new(self, widgetmenu, font, label) SceneWidget.super.new(self, widgetmenu, font, label)
@ -139,7 +139,7 @@ end
function ExitWidget:new(scene, menu) function ExitWidget:new(scene, menu)
self.scene = scene self.scene = scene
local widgetmenu = self.scene.menusystem.menus[menu] local widgetmenu = self.scene.menusystem.menus[menu]
local font = self.scene.assets.fonts["medium"] local font = self.scene.assets:getFont("medium")
local label = core.lang:translate("commons", "exit") local label = core.lang:translate("commons", "exit")
SceneWidget.super.new(self, widgetmenu, font, label) SceneWidget.super.new(self, widgetmenu, font, label)
end end