|
|
# 俄罗斯方块游戏 - 快速开始
|
|
|
|
|
|
## 🎮 项目简介
|
|
|
|
|
|
这是一个使用 PHP 和 C++ 混合编程实现的俄罗斯方块游戏示例,展示了:
|
|
|
- PHP 编写高层游戏逻辑
|
|
|
- C++ 提供底层图形 API 和游戏状态管理
|
|
|
- 通过 Box 机制在 PHP 和 C++ 之间传递对象
|
|
|
|
|
|
## 📦 编译步骤
|
|
|
|
|
|
### 前置条件
|
|
|
- PHP 8.4+(路径:`D:\workspace\php-8.4.20\php.exe`)
|
|
|
- MSVC 编译器
|
|
|
- Windows 10/11 操作系统
|
|
|
|
|
|
### 编译命令
|
|
|
|
|
|
在项目根目录执行:
|
|
|
|
|
|
```bash
|
|
|
D:\workspace\php-8.4.20\php.exe bin\compiler.php examples/tetris
|
|
|
```
|
|
|
|
|
|
编译成功后会生成 `tetris.exe` 文件。
|
|
|
|
|
|
## 🚀 运行游戏
|
|
|
|
|
|
双击运行 `tetris.exe` 或在命令行中执行:
|
|
|
|
|
|
```bash
|
|
|
.\tetris.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`,封装游戏状态
|
|
|
- 游戏面板数据(10x20)
|
|
|
- 当前方块信息(形状、位置、类型)
|
|
|
- 分数和游戏状态
|
|
|
- 方块移动、旋转、消除等核心算法
|
|
|
|
|
|
- **Windows API 封装**:
|
|
|
- 窗口创建和管理
|
|
|
- GDI 图形渲染(绘制方块、网格)
|
|
|
- 键盘输入处理
|
|
|
- UTF-8 中文支持
|
|
|
|
|
|
#### 2. Stub 层 (`php-src/tetris.stub.php`)
|
|
|
- 声明所有 C++ 函数供 PHP 调用
|
|
|
- 定义函数签名和返回类型
|
|
|
- 使用 `mixed` 类型表示 Box 对象
|
|
|
|
|
|
#### 3. PHP 层 (`main.php`)
|
|
|
- **TetrisGame 类**:游戏主控制器
|
|
|
- 游戏循环管理
|
|
|
- 消息处理(键盘输入、窗口事件)
|
|
|
- 自动下落逻辑
|
|
|
- 速度递增机制
|
|
|
- 游戏结束处理
|
|
|
|
|
|
## 🔑 关键技术点
|
|
|
|
|
|
### Box 对象传递
|
|
|
|
|
|
C++ 的 `TetrisBox` 类继承自 `Box`,通过 `{new TetrisBox()}` 返回给 PHP 层,PHP 使用 `mixed` 类型接收和操作这个对象指针。
|
|
|
|
|
|
```cpp
|
|
|
// C++ 实现
|
|
|
var php_tetris_new() {
|
|
|
return {new TetrisBox()};
|
|
|
}
|
|
|
|
|
|
void php_tetris_move_down(Variant box) {
|
|
|
auto tetris = box.toBox<TetrisBox>();
|
|
|
// 操作游戏状态
|
|
|
}
|
|
|
```
|
|
|
|
|
|
```php
|
|
|
// PHP 调用
|
|
|
$game = tetris_new(); // 接收 mixed 类型
|
|
|
tetris_move_down($game); // 传递给 C++ 函数
|
|
|
```
|
|
|
|
|
|
### 函数命名规范
|
|
|
|
|
|
所有 C++ 函数必须以 `php_` 前缀命名,这样编译器才能识别并在 PHP 层调用。
|
|
|
|
|
|
### Windows GUI 编程
|
|
|
|
|
|
- 使用 Win32 API 创建窗口和处理消息循环
|
|
|
- GDI 绘图 API 进行图形渲染
|
|
|
- 支持 UTF-8 编码的中文显示(通过 `MultiByteToWideChar` 转换)
|
|
|
|
|
|
### 性能优化
|
|
|
|
|
|
- C++ 层处理所有计算密集型操作(碰撞检测、消除判断等)
|
|
|
- PHP 层负责高层逻辑和流程控制
|
|
|
- 使用 PeekMessage 实现非阻塞消息处理
|
|
|
- 帧率控制在约 60 FPS
|
|
|
|
|
|
## 📁 项目结构
|
|
|
|
|
|
```
|
|
|
tetris/
|
|
|
├── main.php # PHP 主程序(游戏逻辑)
|
|
|
├── project.yml # 项目配置文件
|
|
|
├── README.md # 项目说明
|
|
|
├── QUICKSTART.md # 本快速开始指南
|
|
|
├── php-src/
|
|
|
│ └── tetris.stub.php # C++ 函数的 PHP 声明(stub)
|
|
|
└── cpp-src/
|
|
|
└── tetris.cc # C++ 实现(图形 API 和游戏状态管理)
|
|
|
```
|
|
|
|
|
|
## 🔧 扩展开发
|
|
|
|
|
|
可以进一步改进的方向:
|
|
|
1. ✅ 添加完整的方块旋转逻辑
|
|
|
2. ✅ 实现真实的方块碰撞检测
|
|
|
3. ✅ 添加下一个方块预览
|
|
|
4. ✅ 添加暂停功能
|
|
|
5. ✅ 添加音效
|
|
|
6. ✅ 保存最高分记录
|
|
|
7. ✅ 添加幽灵方块(显示落点)
|
|
|
8. ✅ 支持自定义难度级别
|
|
|
|
|
|
## 📚 参考示例
|
|
|
|
|
|
本项目参考了以下示例:
|
|
|
- `examples/win32-hello`:Windows GUI 编程基础
|
|
|
- `examples/prime`:Box 对象封装和传递
|
|
|
|
|
|
## ⚠️ 注意事项
|
|
|
|
|
|
1. **类型匹配**:Stub 文件中使用 `mixed` 类型对应 C++ 的 `var`/`Variant` 类型
|
|
|
2. **编码问题**:C++ 源文件必须使用 UTF-8 编码以支持中文
|
|
|
3. **链接库**:需要链接 `user32.lib`、`gdi32.lib`、`kernel32.lib` 等 Windows 系统库
|
|
|
4. **Box 资源管理**:Box 对象由 C++ 管理内存,PHP 层只需持有引用
|
|
|
|
|
|
## 🎓 学习价值
|
|
|
|
|
|
这个项目适合学习:
|
|
|
- PHP 和 C++ 混合编程架构
|
|
|
- Box 对象传递机制
|
|
|
- Windows GUI 编程基础
|
|
|
- 游戏开发基本概念
|
|
|
- 跨语言类型映射
|
|
|
|
|
|
---
|
|
|
|
|
|
**祝游戏愉快!** 🎮✨
|
|
|
|