基于SDL的Chrome恐龙游戏:死亡后如何重置游戏数值
问题分析
当前代码的核心问题是:游戏结束后仅通过isGameOver暂停了游戏循环,但没有重置玩家状态、清理场景内的障碍物,也没有重置游戏核心变量。按下空格后只是恢复了循环,但玩家仍处于死亡状态,旧的障碍物还在场景中,导致游戏无法正常重启。
解决方案
我们需要新增一个专门的游戏重置函数,在玩家死亡后按下空格时,彻底重置所有必要的游戏状态。以下是具体修改步骤:
1. 在GameScene.h中添加重置函数声明
在GameScene类的private部分添加:
void resetGame();
2. 实现resetGame()函数(GameScene.cpp)
这个函数负责重置所有游戏初始状态:
void GameScene::resetGame() { // 1. 重置玩家状态:恢复存活、回到初始位置、重置onFloor状态 player->setIsAlive(true); // 假设Player类有setIsAlive方法,若没有可直接修改成员变量 player->setPosition(100, 300); // 设为玩家初始位置,可根据需求调整 player->setOnFloor(false); // 2. 清除所有已生成的障碍物 for (Obstacle* obs : spawnedObstacle) { // 从Scene的objects列表中移除对象(需确保Scene有removeGameObject方法,无则自行实现遍历删除) this->removeGameObject(obs); delete obs; } spawnedObstacle.clear(); // 3. 清除所有已生成的飞鸟 for (FlyingObstacle* bird : spawnedBird) { this->removeGameObject(bird); delete bird; } spawnedBird.clear(); // 4. 重置分数(保留最高分) if (points > highscore) { highscore = points; } points = 0; // 5. 重置生成计时器 currentSpawnTimer = 300; spawnTime = rand() % 300; // 6. 重新生成初始的障碍物和飞鸟(和start()逻辑保持一致) for (int i = 0; i < 1; i++) { obstacleSpawn(); } for (int i = 0; i < 3; i++) { birdSpawn(); } // 7. 标记游戏可运行 isGameOver = false; }
3. 修改update()中的空格键逻辑
将原来仅设置isGameOver = false的逻辑,改为调用resetGame(),同时防止按键重复触发:
void GameScene::update() { if (isGameOver == true) { if (app.keyboard[SDL_SCANCODE_SPACE]) { resetGame(); // 替换原来的isGameOver = false app.keyboard[SDL_SCANCODE_SPACE] = false; // 防止按住空格重复触发重置 } } // 原有的游戏运行逻辑保持不变 if (isGameOver == false) { Scene::update(); floorCollision(); obstacleCollision(); birdCollision(); if (currentSpawnTimer > 0) currentSpawnTimer--; if (currentSpawnTimer <= 0) { for (int i = 0; i < 1; i++) { obstacleSpawn(); } for (int i = 0; i < 3; i++) { birdSpawn(); } currentSpawnTimer = spawnTime; } if (player->getOnFloor() == false) { player->setY(player->getY() + 7); } } }
4. 修正分数计算的bug
当前floorCollision()中highscore跟着points一起递增,不符合逻辑,只保留当前分数递增:
void GameScene::floorCollision() { for (int i = 0; i < objects.size(); i++) { Floor* floor = dynamic_cast<Floor*>(objects[i]); if (floor != NULL) { int collision = checkCollision( player->getX(), player->getY(), player->getWidth(), player->getHeight(), floor->getX(), floor->getY(), floor->getWidth(), floor->getHeight() ); if (collision == 1) { player->setOnFloor(true); if (player->getIsAlive() == true) { points++; // 仅增加当前游戏分数 } break; } } } }
5. 修正draw()中的文本重叠问题
调整新高分和旧高分的文本位置,避免重叠:
void GameScene::draw() { Scene::draw(); drawText(110, 20, 255, 255, 255, TEXT_CENTER, "POINTS: %03d", points); if (player->getIsAlive() == true && isGameOver == true) { drawText(900, 20, 255, 255, 255, TEXT_CENTER, "PRESS SPACE TO START MOVING"); } if (player->getIsAlive() == false) { if (isGameOver == false) { drawText(SCREEN_WIDTH / 2, 200, 255, 255, 255, TEXT_CENTER, "YOU LOSE! PRESS SPACE TO RESTART"); } if (isGameOver == true) { drawText(SCREEN_WIDTH / 2, 180, 255, 255, 255, TEXT_CENTER, "HIGHSCORE: %03d", highscore); if (points > highscore) { drawText(SCREEN_WIDTH / 2, 220, 255, 255, 255, TEXT_CENTER, "NEW HIGHSCORE: %03d", points); } } } }
额外注意事项
- 若
Scene类没有removeGameObject()方法,需自行实现:遍历objects列表找到对应对象指针并删除。 - 玩家死亡时的逻辑可补充:比如暂停障碍物移动(如果你的障碍物有移动逻辑),确保死亡后场景完全暂停。
内容的提问来源于stack exchange,提问作者BlasterMaster
相关产品推荐
相关产品推荐

