Skip to content

Instantly share code, notes, and snippets.

@naranyala
Created June 19, 2025 23:49
Show Gist options
  • Save naranyala/7da12c5cd0a38ed0b5e4f08c30ca7350 to your computer and use it in GitHub Desktop.
Save naranyala/7da12c5cd0a38ed0b5e4f08c30ca7350 to your computer and use it in GitHub Desktop.
pong game in odin code using raylib
package main
import "core:fmt"
import rl "vendor:raylib"
// Constants
WINDOW_WIDTH :: 800
WINDOW_HEIGHT :: 600
PADDLE_SPEED :: f32(300.0)
BALL_SPEED :: f32(200.0)
BALL_MAX_SPEED :: f32(400.0)
BALL_RADIUS :: f32(10.0)
main :: proc() {
rl.InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Pong")
defer rl.CloseWindow()
rl.SetTargetFPS(60)
// Game objects
left_paddle := rl.Rectangle{50, 250, 20, 100}
right_paddle := rl.Rectangle{730, 250, 20, 100}
ball := rl.Vector2{400, 300}
ball_velocity := rl.Vector2{BALL_SPEED, BALL_SPEED}
left_score: i32 = 0
right_score: i32 = 0
for !rl.WindowShouldClose() {
dt := rl.GetFrameTime()
handle_input(&left_paddle, &right_paddle, dt)
update_ball(&ball, &ball_velocity, &left_paddle, &right_paddle, dt, &left_score, &right_score)
draw_game(left_paddle, right_paddle, ball, left_score, right_score)
}
}
handle_input :: proc(
left: ^rl.Rectangle,
right: ^rl.Rectangle,
dt: f32,
) {
if rl.IsKeyDown(.W) && left.y > 0 {
left.y -= PADDLE_SPEED * dt
} else if rl.IsKeyDown(.S) && left.y < f32(WINDOW_HEIGHT) - left.height {
left.y += PADDLE_SPEED * dt
}
if rl.IsKeyDown(.UP) && right.y > 0 {
right.y -= PADDLE_SPEED * dt
} else if rl.IsKeyDown(.DOWN) && right.y < f32(WINDOW_HEIGHT) - right.height {
right.y += PADDLE_SPEED * dt
}
}
update_ball :: proc(
ball: ^rl.Vector2,
velocity: ^rl.Vector2,
left: ^rl.Rectangle,
right: ^rl.Rectangle,
dt: f32,
left_score: ^i32,
right_score: ^i32,
) {
ball.x += velocity.x * dt
ball.y += velocity.y * dt
// Top/Bottom wall collision
if ball.y <= BALL_RADIUS || ball.y >= f32(WINDOW_HEIGHT) - BALL_RADIUS {
velocity.y *= -1
}
// Left paddle collision
if rl.CheckCollisionCircleRec(ball^, BALL_RADIUS, left^) {
velocity.x *= -1
velocity.y += (ball.y - (left.y + left.height / 2)) * 2
velocity.y = clamp(velocity.y, -BALL_MAX_SPEED, BALL_MAX_SPEED)
ball.x = left.x + left.width + BALL_RADIUS
}
// Right paddle collision
if rl.CheckCollisionCircleRec(ball^, BALL_RADIUS, right^) {
velocity.x *= -1
velocity.y += (ball.y - (right.y + right.height / 2)) * 2
velocity.y = clamp(velocity.y, -BALL_MAX_SPEED, BALL_MAX_SPEED)
ball.x = right.x - BALL_RADIUS
}
// Score logic
if ball.x < 0 {
right_score^ += 1
reset_ball(ball, velocity)
} else if ball.x > f32(WINDOW_WIDTH) {
left_score^ += 1
reset_ball(ball, velocity)
}
}
reset_ball :: proc(ball: ^rl.Vector2, velocity: ^rl.Vector2) {
ball.x = 400
ball.y = 300
velocity.x = BALL_SPEED if rl.GetRandomValue(0, 1) == 0 else -BALL_SPEED
velocity.y = BALL_SPEED
}
clamp :: proc(value, min, max: f32) -> f32 {
if value < min do return min
if value > max do return max
return value
}
draw_game :: proc(
left, right: rl.Rectangle,
ball: rl.Vector2,
left_score, right_score: i32,
) {
rl.BeginDrawing()
rl.ClearBackground(rl.BLACK)
rl.DrawRectangleRec(left, rl.WHITE)
rl.DrawRectangleRec(right, rl.WHITE)
rl.DrawCircleV(ball, BALL_RADIUS, rl.WHITE)
left_text := fmt.ctprintf("Left: %d", left_score)
right_text := fmt.ctprintf("Right: %d", right_score)
rl.DrawText(left_text, 10, 10, 20, rl.WHITE)
rl.DrawText(right_text, 700, 10, 20, rl.WHITE)
rl.DrawText("W/S: Left | UP/DOWN: Right", 10, 550, 16, rl.GRAY)
rl.EndDrawing()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment