46

XNA (およびさまざまなバージョン) に関するチュートリアルをたくさん読みましたが、プリミティブの描画についてまだ少し混乱しています。すべてが本当に複雑に思えます。

コードを使用して、画面に 1 本または 2 本の線を描画する最も単純な XNA 実装を誰かに見せてもらえますか? おそらく簡単な説明(ボイラープレートを含む)で?

私はゲーム プログラマーではなく、XNA の経験もほとんどありません。私の最終的な目標は、最終的に回転などで(手動で)変換するいくつかの線を画面に描画することです。ただし、この最初のステップでは..単純に線を引く必要があります。昔の OpenGL の時代には、いくつかのメソッド呼び出しで線を引くのはかなり簡単だったのを覚えています。管理されていない directx 呼び出しを使用するように単純に戻す必要がありますか?

4

10 に答える 10

19

XNA を使用する場合、すべて (2D プリミティブも含む) を 3D カードが理解できる方法で表現する必要があります。つまり、線は単なる頂点の集合です。

MSDN にはかなり優れたウォークスルーがあります。

http://msdn.microsoft.com/en-us/library/bb196414.aspx#ID2EEF

プリミティブ ラインをレンダリングするには、テクスチャ化されたクワッドを設定して回転させるよりも多くのコードが必要であることがわかります。基本的に、ラインをレンダリングするときに同じことを行うからです。

于 2008-11-06T20:41:50.807 に答える
16

NoHayProblemaの答えに続いて(私はまだコメントできません)。

その答えは、この古い質問に対する正しいものですが、不完全です。Texture2Dコンストラクターは、初期化されていないテクスチャを返します。これは、画面に描画されることはありません。このアプローチを使用するには、テクスチャのデータを次のように設定する必要があります。

Texture2D SimpleTexture = new Texture2D(GraphicsDevice, 1, 1, false,
    SurfaceFormat.Color);

Int32[] pixel = {0xFFFFFF}; // White. 0xFF is Red, 0xFF0000 is Blue
SimpleTexture.SetData<Int32> (pixel, 0, SimpleTexture.Width * SimpleTexture.Height);

// Paint a 100x1 line starting at 20, 50
this.spriteBatch.Draw(SimpleTexture, new Rectangle(20, 50, 100, 1), Color.Blue);

データをピクセルに書き込む方法は、テクスチャのSurfaceFormatと一致している必要があることを考慮に入れてください。テクスチャがRGBとしてフォーマットされているため、この例は機能します。回転はspriteBatch.Drawで次のように適用できます。

this.spriteBatch.Draw (SimpleTexture, new Rectangle(0, 0, 100, 1), null,
    Color.Blue, -(float)Math.PI/4, new Vector2 (0f, 0f), SpriteEffects.None, 1f);
于 2011-01-15T00:43:30.923 に答える
10

そのhttp://www.bit-101.com/blog/?p=2832のチュートリアルを見つけました

XNA 4.0 で BasicEffect (シェーダー) と組み込みの描画ユーザー プリミティブを使用する

私が役立つと思ういくつかのコードサンプル:

load content メソッド

basicEffect = new BasicEffect(GraphicsDevice);
basicEffect.VertexColorEnabled = true;
basicEffect.Projection = Matrix.CreateOrthographicOffCenter
(0, GraphicsDevice.Viewport.Width,     // left, right
GraphicsDevice.Viewport.Height, 0,    // bottom, top
0, 1);   

描画方法

basicEffect.CurrentTechnique.Passes[0].Apply();
var vertices = new VertexPositionColor[4];
vertices[0].Position = new Vector3(100, 100, 0);
vertices[0].Color = Color.Black;
vertices[1].Position = new Vector3(200, 100, 0);
vertices[1].Color = Color.Red;
vertices[2].Position = new Vector3(200, 200, 0);
vertices[2].Color = Color.Black;
vertices[3].Position = new Vector3(100, 200, 0);
vertices[3].Color = Color.Red;

GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.LineList, vertices, 0, 2);

これが役に立った場合は、楽しんで投票してください。また、これを入手したチュートリアルにもアクセスしてください。

于 2012-11-12T01:37:37.287 に答える
8

ええと、3D のひどいベクターに取り掛かることなく、非常に簡単な方法でそれを行うことができます。

たとえば、簡単なテクスチャを作成するだけです。

Texture2D SimpleTexture = new Texture2D(GraphicsDevice, 1, 1, false, SurfaceFormat.Color);

次に、そのテクスチャを使用して線を描画します。

this.spriteBatch.Draw(SimpleTexture, new Rectangle(100, 100, 100, 1), Color.Blue);

これが役立つことを願っています

于 2010-09-19T14:53:31.057 に答える
2

「manders」が CodePlex でリリースした「ラウンド ライン」コードもあります。


これについてのブログ投稿は次のとおりです。

于 2009-07-06T03:00:50.647 に答える
1

私は自分でこの問題に遭遇し、LineBatch というクラスを作成することにしました。LineBatch は、spriteBatch やドットを必要とせずに線を描画します。クラスは以下。

public class LineBatch
{
    bool cares_about_begin_without_end;
    bool began;
    GraphicsDevice GraphicsDevice;
    List<VertexPositionColor> verticies = new List<VertexPositionColor>();
    BasicEffect effect;
    public LineBatch(GraphicsDevice graphics)
    {
        GraphicsDevice = graphics;
        effect = new BasicEffect(GraphicsDevice);
        Matrix world = Matrix.Identity;
        Matrix view = Matrix.CreateTranslation(-GraphicsDevice.Viewport.Width / 2, -GraphicsDevice.Viewport.Height / 2, 0);
        Matrix projection = Matrix.CreateOrthographic(GraphicsDevice.Viewport.Width, -GraphicsDevice.Viewport.Height, -10, 10);
        effect.World = world;
        effect.View = view;
        effect.VertexColorEnabled = true;
        effect.Projection = projection;
        effect.DiffuseColor = Color.White.ToVector3();
        cares_about_begin_without_end = true;
    }
    public LineBatch(GraphicsDevice graphics, bool cares_about_begin_without_end)
    {
        this.cares_about_begin_without_end = cares_about_begin_without_end;
        GraphicsDevice = graphics;
        effect = new BasicEffect(GraphicsDevice);
        Matrix world = Matrix.Identity;
        Matrix view = Matrix.CreateTranslation(-GraphicsDevice.Viewport.Width / 2, -GraphicsDevice.Viewport.Height / 2, 0);
        Matrix projection = Matrix.CreateOrthographic(GraphicsDevice.Viewport.Width, -GraphicsDevice.Viewport.Height, -10, 10);
        effect.World = world;
        effect.View = view;
        effect.VertexColorEnabled = true;
        effect.Projection = projection;
        effect.DiffuseColor = Color.White.ToVector3();
    }
    public void DrawAngledLineWithRadians(Vector2 start, float length, float radians, Color color)
    {
        Vector2 offset = new Vector2(
            (float)Math.Sin(radians) * length, //x
            -(float)Math.Cos(radians) * length //y
            );
        Draw(start, start + offset, color);
    }
    public void DrawOutLineOfRectangle(Rectangle rectangle, Color color)
    {
        Draw(new Vector2(rectangle.X, rectangle.Y), new Vector2(rectangle.X + rectangle.Width, rectangle.Y), color);
        Draw(new Vector2(rectangle.X, rectangle.Y), new Vector2(rectangle.X, rectangle.Y + rectangle.Height), color);
        Draw(new Vector2(rectangle.X + rectangle.Width, rectangle.Y), new Vector2(rectangle.X + rectangle.Width, rectangle.Y + rectangle.Height), color);
        Draw(new Vector2(rectangle.X, rectangle.Y + rectangle.Height), new Vector2(rectangle.X + rectangle.Width, rectangle.Y + rectangle.Height), color);
    }
    public void DrawOutLineOfTriangle(Vector2 point_1, Vector2 point_2, Vector2 point_3, Color color)
    {
        Draw(point_1, point_2, color);
        Draw(point_1, point_3, color);
        Draw(point_2, point_3, color);
    }
    float GetRadians(float angleDegrees)
    {
        return angleDegrees * ((float)Math.PI) / 180.0f;
    }
    public void DrawAngledLine(Vector2 start, float length, float angleDegrees, Color color)
    {
        DrawAngledLineWithRadians(start, length, GetRadians(angleDegrees), color);
    }
    public void Draw(Vector2 start, Vector2 end, Color color)
    {
        verticies.Add(new VertexPositionColor(new Vector3(start, 0f), color));
        verticies.Add(new VertexPositionColor(new Vector3(end, 0f), color));
    }
    public void Draw(Vector3 start, Vector3 end, Color color)
    {
        verticies.Add(new VertexPositionColor(start, color));
        verticies.Add(new VertexPositionColor(end, color));
    }
    public void End()
    {
        if (!began)
            if (cares_about_begin_without_end)
                throw new ArgumentException("Please add begin before end!");
            else
                Begin();
        if (verticies.Count > 0)
        {
            VertexBuffer vb = new VertexBuffer(GraphicsDevice, typeof(VertexPositionColor), verticies.Count, BufferUsage.WriteOnly);
            vb.SetData<VertexPositionColor>(verticies.ToArray());
            GraphicsDevice.SetVertexBuffer(vb);

            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Apply();
                GraphicsDevice.DrawPrimitives(PrimitiveType.LineList, 0, verticies.Count / 2);
            }
        }
        began = false;
    }
    public void Begin()
    {
        if (began)
            if (cares_about_begin_without_end)
                throw new ArgumentException("You forgot end.");
            else
                End();
        verticies.Clear();
            began = true;
    }
}
于 2014-09-19T15:45:53.603 に答える
1

白いピクセルを引き伸ばすだけです。

        point = game.Content.Load<Texture2D>("ui/point");

        public void DrawLine(Vector2 start, Vector2 end, Color color)
        {
            Vector2 edge = end - start;
            float angle = (float)Math.Atan2(edge.Y, edge.X);

            spriteBatch.Begin();
            spriteBatch.Draw(point,
                new Rectangle((int)start.X, (int)start.Y, (int)edge.Length(), 1),
                null, 
                color, 
                angle,
                new Vector2(0, 0),
                SpriteEffects.None,
                0);
            spriteBatch.End();
        }
于 2016-06-08T08:04:51.467 に答える
0

開始座標、終了座標、幅、および色を指定して線を作成するために使用する簡単な方法を次に示します。

注: 「ドット」という名前のファイルをコンテンツ ディレクトリに追加する必要があります (行はこれらから作成されます)。

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace Xna.LineHelper
{
    public class LineManager
    {
        int loopCounter;
        int lineLegnth;
        Vector2 lineDirection;
        Vector2 _position;
        Color dotColor;
        Rectangle _rectangle;
        List<Texture2D> _dots = new List<Texture2D>();
        FunctionsLibrary functions = new FunctionsLibrary();

        public void CreateLineFiles(Vector2 startPosition, Vector2 endPosition, int width, Color color, ContentManager content)
        {
            dotColor = color;
            _position.X = startPosition.X;
            _position.Y = startPosition.Y;
            lineLegnth = functions.Distance((int)startPosition.X, (int)endPosition.X, (int)startPosition.Y, (int)endPosition.Y);
            lineDirection = new Vector2((endPosition.X - startPosition.X) / lineLegnth, (endPosition.Y - startPosition.Y) / lineLegnth);
            _dots.Clear();
            loopCounter = 0;
            _rectangle = new Rectangle((int)startPosition.X, (int)startPosition.Y, width, width);
            while (loopCounter < lineLegnth)
            {
                Texture2D dot = content.Load<Texture2D>("dot");
                _dots.Add(dot);

                loopCounter += 1;
            }

        }

        public void DrawLoadedLine(SpriteBatch sb)
        {
            foreach (Texture2D dot in _dots)
            {
                _position.X += lineDirection.X;
                _position.Y += lineDirection.Y;
                _rectangle.X = (int)_position.X;
                _rectangle.Y = (int)_position.Y;
                sb.Draw(dot, _rectangle, dotColor);
            }
        }
    }

    public class FunctionsLibrary
    {
        //Random for all methods
        Random Rand = new Random();

        #region math
        public int TriangleArea1(int bottom, int height)
        {
            int answer = (bottom * height / 2);
            return answer;
        }

        public double TriangleArea2(int A, int B, int C)
        {
            int s = ((A + B + C) / 2);
            double answer = (Math.Sqrt(s * (s - A) * (s - B) * (s - C)));
            return answer;
        }
        public int RectangleArea(int side1, int side2)
        {
            int answer = (side1 * side2);
            return answer;
        }
        public int SquareArea(int side)
        {
            int answer = (side * side);
            return answer;
        }
        public double CircleArea(int diameter)
        {
            double answer = (((diameter / 2) * (diameter / 2)) * Math.PI);
            return answer;
        }
        public int Diference(int A, int B)
        {
            int distance = Math.Abs(A - B);
            return distance;
        }
        #endregion

        #region standardFunctions

        public int Distance(int x1, int x2, int y1, int y2)
        {
            return (int)(Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)));
        }

        #endregion



    }
}
于 2013-12-04T06:29:51.113 に答える