From ca3d486a835be887c2765b0b4a2fc851ef3c7f34 Mon Sep 17 00:00:00 2001 From: Kazhnuz Date: Thu, 25 Nov 2021 11:28:31 +0100 Subject: [PATCH] chore: initial non-working port of the gameplay --- sonic-bluestreak.love/assets/subgames.lua | 4 +- .../game/abstractmobs/character/datas.lua | 32 ++ .../game/abstractmobs/character/equip.lua | 60 +++ .../game/abstractmobs/character/health.lua | 7 + .../game/abstractmobs/character/init.lua | 74 ++++ .../game/abstractmobs/character/levels.lua | 61 +++ .../abstractmobs/character/statmanager.lua | 27 ++ .../game/abstractmobs/ennemy/init.lua | 47 +++ .../game/abstractmobs/ennemy/statmanager.lua | 31 ++ .../game/abstractmobs/parent.lua | 179 +++++++++ .../game/abstractmobs/statmanager.lua | 36 ++ sonic-bluestreak.love/game/battle.lua | 37 ++ sonic-bluestreak.love/game/characters.lua | 178 +++++---- sonic-bluestreak.love/game/difficulty.lua | 23 ++ sonic-bluestreak.love/game/ennemies.lua | 10 +- .../game/events/conditions.lua | 12 + .../game/events/event/dialogbox.lua | 67 ++++ .../game/events/event/getItems.lua | 16 + .../game/events/event/getRings.lua | 16 + .../game/events/event/init.lua | 11 + .../game/events/event/parent.lua | 26 ++ .../game/events/event/playSFX.lua | 16 + .../game/events/event/showGFX.lua | 16 + .../game/events/event/simpleMessage.lua | 16 + .../game/events/event/teleport.lua | 23 ++ .../game/events/event/wait.lua | 19 + sonic-bluestreak.love/game/events/init.lua | 101 +++++ sonic-bluestreak.love/game/init.lua | 163 ++++---- .../game/loot/effectManager.lua | 55 +++ .../game/loot/effects/blockstatus.lua | 17 + .../game/loot/effects/heal.lua | 79 ++++ .../game/loot/effects/init.lua | 6 + .../game/loot/effects/parent.lua | 21 + .../game/loot/effects/protectelem.lua | 19 + .../game/loot/effects/setstatus.lua | 43 ++ sonic-bluestreak.love/game/loot/init.lua | 67 ++++ sonic-bluestreak.love/game/loot/pocket.lua | 62 +++ sonic-bluestreak.love/game/metadata.lua | 83 ++++ .../game/modules/confirmdialog/init.lua | 97 +++++ .../game/modules/drawing/greyscale.lua | 23 ++ .../modules/drawing/parallaxBackground.lua | 165 ++++++++ .../game/modules/gui/actionPrompt.lua | 52 +++ .../game/modules/gui/boxedmenu.lua | 71 ++++ .../game/modules/gui/choiceElem.lua | 22 ++ .../game/modules/gui/complexhpbar.lua | 85 ++++ .../game/modules/gui/emblem.lua | 45 +++ .../game/modules/gui/fancymenu.lua | 32 ++ .../game/modules/gui/frame.lua | 17 - .../game/modules/gui/gameover.lua | 44 +++ .../game/modules/gui/init.lua | 98 ++++- .../game/modules/gui/menuback.lua | 72 ++++ .../game/modules/gui/overlay.lua | 96 +++++ .../game/modules/gui/simplehpbar.lua | 30 ++ .../game/modules/gui/status.lua | 60 --- .../game/modules/menus/fancy.lua | 78 ++++ .../game/modules/menus/list.lua | 172 ++++++++ .../game/modules/menus/parents/menu.lua | 36 ++ .../game/modules/menus/parents/widget.lua | 13 + .../game/modules/messagequeue/init.lua | 40 ++ .../game/modules/messagequeue/message.lua | 42 ++ .../game/modules/playstyle/assets.lua | 29 -- .../game/modules/playstyle/pause.lua | 74 ---- .../modules/{playstyle => subgames}/init.lua | 47 ++- .../game/modules/subgames/pause.lua | 63 +++ .../world/actors/collisions/fakefloor.lua | 2 +- .../world/actors/collisions/floor.lua | 2 +- .../world/actors/collisions/invisible.lua | 2 +- .../world/actors/collisions/textured.lua | 2 +- .../world/actors/collisions/wall.lua | 2 +- .../world/actors/ennemies/motobug.lua | 6 + .../world/actors/ennemies/parent.lua | 2 +- .../{ => subgames}/world/actors/init.lua | 0 .../world/actors/items/collectible.lua | 2 +- .../world/actors/items/ring.lua | 0 .../{ => subgames}/world/actors/parent.lua | 2 +- .../subgames/world/actors/player/init.lua | 146 +++++++ .../world/actors/player/weapons.lua | 4 +- .../world/actors/weapons/parent.lua | 14 +- .../modules/{ => subgames}/world/battle.lua | 4 +- .../{ => subgames}/world/maps/battle.lua | 4 +- .../game/modules/subgames/world/maps/init.lua | 7 + .../{ => subgames}/world/maps/shoot.lua | 110 +----- .../game/modules/subgames/world/maps/test.lua | 48 +++ .../{ => subgames}/world/maps/tools/chunk.lua | 2 +- .../world/maps/tools/chunkterrain.lua | 0 .../modules/{ => subgames}/world/parent.lua | 7 +- .../modules/{ => subgames}/world/shoot.lua | 4 +- .../game/modules/transitions/eggman.lua | 8 + .../game/modules/transitions/init.lua | 5 + .../game/modules/transitions/sonic.lua | 8 + .../game/modules/transitions/zigzag.lua | 41 ++ .../game/modules/tweenmanager/init.lua | 88 ----- .../game/modules/tweenmanager/libs/tween.lua | 367 ------------------ .../modules/world/actors/ennemies/motobug.lua | 6 - .../game/modules/world/maps/init.lua | 7 - .../game/modules/world/maps/test.lua | 46 --- sonic-bluestreak.love/game/scenes/init.lua | 45 +++ .../game/subgame/sonic-boost.lua | 18 - .../game/utils/battle/init.lua | 84 ++++ .../game/utils/characters.lua | 33 ++ .../game/utils/gizmo/properties.lua | 5 + .../game/{modules => }/utils/init.lua | 0 102 files changed, 3468 insertions(+), 1028 deletions(-) create mode 100644 sonic-bluestreak.love/game/abstractmobs/character/datas.lua create mode 100644 sonic-bluestreak.love/game/abstractmobs/character/equip.lua create mode 100644 sonic-bluestreak.love/game/abstractmobs/character/health.lua create mode 100644 sonic-bluestreak.love/game/abstractmobs/character/init.lua create mode 100644 sonic-bluestreak.love/game/abstractmobs/character/levels.lua create mode 100644 sonic-bluestreak.love/game/abstractmobs/character/statmanager.lua create mode 100644 sonic-bluestreak.love/game/abstractmobs/ennemy/init.lua create mode 100644 sonic-bluestreak.love/game/abstractmobs/ennemy/statmanager.lua create mode 100644 sonic-bluestreak.love/game/abstractmobs/parent.lua create mode 100644 sonic-bluestreak.love/game/abstractmobs/statmanager.lua create mode 100644 sonic-bluestreak.love/game/battle.lua create mode 100644 sonic-bluestreak.love/game/difficulty.lua create mode 100644 sonic-bluestreak.love/game/events/conditions.lua create mode 100644 sonic-bluestreak.love/game/events/event/dialogbox.lua create mode 100644 sonic-bluestreak.love/game/events/event/getItems.lua create mode 100644 sonic-bluestreak.love/game/events/event/getRings.lua create mode 100644 sonic-bluestreak.love/game/events/event/init.lua create mode 100644 sonic-bluestreak.love/game/events/event/parent.lua create mode 100644 sonic-bluestreak.love/game/events/event/playSFX.lua create mode 100644 sonic-bluestreak.love/game/events/event/showGFX.lua create mode 100644 sonic-bluestreak.love/game/events/event/simpleMessage.lua create mode 100644 sonic-bluestreak.love/game/events/event/teleport.lua create mode 100644 sonic-bluestreak.love/game/events/event/wait.lua create mode 100644 sonic-bluestreak.love/game/events/init.lua create mode 100644 sonic-bluestreak.love/game/loot/effectManager.lua create mode 100644 sonic-bluestreak.love/game/loot/effects/blockstatus.lua create mode 100644 sonic-bluestreak.love/game/loot/effects/heal.lua create mode 100644 sonic-bluestreak.love/game/loot/effects/init.lua create mode 100644 sonic-bluestreak.love/game/loot/effects/parent.lua create mode 100644 sonic-bluestreak.love/game/loot/effects/protectelem.lua create mode 100644 sonic-bluestreak.love/game/loot/effects/setstatus.lua create mode 100644 sonic-bluestreak.love/game/loot/init.lua create mode 100644 sonic-bluestreak.love/game/loot/pocket.lua create mode 100644 sonic-bluestreak.love/game/metadata.lua create mode 100644 sonic-bluestreak.love/game/modules/confirmdialog/init.lua create mode 100644 sonic-bluestreak.love/game/modules/drawing/greyscale.lua create mode 100644 sonic-bluestreak.love/game/modules/drawing/parallaxBackground.lua create mode 100644 sonic-bluestreak.love/game/modules/gui/actionPrompt.lua create mode 100644 sonic-bluestreak.love/game/modules/gui/boxedmenu.lua create mode 100644 sonic-bluestreak.love/game/modules/gui/choiceElem.lua create mode 100644 sonic-bluestreak.love/game/modules/gui/complexhpbar.lua create mode 100644 sonic-bluestreak.love/game/modules/gui/emblem.lua create mode 100644 sonic-bluestreak.love/game/modules/gui/fancymenu.lua delete mode 100644 sonic-bluestreak.love/game/modules/gui/frame.lua create mode 100644 sonic-bluestreak.love/game/modules/gui/gameover.lua create mode 100644 sonic-bluestreak.love/game/modules/gui/menuback.lua create mode 100644 sonic-bluestreak.love/game/modules/gui/overlay.lua create mode 100644 sonic-bluestreak.love/game/modules/gui/simplehpbar.lua delete mode 100644 sonic-bluestreak.love/game/modules/gui/status.lua create mode 100644 sonic-bluestreak.love/game/modules/menus/fancy.lua create mode 100644 sonic-bluestreak.love/game/modules/menus/list.lua create mode 100644 sonic-bluestreak.love/game/modules/menus/parents/menu.lua create mode 100644 sonic-bluestreak.love/game/modules/menus/parents/widget.lua create mode 100644 sonic-bluestreak.love/game/modules/messagequeue/init.lua create mode 100644 sonic-bluestreak.love/game/modules/messagequeue/message.lua delete mode 100644 sonic-bluestreak.love/game/modules/playstyle/assets.lua delete mode 100644 sonic-bluestreak.love/game/modules/playstyle/pause.lua rename sonic-bluestreak.love/game/modules/{playstyle => subgames}/init.lua (62%) create mode 100644 sonic-bluestreak.love/game/modules/subgames/pause.lua rename sonic-bluestreak.love/game/modules/{ => subgames}/world/actors/collisions/fakefloor.lua (92%) rename sonic-bluestreak.love/game/modules/{ => subgames}/world/actors/collisions/floor.lua (91%) rename sonic-bluestreak.love/game/modules/{ => subgames}/world/actors/collisions/invisible.lua (80%) rename sonic-bluestreak.love/game/modules/{ => subgames}/world/actors/collisions/textured.lua (83%) rename sonic-bluestreak.love/game/modules/{ => subgames}/world/actors/collisions/wall.lua (80%) create mode 100644 sonic-bluestreak.love/game/modules/subgames/world/actors/ennemies/motobug.lua rename sonic-bluestreak.love/game/modules/{ => subgames}/world/actors/ennemies/parent.lua (83%) rename sonic-bluestreak.love/game/modules/{ => subgames}/world/actors/init.lua (100%) rename sonic-bluestreak.love/game/modules/{ => subgames}/world/actors/items/collectible.lua (78%) rename sonic-bluestreak.love/game/modules/{ => subgames}/world/actors/items/ring.lua (100%) rename sonic-bluestreak.love/game/modules/{ => subgames}/world/actors/parent.lua (94%) create mode 100644 sonic-bluestreak.love/game/modules/subgames/world/actors/player/init.lua rename sonic-bluestreak.love/game/modules/{ => subgames}/world/actors/player/weapons.lua (82%) rename sonic-bluestreak.love/game/modules/{ => subgames}/world/actors/weapons/parent.lua (76%) rename sonic-bluestreak.love/game/modules/{ => subgames}/world/battle.lua (73%) rename sonic-bluestreak.love/game/modules/{ => subgames}/world/maps/battle.lua (96%) create mode 100644 sonic-bluestreak.love/game/modules/subgames/world/maps/init.lua rename sonic-bluestreak.love/game/modules/{ => subgames}/world/maps/shoot.lua (59%) create mode 100644 sonic-bluestreak.love/game/modules/subgames/world/maps/test.lua rename sonic-bluestreak.love/game/modules/{ => subgames}/world/maps/tools/chunk.lua (97%) rename sonic-bluestreak.love/game/modules/{ => subgames}/world/maps/tools/chunkterrain.lua (100%) rename sonic-bluestreak.love/game/modules/{ => subgames}/world/parent.lua (88%) rename sonic-bluestreak.love/game/modules/{ => subgames}/world/shoot.lua (78%) create mode 100644 sonic-bluestreak.love/game/modules/transitions/eggman.lua create mode 100644 sonic-bluestreak.love/game/modules/transitions/init.lua create mode 100644 sonic-bluestreak.love/game/modules/transitions/sonic.lua create mode 100644 sonic-bluestreak.love/game/modules/transitions/zigzag.lua delete mode 100644 sonic-bluestreak.love/game/modules/tweenmanager/init.lua delete mode 100644 sonic-bluestreak.love/game/modules/tweenmanager/libs/tween.lua delete mode 100644 sonic-bluestreak.love/game/modules/world/actors/ennemies/motobug.lua delete mode 100644 sonic-bluestreak.love/game/modules/world/maps/init.lua delete mode 100644 sonic-bluestreak.love/game/modules/world/maps/test.lua create mode 100644 sonic-bluestreak.love/game/scenes/init.lua delete mode 100644 sonic-bluestreak.love/game/subgame/sonic-boost.lua create mode 100644 sonic-bluestreak.love/game/utils/battle/init.lua create mode 100644 sonic-bluestreak.love/game/utils/characters.lua create mode 100644 sonic-bluestreak.love/game/utils/gizmo/properties.lua rename sonic-bluestreak.love/game/{modules => }/utils/init.lua (100%) diff --git a/sonic-bluestreak.love/assets/subgames.lua b/sonic-bluestreak.love/assets/subgames.lua index 04afc43..2e4224f 100644 --- a/sonic-bluestreak.love/assets/subgames.lua +++ b/sonic-bluestreak.love/assets/subgames.lua @@ -3,7 +3,9 @@ return { {"shadow", "assets/sprites/shadow.png"} }, ["sprites"] = { - {"ring", "assets/sprites/items/ring"} + {"ring", "assets/sprites/items/ring"}, + {"ringtoss", "assets/sprites/items/ringtoss"}, + {"ringweapon", "assets/sprites/items/ringweapon"}, }, ["imagefonts"] = { {"menu", "assets/gui/fonts/SA2font"}, diff --git a/sonic-bluestreak.love/game/abstractmobs/character/datas.lua b/sonic-bluestreak.love/game/abstractmobs/character/datas.lua new file mode 100644 index 0000000..abd7ca4 --- /dev/null +++ b/sonic-bluestreak.love/game/abstractmobs/character/datas.lua @@ -0,0 +1,32 @@ +local CharacterData = Object:extend() + +function CharacterData:getCommonData() + self.data = core.datas:get("characters", self.simplename) + self.name = self.data.name + self.fullname = self.data.fullname + self.turns = self.data.turns +end + +function CharacterData:getWeaknesses() + return self.data.weakTo +end + +function CharacterData:getResistences() + return self.data.resists +end + +function CharacterData:getSkillName(skill) + local skilldata = core.datas:get("skills", skill) + local name = skilldata.fullname + + + if (skilldata.altName ~= nil) then + if (skilldata.altName[self.simplename] ~= nil) then + name = skilldata.altName[self.simplename] + end + end + print(name) + return name +end + +return CharacterData diff --git a/sonic-bluestreak.love/game/abstractmobs/character/equip.lua b/sonic-bluestreak.love/game/abstractmobs/character/equip.lua new file mode 100644 index 0000000..038ca23 --- /dev/null +++ b/sonic-bluestreak.love/game/abstractmobs/character/equip.lua @@ -0,0 +1,60 @@ +local CharacterEquip = Object:extend() + +local categories = {"gloves", "shoes", "accessories"} + +function CharacterEquip:initEquip() + self.equip = {} + if self.data.inventory == nil then + core.debug:warning("character/equip", "Initial equip not set for " .. self.simplename) + for _, category in ipairs(categories) do + self.equip[category] = "" + end + else + for _, category in ipairs(categories) do + self.equip[category] = self.data.inventory[category] or "" + end + end +end + +function CharacterEquip:setEquip(category, name) + if (not utils.string.isEmpty(self.equip[category])) then + game.loot:addItem(category, self.equip[category], 1) + end + self.equip[category] = name + game.loot:removeItem(category, name, 1) + self:updateHPPP() +end + +function CharacterEquip:removeEquip(category) + if (not utils.string.isEmpty(self.equip[category])) then + game.loot:addItem(category, self.equip[category], 1) + self.equip[category] = "" + self:updateHPPP() + end +end + +function CharacterEquip:predictStat(statName, category, name) + return self.stats:predictStat(statName, category, name) +end + +function CharacterEquip:getEquipStats(stat, ignore) + local boost = 0 + local ignore = ignore or "" + for _, category in ipairs(categories) do + if (category ~= ignore) then + boost = boost + self:getEquipStatByType(stat, category) + end + end + return boost +end + +function CharacterEquip:getEquipStatByType(stat, category) + if (not utils.string.isEmpty(self.equip[category])) then + local data = core.datas:get("items", self.equip[category]) + local boost = data.statsBoost[stat] or 0 + return boost + end + return 0 +end + +return CharacterEquip \ No newline at end of file diff --git a/sonic-bluestreak.love/game/abstractmobs/character/health.lua b/sonic-bluestreak.love/game/abstractmobs/character/health.lua new file mode 100644 index 0000000..9bad5f0 --- /dev/null +++ b/sonic-bluestreak.love/game/abstractmobs/character/health.lua @@ -0,0 +1,7 @@ +local CharacterHealth = Object:extend() + +function CharacterHealth:heal() + self:initLife() +end + +return CharacterHealth \ No newline at end of file diff --git a/sonic-bluestreak.love/game/abstractmobs/character/init.lua b/sonic-bluestreak.love/game/abstractmobs/character/init.lua new file mode 100644 index 0000000..082b8fe --- /dev/null +++ b/sonic-bluestreak.love/game/abstractmobs/character/init.lua @@ -0,0 +1,74 @@ +local AbstractMobParent = require "game.abstractmobs.parent" +local AbstractCharacter = AbstractMobParent:extend() + +local CharacterHealth = require "game.abstractmobs.character.health" +local CharacterLevels = require "game.abstractmobs.character.levels" +local CharacterDatas = require "game.abstractmobs.character.datas" +local CharacterEquip = require "game.abstractmobs.character.equip" +AbstractCharacter:implement(CharacterHealth) +AbstractCharacter:implement(CharacterLevels) +AbstractCharacter:implement(CharacterDatas) +AbstractCharacter:implement(CharacterEquip) + +local CharacterStatManager = require "game.abstractmobs.character.statmanager" + +function AbstractCharacter:new(name) + self.simplename = name + AbstractCharacter.super.new(self, {"simplename", "level", "exp", "exp_next", "hp", "pp", "statuts", "equip"}, nil, CharacterStatManager) + self:updateHPPP() +end + +function AbstractCharacter:initBasicElements() + self:getCommonData() + self:initEquip() + self:initLevel() +end + +function AbstractCharacter:updateHPPP() + if (self.hp ~= nil) then + self.hp = math.min(self.hp, self.stats:get(self.stats.HPMAX)) + end + if (self.pp ~= nil) then + self.pp = math.min(self.pp, self.stats:get(self.stats.PPMAX)) + end +end + +function AbstractCharacter:getStat(statName, ignoreEquip) + return self.stats:get(statName, ignoreEquip) +end + +function AbstractCharacter:createSkills() + local learnedlist = {} + + for i, v in ipairs(self.data.skills) do + local tech_name, tech_level, isLearned = v[1], v[2], false + if tech_level <= self.level then + local canLearn = true + for i, learnedSkill in ipairs(learnedlist) do + -- We check if the skill have already been learned, to level-up it + if learnedSkill.name == tech_name then + canLearn = false + learnedSkill.level = learnedSkill.level + 1 + end + end + + if (canLearn) then + local skilldata = {} + skilldata.name = tech_name + skilldata.level = 1 + skilldata.learnedAt = tech_level + + table.insert(learnedlist, skilldata) + end + end + -- On continue ensuite d'itérer dans la liste + end + + return learnedlist +end + +function AbstractCharacter:finishDeserialization() + self.skills = self:createSkills() +end + +return AbstractCharacter diff --git a/sonic-bluestreak.love/game/abstractmobs/character/levels.lua b/sonic-bluestreak.love/game/abstractmobs/character/levels.lua new file mode 100644 index 0000000..2fd49d1 --- /dev/null +++ b/sonic-bluestreak.love/game/abstractmobs/character/levels.lua @@ -0,0 +1,61 @@ +local CharacterLevel = Object:extend() + +local charutils = require "game.utils.characters" +local STATS = require "datas.consts.stats" + +function CharacterLevel:initLevel() + self.level = self.data.startlevel + self.exp = charutils.getExpValue(self.level) + self.exp_next = charutils.getExpValue(self.level + 1) +end + +function CharacterLevel:setLevel(newlevel) + self.level = newlevel + local exp + local exp_min = charutils.getExpValue(self.level) + local exp_max = charutils.getExpValue(self.level + 1) + exp = self.exp + + self.exp = math.max(math.min(exp, exp_max - 1), exp_min) + self.exp_next = exp_max + + self:updateHPPP() + self.skills = self:createSkills() +end + +function CharacterLevel:levelUp() + if (game.difficulty:get("levelUpHeal")) then + self:heal() + end + self:setLevel(self.level + 1) +end + +function CharacterLevel:getLevelStat(statname) + local baseStat = self.data.stats[statname] + if (baseStat == nil) then + error("Stat " .. statname .. " doesn't exist") + else + local stat = 0 + + if (statname == "hpmax") then + stat = charutils.getHPValue(self.level, baseStat) + elseif (statname == "ppmax") then + stat = charutils.getPPValue(self.level, baseStat) + else + stat = charutils.getStatValue(self.level, baseStat) + end + + return stat + end +end + +function CharacterLevel:getComputedStat(statname) + core.debug:warning("CharacterLevel", "Function getComputedStat is deprecated") + return self:getLevelStat(statname) +end + +function CharacterLevel:getStatList() + return STATS.LIST +end + +return CharacterLevel diff --git a/sonic-bluestreak.love/game/abstractmobs/character/statmanager.lua b/sonic-bluestreak.love/game/abstractmobs/character/statmanager.lua new file mode 100644 index 0000000..620c271 --- /dev/null +++ b/sonic-bluestreak.love/game/abstractmobs/character/statmanager.lua @@ -0,0 +1,27 @@ +local StatManager = require "game.abstractmobs.statmanager" +local CharacterStatManager = StatManager:extend() + +function CharacterStatManager:new(owner) + CharacterStatManager.super.new(self, owner) +end + +function CharacterStatManager:computeStat(statname, ignoreEquip) + local stat = self:getBaseStat(statname) + self.owner:getEquipStats(statname, ignoreEquip) + return stat +end + +function CharacterStatManager:predictStat(statname, category, name) + local data = core.datas:get("items", name) + local boost = data.statsBoost[statname] or 0 + return self:computeStat(statname, category) + boost +end + +function CharacterStatManager:getBaseStat(statname) + if (self:isBattleStat(statname)) then + return self:getBattleStat(statname) + else + return self.owner:getLevelStat(statname) + end +end + +return CharacterStatManager \ No newline at end of file diff --git a/sonic-bluestreak.love/game/abstractmobs/ennemy/init.lua b/sonic-bluestreak.love/game/abstractmobs/ennemy/init.lua new file mode 100644 index 0000000..1a71cd8 --- /dev/null +++ b/sonic-bluestreak.love/game/abstractmobs/ennemy/init.lua @@ -0,0 +1,47 @@ +local AbstractMobParent = require "game.abstractmobs.parent" + +local AbstractEnnemy = AbstractMobParent:extend() +local elements = require "datas.gamedata.battles.elements" +local EnnemyStatManager = require "game.abstractmobs.ennemy.statmanager" + +function AbstractEnnemy:new(directory, name) + self.simplename = name + self.directory = directory + AbstractEnnemy.super.new(self, nil, nil, EnnemyStatManager) +end + +function AbstractEnnemy:getWeaknesses() + local elementData = elements[self.data.element] or elements["none"] + return elementData.weakTo +end + +function AbstractEnnemy:getResistences() + local elementData = elements[self.data.element] or elements["none"] + return elementData.resists +end + +function AbstractEnnemy:haveProtecType(protectype) + return utils.table.contain(self.data.protectypes, protectype) +end + +function AbstractEnnemy:getProtecTypes() + return self.data.protectypes +end + +function AbstractEnnemy:initBasicElements() + self.data = core.datas:get("ennemies", self.simplename) + self.name = self.data.name + self.fullname = self.data.fullname + self.turns = self.data.turns +end + +function AbstractEnnemy:createSkills() + return self.data.skills +end + +function AbstractEnnemy:setBonus(pvFactor, statFactor) + self.stats:setBonus(pvFactor, statFactor) + self.hp = self.stats:get(self.stats.HPMAX) +end + +return AbstractEnnemy diff --git a/sonic-bluestreak.love/game/abstractmobs/ennemy/statmanager.lua b/sonic-bluestreak.love/game/abstractmobs/ennemy/statmanager.lua new file mode 100644 index 0000000..fa4a46f --- /dev/null +++ b/sonic-bluestreak.love/game/abstractmobs/ennemy/statmanager.lua @@ -0,0 +1,31 @@ +local StatManager = require "game.abstractmobs.statmanager" +local EnnemyStatManager = StatManager:extend() + +function EnnemyStatManager:new(owner) + EnnemyStatManager.super.new(self, owner, "ENNEMI") + self.pvFactor = 1 + self.statFactor = 1 +end + +function EnnemyStatManager:setBonus(pvFactor, statFactor) + self.pvFactor = pvFactor or 1 + self.statFactor = statFactor or 1 +end + +function EnnemyStatManager:computeStat(statname) + local stat = self.owner.data.stats[statname] + + if (self:isBattleStat(statname)) then + return self:getBattleStat(statname) + end + + if statname == EnnemyStatManager.HPMAX then + return stat * self.pvFactor + elseif (statname ~= EnnemyStatManager.PPMAX) then + return stat * self.statFactor + else + return stat + end +end + +return EnnemyStatManager \ No newline at end of file diff --git a/sonic-bluestreak.love/game/abstractmobs/parent.lua b/sonic-bluestreak.love/game/abstractmobs/parent.lua new file mode 100644 index 0000000..1fb1d04 --- /dev/null +++ b/sonic-bluestreak.love/game/abstractmobs/parent.lua @@ -0,0 +1,179 @@ +local Serializable = require "birb.classes.serializable" +local AbstractMobParent = Serializable:extend() +local StatManager = require "game.abstractmobs.statmanager" + +local statutStatList = require "datas.gamedata.statuses" + +function AbstractMobParent:new(serializeFields, listSerializable, statManager) + local statManager = statManager or StatManager + self:initBasicElements() + + self.stats = statManager(self) + self.skills = self:createSkills() + self.statuts = {} + self:initLife() + AbstractMobParent.super.new(self, serializeFields, listSerializable) +end + +function AbstractMobParent:initBasicElements() + self.name = "PlaceHolder" + self.fullname = "PlaceHolder" + self.turns = 2 +end + +function AbstractMobParent:haveProtecType() + return false +end + +function AbstractMobParent:getProtecTypes() + return {} +end + +function AbstractMobParent:createSkills() + return {} +end + +-- LIFE FUNCTIONS +-- Handle HP and stuff like that + +function AbstractMobParent:initLife() + self.hp = self.stats:get(self.stats.HPMAX) + self.pp = self.stats:get(self.stats.PPMAX) + self.status = 0 +end + +function AbstractMobParent:setHP(newHP, relative) + if (relative) then + self.hp = self.hp + newHP + else + self.hp = newHP + end + self.hp = math.floor(math.max(0, self.hp)) + if (self.hp == 0) then + self:die() + end + self.hp = math.min(self.hp, self.stats:get(self.stats.HPMAX)) +end + +function AbstractMobParent:setPP(newPP, relative) + if (relative) then + self.pp = self.pp + newPP + else + self.pp = newPP + end + self.pp = math.floor(math.max(0, self.pp)) + self.pp = math.min(self.pp, self.stats:get(self.stats.PPMAX)) +end + +function AbstractMobParent:getStats() + return self.stats +end + +-- STATUT HANDLING + +function AbstractMobParent:addStatut(name, duration, source) + local statut = self:getStatutData(name) + local duration = duration or 1 + + if (statut.remove ~= nil) then + duration = - self:removeStatutTurns(statut.remove, duration) + end + + if (duration > 0) then + if (statut.replaceAll == true) then + self:resetStatut() + else + self:removeStatut(name) + end + self.statuts[name] = {} + self.statuts[name].duration = duration + end +end + +function AbstractMobParent:getStatutKey(statutName) + local statut = self:getStatutData(statutName) + local key = "" + if (self.statuts[statutName] ~= nil) then + key = statutName + end + if (statut.alternative ~= nil) then + for _, alternative in ipairs(statut.alternative) do + if (self.statuts[alternative] ~= nil) then + key = alternative + end + end + end + return key +end + +function AbstractMobParent:haveStatuts(statutName) + return (self.statuts[self:getStatutKey(statutName)] ~= nil) +end + +function AbstractMobParent:removeStatut(statutName) + local key = self:getStatutKey(statutName) + if (key ~= nil) then + self.statuts[key] = nil + return true + end + return false +end + +function AbstractMobParent:removeStatutTurns(statutName, turns) + local statut = self:getStatutData(statutName) + if (statut.temporary == false) then + return 0 + end + if (not self:haveStatuts(statutName)) then + return turns + end + local key = self:getStatutKey(statutName) + local relativeTurns = self.statuts[key].duration - turns + + if (relativeTurns <= 0) then + self:removeStatut(statutName) + else + self.statuts[key].duration = relativeTurns + end + + return relativeTurns +end + +function AbstractMobParent:resetStatut() + self.statuts = {} +end + +function AbstractMobParent:die() + self:addStatut("ko") +end + +function AbstractMobParent:isAlive() + return (not self:haveStatuts("ko")) +end + +function AbstractMobParent:removeOneTurnToStatut() + for name, _ in pairs(self.statuts) do + self:removeStatutTurns(name, 1) + end +end + +function AbstractMobParent:getStatutsStat(statName) + local stat = 0 + for statutName, _ in pairs(self.statuts) do + local statut = self:getStatutData(statutName) + if (statut.stats ~= nil) then + for _, statutStat in ipairs(statut.stats) do + if (statutStat[1] == statName) then + stat = stat + statutStat[2] + end + end + end + end + return stat +end + +function AbstractMobParent:getStatutData(statutName) + return statutStatList[statutName] +end + +return AbstractMobParent diff --git a/sonic-bluestreak.love/game/abstractmobs/statmanager.lua b/sonic-bluestreak.love/game/abstractmobs/statmanager.lua new file mode 100644 index 0000000..05f9dc9 --- /dev/null +++ b/sonic-bluestreak.love/game/abstractmobs/statmanager.lua @@ -0,0 +1,36 @@ +local StatManager = Object:extend() +local CONST = require "datas.consts.stats" +StatManager.CONST = CONST + +StatManager.HPMAX = CONST.HPMAX +StatManager.PPMAX = CONST.PPMAX +StatManager.ATTACK = CONST.ATTACK +StatManager.POWER = CONST.POWER +StatManager.DEFENSE = CONST.DEFENSE +StatManager.MIND = CONST.MIND +StatManager.TECHNIC = CONST.TECHNIC +StatManager.SPEED = CONST.SPEED + +function StatManager:new(owner, battleStatType) + local battleStatType = battleStatType or "HERO" + self.owner = owner + self.battleStats = CONST.BATTLESTAT[battleStatType] +end + +function StatManager:get(statname) + return self:computeStat(statname) +end + +function StatManager:computeStat(statname) + return self.list[statname] +end + +function StatManager:isBattleStat(statname) + return utils.table.contain(CONST.BATTLELIST, statname) +end + +function StatManager:getBattleStat(statname) + return self.battleStats[statname] +end + +return StatManager \ No newline at end of file diff --git a/sonic-bluestreak.love/game/battle.lua b/sonic-bluestreak.love/game/battle.lua new file mode 100644 index 0000000..2d54c89 --- /dev/null +++ b/sonic-bluestreak.love/game/battle.lua @@ -0,0 +1,37 @@ +local CoreCBS = Object:extend() + +local defTransitions = require "birb.modules.transitions" +local radTransitions = require "game.modules.transitions" + +local DEFAULTX = 424/2 +local DEFAULTY = 240/2 + +function CoreCBS:new() + self.lastx, self.lasty = DEFAULTX, DEFAULTY +end + +function CoreCBS:startBattle(category, name, x, y) + local data = core.datas:get("battles", name) + self.lastx, self.lasty = x or DEFAULTX, y or DEFAULTY + core.screen:startTransition(radTransitions.eggman, radTransitions.borders, function() scenes.cbs(data) end, x, y) +end + +function CoreCBS:endBattle(isFleeing) + local transitionEnd = radTransitions.sonic + if (isFleeing) then + transitionEnd = defTransitions.circle; + end + core.screen:startTransition(radTransitions.borders, transitionEnd, + function() + if (core.scenemanager:haveStoredScene("afterBattle")) then + core.scenemanager:setStoredScene("afterBattle") + else + scenes.menus.main() + end + end, self.lastx, self.lasty) + self.lastx, self.lasty = DEFAULTX, DEFAULTY +end + + + +return CoreCBS \ No newline at end of file diff --git a/sonic-bluestreak.love/game/characters.lua b/sonic-bluestreak.love/game/characters.lua index b082ee1..9ee8328 100644 --- a/sonic-bluestreak.love/game/characters.lua +++ b/sonic-bluestreak.love/game/characters.lua @@ -22,127 +22,167 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ]] -local CharacterManager = Object:extend() +local Serializable = require "birb.classes.serializable" +local CharacterManager = Serializable:extend() + +local AbstractCharacter = require "game.abstractmobs.character" +local startdata = require "datas.gamedata.startdata" function CharacterManager:new(controller) self.controller = controller self.namelist = require "datas.gamedata.characters" self.list = {} - self.team = require "datas.gamedata.characters.baseteam" + self.team = startdata.baseteam self.active = 1 self:init() + CharacterManager.super.new(self, {"team"}, {"list"}, {list = AbstractCharacter}) end function CharacterManager:init() - for k, v in pairs(self.namelist) do - local dir = "datas/gamedata/characters/" .. v .. "/init.lua" - local fileinfo = love.filesystem.getInfo(dir) - if fileinfo ~= nil then - self:initCharacter(v) + for k, name in pairs(self.namelist) do + if (core.datas:exists("characters", name)) then + self.list[name] = AbstractCharacter(name) end end end -function CharacterManager:getCharacterData(charname) - -- va eprmettre de récupérer les données d'un personnage - local charfolder = "datas.gamedata.characters." .. charname - local character = require(charfolder) - character.stats = require(charfolder .. ".stats") - character.assets = require(charfolder .. ".assets") - character.skills = require(charfolder .. ".skills") - character.actions = require(charfolder .. ".actions") +-- WRAPPER FUNCTIONS +-- Simple wrappers around characters functions - return character +function CharacterManager:setLevel(name, newlevel) + self.list[name]:setLevel(newlevel) end -function CharacterManager:initCharacter(id) - local character = self:getCharacterData(id) - - local startlevel = character.stats.startlevel - character.stats.level = startlevel - character.stats.exp = self:getExpValue(startlevel) - character.stats.exp_next = self:getExpValue(startlevel + 1) - - character.stats.hp = character.stats.hpmax - character.stats.pp = 100 - character.stats.status = 0 - - self.list[id] = character +function CharacterManager:levelUp(name) + self.list[name]:levelUp() end -function CharacterManager:getExpValue(level) - return math.floor( ( 4 * ( level ^ 3 ) ) / 5 ) +function CharacterManager:heal(name) + self.list[name]:heal() end -function CharacterManager:setLevel(id, newlevel) - self.list[id].stats.level = newlevel - local stats = self.list[id].stats - local exp, exp_next, exp_current - exp = self:getExpValue(stats.level) - exp_next = self:getExpValue(stats.level + 1) - exp_current = self.list[id].stats.exp - - self.list[id].stats.exp = math.max(math.min(exp_current, exp_next - 1), exp) - self.list[id].stats.exp_next = exp_next -end - -function CharacterManager:levelUp(id) - self:setLevel(id, self.list[id].stats.level + 1) -end - -function CharacterManager:getStatValue(level, base) - return math.floor( (((base * 2) * level)/100) ) + 5 -end - -function CharacterManager:getHPValue(level, base) - return math.floor( (((base * 2.7) * level)/100) ) + 15 + level -end +-- DATA FUNCTIONS +-- function to handle saving function CharacterManager:getData() local data = {} - data.list = self.list data.team = self.team + data.list = {} + for name, character in pairs(self.list) do + data.list[name] = character:getData() + end return data end function CharacterManager:setData(data) local data = data - self.list = data.list self.team = data.team + for name, charData in pairs(data.list) do + self.list[name]:setData(charData) + end end -function CharacterManager:heal(id) - self.list[id].stats.hp = self.list[id].stats.hpmax - self.list[id].stats.pp = 100 - self.list[id].stats.status = 0 -end +-- TEAM FUNCTIONS +-- Team handling and management -function CharacterManager:addToTeam(id) - self:heal(id) - table.insert(self.team, id) +function CharacterManager:addToTeam(name) + self:heal(name) + if (#self.team < 4) then + table.insert(self.team, name) + end end function CharacterManager:removeToTeam(teamid) - self.team[teamid] = "" + if (#self.team > 1) then + table.remove(self.team, teamid) + end +end + +function CharacterManager:getPositionInTeam(charName) + local charId = -1 + for i,name in ipairs(self.team) do + if (name == charName) then + charId = i + end + end + return charId +end + +function CharacterManager:addOrRemoveToTeam(charName) + local charId = self:getPositionInTeam(charName) + if (charId == -1) then + self:addToTeam(charName) + else + self:removeToTeam(charId) + if (charId < self.active) then + self.active = self.active - 1 + end + end + self:fixActiveCharacter() +end + +function CharacterManager:setActiveCharacter(direction) + local direction = direction or 1 + local count = direction + self.active = self.active + utils.math.sign(direction) + if (self.active > #self.team) then + self.active = 1 + end + if (self.active < 1) then + self.active = #self.team + end + if (self.list[self.team[self.active]].hp <= 0) and not game.difficulty:get("playerKoChar") then + count = count + self:setActiveCharacter(direction) + end + return count +end + +function CharacterManager:fixActiveCharacter() + if (self.active < 1) then + self.active = 1 + elseif (self.active > #self.team) then + self.active = #self.team + end end function CharacterManager:getActiveCharacter() return self.team[self.active] end +function CharacterManager:getActiveCharacterData() + return self.list[self.team[self.active]] +end + +-- SCENES FUNCTIONS +-- Handle damages from the scenes + +function CharacterManager:sendDamageFromMap(name, damageRatio) + local character = self.list[name] + if (character.hp > 0) then + local newHP = math.floor(character.hp - (character.stats:get(character.stats.HPMAX) * damageRatio)) + if (not game.difficulty:get("hazardMakesKo")) then + newHP = math.max(1, newHP) + end + self.list[name]:setHP(newHP, false) + end +end + +function CharacterManager:loadSprite(assets, name) + assets:addSprite(name, "datas/gamedata/characters/" .. name .. "/sprites") +end + -- DEBUG FUNCTIONS function CharacterManager:printCharacter(id) local character = self.list[id] - local stats = character.stats - print(id .. ". " .. character.fullname) - print("Lvl " .. character.stats.level .. " (" .. stats.exp .. "/" .. stats.exp_next .. " exp)") + core.debug:print(id .. ". " .. character.fullname) + core.debug:print("Lvl " .. character.level .. " (" .. character.exp .. "/" .. character.exp_next .. " exp)") end function CharacterManager:printTeam() for i,v in ipairs(self.team) do self:printCharacter(v) - print("-----") + core.debug:print("-----") end end diff --git a/sonic-bluestreak.love/game/difficulty.lua b/sonic-bluestreak.love/game/difficulty.lua new file mode 100644 index 0000000..f98b386 --- /dev/null +++ b/sonic-bluestreak.love/game/difficulty.lua @@ -0,0 +1,23 @@ +local Serializable = require "birb.classes.serializable" +local Difficulty = Serializable:extend() + +function Difficulty:new() + self.toggles = {} + self.toggles.hazardMakesKo = false + self.toggles.playerKoChar = true + self.toggles.easierBattles = false + self.toggles.checkPointRegen = false + self.toggles.levelUpHeal = false + self.toggles.allDamage = true + Difficulty.super.new(self, {"toggles"}) +end + +function Difficulty:toggle(toggleName) + self.toggles[toggleName] = (self.toggles[toggleName] == false) +end + +function Difficulty:get(toggleName) + return self.toggles[toggleName] +end + +return Difficulty \ No newline at end of file diff --git a/sonic-bluestreak.love/game/ennemies.lua b/sonic-bluestreak.love/game/ennemies.lua index 60336f1..f062cf3 100644 --- a/sonic-bluestreak.love/game/ennemies.lua +++ b/sonic-bluestreak.love/game/ennemies.lua @@ -1,15 +1,13 @@ local EnnemyManager = Object:extend() +local AbstractEnnemy = require "game.abstractmobs.ennemy" + function EnnemyManager:new(controller) self.controller = controller end -function EnnemyManager:getEnnemyData(ennemy) - local data = require("datas.gamedata.ennemies." .. ennemy) - data.skills = require("datas.gamedata.ennemies." .. ennemy .. ".skills") - data.stats = require("datas.gamedata.ennemies." .. ennemy .. ".stats") - - return data +function EnnemyManager:getEnnemyData(category, ennemy) + return AbstractEnnemy(category, ennemy) end return EnnemyManager diff --git a/sonic-bluestreak.love/game/events/conditions.lua b/sonic-bluestreak.love/game/events/conditions.lua new file mode 100644 index 0000000..d479a24 --- /dev/null +++ b/sonic-bluestreak.love/game/events/conditions.lua @@ -0,0 +1,12 @@ +local Conditions = {} + +function Conditions.haveMoney(cond, predicate, asker) + return predicate.utils.testVariables(game.loot.rings , cond[2], cond[3]) +end + +function Conditions.default(cond, predicate, asker) + local flag = predicate.utils.merge(cond) + return asker:haveFlag(flag) +end + +return Conditions \ No newline at end of file diff --git a/sonic-bluestreak.love/game/events/event/dialogbox.lua b/sonic-bluestreak.love/game/events/event/dialogbox.lua new file mode 100644 index 0000000..44802be --- /dev/null +++ b/sonic-bluestreak.love/game/events/event/dialogbox.lua @@ -0,0 +1,67 @@ +local StepParent = require "game.events.event.parent" +local DialogBox = StepParent:extend() + +local Talkies = require('birb.libs.talkies') + +function DialogBox:new(controller, args) + DialogBox.super.new(self, controller, args) + Talkies.font = love.graphics.newFont("assets/gui/fonts/PixelOperator.ttf", 16) + Talkies.talkSound = love.audio.newSource("assets/sfx/talk.wav", "static") + Talkies.optionOnSelectSound = love.audio.newSource("assets/sfx/menus/select.wav", "static") + Talkies.optionSwitchSound = love.audio.newSource("assets/sfx/menus/beep.wav", "static") +end + +function DialogBox:start() + local args = self:addOptions() + + if (args == nil) then + Talkies.say(self.arguments.title, self.arguments.message) + else + Talkies.say(self.arguments.title, self.arguments.message, args) + end +end + +function DialogBox:addOptions() + local args = {} + args.options = {} + local haveAddedSomething = false + if (self.arguments.option1 ~= nil) then + table.insert(args.options, {self.arguments.option1, function() self:setOption(1) end}) + haveAddedSomething = true + end + if (self.arguments.option2 ~= nil) then + table.insert(args.options, {self.arguments.option2, function() self:setOption(2) end}) + haveAddedSomething = true + end + if (self.arguments.option3 ~= nil) then + table.insert(args.options, {self.arguments.option3, function() self:setOption(3) end}) + haveAddedSomething = true + end + if (haveAddedSomething) then + return args + end +end + +function DialogBox:setOption(num) + self.events:addFlag(self.arguments.flag, num) + self:finish() +end + +function DialogBox:update(dt) + Talkies.update(dt) + + if (not Talkies.isOpen()) then + self:finish() + end + local keys = self.events.scene.sources[1].keys + if (keys["up"].isPressed) then Talkies.prevOption(); + elseif (keys["down"].isPressed) then Talkies.nextOption(); + elseif (keys["A"].isPressed) then Talkies.onAction(); + end +end + +function DialogBox:draw() + Talkies.draw() +end + +return DialogBox; diff --git a/sonic-bluestreak.love/game/events/event/getItems.lua b/sonic-bluestreak.love/game/events/event/getItems.lua new file mode 100644 index 0000000..36bd518 --- /dev/null +++ b/sonic-bluestreak.love/game/events/event/getItems.lua @@ -0,0 +1,16 @@ +local StepParent = require "game.events.event.parent" +local SimpleMessageStep = StepParent:extend() + +function SimpleMessageStep:new(controller, args) + SimpleMessageStep.super.new(self, controller, args) +end + +function SimpleMessageStep:start() + game.loot:addItem(self.arguments.type, self.arguments.item, self.arguments.number) +end + +function SimpleMessageStep:update(dt) + self:finish() +end + +return SimpleMessageStep; diff --git a/sonic-bluestreak.love/game/events/event/getRings.lua b/sonic-bluestreak.love/game/events/event/getRings.lua new file mode 100644 index 0000000..f881b6a --- /dev/null +++ b/sonic-bluestreak.love/game/events/event/getRings.lua @@ -0,0 +1,16 @@ +local StepParent = require "game.events.event.parent" +local SimpleMessageStep = StepParent:extend() + +function SimpleMessageStep:new(controller, args) + SimpleMessageStep.super.new(self, controller, args) +end + +function SimpleMessageStep:start() + game.loot.rings = game.loot.rings + self.arguments.number +end + +function SimpleMessageStep:update(dt) + self:finish() +end + +return SimpleMessageStep; diff --git a/sonic-bluestreak.love/game/events/event/init.lua b/sonic-bluestreak.love/game/events/event/init.lua new file mode 100644 index 0000000..15afa66 --- /dev/null +++ b/sonic-bluestreak.love/game/events/event/init.lua @@ -0,0 +1,11 @@ +return { + ["wait"] = require("game.events.event.wait"), + ["simpleMessage"] = require("game.events.event.simpleMessage"), + ["dialogBox"] = require("game.events.event.dialogbox"), + ["optionBox"] = require("game.events.event.dialogbox"), + ["playSFX"] = require("game.events.event.playSFX"), + ["getRings"] = require("game.events.event.getRings"), + ["getItems"] = require("game.events.event.getItems"), + ["teleport"] = require("game.events.event.teleport"), + ["showGFX"] = require("game.events.event.showGFX") +} \ No newline at end of file diff --git a/sonic-bluestreak.love/game/events/event/parent.lua b/sonic-bluestreak.love/game/events/event/parent.lua new file mode 100644 index 0000000..725e2f5 --- /dev/null +++ b/sonic-bluestreak.love/game/events/event/parent.lua @@ -0,0 +1,26 @@ +local StepParent = Object:extend() + +function StepParent:new(eventSystem, arguments) + self.events = eventSystem + self.arguments = arguments + self.isStarted = false +end + +function StepParent:updateStep(dt) + if (not self.isStarted) then + self:start() + self.isStarted = true + else + self:update(dt) + end +end + +function StepParent:finish() + self.events:endStep() +end + +function StepParent:draw() + +end + +return StepParent \ No newline at end of file diff --git a/sonic-bluestreak.love/game/events/event/playSFX.lua b/sonic-bluestreak.love/game/events/event/playSFX.lua new file mode 100644 index 0000000..a5f7785 --- /dev/null +++ b/sonic-bluestreak.love/game/events/event/playSFX.lua @@ -0,0 +1,16 @@ +local StepParent = require "game.events.event.parent" +local SimpleMessageStep = StepParent:extend() + +function SimpleMessageStep:new(controller, args) + SimpleMessageStep.super.new(self, controller, args) +end + +function SimpleMessageStep:start() + self.events.scene.assets.sfx[self.arguments.sfx]:play() +end + +function SimpleMessageStep:update(dt) + self:finish() +end + +return SimpleMessageStep; diff --git a/sonic-bluestreak.love/game/events/event/showGFX.lua b/sonic-bluestreak.love/game/events/event/showGFX.lua new file mode 100644 index 0000000..2e83cbc --- /dev/null +++ b/sonic-bluestreak.love/game/events/event/showGFX.lua @@ -0,0 +1,16 @@ +local StepParent = require "game.events.event.parent" +local SimpleMessageStep = StepParent:extend() + +function SimpleMessageStep:new(controller, args) + SimpleMessageStep.super.new(self, controller, args) +end + +function SimpleMessageStep:start() + self.events.scene.world.obj.GFX(self.events.scene.world, self.arguments.x, self.arguments.y, self.arguments.spritename) +end + +function SimpleMessageStep:update(dt) + self:finish() +end + +return SimpleMessageStep; diff --git a/sonic-bluestreak.love/game/events/event/simpleMessage.lua b/sonic-bluestreak.love/game/events/event/simpleMessage.lua new file mode 100644 index 0000000..9118cc8 --- /dev/null +++ b/sonic-bluestreak.love/game/events/event/simpleMessage.lua @@ -0,0 +1,16 @@ +local StepParent = require "game.events.event.parent" +local SimpleMessageStep = StepParent:extend() + +function SimpleMessageStep:new(controller, args) + SimpleMessageStep.super.new(self, controller, args) +end + +function SimpleMessageStep:start() + self.events.scene:showMessage(self.arguments.message) +end + +function SimpleMessageStep:update(dt) + self:finish() +end + +return SimpleMessageStep; diff --git a/sonic-bluestreak.love/game/events/event/teleport.lua b/sonic-bluestreak.love/game/events/event/teleport.lua new file mode 100644 index 0000000..2af3982 --- /dev/null +++ b/sonic-bluestreak.love/game/events/event/teleport.lua @@ -0,0 +1,23 @@ +local StepParent = require "game.events.event.parent" +local SimpleMessageStep = StepParent:extend() +local defTransitions = require "birb.modules.transitions" + +function SimpleMessageStep:new(controller, args) + SimpleMessageStep.super.new(self, controller, args) +end + +function SimpleMessageStep:start() + local charDir = self.arguments.charDir + if (charDir == "default") then + charDir = self.events.scene.world.players[1].actor.charDir or "down" + end + core.screen:startTransition(defTransitions.default, defTransitions.default, + function() self.events.scene.world:teleport(self.arguments.area, self.arguments.x, self.arguments.y, charDir) end, + 0, 0) +end + +function SimpleMessageStep:update(dt) + self:finish() +end + +return SimpleMessageStep; diff --git a/sonic-bluestreak.love/game/events/event/wait.lua b/sonic-bluestreak.love/game/events/event/wait.lua new file mode 100644 index 0000000..d81162e --- /dev/null +++ b/sonic-bluestreak.love/game/events/event/wait.lua @@ -0,0 +1,19 @@ +local StepParent = require "game.events.event.parent" +local WaitStep = StepParent:extend() + +function WaitStep:new(controller, args) + WaitStep.super.new(self, controller, args) +end + +function WaitStep:start() + self.timer = 0 +end + +function WaitStep:update(dt) + self.timer = self.timer + dt + if (self.timer > self.arguments.duration) then + self:finish() + end +end + +return WaitStep; diff --git a/sonic-bluestreak.love/game/events/init.lua b/sonic-bluestreak.love/game/events/init.lua new file mode 100644 index 0000000..af3530a --- /dev/null +++ b/sonic-bluestreak.love/game/events/init.lua @@ -0,0 +1,101 @@ +local EventManager = Object:extend() + +local stepObjectList = require "game.events.event" +local Conditions = require "game.events.conditions" + +local Predicates = require "birb.classes.predicate" + +function EventManager:new(scene) + self.scene = scene + self.world = scene.world + + self.isStarted = false + self.currentStepId = 0 + self.currentStep = nil + self.stepList = {} + self.flags = {} +end + +function EventManager:startEvent(owner, stepList) + self.stepList = stepList + self.flags = {} + self.owner = owner + self.isStarted = true + self.currentStepId = 0 + self.currentStep = nil + self.scene:startEvent() +end + +function EventManager:addFlag(flagname, flagcontent) + if (flagcontent == true) then + flagcontent = "V" + end + if (flagcontent == false) then + flagcontent = "F" + end + local flag = flagname .. ":" .. flagcontent + table.insert(self.flags, flag) +end + +function EventManager:testCondition(condition) + local predicate = Predicates.createPredicate(condition, Conditions, self) + return predicate:solve() +end + +function EventManager:haveFlag(flagToTest) + if (flagToTest == nil or flagToTest == "") then + return true + end + return utils.table.contain(self.flags, flagToTest) +end + +function EventManager:update(dt) + if (self.isStarted) then + if (self.currentStep ~= nil) then + self.currentStep:updateStep(dt) + else + self:switchStep() + end + end +end + +function EventManager:switchStep() + if self:haveNextStep() then + self.currentStepId = self.currentStepId + 1 + local stepData = core.datas:parse("eventstep", self.stepList[self.currentStepId]) + core.debug:print("event", "Starting step " .. stepData.name) + if (not self:testCondition(stepData.condition)) then + self:switchStep() + else + if (stepObjectList[stepData.name] ~= nil) then + self.currentStep = stepObjectList[stepData.name](self, stepData.arguments) + end + end + else + self:endEvent() + end +end + +function EventManager:endStep() + self.currentStep = nil +end + +function EventManager:endEvent() + core.debug:print("event", "Ending event, giving back controle") + self.scene:endEvent() + self.isStarted = false +end + +function EventManager:haveNextStep() + return ((self.currentStepId + 1) <= #self.stepList) +end + +function EventManager:draw() + if (self.isStarted) then + if (self.currentStep ~= nil) then + self.currentStep:draw() + end + end +end + +return EventManager diff --git a/sonic-bluestreak.love/game/init.lua b/sonic-bluestreak.love/game/init.lua index ad712ff..b25d717 100644 --- a/sonic-bluestreak.love/game/init.lua +++ b/sonic-bluestreak.love/game/init.lua @@ -23,79 +23,119 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ]] -local Game = Object:extend() +local Serializer = require "birb.classes.serializable.serializer" + +local Game = Serializer:extend() local Characters = require "game.characters" local Ennemies = require "game.ennemies" +local Loot = require "game.loot" +local CBSCore = require "game.battle" +local Difficulty = require "game.difficulty" +local Metadata = require "game.metadata" -local binser = require "core.modules.gamesystem.libs.binser" +local startdata = require "datas.gamedata.startdata" -Game.utils = require "game.modules.utils" +Game.utils = require "game.utils" Game.gui = require "game.modules.gui" +local VAR_TO_SERIALIZE = { + "gametime", + "destroyedGizmo", + "variables", + "flags", + "position", + "actions", + "characters", + "loot", + "difficulty" +} + function Game:new() self.slot = -1 + self.slotNumber = 3 + self.version = core.conf.gameversion or "N/A" + self:reset() + self.metadata = Metadata(self) + Game.super.new(self, VAR_TO_SERIALIZE) +end + +function Game:initPosition() + self.position = {} + self.position.x = startdata.position.x + self.position.y = startdata.position.y + self.position.area = startdata.position.area +end + +function Game:getMetadataFile(absolute) + local dir = "" + if absolute then + dir = love.filesystem.getSaveDirectory() .. "/" + if not utils.filesystem.exists(dir) then + love.filesystem.createDirectory( "" ) + end + end + + local filepath = dir .. "metadata.save" + + return filepath +end + +function Game:getMetadata() + return self.metadata:get() +end + +function Game:reset() self.gametime = 0 self.characters = Characters(self) self.ennemies = Ennemies(self) + self.loot = Loot(self) + self.cbs = CBSCore(self) + self.difficulty = Difficulty(self) + + self:initPosition() + + self.flags = {} + self.destroyedGizmo = {} + self.variables = {} + self.completion = 0 + self.mapName = "" + self.actions = startdata.actions end -function Game:setData(data) - local data = data - self.gametime = data.gametime - self.characters:setData(data.characters) -end - -function Game:getData() - local data = {} - data.gametime = self.gametime - data.characters = self.characters:getData() - - return data +function Game:reload() + self:read(self.slot) end function Game:read(save_id) self.slot = save_id if (self.slot > 0) then - filepath = self:getSaveFile(self.slot, true) - if love.filesystem.exists("save" .. self.slot .. ".save") then - local loadedDatas = binser.readFile(filepath) - - self:setData(loadedDatas[1]) - - end + self:deserialize(self:getSaveName()) end end -function Game:write(save_id) +function Game:deleteCurrentSave() if (self.slot > 0) then - local data = self:getData() - - filepath = self:getSaveFile(self.slot, true) - binser.writeFile(filepath, data) + self:delete(self:getSaveName()) + self.metadata:remove(self.slot) end end -function Game:getSaveFile(saveslot, absolute) - local dir = "" - if absolute then - dir = love.filesystem.getSaveDirectory() .. "/" - if not love.filesystem.exists(dir) then - love.filesystem.createDirectory( "" ) - end +function Game:write() + if (self.slot > 0) then + self:serialize(self:getSaveName()) + self.metadata:update() end +end - local filepath = dir .. "save" .. saveslot .. ".save" - - return filepath +function Game:getSaveName(saveslot) + local saveslot = saveslot or self.slot + return "save" .. saveslot .. ".save" end function Game:resetSaves() - for i=1, 3 do - filepath = self:getSaveFile(i, true) - if love.filesystem.exists("save" .. i .. ".save") then - love.filesystem.remove( "save" .. i .. ".save" ) - end + for i=1, self.slotNumber do + self:delete(self:getSaveName(i)) end end @@ -104,46 +144,15 @@ function Game:update(dt) end function Game:getTime() - local time = self.gametime - local hours, minute, seconds - seconds = math.floor(self.gametime) - minutes = math.floor(seconds / 60) - hours = math.floor(minutes / 60) - seconds = seconds % 60 - minutes = minutes % 60 - hours = hours - - return seconds, minutes, hours + return utils.time.getFields(self.gametime) end -function Game:getTimeString() - local string - local seconds, minutes, hours = self:getTime() - local stringSeconds, stringMinutes, stringHours - if (seconds <= 9) then - stringSeconds = 0 .. seconds - else - stringSeconds = seconds - end - - if (minutes <= 9) then - stringMinutes = 0 .. minutes - else - stringMinutes = minutes - end - - if (hours <= 9) then - stringHours = 0 .. hours - else - stringHours = hours - end - - string = stringHours .. ":" .. stringMinutes .. ":" .. stringSeconds - return string +function Game:getTimeString() + return utils.time.toString(self.gametime) end function Game:printTime() - print(self:getTimeString()) + core.debug:print(self:getTimeString()) end return Game diff --git a/sonic-bluestreak.love/game/loot/effectManager.lua b/sonic-bluestreak.love/game/loot/effectManager.lua new file mode 100644 index 0000000..ca73f56 --- /dev/null +++ b/sonic-bluestreak.love/game/loot/effectManager.lua @@ -0,0 +1,55 @@ +local EffectManager = Object:extend() + +local effectList = require "game.loot.effects" + +function EffectManager:new() + self.itemdata = nil; +end + +function EffectManager:getItemData(category, item) + self.itemdata = core.datas:get("items", item) +end + +function EffectManager:applyEffects(character) + for _, effect in ipairs(self.itemdata.effects) do + local effectInstance = self:getEffectObject(effect, character, self.itemdata.duration) + effectInstance:applyEffect() + end +end + +function EffectManager:applyEffectsBattle(battleTarget) + local character = battleTarget.abstract + for _, effect in ipairs(self.itemdata.effects) do + local effectInstance = self:getEffectObject(effect, character, self.itemdata.duration) + effectInstance:applyEffect() + effectInstance:battleCallback(battleTarget) + end +end + +function EffectManager:getEffectStrings(character) + local returnString = "No Effect"; + if (#self.itemdata.effects >= 1) then + local effectInstance = self:getEffectObject(self.itemdata.effects[1], character, self.itemdata.duration) + if (effectInstance ~= nil) then + returnString = effectInstance:getText() .. "\n" + end + end + if (#self.itemdata.effects >= 2) then + local effectInstance = self:getEffectObject(self.itemdata.effects[2], character, self.itemdata.duration) + if (effectInstance ~= nil) then + returnString = returnString .. effectInstance:getText() + end + end + return returnString +end + +function EffectManager:getEffectObject(rawEffectData, character, duration) + local effect = core.datas:parse("itemeffects", rawEffectData) + if (effectList[effect.type] ~= nil) then + return effectList[effect.type](effect, character, duration) + else + return nil + end +end + +return EffectManager diff --git a/sonic-bluestreak.love/game/loot/effects/blockstatus.lua b/sonic-bluestreak.love/game/loot/effects/blockstatus.lua new file mode 100644 index 0000000..0248224 --- /dev/null +++ b/sonic-bluestreak.love/game/loot/effects/blockstatus.lua @@ -0,0 +1,17 @@ +local ParentEffect = require "game.loot.effects.parent" +local BlockStatusEffect = ParentEffect:extend() + +function BlockStatusEffect:new(effect, character) + self.effect = effect + self.character = character +end + +function BlockStatusEffect:applyEffect() + +end + +function BlockStatusEffect:getText() + return "Block " .. self.effect.blockWhat .. " " .. "effects" +end + +return BlockStatusEffect \ No newline at end of file diff --git a/sonic-bluestreak.love/game/loot/effects/heal.lua b/sonic-bluestreak.love/game/loot/effects/heal.lua new file mode 100644 index 0000000..ed1aca4 --- /dev/null +++ b/sonic-bluestreak.love/game/loot/effects/heal.lua @@ -0,0 +1,79 @@ +local ParentEffect = require "game.loot.effects.parent" +local HealEffect = ParentEffect:extend() + +function HealEffect:new(effect, character) + self.effect = effect + self.character = character + self.recovered = 0 +end + +function HealEffect:applyEffect() + self:autosetHealFactor() + self:heal(self.recovered) +end + +function HealEffect:autosetHealFactor() + local recovered = 0 + local max = self:getMaxValue() + if (self.character:isAlive()) then + if (self.effect.computationMode == "percent") then + recovered = max * (self.effect.value/100) + else + recovered = self.effect.value + end + recovered = math.min(recovered, max - self:getCurrentValue()) + end + self.recovered = recovered +end + +function HealEffect:getCurrentValue() + if (self.effect.healType == "hp") then + return self.character.hp + elseif (self.effect.healType == "mp") then + return self.character.pp + end +end + +function HealEffect:getMaxValue() + local stats = self.character.stats + if (self.effect.healType == "hp") then + return stats:get(stats.HPMAX) + elseif (self.effect.healType == "mp") then + return stats:get(stats.PPMAX) + end +end + +function HealEffect:heal(value) + if (self.effect.healType == "hp") then + self.character:setHP(value, true) + elseif (self.effect.healType == "mp") then + self.character:setPP(value, true) + end +end + +function HealEffect:battleCallback(fighter) + if (self.effect.healType == "hp") then + fighter.actor:setDamageNumber(self.recovered) + fighter:updateHP() + elseif (self.effect.healType == "mp") then + fighter.actor:setDamageNumber(self.recovered, true) + fighter:updatePP() + end +end + +function HealEffect:getText() + local num = self.effect.value + if (self.effect.computationMode == "percent") then + num = num .. "%" + end + local type = "" + if (self.effect.healType == "hp") then + type = "HP" + end + if (self.effect.healType == "mp") then + type = "MP" + end + return "Heal " .. num .. " " .. type; +end + +return HealEffect \ No newline at end of file diff --git a/sonic-bluestreak.love/game/loot/effects/init.lua b/sonic-bluestreak.love/game/loot/effects/init.lua new file mode 100644 index 0000000..177e9b7 --- /dev/null +++ b/sonic-bluestreak.love/game/loot/effects/init.lua @@ -0,0 +1,6 @@ +return { + heal = require "game.loot.effects.heal", + setStatus = require "game.loot.effects.setstatus", + protectElement = require "game.loot.effects.protectelem", + blockStatus = require "game.loot.effects.blockstatus" +} \ No newline at end of file diff --git a/sonic-bluestreak.love/game/loot/effects/parent.lua b/sonic-bluestreak.love/game/loot/effects/parent.lua new file mode 100644 index 0000000..ef5045e --- /dev/null +++ b/sonic-bluestreak.love/game/loot/effects/parent.lua @@ -0,0 +1,21 @@ +local EffectParent = Object:extend() + +function EffectParent:new(effect, character, duration) + self.effect = effect + self.character = character + self.duration = duration +end + +function EffectParent:applyEffect() + +end + +function EffectParent:getText() + return "No effect" +end + +function EffectParent:battleCallback(fighter) + +end + +return EffectParent diff --git a/sonic-bluestreak.love/game/loot/effects/protectelem.lua b/sonic-bluestreak.love/game/loot/effects/protectelem.lua new file mode 100644 index 0000000..f509c7a --- /dev/null +++ b/sonic-bluestreak.love/game/loot/effects/protectelem.lua @@ -0,0 +1,19 @@ +local ParentEffect = require "game.loot.effects.parent" +local ProtectElemEffect = ParentEffect:extend() + +function ProtectElemEffect:new(effect, character) + self.effect = effect + self.character = character +end + +function ProtectElemEffect:applyEffect() + +end + +function ProtectElemEffect:getText() + local returnString = "Protect from " .. self.effect.element + + return returnString +end + +return ProtectElemEffect \ No newline at end of file diff --git a/sonic-bluestreak.love/game/loot/effects/setstatus.lua b/sonic-bluestreak.love/game/loot/effects/setstatus.lua new file mode 100644 index 0000000..b271205 --- /dev/null +++ b/sonic-bluestreak.love/game/loot/effects/setstatus.lua @@ -0,0 +1,43 @@ +local ParentEffect = require "game.loot.effects.parent" +local StatusEffect = ParentEffect:extend() + +function StatusEffect:new(effect, character, duration) + self.effect = effect + self.character = character + self.duration = duration or -1 +end + +function StatusEffect:applyEffect() + if (self.effect.set) then + self:addStatut() + else + self:removeStatut() + end +end + +function StatusEffect:addStatut() + self.character:addStatut(self.effect.status, self.duration) +end + +function StatusEffect:removeStatut() + self.character:removeStatut(self.effect.status) +end + +function StatusEffect:getText() + local returnString = "" + if (self.effect.set) then + returnString = returnString .. "Give " + else + returnString = returnString .. "Remove " + end + + if (self.effect.status == "allNegative") then + returnString = returnString .. "all negative effects" + else + returnString = returnString .. self.effect.status .. " " .. "effect" + end + + return returnString +end + +return StatusEffect \ No newline at end of file diff --git a/sonic-bluestreak.love/game/loot/init.lua b/sonic-bluestreak.love/game/loot/init.lua new file mode 100644 index 0000000..f914b81 --- /dev/null +++ b/sonic-bluestreak.love/game/loot/init.lua @@ -0,0 +1,67 @@ +local Serializable = require "birb.classes.serializable" +local LootManager = Serializable:extend() +local Pocket = require "game.loot.pocket" +local EffectManager = require "game.loot.effectManager" + +function LootManager:new(controller) + self.controller = controller + self.rings = 0 + self.inventory = {} + self.pocketIndex = {} + self.effects = EffectManager() + + self:generatePockets() + LootManager.super.new(self, {}, {"inventory"}) +end + +function LootManager:generatePockets() + local structure = require "datas.gamedata.items" + for i,pocketdata in ipairs(structure) do + local pocket = Pocket(pocketdata) + self.pocketIndex[pocketdata.name] = i + table.insert(self.inventory, pocket) + end +end + +function LootManager:getPocketIdByName(name) + return self.pocketIndex[name] +end + +function LootManager:getPocketById(id) + return self.inventory[id] +end + +function LootManager:getPocketByName(name) + return self.inventory[self.pocketIndex[name]] +end + +function LootManager:addItem(type, item, number) + local pocket = self:getPocketByName(type) + if (core.datas:exists("items", item)) then + pocket:addItem(item, number) + end +end + +function LootManager:removeItem(type, item, number) + local pocket = self:getPocketByName(type) + if (core.datas:exists("items", item)) then + pocket:removeItem(item, number) + end +end + +function LootManager:getItemNumber(type, item) + local pocket = self:getPocketByName(type) + return pocket:getItemNumber(item) +end + +function LootManager:applyItemEffect(category, item, target) + self.effects:getItemData(category, item) + self.effects:applyItemEffect(target) +end + +function LootManager:getEffectStrings(category, item) + self.effects:getItemData(category, item) + return self.effects:getEffectStrings(nil) +end + +return LootManager diff --git a/sonic-bluestreak.love/game/loot/pocket.lua b/sonic-bluestreak.love/game/loot/pocket.lua new file mode 100644 index 0000000..0dc0cb6 --- /dev/null +++ b/sonic-bluestreak.love/game/loot/pocket.lua @@ -0,0 +1,62 @@ +local Serializable = require "birb.classes.serializable" +local Pocket = Serializable:extend() + +function Pocket:new(pocketdata) + self.name = pocketdata.name + self.fullname = pocketdata.fullname + self.inBattle = pocketdata.inBattle + self.description = pocketdata.description + self.isEquipement = pocketdata.isEquipement + self.list = {} + Pocket.super.new(self, {"list"}) +end + +function Pocket:addItem(item, number) + local success = false + + for i,itemData in ipairs(self.list) do + if (itemData.name == item) then + itemData.number = itemData.number + number + success = true + end + end + + if (not success) then + local itemData = {} + itemData.name = item + itemData.number = number + table.insert(self.list, itemData) + end +end + +function Pocket:removeItem(item, number) + for i,itemData in ipairs(self.list) do + if (itemData.name == item) then + if (itemData.number > number) then + itemData.number = itemData.number - number + else + table.remove(self.list, i) + end + end + end +end + +function Pocket:getItem(name) + for i, itemData in ipairs(self.list) do + if (itemData.name == name) then + return itemData + end + end + return nil +end + +function Pocket:getItemNumber(name) + local item = self:getItem(name) + if (item == nil) then + return 0 + else + return item.number + end +end + +return Pocket \ No newline at end of file diff --git a/sonic-bluestreak.love/game/metadata.lua b/sonic-bluestreak.love/game/metadata.lua new file mode 100644 index 0000000..77aeef9 --- /dev/null +++ b/sonic-bluestreak.love/game/metadata.lua @@ -0,0 +1,83 @@ +-- game.metadata :: Basic metadata subsystem + +--[[ + Copyright © 2021 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 Serializer = require "birb.classes.serializable.serializer" +local Metadata = Serializer:extend() + +local META_FILE = "metadata.save" + +function Metadata:new(game) + self.game = game + self:reset() + Metadata.super.new(self, {"data"}) +end + +function Metadata:reset() + self.data = {} + for i = 1, self.game.slotNumber, 1 do + local newMetadata = {} + newMetadata.exist = false + newMetadata.completion = 0 + newMetadata.gametime = 0 + newMetadata.team = {} + newMetadata.rings = 0 + newMetadata.emeralds = 0 + newMetadata.location = "" + table.insert(self.data, newMetadata) + end +end + +function Metadata:update() + self:read() + if (self.data[self.game.slot] == nil) then + self.data[self.game.slot] = {} + end + self.data[self.game.slot].exist = true + self.data[self.game.slot].completion = self.game.completion + self.data[self.game.slot].gametime = self.game.gametime + self.data[self.game.slot].team = self.game.characters.team + self.data[self.game.slot].rings = self.game.loot.rings + self.data[self.game.slot].emeralds = 0 + self.data[self.game.slot].location = self.game.mapName + self:write() +end + +function Metadata:get() + self:read() + return self.data +end + +function Metadata:write() + self:serialize(META_FILE) +end + +function Metadata:read() + self:deserialize(META_FILE) +end + +function Metadata:remove(slot) + self.data[slot].exist = false + self:write() + end + +return Metadata diff --git a/sonic-bluestreak.love/game/modules/confirmdialog/init.lua b/sonic-bluestreak.love/game/modules/confirmdialog/init.lua new file mode 100644 index 0000000..9f9b502 --- /dev/null +++ b/sonic-bluestreak.love/game/modules/confirmdialog/init.lua @@ -0,0 +1,97 @@ +local GuiElement = require "birb.modules.gui.elements.canvas" +local ConfirmDialog = GuiElement:extend() + +local gui = require "game.modules.gui" + +local WIDTH = 256 +local PADWIDTH = 16 +local PADHEIGHT = 16 +local DEFAULT_LINES = 2 + +function ConfirmDialog:new(scene, message, choice1func, choice1, choice2func, choice2) + self.scene = scene + self.lines = DEFAULT_LINES + self.message = message + + self.choiceLabel = {} + self.choiceFunc = {} + self.choiceSound = {} + self.choiceLabel[1] = choice1 or "Yes" + self.choiceLabel[2] = choice2 or "No" + self.choiceFunc[1] = choice1func + self.choiceFunc[2] = choice2func or function() self:dismiss() end + self.choiceSound[1] = "mSelect" + self.choiceSound[2] = "mBack" + self.autoDismiss = false + + self.darken = true + + self.currentChoice = 0 + self.cancelChoice = -1 + + ConfirmDialog.super.new(self, "dialog", 424/2, 240/2, WIDTH + PADWIDTH, self:computeHeight()) + self.back = gui.newTextBox("assets/gui/dialogbox.png", self.w, self.h) + self.ox = self.w/2 + self.oy = self.h/2 + self.canvas.padding = 0 + self.depth = 0 + self.isVisible = 1 + self:getFocus() +end + +function ConfirmDialog:setLines(lines) + self.lines = lines + self.h = self:computeHeight() + self.oy = self.h/2 + self.canvas.needRedraw = true + self.back = gui.newTextBox("assets/gui/dialogbox.png", self.w, self.h) +end + +function ConfirmDialog:computeHeight() + return 32 + (self.lines * 16) + PADHEIGHT +end + +function ConfirmDialog:setCancelChoice(choice) + self.cancelChoice = choice - 1 +end + +function ConfirmDialog:keypressed(key) + if (key == "up" or key == "down") then + self.currentChoice = (self.currentChoice + 1) % 2 + self.scene.assets.sfx["mBeep"]:play() + self.canvas.needRedraw = true + elseif (key == "A") then + self:doAction(self.currentChoice) + elseif (key == "B") then + self:doAction(self.cancelChoice) + end +end + +function ConfirmDialog:doAction(choice) + if (self.choiceFunc[choice + 1] ~= nil) then + self.scene.assets.sfx[self.choiceSound[choice + 1]]:play() + self.choiceFunc[choice + 1]() + if (self.autoDismiss) then + self:dismiss() + end + end +end + +function ConfirmDialog:dismiss() + self.gui:setLastFocus() + self:destroy() +end + +function ConfirmDialog:drawTexture() + love.graphics.draw(self.back, 0) + local padx, pady = 8, 6 + self.scene.assets.fonts["small"]:draw(self.message ,padx, pady, WIDTH,"left") + for i = 1, 2, 1 do + self.scene.assets.fonts["small"]:draw(self.choiceLabel[i], padx + 8, pady + (self.lines + i - 1)*16) + if ((self.currentChoice + 1) == i) then + self.scene.assets.fonts["small"]:draw(">", padx, pady + (self.lines + i - 1)*16) + end + end +end + +return ConfirmDialog \ No newline at end of file diff --git a/sonic-bluestreak.love/game/modules/drawing/greyscale.lua b/sonic-bluestreak.love/game/modules/drawing/greyscale.lua new file mode 100644 index 0000000..004af6a --- /dev/null +++ b/sonic-bluestreak.love/game/modules/drawing/greyscale.lua @@ -0,0 +1,23 @@ +local GrayScale = {} + +local greyscaleShader = love.graphics.newShader[[ + vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords ){ + vec4 pixel = Texel(texture, texture_coords );//This is the current pixel color + number average = (pixel.r+pixel.b+pixel.g)/3.0; + pixel.r = average; + pixel.g = average; + pixel.b = average; + return pixel; + } + ]] + + +function GrayScale.startShader() + love.graphics.setShader(greyscaleShader) +end + +function GrayScale.endShader() + love.graphics.setShader() +end + +return GrayScale \ No newline at end of file diff --git a/sonic-bluestreak.love/game/modules/drawing/parallaxBackground.lua b/sonic-bluestreak.love/game/modules/drawing/parallaxBackground.lua new file mode 100644 index 0000000..4a7c370 --- /dev/null +++ b/sonic-bluestreak.love/game/modules/drawing/parallaxBackground.lua @@ -0,0 +1,165 @@ +local ParallaxBackground = Object:extend() + +local maputils = require "scenes.battlesystem.utils" + +function ParallaxBackground:new(scene, height, bottomBorder, type) + self.scene = scene + self.assets = self.scene.assets + + self.datas = {} + self.datas.type = type or "forest" + + self.height = height + self.bottomBorder = bottomBorder + + local zones = require "datas.gamedata.maps.shoot.zones" + local datas = zones[self.datas.type] + self.datas.background = datas.background + self.datas.tiles = datas.tiles + self.datas.borders = datas.borders + + self.assets:addTileset("normaltiles", "assets/backgrounds/normaltile") + self.assets:addTileset("borders", "assets/backgrounds/borders") + + local backpath = "assets/backgrounds/parallax/" .. self.datas.background + self.assets:addImage("back1", backpath .. "-back.png") + self.assets:addImage("back2", backpath .. "-fore.png") + self.assets:addImage("cliff", backpath .. "-cliff.png") + + self.texture = {} + self.texture.floor = self:generateFloor(datas.tiles) +end + +-- GET FUNCTIONS +-- Get information from the map + +function ParallaxBackground:getTotalHeight() + return self.height + self.bottomBorder; +end + +function ParallaxBackground:getTerrain(x, y) + if (y <= self.height) then + return 0 + else + return nil + end +end + +function ParallaxBackground:isInGrid(x, y) + return ( self:getTerrain(x, y) ~= nil ) +end + +function ParallaxBackground:getStartY() + return 240 - (self:getTotalHeight() * 20) - 10 +end + +function ParallaxBackground:gridToPixel(x, y, center) + local pixelx, pixely + local center = center or false + local x, y = x, y + + if (center) then + x = x + .5 + y = y + .5 + end + + pixelx = maputils.CONST.STARTX + ((x-1) * 31) + ((y-1) * 10) + pixely = self:getStartY() + ((y-1) * 20) + + return math.floor(pixelx), math.floor(pixely) +end + +-- DRAW FUNCTIONS +-- Draw the battle map + +function ParallaxBackground:generateFloor(tile) + local canvas = love.graphics.newCanvas(31*16, self:getTotalHeight() * 20) + local tile = tile or 1 + + love.graphics.setCanvas( canvas ) + + for i=1, self:getTotalHeight() do + for j=0, 18 do + local tiley = (i-1)*20 + local tilex = (j-2)*31 + (i-1)*10 + local variant = 1 + ((i + j) % 2) + local tiles = self.datas.tiles*2 + variant + if (not self:isInGrid(j, i)) then + love.graphics.setColor(.66, .66, .66, 1) + end + self.assets.tileset["normaltiles"]:drawTile(tiles, tilex, tiley) + utils.graphics.resetColor() + end + end + + love.graphics.setCanvas( ) + + local imagedata = canvas:newImageData() + local texture = love.graphics.newImage( imagedata ) + imagedata:release() + canvas:release() + return texture +end + +function ParallaxBackground:draw() + self:drawParallax(-maputils.CONST.STARTX, -self:getStartY(), 424, 240) +end + +function ParallaxBackground:drawParallax(x, y, w, h) + self:drawBackground(x, y, w, h) + self:drawForeground(x, y, w, h) + --love.graphics.draw(self.texture.floor, maputils.CONST.STARTX, self:getStartY()) + local w2, _ = self.texture.floor:getDimensions() + for i=1, 2 do + local x2 = x % w2 + love.graphics.draw(self.texture.floor, ((i-1)*31*16)-x2, -y) + end + self:drawBorders(x, y, w, h) +end + + +function ParallaxBackground:drawBackgrounds() + local w, _ = core.screen:getDimensions() + + local w2, h2 = self.assets.images["back1"]:getDimensions() + local imax = math.ceil(w / w2) + 1 + for i=1, imax do + self.assets.images["back1"]:draw((i-1)*w2, 0, 0, 1, 1) + end + + local w2, h2 = self.assets.images["back2"]:getDimensions() + local imax = math.ceil(w / w2) + 1 + for i=1, imax do + self.assets.images["back2"]:draw((i-1)*w2, self:getStartY()-h2, 0, 1, 1) + end + +end + +function ParallaxBackground:drawBackground(x, y, w, h) + local w2, h2 = self.assets.images["back1"]:getDimensions() + local imax = math.ceil(w / w2) + 1 + for i=1, imax do + local x1 = (x / 5) % w2 + self.assets.images["back1"]:draw((i-1)*w2 - x1, 0, 0, 1, 1, 0, 0) + end +end + +function ParallaxBackground:drawForeground(x, y, w, h) + local w2, h2 = self.assets.images["back2"]:getDimensions() + local imax = math.ceil(w / w2) + 1 + for i=1, imax do + local x1 = (x / 2) % w2 + self.assets.images["back2"]:draw((i-1)*w2 - x1, -y-10, 0, 1, 1, 0, h2) + end +end + +function ParallaxBackground:drawBorders(x, y) + local border = self.datas.borders + 1 + for i=1, 7 do + local x2 = x % 80 + self.assets.tileset["borders"]:drawTile(border, (i-1)*80 - x2, -y, 0, 1, 1, 0, 10) + self.assets.tileset["borders"]:drawTile(border, (i-1)*80 - x2, -(y-self:getTotalHeight()*20), 0, 1, 1) + end +end + +return ParallaxBackground diff --git a/sonic-bluestreak.love/game/modules/gui/actionPrompt.lua b/sonic-bluestreak.love/game/modules/gui/actionPrompt.lua new file mode 100644 index 0000000..da354e9 --- /dev/null +++ b/sonic-bluestreak.love/game/modules/gui/actionPrompt.lua @@ -0,0 +1,52 @@ +local CanvasElement = require "birb.modules.gui.elements.parent" +local ActionPrompt = CanvasElement:extend() + +function ActionPrompt:new() + self.text = "" + ActionPrompt.super.new(self, "actionPrompt", 0, 0, 424, 240) + self.depth = -2 + self.opacity = 0 + self.isShown = false +end + +function ActionPrompt:setText(text) + if (utils.string.isEmpty(text)) then + self:hide() + else + self.text = text + self:show() + end +end + +function ActionPrompt:hide() + if (self.isShown) then + self.tweens.tweens = {} + self:newTween(0.0, 0.6, {opacity = 0}, "outExpo") + end + self.isShown = false +end + +function ActionPrompt:show() + if (not self.isShown) then + self.tweens.tweens = {} + self:newTween(0.0, 0.6, {opacity = 1}, "outExpo") + end + self.isShown = true +end + +function ActionPrompt:draw() + if (not utils.string.isEmpty(self.text)) then + local w = self.assets.fonts["small"]:getWidth(self.text) + 16 + love.graphics.setColor(0,0,0,0.5 * self.opacity) + local x, y = 424 - w/2 - 4, 240 - 20 + love.graphics.rectangle("fill", x - w/2, y + 1, w, 15, 8, 8) + love.graphics.setColor(1, 1, 1, self.opacity) + self.assets.fonts["small"]:setColor(1, 1, 1, self.opacity) + self.assets.fonts["small"]:draw(self.text, x, y, -1, "center") + self.assets.fonts["small"]:setColor(1, 1, 1, 1) + utils.graphics.resetColor() + end +end + + +return ActionPrompt \ No newline at end of file diff --git a/sonic-bluestreak.love/game/modules/gui/boxedmenu.lua b/sonic-bluestreak.love/game/modules/gui/boxedmenu.lua new file mode 100644 index 0000000..6812251 --- /dev/null +++ b/sonic-bluestreak.love/game/modules/gui/boxedmenu.lua @@ -0,0 +1,71 @@ +local ParentMenu = require "birb.modules.gui.textmenu" +local BoxedList = ParentMenu:extend() + +local gui = require "game.modules.gui" + +function BoxedList:new(name, x, y, w, slotNumber, isBoxed, smallborder) + BoxedList.super.new(self, name, "small", x, y, w, slotNumber, 0) + self.paddingLeft = 12 + self.paddingRight = 4 + + self.cursorTexture = love.graphics.newImage("assets/gui/cursor-menulist.png") + self.cursorTransition = 0 + + self.isBoxed = isBoxed + if (isBoxed) then + local border = self.h + 16 + if (smallborder == true) then + border = self.h + 8 + end + self.box = gui.newTextBox("assets/gui/dialogbox.png", w + 8, border) + end +end + +function BoxedList:finalize() + self:setCancelWidget() +end + +function BoxedList:update(dt) + BoxedList.super.update(self, dt) + self:updateCursorPosition(dt) +end + +function BoxedList:updateCursorPosition(dt) + local relativecursor = self.widget.selected - self.view.firstSlot + + local transition = self.cursorTransition - relativecursor + if math.abs(transition) < 0.1 then + self.cursorTransition = relativecursor + else + local speed = dt * 45 + local movement = ((relativecursor) - (self.cursorTransition)) + self.cursorTransition = (self.cursorTransition) + movement * speed + end +end + +function BoxedList:drawCursor() + local x, y = self:getCursorPosition() + love.graphics.draw(self.cursorTexture, x, y) +end + +function BoxedList:getCursorPosition() + local addition = self.lineHeight + local x = self.x + 6 + local y = self.y + ((self.cursorTransition) * addition) + 1 + return x, y +end + +function BoxedList:draw() + if (self.isBoxed) then + local dy = 8 + if (self.smallborder) then + dy = 4 + end + local w, h = self.box:getDimensions() + local diff = (w-self.w)/2 + love.graphics.draw(self.box, self.x - self.ox - diff, self.y - self.oy - dy) + end + BoxedList.super.draw(self) +end + +return BoxedList diff --git a/sonic-bluestreak.love/game/modules/gui/choiceElem.lua b/sonic-bluestreak.love/game/modules/gui/choiceElem.lua new file mode 100644 index 0000000..b846d2f --- /dev/null +++ b/sonic-bluestreak.love/game/modules/gui/choiceElem.lua @@ -0,0 +1,22 @@ +local CanvasElement = require "birb.modules.gui.elements.canvas" +local ChoiceElement = CanvasElement:extend() + +local gui = require "game.modules.gui" + +function ChoiceElement:new(name, label1, label2, label3, x, y, approximateWidth) + self.background = gui.newChoiceBack(approximateWidth) + local w, h = self.background:getDimensions() + ChoiceElement.super.new(self, name, x, y, w, h) + self.label1 = label1 + self.label2 = label2 + self.label3 = label3 +end + +function ChoiceElement:drawTexture() + love.graphics.draw(self.background, 0, 0) + self.assets.fonts["small"]:draw(self.label1, 16, -2, -1, "left") + self.assets.fonts["small"]:draw(self.label2, self.w/2, -2, -1, "center") + self.assets.fonts["small"]:draw(self.label3, self.w - 20, -2, -1, "right") +end + +return ChoiceElement \ No newline at end of file diff --git a/sonic-bluestreak.love/game/modules/gui/complexhpbar.lua b/sonic-bluestreak.love/game/modules/gui/complexhpbar.lua new file mode 100644 index 0000000..a5378ae --- /dev/null +++ b/sonic-bluestreak.love/game/modules/gui/complexhpbar.lua @@ -0,0 +1,85 @@ +local ComplexHPBar = Object:extend() + +local gui = require "game.modules.gui" + +local VALUE_MARGIN = 11 +local HEIGHT = 7 + +function ComplexHPBar:new(width) + self.width = width + self:setColorForeground(1, 1, 1) + self:setColorBackground(0, 0, 0) + self.background = self:createBack( "assets/gui/hpbar_back.png" ) + self.foreground = self:createBack( "assets/gui/hpbar_fore.png" ) +end + +function ComplexHPBar:setColorForeground(r, g, b) + self.barcolor = {} + self.barcolor.r = r + self.barcolor.g = g + self.barcolor.b = b +end + +function ComplexHPBar:setColorBackground(r, g, b) + self.backcolor = {} + self.backcolor.r = r + self.backcolor.g = g + self.backcolor.b = b +end + +function ComplexHPBar:createBack( filepath ) + local image = love.graphics.newImage( filepath ) + local imageWidth, imageHeight = image:getDimensions() + local middleImageWidth = imageWidth - VALUE_MARGIN*2 + + local totalWidth = self.width + 8 -- On récupère la taille à partir de la base + local middleWidth = totalWidth - VALUE_MARGIN*2 + + local iteration = math.ceil((middleWidth) / (middleImageWidth)) + local tilequad = {} + tilequad[1] = love.graphics.newQuad(0, 0, VALUE_MARGIN, imageHeight, imageWidth, imageHeight) + tilequad[2] = love.graphics.newQuad(VALUE_MARGIN, 0, middleImageWidth, imageHeight, imageWidth, imageHeight) + tilequad[3] = love.graphics.newQuad(imageWidth - VALUE_MARGIN, 0, VALUE_MARGIN, imageHeight, imageWidth, imageHeight) + + local canvas1 = love.graphics.newCanvas(middleWidth, imageHeight) + love.graphics.setCanvas( canvas1 ) + local combinedWidth = 0 + for i = 1, iteration do + love.graphics.draw(image, tilequad[2], combinedWidth, 0) + combinedWidth = combinedWidth + middleImageWidth + end + + local canvas2 = love.graphics.newCanvas(totalWidth, imageHeight) + love.graphics.setCanvas( canvas2 ) + love.graphics.draw(image, tilequad[1], 0, 0) + love.graphics.draw(canvas1, VALUE_MARGIN, 0) + love.graphics.draw(image, tilequad[3], totalWidth - 11, 0) + love.graphics.setCanvas( ) + + local imagedata = canvas2:newImageData() + local texture = love.graphics.newImage( imagedata ) + imagedata:release() + canvas2:release() + + return texture +end + +function ComplexHPBar:draw(x, y, percent) + utils.graphics.resetColor() + love.graphics.draw(self.foreground, x, y) + love.graphics.setColor(self.backcolor.r, self.backcolor.g, self.backcolor.b, 1) + love.graphics.draw(self.background, x, y) + utils.graphics.resetColor() + + love.graphics.setColor(self.barcolor.r, self.barcolor.g, self.barcolor.b, 1) + gui.drawBar(x + 4, y + 2, math.floor((self.width) * percent), HEIGHT) + utils.graphics.resetColor() +end + +function ComplexHPBar:drawWithLabels(x, y, value, valuemax) + local percent = value / valuemax + self:draw(x, y, percent) + love.graphics.print(math.floor(value) .. "/" .. valuemax, x+10, y+2) +end + +return ComplexHPBar diff --git a/sonic-bluestreak.love/game/modules/gui/emblem.lua b/sonic-bluestreak.love/game/modules/gui/emblem.lua new file mode 100644 index 0000000..2721a9a --- /dev/null +++ b/sonic-bluestreak.love/game/modules/gui/emblem.lua @@ -0,0 +1,45 @@ +local Emblem = Object:extend() +local greyscale = require "game.modules.drawing.greyscale" + +function Emblem:new(abstract, scene) + self.assets = scene.assets + self.abstract = abstract + + self.charid = self.abstract.simplename + self.stats = self.abstract:getStats() +end + +function Emblem:draw(x, y) + self:drawBackground(x, y) + self:drawForeground(x, y) +end + +function Emblem:drawForeground(x, y) + local emblem2 = "m_" .. self.abstract.data.class + core.screen:setScissor(x, y-16, 32, 40) + if (self.abstract.hp > 0) then + self.assets.sprites[self.charid]:draw(x+14, y+14) + else + greyscale.startShader() + self.assets.sprites[self.charid]:drawFrame(1, x+14, y+14) + end + core.screen:resetScissor( ) + self.assets.images[emblem2]:draw(x, y) + greyscale.endShader() +end + +function Emblem:drawBackground(x, y) + local emblem1 = "e_" .. self.abstract.data.class + + if (self.abstract.hp > 0) then + self.assets.images[emblem1]:draw(x, y) + else + greyscale.startShader() + self.assets.images[emblem1]:draw(x, y) + greyscale.endShader() + end + +end + + +return Emblem diff --git a/sonic-bluestreak.love/game/modules/gui/fancymenu.lua b/sonic-bluestreak.love/game/modules/gui/fancymenu.lua new file mode 100644 index 0000000..61d4c96 --- /dev/null +++ b/sonic-bluestreak.love/game/modules/gui/fancymenu.lua @@ -0,0 +1,32 @@ +local ParentMenu = require "birb.modules.gui.textmenu" +local FancyMenu = ParentMenu:extend() + +local gui = require "game.modules.gui" + +function FancyMenu:new(name, x, y, w, itemNumber, haveBiseau) + FancyMenu.super.new(self, name, "small", x, y, w, itemNumber) + self.biseau = utils.math.either(haveBiseau, 8, 0) + self.itemNumber = itemNumber + self.box = gui.newChoiceBack(self.w + 24) + self.cursorTexture = love.graphics.newImage("assets/gui/cursor-menulist.png") +end + +function FancyMenu:getDimensions() + local w, h = FancyMenu.super.getDimensions(self) + return w + (self.biseau*self.itemNumber), h +end + +function FancyMenu:getListPart(i) + local x, y, w, h = FancyMenu.super.getListPart(self, i) + return x + (self.biseau*i), y, w, h +end + +function FancyMenu:drawWidgetBackground(x, y, w, h) + love.graphics.draw(self.box, x - 8, y + 2) +end + +function FancyMenu:drawGraphicalCursor(x, y, w, h) + love.graphics.draw(self.cursorTexture, x - 3, y + 1) +end + +return FancyMenu diff --git a/sonic-bluestreak.love/game/modules/gui/frame.lua b/sonic-bluestreak.love/game/modules/gui/frame.lua deleted file mode 100644 index 2fd8a88..0000000 --- a/sonic-bluestreak.love/game/modules/gui/frame.lua +++ /dev/null @@ -1,17 +0,0 @@ -local Frame = Object:extend() - -function Frame:new() - self.guiborder = game.gui.newBorder(424, 20, 6) - self.guiborder2 = game.gui.newBorder(424, 40, 12) -end - -function Frame:draw() - love.graphics.setColor(0.256, 0.632, 0.852, 1) - love.graphics.rectangle("fill", 0, 220, 424, 20) - utils.graphics.resetColor() - love.graphics.draw(self.guiborder, 424, 20, 0, -1, -1) - love.graphics.draw(self.guiborder2, 424, 220, 0, 1, 1, 424, 0) - love.graphics.print(love.timer.getFPS(), 200, 8) -end - -return Frame diff --git a/sonic-bluestreak.love/game/modules/gui/gameover.lua b/sonic-bluestreak.love/game/modules/gui/gameover.lua new file mode 100644 index 0000000..af1fdab --- /dev/null +++ b/sonic-bluestreak.love/game/modules/gui/gameover.lua @@ -0,0 +1,44 @@ +local Screen = require "birb.modules.gui.screen" +local GameOverScreen = Screen:extend() + +local TextElement = require "birb.modules.gui.elements.text" +local ConfirmDialog = require "game.modules.confirmdialog" + +local defTransitions = require "birb.modules.transitions" + +local HEIGHT = 40 + +local show = { + {"gameText", "movement", 0.9, 0.4, 424/2 - 4, HEIGHT, "inExpo"}, + {"overText", "movement", 0.9, 0.4, 424/2 + 4, HEIGHT, "inExpo"} + } + +function GameOverScreen:new() + GameOverScreen.super.new(self, "titleScreen") + self:addTransform("show", show) + self.scene:showOverlay(true) + self:show() +end + +function GameOverScreen:createElements() + return { + {TextElement("gameText", "SA2font", "GAME", 0, HEIGHT, "right"), 0, 1}, + {TextElement("overText", "SA2font", "OVER", 424, HEIGHT, "left"), 0, 1}, + {ConfirmDialog(self.scene, "Do you want to return to title ? \nYou can also reload your latest save.", + function() self:returnToTitle() end, "Return to title", + function() self:loadLastSave() end, "Reload last save"), + 1.8, 0} + } +end + +function GameOverScreen:returnToTitle() + core.screen:startTransition(defTransitions.default, defTransitions.circle, function() scenes.menus.title(true) end, 424/2, 240/2) +end + +function GameOverScreen:loadLastSave() + self.scene.tweens:newTween(0, 0.3, {borderPosition=0}, "inOutQuad") + core.screen:startTransition(defTransitions.default, defTransitions.default, function() game:reload() scenes.overworld() end, 424/2, 240/2) +end + + +return GameOverScreen \ No newline at end of file diff --git a/sonic-bluestreak.love/game/modules/gui/init.lua b/sonic-bluestreak.love/game/modules/gui/init.lua index d38f796..c8f0426 100644 --- a/sonic-bluestreak.love/game/modules/gui/init.lua +++ b/sonic-bluestreak.love/game/modules/gui/init.lua @@ -1,9 +1,9 @@ local gui = {} -local barborder = love.graphics.newImage("assets/gui/status/barborder.png") +local barborder = love.graphics.newImage("assets/gui/barborder.png") function gui.newBorder(width, height, middlePosition) - local tileset = love.graphics.newImage("assets/gui/system/borders.png") + local tileset = love.graphics.newImage("assets/gui/borders.png") local tilequad = {} local w, h = tileset:getDimensions() tilequad[1] = love.graphics.newQuad(0, 0, 20, 20, w, h) @@ -11,9 +11,9 @@ function gui.newBorder(width, height, middlePosition) tilequad[3] = love.graphics.newQuad(40, 0, 20, 20, w, h) tilequad[4] = love.graphics.newQuad(60, 0, 20, 20, w, h) - local Texture = love.graphics.newCanvas(width, height) + local canvas = love.graphics.newCanvas(width, height) - love.graphics.setCanvas(Texture) + love.graphics.setCanvas(canvas) utils.graphics.resetColor() local height = math.ceil(height / 20) @@ -37,7 +37,45 @@ function gui.newBorder(width, height, middlePosition) love.graphics.setCanvas( ) - return Texture + local imagedata = canvas:newImageData() + local texture = love.graphics.newImage( imagedata ) + imagedata:release() + canvas:release() + + return texture +end + +function gui.newChoiceBack(approximateWidth) + local asset = love.graphics.newImage("assets/gui/attacklist.png") + local sw, sh = asset:getDimensions() + local startAsset = love.graphics.newQuad(0, 0, 21, sh, sw, sh) + local midAsset = love.graphics.newQuad(21, 0, 12, sh, sw, sh) + local endAsset = love.graphics.newQuad(sw-25, 0, 25, sh, sw, sh) + + local iterations = math.floor((approximateWidth / 12) - 4) + local width = (iterations * 12) + local height = 16 + local canvasWidth = width + 21 + 25 + + local canvas = love.graphics.newCanvas(canvasWidth, height) + + love.graphics.setCanvas(canvas) + + love.graphics.draw(asset, startAsset, 0, 0) + love.graphics.draw(asset, endAsset, 21 + width, 0) + + for i=1, (iterations) do + love.graphics.draw(asset, midAsset, 21 + ((i-1)*12), 0) + end + + love.graphics.setCanvas( ) + + local imagedata = canvas:newImageData() + local texture = love.graphics.newImage( imagedata ) + imagedata:release() + canvas:release() + + return texture end function gui.drawBar(x, y, width, height) @@ -52,9 +90,8 @@ function gui.drawBar(x, y, width, height) end end -function gui.newTextBox(type, width, height) - local filepath = "assets/gui/dialogs/" .. type .. ".png" - local baseimage = love.graphics.newImage(filepath) +function gui.newTextBox(filename, width, height) + local baseimage = love.graphics.newImage(filename) local quad = {} quad[1] = love.graphics.newQuad(00, 00, 8, 8, 24, 24) quad[2] = love.graphics.newQuad(00, 08, 8, 8, 24, 24) @@ -109,7 +146,50 @@ function gui.newTextBox(type, width, height) love.graphics.setCanvas( ) - return canvas + local imagedata = canvas:newImageData() + local texture = love.graphics.newImage( imagedata ) + imagedata:release() + canvas:release() + return texture +end + +function gui.getEmeraldsTexture(number) + local canvas = love.graphics.newCanvas(95, 31) + local emeralds = love.graphics.newImage("assets/gui/emeralds.png") + love.graphics.setCanvas( canvas ) + for i = 1, 7, 1 do + local emerald + local x = (i-1)*12 + if (i > number) then + emerald = love.graphics.newQuad(0,0,23,17,23*8, 17) + else + emerald = love.graphics.newQuad((i*23),0,23,17,23*8, 17) + --emerald = love.graphics.newQuad((i*23),0,23,17,23*7, 17) + end + + local isPair = (i%2 == 0) + local y = 0 + if (isPair == true) then + y = 14 + end + love.graphics.draw(emeralds, emerald,x,y) + emerald:release() + end + + love.graphics.setCanvas( ) + local imagedata = canvas:newImageData() + local texture = love.graphics.newImage( imagedata ) + imagedata:release() + canvas:release() + return texture +end + +function gui.drawEmptyIcon(x, y) + local outlineLight = 0.15 + love.graphics.circle("fill", x + 8, y + 8, 2, 8) + love.graphics.setColor(outlineLight, outlineLight, outlineLight, 1) + love.graphics.circle("line", x + 8, y + 8, 2, 8) + utils.graphics.resetColor() end diff --git a/sonic-bluestreak.love/game/modules/gui/menuback.lua b/sonic-bluestreak.love/game/modules/gui/menuback.lua new file mode 100644 index 0000000..8439d58 --- /dev/null +++ b/sonic-bluestreak.love/game/modules/gui/menuback.lua @@ -0,0 +1,72 @@ +local TextureElement = require "birb.modules.gui.elements.parent" +local MenuBack = TextureElement:extend() + +local backx = 0 +local bordery = 0 +local turn = 0 + +local fancyBackShader = love.graphics.newShader[[ + uniform number screenWidth; + uniform number screenHeight; + vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords ){ + vec4 pixel = Texel(texture, texture_coords); //This is the current pixel color + number value = (screen_coords.x / screenWidth) * (screen_coords.y / screenHeight) * 0.5; + number lighten = 0.25; + return vec4(0.5 + value + lighten,0.0 + lighten,0.5 - value + lighten, 1 - pixel.r); + //return vec4(1,1,1, pixel.r); + } + ]] + +function MenuBack:new() + self.back = love.graphics.newImage("assets/gui/back/background.png") + self.border = love.graphics.newImage("assets/gui/back/border.png") + self.emblem = love.graphics.newImage("assets/gui/back/emblem.png") + self.star = love.graphics.newImage("assets/gui/back/star.png") + self.backImage = love.graphics.newImage("assets/artworks/back.png") + + self.canvas = nil + local w, h = love.graphics.getDimensions() + fancyBackShader:send("screenWidth",w) + fancyBackShader:send("screenHeight",h) + MenuBack.super.new(self, "menuBack", 0, 0, w, h) + self.depth = 200 +end + + +function MenuBack:update(dt) + backx = (backx + dt * 20) % 96 + bordery = (bordery + dt * 35) % 160 + turn = turn + (dt/1.5) % 1 + + self.canvas = love.graphics.newCanvas( 424, 240 ) + love.graphics.setCanvas(self.canvas) + for i = 0, (math.ceil(424/96)), 1 do + for j = 0, (math.ceil(240/96)), 1 do + love.graphics.draw(self.back, backx + ((i - 1 ) * 96), backx + ((j - 1 ) * 96)) + end + end + + for j = 0, (math.ceil(240/160)), 1 do + love.graphics.draw(self.border, 0, bordery + ((j - 1) * 160)) + end + love.graphics.draw(self.emblem, 424, 240 - 32, 0, 0.8, 0.8, 200, 200) + love.graphics.draw(self.star, 424, 240 - 32, turn, 0.8, 0.8, 200, 200) + love.graphics.setColor(1, 1, 1, 1) + + love.graphics.setCanvas() +end + + +function MenuBack:draw() + love.graphics.setColor(1, 1, 1, 1) + love.graphics.rectangle("fill", 0, 0, 424, 240) + love.graphics.setShader(fancyBackShader) + if (self.canvas ~= nil) then + love.graphics.draw(self.canvas, 0, 0) + end + love.graphics.setShader() + utils.graphics.resetColor() + love.graphics.draw(self.backImage, 0, 0) +end + +return MenuBack \ No newline at end of file diff --git a/sonic-bluestreak.love/game/modules/gui/overlay.lua b/sonic-bluestreak.love/game/modules/gui/overlay.lua new file mode 100644 index 0000000..7cca4c5 --- /dev/null +++ b/sonic-bluestreak.love/game/modules/gui/overlay.lua @@ -0,0 +1,96 @@ +local GuiScreen = require "birb.modules.gui.screen" +local TextureElement = require "birb.modules.gui.elements.drawable" +local ColorElement = require "birb.modules.gui.elements.color" +local TextElement = require "birb.modules.gui.elements.text" + +local OverlayScreen = GuiScreen:extend() + +local gui = require "game.modules.gui" +local either = utils.math.either + +local OVERLAY_OPACITY = 0.5 +local wasActive = false +local hadVersion = false + +local animateAppear = { + {"upBorder", "movement", 0.0, 0.5, 0, 30, "inOutQuart"}, + {"downBorder", "movement", 0.0, 0.5, 424, 210, "inOutQuart"} +} + +local animateDisappear = { + {"upBorder", "movement", 0.0, 0.5, 0, 0, "inOutQuart"}, + {"downBorder", "movement", 0.0, 0.5, 424, 240, "inOutQuart"}, + {"version", "movement", 0.0, 0.5, 380, 250, "inOutQuart"}, + {"overlayDarken", "tween", 0.0, 0.6, {opacity = 0}, "outExpo"} +} + +local showBackground = { + {"overlayDarken", "tween", 0.0, 0.6, {opacity = OVERLAY_OPACITY}, "inExpo"} +} + +local hideBackground = { + {"overlayDarken", "tween", 0.0, 0.6, {opacity = 0}, "outExpo"} +} + +local showVersion = { + {"version", "movement", 0.0, 0.5, 380, 220, "inOutQuart"}, +} + +local hideVersion = { + {"version", "movement", 0.0, 0.5, 380, 250, "inOutQuart"}, +} + +function OverlayScreen:new(active, doShowVersion) + self.borders = gui.newBorder(424, 30, 8) + self.doShowVersion = doShowVersion + + OverlayScreen.super.new(self, "overlay") + + local transformStuff = false + if (active == wasActive) then + self.isVisible = active + else + transformStuff = true + end + + self:addTransform("show", animateAppear) + self:addTransform("hide", animateDisappear) + self:addTransform("showBackground", showBackground) + self:addTransform("hideBackground", hideBackground) + self:addTransform("showVersion", showVersion) + self:addTransform("hideVersion", hideVersion) + + if (transformStuff) then + if (active) then + self:show() + else + self:hide() + end + end + + if (active) then + if (self.doShowVersion) then + self:playTransform("showVersion") + else + self:playTransform("hideVersion") + end + end +end + +function OverlayScreen:update(dt) + wasActive = self.isVisible + hadVersion = self.doShowVersion +end + +function OverlayScreen:createElements() + local d = either(wasActive, 30, 0) + local v = either(hadVersion, 30, 0) + return { + {TextureElement("upBorder", self.borders, 0, d, 0, 1, -1, 0, 0, 1), 0, -1}, + {TextureElement("downBorder", self.borders, 424, 240 - d, 0, -1, 1, 0, 0, 1), 0, -1}, + {ColorElement("overlayDarken", 0, 0, 0, 0), 0, 5}, + {TextElement("version", "small", "v" .. game.version, 380, 250 - v, "left"), 0, -1} + } +end + +return OverlayScreen \ No newline at end of file diff --git a/sonic-bluestreak.love/game/modules/gui/simplehpbar.lua b/sonic-bluestreak.love/game/modules/gui/simplehpbar.lua new file mode 100644 index 0000000..42e2e26 --- /dev/null +++ b/sonic-bluestreak.love/game/modules/gui/simplehpbar.lua @@ -0,0 +1,30 @@ +local SimpleHPBar = Object:extend() + +local TweenManager = require "birb.classes.time" +local gui = require "game.modules.gui" + +function SimpleHPBar:new(hp) + self.tweens = TweenManager(self) + self.hp = hp + self.baseHP = hp +end + +function SimpleHPBar:setHP(newHP) + self.tweens:newTween(0, 0.1, {hp = newHP}, 'inCubic') +end + +function SimpleHPBar:update(dt) + self.tweens:update(dt) +end + +function SimpleHPBar:draw(x, y) + love.graphics.setColor(0, 0, 0, 1) + gui.drawBar(x, y, 26, 4) + love.graphics.rectangle("fill", x, y, 24, 4) + love.graphics.setColor(248/255, 160/255, 0, 1) + local bar = math.max(0, math.floor(22 * (self.hp / self.baseHP))) + love.graphics.rectangle("fill", x + 1, y + 1, math.floor(bar), 2) + love.graphics.setColor(1, 1, 1, 1) +end + +return SimpleHPBar diff --git a/sonic-bluestreak.love/game/modules/gui/status.lua b/sonic-bluestreak.love/game/modules/gui/status.lua deleted file mode 100644 index 6ede025..0000000 --- a/sonic-bluestreak.love/game/modules/gui/status.lua +++ /dev/null @@ -1,60 +0,0 @@ -local StatusArea = Object:extend() - -function StatusArea:new(character, type, hpmax) - self.type = "e_" .. type; - self.hpmax = hpmax; - self.hp = hpmax; - self.pp = 100; - self.ppmax = 100; - self.assets = character.assets - self.weapon = 0 - self.rings = 0 -end - -function StatusArea:setWeapon(weapon) - self.weapon = weapon -end - -function StatusArea:setRings(rings) - self.rings = rings -end - -function StatusArea:setHp(hp) - self.hp = hp -end - -function StatusArea:setPp(pp) - self.pp = pp -end - -function StatusArea:draw(x, y) - local x = x or 0 - local y = y or 0 - - self.assets.images[self.type]:draw(x, y) - if (self.weapon ~= 0) then - self.assets.tileset["weapons"]:drawTile(self.weapon, x-2, y-2) - end - - self.assets.images["statusbar"]:draw(x+8, y-2) - - local bar1 = math.floor((self.hp/self.hpmax)*107) - local bar2 = math.floor((self.pp/100)*108) - - love.graphics.setColor(248/255, 160/255, 0, 1) - game.gui.drawBar(x+25, y+9, bar1, 7) - love.graphics.setColor(0, 248/255, 248/255, 1) - game.gui.drawBar(x+13, y+21, bar2, 7) - utils.graphics.resetColor() - - self.assets.fonts["smallnumbers"]:set() - love.graphics.print(math.floor(self.hp) .. "/" .. self.hpmax, x+34, y+9) - love.graphics.print(math.floor(self.pp) .. "%", x+34, y+21) - - self.assets.fonts["numbers"]:set() - love.graphics.print(utils.math.numberToString(self.rings, 3), x+88, y-5) - - self.assets.images["hudring"]:draw(x+125, y-6) -end - -return StatusArea diff --git a/sonic-bluestreak.love/game/modules/menus/fancy.lua b/sonic-bluestreak.love/game/modules/menus/fancy.lua new file mode 100644 index 0000000..eae6269 --- /dev/null +++ b/sonic-bluestreak.love/game/modules/menus/fancy.lua @@ -0,0 +1,78 @@ +local List = require "game.modules.menus.list" + +local fancy = {} +fancy.FancyMenu = List.ListMenu:extend() +fancy.BaseWidget = List.CenteredWidget:extend() +fancy.SubMenuWidget = fancy.BaseWidget:extend() + +local MENU_ITEM_HEIGHT = 16 + +local gui = require "game.modules.gui" + +function fancy.FancyMenu:new(scene, name, x, y, w, itemNumber, haveBiseau) + fancy.FancyMenu.super.new(self, scene, name, x, y, w, itemNumber, false) + self.haveBiseau = haveBiseau +end + +function fancy.FancyMenu:getCursorPosition() + if (self.haveBiseau) then + local addition = MENU_ITEM_HEIGHT + local x = self.x + 4 + ((self.cursorTransition) * addition)/2 + local y = self.y + ((self.cursorTransition) * addition) + return x, y + else + return fancy.FancyMenu.super.getCursorPosition(self) + end +end + +function fancy.FancyMenu:getNextPosition(x, y, h) + if (self.haveBiseau) then + return (x + (h/2)), y+h + else + return fancy.FancyMenu.super.getNextPosition(self, x, y, h) + end +end + +function fancy.FancyMenu:clone(name) + return fancy.FancyMenu(self.scene, name, self.x, self.y, self.w, self.itemNumber, self.haveBiseau) +end + +function fancy.FancyMenu:addSubMenuWidget(newmenu, name) + fancy.SubMenuWidget(self.scene, self.name, newmenu, name) +end + +-- FancyWidgets +-- Add Fancy Widgets +function fancy.BaseWidget:new(scene, menu_name, label, label2) + self.label2 = label2 + fancy.BaseWidget.super.new(self, scene, menu_name, label) + self.box = gui.newChoiceBack(self.menu.w + 24) +end + +function fancy.BaseWidget:drawCanvas() + love.graphics.draw(self.box, 0, 0) + local h = math.floor(self.height / 2) - (self.font:getHeight() / 2) - 2 + self.font:setColor(self.color[1], self.color[2], self.color[3], 1) + self.font:draw(self.label, 16, h, -1, "left") + self.font:draw(self.label2, self.width -8, h, -1, "right") + self.font:setColor(1, 1, 1, 1) + utils.graphics.resetColor() +end + +-- Widget de sous-menu +function fancy.SubMenuWidget:new(scene, menu_name, newmenu, label) + local label2 = "" + if (label ~= "Back") then + label2 = ">" + end + fancy.SubMenuWidget.super.new(self, scene, menu_name, label, label2) + self.newmenu = newmenu +end + +function fancy.SubMenuWidget:action() + self.scene.assets:playSFX("mBeep") + self.scene.menusystem:switchMenu(self.newmenu) + self.scene.menusystem.menus[self.newmenu]:activationAction() +end + +return fancy diff --git a/sonic-bluestreak.love/game/modules/menus/list.lua b/sonic-bluestreak.love/game/modules/menus/list.lua new file mode 100644 index 0000000..2f41a2a --- /dev/null +++ b/sonic-bluestreak.love/game/modules/menus/list.lua @@ -0,0 +1,172 @@ +local ParentMenu = require "game.modules.menus.parents.menu" +local Widget = require "birb.modules.menusystem.widgets" + +local list = {} +list.ListMenu = ParentMenu:extend() +list.CenteredWidget = Widget.Text:extend() +list.DualTextWidget = list.CenteredWidget:extend() +list.SubMenuWidget = list.DualTextWidget:extend() + +local MENU_ITEM_HEIGHT = 16 + +local gui = require "game.modules.gui" + +-- ListMenu +function list.ListMenu:new(scene, name, x, y, w, itemNumber, isBoxed, smallborder) + self.scene = scene + self.name = name + local h = itemNumber * MENU_ITEM_HEIGHT + list.ListMenu.super.new(self, scene, name, x, y, w, h, itemNumber) + self.cursorTexture = love.graphics.newImage("assets/gui/cursor-menulist.png") + self.cursorTransition = 0 + self.submenus = {} + self.itemNumber = itemNumber + self.smallborder = (smallborder == true) + + self.isBoxed = isBoxed + if (self.isBoxed) then + local border = h+16 + if (self.smallborder) then + border = h+8 + end + self.box = gui.newTextBox("assets/gui/dialogbox.png", w, border) + end +end + +function list.ListMenu:addSubMenu(name, nicerName) + local submenu = self:clone(name) + self:addSubMenuWidget(name, nicerName) + table.insert(self.submenus, name) +end + +function list.ListMenu:addSubMenuWidget(newmenu, name) + list.SubMenuWidget(self.scene, self.name, newmenu, name) +end + +function list.ListMenu:finalize(parent) + if (parent ~= "" and parent ~= nil) then + self:addSubMenuWidget(parent, "Back") + self:setCancelWidget() + end + + for i,name in ipairs(self.submenus) do + if (self.menusystem.menus[name] ~= nil) then + self.menusystem.menus[name]:finalize(self.name) + end + end +end + +function list.ListMenu:clone(name) + return list.ListMenu(self.scene, name, self.x, self.y, self.w, self.itemNumber, self.isBoxed) +end + +function list.ListMenu:update(dt) + list.ListMenu.super.update(self, dt) + self:updateCursorPosition(dt) +end + +function list.ListMenu:updateCursorPosition(dt) + local relativecursor = self.widget.selected - self.view.firstSlot + + local transition = self.cursorTransition - relativecursor + if math.abs(transition) < 0.1 then + self.cursorTransition = relativecursor + else + local speed = dt*45 + local movement = ((relativecursor) - (self.cursorTransition)) + self.cursorTransition = (self.cursorTransition) + movement * speed + end +end + +function list.ListMenu:drawCursor() + local x, y = self:getCursorPosition() + love.graphics.draw(self.cursorTexture, x, y) +end + +function list.ListMenu:getCursorPosition() + local addition = MENU_ITEM_HEIGHT + local x = self.x + 6 + local y = self.y + ((self.cursorTransition) * addition) + 1 + return x, y +end + +function list.ListMenu:draw() + if (self.isBoxed) then + local dy = 8 + if (self.smallborder) then + dy = 4 + end + love.graphics.draw(self.box, self.x, self.y - dy) + end + self:updateView() + local widgety = self.y + local widgetx = self.x + for i,v in ipairs(self.widget.list) do + if (i >= self.view.firstSlot) and (i < self.view.firstSlot + self.view.slotNumber) then + v:draw(widgetx, widgety, self.w, self.widget.h) + if self.widget.selected == i and self:haveFocus() == true then + v:drawSelected(widgetx, widgety, self.w, self.widget.h) + else + v:draw(widgetx, widgety, self.w, self.widget.h) + end + widgetx, widgety = self:getNextPosition(widgetx, widgety, self.widget.h) + end + end +end + +function list.ListMenu:getNextPosition(x, y, h) + return x, y+h +end + +-- Widgets +-- Tout les widgets pour la liste de base + +-- Widget centré +function list.CenteredWidget:new(scene, menu_name, label) + local font = scene.assets.fonts["small"] + font:setFilter("shadow") + self.scene = scene + local widgetMenu = scene.menusystem.menus[menu_name] + list.CenteredWidget.super.new(self, widgetMenu, font, label) +end + +function list.CenteredWidget:drawCanvas() + local h = math.floor(self.height / 2) - (self.font:getHeight() / 2) - 2 + self.font:setColor(self.color[1], self.color[2], self.color[3], 1) + self.font:draw(self.label, self.width / 2, h, -1, "center") + self.font:setColor(1, 1, 1, 1) + utils.graphics.resetColor() +end + +-- Widget avec deux bouts de textes +function list.DualTextWidget:new(scene, menu_name, label, label2) + self.label2 = label2 + list.DualTextWidget.super.new(self, scene, menu_name, label) +end + +function list.DualTextWidget:drawCanvas() + local h = math.floor(self.height / 2) - (self.font:getHeight() / 2) + self.font:setColor(self.color[1], self.color[2], self.color[3], 1) + self.font:draw(self.label, 16, h, -1, "left") + self.font:draw(self.label2, self.width - 8, h, -1, "right") + self.font:setColor(1, 1, 1, 1) + utils.graphics.resetColor() +end + +-- Widget de sous-menu +function list.SubMenuWidget:new(scene, menu_name, newmenu, label) + local label2 = "" + if (label ~= "Back") then + label2 = ">" + end + list.SubMenuWidget.super.new(self, scene, menu_name, label, label2) + self.newmenu = newmenu +end + +function list.SubMenuWidget:action() + self.scene.assets:playSFX("mBeep") + self.scene.menusystem:switchMenu(self.newmenu) + self.scene.menusystem.menus[self.newmenu]:activationAction() +end + +return list diff --git a/sonic-bluestreak.love/game/modules/menus/parents/menu.lua b/sonic-bluestreak.love/game/modules/menus/parents/menu.lua new file mode 100644 index 0000000..cc9557a --- /dev/null +++ b/sonic-bluestreak.love/game/modules/menus/parents/menu.lua @@ -0,0 +1,36 @@ +local ListBox = require "birb.modules.menusystem.listbox" +local TweenManager = require "birb.classes.time" + +local RadianceMenu = ListBox:extend() + +function RadianceMenu:new(scene, name, x, y, w, h, itemNumber) + self.scene = scene + self.tweens = TweenManager(self) + RadianceMenu.super.new(self, self.scene.menusystem, name, x, y, w, h, itemNumber) +end + +function RadianceMenu:update(dt) + self.tweens:update(dt) + RadianceMenu.super.update(self, dt) +end + +function RadianceMenu:moveFrom(x, y) + local newX, newY = self.x, self.y + self.x, self.y = x, y + + self.tweens:addTween(0, 0.3, {x = newX, y = newY}, "inOutQuad") +end + +function RadianceMenu:moveTo(newX, newY) + self.tweens:addTween(0, 0.3, {x = newX, y = newY}, "inOutQuad") +end + +function RadianceMenu:getCenter() + return self.x + self.width, self.y + self.height +end + +function RadianceMenu:activationAction() + -- Do nothing +end + +return RadianceMenu diff --git a/sonic-bluestreak.love/game/modules/menus/parents/widget.lua b/sonic-bluestreak.love/game/modules/menus/parents/widget.lua new file mode 100644 index 0000000..7990a58 --- /dev/null +++ b/sonic-bluestreak.love/game/modules/menus/parents/widget.lua @@ -0,0 +1,13 @@ +local Widget = require "birb.modules.menusystem.widgets" +local RadianceWidget = Widget.Text:extend() + +function RadianceWidget:new(scene, name, label, color) + self.scene = scene + local label = label or "" + local font = scene.assets.fonts["small"] + font:setFilter("shadow") + local widgetMenu = scene.menusystem.menus[name] + RadianceWidget.super.new(self, widgetMenu, font, label, color) +end + +return RadianceWidget diff --git a/sonic-bluestreak.love/game/modules/messagequeue/init.lua b/sonic-bluestreak.love/game/modules/messagequeue/init.lua new file mode 100644 index 0000000..f9738ee --- /dev/null +++ b/sonic-bluestreak.love/game/modules/messagequeue/init.lua @@ -0,0 +1,40 @@ +local GuiElement = require "birb.modules.gui.elements.parent" +local MessageQueue = GuiElement:extend() +local Message = require "game.modules.messagequeue.message" +local MAX = 3 + +function MessageQueue:new(scene) + self.messages = {} + self.permaMessage = nil + self.scene = scene + MessageQueue.super.new(self, "messageQueue", 0, 0, 424, 240) + self.depth = 0 +end + +function MessageQueue:addMessage(newMessage) + for _, message in ipairs(self.messages) do + message:move() + end + table.insert(self.messages, 1, Message(self.scene, newMessage, false)) + self.messages[MAX + 1] = nil +end + +function MessageQueue:pinMessage(message) + if (self.permaMessage ~= nil and self.permaMessage.text ~= message) then + self.permaMessage = Message(self.scene, message, true) + end +end + +function MessageQueue:update(dt) + for _, message in ipairs(self.messages) do + message:update(dt) + end +end + +function MessageQueue:draw() + for _, message in ipairs(self.messages) do + message:draw() + end +end + +return MessageQueue \ No newline at end of file diff --git a/sonic-bluestreak.love/game/modules/messagequeue/message.lua b/sonic-bluestreak.love/game/modules/messagequeue/message.lua new file mode 100644 index 0000000..403141f --- /dev/null +++ b/sonic-bluestreak.love/game/modules/messagequeue/message.lua @@ -0,0 +1,42 @@ +local Message = Object:extend() +local TweenManager = require "birb.classes.time" + +local SPACING = 20 +local PLAYER_MESSAGE = 240 - 24 + +function Message:new(scene, message, isPinned) + self.message = message + self.scene = scene + assert(message ~= nil, "the message must be set") + self.isPinned = isPinned or false + self.opacity = 0 + self.y = 0 + + self.tweens = TweenManager(self) + self.tweens:newTween(0, 0.2, {opacity = 1}, "inOutCubic") + self.tweens:newTween(1, 0.2, {opacity = 0}, "inOutCubic") +end + +function Message:move() + self.tweens:newTween(0, 0.2, {y = self.y - SPACING}, "inOutCubic") +end + +function Message:update(dt) + self.tweens:update(dt) +end + +function Message:draw() + local yTransparency = math.max(0, math.min(1, (math.abs(self.y) - 32) / SPACING)) + local opacity = math.max(0, math.min(1, self.opacity - yTransparency)) + + love.graphics.setColor(0, 0, 0, 0.5 * opacity) + if (opacity > 0) then + love.graphics.rectangle("fill", 0, PLAYER_MESSAGE + self.y, 424, 16) + self.scene.assets.fonts["small"]:setColor(1, 1, 1, opacity) + self.scene.assets.fonts["small"]:draw(self.message, 424 / 2, PLAYER_MESSAGE - 1 + self.y, -1, "center") + self.scene.assets.fonts["small"]:setColor(1, 1, 1, 1) + end + utils.graphics.resetColor() +end + +return Message diff --git a/sonic-bluestreak.love/game/modules/playstyle/assets.lua b/sonic-bluestreak.love/game/modules/playstyle/assets.lua deleted file mode 100644 index 5614728..0000000 --- a/sonic-bluestreak.love/game/modules/playstyle/assets.lua +++ /dev/null @@ -1,29 +0,0 @@ -return { - ["textures"] = { - {"shadow", "assets/sprites/shadow.png"}, - {"e_power", "assets/gui/status/emblem_power.png"}, - {"e_fly", "assets/gui/status/emblem_technic.png"}, - {"e_speed", "assets/gui/status/emblem_speedster.png"}, - {"statusbar", "assets/gui/status/status_bar.png"}, - {"hudring", "assets/gui/hud/ring.png"} - }, - ["sprites"] = { - {"ring", "assets/sprites/items/ring"}, - {"ringweapon", "assets/sprites/items/ringweapon"}, - {"ringtoss", "assets/sprites/items/ringtoss"} - }, - ["imagefonts"] = { - {"menu", "assets/gui/fonts/SA2font"}, - {"numbers", "assets/gui/fonts/numbers"}, - {"smallnumbers", "assets/gui/fonts/smallnumbers"}, - }, - ["sfx"] = { - {"navigate", "assets/sfx/menu/select.wav"}, - {"confirm", "assets/sfx/menu/validate.wav"}, - {"cancel", "assets/sfx/menu/cancel.wav"}, - }, - ["tilesets"] = { - {"weapons", "assets/gui/status/weapons"}, - {"sptiles", "assets/backgrounds/specialtile"} - } -} diff --git a/sonic-bluestreak.love/game/modules/playstyle/pause.lua b/sonic-bluestreak.love/game/modules/playstyle/pause.lua deleted file mode 100644 index c679a61..0000000 --- a/sonic-bluestreak.love/game/modules/playstyle/pause.lua +++ /dev/null @@ -1,74 +0,0 @@ -local ListBox = require "core.modules.menusystem.listbox" -local PauseMenu = ListBox:extend() - -local Widget = require "core.modules.menusystem.widgets" - -local ResumeWidget = Widget.Text:extend() -local RestartWidget = Widget.Text:extend() -local ExitWidget = Widget.Text:extend() - -function PauseMenu:new(playstyle) - local height, width, x, y - height = 72 - width = 128 - x = 424/2 - width/2 - y = 240/2 - height/2 - - PauseMenu.super.new(self, playstyle.menusystem, "pauseMenu", x, y, width, height, 3) - self.playstyle = playstyle - - self:setSound(self.playstyle.assets.sfx["navigate"]) - self.isActive = false - self.isVisible = false - - local font = self.playstyle.assets.fonts["menu"] - - self.textbox = game.gui.newTextBox("basic", width+16, height+16) - - ResumeWidget(self, font) - RestartWidget(self, font) - ExitWidget(self, font) -end - -function PauseMenu:draw() - love.graphics.draw(self.textbox, self.x-8, self.y-8) - PauseMenu.super.draw(self) -end - ---- MENU WIDGETS - -function ResumeWidget:new(menu, font) - ResumeWidget.super.new(self, menu, font, "resume") -end - -function ResumeWidget:action() - self.menu.isActive = false - self.menu.isVisible = false - self.menu.playstyle.world.isActive = true - self.menu.playstyle.assets.isActive = true - self.menu.playstyle:flushKeys() -end - -function RestartWidget:new(menu, font) - ResumeWidget.super.new(self, menu, font, "restart") -end - -function RestartWidget:action() - self.menu.playstyle:restartLevel() - self.menu.isActive = false - self.menu.isVisible = false - self.menu.playstyle.world.isActive = true - self.menu.playstyle.assets.isActive = true - self.menu.playstyle:flushKeys() -end - -function ExitWidget:new(menu, font) - ExitWidget.super.new(self, menu, font, "exit") -end - -function ExitWidget:action() - self.menu.playstyle:exitLevel() -end - - -return PauseMenu diff --git a/sonic-bluestreak.love/game/modules/playstyle/init.lua b/sonic-bluestreak.love/game/modules/subgames/init.lua similarity index 62% rename from sonic-bluestreak.love/game/modules/playstyle/init.lua rename to sonic-bluestreak.love/game/modules/subgames/init.lua index e5d9775..1c383c3 100644 --- a/sonic-bluestreak.love/game/modules/playstyle/init.lua +++ b/sonic-bluestreak.love/game/modules/subgames/init.lua @@ -1,25 +1,22 @@ -Scene = require("core.modules.scenes") +local Scene = require("game.scenes") local PlayStyle = Scene:extend() -local PauseMenu = require("game.modules.playstyle.pause") -local TestWorld = require("game.modules.world.parent") - - -function PlayStyle:new(supportedLevels, missionfile, playerList) - local playerList = playerList or {"sonic"} +local PauseMenu = require("game.modules.subgames.pause") +local TestWorld = require("game.modules.subgames.world.parent") +function PlayStyle:new(supportedLevels, missionfile) PlayStyle.super.new(self) self.timer = 0 - self.assets:batchImport("game.modules.playstyle.assets") - self:loadMissionFile(supportedLevels, missionfile) + self.assets:batchImport("assets.subgames") + --self:loadMissionFile(supportedLevels, missionfile) PauseMenu(self) self:initWorld() self:initMission() - self:initCharacters(playerList) + self:initCharacters() - self:startLevel() + self.haveStarted = false end function PlayStyle:loadMissionFile(supportedLevels, missionfile) @@ -35,18 +32,9 @@ function PlayStyle:initMission() -- NOTHING end -function PlayStyle:initCharacters(characterList) - self.characterList = characterList - self.world:setPlayerNumber(#characterList) +function PlayStyle:initCharacters() + self.world:setPlayerNumber(1) self.world.cameras:setMode("split") - for i, characterName in ipairs(characterList) do - self:initCharacterRessources(characterName) - end -end - -function PlayStyle:initCharacterRessources(characterName) - local folder = "assets/sprites/characters/" - self.assets:addSprite(characterName, folder .. characterName) end function PlayStyle:getCharacterName(charID) @@ -54,7 +42,15 @@ function PlayStyle:getCharacterName(charID) end function PlayStyle:update(dt) - PlayStyle.super.update(self, dt) + if (self.haveStarted) then + PlayStyle.super.update(self, dt) + self:updatePauseMenus(dt) + else + self:startLevel() + end +end + +function PlayStyle:updatePauseMenus(dt) if self.menusystem.menus["pauseMenu"].isActive == false then self.timer = self.timer + dt end @@ -78,8 +74,9 @@ function PlayStyle:update(dt) end function PlayStyle:startLevel() + self.haveStarted = true self.world:loadMap() - self.assets:playMusic() + --self.assets:playMusic() end function PlayStyle:restartLevel() @@ -87,7 +84,7 @@ function PlayStyle:restartLevel() end function PlayStyle:exitLevel() - scenes.title() + scenes.menus.title() end return PlayStyle diff --git a/sonic-bluestreak.love/game/modules/subgames/pause.lua b/sonic-bluestreak.love/game/modules/subgames/pause.lua new file mode 100644 index 0000000..ecf113f --- /dev/null +++ b/sonic-bluestreak.love/game/modules/subgames/pause.lua @@ -0,0 +1,63 @@ +local RadianceListMenu = require "game.modules.menus.list" +local PauseMenu = RadianceListMenu.ListMenu:extend() + +local ResumeWidget = RadianceListMenu.DualTextWidget:extend() +local RestartWidget = RadianceListMenu.DualTextWidget:extend() +local ExitWidget = RadianceListMenu.DualTextWidget:extend() + +local WIDTH = 80 + +function PauseMenu:new(subgame) + local x, y + x = 424/2 - WIDTH/2 + y = 240/2 - (3*17)/2 + + PauseMenu.super.new(self, subgame, "pauseMenu", x, y, WIDTH, 3, true) + + self:setSound(self.scene.assets.sfx["navigate"]) + self.isActive = false + self.isVisible = false + + ResumeWidget(subgame) + self:setCancelWidget() + RestartWidget(subgame) + ExitWidget(subgame) +end + +--- MENU WIDGETS + +function ResumeWidget:new(scene) + ResumeWidget.super.new(self, scene, "pauseMenu", "Resume", "") +end + +function ResumeWidget:action() + self.menu.isActive = false + self.menu.isVisible = false + self.scene.world.isActive = true + self.scene.assets.isActive = true + self.scene:flushKeys() +end + +function RestartWidget:new(scene) + ResumeWidget.super.new(self, scene, "pauseMenu", "Restart", "") +end + +function RestartWidget:action() + self.scene:restartLevel() + self.menu.isActive = false + self.menu.isVisible = false + self.scene.world.isActive = true + self.scene.assets.isActive = true + self.scene:flushKeys() +end + +function ExitWidget:new(scene) + ExitWidget.super.new(self, scene, "pauseMenu", "Exit", "") +end + +function ExitWidget:action() + self.scene:exitLevel() +end + + +return PauseMenu diff --git a/sonic-bluestreak.love/game/modules/world/actors/collisions/fakefloor.lua b/sonic-bluestreak.love/game/modules/subgames/world/actors/collisions/fakefloor.lua similarity index 92% rename from sonic-bluestreak.love/game/modules/world/actors/collisions/fakefloor.lua rename to sonic-bluestreak.love/game/modules/subgames/world/actors/collisions/fakefloor.lua index 49f2402..23176e1 100644 --- a/sonic-bluestreak.love/game/modules/world/actors/collisions/fakefloor.lua +++ b/sonic-bluestreak.love/game/modules/subgames/world/actors/collisions/fakefloor.lua @@ -1,4 +1,4 @@ -local Base = require "core.modules.world.actors.actor3D" +local Base = require "birb.modules.world.actors.actor3D" local FakeFloor = Base:extend() function FakeFloor:new(world, x, y, z, w, h, d) diff --git a/sonic-bluestreak.love/game/modules/world/actors/collisions/floor.lua b/sonic-bluestreak.love/game/modules/subgames/world/actors/collisions/floor.lua similarity index 91% rename from sonic-bluestreak.love/game/modules/world/actors/collisions/floor.lua rename to sonic-bluestreak.love/game/modules/subgames/world/actors/collisions/floor.lua index a2cf4ca..d396ceb 100644 --- a/sonic-bluestreak.love/game/modules/world/actors/collisions/floor.lua +++ b/sonic-bluestreak.love/game/modules/subgames/world/actors/collisions/floor.lua @@ -1,4 +1,4 @@ -local Base = require "core.modules.world.actors.actor3D" +local Base = require "birb.modules.world.actors.actor3D" local Floor = Base:extend() function Floor:new(world, x, y, z, w, h, d) diff --git a/sonic-bluestreak.love/game/modules/world/actors/collisions/invisible.lua b/sonic-bluestreak.love/game/modules/subgames/world/actors/collisions/invisible.lua similarity index 80% rename from sonic-bluestreak.love/game/modules/world/actors/collisions/invisible.lua rename to sonic-bluestreak.love/game/modules/subgames/world/actors/collisions/invisible.lua index 82fee54..265f45d 100644 --- a/sonic-bluestreak.love/game/modules/world/actors/collisions/invisible.lua +++ b/sonic-bluestreak.love/game/modules/subgames/world/actors/collisions/invisible.lua @@ -1,4 +1,4 @@ -local Base = require "core.modules.world.actors.actor3D" +local Base = require "birb.modules.world.actors.actor3D" local Invisible = Base:extend() function Invisible:new(world, x, y, z, w, h, d) diff --git a/sonic-bluestreak.love/game/modules/world/actors/collisions/textured.lua b/sonic-bluestreak.love/game/modules/subgames/world/actors/collisions/textured.lua similarity index 83% rename from sonic-bluestreak.love/game/modules/world/actors/collisions/textured.lua rename to sonic-bluestreak.love/game/modules/subgames/world/actors/collisions/textured.lua index 000bc4e..5917edb 100644 --- a/sonic-bluestreak.love/game/modules/world/actors/collisions/textured.lua +++ b/sonic-bluestreak.love/game/modules/subgames/world/actors/collisions/textured.lua @@ -1,4 +1,4 @@ -local Base = require "core.modules.world.actors.actor3D" +local Base = require "birb.modules.world.actors.actor3D" local Textured = Base:extend() function Textured:new(world, x, y, z, w, h, d, top, bottom) diff --git a/sonic-bluestreak.love/game/modules/world/actors/collisions/wall.lua b/sonic-bluestreak.love/game/modules/subgames/world/actors/collisions/wall.lua similarity index 80% rename from sonic-bluestreak.love/game/modules/world/actors/collisions/wall.lua rename to sonic-bluestreak.love/game/modules/subgames/world/actors/collisions/wall.lua index c1aba12..6fb1280 100644 --- a/sonic-bluestreak.love/game/modules/world/actors/collisions/wall.lua +++ b/sonic-bluestreak.love/game/modules/subgames/world/actors/collisions/wall.lua @@ -1,4 +1,4 @@ -local Base = require "core.modules.world.actors.actor3D" +local Base = require "birb.modules.world.actors.actor3D" local Wall = Base:extend() function Wall:new(world, x, y, z, w, h, d) diff --git a/sonic-bluestreak.love/game/modules/subgames/world/actors/ennemies/motobug.lua b/sonic-bluestreak.love/game/modules/subgames/world/actors/ennemies/motobug.lua new file mode 100644 index 0000000..ad97082 --- /dev/null +++ b/sonic-bluestreak.love/game/modules/subgames/world/actors/ennemies/motobug.lua @@ -0,0 +1,6 @@ +local Parent = require "game.modules.subgames.world.actors.ennemies.parent" +local Motobug = Parent:extend() + + + +return Motobug diff --git a/sonic-bluestreak.love/game/modules/world/actors/ennemies/parent.lua b/sonic-bluestreak.love/game/modules/subgames/world/actors/ennemies/parent.lua similarity index 83% rename from sonic-bluestreak.love/game/modules/world/actors/ennemies/parent.lua rename to sonic-bluestreak.love/game/modules/subgames/world/actors/ennemies/parent.lua index 11347c0..ad39146 100644 --- a/sonic-bluestreak.love/game/modules/world/actors/ennemies/parent.lua +++ b/sonic-bluestreak.love/game/modules/subgames/world/actors/ennemies/parent.lua @@ -1,4 +1,4 @@ -local Parent = require "game.modules.world.actors.parent" +local Parent = require "game.modules.subgames.world.actors.parent" local EnnemyParent = Parent:extend() function EnnemyParent:new(world, x, y, z, w, h, d) diff --git a/sonic-bluestreak.love/game/modules/world/actors/init.lua b/sonic-bluestreak.love/game/modules/subgames/world/actors/init.lua similarity index 100% rename from sonic-bluestreak.love/game/modules/world/actors/init.lua rename to sonic-bluestreak.love/game/modules/subgames/world/actors/init.lua diff --git a/sonic-bluestreak.love/game/modules/world/actors/items/collectible.lua b/sonic-bluestreak.love/game/modules/subgames/world/actors/items/collectible.lua similarity index 78% rename from sonic-bluestreak.love/game/modules/world/actors/items/collectible.lua rename to sonic-bluestreak.love/game/modules/subgames/world/actors/items/collectible.lua index c09c971..a977081 100644 --- a/sonic-bluestreak.love/game/modules/world/actors/items/collectible.lua +++ b/sonic-bluestreak.love/game/modules/subgames/world/actors/items/collectible.lua @@ -1,4 +1,4 @@ -local Parent = require "game.modules.world.actors.parent" +local Parent = require "game.modules.subgames.world.actors.parent" local Collectible = Parent:extend() function Collectible:new(world, x, y, z, w, h, d) diff --git a/sonic-bluestreak.love/game/modules/world/actors/items/ring.lua b/sonic-bluestreak.love/game/modules/subgames/world/actors/items/ring.lua similarity index 100% rename from sonic-bluestreak.love/game/modules/world/actors/items/ring.lua rename to sonic-bluestreak.love/game/modules/subgames/world/actors/items/ring.lua diff --git a/sonic-bluestreak.love/game/modules/world/actors/parent.lua b/sonic-bluestreak.love/game/modules/subgames/world/actors/parent.lua similarity index 94% rename from sonic-bluestreak.love/game/modules/world/actors/parent.lua rename to sonic-bluestreak.love/game/modules/subgames/world/actors/parent.lua index 87132fc..5a9c759 100644 --- a/sonic-bluestreak.love/game/modules/world/actors/parent.lua +++ b/sonic-bluestreak.love/game/modules/subgames/world/actors/parent.lua @@ -1,4 +1,4 @@ -local Base = require "core.modules.world.actors.actor3D" +local Base = require "birb.modules.world.actors.actor3D" local Parent = Base:extend() function Parent:new(world, type, x, y, z, w, h, d, isSolid) diff --git a/sonic-bluestreak.love/game/modules/subgames/world/actors/player/init.lua b/sonic-bluestreak.love/game/modules/subgames/world/actors/player/init.lua new file mode 100644 index 0000000..e94f56a --- /dev/null +++ b/sonic-bluestreak.love/game/modules/subgames/world/actors/player/init.lua @@ -0,0 +1,146 @@ +local cwd = (...):gsub('%.player$', '') .. "." +local Parent = require(cwd .. "parent") +local Player = Parent:extend() + +local Emblem = require "game.modules.gui.emblem" + +local Weapons = require(cwd .. "player.weapons") + +function Player:new(world, x, y, z, id) + Player.super.new(self, world, "player", x, y, 0, 16, 12, 24, true) + self:setGravity(480*2) + + self:initPlayer() + + self.weapons = Weapons(self) + + self.action = "normal" + + self.rings = 0 + self.score = 0 +end + +function Player:initPlayer() + self.charName = game.characters:getActiveCharacter() + self.assets:addSprite(self.charName, "datas/gamedata/characters/" .. self.charName .. "/sprites") + self:setSprite(self.charName, true, 8, 10) + + self.emblem = Emblem(game.characters:getActiveCharacterData(), self.scene) + self.guiborder = game.gui.newBorder(424, 20, 6) +end + +function Player:updateStart(dt) + self.xfrc, self.yfrc = 480*3, 480*3 + + self:basicMovements() + + if self.keys["A"].isPressed and (self.onGround) then + self.zsp = 280*1.33 + end + + if self.keys["B"].isPressed then + self.weapons:shoot(self.x, self.y+1, self.z+8, 1) + end +end + +function Player:basicMovements() + local xsp, ysp = 0, 0 + local speed = 160 + if self.keys["up"].isDown then + ysp = -1 + end + if self.keys["down"].isDown then + ysp = 1 + end + if (self.world.autorun == true) then + xsp = 1 + else + if self.keys["left"].isDown then + xsp = -1 + end + if self.keys["right"].isDown then + xsp = 1 + end + end + + if (xsp ~= 0 or ysp ~= 0) then + local angle = utils.math.pointDirection(0, 0, xsp, ysp) + self.xsp, self.ysp = utils.math.lengthdir(160, angle) + end +end + +function Player:collisionResponse(collision) + if collision.other.type == "collectible" then + collision.other.owner:getPicked(self) + end +end + +function Player:animationEnded(name) + +end + +function Player:updateEnd(dt) + self:setAnimation() +end + +function Player:setAnimation() + local gsp = utils.math.pointDistance(0, 0, self.xsp, self.ysp) + self.sprite:setCustomSpeed(math.abs(gsp) / 12) + self:setDirection(self.xsp) + if (self.action == "punching") then + --the animation system is already active + else + if (self.onGround) then + if (math.abs(self.xsp) > 0) or (math.abs(self.ysp) > 0) then + self.sprite:changeAnimation("walk", false) + else + self.sprite:changeAnimation("idle", false) + end + else + if (self.zsp) > 0 then + self.sprite:changeAnimation("jump", false) + else + self.sprite:changeAnimation("fall", false) + end + end + end +end + +function Player:setDirection(direction) + direction = direction or 0 + if direction ~= 0 then + direction = utils.math.sign(direction) + self.direction = direction + self.sprite:setScallingX(direction) + end +end + +function Player:getViewCenter() + local x, y = Player.super.getViewCenter(self) + return x, y-16 +end + +function Player:draw() + Player.super.draw(self) +end + +function Player:drawHUD(id) + love.graphics.draw(self.guiborder, 0, 20, 0, 1, -1) + self.emblem:draw(424 - 40, 12) +end + +function Player:setRing(value, isRelative) + if (isRelative == false) then + self.rings = 0 + end + self.rings = self.rings + value +end + +function Player:setScore(value, isRelative) + if (isRelative == false) then + self.score = 0 + end + self.score = self.score + value +end + +return Player diff --git a/sonic-bluestreak.love/game/modules/world/actors/player/weapons.lua b/sonic-bluestreak.love/game/modules/subgames/world/actors/player/weapons.lua similarity index 82% rename from sonic-bluestreak.love/game/modules/world/actors/player/weapons.lua rename to sonic-bluestreak.love/game/modules/subgames/world/actors/player/weapons.lua index 8c972e4..5561d33 100644 --- a/sonic-bluestreak.love/game/modules/world/actors/player/weapons.lua +++ b/sonic-bluestreak.love/game/modules/subgames/world/actors/player/weapons.lua @@ -10,12 +10,12 @@ end function WeaponManager:switch(newWeapon) if (weaponList[newWeapon] ~= nil) then self.currentWeapon = newWeapon; - self.player.statusbar:setWeapon(self.currentWeapon); + --self.player.statusbar:setWeapon(self.currentWeapon); end end function WeaponManager:shoot(x, y, z, dir) - weaponData = weaponList[self.currentWeapon] + local weaponData = weaponList[self.currentWeapon] for i,coord in ipairs(weaponData.launch) do self.player.obj.Weapon(self.player.world, x + coord[1], y + coord[2], z + coord[3], dir, weaponData) diff --git a/sonic-bluestreak.love/game/modules/world/actors/weapons/parent.lua b/sonic-bluestreak.love/game/modules/subgames/world/actors/weapons/parent.lua similarity index 76% rename from sonic-bluestreak.love/game/modules/world/actors/weapons/parent.lua rename to sonic-bluestreak.love/game/modules/subgames/world/actors/weapons/parent.lua index c858973..de10a1d 100644 --- a/sonic-bluestreak.love/game/modules/world/actors/weapons/parent.lua +++ b/sonic-bluestreak.love/game/modules/subgames/world/actors/weapons/parent.lua @@ -1,4 +1,4 @@ -local Parent = require "game.modules.world.actors.parent" +local Parent = require "game.modules.subgames.world.actors.parent" local WeaponShot = Parent:extend() function WeaponShot:new(world, x, y, z, direction, data) @@ -7,17 +7,19 @@ function WeaponShot:new(world, x, y, z, direction, data) self.direction = direction self.data = data self.zsp = self.data.zspeed - self.xsp = self.data.xspeed * direction + self.xsp = (self.data.xspeed * direction) self.xfrc, self.yfrc = 0, 0 if (self.zsp ~= 0) then self:setGravity(480*2) end + print(self.xsp) end function WeaponShot:updateStart(dt) - if (self.xsp == 0) then - self:destroy() - end + print(self.xsp) + -- if (self.xsp == 0) then + -- self:destroy() + -- end end function WeaponShot:draw() @@ -26,7 +28,7 @@ function WeaponShot:draw() love.graphics.setColor(self.data.color[1], self.data.color[2], self.data.color[3], 0.6) local x, y = self.x + self.y/2 + 8, self.y - self.z - 3 local angle = utils.math.pointDirection(0, 0, self.xsp, self.zsp * -1) - self.scene.assets.sprites["ringtoss"]:drawAnimation(x, y, angle) + self.scene.assets.sprites["ringtoss"]:draw(x, y, angle) love.graphics.setColor(1, 1, 1, 1) end diff --git a/sonic-bluestreak.love/game/modules/world/battle.lua b/sonic-bluestreak.love/game/modules/subgames/world/battle.lua similarity index 73% rename from sonic-bluestreak.love/game/modules/world/battle.lua rename to sonic-bluestreak.love/game/modules/subgames/world/battle.lua index 183f74a..162008a 100644 --- a/sonic-bluestreak.love/game/modules/world/battle.lua +++ b/sonic-bluestreak.love/game/modules/subgames/world/battle.lua @@ -1,7 +1,7 @@ -local ParentWorld = require "game.modules.world.parent" +local ParentWorld = require "game.modules.subgames.world.parent" local BattleWorld = ParentWorld:extend() -local customMap = require "game.modules.world.maps" +local customMap = require "game.modules.subgames.world.maps" function BattleWorld:new(scene, mapname) local mappath = game.utils.getMapPath("battle", mapname) diff --git a/sonic-bluestreak.love/game/modules/world/maps/battle.lua b/sonic-bluestreak.love/game/modules/subgames/world/maps/battle.lua similarity index 96% rename from sonic-bluestreak.love/game/modules/world/maps/battle.lua rename to sonic-bluestreak.love/game/modules/subgames/world/maps/battle.lua index 3aacc2d..ad33b78 100644 --- a/sonic-bluestreak.love/game/modules/world/maps/battle.lua +++ b/sonic-bluestreak.love/game/modules/subgames/world/maps/battle.lua @@ -1,9 +1,9 @@ -local BaseMap = require "core.modules.world.maps.parent" +local BaseMap = require "birb.modules.world.maps.parent" local BattleMap = BaseMap:extend() function BattleMap:new(world, maptype, mapname) BattleMap.super.new(self, world) - self:setPadding(0, 128, 0, 20) + self:setPadding(0, 128, 0, 0) self.directory = game.utils.getMapDirectory(maptype, mapname) self.mappath = game.utils.getMapPath(maptype, mapname) diff --git a/sonic-bluestreak.love/game/modules/subgames/world/maps/init.lua b/sonic-bluestreak.love/game/modules/subgames/world/maps/init.lua new file mode 100644 index 0000000..e3a6577 --- /dev/null +++ b/sonic-bluestreak.love/game/modules/subgames/world/maps/init.lua @@ -0,0 +1,7 @@ +local customMap = {} + +customMap.Test = require "game.modules.subgames.world.maps.test" +customMap.Battle = require "game.modules.subgames.world.maps.battle" +customMap.Shoot = require "game.modules.subgames.world.maps.shoot" + +return customMap diff --git a/sonic-bluestreak.love/game/modules/world/maps/shoot.lua b/sonic-bluestreak.love/game/modules/subgames/world/maps/shoot.lua similarity index 59% rename from sonic-bluestreak.love/game/modules/world/maps/shoot.lua rename to sonic-bluestreak.love/game/modules/subgames/world/maps/shoot.lua index e05d1f4..3e57f60 100644 --- a/sonic-bluestreak.love/game/modules/world/maps/shoot.lua +++ b/sonic-bluestreak.love/game/modules/subgames/world/maps/shoot.lua @@ -1,19 +1,20 @@ -local BaseMap = require "core.modules.world.maps.parent" +local BaseMap = require "birb.modules.world.maps.parent" local ShootMap = BaseMap:extend() local TILESIZE = 31 local TESTZONE = "forest" -local zoneDatas = require "datas.gamedata.maps.shoot.zones" +local zoneDatas = require "datas.gamedata.maps.shoot.zones" +local Background = require "game.modules.drawing.parallaxBackground" -local Chunk = require "game.modules.world.maps.tools.chunk" +local Chunk = require "game.modules.subgames.world.maps.tools.chunk" function ShootMap:new(world, maptype, mapname) ShootMap.super.new(self, world) self:setPadding(0, 0, 0, 0) self:getLevelData(mapname) - self:generateTextures(self.datas.tiles, self.datas.background) + self.parallaxBackground = Background(world.scene, 5, 1, self.datas.background) self.layout = {} self.chunklist = {} @@ -26,7 +27,7 @@ function ShootMap:updateWidth() end function ShootMap:getLevelData(mapname) - local file = file or "testlevel.test1" + local file = mapname or "testlevel.test1" local level = require("datas.gamedata.maps.shoot." .. file) self.zone = level.datas.zone @@ -137,7 +138,7 @@ function ShootMap:addBlock(x, y, w, h, top, bottom) end function ShootMap:getDimensions() - return self.width, 100 + return 3000, 100 end function ShootMap:loadPlayers() @@ -148,107 +149,12 @@ function ShootMap:loadActors() -- Empty Placeholder function end -function ShootMap:generateTextures(tile, background) - - self.texture = {} - self.texture.floor = self:generateFloor(tile) - self.texture.border = love.graphics.newImage("assets/backgrounds/borders.png") - self.quads = {} - local w, h = self.texture.border:getDimensions() - self.quads.borders = love.graphics.newQuad(0, tile*10, 80, 10, w, h) - - self:addParallax(background) -end - -function ShootMap:generateFloor(tile) - local canvas = love.graphics.newCanvas(31*16, 100) - local tile = tile or 1 - - local tileTexture = love.graphics.newImage("assets/backgrounds/normaltile.png") - local tileQuad = {} - local w, h = tileTexture:getDimensions() - tileQuad[1] = love.graphics.newQuad( 0, tile*24, 40, 24, w, h) - tileQuad[2] = love.graphics.newQuad(40, tile*24, 40, 24, w, h) - - love.graphics.setCanvas( canvas ) - - for i=1, 5 do - for j=0, 18 do - local tiley = (i-1)*20 - 4 - local tilex = (j-2)*31 + (i-1)*10 - local variant = 1 + ((i + j) % 2) - love.graphics.draw(tileTexture, tileQuad[variant], tilex, tiley) - end - end - - love.graphics.setCanvas( ) - - local imagedata = canvas:newImageData() - local texture = love.graphics.newImage( imagedata ) - imagedata:release() - canvas:release() - return texture -end - function ShootMap:draw(x, y, w, h) self:drawChunks(x) end -function ShootMap:addParallax(filename) - -- Empty Placeholder function - local filename = filename or "forest" - local backfolder = "assets/backgrounds/parallax/" - filename = backfolder .. filename - self.texture.back1 = love.graphics.newImage(filename .. "-back.png") - self.texture.back2 = love.graphics.newImage(filename .. "-fore.png") -end - function ShootMap:drawParallax(x, y, w, h) - - self:drawBackground(x, y, w, h) - self:drawForeground(x, y + 10, w, h) - local w2, _ = self.texture.floor:getDimensions() - for i=1, 2 do - local x2 = x % w2 - love.graphics.draw(self.texture.floor, ((i-1)*31*16)-x2, -y) - end - - self:drawBorder(x, y + 10) - self:drawBorder(x, y - 100) -end - -function ShootMap:drawBackground(x, y, w, h) - local w2, h2 = self.texture.back1:getDimensions() - local imax = math.ceil(w / w2) + 1 - for i=1, imax do - local x1 = (x / 5) % w2 - love.graphics.draw(self.texture.back1, (i-1)*w2 - x1, 0, 0, 1, 1, 0, 0) - end -end - -function ShootMap:drawForeground(x, y, w, h) - local w2, h2 = self.texture.back2:getDimensions() - local imax = math.ceil(w / w2) + 1 - for i=1, imax do - local x1 = (x / 2) % w2 - love.graphics.draw(self.texture.back2, (i-1)*w2 - x1, -y, 0, 1, 1, 0, h2) - end -end - -function ShootMap:drawBorder(x, y) - for i=1, 7 do - local x2 = x % 80 - love.graphics.draw(self.texture.border, self.quads.borders, (i-1)*80 - x2, -y, 0, 1, 1) - end -end - -function ShootMap:drawCliff(x, y, w, h) - local w2, h2 = self.texture.cliff:getDimensions() - local imax = math.ceil(w / w2) + 1 - for i=1, imax do - local x1 = (x) % w2 - love.graphics.draw(self.texture.cliff, (i-1)*w2 - x1, -y, 0, 1, 1, 0, 0) - end + self.parallaxBackground:drawParallax(x, y, w, h) end function ShootMap:drawChunks(x) diff --git a/sonic-bluestreak.love/game/modules/subgames/world/maps/test.lua b/sonic-bluestreak.love/game/modules/subgames/world/maps/test.lua new file mode 100644 index 0000000..e38faa4 --- /dev/null +++ b/sonic-bluestreak.love/game/modules/subgames/world/maps/test.lua @@ -0,0 +1,48 @@ +local BaseMap = require "birb.modules.world.maps.parent" +local TestMap = BaseMap:extend() + +function TestMap:new(world) + TestMap.super.new(self, world) + self:setPadding(0, 96, 0, 0) + + self.background = love.graphics.newImage("assets/backgrounds/parallax/test-back.png") +end + +function TestMap:loadCollisions() + self.world:newCollision("wall", 0, 0, -16, 8*64, 8*32, 16) + self.world:newCollision("wall", 64*1, 32*1, 0, 64*1, 32*3, 48) + self.world:newCollision("wall", 64*4, 32*1, 0, 64*3, 32*1, 48) + self.world:newCollision("wall", 64*6, 32*4, 0, 64*1, 32*3, 48) + self.world:newCollision("wall", 64*1, 32*6, 0, 64*3, 32*1, 48) +end + +function TestMap:getDimensions() + return 8*64, 8*32 +end + +function TestMap:loadPlayers() + self.world:addPlayer(16, 16, 0, 1) +end + +function TestMap:loadActors() + -- Empty Placeholder function +end + +function TestMap:draw() + -- Empty Placeholder function +end + +function TestMap:drawParallax(x, y, w, h) + local imax, jmax = (w/32)+1, (h/32)+1 + local x, y = x or 0, y or 0 + local x = math.floor(x/4) % 32 + local y = math.floor((y+96)/6) % 32 + + for i=0, math.ceil(imax) do + for j=0, math.ceil(jmax) do + love.graphics.draw(self.background, (i-1)*32-x, (j-1)*32-y) + end + end +end + +return TestMap diff --git a/sonic-bluestreak.love/game/modules/world/maps/tools/chunk.lua b/sonic-bluestreak.love/game/modules/subgames/world/maps/tools/chunk.lua similarity index 97% rename from sonic-bluestreak.love/game/modules/world/maps/tools/chunk.lua rename to sonic-bluestreak.love/game/modules/subgames/world/maps/tools/chunk.lua index a254eef..963bbca 100644 --- a/sonic-bluestreak.love/game/modules/world/maps/tools/chunk.lua +++ b/sonic-bluestreak.love/game/modules/subgames/world/maps/tools/chunk.lua @@ -1,5 +1,5 @@ local Chunk = Object:extend() -local ChunkTerrain = require "game.modules.world.maps.tools.chunkterrain" +local ChunkTerrain = require "game.modules.subgames.world.maps.tools.chunkterrain" function Chunk:new(map, data) self.map = map diff --git a/sonic-bluestreak.love/game/modules/world/maps/tools/chunkterrain.lua b/sonic-bluestreak.love/game/modules/subgames/world/maps/tools/chunkterrain.lua similarity index 100% rename from sonic-bluestreak.love/game/modules/world/maps/tools/chunkterrain.lua rename to sonic-bluestreak.love/game/modules/subgames/world/maps/tools/chunkterrain.lua diff --git a/sonic-bluestreak.love/game/modules/world/parent.lua b/sonic-bluestreak.love/game/modules/subgames/world/parent.lua similarity index 88% rename from sonic-bluestreak.love/game/modules/world/parent.lua rename to sonic-bluestreak.love/game/modules/subgames/world/parent.lua index 724f59d..3bf246f 100644 --- a/sonic-bluestreak.love/game/modules/world/parent.lua +++ b/sonic-bluestreak.love/game/modules/subgames/world/parent.lua @@ -1,13 +1,13 @@ -local World3D = require "core.modules.world.world3D" +local World3D = require "birb.modules.world.world3D" local ParentWorld = World3D:extend() -local customMap = require "game.modules.world.maps" +local customMap = require "game.modules.subgames.world.maps" function ParentWorld:new(scene, maptype, mapname) local mappath = game.utils.getMapPath("test", "test") self.customMap = customMap - ParentWorld.super.new(self, scene, "game.modules.world.actors", mappath, maptype) + ParentWorld.super.new(self, scene, "game.modules.subgames.world.actors", mappath, maptype) self.mapname = mapname self.autorun = false @@ -28,7 +28,6 @@ end function ParentWorld:addInvisibleWalls() local w, h = self:getDimensions() - print(w, h) self.obj.collisions["invisible"](self, 0, -16, 0, w, 16, 1000) self.obj.collisions["invisible"](self, 0, h, 0, w, 16, 1000) self.obj.collisions["invisible"](self, w, 0, 0, 16, h, 1000) diff --git a/sonic-bluestreak.love/game/modules/world/shoot.lua b/sonic-bluestreak.love/game/modules/subgames/world/shoot.lua similarity index 78% rename from sonic-bluestreak.love/game/modules/world/shoot.lua rename to sonic-bluestreak.love/game/modules/subgames/world/shoot.lua index 63a692c..4c62f79 100644 --- a/sonic-bluestreak.love/game/modules/world/shoot.lua +++ b/sonic-bluestreak.love/game/modules/subgames/world/shoot.lua @@ -1,7 +1,7 @@ -local ParentWorld = require "game.modules.world.parent" +local ParentWorld = require "game.modules.subgames.world.parent" local ShootWorld = ParentWorld:extend() -local customMap = require "game.modules.world.maps" +local customMap = require "game.modules.subgames.world.maps" function ShootWorld:new(scene, mapname) local mappath = game.utils.getMapPath("shoot", mapname) diff --git a/sonic-bluestreak.love/game/modules/transitions/eggman.lua b/sonic-bluestreak.love/game/modules/transitions/eggman.lua new file mode 100644 index 0000000..c8506c3 --- /dev/null +++ b/sonic-bluestreak.love/game/modules/transitions/eggman.lua @@ -0,0 +1,8 @@ +local DecalTransition = require "birb.modules.transitions.decal" +local EggmanTransition = DecalTransition:extend() + +function EggmanTransition:new(func, ox, oy, fadeOut) + EggmanTransition.super.new(self, func, ox, oy, fadeOut, "eggdecal") +end + +return EggmanTransition \ No newline at end of file diff --git a/sonic-bluestreak.love/game/modules/transitions/init.lua b/sonic-bluestreak.love/game/modules/transitions/init.lua new file mode 100644 index 0000000..6aa01a5 --- /dev/null +++ b/sonic-bluestreak.love/game/modules/transitions/init.lua @@ -0,0 +1,5 @@ +return { + sonic = require "game.modules.transitions.sonic", + eggman = require "game.modules.transitions.eggman", + borders = require "game.modules.transitions.zigzag", +} \ No newline at end of file diff --git a/sonic-bluestreak.love/game/modules/transitions/sonic.lua b/sonic-bluestreak.love/game/modules/transitions/sonic.lua new file mode 100644 index 0000000..0450fe2 --- /dev/null +++ b/sonic-bluestreak.love/game/modules/transitions/sonic.lua @@ -0,0 +1,8 @@ +local DecalTransition = require "birb.modules.transitions.decal" +local SonicTransition = DecalTransition:extend() + +function SonicTransition:new(func, ox, oy, fadeOut) + SonicTransition.super.new(self, func, ox, oy, fadeOut, "sonicdecal") +end + +return SonicTransition \ No newline at end of file diff --git a/sonic-bluestreak.love/game/modules/transitions/zigzag.lua b/sonic-bluestreak.love/game/modules/transitions/zigzag.lua new file mode 100644 index 0000000..ce41244 --- /dev/null +++ b/sonic-bluestreak.love/game/modules/transitions/zigzag.lua @@ -0,0 +1,41 @@ +local CanvasTransition = require "birb.modules.transitions.canvas" +local ZigZagTransition = CanvasTransition:extend() + +function ZigZagTransition:new(func, ox, oy, fadeOut) + self.offset = 0 + ZigZagTransition.super.new(self, func, ox, oy, fadeOut, "inQuad", "outQuad", 1, 0.1) + +end + +function ZigZagTransition:loadResources() + self.border = love.graphics.newImage("assets/transitions/border.png") +end + +function ZigZagTransition:drawCanvas(dt) + local w, _ = self.border:getDimensions() + self.offset = (self.offset + (dt * 256)) % w + utils.graphics.resetColor() + love.graphics.rectangle("fill", 0, 0, 424, 240) + love.graphics.setColor(0,0,0,1) + local max = 120 + 16 + self:drawBorder(0 + max * (self.value), false) + utils.graphics.resetColor() + self:drawBorder(240 - max * (self.value), true) +end + +function ZigZagTransition:drawBorder(y, reversed) + local offset = self.offset + local sy = 1 + if (reversed) then + offset = self.offset * -1 + sy = -1 + end + local w, h = self.border:getDimensions() + local ox, oy = 0, h + for i = -1, math.ceil(424 / w), 1 do + love.graphics.draw(self.border,(i * w) + offset,y,0,1,sy,ox,oy) + end + +end + +return ZigZagTransition \ No newline at end of file diff --git a/sonic-bluestreak.love/game/modules/tweenmanager/init.lua b/sonic-bluestreak.love/game/modules/tweenmanager/init.lua deleted file mode 100644 index 8bd7794..0000000 --- a/sonic-bluestreak.love/game/modules/tweenmanager/init.lua +++ /dev/null @@ -1,88 +0,0 @@ -local TweenManager = Object:extend() - -local tween = require "game.modules.tweenmanager.libs.tween" -local Timer = require "core.modules.world.actors.utils.timer" - -function TweenManager:new(subject) - self.subject = subject - self.time = 0 - - self.tweens = {} - self.switches = {} - - self.timers = {} -end - -function TweenManager:newTween(start, duration, target, easing) - local newTween = {} - -- we add the data into a tween wrapper - newTween.tween = tween.new(duration, self.subject, target, easing) - newTween.start = self.time + start -- /!\ START IS RELATIVE TO CURRENT TIME - newTween.clear = newTween.start + duration - - table.insert(self.tweens, newTween) -end - -function TweenManager:newTimer(start, name) - self.timers[name] = Timer(self, name, start) -end - -function TweenManager:newSwitch(start, bools) - local newSwitch = {} - -- we add the data into a tween wrapper - newSwitch.bools = bools - newSwitch.start = self.time + start -- /!\ START IS RELATIVE TO CURRENT TIME - newSwitch.clear = newSwitch.start + 1 - - table.insert(self.switches, newSwitch) -end - -function TweenManager:update(dt) - self.time = self.time + dt - - for i, tweenWrapper in ipairs(self.tweens) do - if (self.time > tweenWrapper.start) then - tweenWrapper.tween:update(dt) - end - end - - for i, switch in ipairs(self.switches) do - if (self.time > switch.start) then - -- We test each boolean in the switch - for i, bool in ipairs(switch.bools) do - -- if it's nil, we set it to true - if self.subject[bool] == nil then - self.subject[bool] = true - else - -- if it's not nil, we reverse the boolean - self.subject[bool] = (self.subject[bool] == false) - end - end - table.remove(self.switches, i) - end - end - - for k, timer in pairs(self.timers) do - timer:update(dt) - end - - self:clearEndedTweens() -end - -function TweenManager:timerResponse(timername) - if self.subject.timerResponse == nil then - core.debug:warning("tweenmanager", "the subject have no timerResponse function") - return 0 - end - self.subject:timerResponse(timername) -end - -function TweenManager:clearEndedTweens(dt) - for i, tweenWrapper in ipairs(self.tweens) do - if (self.time > tweenWrapper.clear) then - table.remove(self.tweens, i) - end - end -end - -return TweenManager diff --git a/sonic-bluestreak.love/game/modules/tweenmanager/libs/tween.lua b/sonic-bluestreak.love/game/modules/tweenmanager/libs/tween.lua deleted file mode 100644 index 4f2c681..0000000 --- a/sonic-bluestreak.love/game/modules/tweenmanager/libs/tween.lua +++ /dev/null @@ -1,367 +0,0 @@ -local tween = { - _VERSION = 'tween 2.1.1', - _DESCRIPTION = 'tweening for lua', - _URL = 'https://github.com/kikito/tween.lua', - _LICENSE = [[ - MIT LICENSE - - Copyright (c) 2014 Enrique García Cota, Yuichi Tateno, Emmanuel Oga - - 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. - ]] -} - --- easing - --- Adapted from https://github.com/EmmanuelOga/easing. See LICENSE.txt for credits. --- For all easing functions: --- t = time == how much time has to pass for the tweening to complete --- b = begin == starting property value --- c = change == ending - beginning --- d = duration == running time. How much time has passed *right now* - -local pow, sin, cos, pi, sqrt, abs, asin = math.pow, math.sin, math.cos, math.pi, math.sqrt, math.abs, math.asin - --- linear -local function linear(t, b, c, d) return c * t / d + b end - --- quad -local function inQuad(t, b, c, d) return c * pow(t / d, 2) + b end -local function outQuad(t, b, c, d) - t = t / d - return -c * t * (t - 2) + b -end -local function inOutQuad(t, b, c, d) - t = t / d * 2 - if t < 1 then return c / 2 * pow(t, 2) + b end - return -c / 2 * ((t - 1) * (t - 3) - 1) + b -end -local function outInQuad(t, b, c, d) - if t < d / 2 then return outQuad(t * 2, b, c / 2, d) end - return inQuad((t * 2) - d, b + c / 2, c / 2, d) -end - --- cubic -local function inCubic (t, b, c, d) return c * pow(t / d, 3) + b end -local function outCubic(t, b, c, d) return c * (pow(t / d - 1, 3) + 1) + b end -local function inOutCubic(t, b, c, d) - t = t / d * 2 - if t < 1 then return c / 2 * t * t * t + b end - t = t - 2 - return c / 2 * (t * t * t + 2) + b -end -local function outInCubic(t, b, c, d) - if t < d / 2 then return outCubic(t * 2, b, c / 2, d) end - return inCubic((t * 2) - d, b + c / 2, c / 2, d) -end - --- quart -local function inQuart(t, b, c, d) return c * pow(t / d, 4) + b end -local function outQuart(t, b, c, d) return -c * (pow(t / d - 1, 4) - 1) + b end -local function inOutQuart(t, b, c, d) - t = t / d * 2 - if t < 1 then return c / 2 * pow(t, 4) + b end - return -c / 2 * (pow(t - 2, 4) - 2) + b -end -local function outInQuart(t, b, c, d) - if t < d / 2 then return outQuart(t * 2, b, c / 2, d) end - return inQuart((t * 2) - d, b + c / 2, c / 2, d) -end - --- quint -local function inQuint(t, b, c, d) return c * pow(t / d, 5) + b end -local function outQuint(t, b, c, d) return c * (pow(t / d - 1, 5) + 1) + b end -local function inOutQuint(t, b, c, d) - t = t / d * 2 - if t < 1 then return c / 2 * pow(t, 5) + b end - return c / 2 * (pow(t - 2, 5) + 2) + b -end -local function outInQuint(t, b, c, d) - if t < d / 2 then return outQuint(t * 2, b, c / 2, d) end - return inQuint((t * 2) - d, b + c / 2, c / 2, d) -end - --- sine -local function inSine(t, b, c, d) return -c * cos(t / d * (pi / 2)) + c + b end -local function outSine(t, b, c, d) return c * sin(t / d * (pi / 2)) + b end -local function inOutSine(t, b, c, d) return -c / 2 * (cos(pi * t / d) - 1) + b end -local function outInSine(t, b, c, d) - if t < d / 2 then return outSine(t * 2, b, c / 2, d) end - return inSine((t * 2) -d, b + c / 2, c / 2, d) -end - --- expo -local function inExpo(t, b, c, d) - if t == 0 then return b end - return c * pow(2, 10 * (t / d - 1)) + b - c * 0.001 -end -local function outExpo(t, b, c, d) - if t == d then return b + c end - return c * 1.001 * (-pow(2, -10 * t / d) + 1) + b -end -local function inOutExpo(t, b, c, d) - if t == 0 then return b end - if t == d then return b + c end - t = t / d * 2 - if t < 1 then return c / 2 * pow(2, 10 * (t - 1)) + b - c * 0.0005 end - return c / 2 * 1.0005 * (-pow(2, -10 * (t - 1)) + 2) + b -end -local function outInExpo(t, b, c, d) - if t < d / 2 then return outExpo(t * 2, b, c / 2, d) end - return inExpo((t * 2) - d, b + c / 2, c / 2, d) -end - --- circ -local function inCirc(t, b, c, d) return(-c * (sqrt(1 - pow(t / d, 2)) - 1) + b) end -local function outCirc(t, b, c, d) return(c * sqrt(1 - pow(t / d - 1, 2)) + b) end -local function inOutCirc(t, b, c, d) - t = t / d * 2 - if t < 1 then return -c / 2 * (sqrt(1 - t * t) - 1) + b end - t = t - 2 - return c / 2 * (sqrt(1 - t * t) + 1) + b -end -local function outInCirc(t, b, c, d) - if t < d / 2 then return outCirc(t * 2, b, c / 2, d) end - return inCirc((t * 2) - d, b + c / 2, c / 2, d) -end - --- elastic -local function calculatePAS(p,a,c,d) - p, a = p or d * 0.3, a or 0 - if a < abs(c) then return p, c, p / 4 end -- p, a, s - return p, a, p / (2 * pi) * asin(c/a) -- p,a,s -end -local function inElastic(t, b, c, d, a, p) - local s - if t == 0 then return b end - t = t / d - if t == 1 then return b + c end - p,a,s = calculatePAS(p,a,c,d) - t = t - 1 - return -(a * pow(2, 10 * t) * sin((t * d - s) * (2 * pi) / p)) + b -end -local function outElastic(t, b, c, d, a, p) - local s - if t == 0 then return b end - t = t / d - if t == 1 then return b + c end - p,a,s = calculatePAS(p,a,c,d) - return a * pow(2, -10 * t) * sin((t * d - s) * (2 * pi) / p) + c + b -end -local function inOutElastic(t, b, c, d, a, p) - local s - if t == 0 then return b end - t = t / d * 2 - if t == 2 then return b + c end - p,a,s = calculatePAS(p,a,c,d) - t = t - 1 - if t < 0 then return -0.5 * (a * pow(2, 10 * t) * sin((t * d - s) * (2 * pi) / p)) + b end - return a * pow(2, -10 * t) * sin((t * d - s) * (2 * pi) / p ) * 0.5 + c + b -end -local function outInElastic(t, b, c, d, a, p) - if t < d / 2 then return outElastic(t * 2, b, c / 2, d, a, p) end - return inElastic((t * 2) - d, b + c / 2, c / 2, d, a, p) -end - --- back -local function inBack(t, b, c, d, s) - s = s or 1.70158 - t = t / d - return c * t * t * ((s + 1) * t - s) + b -end -local function outBack(t, b, c, d, s) - s = s or 1.70158 - t = t / d - 1 - return c * (t * t * ((s + 1) * t + s) + 1) + b -end -local function inOutBack(t, b, c, d, s) - s = (s or 1.70158) * 1.525 - t = t / d * 2 - if t < 1 then return c / 2 * (t * t * ((s + 1) * t - s)) + b end - t = t - 2 - return c / 2 * (t * t * ((s + 1) * t + s) + 2) + b -end -local function outInBack(t, b, c, d, s) - if t < d / 2 then return outBack(t * 2, b, c / 2, d, s) end - return inBack((t * 2) - d, b + c / 2, c / 2, d, s) -end - --- bounce -local function outBounce(t, b, c, d) - t = t / d - if t < 1 / 2.75 then return c * (7.5625 * t * t) + b end - if t < 2 / 2.75 then - t = t - (1.5 / 2.75) - return c * (7.5625 * t * t + 0.75) + b - elseif t < 2.5 / 2.75 then - t = t - (2.25 / 2.75) - return c * (7.5625 * t * t + 0.9375) + b - end - t = t - (2.625 / 2.75) - return c * (7.5625 * t * t + 0.984375) + b -end -local function inBounce(t, b, c, d) return c - outBounce(d - t, 0, c, d) + b end -local function inOutBounce(t, b, c, d) - if t < d / 2 then return inBounce(t * 2, 0, c, d) * 0.5 + b end - return outBounce(t * 2 - d, 0, c, d) * 0.5 + c * .5 + b -end -local function outInBounce(t, b, c, d) - if t < d / 2 then return outBounce(t * 2, b, c / 2, d) end - return inBounce((t * 2) - d, b + c / 2, c / 2, d) -end - -tween.easing = { - linear = linear, - inQuad = inQuad, outQuad = outQuad, inOutQuad = inOutQuad, outInQuad = outInQuad, - inCubic = inCubic, outCubic = outCubic, inOutCubic = inOutCubic, outInCubic = outInCubic, - inQuart = inQuart, outQuart = outQuart, inOutQuart = inOutQuart, outInQuart = outInQuart, - inQuint = inQuint, outQuint = outQuint, inOutQuint = inOutQuint, outInQuint = outInQuint, - inSine = inSine, outSine = outSine, inOutSine = inOutSine, outInSine = outInSine, - inExpo = inExpo, outExpo = outExpo, inOutExpo = inOutExpo, outInExpo = outInExpo, - inCirc = inCirc, outCirc = outCirc, inOutCirc = inOutCirc, outInCirc = outInCirc, - inElastic = inElastic, outElastic = outElastic, inOutElastic = inOutElastic, outInElastic = outInElastic, - inBack = inBack, outBack = outBack, inOutBack = inOutBack, outInBack = outInBack, - inBounce = inBounce, outBounce = outBounce, inOutBounce = inOutBounce, outInBounce = outInBounce -} - - - --- private stuff - -local function copyTables(destination, keysTable, valuesTable) - valuesTable = valuesTable or keysTable - local mt = getmetatable(keysTable) - if mt and getmetatable(destination) == nil then - setmetatable(destination, mt) - end - for k,v in pairs(keysTable) do - if type(v) == 'table' then - destination[k] = copyTables({}, v, valuesTable[k]) - else - destination[k] = valuesTable[k] - end - end - return destination -end - -local function checkSubjectAndTargetRecursively(subject, target, path) - path = path or {} - local targetType, newPath - for k,targetValue in pairs(target) do - targetType, newPath = type(targetValue), copyTables({}, path) - table.insert(newPath, tostring(k)) - if targetType == 'number' then - assert(type(subject[k]) == 'number', "Parameter '" .. table.concat(newPath,'/') .. "' is missing from subject or isn't a number") - elseif targetType == 'table' then - checkSubjectAndTargetRecursively(subject[k], targetValue, newPath) - else - assert(targetType == 'number', "Parameter '" .. table.concat(newPath,'/') .. "' must be a number or table of numbers") - end - end -end - -local function checkNewParams(duration, subject, target, easing) - assert(type(duration) == 'number' and duration > 0, "duration must be a positive number. Was " .. tostring(duration)) - local tsubject = type(subject) - assert(tsubject == 'table' or tsubject == 'userdata', "subject must be a table or userdata. Was " .. tostring(subject)) - assert(type(target)== 'table', "target must be a table. Was " .. tostring(target)) - assert(type(easing)=='function', "easing must be a function. Was " .. tostring(easing)) - checkSubjectAndTargetRecursively(subject, target) -end - -local function getEasingFunction(easing) - easing = easing or "linear" - if type(easing) == 'string' then - local name = easing - easing = tween.easing[name] - if type(easing) ~= 'function' then - error("The easing function name '" .. name .. "' is invalid") - end - end - return easing -end - -local function performEasingOnSubject(subject, target, initial, clock, duration, easing) - local t,b,c,d - for k,v in pairs(target) do - if type(v) == 'table' then - performEasingOnSubject(subject[k], v, initial[k], clock, duration, easing) - else - t,b,c,d = clock, initial[k], v - initial[k], duration - subject[k] = easing(t,b,c,d) - end - end -end - --- Tween methods - -local Tween = {} -local Tween_mt = {__index = Tween} - -function Tween:set(clock) - assert(type(clock) == 'number', "clock must be a positive number or 0") - - self.initial = self.initial or copyTables({}, self.target, self.subject) - self.clock = clock - - if self.clock <= 0 then - - self.clock = 0 - copyTables(self.subject, self.initial) - - elseif self.clock >= self.duration then -- the tween has expired - - self.clock = self.duration - copyTables(self.subject, self.target) - - else - - performEasingOnSubject(self.subject, self.target, self.initial, self.clock, self.duration, self.easing) - - end - - return self.clock >= self.duration -end - -function Tween:reset() - return self:set(0) -end - -function Tween:update(dt) - assert(type(dt) == 'number', "dt must be a number") - return self:set(self.clock + dt) -end - - --- Public interface - -function tween.new(duration, subject, target, easing) - easing = getEasingFunction(easing) - checkNewParams(duration, subject, target, easing) - return setmetatable({ - duration = duration, - subject = subject, - target = target, - easing = easing, - clock = 0 - }, Tween_mt) -end - -return tween diff --git a/sonic-bluestreak.love/game/modules/world/actors/ennemies/motobug.lua b/sonic-bluestreak.love/game/modules/world/actors/ennemies/motobug.lua deleted file mode 100644 index 618ca36..0000000 --- a/sonic-bluestreak.love/game/modules/world/actors/ennemies/motobug.lua +++ /dev/null @@ -1,6 +0,0 @@ -local Parent = require "game.modules.world.actors.ennemies.parent" -local Motobug = Parent:extend() - - - -return Motobug diff --git a/sonic-bluestreak.love/game/modules/world/maps/init.lua b/sonic-bluestreak.love/game/modules/world/maps/init.lua deleted file mode 100644 index 41f47b0..0000000 --- a/sonic-bluestreak.love/game/modules/world/maps/init.lua +++ /dev/null @@ -1,7 +0,0 @@ -local customMap = {} - -customMap.Test = require "game.modules.world.maps.test" -customMap.Battle = require "game.modules.world.maps.battle" -customMap.Shoot = require "game.modules.world.maps.shoot" - -return customMap diff --git a/sonic-bluestreak.love/game/modules/world/maps/test.lua b/sonic-bluestreak.love/game/modules/world/maps/test.lua deleted file mode 100644 index 75295e2..0000000 --- a/sonic-bluestreak.love/game/modules/world/maps/test.lua +++ /dev/null @@ -1,46 +0,0 @@ -local BaseMap = require "core.modules.world.maps.parent" -local TestMap = BaseMap:extend() - -function TestMap:new(world) - TestMap.super.new(self, world) - --self:setPadding(0, 0, 0, 0) - - self.background = love.graphics.newImage("assets/backgrounds/dumbtestmap.png") -end - -function TestMap:loadCollisions() - local w, h = self:getDimensions() - self.world:newCollision("floor", 0, 0, -16, w, h, 16) -end - -function TestMap:getDimensions() - return self.background:getDimensions() -end - -function TestMap:loadPlayers() - self.world:addPlayer(16, 16, 0, 1) -end - -function TestMap:loadActors() - -- Empty Placeholder function -end - -function TestMap:draw() - -- Empty Placeholder function - love.graphics.draw(self.background, 0, 0) -end - -function TestMap:drawParallax(x, y, w, h) - -- local imax, jmax = (w/32)+1, (h/32)+1 - -- local x, y = x or 0, y or 0 - -- local x = math.floor(x/4) % 32 - -- local y = math.floor((y+96)/6) % 32 - -- - -- for i=0, math.ceil(imax) do - -- for j=0, math.ceil(jmax) do - -- love.graphics.draw(self.background, (i-1)*32-x, (j-1)*32-y) - -- end - -- end -end - -return TestMap diff --git a/sonic-bluestreak.love/game/scenes/init.lua b/sonic-bluestreak.love/game/scenes/init.lua new file mode 100644 index 0000000..3a6fb28 --- /dev/null +++ b/sonic-bluestreak.love/game/scenes/init.lua @@ -0,0 +1,45 @@ +local BirbScene = require "birb.modules.scenes" +local RadianceScene = BirbScene:extend() + +local Overlay = require "game.modules.gui.overlay" +local MessageQueue = require "game.modules.messagequeue" +local ActionPrompt = require "game.modules.gui.actionPrompt" + +function RadianceScene:new(haveBorder, showVersion) + RadianceScene.super.new(self) + + -- Importation Global des assets + self.assets:batchImport("assets.commons") + self.assets.fonts["small"]:setLineHeight(16/18) + self.assets.fonts["small"]:setFilter("shadow") + self.gui:addSFX("select", "mSelect") + self.gui:addSFX("navigate", "mBeep") + self.gui:addSFX("back", "mBack") + self.gui:addSFX("error", "mError") + + Overlay(haveBorder, showVersion) + MessageQueue(self) + ActionPrompt() +end + +function RadianceScene:hideOverlay() + self.gui:hideScreen("overlay") +end + +function RadianceScene:showMessage(message) + self.gui.elements["messageQueue"]:addMessage(message) +end + +function RadianceScene:setPrompt(message) + self.gui.elements["actionPrompt"]:setText(message) +end + +function RadianceScene:showOverlay(darken) + self.gui:showScreen("overlay") + if (darken) then + self.gui:playScreenTransform("overlay", "showBackground") + end +end + + +return RadianceScene \ No newline at end of file diff --git a/sonic-bluestreak.love/game/subgame/sonic-boost.lua b/sonic-bluestreak.love/game/subgame/sonic-boost.lua deleted file mode 100644 index 9ae88e9..0000000 --- a/sonic-bluestreak.love/game/subgame/sonic-boost.lua +++ /dev/null @@ -1,18 +0,0 @@ -local SonicBoost = Object:extend() - -function SonicBoost:new(controller) - self.controller = controller - self.datas = {} - - self.datas.characters = require "datas.subgame.sonic-boost.characters" -end - -function SonicBoost:getCharacterData(name) - return self.datas.characters[name] -end - -function SonicBoost:getData() - return self.datas -end - -return SonicBoost diff --git a/sonic-bluestreak.love/game/utils/battle/init.lua b/sonic-bluestreak.love/game/utils/battle/init.lua new file mode 100644 index 0000000..be1569d --- /dev/null +++ b/sonic-bluestreak.love/game/utils/battle/init.lua @@ -0,0 +1,84 @@ +local BattleUtils = {} +local CONSTS = require "datas.consts.battle" +local protectypes = require "datas.gamedata.battles.protectypes" + +local STATS = require "datas.consts.stats" + +function BattleUtils.computeLaunchingDamages(base, fighter, isSpecial) + local damages = base / CONSTS.DAMAGE.DIVISOR + if (isSpecial) then + damages = damages * fighter:getStat(STATS.POWER) + else + damages = damages * fighter:getStat(STATS.ATTACK) + end + + damages = damages * BattleUtils.computerArmorAndDamage(fighter:getStat(STATS.DAMAGE)) + + if (BattleUtils.rollDice(fighter:getStat(STATS.CRITICAL))) then + damages = damages * 2 + end + + return damages +end + +function BattleUtils.computeReceivingDamages(base, fighter, isSpecial, isDefending) + local damages = base + if (isSpecial) then + damages = damages / fighter:getStat(STATS.MIND) + else + damages = damages / fighter:getStat(STATS.DEFENSE) + end + + damages = damages * BattleUtils.computerArmorAndDamage(fighter:getStat(STATS.ARMOR), true) + + if (isDefending) then + damages = damages * CONSTS.DAMAGE.DEFFACTOR + end + + return damages +end + +function BattleUtils.applyProtectTypes(value, type, protectypeList) + for _, protectype in ipairs(protectypeList) do + local protecttypeData = protectypes[protectype] + if protecttypeData ~= nil then + if (utils.table.contain(protecttypeData.resistTo, type)) then + value = value * CONSTS.ATKWRONGTYPE + end + else + core.debug:warning("battleutils", "protectype " .. protectype .. " doesn't exists ") + end + end + return value +end + +function BattleUtils.applyWeaknesses(damages, element, weaknessList) + if (utils.table.contain(weaknessList, element)) then + damages = damages * 1.2 + end + return damages +end + +function BattleUtils.applyResistences(damages, element, resistsList) + if (utils.table.contain(resistsList, element)) then + damages = damages * 0.8 + end + return damages +end + +function BattleUtils.rollDice(stat) + local stat = stat or 100 + return (math.random(100) <= stat) +end + +function BattleUtils.computerArmorAndDamage(stat, isNegative) + if (isNegative) then + stat = stat * -1 + end + if (stat < 0) then + stat = stat * STATS.ARMOR_AND_DAMAGE_RATIO + end + return (100 + (stat))/100 +end + +return BattleUtils diff --git a/sonic-bluestreak.love/game/utils/characters.lua b/sonic-bluestreak.love/game/utils/characters.lua new file mode 100644 index 0000000..8c11059 --- /dev/null +++ b/sonic-bluestreak.love/game/utils/characters.lua @@ -0,0 +1,33 @@ +local CharUtils = {} + +local CONST = require "datas.consts.stats" + +function CharUtils.getExpValue(level) + return math.floor( ( CONST.EXP_MULTIPLICATOR * ( level ^ 3 ) ) / CONST.EXP_RATIO ) +end + +function CharUtils.getRelativeExpValue(exp, level) + return exp - CharUtils.getExpValue(level) +end + +function CharUtils.getLevelExpRange(level) + return CharUtils.getExpValue(level + 1) - CharUtils.getExpValue(level) +end + +function CharUtils.getRemainingExp(exp, level) + return CharUtils.getExpValue(level + 1) - exp +end + +function CharUtils.getStatValue(level, base) + return math.floor( (((base * CONST.MULT_STAT) * level)/100) ) + CONST.BASE_STAT +end + +function CharUtils.getHPValue(level, base) + return math.floor( (((CONST.SALT_HP + base * CONST.MULT_HP) * level)/100) ) + CONST.BASE_HP + level +end + +function CharUtils.getPPValue(level, base) + return math.floor( (((base * CONST.MULT_MP) * level)/100) ) + CONST.BASE_MP +end + +return CharUtils diff --git a/sonic-bluestreak.love/game/utils/gizmo/properties.lua b/sonic-bluestreak.love/game/utils/gizmo/properties.lua new file mode 100644 index 0000000..4f0bb73 --- /dev/null +++ b/sonic-bluestreak.love/game/utils/gizmo/properties.lua @@ -0,0 +1,5 @@ +return { + isSolid = false, + needButton = true, -- "useButton" or "onContact" + destroy = "none", +} \ No newline at end of file diff --git a/sonic-bluestreak.love/game/modules/utils/init.lua b/sonic-bluestreak.love/game/utils/init.lua similarity index 100% rename from sonic-bluestreak.love/game/modules/utils/init.lua rename to sonic-bluestreak.love/game/utils/init.lua