godot-rust(gdext)2D游戏之旅【flappy-bird】 - 2

0 阅读2分钟

简介

本文以Make Flappy Bird Game in Godot Engine | gameidea为蓝本撰写。如果你对rust、godot等内容比较生疏或感到疑惑,可以先阅读godot-rust入门文档

本文搭建在godot-rust(gdext)创建项目的基础之上,如果你对该部分内容感到生疏,可以先阅读这部分内容,为接下来的操作做好准备。

注意,本文使用的godot版本为4.6.2,godot版本的变化可能会导致一些内容失效

本文所有操作均在Windows11环境下进行。

正文

创建Pipes

在rust中创建Pipe节点

// pipe.rs
use godot::prelude::*;

#[derive(GodotClass)]
#[class(init, base=Node2D)]
struct Pipe {}

执行cargo build

在godot中新建你刚刚创建的Pipe节点,并保存在你的Pipe文件夹下。

创建Pipe节点

Pipe节点添加三个子节点Area2D,分别命名为PipeTopPipeBottomScoreArea,并向这三个子节点各添加一个CollisionShape2D子节点,并均用RectangleShape2D来表示CollisionShape2DShape

创建pipe节点

pipe碰撞形状设置

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

编辑pipe位置

从上往下的顺序依次是:

  • PipeTop
  • ScoreArea
  • PipeBottom

上下碰撞检测游戏是否失败,中间碰撞用于检测游戏是否得分。

Pipe添加4个Sprite2D子节点,名称分别为Pipe1Pipe2Pipe3Pipe4,用assert文件夹下的pipe.png填充为Texture,将Sprite2D分别摆放到适合的位置。

pipe添加视觉效果

现在来丰富rust的Pipe代码

// 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属性配合调整到合适的大小,这里我给一个图片作为参考

调整Pipe大小

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

参考

  1. godot-rust(gdext)创建项目 - 掘金
  2. godot - Rust
  3. Make Flappy Bird Game in Godot Engine | gameidea