【问题标题】:Making a paint program using XNA使用 XNA 制作绘画程序
【发布时间】:2016-04-27 18:21:28
【问题描述】:

您好,我正在尝试使用 XNA 制作一个绘图程序,并且我尽可能地遵循了此处的指南:How to create Paint-like app with XNA? 到目前为止一切都很好,但是有一个问题:the drawn rectangles dont connect together to form a line.我没有想法,我将不胜感激提供的任何帮助。下面是我的代码。还请查看随附的图片以更好地理解。

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;

namespace ProfAnas
{
/// <summary>
/// This is the main type for your game.
/// </summary>
public class Game1 : Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    Texture2D canvas;
    Vector2 brushPos;

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

        graphics.PreferredBackBufferWidth = 1920;  // set this value to the desired width of your window
        graphics.PreferredBackBufferHeight = 1080;   // set this value to the desired height of your window
        graphics.ApplyChanges();
    }

    /// <summary>
    /// Allows the game to perform any initialization it needs to before starting to run.
    /// This is where it can query for any required services and load any non-graphic
    /// related content.  Calling base.Initialize will enumerate through any components
    /// and initialize them as well.
    /// </summary>
    protected override void Initialize()
    {
        // TODO: Add your initialization logic here
        base.Initialize();

        Color[] pixel = new Color[1920 * 1080];
        for (int i = 0; i < pixel.Length; i++)
        {
            pixel[i] = Color.White;

        }

        pixel[1919] = Color.Red;

        spriteBatch = new SpriteBatch(GraphicsDevice);
        canvas = new Texture2D(this.GraphicsDevice, 1920, 1080);
        canvas.SetData<Color>(pixel);

    }

    /// <summary>
    /// LoadContent will be called once per game and is the place to load
    /// all of your content.
    /// </summary>
    protected override void LoadContent()
    {
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);

        // TODO: use this.Content to load your game content here
    }

    /// <summary>
    /// UnloadContent will be called once per game and is the place to unload
    /// game-specific content.
    /// </summary>
    protected override void UnloadContent()
    {
        // TODO: Unload any non ContentManager content here
    }

    /// <summary>
    /// Allows the game to run logic such as updating the world,
    /// checking for collisions, gathering input, and playing audio.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    protected override void Update(GameTime gameTime)
    {
        MouseState state = Mouse.GetState();

        Color[] pixel = new Color[1920 * 1080];
        canvas.GetData<Color>(pixel);

        if (state.LeftButton == ButtonState.Pressed)
        {
            brushPos.X = state.X;
            brushPos.Y = state.Y;

            double piOn4 = Math.PI / 4;

            int xComponent;
            int yComponent;

            int screenWidth = 1920;
            int screenHeight = 1080;

            int regionXHalfed = (int)Math.Ceiling((10.0 * Math.Cos(piOn4) + 30.0 * Math.Cos(piOn4))/2);
            int regionYHalfed = (int)Math.Ceiling((10.0 * Math.Sin(piOn4) + 30.0 * Math.Sin(piOn4))/2);

            double angle;
            double centerToBoundary;
            double pixelToCenter;
            List<int> boundedPixel = new List<int>();


            for (int row=(state.Y-regionYHalfed); row < (state.Y + regionYHalfed); row++)
            {
                for (int column= (state.X - regionXHalfed); column < (state.X + regionXHalfed); column++)
                {


                    xComponent=column - state.X+1;
                    yComponent=row - state.Y+1;

                    if (xComponent == 0)
                    {
                        pixelToCenter = Math.Sqrt((double)xComponent*xComponent + (double)yComponent*yComponent);

                        if (Math.Abs(pixelToCenter) <= 5*Math.Sqrt(2))
                        {
                            boundedPixel.Add(((row) * screenWidth + column) + 1);
                        }

                        continue;
                    }

                    angle=Math.Atan( (double)yComponent / (double)xComponent);



                    if (angle>= (piOn4 - Math.Atan(1.0/3)) && angle<= (piOn4 + Math.Atan(1.0/3)))
                    {
                        centerToBoundary = 15 / Math.Cos(angle - piOn4);
                        pixelToCenter= xComponent / Math.Cos(angle);

                        if( Math.Abs(pixelToCenter) <= Math.Abs(centerToBoundary))
                        {
                            boundedPixel.Add(((row)* screenWidth + column)+1);
                        }
                    }

                    if (angle >= (piOn4 + Math.Atan(1.0 / 3)) && angle <= Math.PI/2)
                    {
                        centerToBoundary = 5 / Math.Cos(angle + piOn4);
                        pixelToCenter = xComponent / Math.Cos(angle);

                        if (Math.Abs(pixelToCenter) <= Math.Abs(centerToBoundary))
                        {
                            boundedPixel.Add(((row) * screenWidth + column) + 1);
                        }
                    }
                    if (angle >= 0.0 && angle <= (piOn4 - Math.Atan(1.0 / 3)))
                    {
                        centerToBoundary = 5 / Math.Cos(angle + piOn4);
                        pixelToCenter = xComponent / Math.Cos(angle);

                        if (Math.Abs(pixelToCenter) <= Math.Abs(centerToBoundary))
                        {
                            boundedPixel.Add(((row) * screenWidth + column) + 1);
                        }
                    }

                    if (angle >= -Math.PI / 2 && angle <= 0.0)
                    {
                        centerToBoundary = 5 / Math.Cos(angle + piOn4);
                        pixelToCenter = xComponent / Math.Cos(angle);

                        if (Math.Abs(pixelToCenter) <= Math.Abs(centerToBoundary))
                        {
                            boundedPixel.Add(((row) * screenWidth + column) + 1);
                        }
                    }

                }
            }

            foreach (int i in boundedPixel)
            {
                if(i>=0)
                    pixel[i] = Color.Red;

            }
        }

        canvas.SetData<Color>(pixel);

        // TODO: Add your update logic here

        base.Update(gameTime);
    }

    /// <summary>
    /// This is called when the game should draw itself.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        // TODO: Add your drawing code here
        spriteBatch.Begin();
        spriteBatch.Draw(canvas, new Vector2(0, 0));
        spriteBatch.End();

        base.Draw(gameTime);
    }
}
}

谢谢你:)

【问题讨论】:

  • 发生这种情况是因为鼠标在帧之间移动的距离大于“画笔”的宽度。您遵循的示例根本没有考虑这种情况。你必须尝试一些更高级的东西。

标签: c# mono xna paint


【解决方案1】:

正如@adv12 所建议的那样,XNA 游戏的更新方法不如 MSPaint 的快,这就是为什么如果逐像素绘制(或者在你的情况下是矩形绘制)你永远不会有一条线-rectangle) 如果您在画布上快速移动鼠标。

可能的解决方案是在释放鼠标左键时在按下鼠标左键时创建的矩形之间绘制新矩形。这将给您当前正在绘制的矩形的两倍 -1,并且无论调用 Update 的速度有多快,您都会有一条线。

【讨论】:

    猜你喜欢
    • 2013-03-27
    • 2014-04-23
    • 2011-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多