27|Rust Bevy游戏开发:用300行代码做一个贪吃蛇游戏
唐刚
你好,我是 Mike。今天我们一起来学习 Rust 游戏编程技术。这节课我们会基于 Bevy 游戏框架来开发一个入门版的贪吃蛇游戏。
Rust 生态内目前已经有不少很不错的游戏开发框架,而 Bevy 是其中最热门的那一个,目前(2023 年 12 月)最新版本是 0.12,还处在积极开发的过程中。Bevy 框架和 Axum Web 框架、Slint 框架给人的感觉有点儿像,都很简单、优美、灵活。用 Bevy 框架写游戏非常惬意,已经有不少人在尝试使用 Bevy 开发自己的独立游戏,目前有三款(Molecoole、Tiny Glade、Roids)已经上架或即将上架 Steam。
用 Bevy 开发的游戏能够运行在 Windows、macOS、Linux, Web 浏览器等平台。
Bevy 框架
Bevy 框架是一个数据驱动的游戏开发框架(引擎),其核心是一个 ECS。
ECS
ECS 是 Entity Component System 的缩写,意思是实体 - 组件 - 系统。它是一种编程范式,这种范式非常有趣,也非常有潜力,现在的主流游戏引擎都开始支持这种编程范式了。这种范式是与传统的 OOP(面向对象编程)范式相对的,跟 Rust 的 trait 的设计理念有一些相似之处。
我们用一个例子来说明 ECS 是怎样对问题进行建模的。假如现在有这样一幅画面:一个下午,在温暖的家里面,爸爸 D 正在边吃甜点边看书,妈妈 M 在边吃甜点边玩手机,儿子 S 在和狗狗 B 玩。你想一想,这个场景如果用 OOP 方式,应该如何建模呢?而用 ECS 范式可以这样建立模型:
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
使用Rust语言和Bevy游戏框架开发贪吃蛇游戏的技术细节。文章首先介绍了Bevy框架的特点,包括其基于ECS的设计范式、资源管理、事件处理、世界状态维护、固定帧率和坐标系统等。通过实战贪吃蛇游戏的步骤,展示了如何引入Bevy库、创建窗口、绘制蛇的头等具体操作。在具体步骤中,作者介绍了如何让蛇动起来、控制蛇的方向、将窗口网格化、让蛇按网格移动、配置窗口比例和尺寸、随机产生食物以及使用定时器产生食物。接着,文章详细介绍了如何定义蛇的身体、让蛇身跟随蛇头移动、处理蛇吃食物并长大的效果。通过简洁的代码示例和清晰的解释,读者可以快速了解Rust游戏开发的基本原理和实践方法。整体而言,本文通过实际案例向读者展示了使用Rust和Bevy框架开发游戏的全过程,为对游戏开发感兴趣的读者提供了宝贵的参考和学习资源。文章还提到了撞墙和自身Game Over的处理,以及对Bevy游戏引擎的基本使用方式和ECS系统的重要性。同时,作者鼓励读者通过编写小游戏来提升建模能力,展示了游戏开发的乐趣和技术挑战。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Rust 语言从入门到实战》,新⼈⾸单¥59
《Rust 语言从入门到实战》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(5)
- 最新
- 精选
- NiceBlueChai还有个bug,向上走的过程中快速按左下(或者右下),蛇直接原地向相反方向走了
作者回复: 哈哈,真的是。🤔👍👍
2024-01-29归属地:山东 - seven9t补充了个最起码的长按加速功能,没找到timer的就地调频接口,只能另开了个timer做切换。各位有啥更好办法么。
作者回复: 非常强的动手能力👍👍
2024-01-21归属地:广东 - unistartBUG: 食物可能在蛇身上产生 处理: 在生成食物的时候,判断一下随机生成的Position值是否和当前蛇的某一个部分位置是重合的,如果是就直接return,不生成食物。 // 修改food_spawner fn food_spawner( mut commands: Commands, time: Res<Time>, mut timer: ResMut<FoodSpawnTimer>, segment_pos_set: Query<&Position, With<SnakeSegment>> ) { // ... let rand_x: i32 = (random::<f32>() * ARENA_WIDTH as f32) as i32; let rand_y: i32 = (random::<f32>() * ARENA_HEIGHT as f32) as i32; for pos in segment_pos_set.iter() { if pos.x == rand_x && pos.y == rand_y { return; } } // ... .insert(Position { x: rand_x, y: rand_y, }) // ... } BUG: 食物有可能在已经产生过的地方产生 个人感觉这个不太算bug吧,分两种情况看,一种是食物A之前被吃过,又在相同的位置生成了新的食物,这个应该是没问题的;另一种就是食物A之前没有被吃过,同时新生成的食物B的位置和食物A重合,这样确实貌似有问题。 但是我不知道Bevy是如何处理的,按我的理解来说食物B应该会盖掉食物A,即某一位置只会有一个最新的食物实体。还是说bevy中出现这种情况,同一位置会有多个实体。如果是同一位置有多个实体的话,那么再Query一下已经生成的Food的Position,然后和新生成的食物坐标比较一下是否有出现的重合就行了吧。
作者回复: 非常棒的思考 👍. 要判断食物位置是否重合的话, 需要用一个结构来维护食物的 Positions, 将其设定为 Resource. 在最新一篇总结更新中会讲到这个问题.
2023-12-30归属地:湖南2 - 大白菜🥬14步那里需要添加LastTailPosition资源, App需要添加 .insert_resource(LastTailPosition::default())
作者回复: 对的对的
2023-12-27归属地:重庆 - 十八哥当年用vb.net用了1千行实现的。思路是按钮数组,一个二维数组。
作者回复: 不错的思路。
2023-12-26归属地:天津
收起评论