# 俄罗斯方块游戏 - 完整使用指南 ## 📋 系统要求 - **PHP 版本**: >= 8.4.0 - **操作系统**: Windows 10/11 - **编译器**: MSVC (Microsoft Visual C++) - **依赖**: PHPX 编译器框架 ## 🎮 游戏介绍 这是一个使用 PHP 和 C++ 混合编程的俄罗斯方块游戏示例,展示了: - PHP 编写高层游戏逻辑 - C++ 提供底层图形 API 和性能关键代码 - 通过 Box 机制在 PHP 和 C++ 之间传递对象 ## 📁 项目结构 ``` tetris/ ├── main.php # 完整版游戏主程序 ├── test-simple.php # 简化测试版(用于快速验证) ├── project.yml # 项目配置文件 ├── README.md # 项目说明 ├── USAGE_GUIDE.md # 本使用指南 ├── php-src/ │ └── tetris.stub.php # C++ 函数的 PHP 声明 └── cpp-src/ └── tetris.cc # C++ 实现(游戏引擎 + 图形渲染) ``` ## 🔧 编译方法 ### 方法一:编译完整版游戏 ```bash cd examples/tetris php ../../bin/compiler.php build main.php ``` 或使用 project.yml: ```bash cd examples/tetris php ../../bin/compiler.php build . ``` ### 方法二:编译简化测试版 ```bash cd examples/tetris php ../../bin/compiler.php build test-simple.php ``` ### 编译选项 ```bash # 启用优化 php ../../bin/compiler.php build -O2 main.php # 启用调试信息 php ../../bin/compiler.php build --debug-info main.php # 指定输出文件名 php ../../bin/compiler.php build -o tetris-game main.php # 并行编译(加速) php ../../bin/compiler.php build -j 8 main.php ``` ## 🚀 运行游戏 编译成功后,会在 `build/` 目录生成可执行文件: ```bash # 运行完整版游戏 .\build\tetris.exe # 或运行测试版 .\build\test-simple.exe ``` ## 🎯 游戏控制 ### 键盘操作 | 按键 | 功能 | |------|------| | ← (左箭头) | 向左移动方块 | | → (右箭头) | 向右移动方块 | | ↑ (上箭头) | 旋转方块 | | ↓ (下箭头) | 加速下落 | | 空格键 | 直接落下(硬降) | ### 游戏规则 1. **基本玩法** - 不同形状的方块从顶部随机出现 - 玩家可以移动和旋转方块 - 方块落地后固定,新方块继续出现 2. **消除规则** - 当一行被完全填满时,该行消除 - 一次消除多行有额外奖励分数 - 消除后上方的方块会自动下落 3. **计分系统** - 消除 1 行:100 分 - 消除 2 行:400 分(2×2×100) - 消除 3 行:900 分(3×3×100) - 消除 4 行:1600 分(4×4×100) 4. **难度递增** - 初始下落间隔:500 毫秒 - 每获得 500 分,速度提升一级 - 最快下落间隔:100 毫秒 5. **游戏结束** - 当新方块无法放置时,游戏结束 - 显示最终得分 - 可以选择重新开始或退出 ## 🏗️ 技术架构 ### 三层架构设计 #### 1. C++ 层 (cpp-src/tetris.cc) **TetrisBox 类** - 继承自 `Box` ```cpp class TetrisBox : public Box { public: int board[BOARD_HEIGHT][BOARD_WIDTH]; // 游戏面板 int currentShape[4][4]; // 当前方块 int currentX, currentY; // 当前位置 int currentType; // 方块类型 int score; // 分数 bool gameOver; // 游戏状态 // 核心算法 void spawnNewPiece(); // 生成新方块 bool isValidPosition(); // 碰撞检测 void rotate(); // 旋转 bool moveDown/moveLeft/moveRight(); // 移动 void lockPiece(); // 固定方块 void clearLines(); // 消除行 }; ``` **导出的 C++ 函数**(以 `php_` 前缀命名): - `php_tetris_new()` - 创建游戏实例 - `php_tetris_reset()` - 重置游戏 - `php_tetris_get_score()` - 获取分数 - `php_tetris_is_game_over()` - 检查游戏结束 - `php_tetris_rotate/move_*()` - 方块控制 - `php_tetris_render()` - 图形渲染 - `php_tetris_handle_key()` - 键盘处理 #### 2. Stub 层 (php-src/tetris.stub.php) 声明所有 C++ 函数供 PHP 调用: ```php function tetris_new(): mixed {} function tetris_get_score(mixed $game): int {} function tetris_move_down(mixed $game): bool {} // ... 其他函数声明 ``` #### 3. PHP 层 (main.php) **TetrisGame 类** - 游戏主控制器 ```php class TetrisGame { private mixed $game; // C++ Box 对象 private int $hWnd; // 窗口句柄 private int $lastDropTime; // 上次下落时间 private int $dropInterval; // 下落间隔 public function initWindow() // 初始化窗口 public function run() // 游戏主循环 private function handleKeyPress() // 处理输入 private function handleGameOver() // 处理游戏结束 } ``` ### Box 对象传递机制 ``` C++ 层 PHP 层 ┌─────────────┐ │ TetrisBox │ new TetrisBox() │ extends Box│ ──────────────► mixed $game │ │ ◄────────────── 传递给 C++ 函数 └─────────────┘ toBox() ``` **关键点**: 1. C++ 类必须继承自 `Box` 2. 使用 `{new ClassName()}` 返回给 PHP 3. PHP 使用 `mixed` 类型接收 4. C++ 函数中使用 `box.toBox()` 转换回来 ### Windows GUI 编程 **窗口创建流程**: ```php // 1. 注册窗口类(C++ 中完成) // 2. 创建窗口 $hWnd = tetris_create_window("俄罗斯方块"); // 3. 显示窗口 tetris_show_window($hWnd, SW_SHOW); // 4. 消息循环 while (PeekMessage($msg, $hWnd, 0, 0, 1)) { // 处理消息 } // 5. 渲染画面 tetris_render($game, $hWnd); ``` **GDI 绘图**: - 使用 `FillRect` 绘制方块 - 使用 `Rectangle` 绘制边框 - 使用 `CreateSolidBrush` 设置颜色 - 支持 UTF-8 中文显示(通过 `MultiByteToWideChar` 转换) ## 🐛 常见问题 ### Q1: 编译时提示 PHP 版本过低 **错误信息**: ``` Composer detected issues in your platform: Your Composer dependencies require a PHP version ">= 8.4.0". You are running 8.1.27. ``` **解决方案**: 1. 升级 PHP 到 8.4+ 版本 2. 或修改 `composer.json` 中的版本要求(不推荐) ### Q2: 编译成功但运行时没有窗口 **可能原因**: - 使用了 `--no-console` 参数但没有正确创建窗口 - 窗口创建失败 **解决方案**: 1. 检查 `tetris_create_window()` 返回值是否为 0 2. 使用消息框调试:`tetris_messagebox(0, "Debug", "Info", 0)` 3. 查看是否有错误日志 ### Q3: 中文显示乱码 **解决方案**: 确保: 1. 源文件使用 UTF-8 编码保存 2. C++ 中使用 `MultiByteToWideChar` 转换 3. 使用 `MessageBoxW` 而不是 `MessageBoxA` ### Q4: 游戏运行卡顿 **优化建议**: 1. 减少渲染频率(目前约 60 FPS) 2. 使用 `-O2` 优化级别编译 3. 检查是否有内存泄漏 ### Q5: 如何调试游戏逻辑? **调试方法**: ```php // 1. 使用 echo 输出(控制台模式) echo "Score: " . tetris_get_score($game) . "\n"; // 2. 写入日志文件 file_put_contents('game.log', $message, FILE_APPEND); // 3. 使用消息框 tetris_messagebox(0, $message, "Debug", MB_OK); // 4. 使用调试模式编译 php ../../bin/compiler.php build --debug-info main.php ``` ## 📊 性能分析 ### 帧率控制 ```php Sleep(16); // 约 60 FPS (1000ms / 60 ≈ 16ms) ``` ### 自动下落计时 ```php $currentTime = GetTickCount(); if ($currentTime - $this->lastDropTime > $this->dropInterval) { tetris_move_down($this->game); $this->lastDropTime = $currentTime; } ``` ### 速度调整 ```php // 根据分数动态调整下落速度 $this->dropInterval = max(100, 500 - intdiv($score, 500) * 50); ``` ## 🔬 扩展开发 ### 添加新功能示例 #### 1. 添加暂停功能 **C++ 层** (`tetris.cc`): ```cpp Bool php_tetris_is_paused(var box) { auto tetris = box.toBox(); return tetris->paused; } void php_tetris_toggle_pause(var box) { auto tetris = box.toBox(); tetris->paused = !tetris->paused; } ``` **Stub 层** (`tetris.stub.php`): ```php function tetris_is_paused(mixed $game): bool {} function tetris_toggle_pause(mixed $game): void {} ``` **PHP 层** (`main.php`): ```php case VK_P: tetris_toggle_pause($this->game); break; ``` #### 2. 添加音效 可以使用 Windows API 的 `PlaySound` 函数: ```cpp #include void php_play_sound(String wavFile) { PlaySound(wavFile.data(), NULL, SND_FILENAME | SND_ASYNC); } ``` #### 3. 保存最高分 ```php function saveHighScore(int $score): void { file_put_contents('highscore.txt', $score); } function loadHighScore(): int { if (file_exists('highscore.txt')) { return (int)file_get_contents('highscore.txt'); } return 0; } ``` ## 📚 学习资源 ### 参考示例 - `examples/win32-hello` - Windows GUI 基础 - `examples/prime` - Box 对象封装 - `docs/MIXED_CPP_PHP.md` - C++ 和 PHP 混合编程 ### 外部资源 - [Windows API 文档](https://docs.microsoft.com/windows/win32/) - [GDI 绘图教程](https://docs.microsoft.com/windows/win32/gdi/) - [PHPX 编译器文档](https://github.com/swoole/phpx) ## 🎓 教学要点 这个项目适合学习: 1. **混合编程架构** - 如何在 PHP 和 C++ 之间分工 - 对象传递机制(Box) - 函数导出规范 2. **游戏开发基础** - 游戏循环设计 - 事件驱动编程 - 状态管理 3. **Windows 编程** - Win32 API 使用 - 消息循环处理 - GDI 图形绘制 4. **性能优化** - 计算密集型任务交给 C++ - PHP 负责高层逻辑 - 合理的帧率控制 ## 📝 许可证 本项目遵循与 PHPX 编译器相同的许可证。 ## 🤝 贡献 欢迎提交改进建议和 Bug 报告! --- **祝游戏愉快!** 🎮