这样写的代码还是只有bkmusic和jumpmusic的声音,未实现game over时播放一次音频defeat;敌人死亡时播放一次音频monstermusic;lives生命值减少时播放一次音频lostblood;与moneys发生碰撞时播放音频moneymusic,以下是我原有代码,请根据要求修改完成后展示完整代码#include<graphics.h>
#include<conio.h>
#include<stdio.h>
#include <time.h>
#pragma comment( lib, "MSIMG32.LIB")
#include <atomic>
#include <thread>
#include <windows.h>
#include <mmsystem.h>
#include <vector>
#include <string>
#include <conio.h>
#pragma comment(lib, "winmm.lib")
using namespace std;
#define WIDTH 1080
#define HEIGHT 600
atomic<bool> stopPlayback(false);
thread* mp3Thread = nullptr;
void playMP3(const char* filename) {
if (stopPlayback.load()) return;
char cmd[256] = { 0 };
sprintf_s(cmd, "open \"%s\" alias mp3", filename);
mciSendStringA(cmd, NULL, 0, NULL);
sprintf_s(cmd, "play mp3 repeat");
mciSendStringA(cmd, NULL, 0, NULL);
while (!stopPlayback.load()) {
if (_kbhit()) {
char key = _getch();
if (key == 'w' || GetAsyncKeyState(VK_UP)) {
PlaySoundA("music/jumpmusic.wav", NULL, SND_FILENAME | SND_ASYNC | SND_NODEFAULT);
}
}
this_thread::sleep_for(chrono::milliseconds(100));
}
sprintf_s(cmd, "close mp3");
mciSendStringA(cmd, NULL, 0, NULL);
}
enum PlayerStatus {
stillleft, stillright, walkleft, walkright,
jumpleft, jumpright, die
};
void transparentimage3(IMAGE* dstimg, int x, int y, IMAGE* srcimg) {
HDC dstDC = GetImageHDC(dstimg);
HDC srcDC = GetImageHDC(srcimg);
int w = srcimg->getwidth();
int h = srcimg->getheight();
BLENDFUNCTION bf = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
AlphaBlend(dstDC, x, y, w, h, srcDC, 0, 0, w, h, bf);
}
class Land {
public:
IMAGE im_land;
float land_width, land_height;
float x, y, top;
void initialize() {
loadimage(&im_land, _T("shortland.png"), 1000, 100);
land_height = im_land.getheight();
land_width = im_land.getwidth();
x = WIDTH / 2;
y = x + land_width;
top = HEIGHT / 2;
}
void draw(float px, float py) {
transparentimage3(NULL, x - px, top - py, &im_land);
}
};
class Key {
public:
IMAGE im_key;
float x, y;
float width, height;
bool active;
void initialize() {
loadimage(&im_key, _T("money.png"), 40, 40);
width = im_key.getwidth();
height = im_key.getheight();
active = true;
}
void draw(float px, float py) {
if (active)
transparentimage3(NULL, x - px, y - py, &im_key);
}
bool checkCollision(float playerX, float playerY, float playerWidth, float playerHeight) {
if (!active) return false;
float playerRight = playerX + playerWidth;
float playerBottom = playerY + playerHeight;
float keyRight = x + width;
float keyBottom = y + height;
return (playerX < keyRight &&
playerRight > x &&
playerY < keyBottom &&
playerBottom > y);
}
};
class Enemy {
public:
IMAGE im_enemy;
float e_height, e_width;
float vx, vy;
float x, y;
float x_min, x_max;
float g;
bool isAlive;
bool isOnGround;
void initialize() {
loadimage(&im_enemy, _T("monster.png"), 40, 40);
e_height = im_enemy.getheight();
e_width = im_enemy.getwidth();
vy = 0;
g = 3; // 减小重力
isOnGround = false;
isAlive = true;
}
void draw(float px, float py) {
if (isAlive) {
transparentimage3(NULL, x - e_width / 2 - px, y - e_height / 2 - py, &im_enemy);
}
}
void update(vector<Land>& lands) {
if (!isAlive) return;
// 水平移动
x += vx;
if (x > x_max || x < x_min) {
vx = -vx;
}
// 应用重力
vy += g;
y += vy;
// 检测与地面的碰撞
isOnGround = false;
for (auto& land : lands) {
float enemyBottom = y + e_height / 2;
float enemyLeft = x - e_width / 2;
float enemyRight = x + e_width / 2;
float landLeft = land.x - land.land_width / 2;
float landRight = land.x + land.land_width / 2;
float landTop = land.top;
// 检查是否在地面上方且垂直距离接近
if (enemyBottom >= landTop - 5 && enemyBottom <= landTop + 10 &&
enemyRight > landLeft && enemyLeft < landRight) {
y = landTop - e_height / 2; // 调整敌人位置到地面
vy = 0; // 重置垂直速度
isOnGround = true;
break;
}
}
}
};
class Scene {
public:
IMAGE im_bk;
IMAGE im_star;
IMAGE im_pan;
IMAGE gameOverImg;
vector<Land> land;
vector<Enemy> enemies;
vector<Key> moneys;
void draw(float px, float py) {
// 修改背景绘制方式,使其随玩家移动
// 背景移动速度为玩家移动速度的一半
float bgOffsetX = px / 4; // 调整这个值可以改变背景移动速度
float bgOffsetY = py / 4; // 调整这个值可以改变背景移动速度
// 计算背景位置,确保不会超出边界
int bgX = -bgOffsetX;
int bgY = -bgOffsetY;
// 确保背景不会显示空白区域
if (bgX > 0) bgX = 0;
if (bgY > 0) bgY = 0;
if (bgX < WIDTH - im_bk.getwidth()) bgX = WIDTH - im_bk.getwidth();
if (bgY < HEIGHT - im_bk.getheight()) bgY = HEIGHT - im_bk.getheight();
putimage(bgX, bgY, &im_bk);
for (int i = 0; i < land.size(); i++) {
land[i].draw(px, py);
}
for (int i = 0; i < enemies.size(); i++) {
enemies[i].draw(px, py);
}
for (int i = 0; i < moneys.size(); i++) {
moneys[i].draw(px, py);
}
transparentimage3(NULL, land[land.size() - 1].x + im_star.getwidth() - px, land[land.size() - 1].top - im_star.getheight() - py, &im_star);
}
void initialize() {
loadimage(&im_bk, _T("bk.jpg"), 1080, 800); // 依次导入各张背景图片
loadimage(&im_star, _T("star.png"), 20, 20);
loadimage(&gameOverImg, _T("gameover.png"), WIDTH, HEIGHT); // 加载游戏结束图片
land.clear();
// 有序排列地面 - 阶梯式
Land l1;
l1.initialize();
l1.x = 200;
l1.top = HEIGHT - 100;
land.push_back(l1);
Land l2;
l2.initialize();
l2.x = 500;
l2.top = HEIGHT - 200;
land.push_back(l2);
Land l3;
l3.initialize();
l3.x = 800;
l3.top = HEIGHT - 150;
land.push_back(l3);
Land l4;
l4.initialize();
l4.x = 1100;
l4.top = HEIGHT - 250;
land.push_back(l4);
Land l5;
l5.initialize();
l5.x = 1400;
l5.top = HEIGHT - 100;
land.push_back(l5);
enemies.clear();
for (int i = 0; i < 3; ++i) {
Enemy enemy;
enemy.initialize();
int idx = rand() % land.size(); // 确保敌人生成在地面上
enemy.x = land[idx].x;
enemy.y = land[idx].top - enemy.e_height / 2;
enemy.x_min = land[idx].x - 100;
enemy.x_max = land[idx].x + 100;
enemy.vx = 2 + rand() % 3;
enemies.push_back(enemy);
}
moneys.clear();
for (int i = 0; i < 10; ++i) {
Key money;
money.initialize();
int idx = rand() % land.size();
money.x = land[idx].x + rand() % ((int)land[idx].land_width - 40);
money.y = land[idx].top - 50;
moneys.push_back(money);
}
}
void showGameOver() {
cleardevice();
transparentimage3(NULL, 0, 0, &gameOverImg);
FlushBatchDraw();
Sleep(3000); // 显示3秒
}
void showLifeInfo(int lives) {
cleardevice();
setbkmode(TRANSPARENT);
settextcolor(WHITE);
settextstyle(50, 0, _T("宋体"));
IMAGE im_lives;
loadimage(&im_lives, _T("life.png"), 150, 150);
TCHAR buffer[100];
transparentimage3(NULL, WIDTH / 2 - 100, HEIGHT / 2 - 25, &im_lives);
wsprintf(buffer, _T(" X %d"), lives);
outtextxy(WIDTH / 2 + 90, HEIGHT / 2 + 20, buffer);
FlushBatchDraw();
Sleep(2000); // 显示2秒
}
};
Scene scene;
class Player {
public:
IMAGE im_now;
IMAGE im_stillleft;
IMAGE im_stillright;
IMAGE im_jumpleft;
IMAGE im_jumpright;
IMAGE im_walkright;
IMAGE im_walkleft;
PlayerStatus playerStatus;
float x_left, y_bottom;
float vx, vy;
float width, height;
float g;
int score = 0;
int lives = 3;
void draw() {
transparentimage3(NULL, WIDTH / 2, HEIGHT / 2 - height, &im_now);
}
void initialize() {
loadimage(&im_stillleft, _T("kim_left.png"), 60, 80);
loadimage(&im_stillright, _T("kim_right.png"), 60, 80);
loadimage(&im_jumpleft, _T("kim_jumpleft.png"), 60, 80);
loadimage(&im_jumpright, _T("kim_jumpright.png"), 60, 80);
loadimage(&im_walkright, _T("kim_right.png"), 60, 80);
loadimage(&im_walkleft, _T("kim_left.png"), 60, 80);
playerStatus = stillright;
im_now = im_stillright;
width = im_stillright.getwidth();
height = im_stillright.getheight();
update(WIDTH / 2, HEIGHT / 3);
//// 初始位置放在第一块地面上
x_left = scene.land[0].x;
y_bottom = scene.land[0].top;
vx = 10; // 水平速度
vy = 0;
g = 5;
}
void update(float x, float y) {
x_left = x;
y_bottom = y;
}
void walkRight(Scene& scene) {
x_left += vx;
if (x_left < 0) x_left = 0;
if (isNotOnAllLands(scene.land, vy)) {
im_now = im_jumpright;
playerStatus = jumpright;
return;
}
if (playerStatus == jumpleft || playerStatus == jumpright) {
im_now = im_jumpright;
}
else {
playerStatus = walkright;
im_now = im_walkright;
}
}
void walkLeft(Scene& scene) {
x_left -= vx;
if (x_left < 0) x_left = 0;
if (isNotOnAllLands(scene.land, vy)) {
im_now = im_jumpleft;
playerStatus = jumpleft;
return;
}
if (playerStatus == jumpleft || playerStatus == jumpright) {
im_now = im_jumpleft;
}
else {
playerStatus = walkleft;
im_now = im_walkleft;
}
}
void standstill() {
if (playerStatus == stillleft || playerStatus == walkleft) {
im_now = im_stillleft;
}
else if (playerStatus == stillright || playerStatus == walkright) {
im_now = im_stillright;
}
}
void beginjump() {
if (playerStatus != jumpleft && playerStatus != jumpright) {
if (playerStatus == walkleft || playerStatus == stillleft) {
im_now = im_jumpleft;
playerStatus = jumpleft;
}
else if (playerStatus == walkright || playerStatus == stillright) {
im_now = im_jumpright;
playerStatus = jumpright;
}
vy = -30;
}
}
bool isOnLand(Land& land, float ySpeed) {
float playerRight = x_left + width;
float playerBottom = y_bottom;
float landLeft = land.x - land.land_width / 2;
float landRight = land.x + land.land_width / 2;
float landTop = land.top;
// 检查是否在地面上方且垂直距离接近
bool onGround = (playerBottom >= landTop - 5 && playerBottom <= landTop + 10) &&
(x_left < landRight && playerRight > landLeft);
if (onGround) {
y_bottom = landTop; // 将玩家放在地面上
return true;
}
return false;
}
bool isNotOnAllLands(vector<Land>& lands, float speed) {
for (auto& land : lands) {
if (isOnLand(land, speed)) {
return false;
}
}
return true;
}
void updateKeycode(Scene& scene) {
// 应用重力
vy += g;
y_bottom += vy;
// 检测与地面的碰撞
bool onGround = false;
for (auto& land : scene.land) {
if (isOnLand(land, vy)) {
onGround = true;
vy = 0; // 重置垂直速度
// 落地后恢复行走状态
if (playerStatus == jumpleft) {
playerStatus = stillleft;
}
else if (playerStatus == jumpright) {
playerStatus = stillright;
}
break;
}
}
// 如果不在任何地面上且速度向下,保持跳跃状态
if (!onGround && vy > 0) {
if (playerStatus == stillleft || playerStatus == walkleft) {
playerStatus = jumpleft;
}
else if (playerStatus == stillright || playerStatus == walkright) {
playerStatus = jumpright;
}
}
}
bool stompEnemy(Enemy& enemy) {
if (!enemy.isAlive) return false;
float playerBottom = y_bottom;
float playerLeft = x_left;
float playerRight = x_left + width;
float enemyTop = enemy.y - enemy.e_height / 2;
float enemyLeft = enemy.x - enemy.e_width / 2;
float enemyRight = enemy.x + enemy.e_width / 2;
// 检查玩家是否在敌人上方
if (playerBottom <= enemyTop + 10 &&
playerRight > enemyLeft &&
playerLeft < enemyRight &&
vy > 0) {
enemy.isAlive = false; // 敌人死亡
vy = -20; // 玩家弹起
score += 100;
// 播放敌人死亡音效
PlaySoundA("music/monstermusic.wav", NULL, SND_FILENAME | SND_ASYNC | SND_NODEFAULT);
return true;
}
return false;
}
};
Player player;
bool gameOver = false;
void startup() {
srand(time(0));
scene.initialize();
player.initialize();
initgraph(WIDTH, HEIGHT, SHOWCONSOLE);
BeginBatchDraw();
}
void show() {
if (gameOver) return;
cleardevice();
scene.draw(player.x_left - WIDTH / 2, player.y_bottom - HEIGHT / 2);
player.draw();
TCHAR buffer[100];
wsprintf(buffer, _T("分数: %d | 生命: %d"), player.score, player.lives);
setbkmode(TRANSPARENT);
settextcolor(RED);
settextstyle(20, 0, _T("宋体"));
outtextxy(10, 10, buffer);
FlushBatchDraw();
Sleep(30);
}
void withinput() {
player.standstill();
if (gameOver) return;
player.standstill();
if (_kbhit()) {
if (GetAsyncKeyState(VK_RIGHT) || GetAsyncKeyState('D'))
player.walkRight(scene);
else if (GetAsyncKeyState(VK_LEFT) || GetAsyncKeyState('A'))
player.walkLeft(scene);
if (GetAsyncKeyState(VK_UP) || GetAsyncKeyState('W'))
player.beginjump();
}
}
void withoutinput() {
if (gameOver) return;
player.updateKeycode(scene);
// 更新敌人位置
for (int i = 0; i < scene.enemies.size(); i++) {
scene.enemies[i].update(scene.land);
}
// 检查玩家与敌人碰撞
for (int i = 0; i < scene.enemies.size(); i++) {
if (player.stompEnemy(scene.enemies[i])) {
// 踩踏成功处理
}
else {
// 检查其他碰撞
float playerRight = player.x_left + player.width;
float playerBottom = player.y_bottom;
float enemyLeft = scene.enemies[i].x - scene.enemies[i].e_width / 2;
float enemyRight = scene.enemies[i].x + scene.enemies[i].e_width / 2;
float enemyTop = scene.enemies[i].y - scene.enemies[i].e_height / 2;
float enemyBottom = scene.enemies[i].y + scene.enemies[i].e_height / 2;
if (player.x_left < enemyRight &&
playerRight > enemyLeft &&
player.y_bottom > enemyTop &&
playerBottom < enemyBottom &&
scene.enemies[i].isAlive) {
player.lives--;
// 播放生命值减少音效
PlaySoundA("music/lostblood.wav", NULL, SND_FILENAME | SND_ASYNC | SND_NODEFAULT);
if (player.lives <= 0) {
// 播放游戏结束音效
PlaySoundA("music/defeat2.wav", NULL, SND_FILENAME | SND_ASYNC | SND_NODEFAULT);
gameOver = true;
scene.showGameOver();
return;
}
// 显示剩余生命值
scene.showLifeInfo(player.lives);
// 重置玩家位置
player.x_left = scene.land[0].x;
player.y_bottom = scene.land[0].top;
player.vy = 0;
// 重置敌人
for (auto& enemy : scene.enemies) {
enemy.isAlive = true;
}
return;
}
}
}
// 检查道具碰撞
for (int i = 0; i < scene.moneys.size(); i++) {
if (scene.moneys[i].checkCollision(player.x_left, player.y_bottom, player.width, player.height)) {
player.score += 10;
// 播放收集金钱音效
PlaySoundA("music/moneymusic.wav", NULL, SND_FILENAME | SND_ASYNC | SND_NODEFAULT);
scene.moneys.erase(scene.moneys.begin() + i);
i--;
}
}
// 检查掉落
if (player.y_bottom > HEIGHT * 1.5) {
player.lives--;
// 播放生命值减少音效
PlaySoundA("music/lostblood.wav", NULL, SND_FILENAME | SND_ASYNC | SND_NODEFAULT);
if (player.lives <= 0) {
// 播放游戏结束音效
PlaySoundA("music/defeat.wav", NULL, SND_FILENAME | SND_ASYNC | SND_NODEFAULT);
gameOver = true;
scene.showGameOver();
return;
}
// 显示剩余生命值
scene.showLifeInfo(player.lives);
// 重置玩家位置
player.x_left = scene.land[0].x;
player.y_bottom = scene.land[0].top;
player.vy = 0;
}
}
int main() {
startup();
mp3Thread = new std::thread(playMP3, "music/bkmusic.mp3");
while (true) {
show();
withinput();
withoutinput();
if (gameOver) {
break;
}
}
// 游戏结束后关闭图形窗口
_getch();
closegraph();
if (mp3Thread && mp3Thread->joinable()) {
stopPlayback.store(true);
mp3Thread->join();
}
delete mp3Thread;
return 0;
}