Difficulty director created

This commit is contained in:
2024-12-08 15:25:55 -06:00
parent 78bdd05d42
commit e780be4019
8 changed files with 106 additions and 32 deletions

View File

@@ -9,3 +9,5 @@ Tile.exit = 3
Flux = require 'packages.flux'
Timer = require 'packages.timer'
MAX_LEVELS = 3

View File

@@ -127,6 +127,10 @@ function lume.random(a, b)
return a + math.random() * (b - a)
end
function lume.randomint(a, b)
return math.floor(lume.random(a, b))
end
function lume.randomchoice(t)
return t[math.random(#t)]
end

View File

@@ -19,7 +19,7 @@ function GameCore.new()
self.uiInput = baton.new(input.ui)
self.states = {
mainmenu = MainMenu.new(self, self.uiInput),
game = Game.new(self, 19, 10),
game = Game.new(self),
pausemenu = PauseMenu.new(self, self.uiInput),
gameover = GameOver.new(self, self.uiInput),
victory = Victory.new(self, self.uiInput)

View File

@@ -4,11 +4,10 @@ local Camera = require 'src.display.camera'
local input = require 'src.input_maps'
local bump = require 'packages.bump'
local Player = require 'src.entities.player'
local Siren = require 'src.entities.enemies.siren'
local Worm = require 'src.entities.enemies.worm'
local Effects = require 'src.display.shaders.effects'
local mazeutils = require 'src.maze_generation.utils'
local Maze = require 'src.maze_generation.oshift'
local difficulty = require 'src.utils.difficulty_director'
local Game = {}
@@ -82,27 +81,29 @@ local function splitTime(startTime, endTime)
return minute, second
end
function Game.new(core, mazeWidth, mazeHeight)
function Game.new(core)
setmetatable(Game, { __index = LoveNode })
local self = setmetatable(LoveNode.new(), Game)
self.core = core
self.camera = Camera.new(
(1 + 2 * mazeWidth) * TILE_SIZE,
(1 + 2 * mazeHeight) * TILE_SIZE
)
self.input = baton.new(input.player)
self.env = {}
self.env.mazeWidth, self.env.mazeHeight = mazeWidth, mazeHeight
self.env.entrance = {}
self.env.exits = {}
return self
end
function Game:enter(level, startTime)
self.env = {}
self.env.entrance = {}
self.env.exits = {}
self.level = level or 1
self.env.mazeWidth, self.env.mazeHeight = difficulty.getMazeSize(self.level)
self.camera = Camera.new(
(1 + 2 * self.env.mazeWidth) * TILE_SIZE,
(1 + 2 * self.env.mazeHeight) * TILE_SIZE
)
-- Init environment
self.world = bump.newWorld(TILE_SIZE)
self.env.walls, self.env.maze, self.env.entrance, self.env.exits = initMaze(
@@ -110,21 +111,12 @@ function Game:enter(level, startTime)
self.env.mazeWidth,
self.env.mazeHeight
)
self.env.nodes = mazeutils.getNodeTiles(self.env.maze)
self.player = Player.new(self.env.entrance.x, self.env.entrance.y, self)
self.effect = Effects.new(self)
self.env.nodes = mazeutils.getNodeTiles(self.env.maze)
self.maxLevel = 3
self.level = level or 1
self.enemies = {
Siren.new(self),
Worm.new(self),
Worm.new(self),
Worm.new(self),
Worm.new(self)
}
self.enemies = difficulty.getEnemies(self, self.level)
for _, enemy in ipairs(self.enemies) do
enemy:enter()
@@ -213,7 +205,7 @@ function Game:failLevel()
end
function Game:nextLevel()
if self.level == self.maxLevel then
if self.level == MAX_LEVELS then
self.core:switchState(self.core.states.victory)
else
self.core:switchState(self.core.states.game, self.level + 1, self.startTime)

View File

@@ -25,7 +25,7 @@ function Siren.new(game)
self.texture = love.graphics.newImage 'assets/images/siren.png'
local g = anim8.newGrid(self.size.w, self.size.h, self.texture:getDimensions())
self.animation = anim8.newAnimation(g('1-1', 1), 0.1)
self.animation = anim8.newAnimation(g('1-8', 1), 0.1)
self.isEnemy = true
self.pos = self:_findSpawnPoint()

View File

@@ -30,16 +30,16 @@ local wormQuads = {
}
local spriteBatch = love.graphics.newSpriteBatch(atlas)
function Worm.new(game, length)
function Worm.new(game, minLen, maxLen)
setmetatable(Worm, { __index = LoveNode })
local self = setmetatable(LoveNode.new(), Worm)
self.game = game
local defaultLength = math.floor(lume.random(4, 15))
local tailLength = lume.randomint(minLen, maxLen)
self.stats = {
spawnDistanceFromPlayer = 5 * TILE_SIZE,
moveDelay = 0.2, -- Seconds between movement steps
tailLength = length or defaultLength
tailLength = tailLength
}
self.size = {}
@@ -163,6 +163,7 @@ end
--
function Worm:_findSpawnPoint()
print('env', self.game.env.nodes)
local pos = random.chooseUntil(self.game.env.nodes, function(element)
local distanceToPlayer = vector.dist(element.x, element.y, self.game.player:getPos())
local isFarEnough = distanceToPlayer > self.stats.spawnDistanceFromPlayer

View File

@@ -0,0 +1,75 @@
local lume = require 'packages.lume'
local Siren = require 'src.entities.enemies.siren'
local Worm = require 'src.entities.enemies.worm'
--[[
Split levels into 3 categories: easy medium hard
easy levels
- are ~8x8
- only have short worms
medium levels
- are ~16x16
- have a few short to medium worms and one siren
hard levels
- are ~24x24
- have medium to long worms and multiple sirens
]]
local easyBreakpoint = 0.34
local mediumBreakpoint = 0.67
local difficulty = {}
function difficulty.getMazeSize(stage)
local difficultyScore = stage / MAX_LEVELS
local mazeWidth, mazeHeight
if difficultyScore < easyBreakpoint then
-- Easy
mazeWidth, mazeHeight = 8, 8
elseif difficultyScore < mediumBreakpoint then
-- Medium
mazeWidth, mazeHeight = 16, 16
else
-- Hard
mazeWidth, mazeHeight = 24, 24
end
return mazeWidth, mazeHeight
end
function difficulty.getEnemies(game, stage)
local difficultyScore = stage / MAX_LEVELS
local enemies = {}
local numWorms, numSirens = 0, 0
local minWormLength, maxWormLength = 3, 3
if difficultyScore < easyBreakpoint then
-- Easy
numWorms = lume.randomint(1, 3)
minWormLength, maxWormLength = 3, 7
elseif difficultyScore < mediumBreakpoint then
-- Medium
numWorms = lume.randomint(2, 7)
numSirens = 1
minWormLength, maxWormLength = 3, 7
else
-- Hard
numWorms = lume.randomint(5, 15)
numSirens = lume.randomint(1, 3)
minWormLength, maxWormLength = 5, 15
end
for _ = 1, numWorms do
table.insert(enemies, Worm.new(game, minWormLength, maxWormLength))
end
for _ = 1, numSirens do
table.insert(enemies, Siren.new(game))
end
return enemies
end
return difficulty

View File

@@ -8,11 +8,10 @@
- [ ] Try replacing the Moonshine scan-line effect with the custom shader (or delete it)
- [ ] Create player sprite
- Make a mouse sprite for the player
- [ ] Create a local leaderboard to see who clears maze in the lowest amount of time
# in progress
- [ ] Make the maze end after 5 solves, with progressive difficulty (9x9 no enemies, increase size + enemy count each stage)
- [ ] Create a local leaderboard to see who clears maze in the lowest amount of time
# complete
@@ -43,3 +42,4 @@
- [x] Added font
- [x] Added menu art
- [x] Create a siren sprite
- [x] Make the maze end after 5 solves, with progressive difficulty (9x9 no enemies, increase size + enemy count each stage)