iT邦幫忙

2024 iThome 鐵人賽

DAY 21
0
Software Development

Rust 學得動嗎系列 第 21

[Day21] Rust 在遊戲開發中的應用

  • 分享至 

  • xImage
  •  

今天,我們來聊聊 Rust 在遊戲開發領域的應用,去年的鐵人賽主題是三十歲時在做什麼?有沒有空?可以來做遊戲嗎?,裡面是使用Bevy來做開發遊戲的引擎。Rust 的高效能、低延遲和記憶體安全特性使其成為遊戲開發的優秀選擇,特別是在需要高效能的遊戲引擎和複雜遊戲邏輯實作方面。

1. 使用 Bevy 遊戲引擎

Bevy 是一個資料驅動的遊戲引擎,使用了 Rust 的實體元件系統(ECS)架構。

use bevy::prelude::*;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_startup_system(setup)
        .add_system(move_sprite)
        .run();
}

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
    commands.spawn_bundle(Camera2dBundle::default());
    commands.spawn_bundle(SpriteBundle {
        texture: asset_server.load("sprite.png"),
        ..Default::default()
    })
    .insert(Velocity { x: 1.0, y: 1.0 });
}

#[derive(Component)]
struct Velocity {
    x: f32,
    y: f32,
}

fn move_sprite(mut query: Query<(&mut Transform, &Velocity)>, time: Res<Time>) {
    for (mut transform, velocity) in query.iter_mut() {
        transform.translation.x += velocity.x * time.delta_seconds();
        transform.translation.y += velocity.y * time.delta_seconds();
    }
}

2. 使用 ggez 建立 2D 遊戲

ggez 是一個輕量級的 2D 遊戲框架,適合快速開發原型和小型遊戲。

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

struct MainState {
    pos_x: f32,
}

impl MainState {
    fn new() -> GameResult<MainState> {
        Ok(MainState { pos_x: 0.0 })
    }
}

impl EventHandler for MainState {
    fn update(&mut self, _ctx: &mut Context) -> GameResult {
        self.pos_x = self.pos_x % 800.0 + 1.0;
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult {
        graphics::clear(ctx, [0.1, 0.2, 0.3, 1.0].into());
        let circle = graphics::Mesh::new_circle(
            ctx,
            graphics::DrawMode::fill(),
            [self.pos_x, 380.0],
            30.0,
            2.0,
            Color::WHITE,
        )?;
        graphics::draw(ctx, &circle, graphics::DrawParam::default())?;
        graphics::present(ctx)?;
        Ok(())
    }
}

fn main() -> GameResult {
    let (ctx, event_loop) = ContextBuilder::new("my_game", "ggez")
        .build()?;
    let state = MainState::new()?;
    event::run(ctx, event_loop, state)
}

3. 使用 Amethyst 引擎

Amethyst 是一個資料導向的遊戲引擎,專注於並行性和可擴展性。

use amethyst::{
    prelude::*,
    renderer::{
        plugins::{RenderFlat2D, RenderToWindow},
        types::DefaultBackend,
        RenderingBundle,
    },
    utils::application_root_dir,
};

struct MyState;

impl SimpleState for MyState {
    fn on_start(&mut self, _data: StateData<'_, GameData>) {
        println!("遊戲開始!");
    }
}

fn main() -> amethyst::Result<()> {
    let app_root = application_root_dir()?;
    let display_config_path = app_root.join("config").join("display.ron");

    let game_data = GameDataBuilder::default()
        .with_bundle(
            RenderingBundle::<DefaultBackend>::new()
                .with_plugin(
                    RenderToWindow::from_config_path(display_config_path)?
                        .with_clear([0.0, 0.0, 0.0, 1.0]),
                )
                .with_plugin(RenderFlat2D::default()),
        )?;

    let assets_dir = app_root.join("assets");
    let mut game = Application::new(assets_dir, MyState, game_data)?;
    game.run();

    Ok(())
}

4. 遊戲物理引擎:使用 nphysics

nphysics 是一個 2D 和 3D 實時物理引擎庫。

use nphysics2d::object::{DefaultBodyHandle, DefaultColliderHandle};
use nphysics2d::world::World;
use nphysics2d::math::{Isometry, Vector};
use ncollide2d::shape::{Cuboid, ShapeHandle};

fn main() {
    let mut world = World::new();
    
    // 創建地面
    let ground_shape = ShapeHandle::new(Cuboid::new(Vector::new(5.0, 0.1)));
    world.add_collider(
        0.0,
        ground_shape,
        DefaultBodyHandle::ground(),
        Isometry::translation(0.0, -1.0),
        DefaultColliderHandle::ground(),
    );

    // 創建一個動態物體
    let cuboid = ShapeHandle::new(Cuboid::new(Vector::new(0.5, 0.5)));
    let body_handle = world.add_rigid_body(
        Isometry::translation(0.0, 3.0),
        cuboid.inertia(1.0),
        cuboid.center_of_mass(),
    );
    world.add_collider(
        0.0,
        cuboid,
        body_handle,
        Isometry::identity(),
        DefaultColliderHandle::new(body_handle),
    );

    // 模擬
    for _ in 0..200 {
        world.step();
        let position = world.rigid_body(body_handle).unwrap().position();
        println!("物體位置:{:?}", position.translation.vector);
    }
}

5. 使用 rust-sdl2 進行遊戲開發

SDL2 是一個跨平台的開發庫,rust-sdl2 提供了 Rust 的綁定。

use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::pixels::Color;
use sdl2::rect::Rect;

fn main() -> Result<(), String> {
    let sdl_context = sdl2::init()?;
    let video_subsystem = sdl_context.video()?;
    let window = video_subsystem.window("Rust SDL2", 800, 600)
        .position_centered()
        .build()
        .map_err(|e| e.to_string())?;

    let mut canvas = window.into_canvas().build().map_err(|e| e.to_string())?;
    canvas.set_draw_color(Color::RGB(0, 0, 0));
    canvas.clear();
    canvas.present();

    let mut event_pump = sdl_context.event_pump()?;

    'running: loop {
        for event in event_pump.poll_iter() {
            match event {
                Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                    break 'running
                },
                _ => {}
            }
        }

        canvas.set_draw_color(Color::RGB(0, 0, 0));
        canvas.clear();
        canvas.set_draw_color(Color::RGB(255, 0, 0));
        canvas.fill_rect(Rect::new(50, 50, 100, 100))?;
        canvas.present();
    }

    Ok(())
}

6. 遊戲音效:使用 rodio

rodio 是一個簡單的音效庫,適用於遊戲開發。

use rodio::{Decoder, OutputStream, Sink};
use std::fs::File;
use std::io::BufReader;

fn main() {
    let (_stream, stream_handle) = OutputStream::try_default().unwrap();
    let sink = Sink::try_new(&stream_handle).unwrap();

    let file = BufReader::new(File::open("music.ogg").unwrap());
    let source = Decoder::new(file).unwrap();
    sink.append(source);

    sink.sleep_until_end();
}

結論

Rust 在遊戲開發領域展現了巨大的潛力,尤其在需要高效能與複雜邏輯的情境下。從遊戲引擎到物理模擬、跨平台開發與音效處理,Rust 提供了強大的工具與庫,逐步擴展其在遊戲開發中的應用場景。隨著 Rust 生態系統的不斷成長,它將成為未來遊戲開發的重要選擇之一,只是現在還沒有太多人使用Rust來開發遊戲,如果想要以開發遊戲維生的工程師可能要先以其他語言為主。


上一篇
[Day 20] Rust 在機器學習和資料科學中的應用
下一篇
[Day 22] Rust 在密碼學和區塊鏈技術中的應用
系列文
Rust 學得動嗎30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言