[Day29] Bevy 游戏引擎 (Part 3) 收工

好 那今天就是专案的收尾了
我先预告一下明天会把一些我从开始学习 Rust 之後陆续得到的学习资源
也就是套件库 以及 教学 Blog
OK 我们继续昨天的内容


昨天我们做出了能够上下左右改变方向的玩家
那麽其实如果要改变位置只要改一小段昨天的代码改就好了
那今天要做的是 让箭头消失 和 记分板
首先先讲 让箭头消失好了 这个比较简单
一样 我就只讲一个方向 因为大同小异

fn despawns_monster_up(
    mut commands: Commands,
    mut arrow_positions: Query<(Entity, &mut Transform, &UpArrow), Without<crate::characters::Main>>,
    character: Query<(Entity, &Transform, &crate::characters::Main), Without<UpArrow>>,
    mut score: ResMut<ScoreBoard>,
){
    let (_entity, transform, _character) = character.single().expect("");
    let path = transform.rotation.w;
    for (entity, transform, _arrow) in arrow_positions.iter_mut() {
        let posx = transform.translation.x;
        let posy = transform.translation.y;
        if -100. <= posy && posy <= 0. && path == (-0.70710677)
        {
            score.add_score();
            commands.entity(entity).despawn();
        }
        if posy >= 0. && posx == 0. {
            commands.entity(entity).despawn();
        }
    }
}

可以看到说 我引入了他的角色跟箭头
因为我们需要角色的转角跟箭头的位置
而之中可以看到我们抓了 rotation.w 这个是我在 Character 的 movement 里面测出来的

if key_input.just_pressed(KeyCode::W) {
            transform.rotation = Quat::from_rotation_z(0.5 * PI);
            println!("{}", transform.rotation);
}

後面三个方向也是

那麽当转向的时候就会输出这些
之後再去看官方的 docs 就能得到角度了
而中间 path 不是使用 PI * -0.5
是因为会有浮点数误差 所以就改成以输出的数值为主
然後我是设定说 当到原点时 消失 当方向一致 然後物件在下方 100. 的位置时 消失并且加分
那麽中间那行 add_score 就是计分板的部份了


这边我定义出了

pub struct ScoreBoard {
    score: usize,
}

impl ScoreBoard {
    pub fn add_score(&mut self) {
        self.score += 1;
    }
    pub fn get_score(&self) -> usize {
        self.score
    }
}

上面是记分板的功能
获取分数跟增加分数
当然 读者也能自行增加
那麽下面这边比较复杂

pub fn score_ui(
    mut commands: Commands,
    asset_server: ResMut<AssetServer>,
    mut color_materials: ResMut<Assets<ColorMaterial>>,)
{
    let font: Handle<Font> = asset_server.load("font.ttf");
    let material = color_materials.add(Color::NONE.into());
    commands
        .spawn_bundle(NodeBundle {
            style: Style {
                position_type: PositionType::Absolute,
                position: Rect {
                    left: Val::Px(10.),
                    top: Val::Px(10.),
                    ..Default::default()
                },
                ..Default::default()
            },
            material: material.clone(),
            ..Default::default()
        })
        .with_children(|parent| {
            parent
                .spawn_bundle(TextBundle {
                    text: Text::with_section(
                        "Score: 0",
                        TextStyle {
                            font_size: 40.0,
                            font: font.clone(),
                            color: Color::rgb(0.9, 0.9, 0.9),
                        },
                        Default::default(),
                    ),
                    ..Default::default()
                })
                .insert(ScoreText);
        });
}

因为我们要做出整个 UI 界面
所以我们要定义出 这个 UI 的位置 然後字体之类等等
而上方的设定是位於左上角
字体是我随便在 Google 上抓的
然後可以看到说 下面的 text 是我们要的输出 而 Score: 0 是预设值

pub struct ScoreText;
pub fn update_score_text(score: Res<ScoreBoard>, mut query: Query<(&mut Text, &ScoreText)>) {
    if !score.is_changed() {
        return;
    }
    for (mut text, _marker) in query.iter_mut() {
        text.sections[0].value = format!(
            "Score: {}",
            score.get_score(),
        );
    }
}

那 ScoreText 我定义在下面
而这个 function 的用途就是确认有没有更动 如果有就去找他现在的值


最後就是初始化的部份了

fn main() {
    App::build()
        .insert_resource(WindowDescriptor {
            title: "owo!".to_string(),
            width: 800.,
            height: 600.,
            ..Default::default()
        })
        .insert_resource(ClearColor(Color::rgb(1., 0.4, 0.4)))
        .init_resource::<score::ScoreBoard>()
        .add_startup_stage("game_setup", SystemStage::single(characters::spawn_main.system()).with_system(score::score_ui.system()))
        .add_startup_system(setup.system())
        .add_plugins(DefaultPlugins)
        .add_plugin(characters::CharacterPlugin)
        //.add_plugin(score::UI)
        .add_plugin(arrow::ArrowsPlugin)
        .add_system(score::update_score_text.system())
        .run();
}

我的 main 函数长这样
那麽可以看到除了之前的 character 的 Plugin 还有 Arrow 的 Plugin 以外

.init_resource::<score::ScoreBoard>()
        .add_startup_stage("game_setup", SystemStage::single(characters::spawn_main.system()).with_system(score::score_ui.system()))

这行格外的重要
这是让他的资源去进行初始化,且在同一时机
game_setup 是我自己取的 没什麽重要性
最後成品会长这样

Source
OK 剩下一天
各位晚安


<<:  Kotlin Android 第28天,从 0 到 ML - TensorFlow Lite -姿态估计 (Pose estimation)

>>:  Day 27: Tensorflow分类 分类图像衣物(二)

[Day 28] 组件和new Vue的差别

这篇我一直都很想讲!因为自己刚开始也分不清楚这两个差别到底在哪,相信一定会有人跟我一样的对吧!!那就...

Day 25 利用transformer自己实作一个翻译程序(七) Scaled dot product attention

Scaled dot product attention 前面有提到transformer需要3个矩...

Day10 while回圈

在写程序时,回圈是经常使用到的工具,他可以重复执行同样的工作,直到条件式不符合时跳出回圈,执行下一个...

Dungeon Mizarka 023

这几天可能不会有什麽进展,今天先将之前试验建置VS的部份做个整理。整理有关於Code strippi...

【Day24】人力资源篇-Time Off

#odoo #开源系统 #数位赋能 #E化自主 休假管理,在实务上又是另一门高深的学问。公司除了必须...