const的用法lizi

Const 最早想法是用于取代预处理器#define 这个宏,从而形成常量的概念。针对常量const对象,const指针及指向const的指针,函数const类型参数,const 函数返回类型, const类成员,及const成员函数,及对const最后理解的一些总结来描述 const。
① const对象和const类型的对象
对于这两个概念的描述如下
1. int const Object; //Object是一个const量是不可以被修改 Object = 2;Error
2. const int Object; //Object是 const int型他所存放的内容不可以被修改
对于1,2这两种const用于对象,表述虽然不同但是效果是一样的。因为对象本身存放着内容对对象的改变就是对于对象内容的改变,同样改变后者也是在改变前者。所以语义上一样的。
② const指针 和 指向const的指针 及两者结合
对于三个概念描述如下
1. int* const p; //指针p是const不能被修改 例如p++; //修改p本身会Error
//修改p指向内容 *p = 2; //OK
2. const int* p; //p是指向一个整形常量的指针指向的内容不可以改变 p++;//OK
// *p = 2; //Error
3. const int* const p; //指针p本身是不能被修改并且p所有有效的内容也不能被
//修改 *p = 2; Error 和 p++; Error
③ const 参数修饰 和 参数返回类型的const修饰
1.const 参数修饰
此时函数参数修饰 const的具体用法 ① ②中用法是一样的
例如 void Fun( const int I ) { I++;} //Error不能修改常量I
2.const修饰函数返回类型用法也是类似于 ①②中,仅仅修饰的对象变化变成一个返回对象
例如:const int Fun() { static int I; return I;}
int Res = (Fun())++ //Error不能修改常量返回对象
④ const类成员 和 const 成员函数
1. const成员
类const 成员在构造期间会允许被初始化并且在以后不能被改变。我们就可以知道类const成员和一般const 变量是有所不同的,类const成员是对应于每个对象而言才有意义。因为他在构造期被初始化,只有当类实例化后才会进行构造。所以类const成员可以这 样描述: 在类的每一次实例化时被初始化,在这个对象的生存周期中不可改变。
2. const 成员函数
描述: void Class::MemberFun() const {}; //此时这个const修饰的this所有类成员变量都不允许在这个函数体作用后被修改。这在设计上会带来一些好处,能防止你意外的处理带来的问题。
总结:
<1> const 常量 一般编译器不会分配空间只是维护一张表。而当extern 外部引用这个常量或者“&”对这个常量取地址时,编译器才会为其分配地址。Const本身的机制比较复杂。
<2> const 记忆法则 const修饰后面一个最近的名称。我曾初学的时候被const 修饰搞的糊里糊涂,后来慢慢的总结我觉得这样理解最容易的。
例子: const int I; 此时const仅仅修饰int 表明 I不是一个常量但是I的内容是常量。因为c/c++表达 对I的改变就是对I内容的改变所以 I也类似一个const。大家不妨可以用指针const修饰试试理解会有帮助的我想。
<3> 对于所有非const 类型可以无条件转化为 const类型,但是后者不能自动转化为前者除非显式的强制转化去掉const性。这样做是有意义的,因为const类型是非const的一个子集是一种 特殊,由普遍转化为特殊是合理的,就象模板特化,继承的向上映射都是有意义的。
<4> 记住所有const修饰的内容并不是永远不可改变,如果人为的强制转化编译器是不会提醒的。因为它没有义务这么做,所以我们对其转化时要小心。
<5> 在const类成员函数处理时,我们引入了mutable修饰类成员变量,经过其修饰的成员变量可以在const类成员函数中被修改,编译器是允许的。而其他未被mutable修饰的成员还是按照const规则不能在const成员函数中被改变。 
按照这个写法,player在碰到star后并没有触发star的粒子特效,帮我修改仅展示修改部分代码// 粒子系统头文件 (ParticleSystem.h) #pragma once #include <graphics.h> #include <vector> #include <cmath> #include <cstdlib> #include <ctime> #include <algorithm> // 添加以下宏定义(方法1或方法2) #ifndef GetAValue #define GetAValue(rgb) ((rgb >> 24) & 0xFF) // 从COLORREF获取Alpha值 #endif #ifndef RGBA #define RGBA(r,g,b,a) ((COLORREF)((((a) & 0xff) << 24) | \ (((r) & 0xff) << 16) | \ (((g) & 0xff) << 8) | \ ((b) & 0xff))) #endif // 粒子结构体 struct Particle { float x, y; // 位置 float vx, vy; // 速度 float size; // 大小 float life; // 剩余生命周期 (0-1) COLORREF color; // 颜色 float rotation; // 旋转角度 float rotationSpeed; // 旋转速度 }; // 粒子系统类 class StarParticleSystem { private: std::vector<Particle> particles; IMAGE particleImg; // 粒子图像 bool initialized = false; public: StarParticleSystem() { // 初始化随机种子 srand(static_cast<unsigned>(time(nullptr))); } // 初始化粒子图像 void initialize() { if (initialized) return; // 创建粒子图像:圆形渐变 particleImg.Resize(32, 32); SetWorkingImage(&particleImg); SetWorkingImage(&particleImg); cleardevice(); // 创建渐变圆形 for (int r = 15; r >= 0; r--) { int alpha = static_cast<int>(255 * (1.0f - r / 15.0f)); setfillcolor(RGBA(255, 255, 200, alpha)); // 使用RGBA宏 solidcircle(16, 16, r); } SetWorkingImage(NULL); initialized = true; } // 在星星位置创建爆炸效果 void createStarExplosion(float centerX, float centerY, int count = 100) { initialize(); // 确保已初始化 for (int i = 0; i < count; i++) { Particle p; p.x = centerX; p.y = centerY; // 随机方向 (向外扩散) float angle = (rand() % 360) * 3.14159f / 180.0f; float speed = 1.0f + (rand() % 10) / 5.0f; p.vx = cos(angle) * speed; p.vy = sin(angle) * speed; // 随机大小 (5-20像素) p.size = 5.0f + (rand() % 15); // 随机生命周期 (0.5-1.5秒) p.life = 0.5f + (rand() % 100) / 100.0f; // 随机颜色 (黄色到金色) int r = 255; int g = 200 + (rand() % 55); int b = 50 + (rand() % 100); p.color = RGB(r, g, b); // 旋转效果 p.rotation = rand() % 360; p.rotationSpeed = -5.0f + (rand() % 10); particles.push_back(p); } // 添加几个大型中心粒子 for (int i = 0; i < 5; i++) { Particle p; p.x = centerX; p.y = centerY; p.vx = (rand() % 10 - 5) / 5.0f; p.vy = (rand() % 10 - 5) / 5.0f; p.size = 20.0f + (rand() % 15); p.life = 1.0f + (rand() % 50) / 100.0f; p.color = RGB(255, 255, 200); p.rotation = rand() % 360; p.rotationSpeed = -5.0f + (rand() % 10); particles.push_back(p); } } // 更新所有粒子 void update() { for (auto it = particles.begin(); it != particles.end(); ) { // 更新位置 it->x += it->vx; it->y += it->vy; // 添加阻力效果 it->vx *= 0.98f; it->vy *= 0.98f; // 添加轻微重力 it->vy += 0.05f; // 减少生命周期 it->life -= 0.02f; // 更新旋转 it->rotation += it->rotationSpeed; // 移除死亡的粒子 if (it->life <= 0) { it = particles.erase(it); } else { ++it; } } } // 绘制所有粒子 void draw() { for (auto& p : particles) { // 计算透明度 int alpha = static_cast<int>(255 * p.life); // 计算绘制位置 float drawX = p.x - p.size / 2; float drawY = p.y - p.size / 2; // 使用旋转和透明方式绘制粒子 putimage_rotate_alpha(drawX, drawY, &particleImg, alpha, p.size, p.size, p.rotation); } } // 清除所有粒子 void clear() { particles.clear(); } // 检查是否有活跃粒子 bool hasActiveParticles() const { return !particles.empty(); } private: // 辅助函数:带旋转和透明度的图像绘制 void putimage_rotate_alpha(float x, float y, IMAGE* img, int alpha, int width, int height, float rotation) { // 创建临时图像 IMAGE tempImg; tempImg.Resize(width, height); SetWorkingImage(&tempImg); cleardevice(); // 旋转并绘制到临时图像 DWORD* dst = GetImageBuffer(&tempImg); DWORD* src = GetImageBuffer(img); float centerX = width / 2.0f; float centerY = height / 2.0f; float sinRot = sin(rotation * 3.14159f / 180.0f); float cosRot = cos(rotation * 3.14159f / 180.0f); for (int dy = 0; dy < height; dy++) { for (int dx = 0; dx < width; dx++) { // 计算旋转后的位置 float srcX = centerX + (dx - centerX) * cosRot - (dy - centerY) * sinRot; float srcY = centerY + (dx - centerX) * sinRot + (dy - centerY) * cosRot; if (srcX >= 0 && srcX < img->getwidth() && srcY >= 0 && srcY < img->getheight()) { int srcIdx = static_cast<int>(srcY) * img->getwidth() + static_cast<int>(srcX); DWORD color = src[srcIdx]; // 应用透明度 BYTE a = (BYTE)((GetAValue(color) * alpha) / 255); // 使用GetAValue宏 color = (color & 0x00FFFFFF) | (a << 24); dst[dy * width + dx] = color; } } } SetWorkingImage(NULL); // 绘制临时图像到屏幕 HDC dstDC = GetImageHDC(NULL); HDC srcDC = GetImageHDC(&tempImg); BLENDFUNCTION bf = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; AlphaBlend( dstDC, static_cast<int>(x), static_cast<int>(y), width, height, srcDC, 0, 0, width, height, bf ); } }; // 全局粒子系统实例 extern StarParticleSystem starParticles;#pragma once #include <windows.h> class Timer // 改进的延时 { private: LARGE_INTEGER clock; LONGLONG lastClock; int frequency; public: Timer() { QueryPerformanceFrequency(&clock); frequency = (int)clock.QuadPart / 1000; lastClock = 0; } void Sleep(int ms) { unsigned int c = ms * frequency; if (lastClock == 0) { QueryPerformanceCounter(&clock); lastClock = clock.QuadPart; } lastClock += c; QueryPerformanceCounter(&clock); if (clock.QuadPart > lastClock) lastClock = clock.QuadPart; else { do { ::Sleep(1); QueryPerformanceCounter(&clock); } while (clock.QuadPart < lastClock); } } };#include<graphics.h> #include<conio.h> #include<stdio.h> #include <time.h> #include "Timer.h" #include <atomic> #include <thread> #include <windows.h> #include <mmsystem.h> #include <vector> #include <string> #include<cmath> #pragma comment( lib, "MSIMG32.LIB") #pragma comment(lib, "winmm.lib") #include "lizi.h" using namespace std; #define WIDTH 1080 #define HEIGHT 600 StarParticleSystem starParticles; atomic<bool> stopPlayback(false); thread* mp3Thread = nullptr; Timer timer; clock_t gameStartTime = 0; 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); } void stopBackgroundMusic() { if (!stopPlayback.load()) { stopPlayback.store(true); mciSendStringA("close mp3", 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, left_x, top_y; void initialize(int width = 400, int height = 80) { loadimage(&im_land, _T("land1.png"), width, height); land_height = im_land.getheight(); land_width = im_land.getwidth(); top_y = HEIGHT / 2; } void draw(float px, float py) { transparentimage3(NULL, x - land_width / 2 - px, top_y - py - 10, &im_land); ///调试 setlinecolor(GREEN); rectangle(x - land_width / 2 - px, top_y - py - 10, x + land_width / 2 - px, top_y - py + land_height); } }; class Key { public: IMAGE im_key; float x, y; float width, height; bool active; void initialize() { loadimage(&im_key, _T("money.png"), 35, 35); 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_y; // 检查是否在地面上方且垂直距离接近 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 victoryImg;; IMAGE gameOverImg; vector<Land> land; vector<Enemy> enemies; vector<Key> moneys; float panX, panY; float panWidth, panHeight; 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); } // 绘制星星(终点) Land& lastLand = land[land.size() - 1]; float starX = lastLand.x - im_star.getwidth() / 2 - px; float starY = lastLand.top_y - im_star.getheight()-30 - py; transparentimage3(NULL, starX, starY, &im_star); // 绘制底部的盘子(放在星星正下方) float panX = lastLand.x - panWidth / 2 - px; float panY = lastLand.top_y + 600 - py; // 在星星下方500像素处 transparentimage3(NULL, panX, panY, &im_pan); } void initialize() { loadimage(&im_bk, _T("bk.jpg"), 1080, 800); // 依次导入各张背景图片 loadimage(&im_star, _T("star.png"), 40, 40); loadimage(&im_pan, _T("pan.png"), 600, 100); // 加载盘子图片 loadimage(&victoryImg, _T("chip.png"), 300, 300); // 加载胜利结算图片 loadimage(&gameOverImg, _T("gameover.png"), WIDTH, HEIGHT); // 加载游戏结束图片 // 初始化盘子 panWidth = im_pan.getwidth(); panHeight = im_pan.getheight(); land.clear(); // 有序排列地面 - 阶梯式,确保不重叠 Land l1; l1.initialize(400, 80); // 宽度400,高度80 l1.x = 200; l1.top_y = HEIGHT - 100; land.push_back(l1); Land l2; l2.initialize(300, 60); l2.x = 700; // 从l1的右侧开始 (200 + 400/2 + 300/2 + 间隙) l2.top_y = HEIGHT - 200; land.push_back(l2); Land l3; l3.initialize(350, 70); l3.x = 1100; l3.top_y = HEIGHT - 150; land.push_back(l3); Land l4; l4.initialize(300, 60); l4.x = 1500; l4.top_y = HEIGHT - 250; land.push_back(l4); Land l5; l5.initialize(400, 80); l5.x = 1900; l5.top_y = HEIGHT - 100; land.push_back(l5); // 确定玩家初始位置(中心点) float playerCenterX = land[0].x; // 玩家初始位置中心 float safeDistance = 200.0f; // 安全距离 enemies.clear(); for (int i = 0; i < 3; ++i) { Enemy enemy; enemy.initialize(); // 尝试找到安全位置 int attempts = 0; bool positionSafe = false; int idx = 0; while (!positionSafe && attempts < 20) { idx = rand() % land.size(); enemy.x = land[idx].x; // 检查是否在安全距离外 float distance = fabs(enemy.x - playerCenterX); positionSafe = (distance > safeDistance); attempts++; } enemy.y = land[idx].top_y - 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_y - 50; moneys.push_back(money); } } void showGameOver() { cleardevice(); transparentimage3(NULL, 0, 0, &gameOverImg); FlushBatchDraw(); Sleep(3000); // 显示3秒 } void showVictoryScreen(int score, double timeTaken) { cleardevice(); // 绘制胜利结算图片 IMAGE ziImg; loadimage(&ziImg, _T("zi.png"), 600, 200); // 假设zi图片大小为200x100 int chipX = (WIDTH - victoryImg.getwidth()) / 2; int chipY = HEIGHT / 4; transparentimage3(NULL, chipX, chipY, &victoryImg); int ziX = chipX + (victoryImg.getwidth() - ziImg.getwidth()) / 2; int ziY = chipY + (victoryImg.getheight() - ziImg.getheight()) / 2 - 180; // 向上偏移20像素 transparentimage3(NULL, ziX, ziY, &ziImg); // 在图片下方显示分数 TCHAR buffer[100]; wsprintf(buffer, _T("得分: %d"), score); setbkmode(TRANSPARENT); settextcolor(WHITE); settextstyle(36, 0, _T("宋体")); outtextxy((WIDTH - textwidth(buffer)) / 2, chipY + victoryImg.getheight() + 20, buffer); // 修复时间显示问题:使用sprintf_s转换浮点数 char timeBuffer[50]; sprintf_s(timeBuffer, "通关时间: %.2f 秒", timeTaken); // 将char数组转换为TCHAR数组 TCHAR tcharTime[50]; #ifdef UNICODE MultiByteToWideChar(CP_ACP, 0, timeBuffer, -1, tcharTime, 50); #else strcpy_s(tcharTime, timeBuffer); #endif outtextxy((WIDTH - textwidth(tcharTime)) / 2, chipY + victoryImg.getheight() + 90, tcharTime); FlushBatchDraw(); Sleep(5000); // 显示5秒 } 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; float fallingG; // 自由落体时的重力加速度 int score = 0; int lives = 3; bool isWin = false; // 是否触碰到星星 bool isFalling = false; // 是否处于自由落体状态 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(); if (!scene.land.empty()) { x_left = scene.land[0].x - width / 2; y_bottom = scene.land[0].top_y; } else { x_left = WIDTH / 2; y_bottom = HEIGHT - 100; } vx = 15; // 水平速度 vy = 0; g = 5; fallingG = 0.4; // 自由落体时的重力加速度(更慢) } 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) { if (isFalling) return; // 自由落体时不能移动 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 (isFalling) return; // 自由落体时不能移动 if (playerStatus == stillleft || playerStatus == walkleft) { im_now = im_stillleft; } else if (playerStatus == stillright || playerStatus == walkright) { im_now = im_stillright; } } void beginjump() { if (isFalling) return; // 自由落体时不能移动 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 = -50; } } bool isOnLand(Land& land, float ySpeed) { float playerRight = x_left + width; float playerBottom = y_bottom; float playerTop = y_bottom - height; // 添加playerTop定义 float landLeft = land.x - land.land_width / 2; float landRight = land.x + land.land_width / 2; float landTop = land.top_y; // 检查是否在地面上方且垂直距离接近 bool verticalOverlap = (playerBottom >= landTop - 10 && playerTop <= landTop + 10); bool horizontalOverlap = (x_left < landRight && playerRight > landLeft); if (verticalOverlap && horizontalOverlap) { 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) { // 应用重力 float currentG = isFalling ? fallingG : g; vy += currentG; 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 = -15; // 玩家弹起 score += 100; // 播放敌人死亡音效 PlaySoundA("music/monstermusic.wav", NULL, SND_FILENAME | SND_ASYNC | SND_NODEFAULT); return true; } return false; } // 检查是否碰到星星 bool checkStarCollision() { if (isWin || isFalling) return false; // 星星的位置在最后一块地面上方 Land& lastLand = scene.land.back(); // 修正星星位置计算:使用中心点坐标 float starX = lastLand.x - scene.im_star.getwidth() / 2; float starY = lastLand.top_y - scene.im_star.getheight() - 30; float starWidth = scene.im_star.getwidth(); float starHeight = scene.im_star.getheight(); // 玩家位置 float playerLeft = x_left; float playerRight = x_left + width; float playerTop = y_bottom - height; float playerBottom = y_bottom; // 检测碰撞 if (playerRight > starX && playerLeft < starX + starWidth && playerBottom > starY && playerTop < starY + starHeight) { isWin = true; isFalling = true; vy = 0; // 重置垂直速度 return true; } return false; } // 检查是否碰到盘子 bool checkPanCollision() { if (!isFalling) return false; Land& lastLand = scene.land.back(); // 盘子位置在星星正下方 float panX = lastLand.x - scene.panWidth / 2; float panY = lastLand.top_y + 600; // 在星星下方600像素处 // 玩家位置 float playerLeft = x_left; float playerRight = x_left + width; float playerBottom = y_bottom; // 检测碰撞(扩大碰撞范围) if (playerBottom >= panY - 30 && playerBottom <= panY + 30 && playerRight > panX && playerLeft < panX + scene.panWidth) { // 碰到盘子,停止自由落体 isFalling = false; // 调整玩家位置到盘子上方 y_bottom = panY; PlaySoundA("music/victory.wav", NULL, SND_FILENAME | SND_ASYNC | SND_NODEFAULT); return true; } return false; } }; Player player; bool gameOver = false; bool gameWin = false; void startup() { srand(time(0)); scene.initialize(); player.initialize(); initgraph(WIDTH, HEIGHT, SHOWCONSOLE); BeginBatchDraw(); gameStartTime = clock(); // 记录游戏开始时间 } 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; // 检查是否碰到星星 if (player.checkStarCollision()) { // 玩家碰到星星后,调整位置确保在屏幕中央 player.x_left = scene.land.back().x - player.width/2; } // 如果是自由落体状态 if (player.isFalling) { // 应用自由落体物理 player.vy += player.fallingG; player.y_bottom += player.vy; // 检查是否碰到盘子 if (player.checkPanCollision()) { gameWin = true; // 停止背景音乐 stopBackgroundMusic(); PlaySoundA("music/victory.wav", NULL, SND_FILENAME | SND_ASYNC | SND_NODEFAULT); return; } } else { 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) { // 停止背景音乐 stopBackgroundMusic(); // 播放游戏结束音效 PlaySoundA("music/defeat.wav", NULL, SND_FILENAME | SND_ASYNC | SND_NODEFAULT); gameOver = true; scene.showGameOver(); return; } // 显示剩余生命值 scene.showLifeInfo(player.lives); // 重置玩家位置 if (!scene.land.empty()) { player.x_left = scene.land[0].x - player.width / 2; player.y_bottom = scene.land[0].top_y; } else { player.x_left = WIDTH / 2; player.y_bottom = HEIGHT - 100; } 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) { // 停止背景音乐 stopBackgroundMusic(); // 播放游戏结束音效 PlaySoundA("music/defeat.wav", NULL, SND_FILENAME | SND_ASYNC | SND_NODEFAULT); gameOver = true; scene.showGameOver(); return; } // 显示剩余生命值 scene.showLifeInfo(player.lives); // 重置玩家位置 if (!scene.land.empty()) { player.x_left = scene.land[0].x - player.width / 2; player.y_bottom = scene.land[0].top_y; } else { player.x_left = WIDTH / 2; player.y_bottom = HEIGHT - 100; } player.vy = 0; } } }; int main() { startup(); mp3Thread = new std::thread(playMP3, "music/bkmusic.mp3"); while (true) { show(); withinput(); withoutinput(); if (gameOver) { // 这里不再需要播放defeat音效,因为已经在withoutinput中播放过了 break; } if (gameWin) { double timeTaken = (double)(clock() - gameStartTime) / CLOCKS_PER_SEC; // 显示胜利结算画面 scene.showVictoryScreen(player.score,timeTaken); break; } } // 游戏结束后关闭图形窗口 _getch(); closegraph(); if (mp3Thread && mp3Thread->joinable()) { stopPlayback.store(true); mp3Thread->join(); } delete mp3Thread; return 0; }
最新发布
07-03
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值