From 32c72c18e9de30a7f6449d0bce815931472e8afc Mon Sep 17 00:00:00 2001 From: Kazhnuz Date: Sun, 18 Apr 2021 12:34:30 +0200 Subject: [PATCH] feat: initial terrain collision system Fixes #79 --- .../datas/gamedata/maps/terrains.lua | 137 +++++++++++------- .../scenes/overworld/actors/gizmo.lua | 2 +- .../overworld/actors/player/actions.lua | 57 ++++++-- .../scenes/overworld/actors/player/init.lua | 13 +- .../overworld/actors/player/interactions.lua | 58 +++++--- 5 files changed, 170 insertions(+), 97 deletions(-) diff --git a/sonic-radiance.love/datas/gamedata/maps/terrains.lua b/sonic-radiance.love/datas/gamedata/maps/terrains.lua index a924234..3efc011 100644 --- a/sonic-radiance.love/datas/gamedata/maps/terrains.lua +++ b/sonic-radiance.love/datas/gamedata/maps/terrains.lua @@ -1,62 +1,87 @@ return { - ["non-solid"] = { - { - terrainType = "normal", - forceAction = nil, - level=0, - height=0, - canJump = true - } - }, - ice = { - { - terrainType = "forceAction", - forceAction = "slide", - level=0, - height=0, - canJump = false - } - }, - water = { - { - terrainType = "forceAction", - forceAction = "fall", - level=-32, - height=0, - damage = 10, - speedFactor = 0, + highpriority = {"ice"}, + list = { + ["non-solid"] = { + { + forceAction = nil, + level=0, + height=0, + canJump = true + } }, - { - terrainType = "normal", - forceAction = nil, - level=-10, - height=0, - mustHaveAction = "swim", - mustDoAction = nil, - speedFactor = 0.8, - canJump = true, - damage = 0, + ice = { + { + forceAction = "slide", + level=0, + height=0, + canJump = false, + speedFactor = 1.2, + } }, - { - terrainType = "normal", - forceAction = nil, - level=0, - height=0, - mustHaveAction = "run", - mustDoAction = "run", - speedFactor = 1, - canJump = true, - damage = 0, - } - }, - grass = { - { - terrainType = "normal", - forceAction = nil, - level=0, - height=16, - speedFactor = 0.75, - canJump = false, + water = { + { + level=-32, + height=0, + fallDamage = 10, + speedFactor = 0, + canJump = false, + }, + { + forceAction = nil, + level=-10, + height=0, + mustHaveAction = "swim", + mustDoAction = nil, + speedFactor = 0.5, + canJump = true, + damage = 0, + }, + { + forceAction = nil, + level=0, + height=0, + mustHaveAction = "run", + mustDoAction = "run", + speedFactor = 1, + canJump = true, + damage = 0, + } + }, + hole = { + { + level=-32, + height=0, + fallDamage = 10, + speedFactor = 0, + canJump = false, + }, + }, + lava = { + { + level=-32, + height=0, + fallDamage = 20, + speedFactor = 0, + canJump = false, + }, + }, + swamp = { + { + forceAction = nil, + level=-8, + height=0, + speedFactor = 0.66, + canJump = false, + } + }, + grass = { + { + forceAction = nil, + level=0, + height=8, + speedFactor = 0.66, + canJump = false, + } } } } \ No newline at end of file diff --git a/sonic-radiance.love/scenes/overworld/actors/gizmo.lua b/sonic-radiance.love/scenes/overworld/actors/gizmo.lua index ffcd549..a1df771 100644 --- a/sonic-radiance.love/scenes/overworld/actors/gizmo.lua +++ b/sonic-radiance.love/scenes/overworld/actors/gizmo.lua @@ -10,7 +10,7 @@ function Gizmo:new(world, x, y, w, h, overrides) local h = h or 16; Gizmo.super.new(self, world, "gizmo", x, y, w, h, false) self.overrides = overrides - self.drawDebugBox = true + self.drawDebugBox = false self.event = defaultEvent end diff --git a/sonic-radiance.love/scenes/overworld/actors/player/actions.lua b/sonic-radiance.love/scenes/overworld/actors/player/actions.lua index cc7869c..2190682 100644 --- a/sonic-radiance.love/scenes/overworld/actors/player/actions.lua +++ b/sonic-radiance.love/scenes/overworld/actors/player/actions.lua @@ -11,6 +11,10 @@ ACTIONS["power"] = {"punch"} function PlayerActions:initActions() self.currentAction = "idle" + self.canJump = true + self.canAct = true + self.speedFactor = 1 + self.forceAction = nil end function PlayerActions:canDoAction(action) @@ -19,44 +23,75 @@ function PlayerActions:canDoAction(action) return (classCanDoAction and playerCanDoAction) end +function PlayerActions:act() + if (self.forceAction ~= nil) then + self:forcedAction() + else + self:actionMove() + self:actionJump() + self:actionSwitch() + self:actionRun() + self:actionPunch() + end +end + +function PlayerActions:forcedAction() + local charSpeed = BASE_SPEED * self.speedFactor + + if (self.forceAction == "slide") then + if (self.xsp ~= 0 or self.ysp ~= 0) then + if (self.currentAction == "run") then + charSpeed = charSpeed * RUN_FACTOR + end + self.xsp, self.ysp = utils.math.lengthdir(charSpeed, math.rad(self.charsetManager.angle[self.charDir])) + self.xsp = -self.xsp + else + self:actionMove() + end + end +end + function PlayerActions:actionMove() + local charSpeed = BASE_SPEED * self.speedFactor + if (self.currentAction == "punch") then return end + if (self.currentAction == "jumpdash" or self.currentAction == "run") then - self.xsp, self.ysp = utils.math.lengthdir(BASE_SPEED * RUN_FACTOR, math.rad(self.charsetManager.angle[self.charDir])) + self.xsp, self.ysp = utils.math.lengthdir(charSpeed * RUN_FACTOR, math.rad(self.charsetManager.angle[self.charDir])) self.xsp = -self.xsp if (utils.table.contain({"up", "down"}, self.charDir)) then if self.keys["left"].isDown then - self.xsp = -BASE_SPEED + self.xsp = -charSpeed end if self.keys["right"].isDown then - self.xsp = BASE_SPEED + self.xsp = charSpeed end else if self.keys["up"].isDown then - self.ysp = -BASE_SPEED + self.ysp = -charSpeed end if self.keys["down"].isDown then - self.ysp = BASE_SPEED + self.ysp = charSpeed end end else if self.keys["up"].isDown then - self.ysp = -BASE_SPEED + self.ysp = -charSpeed self.charDir = "up" end if self.keys["down"].isDown then - self.ysp = BASE_SPEED + self.ysp = charSpeed self.charDir = "down" end if self.keys["left"].isDown then - self.xsp = -BASE_SPEED + self.xsp = -charSpeed self.charDir = "left" end if self.keys["right"].isDown then - self.xsp = BASE_SPEED + self.xsp = charSpeed self.charDir = "right" end end @@ -64,7 +99,7 @@ end function PlayerActions:actionJump() if self.keys["B"].isPressed then - if (self.onGround) then + if (self.onGround and self.canJump) then self:goUpward(JMP_STRENGHT) self.assets.sfx["jump"]:play() if (self.currentAction == "run") then @@ -101,7 +136,7 @@ end function PlayerActions:actionRun() if self.keys["C"].isPressed then - if (self:canDoAction("run")) then + if (self:canDoAction("run") and self.speedFactor > 0) then self.assets.sfx["dash"]:play() if (utils.table.contain({"run", "idle"}, self.currentAction)) then self.currentAction = "run" diff --git a/sonic-radiance.love/scenes/overworld/actors/player/init.lua b/sonic-radiance.love/scenes/overworld/actors/player/init.lua index 022b6f7..c7add90 100644 --- a/sonic-radiance.love/scenes/overworld/actors/player/init.lua +++ b/sonic-radiance.love/scenes/overworld/actors/player/init.lua @@ -14,17 +14,18 @@ Player:implement(Actions) Player:implement(Charset) Player:implement(Map) - local FRICTION = 480 * 3 local GRAV = 10 local DEFAULT_GROUND_LEVEL = 0 local DEFAULT_GROUND_HEIGHT = 0 +local RESPAWN_LIMIT = -32 function Player:new(world, x, y, id) Player.super.new(self, world, "player", x, y, 16, 16, true) self.groundLevel = DEFAULT_GROUND_LEVEL self.groundHeight = DEFAULT_GROUND_HEIGHT self.z = self.groundLevel + self.grav = GRAV self.tweens = TweenManager(self) self.onGround = true @@ -41,11 +42,7 @@ function Player:updateStart(dt) self.tweens:update(dt) self:updateTerrain() - self:actionMove() - self:actionJump() - self:actionSwitch() - self:actionRun() - self:actionPunch() + self:act() self.world:getTileTypeAtPoint(self.x, self.y) @@ -77,6 +74,10 @@ function Player:checkGround() self.z = self.groundLevel self.zsp = 0 self:endJump() + if (self.z <= RESPAWN_LIMIT) then + self.x = self.lastPos.x + self.y = self.lastPos.y + end end end diff --git a/sonic-radiance.love/scenes/overworld/actors/player/interactions.lua b/sonic-radiance.love/scenes/overworld/actors/player/interactions.lua index fbd6d8a..d8f7528 100644 --- a/sonic-radiance.love/scenes/overworld/actors/player/interactions.lua +++ b/sonic-radiance.love/scenes/overworld/actors/player/interactions.lua @@ -21,8 +21,8 @@ function PlayerInteractions:initInteractions() self.terrain.name = "" self.terrain.data = {} self.lastPos = {} - self.lastPos.x = math.floor(self.x/16) * 16 - self.lastPos.y = math.floor(self.y/16) * 16 + self.lastPos.x = self.x + self.lastPos.y = self.y end function PlayerInteractions:updateInteraction() @@ -73,12 +73,8 @@ end function PlayerInteractions:updateTerrain() local newTerrain = self:getCurrentTerrain() - - if (self.terrain.name ~= newTerrain) then - print(newTerrain) - self.terrain.name = newTerrain - self:updateTerrainData() - end + self.terrain.name = newTerrain + self:updateTerrainData() if (newTerrain == "non-solid") then self:updateLastPosition() end @@ -87,25 +83,27 @@ end function PlayerInteractions:updateLastPosition() local canUpdate = true for _, coord in ipairs(TERRAIN_CHECKER) do - local newTerrain = self.world:getTileTypeAtPoint(self.x + coord.x, self.y + coord.y) + local xx, yy = coord.x, coord.y + if (xx == MIN_X) then xx=0 else xx=16 end + if (yy == MIN_Y) then yy=0 else yy=16 end + local newTerrain = self.world:getTileTypeAtPoint(self.x + xx, self.y + yy) if (newTerrain ~= "non-solid") then - self.canUpdate = false - break; + canUpdate = false end end - if (canUpdate) then + if (canUpdate and self.onGround) then self.lastPos = {} - self.lastPos.x = math.floor(self.x/16) * 16 - self.lastPos.y = math.floor(self.y/16) * 16 + self.lastPos.x = self.x + self.lastPos.y = self.y end end function PlayerInteractions:updateTerrainData() - local dataPack = terrainData[self.terrain.name] - local newData = terrainData["non-solid"][1] + local dataPack = terrainData.list[self.terrain.name] + local newData = terrainData.list["non-solid"][1] if (dataPack == nil) then - dataPack = terrainData["non-solid"] + dataPack = terrainData.list["non-solid"] end for id, data in ipairs(dataPack) do @@ -119,7 +117,6 @@ function PlayerInteractions:updateTerrainData() if (useThisData) then newData = data - print(id) end end @@ -127,16 +124,31 @@ function PlayerInteractions:updateTerrainData() end function PlayerInteractions:setTerrainData(data) - --TODO + self.groundLevel = data.level or 0 + self.groundHeight = data.height or 0 + if (self.onGround) then + self.speedFactor = data.speedFactor or 1 + self.canJump = data.canJump ~= false + self.forceAction = data.forceAction + end + self.terrain.data = data end function PlayerInteractions:getCurrentTerrain() - local terrain = self.terrain.name + local terrain = "" + local highpriority = terrainData.highpriority for _, coord in ipairs(TERRAIN_CHECKER) do local newTerrain = self.world:getTileTypeAtPoint(self.x + coord.x, self.y + coord.y) - terrain = newTerrain - if (newTerrain == "non-solid") then - break; + if (utils.table.contain(highpriority, newTerrain)) then + terrain = newTerrain + elseif (newTerrain == "non-solid") then + if (not utils.table.contain(highpriority, terrain)) then + terrain = newTerrain + end + else + if (not (utils.table.contain(highpriority, terrain) or terrain == "non-solid")) then + terrain = newTerrain + end end end return terrain