You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:31:50