#include <graphics.h>
#include <stdio.h>
#include <conio.h>
#include <mmsystem.h>
#include <math.h>
#include <time.h>
#include <stdlib.h> // 添加缺少的头文件
#include <windows.h> // 添加缺少的头文件
#pragma comment(lib, "winmm.lib")
#define WIDTH 640
#define HEIGHT 480
#define MAP_WIDTH 20
#define MAP_HEIGHT 20
#define PACMAN_SIZE 20
#define BEAN_SIZE 5
#define ENEMY_SIZE 15
#define MAX_BEANS 50
#define MAX_ENEMIES 5
#define MAX_PROPS 5
#define LEVEL_COUNT 3
// 游戏状态
typedef enum {
MENU,
SELECT_DIFFICULTY,
PLAYING,
PAUSED,
GAME_OVER,
LEVEL_COMPLETED,
GAME_COMPLETED
} GameState;
// 方向
typedef enum {
RIGHT = 0,
DOWN = 1,
LEFT = 2,
UP = 3
} Direction;
// 难度
typedef enum {
EASY,
MEDIUM,
HARD
} Difficulty;
// 关卡结构体定义(新增)
typedef struct {
int map[MAP_HEIGHT][MAP_WIDTH];
int beanCount;
int enemyCount;
int propCount;
int requiredScore;
} Level;
// 吃豆人结构体
typedef struct {
int x;
int y;
int radius;
Direction direction;
int speed;
int lives;
int score;
int invincible; // 无敌状态
int invincibleTime;
IMAGE img; // 吃豆人图像
} Pacman;
// 豆子结构体
typedef struct {
int x;
int y;
int radius;
int eaten;
IMAGE img; // 豆子图像
} Bean;
// 敌人结构体
typedef struct {
int x;
int y;
int radius;
int speed;
Direction direction;
int state; // 0: 巡逻, 1: 追逐, 2: 逃跑
int scaredTimer; // 被吓到的时间
IMAGE img; // 敌人图像
} Enemy;
// 道具结构体
typedef struct {
int x;
int y;
int radius;
int type; // 0: 无敌, 1: 减速, 2: 加分
int active;
int duration;
IMAGE img; // 道具图像
} Prop;
// 全局变量
GameState gameState = MENU;
Difficulty difficulty = MEDIUM;
int currentLevel = 0;
int gamePaused = 0;
// 地图数组 - 修改为20x20以匹配关卡定义
int map[MAP_HEIGHT][MAP_WIDTH] = {
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1},
{1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
};
// 关卡定义
Level levels[LEVEL_COUNT] = {
{
// 第1关地图
{
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1},
{1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
},
20, // 豆子数量
2, // 敌人数量
1, // 道具数量
15 // 通关分数
},
{
// 第2关地图
{
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1},
{1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
},
30, // 豆子数量
3, // 敌人数量
2, // 道具数量
25 // 通关分数
},
{
// 第3关地图
{
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
},
40, // 豆子数量
4, // 敌人数量
3, // 道具数量
35 // 通关分数
}
};
// 函数声明
void initGame(Pacman* pacman, Bean beans[], int beanCount, Enemy enemies[], int enemyCount, Prop props[], int propCount);
void drawMap();
void drawGame(Pacman* pacman, Bean beans[], int beanCount, Enemy enemies[], int enemyCount, Prop props[], int propCount);
void movePacman(Pacman* pacman);
void moveEnemy(Enemy* enemy, Pacman* pacman, Bean beans[], int beanCount);
void checkCollision(Pacman* pacman, Bean beans[], int beanCount, Enemy enemies[], int enemyCount, Prop props[], int propCount);
void drawMenu();
void drawDifficultyMenu();
void drawGameOver(int score);
void drawLevelCompleted(int level, int score);
void drawGameCompleted(int score);
void handleInput(Pacman* pacman);
void loadLevel(int level, Pacman* pacman, Bean beans[], Enemy enemies[], Prop props[]);
void applyPropEffect(Pacman* pacman, Enemy enemies[], int enemyCount, int propType);
void updateProps(Prop props[], int propCount);
int main() {
initgraph(WIDTH, HEIGHT);
srand((unsigned int)time(NULL)); // 初始化随机数种子
Pacman pacman;
Bean beans[MAX_BEANS];
Enemy enemies[MAX_ENEMIES];
Prop props[MAX_PROPS];
// 加载第一关
loadLevel(currentLevel, &pacman, beans, enemies, props);
while (1) {
// 处理输入
handleInput(&pacman);
// 游戏逻辑
if (gameState == PLAYING && !gamePaused) {
movePacman(&pacman);
for (int i = 0; i < levels[currentLevel].enemyCount; i++) {
moveEnemy(&enemies[i], &pacman, beans, levels[currentLevel].beanCount);
}
checkCollision(&pacman, beans, levels[currentLevel].beanCount, enemies, levels[currentLevel].enemyCount, props, levels[currentLevel].propCount);
updateProps(props, levels[currentLevel].propCount);
// 检查是否通关
if (pacman.score >= levels[currentLevel].requiredScore) {
if (currentLevel < LEVEL_COUNT - 1) {
gameState = LEVEL_COMPLETED;
}
else {
gameState = GAME_COMPLETED;
}
}
}
// 绘制游戏
switch (gameState) {
case MENU:
drawMenu();
break;
case SELECT_DIFFICULTY:
drawDifficultyMenu();
break;
case PLAYING:
drawGame(&pacman, beans, levels[currentLevel].beanCount, enemies, levels[currentLevel].enemyCount, props, levels[currentLevel].propCount);
if (gamePaused) {
settextcolor(WHITE);
settextstyle(40, 0, _T("宋体"));
outtextxy(WIDTH / 2 - 80, HEIGHT / 2 - 20, _T("游戏暂停"));
settextstyle(20, 0, _T("宋体"));
outtextxy(WIDTH / 2 - 100, HEIGHT / 2 + 30, _T("按P键继续游戏"));
}
break;
case GAME_OVER:
drawGameOver(pacman.score);
break;
case LEVEL_COMPLETED:
drawLevelCompleted(currentLevel + 1, pacman.score);
break;
case GAME_COMPLETED:
drawGameCompleted(pacman.score);
break;
}
Sleep(20);
}
getch();
closegraph();
return 0;
}
void initGame(Pacman* pacman, Bean beans[], int beanCount, Enemy enemies[], int enemyCount, Prop props[], int propCount) {
// 初始化吃豆人
pacman->x = WIDTH / 2;
pacman->y = HEIGHT / 2;
pacman->radius = PACMAN_SIZE;
pacman->direction = RIGHT;
pacman->speed = 5;
pacman->lives = 3;
pacman->score = 0;
pacman->invincible = 0;
pacman->invincibleTime = 0;
// 加载吃豆人图像
// loadimage(&pacman->img, _T("pacman.png"));
// 初始化豆子
for (int i = 0; i < beanCount; i++) {
int x, y;
do {
x = rand() % MAP_WIDTH;
y = rand() % MAP_HEIGHT;
} while (map[y][x] == 1);
beans[i].x = x * 30 + 15;
beans[i].y = y * 30 + 15;
beans[i].radius = BEAN_SIZE;
beans[i].eaten = 0;
// 加载豆子图像
// loadimage(&beans[i].img, _T("bean.png"));
}
// 初始化敌人
for (int i = 0; i < enemyCount; i++) {
int x, y;
do {
x = rand() % MAP_WIDTH;
y = rand() % MAP_HEIGHT;
} while (map[y][x] == 1 || (abs(x * 30 + 15 - pacman->x) < 100 && abs(y * 30 + 15 - pacman->y) < 100));
enemies[i].x = x * 30 + 15;
enemies[i].y = y * 30 + 15;
enemies[i].radius = ENEMY_SIZE;
enemies[i].speed = 3 + difficulty; // 难度越高速度越快
enemies[i].direction = (Direction)(rand() % 4);
enemies[i].state = 0; // 初始巡逻状态
enemies[i].scaredTimer = 0;
// 加载敌人图像
// loadimage(&enemies[i].img, _T("enemy.png"));
}
// 初始化道具
for (int i = 0; i < propCount; i++) {
int x, y;
do {
x = rand() % MAP_WIDTH;
y = rand() % MAP_HEIGHT;
} while (map[y][x] == 1);
props[i].x = x * 30 + 15;
props[i].y = y * 30 + 15;
props[i].radius = 10;
props[i].type = rand() % 3; // 随机道具类型
props[i].active = 1;
props[i].duration = 500; // 道具持续时间
// 加载道具图像
// loadimage(&props[i].img, _T("prop.png"));
}
}
void drawMap() {
for (int y = 0; y < MAP_HEIGHT; y++) {
for (int x = 0; x < MAP_WIDTH; x++) {
if (map[y][x] == 1) {
// 绘制墙壁
setfillcolor(BLUE);
bar(x * 30, y * 30, (x + 1) * 30, (y + 1) * 30);
}
}
}
}
void drawGame(Pacman* pacman, Bean beans[], int beanCount, Enemy enemies[], int enemyCount, Prop props[], int propCount) {
// 清屏
cleardevice();
// 绘制地图
drawMap();
// 绘制吃豆人
static int frame = 0;
frame = (frame + 1) % 10;
if (pacman->invincible && (frame < 5)) {
setfillcolor(YELLOW);
}
else {
setfillcolor(RED);
}
// 如果加载了图像则显示图像,否则绘制圆形
// if (pacman->img.getwidth() > 0) {
// putimage(pacman->x - pacman->radius, pacman->y - pacman->radius, &pacman->img);
// } else {
// 根据方向调整嘴巴
int startAngle = 30;
int endAngle = 330;
switch (pacman->direction) {
case RIGHT:
startAngle = 30;
endAngle = 330;
break;
case DOWN:
startAngle = 120;
endAngle = 240;
break;
case LEFT:
startAngle = 210;
endAngle = 150;
break;
case UP:
startAngle = 300;
endAngle = 60;
break;
}
pieslice(pacman->x, pacman->y, startAngle, endAngle, pacman->radius);
// }
// 绘制豆子
for (int i = 0; i < beanCount; i++) {
if (!beans[i].eaten) {
// if (beans[i].img.getwidth() > 0) {
// putimage(beans[i].x - beans[i].radius, beans[i].y - beans[i].radius, &beans[i].img);
// } else {
setfillcolor(YELLOW);
circle(beans[i].x, beans[i].y, beans[i].radius);
// }
}
}
// 绘制道具
for (int i = 0; i < propCount; i++) {
if (props[i].active) {
// if (props[i].img.getwidth() > 0) {
// putimage(props[i].x - props[i].radius, props[i].y - props[i].radius, &props[i].img);
// } else {
// 根据道具类型设置不同颜色
switch (props[i].type) {
case 0: // 无敌
setfillcolor(GREEN);
break;
case 1: // 减速
setfillcolor(BLUE);
break;
case 2: // 加分
setfillcolor(RED);
break;
}
circle(props[i].x, props[i].y, props[i].radius);
// }
}
}
// 绘制敌人
for (int i = 0; i < enemyCount; i++) {
// if (enemies[i].img.getwidth() > 0) {
// if (enemies[i].scaredTimer > 0) {
// // 被吓到的敌人显示为青色
// IMAGE tempImg;
// tempImg = enemies[i].img;
// for (int y = 0; y < tempImg.getheight(); y++) {
// for (int x = 0; x < tempImg.getwidth(); x++) {
// COLORREF color = getpixel(x, y, &tempImg);
// if (color != BLACK) {
// putpixel(x, y, CYAN);
// }
// }
// }
// putimage(enemies[i].x - enemies[i].radius, enemies[i].y - enemies[i].radius, &tempImg);
// } else {
// putimage(enemies[i].x - enemies[i].radius, enemies[i].y - enemies[i].radius, &enemies[i].img);
// }
// } else {
if (enemies[i].scaredTimer > 0) {
setfillcolor(CYAN); // 被吓到的敌人显示为青色
}
else {
setfillcolor(MAGENTA);
}
circle(enemies[i].x, enemies[i].y, enemies[i].radius);
// }
}
// 显示得分和生命
char info[50];
sprintf_s(info, sizeof(info), "Score: %d Lives: %d", pacman->score, pacman->lives);
settextcolor(WHITE);
settextstyle(20, 0, _T("宋体"));
outtextxy(10, 10, info);
// 显示关卡
sprintf_s(info, sizeof(info), "Level: %d", currentLevel + 1);
outtextxy(WIDTH - 100, 10, info);
// 显示无敌时间
if (pacman->invincible) {
sprintf_s(info, sizeof(info), "Invincible: %d", pacman->invincibleTime / 10);
outtextxy(WIDTH / 2 - 50, 10, info);
}
}
void movePacman(Pacman* pacman) {
// 处理连续按键
if (_kbhit()) {
char key = _getch();
Direction newDirection = pacman->direction;
switch (key) {
case 'w':
newDirection = UP;
break;
case 's':
newDirection = DOWN;
break;
case 'a':
newDirection = LEFT;
break;
case 'd':
newDirection = RIGHT;
break;
}
// 改变方向
pacman->direction = newDirection;
}
// 根据当前方向移动
int newX = pacman->x;
int newY = pacman->y;
switch (pacman->direction) {
case RIGHT:
newX += pacman->speed;
break;
case DOWN:
newY += pacman->speed;
break;
case LEFT:
newX -= pacman->speed;
break;
case UP:
newY -= pacman->speed;
break;
}
// 检查是否可以移动
int mapX = newX / 30;
int mapY = newY / 30;
if (map[mapY][mapX] == 0) {
pacman->x = newX;
pacman->y = newY;
}
// 处理穿墙(从一边进入从另一边出来)
if (pacman->x < 0) pacman->x = WIDTH;
if (pacman->x > WIDTH) pacman->x = 0;
if (pacman->y < 0) pacman->y = HEIGHT;
if (pacman->y > HEIGHT) pacman->y = 0;
// 无敌时间减少
if (pacman->invincible) {
pacman->invincibleTime--;
if (pacman->invincibleTime <= 0) {
pacman->invincible = 0;
}
}
}
void moveEnemy(Enemy* enemy, Pacman* pacman, Bean beans[], int beanCount) {
// 如果被吓到,随机移动
if (enemy->scaredTimer > 0) {
enemy->scaredTimer--;
// 随机改变方向
if (rand() % 20 == 0) {
enemy->direction = (Direction)(rand() % 4);
}
}
else {
// 正常状态,决定是巡逻还是追逐
int dx = pacman->x - enemy->x;
int dy = pacman->y - enemy->y;
int distance = sqrt(dx * dx + dy * dy);
// 如果吃豆人在范围内且不是无敌状态,追逐
if (distance < 200 && !pacman->invincible) {
enemy->state = 1; // 追逐
}
else {
enemy->state = 0; // 巡逻
}
// 根据状态决定移动方式
if (enemy->state == 1) { // 追逐
if (abs(dx) > abs(dy)) {
if (dx > 0) {
enemy->direction = RIGHT;
}
else {
enemy->direction = LEFT;
}
}
else {
if (dy > 0) {
enemy->direction = DOWN;
}
else {
enemy->direction = UP;
}
}
}
else { // 巡逻
// 随机改变方向
if (rand() % 50 == 0) {
enemy->direction = (Direction)(rand() % 4);
}
}
}
// 根据方向移动
int newX = enemy->x;
int newY = enemy->y;
switch (enemy->direction) {
case RIGHT:
newX += enemy->speed;
break;
case DOWN:
newY += enemy->speed;
break;
case LEFT:
newX -= enemy->speed;
break;
case UP:
newY -= enemy->speed;
break;
}
// 检查是否可以移动
int mapX = newX / 30;
int mapY = newY / 30;
if (map[mapY][mapX] == 0) {
enemy->x = newX;
enemy->y = newY;
}
else {
// 撞到墙,随机改变方向
enemy->direction = (Direction)(rand() % 4);
}
// 处理穿墙
if (enemy->x < 0) enemy->x = WIDTH;
if (enemy->x > WIDTH) enemy->x = 0;
if (enemy->y < 0) enemy->y = HEIGHT;
if (enemy->y > HEIGHT) enemy->y = 0;
}
void checkCollision(Pacman* pacman, Bean beans[], int beanCount, Enemy enemies[], int enemyCount, Prop props[], int propCount) {
// 检测吃豆人吃豆子
for (int i = 0; i < beanCount; i++) {
if (!beans[i].eaten) {
int dx = pacman->x - beans[i].x;
int dy = pacman->y - beans[i].y;
if (dx * dx + dy * dy <= (pacman->radius + beans[i].radius) * (pacman->radius + beans[i].radius)) {
beans[i].eaten = 1;
pacman->score += 10;
// PlaySound(TEXT("eat.wav"), NULL, SND_FILENAME | SND_ASYNC);
}
}
}
// 检测吃豆人吃道具
for (int i = 0; i < propCount; i++) {
if (props[i].active) {
int dx = pacman->x - props[i].x;
int dy = pacman->y - props[i].y;
if (dx * dx + dy * dy <= (pacman->radius + props[i].radius) * (pacman->radius + props[i].radius)) {
props[i].active = 0;
applyPropEffect(pacman, enemies, enemyCount, props[i].type);
// PlaySound(TEXT("powerup.wav"), NULL, SND_FILENAME | SND_ASYNC);
}
}
}
// 检测吃豆人与敌人碰撞
for (int i = 0; i < enemyCount; i++) {
int dx = pacman->x - enemies[i].x;
int dy = pacman->y - enemies[i].y;
if (dx * dx + dy * dy <= (pacman->radius + enemies[i].radius) * (pacman->radius + enemies[i].radius)) {
if (pacman->invincible) {
// 无敌状态,敌人被吃掉
enemies[i].x = rand() % MAP_WIDTH * 30 + 15;
enemies[i].y = rand() % MAP_HEIGHT * 30 + 15;
enemies[i].scaredTimer = 0;
pacman->score += 50;
// PlaySound(TEXT("eatghost.wav"), NULL, SND_FILENAME | SND_ASYNC);
}
else if (enemies[i].scaredTimer > 0) {
// 敌人被吓到,被吃掉
enemies[i].x = rand() % MAP_WIDTH * 30 + 15;
enemies[i].y = rand() % MAP_HEIGHT * 30 + 15;
enemies[i].scaredTimer = 0;
pacman->score += 50;
// PlaySound(TEXT("eatghost.wav"), NULL, SND_FILENAME | SND_ASYNC);
}
else {
// 普通碰撞,扣生命值
pacman->lives--;
if (pacman->lives <= 0) {
// 游戏结束
// PlaySound(TEXT("gameover.wav"), NULL, SND_FILENAME | SND_ASYNC);
gameState = GAME_OVER;
}
else {
// 重置吃豆人位置
pacman->x = WIDTH / 2;
pacman->y = HEIGHT / 2;
pacman->invincible = 1;
pacman->invincibleTime = 200; // 短暂无敌
// PlaySound(TEXT("hurt.wav"), NULL, SND_FILENAME | SND_ASYNC);
}
}
}
}
}
void drawMenu() {
cleardevice();
settextcolor(WHITE);
settextstyle(40, 0, _T("宋体"));
outtextxy(WIDTH / 2 - 100, HEIGHT / 4, _T("吃豆人游戏"));
settextstyle(25, 0, _T("宋体"));
outtextxy(WIDTH / 2 - 70, HEIGHT / 2 - 30, _T("1. 开始游戏"));
outtextxy(WIDTH / 2 - 70, HEIGHT / 2 + 30, _T("2. 选择难度"));
outtextxy(WIDTH / 2 - 70, HEIGHT / 2 + 90, _T("3. 退出游戏"));
settextstyle(15, 0, _T("宋体"));
outtextxy(WIDTH / 2 - 120, HEIGHT - 50, _T("使用WASD控制吃豆人,P键暂停游戏"));
// 处理菜单选择
if (_kbhit()) {
char key = _getch();
switch (key) {
case '1':
case '\r': // 回车
gameState = PLAYING;
break;
case '2':
gameState = SELECT_DIFFICULTY;
break;
case '3':
case 27: // ESC
closegraph();
exit(0);
break;
}
}
}
void drawDifficultyMenu() {
cleardevice();
settextcolor(WHITE);
settextstyle(40, 0, _T("宋体"));
outtextxy(WIDTH / 2 - 100, HEIGHT / 4, _T("选择难度"));
settextstyle(25, 0, _T("宋体"));
outtextxy(WIDTH / 2 - 70, HEIGHT / 2 - 30, _T("1. 简单"));
outtextxy(WIDTH / 2 - 70, HEIGHT / 2 + 30, _T("2. 中等"));
outtextxy(WIDTH / 2 - 70, HEIGHT / 2 + 90, _T("3. 困难"));
// 处理难度选择
if (_kbhit()) {
char key = _getch();
switch (key) {
case '1':
difficulty = EASY;
gameState = MENU;
break;
case '2':
difficulty = MEDIUM;
gameState = MENU;
break;
case '3':
difficulty = HARD;
gameState = MENU;
break;
}
}
}
void drawGameOver(int score) {
cleardevice();
settextcolor(WHITE);
settextstyle(40, 0, _T("宋体"));
outtextxy(WIDTH / 2 - 100, HEIGHT / 4, _T("游戏结束"));
settextstyle(30, 0, _T("宋体"));
char info[50];
sprintf_s(info, sizeof(info), "得分: %d", score);
outtextxy(WIDTH / 2 - 70, HEIGHT / 2 - 30, info);
settextstyle(20, 0, _T("宋体"));
outtextxy(WIDTH / 2 - 100, HEIGHT / 2 + 30, _T("按任意键返回主菜单"));
if (_kbhit()) {
_getch(); // 消耗按键
gameState = MENU;
loadLevel(0, &(Pacman){0}, (Bean[]) { 0 }, (Enemy[]) { 0 }, (Prop[]) { 0 }); // 重新加载第一关
}
}
void drawLevelCompleted(int level, int score) {
cleardevice();
settextcolor(WHITE);
settextstyle(40, 0, _T("宋体"));
outtextxy(WIDTH / 2 - 100, HEIGHT / 4, _T("通关成功"));
settextstyle(30, 0, _T("宋体"));
char info[50];
sprintf_s(info, sizeof(info), "第 %d 关完成", level);
outtextxy(WIDTH / 2 - 70, HEIGHT / 2 - 30, info);
sprintf_s(info, sizeof(info), "得分: %d", score);
outtextxy(WIDTH / 2 - 70, HEIGHT / 2 + 30, info);
settextstyle(20, 0, _T("宋体"));
outtextxy(WIDTH / 2 - 100, HEIGHT / 2 + 90, _T("按任意键进入下一关"));
if (_kbhit()) {
_getch(); // 消耗按键
currentLevel++;
loadLevel(currentLevel, &(Pacman){0}, (Bean[]) { 0 }, (Enemy[]) { 0 }, (Prop[]) { 0 });
gameState = PLAYING;
}
}
void drawGameCompleted(int score) {
cleardevice();
settextcolor(WHITE);
settextstyle(40, 0, _T("宋体"));
outtextxy(WIDTH / 2 - 100, HEIGHT / 4, _T("恭喜通关"));
settextstyle(30, 0, _T("宋体"));
char info[50];
sprintf_s(info, sizeof(info), "总得分: %d", score);
outtextxy(WIDTH / 2 - 70, HEIGHT / 2 - 30, info);
settextstyle(20, 0, _T("宋体"));
outtextxy(WIDTH / 2 - 100, HEIGHT / 2 + 30, _T("你完成了所有关卡!"));
outtextxy(WIDTH / 2 - 100, HEIGHT / 2 + 90, _T("按任意键返回主菜单"));
if (_kbhit()) {
_getch(); // 消耗按键
gameState = MENU;
currentLevel = 0;
loadLevel(currentLevel, &(Pacman){0}, (Bean[]) { 0 }, (Enemy[]) { 0 }, (Prop[]) { 0 });
}
}
void handleInput(Pacman* pacman) {
if (_kbhit()) {
char key = _getch();
switch (key) {
case 27: // ESC
if (gameState == PLAYING) {
gameState = MENU;
}
break;
case 'p':
case 'P':
if (gameState == PLAYING) {
gamePaused = !gamePaused;
}
break;
}
}
}
void loadLevel(int level, Pacman* pacman, Bean beans[], Enemy enemies[], Prop props[]) {
// 复制地图
for (int y = 0; y < MAP_HEIGHT; y++) {
for (int x = 0; x < MAP_WIDTH; x++) {
map[y][x] = levels[level].map[y][x];
}
}
// 初始化游戏元素
initGame(pacman, beans, levels[level].beanCount, enemies, levels[level].enemyCount, props, levels[level].propCount);
}
void applyPropEffect(Pacman* pacman, Enemy enemies[], int enemyCount, int propType) {
switch (propType) {
case 0: // 无敌
pacman->invincible = 1;
pacman->invincibleTime = 300; // 无敌时间
break;
case 1: // 减速
for (int i = 0; i < enemyCount; i++) {
enemies[i].speed = max(1, enemies[i].speed - 1); // 至少保留1的速度
enemies[i].scaredTimer = 200; // 被吓到的时间
}
break;
case 2: // 加分
pacman->score += 50; // 额外加分
break;
}
}
void updateProps(Prop props[], int propCount) {
for (int i = 0; i < propCount; i++) {
if (!props[i].active && rand() % 1000 < 5) { // 5‰的概率重新生成道具
int x, y;
do {
x = rand() % MAP_WIDTH;
y = rand() % MAP_HEIGHT;
} while (map[y][x] == 1);
props[i].x = x * 30 + 15;
props[i].y = y * 30 + 15;
props[i].type = rand() % 3; // 随机道具类型
props[i].active = 1;
props[i].duration = 500; // 道具持续时间
}
}
}我vs2022运行报错,你帮我看看修改一下