本文介绍了简单的XNA 2D演示:为什么我的F#版本比C#版本慢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

运行此XNA应用程序时,它应该显示一个从左上角移动到右下角的旋转矩形。

When running this XNA application it should display a rotated rectangle that moves from top-left corner to bottom-right corner.

看起来我的F#版本很明显慢得多。似乎Draw方法会跳过很多帧。

It looks like my F# version is noticeably much slower. It seems that the Draw method skips a lot of frames.

我正在使用VS 2012 RC,XNA 4.0,.NET 4.5,F#3.0。我正在尝试使其尽可能发挥作用。

I am using VS 2012 RC, XNA 4.0, .NET 4.5, F# 3.0. I am trying to make it as functional as possible.

性能不佳的原因可能是什么?

What could be the reason for poor performance?

C#:

class Program
{
    static void Main(string[] args)
    {
        using (var game = new FlockGame())
        {
            game.Run();
        }
    }
}

public class FlockGame : Game
{
    private GraphicsDeviceManager graphics;
    private DrawingManager drawingManager;
    private Vector2 position = Vector2.Zero;

    public FlockGame()
    {
        graphics = new GraphicsDeviceManager(this);
    }

    protected override void Initialize()
    {
        drawingManager = new DrawingManager(graphics.GraphicsDevice);
        this.IsFixedTimeStep = false;
    }

    protected override void Update(GameTime gameTime)
    {
        position = new Vector2(position.X + 50.1f * (float)gameTime.ElapsedGameTime.TotalSeconds,
                               position.Y + 50.1f * (float)gameTime.ElapsedGameTime.TotalSeconds);
        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
        //this.GraphicsDevice.Clear(Color.Lavender)

        drawingManager.DrawRectangle(position, new Vector2(100.0f, 100.0f), 0.7845f, Color.Red);

        base.Draw(gameTime);
    }
}

public class DrawingManager
{
    private GraphicsDevice GraphicsDevice;
    private Effect Effect;

    public DrawingManager(GraphicsDevice graphicsDevice)
    {
        GraphicsDevice = graphicsDevice;
        this.Effect =
            new BasicEffect(this.GraphicsDevice)
                {
                    VertexColorEnabled = true,
                    Projection = Matrix.CreateOrthographicOffCenter(0.0f, this.GraphicsDevice.Viewport.Width,
                                                                    this.GraphicsDevice.Viewport.Height,                                                                         0.0f, 0.0f, 1.0f)
                };
    }

    private VertexPositionColor[] GetRectangleVertices (Vector2 center, Vector2 size, float radians, Color color)
    {
        var halfSize = size/2.0f;
        var topLeft = -halfSize;
        var bottomRight = halfSize;
        var topRight = new Vector2(bottomRight.X, topLeft.Y);
        var bottomLeft = new Vector2(topLeft.X, bottomRight.Y);

        topLeft = Vector2.Transform(topLeft, Matrix.CreateRotationZ(radians)) + center;
        topRight = Vector2.Transform(topRight, Matrix.CreateRotationZ(radians)) + center;
        bottomRight = Vector2.Transform(bottomRight, Matrix.CreateRotationZ(radians)) + center;
        bottomLeft = Vector2.Transform(bottomLeft, Matrix.CreateRotationZ(radians)) + center;

        return new VertexPositionColor[]
        {
            new VertexPositionColor(new Vector3(topLeft, 0.0f), color),
            new VertexPositionColor(new Vector3(topRight, 0.0f), color),
            new VertexPositionColor(new Vector3(topRight, 0.0f), color),
            new VertexPositionColor(new Vector3(bottomRight, 0.0f), color),
            new VertexPositionColor(new Vector3(bottomRight, 0.0f), color),
            new VertexPositionColor(new Vector3(bottomLeft, 0.0f), color),
            new VertexPositionColor(new Vector3(bottomLeft, 0.0f), color),
            new VertexPositionColor(new Vector3(topLeft, 0.0f), color)
        };
    }


    public void DrawRectangle(Vector2 center, Vector2 size, float radians, Color color)
    {
        var vertices = GetRectangleVertices(center, size, radians, color);

        foreach (var pass in this.Effect.CurrentTechnique.Passes)
        {
            pass.Apply();
            this.GraphicsDevice.DrawUserPrimitives(PrimitiveType.LineList, vertices, 0, vertices.Length/2);
        }
    }
}

F#:

namespace Flocking

module FlockingProgram = 
    open System
    open Flocking

    [<STAThread>]
    [<EntryPoint>]
    let Main _ =
        use g = new FlockGame()
        g.Run()
        0

// ----------------- -------------------------------------------------- -----------

//------------------------------------------------------------------------------

namespace Flocking

open System
open System.Diagnostics
open Microsoft.Xna.Framework
open Microsoft.Xna.Framework.Graphics
open Microsoft.Xna.Framework.Input


type public FlockGame() as this =
    inherit Game()
    let mutable graphics = new GraphicsDeviceManager(this)
    let mutable drawingManager = null
    let mutable position = Vector2.Zero

    override Game.LoadContent() =
        drawingManager <- new Rendering.DrawingManager(graphics.GraphicsDevice)
        this.IsFixedTimeStep <- false

    override Game.Update gameTime =
        position <- Vector2(position.X + 50.1f * float32 gameTime.ElapsedGameTime.TotalSeconds,
                            position.Y + 50.1f * float32 gameTime.ElapsedGameTime.TotalSeconds)
        base.Update gameTime

    override Game.Draw gameTime =
        //this.GraphicsDevice.Clear(Color.Lavender)

        Rendering.DrawRectangle(drawingManager, position, Vector2(100.0f, 100.0f), 0.7845f, Color.Red)

        base.Draw gameTime

// ------------ -------------------------------------------------- ----------------

//------------------------------------------------------------------------------

namespace Flocking

open System
open System.Collections.Generic
open Microsoft.Xna.Framework
open Microsoft.Xna.Framework.Graphics
open Microsoft.Xna.Framework.Input

module Rendering = 

    [<AllowNullLiteral>]
    type DrawingManager (graphicsDevice : GraphicsDevice) = 
        member this.GraphicsDevice = graphicsDevice
        member this.Effect =
            new BasicEffect(this.GraphicsDevice,
                VertexColorEnabled = true,
                Projection = Matrix.CreateOrthographicOffCenter(0.0f,
                    float32 this.GraphicsDevice.Viewport.Width,
                    float32 this.GraphicsDevice.Viewport.Height,
                    0.0f, 0.0f, 1.0f))


    let private GetRectangleVertices (center:Vector2, size:Vector2, radians:float32, color:Color) = 
        let halfSize = size / 2.0f
        let mutable topLeft = -halfSize
        let mutable bottomRight = halfSize
        let mutable topRight = new Vector2(bottomRight.X, topLeft.Y)
        let mutable bottomLeft = new Vector2(topLeft.X, bottomRight.Y)

        topLeft <- Vector2.Transform(topLeft, Matrix.CreateRotationZ(radians)) + center
        topRight <- Vector2.Transform(topRight, Matrix.CreateRotationZ(radians)) + center
        bottomRight <- Vector2.Transform(bottomRight, Matrix.CreateRotationZ(radians)) + center
        bottomLeft <- Vector2.Transform(bottomLeft, Matrix.CreateRotationZ(radians)) + center

        [|
            new VertexPositionColor(new Vector3(topLeft, 0.0f), color)
            new VertexPositionColor(new Vector3(topRight, 0.0f), color)
            new VertexPositionColor(new Vector3(topRight, 0.0f), color)
            new VertexPositionColor(new Vector3(bottomRight, 0.0f), color)
            new VertexPositionColor(new Vector3(bottomRight, 0.0f), color)
            new VertexPositionColor(new Vector3(bottomLeft, 0.0f), color)
            new VertexPositionColor(new Vector3(bottomLeft, 0.0f), color)
            new VertexPositionColor(new Vector3(topLeft, 0.0f), color)
        |]


    let DrawRectangle (drawingManager:DrawingManager, center:Vector2, size:Vector2, radians:float32, color:Color) = 
        let vertices = GetRectangleVertices(center, size, radians, color)

        for pass in drawingManager.Effect.CurrentTechnique.Passes do
            pass.Apply()
            drawingManager.GraphicsDevice.DrawUserPrimitives(PrimitiveType.LineList, vertices, 0, vertices.Length/2)


推荐答案

这是一个猜测;我对这个域一无所知,但是 Effect 属性每次读取时都会创建一个新的 BasicEffect 对象。也许您想使用构造函数内部的 let 初始化该对象一次,然后返回该对象?

This is a guess; I know nothing about this domain, but the Effect property is creating a new BasicEffect object every time it is read; maybe you want to initialize that object once with a let inside the constructor and then return that object?

这篇关于简单的XNA 2D演示:为什么我的F#版本比C#版本慢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-20 15:24