你遇到的错误:
```
undefined reference to `__imp_GetStockObject'
undefined reference to `__imp_SelectObject'
undefined reference to `__imp_CreateSolidBrush'
...
undefined reference to `__imp_AlphaBlend'
ld returned 1 exit status
```
是 **链接器(linker)错误**,表示编译器找到了函数声明,但无法找到这些 Windows GDI 函数的实际实现 —— 因为 **缺少必要的系统库**。
---
## ✅ 根本原因
你在代码中使用了底层 Windows GDI API 函数:
- `GetStockObject`
- `SelectObject`
- `CreateSolidBrush`
- `Rectangle`, `Ellipse`
- `AlphaBlend` ← 来自 `MSIMG32.LIB`
这些函数不属于 C++ 标准库,也不是 EasyX 提供的,而是来自 Windows SDK。
你需要 **显式链接以下两个系统库**:
1. `gdi32.lib` —— 提供 GDI 绘图函数(如 `SelectObject`, `Rectangle` 等)
2. `msimg32.lib` —— 提供 `AlphaBlend` 函数(透明混合)
否则就会出现 `undefined reference to __imp_...` 错误。
---
## ✅ 解决方案:在 Dev-C++ 中添加所需库
### 方法一:通过项目设置添加库(推荐)
#### 步骤如下:
1. 打开你的 Dev-C++ 项目。
2. 菜单栏点击:**Project → Project Options**
3. 切换到 **"Parameters"** 选项卡
4. 在 **"Linker"** 输入框中添加以下两行:
```
-lgdi32
-lmsimg32
```
> 注意:前面有个 `-l`(小写的 L),表示 link library
5. 点击 OK 保存设置
6. 重新编译运行
---
### 方法二:命令行方式模拟(如果你不用项目)
如果你只是单独编译一个 `.cpp` 文件,应该这样调用 g++:
```bash
g++ 9191.cpp -o 9191.exe -lgdi32 -lmsimg32
```
其中:
- `-lgdi32` → 链接 GDI32 库
- `-lmsimg32` → 支持 AlphaBlend 透明绘图
---
## ✅ 修改后的完整可运行代码(确保兼容性)
```cpp
#include <graphics.h>
#include <conio.h>
#include <time.h>
#include <stdio.h>
#include <windows.h>
#include <math.h>
// 屏幕尺寸
const int WIDTH = 800;
const int HEIGHT = 600;
// 游戏设置
const int PLAYER_SPEED = 5;
const int SIGHT_RADIUS = 120;
const int SCARE_CHANCE = 300;
const int GAME_DURATION = 60; // 秒
// 全局变量
IMAGE buffer; // 双缓冲图像
float playerX, playerY;
bool scaryFaceShown;
int scareTimer;
clock_t startTime;
bool gameRunning;
// 初始化游戏
void InitGame() {
initgraph(WIDTH, HEIGHT);
loadimage(&buffer, NULL, WIDTH, HEIGHT); // 创建后台缓冲区
playerX = WIDTH / 2;
playerY = HEIGHT / 2;
scaryFaceShown = false;
scareTimer = 0;
startTime = clock();
gameRunning = true;
srand(time(NULL));
MessageBoxA(GetHWnd(),
"Game Start!\nSurvive in the dark for 60 seconds.\nUse WASD to move",
"Horror Game",
MB_OK | MB_ICONINFORMATION);
}
// 绘制黑暗遮罩(视野洞)
void DrawVisionMask(HDC hdcMem) {
// 填充黑色背景
setfillcolor(BLACK);
fillrectangle(0, 0, WIDTH, HEIGHT);
HDC hdcBuf = GetImageHDC(&buffer);
// 创建白色圆形区域用于“挖洞”
HPEN hNullPen = (HPEN)GetStockObject(NULL_PEN);
HBRUSH hWhiteBrush = CreateSolidBrush(RGB(255, 255, 255));
SelectObject(hdcBuf, hNullPen);
SelectObject(hdcBuf, hWhiteBrush);
Rectangle(hdcBuf, 0, 0, WIDTH + 1, HEIGHT + 1); // 全白底
Ellipse(hdcBuf,
(int)(playerX - SIGHT_RADIUS), (int)(playerY - SIGHT_RADIUS),
(int)(playerX + SIGHT_RADIUS), (int)(playerY + SIGHT_RADIUS));
// 设置 Alpha 混合参数(半透明黑层覆盖)
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 200; // 透明度:200/255
bf.AlphaFormat = 0;
AlphaBlend(hdcMem, 0, 0, WIDTH, HEIGHT, hdcBuf, 0, 0, WIDTH, HEIGHT, bf);
DeleteObject(hWhiteBrush);
}
// 绘制惊吓鬼脸
void DrawScaryFace() {
setfillcolor(RGB(255, 230, 230));
fillellipse(WIDTH / 2, HEIGHT / 2, 300, 200);
setfillcolor(BLACK);
fillellipse(WIDTH / 2 - 80, HEIGHT / 2 - 40, 30, 50);
fillellipse(WIDTH / 2 + 80, HEIGHT / 2 - 40, 30, 50);
setfillcolor(RED);
fillellipse(WIDTH / 2 - 70, HEIGHT / 2 - 30, 10, 5);
fillellipse(WIDTH / 2 + 90, HEIGHT / 2 - 30, 10, 5);
POINT mouth[] = {
{WIDTH / 2 - 100, HEIGHT / 2 + 80},
{WIDTH / 2, HEIGHT / 2 + 120},
{WIDTH / 2 + 100, HEIGHT / 2 + 80},
{WIDTH / 2, HEIGHT / 2 + 90}
};
setlinecolor(RED);
setlinestyle(PS_SOLID | PS_JOIN_ROUND, 8);
polyline(mouth, 4);
for (int i = 0; i < 15; i++) {
int x = rand() % WIDTH;
int y = rand() % HEIGHT;
setfillcolor(RGB(100, 0, 0));
fillcircle(x, y, rand() % 3 + 1);
}
static bool played = false;
if (!played) {
Beep(800, 300);
Beep(600, 200);
played = true;
}
}
// 更新逻辑
void Update() {
double elapsed = (clock() - startTime) / (double)CLOCKS_PER_SEC;
int timeLeft = GAME_DURATION - (int)elapsed;
if (timeLeft <= 0) {
MessageBoxA(GetHWnd(), "You survived!", "Victory!", MB_OK | MB_ICONASTERISK);
gameRunning = false;
return;
}
char msg[64];
sprintf(msg, "Time left: %d sec", timeLeft);
settextcolor(YELLOW);
setbkmode(TRANSPARENT);
outtextxy(10, 10, msg);
if (!scaryFaceShown && rand() % SCARE_CHANCE == 0 && timeLeft > 10) {
scaryFaceShown = true;
scareTimer = 60;
Beep(1000, 100);
}
if (scaryFaceShown) {
scareTimer--;
if (scareTimer <= 0) {
scaryFaceShown = false;
}
}
if (GetAsyncKeyState('W') & 0x8000) playerY -= PLAYER_SPEED;
if (GetAsyncKeyState('S') & 0x8000) playerY += PLAYER_SPEED;
if (GetAsyncKeyState('A') & 0x8000) playerX -= PLAYER_SPEED;
if (GetAsyncKeyState('D') & 0x8000) playerX += PLAYER_SPEED;
if (playerX < 0) playerX = 0;
if (playerX > WIDTH) playerX = WIDTH;
if (playerY < 0) playerY = 0;
if (playerY > HEIGHT) playerY = HEIGHT;
}
// 主循环
void GameLoop() {
BeginBatchDraw();
while (gameRunning) {
SetWorkingImage(&buffer);
cleardevice();
setlinecolor(LIGHTGRAY);
setlinestyle(PS_DASH, 2);
for (int i = 0; i < 15; i++) {
int x1 = rand() % WIDTH;
int y1 = rand() % HEIGHT;
int x2 = rand() % WIDTH;
int y2 = rand() % HEIGHT;
double dist = sqrt((x1 - playerX)*(x1 - playerX) + (y1 - playerY)*(y1 - playerY));
if (dist < SIGHT_RADIUS * 2.5f) {
line(x1, y1, x2, y2);
}
}
setfillcolor(scaryFaceShown ? RED : GREEN);
fillcircle((int)playerX, (int)playerY, 10);
if (scaryFaceShown) {
DrawScaryFace();
}
DrawVisionMask(GetImageHDC(&buffer));
SetWorkingImage(); // 切回屏幕
putimage(0, 0, &buffer); // 显示帧
Update();
FlushBatchDraw();
Sleep(16);
}
EndBatchDraw();
}
// 清理资源
void Cleanup() {
closegraph();
}
// 主函数
int main() {
InitGame();
GameLoop();
Cleanup();
return 0;
}
```
---
## ✅ 再次强调:必须做的操作
### ✔️ 必须链接这两个库:
- `gdi32.lib`
- `msimg32.lib`
### ✔️ Dev-C++ 添加方法:
> Project → Project Options → Parameters → Linker
> 输入:
```
-lgdi32
-lmsimg32
```
✅ 完成后即可成功编译!
---
###