Hi everyone, I'm fairly new to programming and Pico8.
I'm trying to add powerups to one of my games. I've made an empty table and a function to create each powerup within it.
The problem I'm having is that I'd like one single random powerup to be created depending on the score (say when score==5)
I've managed to do this but the problem was that a second powerup gets created before the player has the chance to up the score.
I've tried to use time() and also creating a boolean but I haven't managed to get 1 single powerup on screen at a time, I either get more than one or nothing.
What would be the best way to do this?
here's the code I have at the moment:
function _init() score=0 powerups={} end function _update() if score==5 then powerup=true end if powerup==true then create_powerup() end end function _draw() for capsule in all(powerups) do spr(capsule.sp,capsule.x,capsule.y) end end --powerups powerups_start=5 total_powerups=4 fall=1 function create_powerup() capsule={ sp=powerups_start+flr(rnd(total_powerups)), x=flr(rnd(100)+20), y=flr(rnd(10))+20 } add(powerups,capsule) powerup=false if powerup==false then del(powerups,capsule) end end function update_powerup() for capsule in all(powerups) do capsule.y+=fall if capsule.x>=player.x and capsule.x<=player.x+player.w and capsule.y==player.y-player.h then sfx(2) lives.left+=1 del(powerups,capsule) end if capsule.y>128 then del(powerups,capsule) end end end |
Thanks in advance!
function _update() if some_condition_that_increases_score then score=score+1 if score==5 then create_powerup() end end end |
Edit: Changed the code I'd written, amongst other things to add a pseudocode condition for the score increasing, so the code overall makes more sense.
Explanation: You can put one if statement inside another - this concept is called a nested if statement. Writing it this way means that if score==5 will only be checked if the score is also increasing, not on every frame.
@AtticusFinn I thought I'd revisit this today and give you enough code to hopefully demonstrate it working. These are based on your own _init _update and _draw functions and should be able to replace them.
function _init() debug=true score=0 powerups={} framecounter=0 end function _update() local scoreadd=0 framecounter=framecounter+1 if framecounter>=30 then if debug then scoreadd=scoreadd+1 end framecounter=0 end if scoreadd>0 then score=score+scoreadd if score==5 then create_powerup() end end end function _draw() cls() for capsule in all(powerups) do spr(capsule.sp,capsule.x,capsule.y) end if debug then print("Score:"..score,1,1,6) print("No.powerups:"..#powerups,1,7,6) end end |
I will briefly explain the code I have added.
Anything with debug is used to guard portions of the code that I only want to run during development. When debug is set to true in _init, then the code guarded by it with if statements (such as if debug then) anywhere in the rest of the program will run. When set to false that code won't run. Here I have used debug to guard/fence-off/make-conditional the score increase in _update and some feedback in _draw. Generally any debug code can be removed when you are done implementing that feature.
I have added framecounter. Pico-8 has 30 frames a second (presuming normal operation), so the way this is coded, with scoreadd going up one every 30 frames, about every second the score should increase by 1.
I have added scoreadd because there could be multiple conditions that cause the score to increase in your game. Setting it to 0 at the start of _update, then adding however much you want to it throughout the course of _update, then adding scoreadd to score at the end of _update, means that there only need be one place in _update where score itself gets updated; this means that anything dependent on an increase in score need only be in that one place - in the example you were trying to create I feel this will be useful.
I have added a cls() statement to _draw. This clears the screen.
In the feedback I have provided, I have used #powerups; the # returns the number of items in the powerups table (with some provisos, such as the number of items does not include specifically named items, only sequentially added items - because you are using add and del and not naming items you don't need to worry about these provisos).
@remcode Hey thanks for the replies and explanation, I appreciate it.
Your code works exactly as what I have in mind but when I change debug to false the powerup doesn't get created. I tried tinkering with it but had no luck.
Here's the cart if it helps
@AtticusFinn I had presumed the creation of the powerup when the score hit a certain amount was only a test so had put it as debug code in _update; find the following section:
if framecounter>=30 then if debug then scoreadd=scoreadd+1 end framecounter=0 end |
and change it to:
if framecounter>=30 then scoreadd=scoreadd+1 framecounter=0 end |
The score will now increase and the powerup be generated with debug set to false.
(Edit: I have now looked at the cart and see you have made this change already; great!)
If you wanted the creation of the powerup to occur without the score increasing, you would need some other way of determining when the powerup should be created. For example, it is possible to use a variable such as seconds which goes up by one whenever framecounter>=30 (instead of scoreadd going up by 1), then you could test for when seconds has reached certain amounts to release new powerups.
It's possible to use code such as:
if framecounter>=30 then framecounter=0 seconds=seconds+1 if seconds%30==0 then create_powerup() end end |
(Edit: enlarged above section of code to make it more obvious where to put it.)
In conjunction with making seconds increment every 30 frames, this would mean that every 30 seconds a new powerup would be created. (% is the modulo operator; see https://en.wikipedia.org/wiki/Modulo_operation for a rather full explanation. Essentially when seconds is at a multiple of 30 the modulo operator will return 0, so seconds%30==0 will be true every time that the seconds variable hits a multiple of 30.)
(Edit: You could of course just test framecounter directly like this rather than resetting it to 0, but pico-8's number limits will overflow after something like 16 minutes if you just add 1 to a variable every frame; see https://en.wikipedia.org/wiki/Integer_overflow for an explanation.)
@remcode That works perfectly! I didn't know about the modulo operator, it's exactly what I needed. Thank you for the help and for being so thorough, I really appreciate it!
[Please log in to post a comment]