简介
本文以Make Flappy Bird Game in Godot Engine | gameidea为蓝本撰写。如果你对rust、godot等内容比较生疏或感到疑惑,可以先阅读godot-rust入门文档。
本文搭建在godot-rust(gdext)创建项目的基础之上,如果你对该部分内容感到生疏,可以先阅读这部分内容,为接下来的操作做好准备。
注意,本文使用的godot版本为4.6.2,godot版本的变化可能会导致一些内容失效。
本文所有操作均在Windows11环境下进行。
正文
创建Pipes
在rust中创建Pipe节点
rust
// pipe.rs
use godot::prelude::*;
#[derive(GodotClass)]
#[class(init, base=Node2D)]
struct Pipe {}
执行cargo build。
在godot中新建你刚刚创建的Pipe节点,并保存在你的Pipe文件夹下。

向Pipe节点添加三个子节点Area2D,分别命名为PipeTop、PipeBottom、ScoreArea,并向这三个子节点各添加一个CollisionShape2D子节点,并均用RectangleShape2D来表示CollisionShape2D的Shape。


到编辑界面拖动三个子节点位置和形状,使之符合我们的游戏需求。

从上往下的顺序依次是:
PipeTopScoreAreaPipeBottom
上下碰撞检测游戏是否失败,中间碰撞用于检测游戏是否得分。
向Pipe添加4个Sprite2D子节点,名称分别为Pipe1、Pipe2、Pipe3、Pipe4,用assert 文件夹下的pipe.png 填充为Texture ,将Sprite2D分别摆放到适合的位置。

现在来丰富rust的Pipe代码
rust
// pipe.rs
use godot::{
classes::{Area2D, CollisionShape2D},
prelude::*,
};
#[derive(GodotClass)]
#[class(init, base=Node2D)]
pub struct Pipe {
base: Base<Node2D>,
#[init(node = "PipeTop")]
pipe_top: OnReady<Gd<Area2D>>,
#[init(node = "PipeBottom")]
pipe_bottom: OnReady<Gd<Area2D>>,
#[init(node = "ScoreArea")]
score_area: OnReady<Gd<Area2D>>,
#[init(val = 150.0)]
scroll_speed: real,
}
#[godot_api]
impl Pipe {
#[signal]
pub fn scored();
#[signal]
pub fn hit();
fn on_pipe_body_entered(&mut self, _pipe: Gd<Node2D>) {
self.signals().hit().emit();
}
fn on_score_area_body_entered(&mut self, _pipe: Gd<Node2D>) {
self.signals().scored().emit();
self.score_area
.get_node_as::<CollisionShape2D>("CollisionShape2D")
.set_deferred("disabled", &true.to_variant());
}
pub fn set_scroll_speed(&mut self, speed: real) {
self.scroll_speed = speed;
}
}
#[godot_api]
impl INode2D for Pipe {
fn ready(&mut self) {
self.pipe_top
.signals()
.body_entered()
.connect_other(&*self, Self::on_pipe_body_entered);
self.pipe_bottom
.signals()
.body_entered()
.connect_other(&*self, Self::on_pipe_body_entered);
self.score_area
.signals()
.body_entered()
.connect_other(&*self, Self::on_score_area_body_entered);
}
fn process(&mut self, delta: f32) {
let mut position = self.base().get_position();
position.x -= self.scroll_speed * delta;
self.base_mut().set_position(position);
if position.x < -150.0 {
self.base_mut().queue_free();
}
}
}
你一定有一个疑惑,这个Pipe到底需要多长?多大?原文没有详细写,这需要我们自己调整一下,回到godot 中,手动增加管道Sprite2D贴图的个数,使用鼠标和transform属性配合调整到合适的大小,这里我给一个图片作为参考

紫色矩形是窗口大小,记得管道中间要留出足够空间让Bird可以通过。