-
Notifications
You must be signed in to change notification settings - Fork 17
Random Bonuses
Currently bonuses generated on bricks destruction are predefined in the level description. In this part I want to add random bonus generation into the game.
First, in the level map some way to denote that a bonus to create on brick destruction
should be random is necessary. It's possible to reserve any number or a string for this, but I simply use 00
.
function bonuses.bonustype_denotes_random( bonustype )
return bonustype == 0
end
Bonuses are generated on bricks destruction by bonus.generate_bonus
function.
function bricks.brick_hit_by_ball( i, brick, shift_ball, bonuses )
if bricks.is_simple( brick ) then
bonuses.generate_bonus(
vector( brick.position.x + brick.width / 2,
brick.position.y + brick.height / 2 ),
brick.bonustype )
table.remove( bricks.current_level_bricks, i )
.....
end
end
In this function, a bonustype associated with the brick is checked.
If it is one of the previously defined "valid" bonustypes (from 11 to 18),
a corresponding bonus is generated.
Check on random bonustype also should be placed in this function.
To explicitly tell, that no bonus should be associated with the brick, it is enough to provide any
"invalid" bonustype, such as -1
.
function bonuses.generate_bonus( position, bonustype )
if bonuses.bonustype_denotes_random( bonustype ) then
bonustype = bonuses.random_bonustype()
end
if bonuses.valid_bonustype( bonustype ) then
bonuses.add_bonus( bonuses.new_bonus( position, bonustype ) )
end
end
function bonuses.valid_bonustype( bonustype )
if bonustype and bonustype > 10 and bonustype < 19 then
return true
else
return false
end
end
Random bonus generation is done under following scheme. There are valuable bonuses and common bonuses; valuable are "Add Life" and "Next Level", common are everything else. I want a common bonus to appear approximately each 10 brick, and a valuable bonus - approximately once in 5 levels. There are maximum 8*11 ~ 90 bricks in each level. Since usually there are some unbreakable and missing bricks, there are, roughly 80 bricks per level or 400 bricks in 5 levels. So, on brick destruction, a common bonus (of randomly decided type) should drop with probability 1/10 and one of the valuable bonuses - with probability 1/400. It might be reasonable to increase those probabilities for armored blocks compared to simple, but I don't want to do this.
If a random number in interval [1,400] is generated, a probability to get a certain predefined number, say 293 or 400, is exactly 1/400. To obtain an event with probability of 1/10, it is necessary to agree on 40 such numbers ( 40 numbers * 1/400 prob for each number = 1/10), an interval [360, 399] for example.
It is possible to generate a bonus with two rolls of dice: on the first roll decide whether a valuable bonus should be generated, a common, or no bonus at all. Then in the two former cases decide an exact type with the second roll.
local bonustype_rng = love.math.newRandomGenerator( os.time() ) --(*1)
function bonuses.random_bonustype()
local bonustype
local prob = bonustype_rng:random( 400 )
if prob == 400 then
bonustype = bonuses.choose_random_valuable_bonus()
elseif prob >= 360 then
bonustype = bonuses.choose_random_common_bonus()
else
bonustype = nil
end
return bonustype
end
function bonuses.choose_random_valuable_bonus()
local valuable_bonustypes = { 17, 18 }
return valuable_bonustypes[ bonustype_rng:random( #valuable_bonustypes )]
end
function bonuses.choose_random_common_bonus()
local common_bonustypes = { 11, 12, 13, 14, 15, 16 }
return common_bonustypes[ bonustype_rng:random( #common_bonustypes )]
end
(*1): To generate random bonustype first it is necessary to initialize random number generator.
Instead of using two calls to a random number generator, it is possible to generate a bonus in a single call. For this, it is necessary to map a correspondence between certain intervals and bonustypes, instead of dividing the range simply into "common bonuses" and "valuable bonuses".
The "valuable bonus" event with probability 1/400 consists of two events "Next Level" and "Add Life" with probabilities 1/800 (1/800 prob for "add life" + 1/800 prob for "next level" = 1/400 prob for "valuable bonus"). Thus, instead of using range [1,400] it is necessary to use [1,800]. Let's assign 800 to "Add Life", and 799 to "Next Level". A common bonus should be generated if the number falls in a range [798-800/10=718, 798]. It should be split in 6 intervals and a common bonustype assigned to each one, e.g. "Slowdown" is in the range [718, 718 + (798-718)/6], "Accelerate" is in the range [718 + 4*(798-718)/6, 718 + 5*(798-718)/6] and so on.
local bonustype_rng = love.math.newRandomGenerator( os.time() )
function bonuses.random_bonustype()
local bonustype
local common_bonuses = { 11, 12, 13, 14, 15, 16 }
local common_bonus_range = (798 - 718) / ( #common_bonuses )
local prob = bonustype_rng:random( 800 )
if prob == 800 then
bonustype = 18
elseif prob == 799 then
bonustype = 17
elseif prob >= 718 then
bonustype =
common_bonuses[1 + math.floor(( prob - 718 ) / common_bonus_range)] --(*1)
else
bonustype = nil
end
return bonustype
end
(*1): such method introduces rounding which results in uneven probabilities, but the difference is not very significant.
Feedback is crucial to improve the tutorial!
Let me know if you have any questions, critique, suggestions or just any other ideas.
Chapter 1: Prototype
- The Ball, The Brick, The Platform
- Game Objects as Lua Tables
- Bricks and Walls
- Detecting Collisions
- Resolving Collisions
- Levels
Appendix A: Storing Levels as Strings
Appendix B: Optimized Collision Detection (draft)
Chapter 2: General Code Structure
- Splitting Code into Several Files
- Loading Levels from Files
- Straightforward Gamestates
- Advanced Gamestates
- Basic Tiles
- Different Brick Types
- Basic Sound
- Game Over
Appendix C: Stricter Modules (draft)
Appendix D-1: Intro to Classes (draft)
Appendix D-2: Chapter 2 Using Classes.
Chapter 3 (deprecated): Details
- Improved Ball Rebounds
- Ball Launch From Platform (Two Objects Moving Together)
- Mouse Controls
- Spawning Bonuses
- Bonus Effects
- Glue Bonus
- Add New Ball Bonus
- Life and Next Level Bonuses
- Random Bonuses
- Menu Buttons
- Wall Tiles
- Side Panel
- Score
- Fonts
- More Sounds
- Final Screen
- Packaging
Appendix D: GUI Layouts
Appendix E: Love-release and Love.js
Beyond Programming: