0
\$\begingroup\$

I want to load multiple instances of a texture on the screen and be able to change the color of each one individually by clicking on it.
I've tried many different ways and currently I'm creating two 2d arrays.
Tile[,] tiles = new Tile[10,10]; (a class I made, essentially just overrides draw) and Texture2D[,] squareTex = new Texture2D[10,10];
Right now I've tried and change the color data but it applies it to every single Tile I have on screen. That doesn't make any sense to me because I am creating 100 different Texture2D's, unless changing color data applies it to the image file itself which seems weird to me. Any ideas?

Game1

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;


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

        Tile[,] tiles = new Tile[10, 10];
        static Texture2D[,] squareTex = new Texture2D[10, 10];

        bool lmbDown = false;

        Point grid = new Point(10, 10);

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

        /// <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
            this.IsMouseVisible = true;
            graphics.PreferredBackBufferWidth = 1000;
            graphics.PreferredBackBufferHeight = 1000;
            this.Window.Position = new Point(this.Window.Position.X, 0);
            graphics.ApplyChanges();


            base.Initialize();
        }

        /// <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);
            for (int x = 0; x < grid.X; x++)
            {
                for (int y = 0; y < grid.Y; y++)
                {
                    squareTex[x, y] = Content.Load<Texture2D>("square");
                }
            }
            //squareTex = Content.Load<Texture2D>("square");

            for (int x = 0; x < grid.X; x++)
            {
                for (int y = 0; y < grid.Y; y++)
                {
                    tiles[x, y] = new Tile(squareTex[x, y], new Vector2(x * 100, y * 100));
                }
            }



            // 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)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                Exit();

            MouseState ms = Mouse.GetState();


            if (ms.LeftButton == ButtonState.Pressed)
            {
                lmbDown = true;
            }

            if (lmbDown && ms.LeftButton == ButtonState.Released)
            {
                lmbDown = false;
                bool exit = false;
                for (int x = 0; x < grid.X && !exit; x++)
                {
                    for (int y = 0; y < grid.Y && !exit; y++)
                    {
                        if (tiles[x, y].collisionRect.Contains(ms.X, ms.Y))
                        {
                            Color[] data = new Color[squareTex[x,y].Width * squareTex[x, y].Height];
                            squareTex[x,y].GetData(data);
                            Color colorFrom = Color.White;
                            Color colorTo = Color.YellowGreen;
                            for (int i = 0; i < data.Length; i++)
                                if (data[i] == colorFrom)
                                    data[i] = colorTo;
                                else if (data[i] == colorTo)
                                    data[i] = colorFrom;

                            //Texture2D temp = tiles[x, y].textureImage;
                            //temp.SetData(data);
                            squareTex[x, y].SetData(data);
                            exit = true;

                        }
                    }
                }
            }



            // 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);
            spriteBatch.Begin();
            for (int x = 0; x < grid.X; x++)
            {
                for (int y = 0; y < grid.Y; y++)
                {
                    tiles[x, y].Draw(gameTime, spriteBatch);
                }
            }
            spriteBatch.End();

            // TODO: Add your drawing code here

            base.Draw(gameTime);
        }
    }
}

Tile

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace AlgorithmMidterm
{
    class Tile
    {
        public Texture2D textureImage;

        protected Vector2 position;


        //This constructor has no "ms per frame"
        public Tile(Texture2D textureImage, Vector2 position)
        {
            this.textureImage = textureImage;
            this.position = position;
        }



        public virtual void Update(GameTime gameTime, Rectangle clientBounds)
        {


        }


        public virtual void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            // Draw the sprite via the passed SpriteBatch
            spriteBatch.Draw(textureImage, position, Color.White);
        }



        // Gets the collision rect based on position, framesize and collision offset
        public Rectangle collisionRect
        {
            get
            {
                return new Rectangle(
                    (int)position.X,
                    (int)position.Y,
                    textureImage.Width,
                    textureImage.Height
                    );
            }

        }
    }
}
\$\endgroup\$
2
\$\begingroup\$

The color of the tile in the Tile.cs draw() method is hardcoded with Color.White. That already gives a less possible chance to change it individually.

Try giving the Tile.cs a color variable. And then change that color variable in the main method.

In your Tile.cs, add this variable:

public Color color = Color.White;

Also in your Tile.cs, change inside your draw() method to this:

spriteBatch.Draw(textureImage, position, color);

Then, in your Game1.cs, change the part where you add the color to this:

if (lmbDown && ms.LeftButton == ButtonState.Released)
        {
            lmbDown = false;
            bool exit = false;
            for (int x = 0; x < grid.X && !exit; x++)
            {
                for (int y = 0; y < grid.Y && !exit; y++)
                {
                    if (tiles[x, y].collisionRect.Contains(ms.X, ms.Y))
                    {
                        tiles[x, y].color = Color.YellowGreen; //<--The needed line of code.

                        //Texture2D temp = tiles[x, y].textureImage;
                        //temp.SetData(data);
                        squareTex[x, y].SetData(data);
                        exit = true;

                    }
                }
            }
        }

I think that's all you needed, please let me know if you're still having problems.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.