// ============================================================================ // GameOverLayer.cpp - 游戏结束层实现 // ============================================================================ #include "GameOverLayer.h" #include "GameScene.h" #include "Number.h" #include "ResLoader.h" #include "StartScene.h" namespace flappybird { GameOverLayer::GameOverLayer(int score) : score_(score) { // 注意:不要在构造函数中创建子节点 // 因为此时 weak_from_this() 还不能使用 } void GameOverLayer::onEnter() { Node::onEnter(); // 在 onEnter 中初始化,此时 weak_from_this() 可用 auto &app = extra2d::Application::instance(); float screenWidth = static_cast(app.getConfig().width); float screenHeight = static_cast(app.getConfig().height); // 整体居中(x 坐标相对于屏幕中心) setPosition(extra2d::Vec2(screenWidth / 2.0f, screenHeight)); // 显示 "Game Over" 文字(y=120,从顶部开始) auto gameOverFrame = ResLoader::getKeyFrame("text_game_over"); if (gameOverFrame) { auto gameOver = extra2d::Sprite::create(gameOverFrame->getTexture(), gameOverFrame->getRect()); gameOver->setAnchor(extra2d::Vec2(0.5f, 0.0f)); gameOver->setPosition(extra2d::Vec2(0.0f, 120.0f)); // x=0 表示相对于中心点 addChild(gameOver); } // 初始化得分面板 initPanel(score_, screenHeight); // 初始化按钮 initButtons(); // 创建向上移动的动画(从屏幕底部移动到正常位置) auto moveAction = extra2d::makePtr( 1.0f, extra2d::Vec2(0.0f, -screenHeight)); runAction(moveAction); } void GameOverLayer::initPanel(int score, float screenHeight) { // 显示得分板(在屏幕中间) auto panelFrame = ResLoader::getKeyFrame("score_panel"); if (!panelFrame) return; auto panel = extra2d::Sprite::create(panelFrame->getTexture(), panelFrame->getRect()); panel->setAnchor(extra2d::Vec2(0.5f, 0.5f)); panel->setPosition( extra2d::Vec2(0.0f, screenHeight / 2.0f)); // x=0 表示相对于中心点 addChild(panel); // 获取最高分(从存储中读取) static int bestScore = 0; if (score > bestScore) { bestScore = score; } // 显示 "New" 标记(如果破了记录) if (score >= bestScore && score > 0) { auto newFrame = ResLoader::getKeyFrame("new"); if (newFrame) { auto newSprite = extra2d::Sprite::create(newFrame->getTexture(), newFrame->getRect()); newSprite->setAnchor(extra2d::Vec2(0.5f, 0.5f)); // 调整位置使其在面板内部,靠近 BEST 分数 newSprite->setPosition( extra2d::Vec2(30.0f, 25.0f)); // 相对于面板的坐标,在 BEST 右侧 panel->addChild(newSprite); } } // 显示奖牌 auto medalFrame = getMedal(score); if (medalFrame) { auto medal = extra2d::Sprite::create(medalFrame->getTexture(), medalFrame->getRect()); medal->setAnchor(extra2d::Vec2(0.5f, 0.5f)); medal->setPosition(extra2d::Vec2(54.0f, 68.0f)); // 相对于面板的坐标 panel->addChild(medal); } // 显示本局得分 auto scoreNumber = extra2d::makePtr(); scoreNumber->setLittleNumber(score); scoreNumber->setPosition( extra2d::Vec2(80.0f, -15.0f)); // 相对于面板的坐标,右侧对齐 panel->addChild(scoreNumber); // 显示最高分 auto bestNumber = extra2d::makePtr(); bestNumber->setLittleNumber(bestScore); bestNumber->setPosition( extra2d::Vec2(80.0f, 25.0f)); // 相对于面板的坐标,右侧对齐 panel->addChild(bestNumber); } void GameOverLayer::initButtons() { // 创建重新开始按钮(y=360) auto restartFrame = ResLoader::getKeyFrame("button_restart"); if (restartFrame) { auto restartBtn = extra2d::Button::create(); restartBtn->setBackgroundImage(restartFrame->getTexture(), restartFrame->getRect()); restartBtn->setAnchor(extra2d::Vec2(0.5f, 0.5f)); restartBtn->setPosition( extra2d::Vec2(0.0f, 360.0f)); // x=0 表示相对于中心点 restartBtn->setOnClick([]() { ResLoader::playMusic(MusicType::Click); auto &app = extra2d::Application::instance(); app.scenes().replaceScene(extra2d::makePtr(), extra2d::TransitionType::Fade, 0.5f); }); addChild(restartBtn); } // 创建返回主菜单按钮(y=420) auto menuFrame = ResLoader::getKeyFrame("button_menu"); if (menuFrame) { auto menuBtn = extra2d::Button::create(); menuBtn->setBackgroundImage(menuFrame->getTexture(), menuFrame->getRect()); menuBtn->setAnchor(extra2d::Vec2(0.5f, 0.5f)); menuBtn->setPosition(extra2d::Vec2(0.0f, 420.0f)); // x=0 表示相对于中心点 menuBtn->setOnClick([]() { ResLoader::playMusic(MusicType::Click); auto &app = extra2d::Application::instance(); app.scenes().replaceScene(extra2d::makePtr(), extra2d::TransitionType::Fade, 0.5f); }); addChild(menuBtn); } // 创建分享按钮(y=480,在 MENU 按钮下方) auto shareFrame = ResLoader::getKeyFrame("button_share"); if (shareFrame) { auto shareBtn = extra2d::Button::create(); shareBtn->setBackgroundImage(shareFrame->getTexture(), shareFrame->getRect()); shareBtn->setAnchor(extra2d::Vec2(0.5f, 0.5f)); shareBtn->setPosition(extra2d::Vec2(0.0f, 460.0f)); // x=0 表示相对于中心点 shareBtn->setOnClick([]() { ResLoader::playMusic(MusicType::Click); // TODO: 实现分享功能 }); addChild(shareBtn); } } void GameOverLayer::onUpdate(float dt) { Node::onUpdate(dt); // 检测手柄按键 auto &input = extra2d::Application::instance().input(); // A 键重新开始游戏 if (input.isButtonPressed(extra2d::GamepadButton::A)) { ResLoader::playMusic(MusicType::Click); auto &app = extra2d::Application::instance(); app.scenes().replaceScene(extra2d::makePtr(), extra2d::TransitionType::Fade, 0.5f); } // B 键返回主菜单 if (input.isButtonPressed(extra2d::GamepadButton::B)) { ResLoader::playMusic(MusicType::Click); auto &app = extra2d::Application::instance(); app.scenes().replaceScene(extra2d::makePtr(), extra2d::TransitionType::Fade, 0.5f); } } extra2d::Ptr GameOverLayer::getMedal(int score) { if (score < 10) { return nullptr; // 无奖牌 } else if (score < 20) { return ResLoader::getKeyFrame("medals_0"); // 铜牌 } else if (score < 30) { return ResLoader::getKeyFrame("medals_1"); // 银牌 } else if (score < 50) { return ResLoader::getKeyFrame("medals_2"); // 金牌 } else { return ResLoader::getKeyFrame("medals_3"); // 钻石奖牌 } } } // namespace flappybird