Setup
-
Install Rust :
-
Select default installation (1).
-
File System :
-
The code needs to be inside the
srcfile, as it's the default target.
. ├── cargo.toml ├── cargo.lock // created when running `cargo run` ├── target // created when running `cargo run` └── src └── main.rs -
-
cargo.toml :
[package] name = "moving_ball" version = "0.1.0" edition = "2024" [dependencies] raylib = "5.5.1" -
Dependencies :
-
Requires
glfw,cmake, andcurl. -
When running
cargo run, all dependencies are downloaded. -
"35 packages downloaded".
-
The
-
-
Execute :
-
cargo run
-
Moving Ball
-
cargo.toml:
[package]
name = "moving_ball"
version = "0.1.0"
edition = "2024"
[dependencies]
raylib = "5.5.1"
-
main.rs:
/*
cargo run
*/
use raylib::prelude::*;
fn main() {
const SCREEN_WIDTH: i32 = 800;
const SCREEN_HEIGHT: i32 = 450;
let (mut rl, thread) = raylib::init()
.size(SCREEN_WIDTH, SCREEN_HEIGHT)
.title("Raylib in Rust | 1_moving_ball")
.build();
rl.set_target_fps(60);
// Initialize ball
let mut ball_position = Vector2 {
x: SCREEN_WIDTH as f32 / 2.0,
y: SCREEN_HEIGHT as f32 / 2.0,
};
while !rl.window_should_close() {
// Update ball position
if rl.is_key_down(KeyboardKey::KEY_RIGHT) {
ball_position.x += 2.0;
}
if rl.is_key_down(KeyboardKey::KEY_LEFT) {
ball_position.x -= 2.0;
}
if rl.is_key_down(KeyboardKey::KEY_UP) {
ball_position.y -= 2.0;
}
if rl.is_key_down(KeyboardKey::KEY_DOWN) {
ball_position.y += 2.0;
}
// Draw
let mut d = rl.begin_drawing(&thread);
d.clear_background(Color::RAYWHITE);
d.draw_text("move the ball with arrow keys", 10, 10, 20, Color::DARKGRAY);
d.draw_circle_v(ball_position, 50.0, Color::MAROON);
}
}
Collect The Coin
-
cargo.toml:
[package]
name = "collect_the_coins"
version = "0.1.0"
edition = "2024"
[dependencies]
raylib = "5.5.1"
rand = "0.8"
-
main.rs:
/*
cargo run
*/
use raylib::prelude::*;
use rand::Rng;
const MAX_COINS: usize = 20;
const PLAYER_SPEED: f32 = 4.0;
struct Player {
position: Vector2,
radius: f32,
score: i32,
}
struct Coin {
position: Vector2,
radius: f32,
active: bool,
}
fn main() {
const SCREEN_WIDTH: i32 = 800;
const SCREEN_HEIGHT: i32 = 600;
let (mut rl, thread) = raylib::init()
.size(SCREEN_WIDTH, SCREEN_HEIGHT)
.title("Raylib in Rust | 2_collect_the_coins")
.build();
rl.set_target_fps(60);
// Initialize player
let mut player = Player {
position: Vector2::new(400.0, 300.0),
radius: 20.0,
score: 0,
};
// Initialize coins
let mut rng = rand::thread_rng();
let mut coins: Vec<Coin> = (0..MAX_COINS)
.map(|_| Coin {
position: Vector2::new(
rng.gen_range(20.0..(SCREEN_WIDTH as f32 - 20.0)),
rng.gen_range(20.0..(SCREEN_HEIGHT as f32 - 20.0)),
),
radius: 8.0,
active: true,
})
.collect();
while !rl.window_should_close() {
// Update player
if rl.is_key_down(KeyboardKey::KEY_W) {
player.position.y -= PLAYER_SPEED;
}
if rl.is_key_down(KeyboardKey::KEY_S) {
player.position.y += PLAYER_SPEED;
}
if rl.is_key_down(KeyboardKey::KEY_A) {
player.position.x -= PLAYER_SPEED;
}
if rl.is_key_down(KeyboardKey::KEY_D) {
player.position.x += PLAYER_SPEED;
}
// Check collisions
for coin in coins.iter_mut() {
if coin.active {
let dist = player.position.distance_to(coin.position);
if dist < player.radius + coin.radius {
coin.active = false;
player.score += 1;
}
}
}
// Draw
let mut d = rl.begin_drawing(&thread);
d.clear_background(Color::DARKGREEN);
d.draw_circle_v(player.position, player.radius, Color::BLUE);
for coin in coins.iter() {
if coin.active {
d.draw_circle_v(coin.position, coin.radius, Color::GOLD);
}
}
d.draw_text(&format!("Score: {}", player.score), 10, 10, 20, Color::WHITE);
}
}
Space Invaders
-
cargo.toml:
[package]
name = "space_invaders"
version = "0.1.0"
edition = "2024"
[dependencies]
raylib = "5.5.1"
rand = "0.8"
-
main.rs:
/*
cargo run
*/
use raylib::prelude::*;
use rand::Rng;
const MAX_BULLETS: usize = 64;
const BULLET_SPEED: f32 = 6.0;
#[derive(Clone, Copy)]
struct Player {
position: Vector2,
radius: f32,
}
#[derive(Clone, Copy)]
struct Bullet {
position: Vector2,
velocity: Vector2,
radius: f32,
active: bool,
}
#[derive(Clone, Copy)]
struct Enemy {
position: Vector2,
radius: f32,
active: bool,
color: Color,
}
fn spawn_bullet(bullets: &mut [Bullet; MAX_BULLETS], pos: Vector2) {
for bullet in bullets.iter_mut() {
if !bullet.active {
bullet.active = true;
bullet.position = pos;
bullet.velocity = Vector2::new(0.0, -BULLET_SPEED);
bullet.radius = 5.0;
return;
}
}
}
fn spawn_inactive_enemies(enemies: &mut [Enemy]) {
let mut rng = rand::thread_rng();
for enemy in enemies.iter_mut() {
if !enemy.active {
enemy.position = Vector2::new(rng.gen_range(50..751) as f32, rng.gen_range(50..301) as f32);
enemy.radius = 15.0;
enemy.active = true;
enemy.color = Color::new(
rng.gen_range(100..255),
rng.gen_range(100..255),
rng.gen_range(100..255),
255,
);
}
}
}
fn main() {
const SCREEN_WIDTH: i32 = 800;
const SCREEN_HEIGHT: i32 = 600;
let (mut rl, thread) = raylib::init()
.size(SCREEN_WIDTH, SCREEN_HEIGHT)
.title("Raylib in Rust | 3_space_invaders")
.build();
rl.set_target_fps(60);
let mut player = Player {
position: Vector2::new(400.0, 500.0),
radius: 20.0,
};
let mut bullets: [Bullet; MAX_BULLETS] = [Bullet {
position: Vector2::zero(),
velocity: Vector2::zero(),
radius: 0.0,
active: false,
}; MAX_BULLETS];
let enemies_count = 20;
let mut enemies: Vec<Enemy> = vec![
Enemy {
position: Vector2::zero(),
radius: 0.0,
active: false,
color: Color::BLACK,
};
enemies_count
];
let mut enemies_destroyed_count = 0;
spawn_inactive_enemies(&mut enemies);
while !rl.window_should_close() {
// Player movement
if rl.is_key_down(KeyboardKey::KEY_A) { player.position.x -= 4.0; }
if rl.is_key_down(KeyboardKey::KEY_D) { player.position.x += 4.0; }
if rl.is_key_down(KeyboardKey::KEY_W) { player.position.y -= 4.0; }
if rl.is_key_down(KeyboardKey::KEY_S) { player.position.y += 4.0; }
if rl.is_key_pressed(KeyboardKey::KEY_SPACE) {
spawn_bullet(&mut bullets, player.position);
}
// Update bullets
for bullet in bullets.iter_mut() {
if bullet.active {
bullet.position.x += bullet.velocity.x;
bullet.position.y += bullet.velocity.y;
if bullet.position.y < 0.0 { bullet.active = false; }
}
}
// Update enemies
let mut active_enemies = 0;
for enemy in enemies.iter_mut() {
if enemy.active {
enemy.position.y += 0.5;
active_enemies += 1;
}
}
// Respawn inactive enemies
if active_enemies < 5 {
spawn_inactive_enemies(&mut enemies);
}
// Collision detection
for bullet in bullets.iter_mut() {
if !bullet.active { continue; }
for enemy in enemies.iter_mut() {
if !enemy.active { continue; }
if Vector2::distance_to(&bullet.position, enemy.position) < (bullet.radius + enemy.radius) {
bullet.active = false;
enemy.active = false;
enemies_destroyed_count += 1;
}
}
}
let mut d = rl.begin_drawing(&thread);
d.clear_background(Color::BLACK);
d.draw_circle_v(player.position, player.radius, Color::BLUE);
for bullet in bullets.iter() {
if bullet.active {
d.draw_circle_v(bullet.position, bullet.radius, Color::YELLOW);
}
}
for enemy in enemies.iter() {
if enemy.active {
d.draw_circle_v(enemy.position, enemy.radius, enemy.color);
}
}
d.draw_text("Space Invaders: WASD move | SPACE shoot", 10, 10, 20, Color::WHITE);
d.draw_text(
&format!("Enemies destroyed: {}", enemies_destroyed_count),
10,
40,
20,
Color::YELLOW,
);
}
}