Slightly more ECS spawner upgrades?

Not positive this is in the spirit, but we're figuring it out, kay?
This commit is contained in:
Sage Vaillancourt 2025-03-07 17:10:04 -05:00
parent 60461aa14f
commit d6c934a265
5 changed files with 116 additions and 43 deletions

View File

@ -3,6 +3,9 @@
-- This file is composed of, essentially, "base types"
local SOME_TABLE <const> = {}
---@alias AnyComponent any
---@alias BitMask number
---@alias CanBeBounced { flat: XyPair, mult = XyPair }
---@alias CanSpawn { entityToSpawn: Entity }
@ -10,7 +13,10 @@
---@alias Entity table
---@alias InRelations Entity[]
---@alias InputState { receivedInputThisFrame: boolean, aJustPressed: boolean, bJustPressed: boolean, upJustPressed: boolean, downJustPressed: boolean, leftJustPressed: boolean, rightJustPressed: boolean }
---@alias ReplaceRelation { entityToModify: Entity, replacement: Replacement }
---@alias Replacement { key: string, value: AnyComponent }
---@alias RoundStateAction "end" | "start"
---@alias Selectable { additions: Entity[] | nil, replacements: ReplaceRelation[] | nil, highlighted: boolean, navigateDown: Selectable | nil, navigateUp: Selectable | nil }
---@alias XyPair { x: number, y: number }
@ -19,7 +25,7 @@ T = {
number = 0,
numberArray = { 1, 2, 3 },
str = "",
marker = {},
marker = SOME_TABLE,
---@type fun(self)
SelfFunction = function() end,
--- Actor
@ -29,28 +35,49 @@ T = {
mult = XyPair,
},
---@type pd_image
pd_image = {},
pd_image = SOME_TABLE,
---@type pd_font
pd_font = {},
pd_font = SOME_TABLE,
---@type AnyComponent
AnyComponent = SOME_TABLE,
---@type BitMask
BitMask = 0,
---@type CanBeBounced
CanBeBounced = {},
CanBeBounced = SOME_TABLE,
---@type CanSpawn
CanSpawn = {},
CanSpawn = SOME_TABLE,
---@type Collision
Collision = {},
Collision = SOME_TABLE,
---@type Entity
Entity = {},
Entity = SOME_TABLE,
---@type InRelations
InRelations = {},
InRelations = SOME_TABLE,
---@type InputState
InputState = {},
InputState = SOME_TABLE,
---@type ReplaceRelation
ReplaceRelation = SOME_TABLE,
---@type Replacement
Replacement = SOME_TABLE,
---@type RoundStateAction
RoundStateAction = "start",
---@type Selectable
Selectable = SOME_TABLE,
---@type XyPair
XyPair = {},
XyPair = SOME_TABLE,
}
---@generic T
@ -60,6 +87,13 @@ function Maybe(t)
return { maybe = t }
end
---@generic T
---@param t T
---@return T[]
function Arr(t)
return { arrOf = t }
end
TextStyle = {
Inverted = "INVERTED",
Bordered = "BORDERED",

View File

@ -12,7 +12,7 @@ function t(name, type, value)
elseif type == "string" then
value = ""
else
value = "{}"
value = "SOME_TABLE"
end
end
types[#types + 1] = { name = name, type = type, value = value }
@ -42,7 +42,7 @@ end
function dumpTypeObjects()
local ret = ""
for _, v in ipairs(types) do
local line = "\n ---@type " .. v.name .. "\n " .. v.name .. " = " .. v.value .. ","
local line = "\n\n ---@type " .. v.name .. "\n " .. v.name .. " = " .. v.value .. ","
ret = ret .. line
end
return ret
@ -51,6 +51,8 @@ end
-- This file is composed of, essentially, "base types"
local SOME_TABLE <const> = {}
!!(tMany({
Entity = "table",
XyPair = "{ x: number, y: number }",
@ -58,10 +60,15 @@ end
BitMask = "number",
CanBeBounced = "{ flat: XyPair, mult: XyPair }",
RoundStateAction = { '"end" | "start"', '"start"' },
AnyComponent = "any",
CanSpawn = "{ entityToSpawn: Entity }",
InRelations = "Entity[]",
CanBeBounced = "{ flat: XyPair, mult = XyPair }",
InputState = "{ receivedInputThisFrame: boolean, aJustPressed: boolean, bJustPressed: boolean, upJustPressed: boolean, downJustPressed: boolean, leftJustPressed: boolean, rightJustPressed: boolean }",
Replacement = "{ key: string, value: AnyComponent }",
ReplaceRelation = "{ entityToModify: Entity, replacement: Replacement }",
Selectable = "{ additions: Entity[] | nil, replacements: ReplaceRelation[] | nil, highlighted: boolean, navigateDown: Selectable | nil, navigateUp: Selectable | nil }",
}))
T = {
@ -69,7 +76,7 @@ T = {
number = 0,
numberArray = { 1, 2, 3 },
str = "",
marker = {},
marker = SOME_TABLE,
---@type fun(self)
SelfFunction = function() end,
--- Actor
@ -79,9 +86,9 @@ T = {
mult = XyPair,
},
---@type pd_image
pd_image = {},
pd_image = SOME_TABLE,
---@type pd_font
pd_font = {},
pd_font = SOME_TABLE,
!!(dumpTypeObjects())
}
@ -92,6 +99,13 @@ function Maybe(t)
return { maybe = t }
end
---@generic T
---@param t T
---@return T[]
function Arr(t)
return { arrOf = t }
end
TextStyle = {
Inverted = "INVERTED",
Bordered = "BORDERED",

View File

@ -1,17 +1,35 @@
---@alias MenuItem { onSelect: fun(), highlighted: boolean, navigateDown: MenuItem | nil, navigateUp: MenuItem | nil }
---@param relation ReplaceRelation
---@param world World
local function applyReplacementRelation(relation, world)
printTable(relation.entityToModify)
relation.entityToModify[relation.replacement.key] = relation.replacement.value
world:addEntity(relation.entityToModify)
printTable(relation.entityToModify)
end
---@type MenuItem[]
local MenuItems = {}
menuController = filteredSystem("menuController", { menuItems = MenuItems, inputState = T.InputState }, function(e, _, system)
menuController = filteredSystem("menuController", { menuItems = Arr(T.Selectable), inputState = T.InputState }, function(e, _, system)
for _, menuItem in pairs(e.menuItems) do
if menuItem.highlighted then
if e.inputState.aJustPressed then
menuItem.onSelect(system.world) -- TODO: That's not very ECS of you!
-- Prepare to remove the menu and all menu items
system.world:removeEntity(e)
for _, item in pairs(e.menuItems) do
system.world:removeEntity(item)
end
system.world:removeEntity(e)
-- TODO: Larger menu that stays open for more purchases before the next round
world:addEntity({ roundAction = "start" })
if menuItem.replacements then
for _, v in ipairs(menuItem.replacements) do
applyReplacementRelation(v, system.world)
end
end
if menuItem.additions then
for _, v in ipairs(menuItem.additions) do
system.world:addEntity(v)
end
end
end
if e.inputState.downJustPressed and menuItem.navigateDown then

View File

@ -102,6 +102,7 @@ roundSystem = filteredSystem("round", { roundAction = T.RoundStateAction, positi
system.world:removeEntity(collectable)
end
---@type SpawnerUpgrade[]
local availableUpgrades = Utils.getNDifferentValues(getAvailableSpawnerUpgrades(), 3)
-- Sorting from shortest to longest sort of makes them look like a bun?
table.sort(availableUpgrades, function(a, b)
@ -119,8 +120,9 @@ roundSystem = filteredSystem("round", { roundAction = T.RoundStateAction, positi
i = i + 1
local collX, collY = 75, 21
y = y - collY - 15 - 15
---@type Selectable
local upgradeEntity = {
onSelect = upgrade.apply,
replacements = { upgrade.replace },
drawAsText = {
text = upgrade.name,
style = TextStyle.Inverted,

View File

@ -101,38 +101,43 @@ function addAllSpawners(world)
})
end
---@alias Upgrade { name: string, apply = fun() }
---@alias SpawnerUpgrade { name: string, replace: ReplaceRelation }
---@return Upgrade[]
---@return SpawnerUpgrade[]
function getAvailableSpawnerUpgrades()
---@type SpawnerUpgrade[]
local upgrades = {}
for _, spawner in pairs(spawnerSystem.entities) do
if spawner.hasUpgradeSpeed then
-- if spawner.hasUpgradeSpeed then
-- upgrades[#upgrades + 1] = { hasUpgradeSpeed = spawner.hasUpgradeSpeed }
end
-- end
if spawner.canSpawn.entityToSpawn.score then
local name = "Double " .. spawner.name .. " value"
local entityToSpawn = spawner.canSpawn.entityToSpawn
if entityToSpawn.score then
upgrades[#upgrades + 1] = {
name = name,
apply = function(world)
print("Applying " .. name)
spawner.canSpawn.entityToSpawn.score = spawner.canSpawn.entityToSpawn.score * 2
world:addEntity({ roundAction = "start" })
end,
name = "Double " .. spawner.name .. " value",
replace = {
entityToModify = entityToSpawn,
replacement = {
key = "score",
value = entityToSpawn.score * 2,
},
},
}
end
assert(spawner.odds, "Expected all spawners to have an `odds` field!")
local name = "Double " .. spawner.name .. " frequency"
upgrades[#upgrades + 1] = {
name = name,
apply = function(world)
print("Applying " .. name)
spawner.odds = spawner.odds * 2
world:addEntity({ roundAction = "start" })
end,
name = "Double " .. spawner.name .. " frequency",
replace = {
entityToModify = entityToSpawn,
replacement = {
key = "odds",
value = entityToSpawn.odds,
}
},
}
end
return upgrades
end