2D Game Renderer in Rust – Let’s Make a Mini RPG!

Introduction

Welcome to the world of game development in Rust! Today, we’ll build a simple 2D RPG game renderer. We’ll use ggez for our graphics needs, focusing on creating a game where players can move a character around a tile-based map, i…


This content originally appeared on DEV Community and was authored by Trish

Introduction

Welcome to the world of game development in Rust! Today, we'll build a simple 2D RPG game renderer. We'll use ggez for our graphics needs, focusing on creating a game where players can move a character around a tile-based map, interact with objects, and perhaps even battle some basic enemies.

Difficulty

๐ŸŒณ Intermediate-Advanced

๐Ÿ”— Keep the conversation going on Twitter(X): @trish_07

๐Ÿ”— GitHub Repository: Explore the 7Days7RustProjects Repository

Prerequisites

  • Intermediate Rust knowledge
  • Basic understanding of 2D graphics
  • Familiarity with game loop concepts

Project Structure

Let's organize our project:

mkdir rust-2d-rpg
cd rust-2d-rpg
cargo init --bin

Hereโ€™s our folder structure:

rust-2d-rpg/
โ”‚
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ main.rs
โ”‚   โ”œโ”€โ”€ game.rs
โ”‚   โ”œโ”€โ”€ map.rs
โ”‚   โ”œโ”€โ”€ player.rs
โ”‚   โ”œโ”€โ”€ enemy.rs
โ”‚   โ””โ”€โ”€ assets/
โ”‚       โ”œโ”€โ”€ player.png
โ”‚       โ”œโ”€โ”€ enemy.png
โ”‚       โ””โ”€โ”€ tile.png
โ”‚
โ”œโ”€โ”€ Cargo.toml
โ””โ”€โ”€ README.md

Step 1: Setting Up Cargo.toml

Add the following dependencies to your Cargo.toml:

[package]
name = "rust-2d-rpg"
version = "0.1.0"
edition = "2018"

[dependencies]
ggez = "0.6.1"
rand = "0.8.4"

Step 2: main.rs - The Entry Point

mod game;
mod map;
mod player;
mod enemy;

use ggez::{Context, ContextBuilder, GameResult};
use ggez::event::{self, EventHandler};

fn main() -> GameResult {
    let cb = ContextBuilder::new("rust_2d_rpg", "YourName")
        .window_setup(ggez::conf::WindowSetup::default().title("2D RPG in Rust"));
    let (mut ctx, event_loop) = cb.build()?;
    let game = game::Game::new(&mut ctx)?;
    event::run(ctx, event_loop, game)
}

Step 3: game.rs - Game Logic

use ggez::{Context, GameResult};
use ggez::event::{self, EventHandler};
use ggez::graphics;

pub struct Game {
    player: player::Player,
    map: map::Map,
    enemies: Vec<enemy::Enemy>,
}

impl Game {
    pub fn new(ctx: &mut Context) -> GameResult<Game> {
        let player = player::Player::new(ctx)?;
        let map = map::Map::new();
        let enemies = vec![enemy::Enemy::new(ctx)?];
        Ok(Game { player, map, enemies })
    }
}

impl EventHandler for Game {
    fn update(&mut self, _ctx: &mut Context) -> GameResult {
        // Update logic for player movement, enemy behavior, etc.
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult {
        graphics::clear(ctx, [0.1, 0.2, 0.3, 1.0].into());
        self.map.draw(ctx)?;
        self.player.draw(ctx)?;
        for enemy in &self.enemies {
            enemy.draw(ctx)?;
        }
        graphics::present(ctx)?;
        Ok(())
    }
}

Step 4: player.rs - Player Management

use ggez::{Context, GameResult};
use ggez::graphics::{self, Rect};
use ggez::nalgebra as na;

pub struct Player {
    position: na::Point2<f32>,
}

impl Player {
    pub fn new(_ctx: &mut Context) -> GameResult<Player> {
        Ok(Player { position: na::Point2::new(100.0, 100.0) })
    }

    pub fn draw(&self, ctx: &mut Context) -> GameResult {
        let rectangle = graphics::Mesh::new_rectangle(
            ctx,
            graphics::DrawMode::fill(),
            Rect::new(self.position.x, self.position.y, 32.0, 32.0),
            graphics::Color::new(0.0, 1.0, 0.0, 1.0),
        )?;
        graphics::draw(ctx, &rectangle, (na::Point2::new(0.0, 0.0),))
    }

    // Add methods for movement, collision detection, etc.
}

Step 5: map.rs - World Generation

use ggez::{Context, GameResult};
use ggez::graphics;

pub struct Map {
    // Simplified map representation
    tiles: Vec<Vec<bool>>,
}

impl Map {
    pub fn new() -> Map {
        let tiles = vec![vec![true; 20]; 15];
        Map { tiles }
    }

    pub fn draw(&self, ctx: &mut Context) -> GameResult {
        let tile_size = 32.0;
        for (y, row) in self.tiles.iter().enumerate() {
            for (x, &tile) in row.iter().enumerate() {
                if tile {
                    let rectangle = graphics::Mesh::new_rectangle(
                        ctx,
                        graphics::DrawMode::fill(),
                        graphics::Rect::new((x as f32) * tile_size, (y as f32) * tile_size, tile_size, tile_size),
                        [0.5, 0.5, 0.5, 1.0].into(),
                    )?;
                    graphics::draw(ctx, &rectangle, (na::Point2::new(0.0, 0.0),))?;
                }
            }
        }
        Ok(())
    }
}

Step 6: enemy.rs - Enemies Management

use ggez::{Context, GameResult};
use ggez::graphics;
use ggez::nalgebra as na;

pub struct Enemy {
    position: na::Point2<f32>,
}

impl Enemy {
    pub fn new(ctx: &mut Context) -> GameResult<Enemy> {
        Ok(Enemy { position: na::Point2::new(200.0, 200.0) })
    }

    pub fn draw(&self, ctx: &mut Context) -> GameResult {
        let rectangle = graphics::Mesh::new_rectangle(
            ctx,
            graphics::DrawMode::fill(),
            graphics::Rect::new(self.position.x, self.position.y, 32.0, 32.0),
            graphics::Color::new(1.0, 0.0, 0.0, 1.0),
        )?;
        graphics::draw(ctx, &rectangle, (na::Point2::new(0.0, 0.0),))
    }

    // Add methods for enemy movement, AI, etc.
}

Step 7: Running the Game

To run the game:

cargo run

Explanation

  • Main Loop: In main.rs, we set up the ggez context and our game loop.
  • Game State: game.rs holds the overall game state, including the player, map, and enemies.
  • Graphics: Each component (Player, Map, Enemy) has its own draw method to handle rendering.
  • Expansion: This basic setup can be expanded with:
    • Player movement using keyboard input.
    • Collision detection between the player and map/enemies.
    • Basic AI for enemy movement or behavior.
    • Inventory system for items.
    • Combat mechanics or interaction with the environment.

Conclusion

You've now built a foundational 2D RPG game renderer in Rust! This project introduces you to game development concepts, graphics handling with ggez, and modular code organization.

Feel free to expand upon this base by:

  • Implementing player input for movement.
  • Adding different types of tiles or interactive objects.
  • Creating a combat system or quests.
  • Enhancing the game with sound or more complex graphics.

This project serves as an excellent platform for learning advanced Rust programming and game development principles. Keep exploring, and have fun creating your own game worlds!


This content originally appeared on DEV Community and was authored by Trish


Print Share Comment Cite Upload Translate Updates
APA

Trish | Sciencx (2024-10-28T14:40:55+00:00) 2D Game Renderer in Rust – Let’s Make a Mini RPG!. Retrieved from https://www.scien.cx/2024/10/28/2d-game-renderer-in-rust-lets-make-a-mini-rpg/

MLA
" » 2D Game Renderer in Rust – Let’s Make a Mini RPG!." Trish | Sciencx - Monday October 28, 2024, https://www.scien.cx/2024/10/28/2d-game-renderer-in-rust-lets-make-a-mini-rpg/
HARVARD
Trish | Sciencx Monday October 28, 2024 » 2D Game Renderer in Rust – Let’s Make a Mini RPG!., viewed ,<https://www.scien.cx/2024/10/28/2d-game-renderer-in-rust-lets-make-a-mini-rpg/>
VANCOUVER
Trish | Sciencx - » 2D Game Renderer in Rust – Let’s Make a Mini RPG!. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2024/10/28/2d-game-renderer-in-rust-lets-make-a-mini-rpg/
CHICAGO
" » 2D Game Renderer in Rust – Let’s Make a Mini RPG!." Trish | Sciencx - Accessed . https://www.scien.cx/2024/10/28/2d-game-renderer-in-rust-lets-make-a-mini-rpg/
IEEE
" » 2D Game Renderer in Rust – Let’s Make a Mini RPG!." Trish | Sciencx [Online]. Available: https://www.scien.cx/2024/10/28/2d-game-renderer-in-rust-lets-make-a-mini-rpg/. [Accessed: ]
rf:citation
» 2D Game Renderer in Rust – Let’s Make a Mini RPG! | Trish | Sciencx | https://www.scien.cx/2024/10/28/2d-game-renderer-in-rust-lets-make-a-mini-rpg/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.