これを実行すると、画面が立ち上がります。
そして、スタートボタン機能とタイトル画面へ戻るボタンの機能が実装されています。
恐らく、2023年03月20日の最新の骨組みの書き方だと思います。(そして手斧が投げられた……
詳しいことはコード中のコメント参照
main.rs
// nannouおよびnannou_eguiクレートをインポート
use nannou::prelude::*;
use nannou_egui::{self, egui, Egui};
// ゲームの状態を表すenum
enum GameState {
Title,
Menu,
}
// ゲームのメインモデルを定義
struct Model {
texture: wgpu::Texture,
ui: Egui,
game_state: GameState,
show_exit_dialog: bool,
}
// エントリポイント
fn main() {
nannou::app(model).update(update).event(event).run();
}
// ゲームの初期化
fn model(app: &App) -> Model {
// UIウィンドウを作成
let ui_window = app
.new_window()
.size(1080, 800)
.view(view)
.raw_event(raw_ui_event)
.build()
.unwrap();
// 背景画像を読み込む
let texture = load_texture(&app, "images/background.jpg");
// エスケープキーで終了しないように設定
app.set_exit_on_escape(false);
let ui_window_ref = app.window(ui_window).unwrap();
// Eguiインスタンスを作成
let ui = Egui::from_window(&ui_window_ref);
// モデルを初期化
Model {
texture,
ui,
game_state: GameState::Title,
show_exit_dialog: false,
}
}
// 画面のキーイベント
fn event(_app: &App, model: &mut Model, event: Event) {
match event {
Event::WindowEvent {
id: _id,
simple: window_event,
} => {
if let Some(KeyPressed(key)) = window_event {
match key {
Key::Up => println!("Pressed Up!!!"),
Key::Down => println!("Pressed Down!!!"),
Key::Escape => model.show_exit_dialog = true,
_ => {}
}
}
}
_ => {}
}
}
// アップデート関数
fn update(_app: &App, model: &mut Model, _update: Update) {
update_ui(model);
}
// UIのアップデート
fn update_ui(model: &mut Model) {
let ctx = model.ui.begin_frame();
match model.game_state {
GameState::Title => {
// タイトル画面の表示
egui::Window::new("Title Screen")
.collapsible(false)
.show(&ctx, |ui| {
if ui.add(egui::Button::new("Start Game")).clicked() {
model.game_state = GameState::Menu;
}
});
}
GameState::Menu => {
// メニュー画面の表示
egui::Window::new("Menu")
.collapsible(false)
.show(&ctx, |ui| {
if ui.add(egui::Button::new("Back to Title")).clicked() {
model.game_state = GameState::Title;
}
});
}
}
// 終了ダイアログの表示
if model.show_exit_dialog {
egui::Window::new("Exit Game")
.collapsible(false)
.show(&ctx, |ui| {
ui.label("Do you want to exit the game?");
if ui.add(egui::Button::new("Yes")).clicked() {
std::process::exit(0);
}
if ui.add(egui::Button::new("No")).clicked() {
model.show_exit_dialog = false;
}
});
}
}
// 描画関数
fn view(app: &App, model: &Model, frame: Frame) {
let draw = app.draw();
// 背景色を設定
draw.background().color(BLACK);
// 背景画像を描画
draw.texture(&model.texture);
draw.to_frame(app, &frame).unwrap();
// UIを描画
model.ui.draw_to_frame(&frame).unwrap();
}
// eguiのイベント処理
fn raw_ui_event(_app: &App, model: &mut Model, event: &nannou::winit::event::WindowEvent) {
model.ui.handle_raw_event(event);
}
// テクスチャを読み込む関数
fn load_texture(app: &App, path: &str) -> wgpu::Texture {
let assets = app.assets_path().unwrap();
let img_path = assets.join(path);
let texture = wgpu::Texture::from_path(app, img_path).unwrap();
texture
}
Cargo.toml
[dependencies]
nannou = "0.18"
wasm-bindgen = "0.2.84"
image = "0.23"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
legion = "0.4"
nannou_egui = "0.5"