Flappy Jacob Prototype
I’m jamming on a flappy bird type game with my son called Flappy Jacob. We’ve implemented a heart point system, powerups based on a random number generator, bosses that have set patterns and attacks, and a scoring system.
Powerups - While you’re jumping through the game, different power ups appear randomly:
- Shield : Player can bust through the level blocks and reflect or be immune to damage from bosses.
- Feather : The player’s movement and jumping has less gravity applied. Boss projectiles slow down in speed.
- Weight : The player’s movement and jumping has more gravity applied. Boss projectiles are reflected back to the boss.
The feather and weight offer a challenging experience the way they are designed. Sometimes a weight is extremely helpful when you need to drop fast to avoid knocking into the walls. The feather can be beneficial when you need to float or glide through the walls.
If you get one of these powerups at the wrong time, there is a chance you’ll die. It does create some momentum in the game play but many times it equals death for the player.
The shield is designed help the player along no matter what the situation is, allowing the player to destory walls.
While these are some decent designs for the game’s mechanics, these powerups still need work. Instead of these powerups appearing randomly based on set percentages, we could design the powerups to be collected and the player can use them when they want to. This design is different but allows the player to make a decision instead of accepting what happens randomly.
As game designers, we shouldn’t accept any mechanic into the game unless it’s been tested, iterated on, and tested again and again.
Using elements randomly has the possibility of being a good design and can be another way to add additional layers to your game play loop. On the negative end, if we have a random mechanic causes the player to die unexpectedly, too often, the design will need more iteration. Do you need to redesign the whole mechanic? Can you get by with adding another layer to the loop? Experiment with different designs and ideas. Be positive the design is in scope and can be executed.
Introduce a “miracle” type situation: the player would just wiggle through enough space to pass through the walls. Magical moments can spread stories outside of the confines of your game world. Maybe that’s not enough or can be exploited. Some designs may need to be more clear. The player should be able to complete the levels or areas by learning from their mistakes. If random powerups cause deaths - no amount of learning will help.
To solve these issues, let’s look at allowing the player to choose which powerup to use at a given time. We limit the amount of powerups that can be carried to three and allow to player to decide when to activate.
Balancing Act
Developing a boss encounter is incredibly enjoyable. Creating all the abilities the boss can perform and attempting to balance. Picturing a design in your head seems perfect at first, right? What could go wrong? Many times when designers are coming up with a boss fight, their mind fills in the blanks. When we see the boss in action, that’s the flaws can be seen. While the boss encounter looked great in our minds and on paper, some of the gameplay wasn’t thought out at all.
For example: the bird boss that wildly kept healing over and over; when designing this fight, bird’s tuning with casting its healing spell happened too often. The only strategy that works is to get a shield powerup and reflect the bird’s projectiles back. As seen in the video, this gameplay creates a frustrating game play experience.
How do we fix this? Let the player know the boss can heal.
- The first few times the bird takes damage, it heals.
- Then when the bird is on its last life, it heals.
Once those conditions are met, the boss never heals again.
Another example:
- The healing spell has a cast timer and additional of the powerups can be used to interupt.
Instead of waiting for a shield to arrive - this allows for all the powerups to contribute to the player with defeating this boss.
Giving the Player Leeway
As game developers, we strive to create a fun and engaging experience for our players. One aspect of game design that requires careful consideration is the balance between player freedom and difficulty. In particular, collision detection is an area where a fine balance must be struck.
While pixel perfect collision detection can have its place in certain games, in many cases it can limit player freedom and experimentation. Tight collision detection may require the player to execute the same jump or move with the same distance every time, leaving little room for creativity or mistakes. On the other hand, perfect collision detection can allow for experimentation, but can make the game too forgiving and reduce the sense of challenge.
One example of balancing player freedom and difficulty is the popular game Flappy Jacob. In this game, the player controls a character who must navigate through a series of obstacles by jumping and avoiding collision. While the game has a simple concept, it can be challenging due to the tight collision detection. If the player’s hair touches the wall, the player dies.
Reducing the player’s hitbox slightly can provide additional freedom without significantly reducing the game’s difficulty. This change allows players to make small mistakes without being penalized too harshly, while still maintaining a sense of challenge. The player can still die if they are not paying attention, being reckless, or not taking their time.
// create a new sprite
const sprite = this.add.sprite(100, 100, 'mySprite');
// resize the sprite's hitbox
sprite.body.setSize(50, 50);
In this example, we create a new sprite at position (100, 100)
with the key 'mySprite'
. Then we use the setSize()
method to resize the sprite’s hitbox to a width and height of 50
pixels.
Note that the setSize()
method sets the hitbox size in pixels, so the actual size of the hitbox will depend on the scale of the sprite and the size of the texture it is using. You can use the setScale()
method to adjust the scale of the sprite if needed.
Gameplay need time and iteration
It is important to note that balancing player freedom and difficulty requires time and iteration. A design that appears perfect in theory may not play out well in practice. It is essential to spend time at the drawing board, consider multiple possibilities, and play with different concepts of gameplay to uncover unforeseen possibilities that players will inevitably find.
Through this process of iteration and testing, we can create games that strike the right balance between player freedom and difficulty, providing an enjoyable and engaging experience for players.