local odds = 0 ---@type { canSpawn: CanSpawn } local selectedSpawner spawnerSystem = filteredSystem({ canSpawn = T.CanSpawn, odds = T.number }, function(spawner, _, system) if odds <= 0 then return end odds = odds - spawner.odds if odds <= 0 then selectedSpawner = spawner else selectedSpawner = selectedSpawner or spawner end end) --- process() and postProcess() are skipped when preProcess() returns true function spawnerSystem:preProcess() local newestX = Ingredients.newestIngredient().position.x local panX = Camera.pan.x local rightEdge = panX + 400 if newestX < rightEdge + 100 then odds = math.random() selectedSpawner = nil return false -- A new ingredient needs spawning! end -- We do not need a new ingredient at this time return true end -- Currently spawns AT MOST one new ingredient per frame, which is probably not enough at high speeds! function spawnerSystem:postProcess() local newestX = Ingredients.newestIngredient().position.x local newlySpawned = Ingredients.nextInCache() -- TODO: If performance becomes an issue, maybe just swap out __index for k, v in pairs(selectedSpawner.canSpawn.entity) do newlySpawned[k] = v end -- TODO: May not need to include lower spawners when we reach higher altitudes. local panY = math.floor(Camera.pan.y or 0) local yRange = selectedSpawner.canSpawn.yRange or { top = panY - 240, bottom = panY + 220 } newlySpawned.position = { x = newestX + 60, y = math.random(yRange.top, yRange.bottom) } self.world:addEntity(newlySpawned) end local expireWhenOffScreenBy = { x = 2000, y = 480 } ---@param world World function addAllSpawners(world) function addCollectableSpawner(name, spawnerOdds, score, sprite, canBounce, yRange) local sizeX, sizeY = sprite:getSize() local size = { x = sizeX, y = sizeY / 2 } world:addEntity({ name = name, odds = spawnerOdds, canSpawn = { yRange = yRange, entity = { score = score, canBeCollidedBy = 1, expireAfterCollision = true, size = size, drawAsSprite = sprite, collectable = sprite, expireWhenOffScreenBy = expireWhenOffScreenBy, canBounce = canBounce, }, }, }) end addCollectableSpawner("Lettuce", 0.7, 1, LettuceSprite, { flat = { x = 22, y = 190 }, mult = { x = 1, y = -0.5 }, }) addCollectableSpawner("Tomato", 0.1, 15, TomatoSprite) addCollectableSpawner("Mushroom", 0.7, 5, MushroomSprite, { flat = { x = 0, y = 290 }, mult = { x = 1, y = -1 }, }, { top = 219, bottom = 223 }) addCollectableSpawner("Cheese", 0.05, 1, CheeseSprite, { flat = { x = 50, y = 390 }, mult = { x = 0.7, y = -0.5 }, }) end function getAvailableSpawnerUpgrades() local upgrades = {} for _, spawner in pairs(spawnSystem.entities) do if spawner.hasUpgradeSpeed then upgrades[#upgrades + 1] = { hasUpgradeSpeed = spawner.hasUpgradeSpeed } end if spawner.hasUpgradeValue then upgrades[#upgrades + 1] = { hasUpgradeValue = spawner.hasUpgradeValue } end end return upgrades end