<?php
require dirname(__DIR__) . '/vendor/autoload.php';
use Kingbes\Raylib\Core;
use Kingbes\Raylib\Utils;
use Kingbes\Raylib\Shapes;
use Kingbes\Raylib\Text;
const MAX_TUBES = 100;
const FLOPPY_RADIUS = 24;
const TUBES_WIDTH = 80;
const SCREEN_WIDTH = 800;
const SCREEN_HEIGHT = 450;
* 小鸟类
*/
class Floppy
{
public $position;
public int $radius;
public $color;
* 初始化小鸟
*
*/
public function __construct()
{
$this->radius = FLOPPY_RADIUS;
$this->position = Utils::vector2(80, SCREEN_HEIGHT / 2 - $this->radius);
$this->color = Utils::color(200, 200, 200);
}
}
* 管道类
*/
class Tubes
{
public $rec;
public $color;
public bool $active;
public function __construct()
{
$this->rec = Utils::rectangle(0, 0, TUBES_WIDTH, 255);
$this->color = Utils::color(100, 100, 100);
$this->active = false;
}
}
* 主游戏类 - 封装游戏逻辑和渲染
*/
class FlappyGame
{
public bool $gameOver = false;
public bool $pause = false;
public int $score = 0;
public int $hiScore = 0;
public Floppy $floppy;
public array $tubes;
public array $tubesPos;
public int $tubesSpeedX = 0;
public function __construct()
{
Core::initWindow(SCREEN_WIDTH, SCREEN_HEIGHT, 'Flappy Bird');
Core::setTargetFPS(60);
$this->initGame();
}
public function initGame()
{
$this->floppy = new Floppy();
$this->tubes = [];
$this->tubesPos = [];
$this->tubesSpeedX = 2;
$this->gameOver = false;
$this->pause = false;
$this->score = 0;
for ($i = 0; $i < MAX_TUBES; $i++) {
$this->tubesPos[$i] = Utils::vector2(
400 + 280 * $i, // 水平位置:间隔280像素
-Core::getRandomValue(0, 120) // 垂直位置:随机偏移
);
}
for ($i = 0; $i < MAX_TUBES * 2; $i++) {
$tube = new Tubes();
if ($i % 2 == 0) {
$tube->rec->x = $this->tubesPos[(int)($i / 2)]->x;
$tube->rec->y = $this->tubesPos[(int)($i / 2)]->y;
} else {
$tube->rec->x = $this->tubesPos[(int)($i / 2)]->x;
$tube->rec->y = 600 + $this->tubesPos[(int)($i / 2)]->y - 255;
}
$tube->active = true;
$this->tubes[$i] = $tube;
}
}
* 更新游戏状态
*/
public function updateGame(): void
{
if ($this->gameOver) {
if (Core::isKeyPressed(257)) {
$this->initGame();
$this->gameOver = false;
}
return;
}
if (Core::isKeyPressed(80)) {
$this->pause = !$this->pause;
}
if ($this->pause) {
return;
}
foreach ($this->tubesPos as $pos) {
$pos->x -= $this->tubesSpeedX;
}
for ($i = 0; $i < MAX_TUBES * 2; $i++) {
$this->tubes[$i]->rec->x = $this->tubesPos[(int)($i / 2)]->x;
}
if (Core::isKeyDown(32)) {
$this->floppy->position->y -= 3;
} else {
$this->floppy->position->y += 1;
}
$this->checkCollisions();
}
* 碰撞检测逻辑
*/
private function checkCollisions(): void
{
for ($i = 0; $i < MAX_TUBES * 2; $i++) {
$tube = $this->tubes[$i];
$pairIndex = (int)($i / 2);
if (!$tube->active) continue;
if (Shapes::checkCollisionCircleRec(
$this->floppy->position,
$this->floppy->radius,
$tube->rec
)) {
$this->gameOver = true;
return;
}
if ($this->tubesPos[$pairIndex]->x < ($this->floppy->position->x - TUBES_WIDTH - $this->floppy->radius)) {
$this->score += 100;
$this->tubes[$pairIndex * 2]->active = false;
$this->tubes[$pairIndex * 2 + 1]->active = false;
if ($this->score > $this->hiScore) {
$this->hiScore = $this->score;
}
}
}
}
* 渲染游戏画面
*/
public function drawGame(): void
{
Core::beginDrawing();
Core::clearBackground(Utils::color(255, 255, 255, 255));
if (!$this->gameOver) {
Shapes::drawCircle(
(int)$this->floppy->position->x,
(int)$this->floppy->position->y,
$this->floppy->radius,
$this->floppy->color
);
foreach ($this->tubes as $tube) {
if ($tube->active) {
Shapes::drawRectangleRec($tube->rec, $tube->color);
}
}
Text::drawText(
sprintf("%04d", $this->score), // 格式化分数为4位数
20,
20,
40,
// 红色
Utils::color(255, 0, 0)
);
Text::drawText(
"HI-SCORE: " . sprintf("%04d", $this->hiScore),
20,
70,
20,
// 绿色
Utils::color(0, 255, 0)
);
if ($this->pause) {
$text = "GAME PAUSED";
$textWidth = Text::measureText($text, 40);
Text::drawText(
$text,
(SCREEN_WIDTH - $textWidth) / 2,
SCREEN_HEIGHT / 2 - 40,
40,
Utils::color(100, 100, 100, 255)
);
}
} else {
$text = "PRESS [ENTER] TO PLAY AGAIN";
$textWidth = Text::measureText($text, 20);
Text::drawText(
$text,
(SCREEN_WIDTH - $textWidth) / 2,
SCREEN_HEIGHT / 2 - 50,
20,
Utils::color(100, 100, 100, 255)
);
}
Core::endDrawing();
}
* 游戏主循环
*/
public function run(): void
{
while (!Core::windowShouldClose()) {
$this->updateGame();
$this->drawGame();
}
Core::closeWindow();
}
}
$game = new FlappyGame();
$game->run();