Difficulty director created
This commit is contained in:
@@ -9,3 +9,5 @@ Tile.exit = 3
|
||||
|
||||
Flux = require 'packages.flux'
|
||||
Timer = require 'packages.timer'
|
||||
|
||||
MAX_LEVELS = 3
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
75
src/utils/difficulty_director.lua
Normal file
75
src/utils/difficulty_director.lua
Normal 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
|
||||
4
todo.md
4
todo.md
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user