JDBC · Follow
--
This is the second part of my previous blog post Flappy Bird Clone with Raylib and C# (Part 1) where we begun to develop a basic Flappy Bird clone with the amazing Raylib library and C# programming language.
First step is to download the 10 PNG images from https://github.com/samuelcust/flappy-bird-assets in order to add them to the sprites folder within our Flappy Bird project:
Next step is editing Game.cs class file to apply the following changes:
- Add new score property as integer that saves the current game score.
- Define new scoreTextures property as Texture2D list.
- The new scorePosX property contains the X coordinate int value of the current score PNG texture on the screen.
public class Game
{
public Bird bird {get; private set;} public int score {get; set;}
private List<Texture2D> scoreTextures = new();
private int scorePosX = SCREEN_WIDTH / 2;
Let’s define a new LoadScoreTextures method to initialize scoreTextures as the list of Texture2D containing 10 PNG score images:
private void LoadScoreTextures() {
for (int index = 0; index < 10; index++){
var fileName = "sprites/" + index + ".png";
Image numberImage = LoadImage(fileName);
Texture2D numberTexture = LoadTextureFromImage(numberImage);
this.scoreTextures.Add(numberTexture);
UnloadImage(numberImage);
}
}
The new DrawScore method draws the properly score texture depending on the value of score property at the top of the screen.
private void DrawScore() { string scoreString = this.score.ToString();
int counter = scoreString.Length;
foreach (char digit in scoreString) {
int index = digit - '0';
int scoreX = this.scorePosX - (24 * (counter - 1));
DrawTexture(this.scoreTextures.ElementAt(index), scoreX, 20, Color.White);
counter--;
}
}
Checking collision between bird and pipes
Raylib library provides multiple methods to check collisions between rectangles and circles as we can view in the Raylib Cheatsheet
We focus on the CheckCollisionRecs function to check collision between two rectangles: the pipe rectangle and the rectangle containing the bird.
When bird is flying, then it could collide with every pipe. We will need a new class Collide function to check collisions between the bird and all pipes.
Edit Pipe.cs class file to add a new Collide method to check any collision between the bird rectangle and the two Pipe rectangles(up and down).
public bool Collide(Bird bird) { Rectangle rec1 = new Rectangle(this.posX, this.posY, PIPE_WIDTH, PIPE_HEIGHT);
Rectangle rec2 = new Rectangle(this.posX, this.posY - PIPE_HEIGHT - PIPE_GAP, PIPE_WIDTH, PIPE_HEIGHT);
Rectangle rectBird = new Rectangle(bird.posX, bird.posY, bird.BIRD_WIDTH, bird.BIRD_HEIGHT);
return CheckCollisionRecs(rec1, rectBird) || CheckCollisionRecs(rec2, rectBird);
}
Add a new CheckCollision method to the PipeManager class file.
We iterate over the pipe list to check any possible collision between them and the bird by using the Collide method of the Pipe class.
If any collision is detected then the CheckCollision function returns true, otherwise it returns false.
public bool CheckCollision(Bird bird) {
foreach (Pipe pipe in this.pipeList) {
if (pipe.Collide(bird)) {
return true;
}
}
return false;
}
Game over scene
Download Game Over png image from https://github.com/samuelcust/flappy-bird-assets and add it to your sprites folder in the game project.
This image will be shown on the game scene when the flying bird collides with any pipe.
Two new properties must be added to Game class file:
private Texture2D textureGameover;private bool gameOver = false;
The textureGameover property stores the Game Over image and the gameover property should be true when bird collides with any pipe.
Collisions will be checked in the game loop within the Game class file.
New LoadGameOverTexture method must be added with the following content:
private void LoadGameOverTexture() {
Image gameoverImage = LoadImage("sprites/gameover.png");
this.textureGameover = LoadTextureFromImage(gameoverImage);
UnloadImage(gameoverImage);
}
Edit the Game class file in the following way within the main loop to check gameOver property:
// Main loop
while (!WindowShouldClose())
{
BeginDrawing();
ClearBackground(Color.White); // Check collision bird and pipes
if (this.pipeManager.CheckCollision(this.bird)) {
this.gameOver = true;
}
// Check collision against the floor
if (this.bird.posY > (SCREEN_HEIGHT - 130)) {
this.gameOver = true;
}
this.HandleInput();
if (!this.gameOver) {
DrawTexture(textureBackground, x, y, Color.White);
this.pipeManager.Update(this);
DrawTexture(textureBase, x, SCREEN_HEIGHT - 112, Color.White);
this.bird.Update(xBird, yBird);
this.DrawScore();
} else {
DrawTexture(textureBackground, x, y, Color.White);
DrawTexture(textureBase, x, SCREEN_HEIGHT - 112, Color.White);
DrawTexture(textureGameover, 50, 120, Color.White);
this.DrawScore();
}
EndDrawing();
}
If bird collides against the floor the game is also over. Execute the Flappy Bird Clone with dotnet commands:
user@linux:~/raylib/flappy_bird$ dotnet build && dotnet run
This is how looks the Game Over scene when the bird collides with pipes:
We need to restart the game from Game Over scene, so push the Enter key to start game again.
Edit the handleInput method in the Game class:
private void HandleInput() { if (!gameOver) {
// Input handling
if (IsKeyDown(KeyboardKey.Space)) {
this.yBird -= BIRD_DOWN;
} else {
this.yBird += BIRD_UP;
}
} else {
if (IsKeyDown(KeyboardKey.Enter)) {
this.InitBirdPosition();
this.pipeManager = new PipeManager(SCREEN_WIDTH);
this.gameOver = false;
}
}
}
}
Now the game is already playable, happy flying.
The full source code of this Flappy Bird clone is available in https://github.com/jdbcdev/flappy-bird
Do not hesitate to leave a comment.