diff --git a/sonic-radiance.love/core/modules/assets/animator.lua b/sonic-radiance.love/core/modules/assets/animator.lua new file mode 100644 index 0000000..c92efb3 --- /dev/null +++ b/sonic-radiance.love/core/modules/assets/animator.lua @@ -0,0 +1,63 @@ +local Animator = Object:extend() + +function Animator:new(sprite) + self.sprite = sprite + self.frame = 1 + self.frameTimer = 0 + self.currentAnimation = "" + self.animationData = {} + + self.customSpeed = 0 + + self:changeToDefaultAnimation() +end + +function Animator:setCustomSpeed(customSpeed) + self.customSpeed = customSpeed or 0 +end + +function Animator:update(dt) + if (self.currentAnimation == "") then + print("warning: no current animation data") + return 0 + end + + local speed = self.animationData.speed + if (self.animationData.speed) == -1 then + speed = self.customSpeed --math.abs(self.xsp / 16) + end + self.frameTimer = self.frameTimer + (speed * dt) + if self.frameTimer > 1 then + self.frameTimer = 0 + if self.frame == self.animationData.endAt then + self.frame = self.animationData.loop + else + self.frame = self.frame + 1 + end + end +end + +function Animator:getFrame() + return self.frame +end + +function Animator:draw(x, y, r, sx, sy, ox, oy, kx, ky) + self.sprite:drawFrame(self.frame, x, y, r, sx, sy, ox, oy, kx, ky) +end + +function Animator:changeAnimation(name, restart) + self.currentAnimation = name + self.animationData = self.sprite.data.animations[self.currentAnimation] + local restart = restart or true + + if (restart) then + self.frame = self.animationData.startAt + self.frameTimer = 0 + end +end + +function Animator:changeToDefaultAnimation(restart) + self:changeAnimation(self.sprite.data.metadata.defaultAnim, restart) +end + +return Animator diff --git a/sonic-radiance.love/core/modules/assets/autotile.lua b/sonic-radiance.love/core/modules/assets/autotile.lua new file mode 100644 index 0000000..8722044 --- /dev/null +++ b/sonic-radiance.love/core/modules/assets/autotile.lua @@ -0,0 +1,85 @@ +local Tileset = require "core.modules.assets.tileset" +local Autotile = Object:extend() + +function Autotile:new(filepath) + self.tileset = Tileset(filepath) + + self.data = require(filepath .. ".lua") + self.metadata = self.data.metadata + + self.tilesize = self.metadata.width +end + +function Autotile:drawtile(i, j, x, y, r, sx, sy, ox, oy, kx, ky) + local i = i or 1 + local j = j or 1 + local tilesize = self.tilesize / 2 + i = (i - 1) * 2 + 1 + j = (j - 1) * 2 + 1 + self.tileset:drawTile_Grid(i , j , x , y , r, sx, sy, ox, oy, kx, ky) + self.tileset:drawTile_Grid(i + 1, j , x + tilesize, y , r, sx, sy, ox, oy, kx, ky) + self.tileset:drawTile_Grid(i , j + 1, x , y + tilesize, r, sx, sy, ox, oy, kx, ky) + self.tileset:drawTile_Grid(i + 1, j + 1, x + tilesize, y + tilesize, r, sx, sy, ox, oy, kx, ky) +end + +function Autotile:draw(x, y, w, h) + local w = w or self.tilesize + local h = h or self.tilesize + w = math.max(math.floor(w / self.tilesize), 1) + h = math.max(math.floor(h / self.tilesize), 1) + local halfsize = self.tilesize / 2 + local tilesize = self.tilesize + if (w == 1) then + self.tileset:drawtile_Grid(1, 1, x , y) + self.tileset:drawtile_Grid(1, 6, x , y + (h*2 - 1) * halfsize) + self.tileset:drawtile_Grid(6, 1, x + (w*2 - 1) * halfsize, y) + self.tileset:drawtile_Grid(6, 6, x + (w*2 - 1) * halfsize, y + (h*2 - 1) * halfsize) + if (h > 1) then + h = h - 1 + for i = 1, h do + self.tileset:drawtile_Grid(1, 3, x, y + (i * tilesize) - halfsize) + self.tileset:drawtile_Grid(6, 3, x + halfsize, y + (i * tilesize) - halfsize) + + self.tileset:drawtile_Grid(1, 4, x , y + (i * tilesize)) + self.tileset:drawtile_Grid(6, 4, x + halfsize, y + (i * tilesize)) + end + end + -- draw just one stuff + else + if (h == 1) then + self.tileset:drawtile_Grid(1, 1, x , y) + self.tileset:drawtile_Grid(1, 6, x , y + (h*2 - 1) * halfsize) + self.tileset:drawtile_Grid(6, 1, x + (w*2 - 1) * halfsize, y) + self.tileset:drawtile_Grid(6, 6, x + (w*2 - 1) * halfsize, y + (h*2 - 1) * halfsize) + w = w - 1 + for i = 1, w do + self.tileset:drawtile_Grid(3, 1, x + (i * tilesize) - halfsize, y) + self.tileset:drawtile_Grid(3, 6, x + (i * tilesize) - halfsize, y + halfsize) + + self.tileset:drawtile_Grid(4, 1, x + (i * tilesize) , y ) + self.tileset:drawtile_Grid(4, 6, x + (i * tilesize), y +halfsize) + end + else + self:drawtile(1, 1, x , y) + self:drawtile(1, 3, x , y + (h - 1) * tilesize) + self:drawtile(3, 1, x + (w - 1) * tilesize, y) + self:drawtile(3, 3, x + (w - 1) * tilesize, y + (h - 1) * tilesize) + w = w - 2 + h = h - 2 + for i=1, w do + self:drawtile(2, 1, i * tilesize, y) + self:drawtile(2, 3, i * tilesize, y + (h + 1) * tilesize) + for j=1, h do + self:drawtile(2, 2, i * tilesize, j * tilesize) + end + end + + for i=1, h do + self:drawtile(1, 2, x , i * tilesize) + self:drawtile(3, 2, x + (w + 1) * tilesize, i * tilesize) + end + end + end +end + +return Autotile diff --git a/sonic-radiance.love/core/modules/assets/background.lua b/sonic-radiance.love/core/modules/assets/background.lua new file mode 100644 index 0000000..eb6d6e0 --- /dev/null +++ b/sonic-radiance.love/core/modules/assets/background.lua @@ -0,0 +1,26 @@ +local Background = Object:extend() + +function Background:new(filepath) + self.image = love.graphics.newImage(filepath) + self.batch = love.graphics.newSpriteBatch(self.image , 1000 ) + + self.width, self.height = self.image:getDimensions() + + local w = math.floor(424 / self.width) * self.width + 1 + local h = math.floor(240 / self.height) * self.height + 1 + + for i=-1, w do + for j=-1, h do + self.batch:add(i * self.width, j * self.height) + j = j + 1 + end + i = i + 1 + end +end + +function Background:draw(ox, oy) + love.graphics.setColor(1, 1, 1) + love.graphics.draw(self.batch, ox, oy) +end + +return Background diff --git a/sonic-radiance.love/core/modules/assets/fonts.lua b/sonic-radiance.love/core/modules/assets/fonts.lua new file mode 100644 index 0000000..2a7c0cd --- /dev/null +++ b/sonic-radiance.love/core/modules/assets/fonts.lua @@ -0,0 +1,153 @@ +local Font = Object:extend() + +-- Initilizing and configuring option + +function Font:new(filename, size) + local filename = filename + self.font = love.graphics.newFont(filename, size) + self.filter = "" + self:setColor(1, 1, 1, 1) + self:setSpacing(false, 0) + self.align = "left" +end + +function Font:set() + love.graphics.setFont(self.font) +end + +function Font:setColor(r, g, b, a) + self.color = {} + self.color.r = r + self.color.g = g + self.color.b = b + self.color.a = a +end + +function Font:setColorFromTable(color) + self.color = color +end + +function Font:setSpacing(use_custom, size) + self.spacing = {} + self.spacing.active = use_custom + self.spacing.size = size +end + +function Font:setAlign(align) + self.align = align +end + +function Font:setFilter(filter) + self.filter = filter +end + +function Font:setLineHeight(height) + self.font:setLineHeight(height) +end + +-- get information functions + +function Font:getHeight() + local font = self.font + return font:getHeight() +end + +function Font:getWidth(string) + local spacing = 0 + if (self.spacing.active == true) then + local charNumber = string.len(string) + spacing = self.spacing.size * charNumber + end + local width = self.font:getWidth(string) + spacing + return width +end + +function Font:getColor() + return self.color +end + +-- print functions + +function Font:draw(text, x, y, limit, align, r, sx, sy, ox, oy, kx, ky) + -- draw text with color and effect applied + local limit = limit or 0 + local align = align or self.align + + self:applyFilter(text, x, y, limit, align, r, sx, sy, ox, oy, kx, ky) + love.graphics.setColor(self.color.r, self.color.g, self.color.b, self.color.a) + self:printf(text, x, y, limit, align, r, sx, sy, ox, oy, kx, ky) +end + +function Font:print(text, x, y, align, r, sx, sy, ox, oy, kx, ky) + + self:set() + if (self.spacing.active) then + utils.draw.printWithSpacing(text, self.spacing.size, align, x, y, r, sx, sy, ox, oy, kx, ky) + else + utils.draw.print(text, align, x, y, r, sx, sy, ox, oy, kx, ky) + end + +end + +function Font:printf(text, x, y, limit, align, r, sx, sy, ox, oy, kx, ky) + self:set() + if (limit > 0) then + love.graphics.printf(text, x, y, limit, align, r, sx, sy, ox, oy, kx, ky) + else + self:print(text, x, y, align, r, sx, sy, ox, oy, kx, ky) + end +end + +-- FILTER SYSTEM + +function Font:applyFilter(text, x, y, limit, align, r, sx, sy, ox, oy, kx, ky) + if self.filter == "shadow" then + self:applyFilterShadow(text, x, y, limit, align, r, sx, sy, ox, oy, kx, ky) + elseif self.filter == "border" then + self:applyFilterBorder(text, x, y, limit, align, r, sx, sy, ox, oy, kx, ky) + elseif self.filter == "doubleborder" then + self:applyFilterDoubleBorder(text, x, y, limit, align, r, sx, sy, ox, oy, kx, ky) + end +end + +function Font:applyFilterShadow(text, x, y, limit, align, r, sx, sy, ox, oy, kx, ky) + love.graphics.setColor(0, 0, 0, 1) + self:printf(text, x+1, y+1, limit, align, align, r, sx, sy, ox, oy, kx, ky) + utils.draw.resetColor() +end + +function Font:applyFilterBorder(text, x, y, limit, align, r, sx, sy, ox, oy, kx, ky) + love.graphics.setColor(0, 0, 0, 1) + + self:printf(text, x-1, y-1, limit, align, r, sx, sy, ox, oy, kx, ky) + self:printf(text, x , y-1, limit, align, r, sx, sy, ox, oy, kx, ky) + self:printf(text, x+1, y-1, limit, align, r, sx, sy, ox, oy, kx, ky) + + self:printf(text, x+1, y , limit, align, r, sx, sy, ox, oy, kx, ky) + self:printf(text, x-1, y , limit, align, r, sx, sy, ox, oy, kx, ky) + + self:printf(text, x-1, y+1, limit, align, r, sx, sy, ox, oy, kx, ky) + self:printf(text, x , y+1, limit, align, r, sx, sy, ox, oy, kx, ky) + self:printf(text, x+1, y+1, limit, align, r, sx, sy, ox, oy, kx, ky) + + utils.draw.resetColor() +end + +function Font:applyFilterDoubleBorder(text, x, y, limit, align, r, sx, sy, ox, oy, kx, ky) + love.graphics.setColor(0, 0, 0, 1) + + self:printf(text, x-2, y-2, limit, align, r, sx, sy, ox, oy, kx, ky) + self:printf(text, x , y-2, limit, align, r, sx, sy, ox, oy, kx, ky) + self:printf(text, x+2, y-2, limit, align, r, sx, sy, ox, oy, kx, ky) + + self:printf(text, x+2, y , limit, align, r, sx, sy, ox, oy, kx, ky) + self:printf(text, x-2, y , limit, align, r, sx, sy, ox, oy, kx, ky) + + self:printf(text, x-2, y+2, limit, align, r, sx, sy, ox, oy, kx, ky) + self:printf(text, x , y+2, limit, align, r, sx, sy, ox, oy, kx, ky) + self:printf(text, x+2, y+2, limit, align, r, sx, sy, ox, oy, kx, ky) + + utils.draw.resetColor() +end + +return Font diff --git a/sonic-radiance.love/core/modules/assets/init.lua b/sonic-radiance.love/core/modules/assets/init.lua new file mode 100644 index 0000000..dde730b --- /dev/null +++ b/sonic-radiance.love/core/modules/assets/init.lua @@ -0,0 +1,162 @@ +local Assets = Object:extend() + +local Sprite = require "core.modules.assets.sprites" +local Font = require "core.modules.assets.fonts" +local Tileset = require "core.modules.assets.tileset" +local Autotile = require "core.modules.assets.autotile" +local Background = require "core.modules.assets.background" + + +function Assets:new() + self.sprites = {} + self.sfx = {} + self.fonts = {} + self.music = nil + self:clearBackgrounds() + self:clearFonts() + self:clearAutotile() + self:clearTileset() + + self.images = {} +end + +function Assets:init() + self.sprites = {} + self.sfx = {} + self.fonts = {} + self.music = nil + self.backgrounds= {} + self:clearFonts() + + self.images = {} +end + +function Assets:clear() + self.sprites = {} + self.sfx = {} + self.fonts = {} + self.music = nil + self.backgrounds= {} + self:clearFonts() + + self.images = {} +end + +function Assets:update(dt) + self:animationsUpdate(dt) +end + +-- SFX et Musique + +function Assets:addSFX(name, filepath) + self:newSFX(name, filepath) +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:setMusic(filename) + if filename ~= nil then + love.audio.stop( ) + self.music = love.audio.newSource(filename, "stream" ) + self.music:setVolume(game.options.data.audio.music / 100) + end +end + +function Assets:playSFX(filename) + if not (self.sfx[filename] == nil) then + self.sfx[filename]:stop() + self.sfx[filename]:setVolume(game.options.data.audio.sfx / 100) + love.audio.play( self.sfx[filename] ) + end +end + +function Assets:playMusic() + if not (self.music == nil) then + love.audio.play(self.music) + end +end + +function Assets:silence() + love.audio.stop() +end + +-- Background -- + +function Assets:addImage(name, filename) + self.images[name] = love.graphics.newImage(filename) +end + +function Assets:drawImage(name, x, y, r, sx, sy, ox, oy, kx, ky) + love.graphics.draw(self.images[name], x, y, r, sx, sy, ox, oy, kx, ky) +end + +-- Images -- + +function Assets:clearBackgrounds() + self.backgrounds = {} +end + +function Assets:addBackground(name, filepath) + self.backgrounds[name] = Background(filepath) +end + +-- SPRITES -- + + +function Assets:addSprite(name, filepath) + self.sprites[name] = Sprite(filepath) +end + +function Assets:clearSprites() + self.sprites = {} +end + +function Assets:animationsUpdate(dt) + for i,v in pairs(self.sprites) do + v:update(dt) + end +end + +-- FONTS -- + +function Assets:clearFonts() + self.fonts = {} +end + +function Assets:addFont(key, filename, size) + local font = Font(filename, size) + self.fonts[key] = font +end + +function Assets:getFont(filename) + return self.fonts[filename] +end + +-- Tileset + +function Assets:addTileset(name, filepath) + self.tileset[name] = Tileset(filepath) +end + +function Assets:clearTileset() + self.tileset = {} +end + +-- Autotile + +function Assets:addAutotile(name, tilesize) + self.autotile[name] = Autotile(name, tilesize) +end + +function Assets:clearAutotile() + self.autotile = {} +end + +return Assets diff --git a/sonic-radiance.love/core/modules/assets/sprites.lua b/sonic-radiance.love/core/modules/assets/sprites.lua new file mode 100644 index 0000000..901f2bc --- /dev/null +++ b/sonic-radiance.love/core/modules/assets/sprites.lua @@ -0,0 +1,56 @@ +-- Un sprite est un tileset animé par un animateur. Un animateur est nécessairement +-- lié à un sprite, mais on peut en invoqué des différents, suivant les besoins. + +local Sprite = Object:extend() +local Animator = require("core.modules.assets.animator") +local Tileset = require("core.modules.assets.tileset") + +function Sprite:new(filepath) + self.tileset = Tileset(filepath) + self.data = require(filepath) + + self.animator = Animator(self) + + self.customSpeed = 0 + + self:changeToDefaultAnimation(true) +end + +function Sprite:update(dt) + self.animator:update(dt) +end + +function Sprite:setCustomSpeed(customSpeed) + self.animator:setCustomSpeed(customSpeed) +end + +function Sprite:changeToDefaultAnimation(restart) + self.animator:changeToDefaultAnimation(restart) +end + +function Sprite:changeAnimation(name, restart) + self.animator:changeAnimation(name, restart) +end + +function Sprite:drawAnimation(x, y, r, sx, sy, ox, oy, kx, ky) + self.animator:draw(x, y, r, sx, sy, ox, oy, kx, ky) +end + +function Sprite:drawFrame(frame, x, y, r, sx, sy, ox, oy, kx, ky) + self.tileset:drawTile(frame, x, y, r, sx, sy, ox, oy, kx, ky) +end + +function Sprite:drawPart(x, y, w, h, r, sx, sy, ox, oy, kx, ky) + local w = math.floor(w) + local h = math.floor(h) + + if w >= 0 and h <= 0 then + return 0 + end + + love.graphics.setScissor(x - ox, y - oy, w, h) + self:drawAnimation(x, y, r, sx, sy, ox, oy, kx, ky) + love.graphics.setScissor( ) +end + +return Sprite diff --git a/sonic-radiance.love/core/modules/assets/tileset.lua b/sonic-radiance.love/core/modules/assets/tileset.lua new file mode 100644 index 0000000..e97652c --- /dev/null +++ b/sonic-radiance.love/core/modules/assets/tileset.lua @@ -0,0 +1,69 @@ +-- Les tileset sont des découpages de texture automatique en quads. Ils ont +-- l'aventage d'être automatisé, réduisant la quantité de code nécessaire à chaque fois +-- qu'on veut des quads. + +-- Ils ont deux façons d'être dessiné : avec leur identifiant de frame (en une dimension) +-- ou en utilisant leur emplacement sur la "grille", en 2D. +-- La grille est un poil plus long, parce que cela nécessite de faire une multiplication + +local Tileset = Object:extend() + +function Tileset:new(filepath) + self.texture = love.graphics.newImage(filepath .. ".png") + + local data = require(filepath) + self.metadata = data.metadata + + self:createQuads() +end + +function Tileset:createGrid() + self.textureWidth, self.textureHeight = self.texture:getDimensions() + self.width, self.height = self.metadata.width, self.metadata.height + self.gridWidth, self.gridHeight = math.floor(self.textureWidth / self.width), + math.floor(self.textureHeight / self.height) +end + +function Tileset:createQuads() + self.quads = {} + + + self:createGrid() + + local quad, n + + n = 1 + for i=0, (self.gridHeight-1) do + for j=0, (self.gridWidth-1) do + quad = love.graphics.newQuad(j * self.width, i * self.height, self.width, self.height, self.textureWidth, self.textureHeight) + self.quads[n] = quad + n = n + 1 + end + end + +end + +function Tileset:getTileID_Grid(x, y) + local n = (y - 1) * self.gridWidth + x + + return n +end + +function Tileset:getTile_Grid(x, y) + return self:getTile(self:getTileID_Grid(x, y)) +end + +function Tileset:getTile(n) + return self.quads[n] +end + +function Tileset:drawTile_Grid(i, j, x, y, r, sx, sy, ox, oy, kx, ky) + local tileID = self:getTileID_Grid(i, j) + love.graphics.draw(self.texture, self.quads[tileID], x, y, r, sx, sy, ox, oy, kx, ky) +end + +function Tileset:drawTile(id, x, y, r, sx, sy, ox, oy, kx, ky) + love.graphics.draw(self.texture, self.quads[id], x, y, r, sx, sy, ox, oy, kx, ky) +end + +return Tileset