Steel教程 - 游戏失败

游戏失败

如果球掉落到了屏幕外面,则游戏失败,本章实现游戏失败检测机制,并在游戏失败后显示一个游戏失败的提示界面。

Border实体与Border组件

由于sensor类型的碰撞器可以用来检测是否和另一个碰撞器相交。那么我们可以创建一个以墙和板子为边界区域的sensor类型的碰撞器,持续检测其是否和球的碰撞器相交,如果发现不相交,则说明球已经落到了屏幕外,则判定游戏失败。

我们首先创建一个Border组件用于标记我们的边界实体:

#[derive(Edit, Component, Default)]
struct Border;

同时也注册一下:

#[no_mangle]
pub fn create() -> Box<dyn App> {
    SteelApp::new()
        ...
        .register_component::<Border>()
        ...
}

完成代码编写后记得编译一下。

然后在场景中创建一个名字为Border的实体,删除Renderer2D组件,并添加Collider2D组件和Border组件,将Collider2D组件的sensor勾上,并通过更改Transform的position和scale调整其位置和大小,刚好覆盖以墙和板子为边界的区域:

请添加图片描述

场景修改后记得保存一下。

标记游戏失败的Lose组件

一旦检测到游戏失败了,我们可以创建一个Lose组件,来标记游戏已经失败的状态:

#[derive(Component)]
struct Lose;

Lose组件只由我们的代码创建生成,不需要在编辑器里面编辑,因此也就不需要实现Edit了,也不需要注册了。

边界检查系统border_check_system

准备好了我们的sensor碰撞器和标记游戏失败的组件之后,就可以写一个边界检查系统border_check_system,持续检查球是否掉出屏幕:

fn border_check_system(
    border: View<Border>,
    ball: View<Ball>,
    mut lose: ViewMut<Lose>,
    col2d: View<Collider2D>,
    physics2d_manager: UniqueView<Physics2DManager>,
) {
    let mut border_entity = EntityId::dead();
    for (entity, (_border, border_col2d, _)) in (&border, &col2d, !&lose).iter().with_id() {
        for (_ball, ball_col2d) in (&ball, &col2d).iter() {
            let intersection_pair = physics2d_manager
                .narrow_phase
                .intersection_pair(border_col2d.handle(), ball_col2d.handle());
            if intersection_pair.is_none() {
                border_entity = entity;
            }
        }
    }
    if border_entity != EntityId::dead() {
        lose.add_component_unchecked(border_entity, Lose);
    }
}

通过查找有Border组件且没有Lose组件的实体得到其Collider2D组件,再通过查找有Ball组件的实体得到其Collider2D组件,然后通过narrow_phase.intersection_pair方法判断2个碰撞器是否相交,如果不相交,则为Border实体添加一个Lose组件,标记游戏失败了。

显示游戏失败的系统lose_system

游戏失败后,我们在屏幕中间显示提示游戏失败的界面,通过lose_system实现:

fn lose_system(
    mut lose: View<Lose>,
    egui_ctx: UniqueView<EguiContext>,
) {
    for _lose in (&lose).iter() {
        egui::CentralPanel::default().show(&egui_ctx, |ui| {
            ui.with_layout(
                egui::Layout::centered_and_justified(egui::Direction::TopDown),
                |ui| {
                    ui.label(egui::RichText::new("You lose!").size(100.0));
                },
            );
        });
    }
}

border_check_system和lose_system都放到Schedule::Update中运行即可:

#[no_mangle]
pub fn create() -> Box<dyn App> {
    SteelApp::new()
        ...
        .add_system(Schedule::Update, border_check_system)
        .add_system(Schedule::Update, lose_system)
        .boxed()
}

再次编译运行游戏,让球掉落到屏幕外面,我们就可以在屏幕中间看到“You lose!”的提示了。

下一章:主菜单

上一章:推一下球

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SSSxCCC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值