从零开发游戏需要学习的c#模块,第三十三章(暂停菜单)

从零开发游戏需要学习的c#模块,第三十三章(暂停菜单) 本节课目标按ESC或P键暂停游戏暂停时画面变暗显示菜单选项选项继续游戏、返回标题、退出暂停时所有敌人和子弹停止移动第一步创建暂停菜单类右键项目 →添加→类文件名PauseMenu.csusing Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using FontStashSharp; using System; using System.Collections.Generic; namespace MY_FIRST_GAME { public class PauseMenu { private Liststring options; private int selectedIndex; private KeyboardState previousKeyboard; private KeyboardState currentKeyboard; public PauseMenu() { options new Liststring { 继续游戏, 返回标题, 退出游戏 }; selectedIndex 0; } // 返回值0继续, 1返回标题, 2退出, -1还在菜单中 public int Update() { previousKeyboard currentKeyboard; currentKeyboard Keyboard.GetState(); if (IsKeyJustPressed(Keys.W) || IsKeyJustPressed(Keys.Up)) { selectedIndex--; if (selectedIndex 0) selectedIndex options.Count - 1; } if (IsKeyJustPressed(Keys.S) || IsKeyJustPressed(Keys.Down)) { selectedIndex; if (selectedIndex options.Count) selectedIndex 0; } if (IsKeyJustPressed(Keys.Enter) || IsKeyJustPressed(Keys.Space)) { return selectedIndex; } return -1; } private bool IsKeyJustPressed(Keys key) { return currentKeyboard.IsKeyDown(key) previousKeyboard.IsKeyUp(key); } public void Draw(SpriteBatch spriteBatch, SpriteFontBase font, GraphicsDevice device) { // 半透明黑色背景 Texture2D overlay new Texture2D(device, 1, 1); overlay.SetData(new[] { new Color(0, 0, 0, 180) }); spriteBatch.Draw(overlay, new Rectangle(0, 0, 800, 600), Color.White); // 标题 string title - 暂停 -; Vector2 titleSize font.MeasureString(title); spriteBatch.DrawString(font, title, new Vector2(400 - titleSize.X / 2, 150), Color.White); // 选项 float startY 250; for (int i 0; i options.Count; i) { Color color (i selectedIndex) ? Color.Gold : Color.LightGray; string text (i selectedIndex) ? $ {options[i]} : $ {options[i]} ; Vector2 textSize font.MeasureString(text); spriteBatch.DrawString(font, text, new Vector2(400 - textSize.X / 2, startY i * 50), color); } // 操作提示 string hint ↑↓ 选择 | 回车 确认 | ESC 继续; spriteBatch.DrawString(font, hint, new Vector2(400 - font.MeasureString(hint).X / 2, 450), Color.Gray); } public void Reset() { selectedIndex 0; } } }第二步改造Game1.cs1. 添加字段csharpprivate PauseMenu pauseMenu default!;private bool isPaused false;2. 在 Initialize 里创建暂停菜单csharppauseMenu new PauseMenu();3. 在 Update 开头处理暂停键在所有 switch 之前加csharp// ★ 暂停切换if (keyboard.IsKeyDown(Keys.P) !isPaused ||keyboard.IsKeyDown(Keys.Escape) sceneManager.CurrentScene SceneType.Game){isPaused !isPaused;pauseMenu.Reset();}4. 把 Game 状态的更新包裹在暂停检查里csharpcase SceneType.Game:if (!isPaused){// 原有的所有 Game 更新逻辑}break;也就是把 case SceneType.Game: 里面那堆代码外面包一层 if (!isPaused)。5. 在 Draw 里画暂停菜单在 DrawGameWorld 和 DrawGameUI 之后加csharp// ★ 画暂停菜单if (isPaused sceneManager.CurrentScene SceneType.Game){_spriteBatch.Begin();int result pauseMenu.Update();pauseMenu.Draw(_spriteBatch, font, GraphicsDevice);_spriteBatch.End();if (result 0) // 继续游戏{isPaused false;}else if (result 1) // 返回标题{isPaused false;sceneManager.CurrentScene SceneType.Title;saveData.TotalCoinsCollected coinsCollectedThisGame;saveData.TotalEnemiesDefeated enemiesDefeatedThisGame;SaveManager.Save(saveData);}else if (result 2) // 退出{Exit();}}注意暂停菜单需要独立的 Begin/End不能和 UI 共用因为需要自己的 Update 调用。最好把上面这段放在 UI 的 Begin/End 之后。好了本节课学习到此结束我是魔法阵维护师关注我下期更精彩