Demaking of B.A.S.


Birds and Saws demake

Discovering PICO-8 a few months ago (yes, I live under a rock), I was captivated by the games crafted by its community. This reignited my long-forgotten passion of creating games for pure enjoyment.

Contemplating game ideas, I realized that my lack of knowledge in LUA and the PICO-8’s capabilities and API might lead to ideas that are not achievable. As a learning exercise, I decided to create a demake of a 2014 iOS game of mine, Birds and Saws.

In this game, the player assumes the role of a bird, navigating left and right to evade blades emerging from the bottom of the screen.

The main goals of the game’s design:

  • Simplicity: No complex menu systems. The player character is part of the welcome screen and just a tap away from starting the game.
  • Quick Runs: Short gameplay sessions (a few minutes at most) and swift restarts after death (no more than a 1-second transition). Perfect for those spare 2-minute breaks.
  • Game Feel: Emphasis on the overall gaming experience rather than incorporating multiple levels, collectibles, boosts or upgrades.

Design

Experimenting with the PICO-8’s cute sprite editor, I quickly realized that porting graphics from the original wasn’t feasible due to limited colors. Opting for a darker theme that resembled the original sprites, I aimed to maintain the game’s aesthetic.

The bird features four animated states: idle when it is standing on a wall, another when it’s scared of the bottom blades, a flying (jumping) animation, and a special one when it’s about to die.

The background is composed of two large tiles that gradually fade to black at the edges. This design choice ensures the circular blades remain visible and stand out against the black background. The warm light from the window accentuates the transition from warm to cold shading on the wall tiles.

Bottom Blades

The blades gradually get faster until they reach a set maximum speed, which is determined by the player’s score. Although players can outrun the blades, they might end up jumping more frequently and at a faster pace, increasing the risk of making mistakes.

To ensure players are aware of the potential danger, the blades’ position is updated in a way that keeps them visible. This serves as a reminder that slowing down could result in the blades catching up. While it may seem like the blades are speeding up as the player goes faster, it’s actually just an illusion. When the player stops, the true speed is applied because the player is no longer outpacing the bottom blades.

I implemented this to prevent fast players from getting too far ahead of the blades at the game’s start when the blades are moving slowly. It also ensures that later in the game, the blades don’t take too long to catch up with the player or fail to catch up altogether.

The initial speed is set to 0.5 pixels per frame, and the maximum speed is capped at 1.7 pixels per frame. I personally can keep the tempo up to 1.9.

The Camera

The camera smoothly tracks the player unless moving exceptionally fast. By checking the player’s relative position on screen, a threshold is set. If the player is lower than half the screen, the camera tracks and lags behind, creating a smoother experience.

Player Jump

Balancing player jump speed and the bottom blades proved challenging initially. Recognizing a rubbery feel due to waiting for the jump to end before initiating a new one, I adjusted the logic. Now, if the player taps mid-jump, it finishes the current jump and initiates the next, providing players with a more controlled feeling.

The player jump implementation consists of three main properties:

  • tile_pos = the tile position where the player landed.
  • jumping = a boolean indicating whether the player is in the air.
  • jump_tile_pos= the jump position added to tile_position. This value ranges from 0 to 1 (start to finish) and increments when the player is in the air. Upon reaching 1, the tile_pos is updated, the jumping is set to false and jump_tile_pos to 0.

Check this code snippet of the logic that handles the player’s jump, ensuring that if the player is mid-jump, the move is completed by updating tile_pos and setting jump_tile_pos to 0:

if self.jumping then
	self.tilepos-=1
else
	self.jumping=true
end
self.jumping_pos=0

Here is an example where the player can press the right, left, right buttons at varying speeds, ensuring the player always lands on position (3). This enhances the game experience as players learn to play faster.

Slow-Mo Effect

I also introduced an animation depicting the bird slowing down in a desperate attempt to evade the circular saw. This is a new element that was not part of the original game.

The slowdown effect is achieved by adjusting the jump speed when it is detected that the player will die, based on a specified threshold. The threshold varies depending on whether the player is jumping towards the opposite wall or not.

Check this code snippet where I set the speed of the jump:

local threshold = self.jump_changes_direction and -0.7 or -0.275
local speed = ternary(
	will_die and self.jump_tile_pos < threshold, 
	self.jump_speed_will_die,
	self.jump_speed
)

--helper function
function ternary (cond,T,F)
    if cond then return T else return F end
end

If the slowdown is active, the “will die” animation is triggered, enhancing the game’s dynamics.

I enabled jumps to be controlled using both the arrows and the X/Z keys. I did this because I think the optimal way to play and improve speed is by using both hands, similar to the original game.

The making of the game took around 2 weeks including me learning about PICO-8 and LUA. Feel free to share your feedback or post your highest score.

Files

bas_windows.zip 987 kB
Dec 10, 2023
bas_osx.zip 3.2 MB
Dec 10, 2023
bas_linux.zip 749 kB
Dec 10, 2023
bas_raspi.zip 2.1 MB
Dec 10, 2023

Get B.A.S.

Download NowName your own price

Comments

Log in with itch.io to leave a comment.

Thanks for the write up, lots of cool insights in here. I liked how you had the main goals guiding the design, the final game feels really focused as a result. I've topped off at a high score of 261 so far!

Thank you for investing your time in playing the game and taking a moment to read my post. Your engagement is truly appreciated.