Sunday, December 11, 2016

Now you're playing with POWER ups

Originally I wasn't planning on including powerups (or powerdowns) in this game. I wanted to make everything dependent on the timer. If you waste too much time and the timer goes down to 0, something bad happens. If you score a good combo and push the timer beyond the max value, something good happens. While this is still the case (on a smaller scale), I have decided to change it when I found those breakout clones. Powerups, and especially powerdowns make for an interesting gameplay. Player will have to choose between getting a powerup (or avoiding a powerdown) and making sure to bounce the ball back. This adds to the challenge on the scale I am using - powerdowns can block off parts of the available area, forcing the player between picking up the unwanted effect or losing a ball. More than that it also allows me to to use those tried and true brekout bonuses. And who doesn't like a slow ball or a bigger paddle?


Anyway, let's get down to implementing the code I blatantly stole from this cart and tweaked it to work for my game.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
function _init()
bonuses = {powerups ={} }

powerups = {
 {spr = 18, col=12, func = function() padw+=4 padh+=2 end},
 {spr = 19, col=8,func = function() padw-=4 padh-=2 end}
}
end

function create_bonus(_x, _y)
 local _bonus = {x = _x-4, y = _y-4}
  local var
   if #bonuses.powerups<3 and rnd(1) <0.1+scoremulti/100 then
    var = flr(rnd(2)) + 1 
   else
    return
   end
    _bonus.spr = powerups[var].spr
    _bonus.func = powerups[var].func
    _bonus.vel = 0.5 + rnd(0.5) 
    _bonus.col = powerups[var].col
    add(bonuses.powerups, _bonus)
end

function bonus_update()
 for i in all(bonuses.powerups) do
  --clear bonuses when there are no bricks left
  if #bugs<1 then 
   create_explosion(i.x+4,i.y+8,i.col,8,2,5)
   del(bonuses.powerups,i) 
  end
  --move the bonus down
  i.y += i.vel
  --bonus/paddle collision
  if i.x+8 >= padx and i.x <= padx+padw 
  and i.y+6 >= pady then
   --make particles
   create_pixelfall(i.x+4,i.y+8,i.col,4,-1)
   create_pixelfall(i.x+4,i.y+8,i.col,4,-1)
   create_explosion(i.x+4,i.y+8,i.col,8,2,5)
   --change current frame to 1 for housekeeping
   frame_num=1
   i.func() --fire up what the powerup does
   --add some juicy effect for the paddle
   padcol=7
   pady+=1
   --destroy this brick after that
   del(bonuses.powerups,i)
  end
  --destroy brick when it 
  --reaches the bottom 
  if i.y+8 >= 128 then
   --and make it look cool with particles
   create_explosion(i.x+4,i.y+8,i.col,8,2,5)
   del(bonuses.powerups,i)
  end 
 end 
end

function bonus_draw()
 for i in all(bonuses.powerups) do
  spr(i.spr,i.x,i.y)
 end
end

Even that my first game has a bad case of messy spaghetti code, I did pick up some programming practices that I think are pretty good (correct me if I am wrong). Like implementing small features in 3 functions: one to establish it, one to update it in _update(), and one for drawing it in _draw(). This makes the code a little more manageable.

_init()

First we make a powerups table to keep our powerups. I might expand it in the future, but right now I have a sprite for the powerup (currently a placeholder), color used for particles and what the powerup does. This is where I will store all my powerups and call them when I want to spawn one. Next on my agenda is adding more powerups and making proper graphics for them.

I am not sure why the powerups are wrapped in another table (bonuses), but this is how it was in the original code and it works just fine (and as someone told me, if the code works it's a good code, so I am leaving it for time being). I might need to go through it and see if it works without the wrapper.

create_bonus()

I call create_bonus each time a ball hits a brick, with the coordinates where I want the powerup to spawn. In my case it is the brick's X and Y, adjusted to spawn it in the center of the brick on X and below the brick on Y (this is what the -4 in local variables helps with).

Then I am doing a quick random check, so a powerup does not spawn on every brick hit. It is 10% that goes bigger if you score a combo of bricks. I am also limiting the amount of active powerups on screen to 3 [line 13]. If that returns true, I am choosing a random powerup [var variable, line 14], else I am stopping the function with RETURN.

The powerup chosen with var is a new table that holds all the info [lines 18-21] and stores it in the powerups table [line 22], so I can call them in the next two functions. I know it is a little confusing - tables within tables - but once you wrap your head around it will make perfect sense.

update_bonus()

This function is responsible for making the powerup fall down, fire its function when caught with the paddle and destroying it when it reaches the bottom of the screen. There is one addon, that is there for keeping the board clean between levels by destroying all the active powerups when there are no bricks (called bugs because of earlier idea for the game) left.

This function reads the data we have stored in the previous function for each existing powerup [line 26] and changes them. So every frame each powerup moves down [i.y += i.vel] and when it touches either the paddle [lines 35,36] or bottom of the screen it does something else - check the code comments for that.

Store this function in your _update(), so it works each frame.

draw_bonus()

Lastly, we just draw all the powerups in _draw() with a simple function that will show a sprite at X and Y each frame until the entry is deleted.

END

...and that's it. With 3 functions and some tables we have added a feature to the game. Now, next step is adding cool powerups that the player will enjoy. My plan is to make more powerdowns spawn, the higher the level of the game. This will add to the challenge of the game and will create a a manageable difficulty curve. But, that's a topic for another post.

No comments:

Post a Comment