Last active
April 9, 2024 16:29
-
-
Save Achie72/0751582802f0d9dfa06271dc040d7912 to your computer and use it in GitHub Desktop.
PICO-8 Wave System
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pico-8 cartridge // http://www.pico-8.com | |
version 42 | |
__lua__ | |
-- I would create an enemy adder function that | |
-- creates enemies at certain positions (basically spawn them in) | |
function add_enemy(_x, _y, _type) | |
-- if youw ant to store enemy properties, I'd do it here in an array | |
-- for ex: | |
--[[ | |
local enemyData = { | |
-- hp, speed, droppedGold, timers, powerups, states, animationtime, sprite | |
"1,1,3", -- enemy type 1 | |
"2,2,3" -- enemy type 2 | |
} | |
]] | |
-- split() -- split(string, seperator) -> gives back and array | |
-- with the elements that were splitted | |
-- local dataForEnemyTypeAdded = split(enemyData[1],",") -- -> {1,1,3} | |
-- if you use this then enemy declaration would look like htis | |
--[[ | |
local enemy = { | |
x = _x, | |
y = _y, | |
type = _type, | |
hp = dataForEnemyTypeAdded[1], | |
speed = dataForEnemyTypeAdded[2], | |
droppedGold = dataForEnemyTypeAdded[3] | |
} | |
]] | |
-- if you would store data like below | |
-- first enemy would drop 1 | |
-- second type would drop 2 | |
-- third would drop | |
-- local enemyDroppedGold = {1,2,3} | |
-- local enemyHealthData = {10,20,30} | |
local enemy = { | |
x = _x, | |
y = _y, | |
type = _type, | |
hp = 10 -- we don't use it in the code, but you can | |
-- do that for however you want | |
-- you would use it like this: goldDropped = enemyDroppedGold[_type] | |
} | |
add(enemies, enemy) | |
end | |
-- this will handle reading in the wave that we want to spawn | |
-- and setup things to go | |
function load_level_data(_level) | |
-- fetch the wave from the global data strote where we have | |
-- all the waves defined already | |
-- global_wave_data[level] - is the current level's wave | |
-- split it into numbers, which are the types of the enemies | |
-- we want to spawn | |
current_level_wave = split(global_wave_data[_level], ",") | |
currentLevelWon = false | |
startNewWave = false | |
end | |
-- runs when cart starts | |
function _init() | |
-- collection to store enemies | |
enemies = {} | |
add_enemy(0,0,1) | |
-- have a collection that stores the wave | |
-- data for each level | |
global_wave_data = { | |
"1,2,1", | |
"3,3,3" | |
} | |
-- you can spice this data up, so maybe, each enemy will hold | |
-- how much time needs to pass before spawning in the next enemy | |
-- so it would be something like: | |
-- "id, timeForNext | id2, timeForNext2" | |
-- "1, 30 | 1, 20 | ...." | |
-- just split the whole thing twice. | |
-- for this you will also need a framecounter (or not and live like a rebel) | |
-- this holds the lvel we are on | |
level = 1 | |
-- did we won the game | |
won = false | |
-- the current level's wave data | |
current_level_wave = {} | |
-- start the first wave | |
load_level_data(level) | |
-- let's have a boolen to signal | |
-- if the current wave is defated | |
-- so we can press a button to start the | |
-- next one | |
currentLevelWon = false | |
startNewWave = false | |
end | |
function _update() | |
-- let's just move them to the left fro | |
-- the time being | |
for enemy in all(enemies) do | |
-- move the enemy 1 pixel per frame | |
enemy.x += 1 | |
-- if it is offscreen delete it | |
if (enemy.x > 128) then | |
if enemy.type == 3 then | |
-- here you can play with where to spawn | |
-- the enemy, first two numbers are the x,y | |
-- positions | |
add_enemy(0,0,1) | |
end | |
del(enemies, enemy) | |
end | |
-- when they die you can do all kinds of things | |
if enemy.hp < 0 then | |
-- here you can give gold to the player | |
-- gold += enemy.goldDropped | |
-- you can also do splitting enemies, | |
-- just call a new add_enemy() here | |
-- with a type check against the enemy | |
-- you want to split | |
--[[ | |
if enemy.type == 3 then | |
add_enemy(0,0,1) | |
end | |
]] | |
end | |
end | |
-- if we won and press button five, start the next | |
-- wave | |
if btnp(5) and currentLevelWon then | |
-- set the start boolean to true, so in the | |
-- empty enemy collection check in won | |
-- we can start the next level | |
startNewWave = true | |
end | |
-- define some strategy to spawn enemies | |
-- this can be basically anything you want | |
-- for now, we want to spawn an enemy every second | |
if (time() % 1 == 0) and (#current_level_wave > 0) then | |
-- grab the first eenemy from the table to spawn | |
-- deli is delete index from table and we can | |
-- save that to spawn it into the game | |
local enemyToSpawn = deli(current_level_wave, 1) | |
-- add the next enemy to the game | |
add_enemy(0, 0, enemyToSpawn) | |
end | |
-- check if all enemies are dead, if so | |
-- load in the new level data. We can do this | |
-- by checking if there are no enemies to spawn still inside | |
-- our wave data, and all enemies that are spawned are actually dead | |
if (#current_level_wave == 0) and (#enemies == 0) then | |
-- we won the current level | |
-- you can do with this boolean whatever you want to | |
-- do | |
currentLevelWon = true | |
-- if we pressed a button after winning, start a new wave | |
if (currentLevelWon and startNewWave) then | |
-- once wave is clear | |
-- increase the level counter | |
level += 1 | |
-- if we still have a wave left to fight in game | |
-- load it in | |
if level <= #global_wave_data then | |
-- load in the next level's data | |
load_level_data(level) | |
else | |
-- else we won | |
won = true | |
end | |
end | |
end | |
end | |
function _draw() | |
cls() | |
for enemy in all(enemies) do | |
-- enemy.type is 1,2,3 so I have just dummy enemy sprites | |
-- on sprite id 1,2,3 | |
spr(enemy.type, enemy.x, enemy.y) | |
end | |
if won then | |
print("won",32,32,7) | |
end | |
end | |
__gfx__ | |
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 | |
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 | |
007007000000000000b00b0000999990000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 | |
000770000088888000bbbbb000999990000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 | |
000770000080880000b0bb0000909900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 | |
007007000088888000bbbbb000999990000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
If you would like to read more like this, feel free to checkout my Ko-fi articles, with many devlogs and code rundowns like this!
https://github.com/Achie72/kofi-articles