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

如何在Xbox One上的UWP MonoGame中实现全屏绘制?

问题:MonoGame UWP游戏在Xbox One上无法填满1920x1080屏幕

我正在开发一款基于MonoGame框架、打包为UWP应用的游戏项目。该项目在Windows和Xbox One设备上均可正常运行,但在Xbox One上的视口尺寸仅为1728x972,而非预期的1920x1080,推测是自适应到了标题安全区域。即便所有图形都能适配标题安全区域,我仍希望使用纯色填充整个电视屏幕,请问是否可以放大视口或在视口外进行绘制?


App.xaml

<Application
    x:Class="FirstXboxGame.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</Application>

App.xaml.cs

using System;

using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace FirstXboxGame
{
    sealed partial class App : Application
    {
        public App()
        {
            this.InitializeComponent();
            this.Suspending += this.OnSuspending;
        }

        protected override void OnLaunched(LaunchActivatedEventArgs e)
        {
            // 如果窗口没有内容,创建框架并导航到第一页
            if (!(Window.Current.Content is Frame rootFrame))
            {
                rootFrame = new Frame();

                rootFrame.NavigationFailed +=
                    (sender, navigationFailedEventArgs) => throw new Exception("Failed to load Page " + navigationFailedEventArgs.SourcePageType.FullName);

                // 将框架放入当前窗口
                Window.Current.Content = rootFrame;

                if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
                {
                    //TODO: 从之前暂停的应用加载状态
                }
            }

            if (!e.PrelaunchActivated)
            {
                if (rootFrame.Content == null)
                {
                    rootFrame.Navigate(typeof(GamePage), e.Arguments);
                }

                Window.Current.Activate();
            }
        }

        private void OnSuspending(object sender, SuspendingEventArgs e)
        {
            var deferral = e.SuspendingOperation.GetDeferral();
            //TODO: 保存应用状态并停止所有后台活动
            deferral.Complete();
        }
    }
}

GamePage.xaml

<Page
    x:Class="FirstXboxGame.GamePage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
>
    <SwapChainPanel x:Name="swapChainPanel"/>
</Page>

GamePage.xaml.cs

using System;

using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace FirstXboxGame
{
    public sealed partial class GamePage : Page
    {
        readonly FirstXboxGame game;

        public GamePage()
        {
            this.InitializeComponent();

            // 创建游戏实例
            var launchArguments = string.Empty;
            this.game = MonoGame.Framework.XamlGame<FirstXboxGame>.Create(launchArguments, Window.Current.CoreWindow, this.swapChainPanel);
        }
    }
}

FirstXboxGame.cs

using Windows.Foundation;
using Windows.Graphics.Display;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace FirstXboxGame
{
    public class FirstXboxGame : Game
    {
        private GraphicsDeviceManager graphics;
        private SpriteBatch spriteBatch;
        private Size resolution;
        private Rectangle screenBounds;
        private Color matteColor;

        public FirstXboxGame()
        {
            this.graphics = new GraphicsDeviceManager(this);
            this.Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            // 保存屏幕信息
            var view = DisplayInformation.GetForCurrentView();

            this.resolution = new Size(view.ScreenWidthInRawPixels, view.ScreenHeightInRawPixels);
            this.screenBounds = new Rectangle(0, 0, (int) this.resolution.Width, (int) this.resolution.Height);

            // 屏幕填充色
            this.matteColor = Color.Red;

            // 切换到全屏
            if (!this.graphics.IsFullScreen)
            {
                this.graphics.ToggleFullScreen();
            }

            this.IsMouseVisible = true;

            // 创建SpriteBatch
            this.spriteBatch = new SpriteBatch(this.GraphicsDevice);

            base.Initialize();
        }

        protected override void LoadContent()
        {
            // TODO: 使用this.Content加载游戏资源
        }

        protected override void Update(GameTime gameTime)
        {
            var pressingBackButton = GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed;
            var pressingBButton = GamePad.GetState(PlayerIndex.One).Buttons.B == ButtonState.Pressed;
            var pressingEscapeKey = Keyboard.GetState().IsKeyDown(Keys.Escape);

            if (pressingBackButton || pressingBButton || pressingEscapeKey)
            {
                this.Exit();
            }

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            // 获取视口边界
            var isFullScreen = this.graphics.IsFullScreen;
            var viewportBounds = this.GraphicsDevice.Viewport.Bounds;
            var viewportTitleSafeArea = this.GraphicsDevice.Viewport.TitleSafeArea;

            // 用填充色清空视口
            this.GraphicsDevice.Clear(this.matteColor);

            // 绘制内容
            this.spriteBatch.Begin();
            // TODO: 绘制精灵
            this.spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}

解决方案

要让游戏填满Xbox One的1920x1080屏幕,需要突破标题安全区域限制,具体操作如下:

1. 让SwapChainPanel占满整个窗口

修改GamePage.xaml,确保SwapChainPanel填充整个Page:

<Page
    x:Class="FirstXboxGame.GamePage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
>
    <SwapChainPanel x:Name="swapChainPanel" 
                    HorizontalAlignment="Stretch" 
                    VerticalAlignment="Stretch"/>
</Page>

2. 强制设置后台缓冲区分辨率

在FirstXboxGame构造函数中,直接指定目标分辨率:

public FirstXboxGame()
{
    this.graphics = new GraphicsDeviceManager(this);
    this.Content.RootDirectory = "Content";
    // 强制设置Xbox One目标分辨率
    graphics.PreferredBackBufferWidth = 1920;
    graphics.PreferredBackBufferHeight = 1080;
    graphics.ApplyChanges();
}

3. 自定义视口覆盖整个屏幕

如果仍有黑边,手动创建覆盖全屏的视口:

protected override void Initialize()
{
    // ... 原有代码 ...

    // 创建覆盖整个屏幕的视口
    var fullViewport = new Viewport(0, 0, 1920, 1080);
    GraphicsDevice.Viewport = fullViewport;

    base.Initialize();
}

4. 启用真实全屏模式

确保使用硬件全屏而非窗口化全屏:

protected override void Initialize()
{
    // ... 原有代码 ...

    graphics.IsFullScreen = true;
    graphics.HardwareModeSwitch = true; // 禁用窗口化全屏,使用真实全屏
    graphics.ApplyChanges();

    base.Initialize();
}

原理说明

Xbox One默认将UWP应用限制在标题安全区域(1728x972是1920x1080的90%),通过强制设置后台缓冲区分辨率、自定义视口,再配合全屏SwapChainPanel布局,就能突破这个限制,让纯色填充整个电视屏幕。

内容的提问来源于stack exchange,提问作者amoss

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 15:20:43