Log In  

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!

P#78545 2020-06-26 17:08

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.

P#78557 2020-06-26 20:30 ( Edited 2020-06-27 07:40)

@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).

P#78566 2020-06-27 08:01 ( Edited 2020-06-27 08:08)

@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

Cart #gball-0 | 2020-06-27 | Code ▽ | Embed ▽ | No License

P#78569 2020-06-27 10:23

@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.)

P#78572 2020-06-27 11:54 ( Edited 2020-06-27 12:06)
1

@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!

P#78578 2020-06-27 16:01

[Please log in to post a comment]

Follow Lexaloffle:          
Generated 2024-04-19 17:50:52 | 0.033s | Q:22