今天,我們來聊聊 Rust 在遊戲開發領域的應用,去年的鐵人賽主題是三十歲時在做什麼?有沒有空?可以來做遊戲嗎?,裡面是使用Bevy來做開發遊戲的引擎。Rust 的高效能、低延遲和記憶體安全特性使其成為遊戲開發的優秀選擇,特別是在需要高效能的遊戲引擎和複雜遊戲邏輯實作方面。
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();
}
}
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)
}
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(())
}
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);
}
}
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(())
}
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來開發遊戲,如果想要以開發遊戲維生的工程師可能要先以其他語言為主。