Skip to content

Instantly share code, notes, and snippets.

@naranyala
Created June 19, 2025 23:51
Show Gist options
  • Save naranyala/9acb1477aa2bbc0d3bcea2d146033366 to your computer and use it in GitHub Desktop.
Save naranyala/9acb1477aa2bbc0d3bcea2d146033366 to your computer and use it in GitHub Desktop.
snake game in odin code using raylib
package main
import rl "vendor:raylib"
import "core:math/rand"
main :: proc() {
rl.InitWindow(800, 600, "Simple Snake Game")
defer rl.CloseWindow()
rl.SetTargetFPS(60)
// Snake body
snake_body: [dynamic]rl.Vector2
defer delete(snake_body)
snake_size: i32 = 20
// Initialize snake with head
append(&snake_body, rl.Vector2{400, 300})
// Snake direction
dir_x: i32 = snake_size
dir_y: i32 = 0
// Food
food_x: i32 = 200
food_y: i32 = 200
// Game timer
timer: f32 = 0.0
move_speed: f32 = 0.2
// Score
score: i32 = 0
for !rl.WindowShouldClose() {
dt := rl.GetFrameTime()
timer += dt
// Input handling
if rl.IsKeyPressed(rl.KeyboardKey.UP) && dir_y == 0 {
dir_x = 0
dir_y = -snake_size
}
if rl.IsKeyPressed(rl.KeyboardKey.DOWN) && dir_y == 0 {
dir_x = 0
dir_y = snake_size
}
if rl.IsKeyPressed(rl.KeyboardKey.LEFT) && dir_x == 0 {
dir_x = -snake_size
dir_y = 0
}
if rl.IsKeyPressed(rl.KeyboardKey.RIGHT) && dir_x == 0 {
dir_x = snake_size
dir_y = 0
}
// Move snake
if timer >= move_speed {
timer = 0.0
// Get current head position
head := snake_body[0]
new_head := rl.Vector2{head.x + f32(dir_x), head.y + f32(dir_y)}
// Add new head
inject_at(&snake_body, 0, new_head)
// Check food collision
if i32(new_head.x) == food_x && i32(new_head.y) == food_y {
score += 10
// Move food to new random position
food_x = i32(rand.int31() % 39) * snake_size
food_y = i32(rand.int31() % 29) * snake_size
} else {
// Remove tail if no food eaten
pop(&snake_body)
}
}
// Check wall collision and self collision
if len(snake_body) > 0 {
head := snake_body[0]
// Wall collision
if head.x < 0 || head.x >= 800 || head.y < 0 || head.y >= 600 {
// Reset game
clear(&snake_body)
append(&snake_body, rl.Vector2{400, 300})
dir_x = snake_size
dir_y = 0
score = 0
}
// Self collision
for i in 1..<len(snake_body) {
segment := snake_body[i]
if head.x == segment.x && head.y == segment.y {
// Reset game
clear(&snake_body)
append(&snake_body, rl.Vector2{400, 300})
dir_x = snake_size
dir_y = 0
score = 0
break
}
}
}
// Drawing
rl.BeginDrawing()
rl.ClearBackground(rl.BLACK)
// Draw snake body
for segment, i in snake_body {
color := rl.GREEN
if i == 0 { // Head
color = rl.LIME
}
rl.DrawRectangle(i32(segment.x), i32(segment.y), snake_size, snake_size, color)
}
// Draw food
rl.DrawRectangle(food_x, food_y, snake_size, snake_size, rl.RED)
// Draw score with actual value
score_text := rl.TextFormat("Score: %d", score)
rl.DrawText(score_text, 10, 10, 20, rl.WHITE)
// Draw controls
rl.DrawText("Use Arrow Keys", 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