乒乓球游戏:C++ GDExtension 实现

这个提交包含在:
2026-08-05 15:10:47 +08:00
父节点 7b7757c002
当前提交 7228d302f5
修改 117 个文件,包含 803 行新增121 行删除
+10 -6
查看文件
@@ -1,12 +1,16 @@
# Godot 4+ specific ignores
.godot/
/android/
# Godot 项目文件
main/.godot/
main/android/
# C++ 扩展编译产物
/build/
/bin/
# C++ 编译产物
build/
main/bin/
# IDE
*.user
*.suo
.vs/
.vscode/
# 其他
.DS_Store
+1
查看文件
@@ -0,0 +1 @@
+73
查看文件
@@ -0,0 +1,73 @@
[docks]
dock_3_selected_tab_idx=0
dock_4_selected_tab_idx=0
dock_5_selected_tab_idx=0
dock_floating={}
dock_closed=[]
dock_split_2=0
dock_split_3=0
dock_hsplit_1=0
dock_hsplit_2=280
dock_hsplit_3=-280
dock_hsplit_4=0
dock_3="Scene,Import"
dock_4="FileSystem,History"
dock_5="Inspector,Signals,Groups"
dock_9="Output,Debugger,Audio,Animation,Shader Editor,Search Results,AnimationTree,ResourcePreloader,ShaderFile,SpriteFrames,Theme,Polygon,TileSet,TileMap,Replication,GridMap"
[docks/FileSystem]
h_split_offset=300
v_split_offset=0
display_mode=0
file_sort=0
file_list_display_mode=1
selected_paths=PackedStringArray("res://")
uncollapsed_paths=PackedStringArray("Favorites", "res://")
[docks/History]
include_scene=true
include_global=true
[EditorNode]
open_scenes=PackedStringArray()
current_scene=""
bottom_panel_offsets={
"Animation": 0,
"Audio": -450,
"Debugger": 0,
"Output": 0,
"Shader Editor": 0
}
selected_default_debugger_tab_idx=0
selected_main_editor_idx=0
[EditorWindow]
screen=0
mode="maximized"
position=Vector2i(0, 45)
[ScriptEditor]
open_scripts=[]
selected_script=""
open_help=[]
script_split_offset=250
list_split_offset=0
zoom_factor=1.0
[GameView]
floating_window_rect=Rect2i(0, 0, 0, 0)
floating_window_screen=-1
[ShaderEditor]
open_shaders=[]
split_offset=250
selected_shader=""
text_shader_zoom_factor=1.0
二进制文件未显示。
@@ -0,0 +1,3 @@
[folding]
sections_unfolded=PackedStringArray()
查看文件
查看文件
+3
查看文件
@@ -0,0 +1,3 @@
63f7b34db8d8cdea90c76aacccf841ec
::res://::1770910434
icon.svg::CompressedTexture2D::1032248987546973613::1770899576::1770899582::1::::<><><>0<>0<>a844cc33f2422ec468dcd6fc2526be58<>res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex::
+11
查看文件
@@ -0,0 +1,11 @@
[game_view]
select_mode=0
[editor_metadata]
executable_path="F:/Godot_v4.6-stable_win64.exe"
[dialog_bounds]
create_new_node=Rect2(397, 162, 1624, 875)
+1
查看文件
@@ -0,0 +1 @@
list=[]
二进制文件未显示。
@@ -0,0 +1,3 @@
source_md5="a16f2eed1b4496c4abf03d329708ba09"
dest_md5="b48bef1f2eefdd190e0a3e60a6188d75"
二进制
查看文件
二进制文件未显示。
+84
查看文件
@@ -0,0 +1,84 @@
# Pingpang
乒乓球对战游戏 — Godot 4.6 + C++ GDExtension
## 项目结构
```
pingpang/
├── CMakeLists.txt # CMake 构建配置
├── build-pingpang.bat # Windows 一键编译脚本
├── godot-cpp/ # Godot C++ 绑定(git submodule, 4.5 分支)
├── src/ # C++ 源码
│ ├── register_types.cpp/h # GDExtension 入口 + 类注册
│ ├── pingpong_ball.cpp/h # 球(移动、碰撞、得分检测)
│ ├── pingpong_paddle.cpp/h # 球拍(玩家输入 / AI)
│ └── pingpong_game.cpp/h # 游戏管理(计分、状态)
├── main/ # Godot 项目目录
│ ├── project.godot # Godot 项目配置
│ ├── pingpang.gdextension # GDExtension 加载配置
│ ├── scenes/
│ │ └── main.tscn # 主场景
│ ├── bin/ # 编译产物(gitignore
│ │ └── pingpang.dll
│ └── .godot/ # Godot 编辑器数据(gitignore
└── bin/ # 历史遗留(即将清理)
```
## 开发环境
| 工具 | 版本/路径 |
|---|---|
| Godot 编辑器 | 4.6 (`F:/PCL/MyDownload/Godot_v4.6-stable_win64.exe`) |
| CMake | VS 2026 自带 |
| Visual Studio | 2026 (`D:/Visual Studio/`) |
| godot-cpp | 4.5 分支 |
## 编译 & 运行
### 编译 C++ 扩展
```bash
# Windows: 双击运行
build-pingpang.bat
# 或手动
cmake -S . -B build -G "Visual Studio 18 2026" -A x64
cmake --build build --config Release
```
编译产物 `pingpang.dll` 会自动输出到 `main/bin/`
### 打开 Godot 项目
1. 启动 Godot 4.6 编辑器
2. 导入项目 → 选择 `main/` 目录
3. 打开后直接按 F5 运行
## 核心类说明
### PingPongBall (CharacterBody2D)
- `speed: float` — 球速(默认 400
- `reset()` — 重置到屏幕中央,随机方向发射
- `scored(which: int)` 信号 — 0=左边得分, 1=右边得分
### PingPongPaddle (CharacterBody2D)
- `speed: float` — 移动速度(默认 350
- `is_player: bool` — true=玩家控制, false=AI
- `ball_path: NodePath` — AI 模式下追踪的球节点
### PingPongGame (Node2D)
- `left_score: int` / `right_score: int` — 当前比分
- `max_score: int` — 获胜分数(默认 5
- `game_over(winner: int)` 信号 — 0=左边赢, 1=右边赢
## 协作指南
1. **添加新的 GDExtension 类**
-`src/` 创建 `.cpp`/`.h` 文件
-`src/register_types.cpp``GDREGISTER_CLASS()`
-`CMakeLists.txt``add_library()` 中添加源文件
2. **场景编辑**:在 Godot 编辑器中编辑 `main/scenes/main.tscn`,所有 C++ 类可在节点列表中直接创建
3. **提交代码前**:确保 `build-pingpang.bat` 编译通过
+20 -17
查看文件
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.24)
project(marry)
project(pingpang)
# 标准 C++17
set(CMAKE_CXX_STANDARD 17)
@@ -11,31 +11,34 @@ set(GODOT_CPP_PATH "${CMAKE_CURRENT_SOURCE_DIR}/godot-cpp")
add_subdirectory("${GODOT_CPP_PATH}")
# 扩展库本体
add_library(marry SHARED
add_library(pingpang SHARED
src/register_types.cpp
src/example.cpp
src/example.h
src/register_types.h
src/pingpong_ball.cpp
src/pingpong_ball.h
src/pingpong_paddle.cpp
src/pingpong_paddle.h
src/pingpong_game.cpp
src/pingpong_game.h
)
target_include_directories(marry PRIVATE src)
target_include_directories(pingpang PRIVATE src)
# 链接 godot-cpp
target_link_libraries(marry PRIVATE godot-cpp)
target_link_libraries(pingpang PRIVATE godot-cpp)
# 输出到 bin/ 目录(Godot 从那里加载;VS 里编译后 dll 直接落到 res://bin/
set_target_properties(marry PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin"
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin"
# 输出到 main/bin/ 目录(Godot 项目从这里加载 GDExtension
set_target_properties(pingpang PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/main/bin"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/main/bin"
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/main/bin"
PREFIX ""
)
# VS 多配置生成器会输出到 bin/Release/ 等子目录,这里复制到 bin/ 根目录
# 保证 .gdextension 里 res://bin/marry.dll 始终能找到
add_custom_command(TARGET marry POST_BUILD
# VS 多配置生成器会输出到子目录,这里复制到 main/bin/ 根目录
add_custom_command(TARGET pingpang POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"$<TARGET_FILE:marry>"
"${CMAKE_CURRENT_SOURCE_DIR}/bin/marry.dll"
COMMENT "复制 marry.dll 到 bin/ 根目录"
"$<TARGET_FILE:pingpang>"
"${CMAKE_CURRENT_SOURCE_DIR}/main/bin/$<TARGET_FILE_NAME:pingpang>"
COMMENT "复制 pingpang.dll 到 main/bin/ 根目录"
)
二进制
查看文件
二进制文件未显示。
二进制
查看文件
二进制文件未显示。
二进制
查看文件
二进制文件未显示。
二进制
查看文件
二进制文件未显示。

某些文件未显示,因为此 diff 中更改的文件太多 显示更多