-
Notifications
You must be signed in to change notification settings - Fork 20
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.
screenshot
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.
insert figure
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. To simplify arithmetics a bit, I generate a random number in a range [1,402]. Let's agree, if the number equal to 402, "Add Life" is generated, if it equal to 401 - "Next Level" (probability of both events is 1/402 ~ 1/400). A common bonus should be generated if the number falls in range [360, 400]. We can split in 6 intervals and assign a certain common bonustype to each. E.g. "Slowdown" is in the range [360, 366], "Accelerate] is in the range [367, 342] and so on. This assignment can be done automatically with the following construct:
elseif prob > 360 then
bonustype = common_bonuses[ math.ceil( (prob - 360) / 7 ) ]
else
figure with axis with numbers and probs
The whole code is
local bonustype_rng = love.math.newRandomGenerator( os.time() )
function bonuses.random_bonustype()
-- once in 5 levels (~400 blocks): L or N
-- once in 10 blocks - any others with roughly equal prob
local bonustype
local common_bonuses = { 11, 12, 13, 14, 15, 16 }
local prob = bonustype_rng:random( 402 )
if prob == 402 then
bonustype = 18
elseif prob == 401 then
bonustype = 17
elseif prob > 360 then
bonustype = common_bonuses[ math.ceil( (prob - 360) / 7 ) ]
else
bonustype = nil
end
return bonustype
end
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: