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

简介

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

本文搭建在godot-rust(gdext)创建项目的基础之上,如果你对该部分内容感到生疏,可以先阅读这部分内容,为接下来的操作做好准备。出于连贯性考虑,本文将省略一些基础性操作,这些操作可以在godot-rust(gdext)你的第一个2D游戏这个系列中看到,可以从这个系列中了解相关内容。

注意,本文使用的godot版本为4.6.2,godot-rust(gdext)版本为0.5.1,相关的版本变化可能会导致一些内容失效

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

本文工程资源和相关素材可以在这里(pong-lab)可以获取。

正文

创建Paddle

rust 复制代码
// paddle.rs
use godot::{
    classes::{CharacterBody2D, ICharacterBody2D, InputEvent, InputEventMouseMotion},
    prelude::*,
};

use crate::state::{State, Stateful};

#[derive(GodotClass)]
#[class(init, base=CharacterBody2D)]
pub struct Paddle {
    base: Base<CharacterBody2D>,

    state: PaddleState,

    #[init(val = 0.0)]
    x_offset: real,

    #[init(val = OnReady::manual())]
    clamp_range: OnReady<Vector2>, // 钳制挡板不会移出游戏区域
}

#[godot_api]
impl ICharacterBody2D for Paddle {
    fn ready(&mut self) {
        let size = self.base().get_viewport_rect().size;
        self.clamp_range.init(Vector2::new(100.0, size.x - 100.0));

        self.on_state_enter(); // 手动调用一次进入状态
    }

    fn input(&mut self, event: Gd<InputEvent>) {
        if self.state != PaddleState::Active {
            return;
        }

        let Ok(motion) = event.try_cast::<InputEventMouseMotion>() else {
            return;
        };

        self.x_offset += motion.get_relative().x; // 只在Active状态下监听鼠标位移
    }

    fn physics_process(&mut self, _delta: f32) {
        if self.state != PaddleState::Active {
            return;
        }

        let position = self.base().get_position();
        let target_x = (position.x + std::mem::take(&mut self.x_offset))
            .clamp(self.clamp_range.x, self.clamp_range.y);

        self.base_mut()
            .set_position(Vector2::new(target_x, position.y));
    }
}

impl Paddle {
    pub fn aiming_position(&mut self) {
        self.base_mut().set_position(Vector2::new(640.0, 700.0)); // 发射小球时的固定位置
    }
}

#[derive(PartialEq, Default, Clone, Copy)]
pub enum PaddleState {
    #[default]
    Frozen,
    Active,
}
impl State for PaddleState {}

impl Stateful for Paddle {
    type S = PaddleState;

    fn on_state_enter(&mut self) {
        match self.state {
            PaddleState::Active => {
                self.x_offset = 0.0; // 清空偏移量,确保进入Active状态后paddle不会突然移动
            }
            PaddleState::Frozen => {
                self.base_mut().set_physics_process(false); // 关闭物理帧
            }
        }
    }

    fn on_state_exit(&mut self) {
        match self.state {
            PaddleState::Active => {}
            PaddleState::Frozen => {
                self.base_mut().set_physics_process(true); // 启动物理帧
            }
        }
    }

    fn set_state(&mut self, new_state: Self::S) {
        self.state = new_state;
    }

    fn state(&self) -> Self::S {
        self.state
    }
}

Paddle 是长为200,这也是为何self.clamp_range.init(Vector2::new(100.0, size.x - 100.0));这里左右都要缩进100的原因。

编译rust后,进入godot编辑器,创建Paddle场景。

同样,Paddle 使用Sprite2D提供视觉能力,将工程里的paddle.png拖入,CollisionShape2D来参与碰撞计算,使用CapsuleShape2D,用鼠标调整其到合适的大小,注意CapsuleShape2D需要旋转90度才能将其放平。

参考

  1. godot-rust(gdext)创建项目 - 掘金
  2. godot - Rust
  3. Make Pong Game in Godot | gameidea
  4. Pong with GDScript Demo - Godot Asset Library
相关推荐
SmalBox13 小时前
【节点】[GradientNoise节点]原理解析与实际应用
unity3d·游戏开发·图形学
wgc2k15 小时前
Oops Framework-6-项目中如何使用AI的思路
人工智能·游戏·cocos2d
小熊Coding15 小时前
从零打造一款回合制 RPG 游戏:基于 Pygame 的《塔影守卫》全解析
python·游戏·计算机专业·pygame·rpg·2d游戏
小雨下雨的雨16 小时前
iOS风格计算器 - 鸿蒙PC Electron框架上的技术实现详解
游戏·ios·华为·electron·harmonyos·鸿蒙
小雨下雨的雨16 小时前
五子棋AI在鸿蒙PC Electron上的实现的原理与实践
人工智能·游戏·华为·electron·harmonyos·鸿蒙
小雨下雨的雨19 小时前
通过鸿蒙PC Electron框架技术完成-井字棋游戏 - 实现详解
前端·javascript·游戏·华为·electron·鸿蒙
winlife_19 小时前
全程用 AI 做一款商业级手游 · EP0 立项:能做到吗、怎么做、边界在哪
人工智能·unity·ai编程·游戏开发·商业化·mcp·funplay
小雨下雨的雨20 小时前
基于鸿蒙PC Electron框架技术完成的五子棋游戏 - 技术实现详解
前端·javascript·游戏·华为·electron·鸿蒙
提子拌饭1331 天前
逛三园游戏——基于鸿蒙PC Electron框架实现
前端·javascript·游戏·华为·electron·鸿蒙
开开心心就好1 天前
支持多显示器的Windows高效分屏工具
运维·python·科技·游戏·计算机外设·ocr·powerpoint