草庐IT

c# - XNA 在不增加分辨率的情况下调整窗口大小

coder 2024-06-16 原文

我想在较大的窗口上创建一个低分辨率的游戏。 (例如 960x540 大小的窗口上的 96x54 分辨率)。

我该怎么做?有没有办法独立于首选的后台缓冲区宽度和高度来调整窗口大小?或者我应该只保留我绘制的低分辨率渲染目标,并在完成最近的纹理采样调整后将其作为全屏四边形绘制在我的窗口上?

提前致谢

小花

最佳答案

我倾向于选择“渲染到纹理”解决方案,这样我就可以在不失真的情况下实现全屏显示。

我用来实现此目的的类通常类似于:

class VirtualScreen
{
    public readonly int VirtualWidth;
    public readonly int VirtualHeight;
    public readonly float VirtualAspectRatio;

    private GraphicsDevice graphicsDevice;
    private RenderTarget2D screen;

    public VirtualScreen(int virtualWidth, int virtualHeight, GraphicsDevice graphicsDevice)
    {
        VirtualWidth = virtualWidth;
        VirtualHeight = virtualHeight;
        VirtualAspectRatio = (float)(virtualWidth) / (float)(virtualHeight);

        this.graphicsDevice = graphicsDevice;
        screen = new RenderTarget2D(graphicsDevice, virtualWidth, virtualHeight, false, graphicsDevice.PresentationParameters.BackBufferFormat, graphicsDevice.PresentationParameters.DepthStencilFormat, graphicsDevice.PresentationParameters.MultiSampleCount, RenderTargetUsage.DiscardContents);
    }

    private bool areaIsDirty = true;

    public void PhysicalResolutionChanged()
    {
        areaIsDirty = true;
    }

    private Rectangle area;

    public void Update()
    {
        if (!areaIsDirty)
        {
            return;
        }

        areaIsDirty = false;
        var physicalWidth = graphicsDevice.Viewport.Width;
        var physicalHeight = graphicsDevice.Viewport.Height;
        var physicalAspectRatio = graphicsDevice.Viewport.AspectRatio;

        if ((int)(physicalAspectRatio * 10) == (int)(VirtualAspectRatio * 10))
        {
            area = new Rectangle(0, 0, physicalWidth, physicalHeight);
            return;
        }


        if (VirtualAspectRatio > physicalAspectRatio)
        {
            var scaling = (float)physicalWidth / (float)VirtualWidth;
            var width = (float)(VirtualWidth) * scaling;
            var height = (float)(VirtualHeight) * scaling;
            var borderSize = (int)((physicalHeight - height) / 2);
            area = new Rectangle(0, borderSize, (int)width, (int)height);
        }
        else
        {
            var scaling = (float)physicalHeight / (float)VirtualHeight;
            var width = (float)(VirtualWidth) * scaling;
            var height = (float)(VirtualHeight) * scaling;
            var borderSize = (int)((physicalWidth - width) / 2);
            area = new Rectangle(borderSize, 0, (int)width, (int)height);
        }
    }

    public void BeginCapture()
    {
        graphicsDevice.SetRenderTarget(screen);
    }

    public void EndCapture()
    {
        graphicsDevice.SetRenderTarget(null);
    }

    public void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(screen, area, Color.White);
    }


}

然后在我的游戏中,初始化看起来像这样:

  VirtualScreen virtualScreen;

    protected override void Initialize()
    {
        virtualScreen = new VirtualScreen(96, 54, GraphicsDevice);
        Window.ClientSizeChanged += new EventHandler<EventArgs>(Window_ClientSizeChanged);
        Window.AllowUserResizing = true;
        base.Initialize();
    }

    void Window_ClientSizeChanged(object sender, EventArgs e)
    {
        virtualScreen.PhysicalResolutionChanged();
    }

所有重要的更新调用:

protected override void Update(GameTime gameTime)
    {
        virtualScreen.Update();

        base.Update(gameTime);
    }

然后是绘画本身:

 protected override void Draw(GameTime gameTime)
    {
        virtualScreen.BeginCapture();


        GraphicsDevice.Clear(Color.CornflowerBlue);
        // game rendering happens here...


        virtualScreen.EndCapture();

        GraphicsDevice.Clear(Color.Black);
        spriteBatch.Begin();
        virtualScreen.Draw(spriteBatch);
        spriteBatch.End();

        base.Draw(gameTime);
    }

有了这个,我基本上可以不再关心分辨率,而只专注于游戏。

关于c# - XNA 在不增加分辨率的情况下调整窗口大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7591466/

有关c# - XNA 在不增加分辨率的情况下调整窗口大小的更多相关文章

  1. ruby - 默认情况下使选项为 false - 2

    这是在Ruby中设置默认值的常用方法:classQuietByDefaultdefinitialize(opts={})@verbose=opts[:verbose]endend这是一个容易落入的陷阱:classVerboseNoMatterWhatdefinitialize(opts={})@verbose=opts[:verbose]||trueendend正确的做法是:classVerboseByDefaultdefinitialize(opts={})@verbose=opts.include?(:verbose)?opts[:verbose]:trueendend编写Verb

  2. ruby - 检查数组是否在增加 - 2

    这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife

  3. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  4. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  5. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  6. ruby - 在不使用 RVM 的情况下在 Mac 上卸载和升级 Ruby - 2

    我最近决定从我的系统中卸载RVM。在thispage提出的一些论点说服我:实际上,我的决定是,我根本不想担心Ruby的多个版本。我只想使用1.9.2-p290版本而不用担心其他任何事情。但是,当我在我的Mac上运行ruby--version时,它告诉我我的版本是1.8.7。我四处寻找如何简单地从我的Mac上卸载这个Ruby,但奇怪的是我没有找到任何东西。似乎唯一想卸载Ruby的人运行linux,而使用Mac的每个人都推荐RVM。如何从我的Mac上卸载Ruby1.8.7?我想升级到1.9.2-p290版本,并且我希望我的系统上只有一个版本。 最佳答案

  7. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  8. [工业相机] 分辨率、精度和公差之间的关系 - 2

    📢博客主页:https://blog.csdn.net/weixin_43197380📢欢迎点赞👍收藏⭐留言📝如有错误敬请指正!📢本文由Loewen丶原创,首发于CSDN,转载注明出处🙉📢现在的付出,都会是一种沉淀,只为让你成为更好的人✨文章预览:一.分辨率(Resolution)1、工业相机的分辨率是如何定义的?2、工业相机的分辨率是如何选择的?二.精度(Accuracy)1、像素精度(PixelAccuracy)2、定位精度和重复定位精度(RepeatPrecision)三.公差(Tolerance)四.课后作业(Post-ClassExercises)视觉行业的初学者,甚至是做了1~2年

  9. ruby - 在什么情况下会使用 Sinatra 或 Merb? - 2

    我正在学习Rails,对Sinatra和Merb知之甚少。我想知道您会在哪些情况下使用Merb/Sinatra。感谢您的反馈! 最佳答案 Sinatra是一个比Rails更小、更轻的框架。如果你想让一些东西快速运行,只需发送几个URL并返回一些简单的内容,就可以使用它。看看Sinatrahomepage;这就是启动和运行“Hello,World”所需的全部内容,而在Rails中,您需要生成整个项目结构、设置Controller和View、设置路由等等(我还没有有一段时间写了一个Rails应用程序,所以我不知道“Hello,World

  10. ruby - 是否可以在不实际发送或读取数据的情况下查明 ruby​​ 套接字是否处于 ESTABLISHED 或 CLOSE_WAIT 状态? - 2

    s=Socket.new(Socket::AF_INET,Socket::SOCK_STREAM,0)s.connect(Socket.pack_sockaddr_in('port','hostname'))ssl=OpenSSL::SSL::SSLSocket.new(s,sslcert)ssl.connect从这里开始,如果ssl连接和底层套接字仍然是ESTABLISHED,或者它是否在默认值7200之后进入CLOSE_WAIT,我想检查一个线程几秒钟甚至更糟的是在实际上不需要.write()或.read()的情况下关闭。是用select()、IO.select()还是其他方法完成

随机推荐