Skip to content

Instantly share code, notes, and snippets.

@jbevain
Created November 15, 2025 02:13
Show Gist options
  • Select an option

  • Save jbevain/97dde36af5c7b1e957ce7235b80aa84a to your computer and use it in GitHub Desktop.

Select an option

Save jbevain/97dde36af5c7b1e957ce7235b80aa84a to your computer and use it in GitHub Desktop.
#:package [email protected]
// Ported from https://github.com/raysan5/raylib-games/blob/master/classics/src/arkanoid.c
// Sample game developed by Marc Palau and Ramon Santamaria
// Copyright (c) 2015 Ramon Santamaria (@raysan5)
using System.Numerics;
using Raylib_cs;
using static Raylib_cs.Raylib;
const int PlayerMaxLife = 5;
const int LinesOfBricks = 5;
const int BricksPerLine = 20;
const int screenWidth = 800;
const int screenHeight = 450;
bool gameOver = false;
bool pause = false;
Vector2 brickSize;
Player player;
Ball ball;
Brick[,] brick;
InitWindow(screenWidth, screenHeight, "Arkanoid - Raylib-cs");
SetTargetFPS(60);
Init();
while (!WindowShouldClose())
{
Update();
Draw();
}
CloseWindow();
void Init()
{
brickSize = new(screenWidth / BricksPerLine, 40);
player = new()
{
Position = new(screenWidth / 2, screenHeight * 7 / 8),
Size = new(screenWidth / 10, 20),
Life = PlayerMaxLife
};
ball = new()
{
Position = new(player.Position.X, player.Position.Y - player.Size.Y / 2 - 7),
Radius = 7,
Active = false,
};
int initialDownPosition = 50;
brick = new Brick[LinesOfBricks, BricksPerLine];
for (int i = 0; i < LinesOfBricks; i++)
{
for (int j = 0; j < BricksPerLine; j++)
{
brick[i, j].Position = new(j*brickSize.X + brickSize.X/2, i*brickSize.Y + initialDownPosition);
brick[i, j].Active = true;
}
}
}
void Update()
{
if (gameOver)
{
if (IsKeyPressed(KeyboardKey.Enter))
{
gameOver = false;
Init();
}
return;
}
if (IsKeyPressed(KeyboardKey.P))
{
pause = !pause;
}
if (pause)
{
return;
}
if (IsKeyDown(KeyboardKey.Left))
{
player.Position.X -= 5;
}
if ((player.Position.X - player.Size.X/2) <= 0)
{
player.Position.X = player.Size.X/2;
}
if (IsKeyDown(KeyboardKey.Right))
{
player.Position.X += 5;
}
if ((player.Position.X + player.Size.X/2) >= screenWidth)
{
player.Position.X = screenWidth - player.Size.X/2;
}
if (!ball.Active && IsKeyPressed(KeyboardKey.Space))
{
ball.Active = true;
ball.Speed = new(0, -5);
}
if (ball.Active)
{
ball.Position.X += ball.Speed.X;
ball.Position.Y += ball.Speed.Y;
}
else
{
ball.Position = new(player.Position.X, player.Position.Y - player.Size.Y/2 - ball.Radius);
}
if (((ball.Position.X + ball.Radius) >= screenWidth) || ((ball.Position.X - ball.Radius) <= 0)) ball.Speed.X *= -1;
if ((ball.Position.Y - ball.Radius) <= 0) ball.Speed.Y *= -1;
if ((ball.Position.Y + ball.Radius) >= screenHeight)
{
ball.Speed = new(0, 0);
ball.Active = false;
player.Life--;
}
if (CheckCollisionCircleRec(ball.Position, ball.Radius, new(player.Position.X - player.Size.X/2, player.Position.Y - player.Size.Y/2, player.Size.X, player.Size.Y)))
{
if (ball.Speed.Y > 0)
{
ball.Speed.Y *= -1;
ball.Speed.X = (ball.Position.X - player.Position.X)/(player.Size.X/2)*5;
}
}
for (int i = 0; i < LinesOfBricks; i++)
{
for (int j = 0; j < BricksPerLine; j++)
{
if (brick[i, j].Active)
{
// Hit below
if (((ball.Position.Y - ball.Radius) <= (brick[i, j].Position.Y + brickSize.Y/2)) &&
((ball.Position.Y - ball.Radius) > (brick[i, j].Position.Y + brickSize.Y/2 + ball.Speed.Y)) &&
(MathF.Abs(ball.Position.X - brick[i, j].Position.X) < (brickSize.X/2 + ball.Radius*2/3)) && (ball.Speed.Y < 0))
{
brick[i, j].Active = false;
ball.Speed.Y *= -1;
}
// Hit above
else if (((ball.Position.Y + ball.Radius) >= (brick[i, j].Position.Y - brickSize.Y/2)) &&
((ball.Position.Y + ball.Radius) < (brick[i, j].Position.Y - brickSize.Y/2 + ball.Speed.Y)) &&
(MathF.Abs(ball.Position.X - brick[i, j].Position.X) < (brickSize.X/2 + ball.Radius*2/3)) && (ball.Speed.Y > 0))
{
brick[i, j].Active = false;
ball.Speed.Y *= -1;
}
// Hit left
else if (((ball.Position.X + ball.Radius) >= (brick[i, j].Position.X - brickSize.X/2)) &&
((ball.Position.X + ball.Radius) < (brick[i, j].Position.X - brickSize.X/2 + ball.Speed.X)) &&
(MathF.Abs(ball.Position.Y - brick[i, j].Position.Y) < (brickSize.Y/2 + ball.Radius*2/3)) && (ball.Speed.X > 0))
{
brick[i, j].Active = false;
ball.Speed.X *= -1;
}
// Hit right
else if (((ball.Position.X - ball.Radius) <= (brick[i, j].Position.X + brickSize.X/2)) &&
((ball.Position.X - ball.Radius) > (brick[i, j].Position.X + brickSize.X/2 + ball.Speed.X)) &&
(MathF.Abs(ball.Position.Y - brick[i, j].Position.Y) < (brickSize.Y/2 + ball.Radius*2/3)) && (ball.Speed.X < 0))
{
brick[i, j].Active = false;
ball.Speed.X *= -1;
}
}
}
}
if (player.Life <= 0)
{
gameOver = true;
}
else
{
gameOver = true;
for (int i = 0; i < LinesOfBricks; i++)
{
for (int j = 0; j < BricksPerLine; j++)
{
if (brick[i, j].Active) gameOver = false;
}
}
}
}
void Draw()
{
BeginDrawing();
ClearBackground(Color.RayWhite);
if (gameOver)
{
DrawText("PRESS [ENTER] TO PLAY AGAIN",
GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2,
GetScreenHeight()/2 - 50, 20,
Color.Gray);
EndDrawing();
return;
}
DrawRectangleF(player.Position.X - player.Size.X/2, player.Position.Y - player.Size.Y/2, player.Size.X, player.Size.Y, Color.Black);
for (int i = 0; i < player.Life; i++)
{
DrawRectangle(20 + 40*i, screenHeight - 30, 35, 10, Color.LightGray);
}
DrawCircleV(ball.Position, ball.Radius, Color.Maroon);
for (int i = 0; i < LinesOfBricks; i++)
{
for (int j = 0; j < BricksPerLine; j++)
{
if (brick[i, j].Active)
{
if ((i + j) % 2 == 0)
DrawRectangleF(brick[i, j].Position.X - brickSize.X/2, brick[i, j].Position.Y - brickSize.Y/2, brickSize.X, brickSize.Y, Color.Gray);
else
DrawRectangleF(brick[i, j].Position.X - brickSize.X/2, brick[i, j].Position.Y - brickSize.Y/2, brickSize.X, brickSize.Y, Color.DarkGray);
}
}
}
EndDrawing();
}
static void DrawRectangleF(float x, float y, float width, float height, Color color) =>DrawRectangle((int)x, (int)y, (int)width, (int)height, color);
struct Player
{
public Vector2 Position;
public Vector2 Size;
public int Life;
}
struct Ball
{
public Vector2 Position;
public Vector2 Speed;
public int Radius;
public bool Active;
}
struct Brick
{
public Vector2 Position;
public bool Active;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment