EasyX 是一个专门为 C++ 设计的、简单易用的图形库,但它也兼容 C 语言,如果你在 Windows 环境下开发,这是一个非常好的选择,因为它能让你专注于游戏逻辑,而不用去处理复杂的 Windows API 或 DirectX。

(图片来源网络,侵删)
第一步:环境准备
-
安装 EasyX:
- 访问 EasyX 官网。
- 下载并安装最新版本的 EasyX,安装过程非常简单,一路“下一步”即可,它会自动配置好你的 Visual Studio(或其他支持的 C++ 编译器)。
-
创建项目:
- 打开 Visual Studio。
- 创建一个新的“控制台应用程序”项目。
- 在项目属性中,确保将“字符集”设置为“使用多字节字符集”,这可以避免一些编码问题。
第二步:完整 C 语言代码
将以下代码复制到你的 .c 文件中(flappy_bird.c)。
#include <stdio.h>
#include <stdlib.h>
#include <conio.h> // 用于 _kbhit() 和 _getch()
#include <graphics.h> // EasyX 图形库头文件
#include <time.h> // 用于随机数生成
// --- 游戏常量 ---
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
#define BIRD_SIZE 30
#define GRAVITY 0.5
#define JUMP_FORCE -8
#define PIPE_WIDTH 80
#define PIPE_GAP 180
#define PIPE_SPEED 3
#define GROUND_HEIGHT 50
#define GROUND_Y (SCREEN_HEIGHT - GROUND_HEIGHT)
#define BIRD_START_X 200
#define BIRD_START_Y SCREEN_HEIGHT / 2
// --- 游戏状态 ---
typedef struct {
int x;
int y;
double velocity;
} Bird;
typedef struct {
int x;
int top_height;
} Pipe;
// --- 函数声明 ---
void initGame(Bird* bird, Pipe* pipes);
void updateGame(Bird* bird, Pipe* pipes, int* score, int* game_over);
void drawGame(const Bird* bird, const Pipe* pipes, int score, int game_over);
void drawBird(const Bird* bird);
void drawPipes(const Pipe* pipes);
void drawGround();
void drawScore(int score);
void drawGameOver(int score);
// --- 主函数 ---
int main() {
// 初始化图形窗口
initgraph(SCREEN_WIDTH, SCREEN_HEIGHT);
// 设置随机数种子
srand((unsigned int)time(NULL));
Bird bird;
Pipe pipes[3]; // 使用3个管道实现循环滚动
int score = 0;
int game_over = 0;
// 初始化游戏
initGame(&bird, pipes);
// 游戏主循环
while (1) {
// 更新游戏状态
if (!game_over) {
updateGame(&bird, pipes, &score, &game_over);
}
// 绘制游戏画面
drawGame(&bird, pipes, score, game_over);
// 控制帧率,并处理退出
Sleep(20); // 约 50 FPS
if (_kbhit()) {
char ch = _getch();
if (ch == 27) { // ESC 键退出
break;
}
if (ch == ' ' && game_over) { // 空格键重新开始
initGame(&bird, pipes);
score = 0;
game_over = 0;
}
if (ch == ' ' && !game_over) { // 空格键跳跃
bird.velocity = JUMP_FORCE;
}
}
}
// 关闭图形窗口
closegraph();
return 0;
}
// --- 函数实现 ---
// 初始化游戏状态
void initGame(Bird* bird, Pipe* pipes) {
bird->x = BIRD_START_X;
bird->y = BIRD_START_Y;
bird->velocity = 0;
// 初始化3个管道,让它们均匀分布
for (int i = 0; i < 3; i++) {
pipes[i].x = SCREEN_WIDTH + i * (SCREEN_WIDTH / 3);
pipes[i].top_height = rand() % (SCREEN_HEIGHT - PIPE_GAP - GROUND_HEIGHT - 100) + 50;
}
}
// 更新游戏逻辑
void updateGame(Bird* bird, Pipe* pipes, int* score, int* game_over) {
// 1. 更新小鸟
bird->velocity += GRAVITY;
bird->y += (int)bird->velocity;
// 2. 更新管道
for (int i = 0; i < 3; i++) {
pipes[i].x -= PIPE_SPEED;
// 如果管道移出屏幕,将其重置到最右边
if (pipes[i].x + PIPE_WIDTH < 0) {
pipes[i].x = SCREEN_WIDTH;
pipes[i].top_height = rand() % (SCREEN_HEIGHT - PIPE_GAP - GROUND_HEIGHT - 100) + 50;
}
// 3. 检测碰撞
// 管道x坐标范围
if (bird->x + BIRD_SIZE > pipes[i].x && bird->x < pipes[i].x + PIPE_WIDTH) {
// 检测是否撞到上管道或下管道
if (bird->y < pipes[i].top_height || bird->y + BIRD_SIZE > pipes[i].top_height + PIPE_GAP) {
*game_over = 1;
}
}
// 4. 计分
// 当小鸟通过管道时加分
if (bird->x == pipes[i].x + PIPE_WIDTH / 2) {
(*score)++;
}
}
// 5. 检测地面和天花板碰撞
if (bird->y + BIRD_SIZE > GROUND_Y || bird->y < 0) {
*game_over = 1;
}
}
// 绘制游戏画面
void drawGame(const Bird* bird, const Pipe* pipes, int score, int game_over) {
// 清屏,填充天蓝色背景
setfillcolor(RGB(135, 206, 235));
solidrectangle(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
// 绘制游戏元素
drawPipes(pipes);
drawBird(bird);
drawGround();
drawScore(score);
if (game_over) {
drawGameOver(score);
}
}
// 绘制小鸟(一个黄色的圆形)
void drawBird(const Bird* bird) {
setfillcolor(YELLOW);
solidcircle(bird->x + BIRD_SIZE / 2, bird->y + BIRD_SIZE / 2, BIRD_SIZE / 2);
// 简单的眼睛
setfillcolor(BLACK);
solidcircle(bird->x + BIRD_SIZE / 2 + 5, bird->y + BIRD_SIZE / 2 - 5, 3);
}
// 绘制管道(绿色的矩形)
void drawPipes(const Pipe* pipes) {
setfillcolor(GREEN);
for (int i = 0; i < 3; i++) {
// 上管道
solidrectangle(pipes[i].x, 0, pipes[i].x + PIPE_WIDTH, pipes[i].top_height);
// 下管道
solidrectangle(pipes[i].x, pipes[i].top_height + PIPE_GAP, pipes[i].x + PIPE_WIDTH, SCREEN_HEIGHT);
}
}
// 绘制地面
void drawGround() {
setfillcolor(BROWN);
solidrectangle(0, GROUND_Y, SCREEN_WIDTH, SCREEN_HEIGHT);
}
// 绘制分数
void drawScore(int score) {
setbkmode(TRANSPARENT); // 设置文字背景透明
settextcolor(WHITE);
settextstyle(50, 0, _T("Arial"));
TCHAR score_str[16];
_stprintf(score_str, _T("%d"), score);
outtextxy(SCREEN_WIDTH / 2 - 20, 50, score_str);
}
// 绘制游戏结束画面
void drawGameOver(int score) {
setbkmode(TRANSPARENT);
settextcolor(WHITE);
settextstyle(60, 0, _T("Arial"));
outtextxy(SCREEN_WIDTH / 2 - 120, SCREEN_HEIGHT / 2 - 100, _T("Game Over"));
settextstyle(30, 0, _T("Arial"));
TCHAR score_str[32];
_stprintf(score_str, _T("Final Score: %d"), score);
outtextxy(SCREEN_WIDTH / 2 - 100, SCREEN_HEIGHT / 2, score_str);
outtextxy(SCREEN_WIDTH / 2 - 120, SCREEN_HEIGHT / 2 + 50, _T("Press SPACE to restart"));
}
第三步:代码解释
头文件和常量
#include <graphics.h>: 引入 EasyX 图形库。#include <conio.h>: 用于检测键盘输入(_kbhit,_getch),无需按回车即可响应。#define ...: 定义了游戏中用到的各种尺寸和速度常量,方便统一修改。
游戏状态结构体
Bird: 存储小鸟的位置 (x,y) 和垂直速度 (velocity),使用double存储速度可以使运动更平滑。Pipe: 存储管道的x坐标和上管道的高度 (top_height),下管道的高度可以通过top_height + PIPE_GAP计算得出。
main() 函数 - 游戏循环
这是游戏的核心。

(图片来源网络,侵删)
initgraph(): 创建一个 800x600 的窗口。srand(): 初始化随机数生成器,用于随机生成管道的高度。while(1): 无限循环,持续运行游戏。- 更新:
updateGame()函数负责计算所有物体的新位置、检测碰撞、更新分数。 - 绘制:
drawGame()函数负责清空屏幕并重新绘制所有游戏元素(背景、管道、小鸟、地面、分数)。 - 输入与帧率控制:
Sleep(20): 暂停 20 毫秒,将游戏帧率控制在约 50 FPS,避免游戏运行过快。_kbhit(): 检查是否有键盘输入。_getch(): 获取按下的键。ESC: 退出游戏。空格键: 游戏中控制小鸟跳跃;游戏结束后重新开始。
initGame() - 初始化
设置小鸟的初始位置和速度,并初始化3个管道的位置,让它们均匀分布在屏幕上,形成连续的“管道流”。
updateGame() - 核心逻辑
- 小鸟物理: 应用重力 (
velocity += GRAVITY),并根据速度更新位置 (y += velocity)。 - 管道移动: 将所有管道向左移动 (
x -= PIPE_SPEED),如果管道完全移出屏幕左侧,就将其重置到屏幕最右侧,并随机生成一个新的高度,实现循环。 - 碰撞检测:
- 管道: 判断小鸟是否在管道的
x轴范围内,并且是否在上下管道之间的y轴范围之外。 - 地面/天花板: 判断小鸟的
y坐标是否超出地面或低于屏幕顶部。
- 管道: 判断小鸟是否在管道的
- 计分: 当小鸟的
x坐标与管道中心线对齐时,认为小鸟成功通过一个管道,分数加一。
drawGame() 及其辅助函数
setfillcolor(): 设置填充颜色。solidrectangle(): 绘制一个填充的矩形(用于背景、管道、地面)。solidcircle(): 绘制一个填充的圆(用于小鸟)。setbkmode(TRANSPARENT): 设置文字背景为透明,这样文字就不会覆盖背景图。settextstyle(): 设置字体、大小和样式。outtextxy(): 在指定位置绘制文字(用于显示分数和 "Game Over")。
第四步:如何编译和运行
- 确保你已经按照第一步安装了 EasyX。
- 将上述代码保存为
flappy_bird.c文件,并添加到你的 Visual Studio 项目中。 - 确保 Visual Studio 的项目配置中,字符集 设置为 “使用多字节字符集”。
- 点击“生成” -> “生成解决方案” (F7) 或直接按 Ctrl + F5 运行程序。
你应该就能看到一个窗口弹出来,玩这个 C 语言版的 Flappy Bird 了!祝你玩得开心!

(图片来源网络,侵删)
