在Visual Studio的C# MonoGame中实现计时、重置与暂停功能
给你的MonoGame游戏添加计时器与暂停功能
嘿,我来帮你实现需要的计时器和暂停功能,完全贴合你现有的代码结构来修改,一步步来:
1. 先添加工变量
在你的SuperAlianorRescue类里,加入这些处理计时和暂停的变量:
// --- TIMER & PAUSE --- // 记录游戏流逝的总时间(单位:秒) private float gameTimeElapsed = 0f; // 标记计时器是否暂停(配合GameState使用更灵活) private bool isTimerPaused = false; // 暂停窗口的区域(屏幕中央的半透明蓝框) private Rectangle pauseWindowRect; // 暂停窗口的半透明蓝色 private Color pauseWindowColor = new Color(0, 0, 255, 180); // 记录上一帧键盘状态,避免按键重复触发 private KeyboardState previousKeyboardState;
2. 初始化暂停窗口
在Initialize方法里,加上暂停窗口的初始化代码,让它居中显示:
// 初始化暂停窗口(宽300,高200,屏幕居中) var viewport = graphics.GraphicsDevice.Viewport; pauseWindowRect = new Rectangle( viewport.Width / 2 - 150, viewport.Height / 2 - 100, 300, 200 );
3. 更新计时器与暂停逻辑
修改你的Update方法(补充关键部分),处理计时更新、按键切换暂停状态,还有碰撞重置计时器:
protected override void Update(GameTime gameTime) { var keyboardState = Keyboard.GetState(); // 处理P键的单次触发(避免按住时反复切换) if (keyboardState.IsKeyDown(Keys.P) && !previousKeyboardState.IsKeyDown(Keys.P)) { if (currentGameState == GameState.GamePlay) { currentGameState = GameState.GamePause; isTimerPaused = true; } else if (currentGameState == GameState.GamePause) { currentGameState = GameState.GamePlay; isTimerPaused = false; } } // 保存上一帧键盘状态 previousKeyboardState = keyboardState; // 只有在游戏进行且未暂停时,更新计时和游戏逻辑 if (currentGameState == GameState.GamePlay && !isTimerPaused) { // 累加流逝时间 gameTimeElapsed += (float)gameTime.ElapsedGameTime.TotalSeconds; // --- 你的原有游戏逻辑(角色移动、敌人生成等)保留在这里 --- // 角色碰到敌人时重置计时器 if (characterHit) { gameTimeElapsed = 0f; characterHit = false; // 重置碰撞标记 // 这里可以加游戏结束或其他碰撞逻辑 } } base.Update(gameTime); }
4. 绘制计时器与暂停窗口
修改Draw方法,添加计时器文本和暂停窗口的绘制:
protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); spriteBatch.Begin(); // 绘制背景(你的原有代码) spriteBatch.Draw(backgroundTexture, Vector2.Zero, Color.White); // 绘制计时器(游戏中或暂停时都显示) if (currentGameState == GameState.GamePlay || currentGameState == GameState.GamePause) { // 格式化时间为 分:秒 格式,比如 01:45 string timerText = $"Time: {TimeSpan.FromSeconds(gameTimeElapsed):mm\\:ss}"; // 把计时器放在屏幕右上角安全区内 var timerPos = new Vector2( safeBounds.Right - scoreFont.MeasureString(timerText).X, safeBounds.Top ); spriteBatch.DrawString(scoreFont, timerText, timerPos, Color.White); } // 绘制暂停窗口和提示文本 if (currentGameState == GameState.GamePause) { // 用1x1白色像素绘制半透明蓝框(需要在Content里加一张whitePixel.png) var whitePixel = Content.Load<Texture2D>("whitePixel"); spriteBatch.Draw(whitePixel, pauseWindowRect, pauseWindowColor); // 绘制"Game Paused"文本,居中显示在窗口里 string pauseText = "Game Paused"; var textSize = scoreFont.MeasureString(pauseText); var textPos = new Vector2( pauseWindowRect.X + (pauseWindowRect.Width - textSize.X) / 2, pauseWindowRect.Y + (pauseWindowRect.Height - textSize.Y) / 2 ); spriteBatch.DrawString(scoreFont, pauseText, textPos, Color.White); } // --- 你的原有绘制逻辑(角色、敌人、分数等)保留在这里 --- spriteBatch.End(); base.Draw(gameTime); }
小提示:关于白色像素纹理
你需要在项目的Content文件夹里添加一张1x1的白色PNG图片,命名为whitePixel,这是MonoGame里绘制纯色矩形的常规做法,比自定义图形简单多了。
5. 碰撞检测时的计时器重置
在你现有的碰撞检测代码里,当检测到角色和敌人碰撞时,直接重置计时器(或者通过characterHit标记,上面的Update代码已经处理了):
// 假设你遍历敌人列表的碰撞检测代码 foreach (var enemyPos in enemyPositions) { var characterRect = new Rectangle((int)characterPosition.X, (int)characterPosition.Y, characterTexture.Width, characterTexture.Height); var enemyRect = new Rectangle((int)enemyPos.X, (int)enemyPos.Y, enemyTexture.Width, enemyTexture.Height); if (characterRect.Intersects(enemyRect)) { gameTimeElapsed = 0f; // 直接重置计时器 characterHit = true; // 这里可以加游戏结束、播放音效等逻辑 break; } }
最后:新游戏初始化时重置计时器
当从主菜单开始新游戏时(比如按ENTER),记得重置计时器状态:
// 比如在处理ENTER键的逻辑里 if (currentGameState == GameState.GameMenu && keyboardState.IsKeyDown(Keys.Enter)) { currentGameState = GameState.GamePlay; gameTimeElapsed = 0f; isTimerPaused = false; // 其他初始化逻辑(分数重置等) }
这样就完全实现了你需要的所有功能:记录游戏流逝时间、碰撞敌人重置计时器、按P键暂停并显示半透明蓝色窗口、再次按P恢复计时和游戏。
内容的提问来源于stack exchange,提问作者Hugi Husser
相关产品推荐
相关产品推荐

