Page 5. Microsoft XNA: Mouse Interaction in MonoGame

Prerequisites

Before we dive into implementing mouse interactivity in your MonoGame project, let's ensure that you have the necessary foundation in place. If you're new to Microsoft XNA and MonoGame or need a refresher, it's highly recommended to start with our introductory project. You can follow the step-by-step walkthrough provided on Page 1: Microsoft XNA's Hello World w/ MonoGame to get acquainted with the basics.

List of Prerequisites:

  1. Visual Studio: Make sure you have a working installation of Visual Studio, which is the development environment we'll use for this project.

  2. MonoGame Framework: Ensure that you have the MonoGame framework installed. This framework provides the essential tools and libraries for game development.

  3. .xnb Font File: To display text in your MonoGame project, you'll need a .xnb file of your desired font. If you haven't created one yet, you can refer back to Page 1 for guidance on how to generate it.

Why Mouse Interaction in MonoGame Matters

Here, we'll equip you with essential skills to create responsive games that react to mouse input. Whether you want clickable buttons, interactive characters, or dynamic UI elements, understanding mouse interactions is vital for game development.

What You'll Learn

  1. Mouse States: Discover how to access the mouse's current state, including position, button clicks, and scroll wheel activity.

  2. Handling Clicks: Learn to detect left and right mouse button clicks and use them to trigger actions like speeding up or slowing down game elements.

  3. Mouse Movement: Explore tracking the mouse's position for various game mechanics, allowing you to control in-game objects.

  4. Scroll Wheel Interaction: Use the mouse scroll wheel to adjust the scale (size) of game elements.

Setting up your code

Here is the code we ended with on Page 4.

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace YourGameNamespace
{
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        SpriteFont font;
        Vector2 position;
        Vector2 velocity;
        Color color;

        // Frame rate variables
        int frameRate;
        int frameCounter;
        TimeSpan elapsedTime = TimeSpan.Zero;

        // Aspect ratio variables
        float aspectRatio;

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

            // Initialize frame rate variables
            frameRate = 0;
            frameCounter = 0;

            // Initialize aspect ratio
            aspectRatio = 4f / 3f;  // Default 4:3 aspect ratio
            this.TargetElapsedTime = TimeSpan.FromTicks(166667); // Sets to 60 FPS
        }

        protected override void Initialize()
        {
            // Handle aspect ratio in Initialize() here
            graphics.PreferredBackBufferWidth = 800;  
            graphics.PreferredBackBufferHeight = (int)(800 / aspectRatio);  
            graphics.ApplyChanges();

            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: Load your game content here
            font = Content.Load<SpriteFont>("Arial");
            position = new Vector2(400, 300);
            velocity = new Vector2(1, 1);
            color = Color.White;
        }

        protected override void Update(GameTime gameTime)
        {
            // Update frame rate counters
            elapsedTime += gameTime.ElapsedGameTime;
            if (elapsedTime > TimeSpan.FromSeconds(1))
            {
                elapsedTime -= TimeSpan.FromSeconds(1);
                frameRate = frameCounter;
                frameCounter = 0;
            }

            // TODO: Add your update logic here
            position += velocity;
            if (position.X > Window.ClientBounds.Width - 50 || position.X < 0)
            {
                velocity.X *= -1;
            }
            if (position.Y > Window.ClientBounds.Height - 50 || position.Y < 0)
            {
                velocity.Y *= -1;
            }

            color = new Color(frameRate % 255, 128, 128);

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // Increment frame counter
            frameCounter++;

            spriteBatch.Begin();
            spriteBatch.DrawString(font, $"Hello, world! FPS: {frameRate}", position, color);
            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}

This will be the structure of your Game1 class.

Understanding Mouse States

In MonoGame, you can access the current state of the mouse by using the Mouse.GetState() method. To do this, you'll need to declare two MouseState variables at the class level. These variables will allow you to check the state of the mouse at any time.

MouseState currentMouseState;
MouseState previousMouseState;

Now, let's break down these variables and what they do:

  • currentMouseState: This variable will hold the current state of the mouse, including information about button presses and mouse position.

  • previousMouseState: This variable will hold the state of the mouse in the previous frame. We use this to detect mouse button clicks.

In your Update() method, add the following code to update the mouse states:

previousMouseState = currentMouseState;
currentMouseState = Mouse.GetState();

This code updates previousMouseState with the state of the mouse from the previous frame and currentMouseState with the current state of the mouse. This is crucial for detecting mouse button clicks.

Detect Mouse Clicks

Inside your Update method, you can check for left and right mouse button clicks using currentMouseState and previousMouseState. Here's how you can do it:

// Detect left mouse button click
if (currentMouseState.LeftButton == ButtonState.Pressed && previousMouseState.LeftButton == ButtonState.Released)
{
    // Code to speed up here
}

// Detect right mouse button click
if (currentMouseState.RightButton == ButtonState.Pressed && previousMouseState.RightButton == ButtonState.Released)
{
    // Code to slow down here
}

Let's break down what's happening here:

  • The first if statement checks if the left mouse button is currently pressed (currentMouseState.LeftButton == ButtonState.Pressed) and if it was released in the previous frame (previousMouseState.LeftButton == ButtonState.Released). This combination detects a left mouse button click.

  • The second if statement does the same but for the right mouse button.

Control Speed w/ Mouse Clicks

In this step, we'll make your game element respond to mouse clicks by adjusting its speed.

Speeding Up with Left Click: When a left click is detected (currentMouseState.LeftButton == ButtonState.Pressed), and the previous frame didn't register a left click (previousMouseState.LeftButton == ButtonState.Released), we execute the code inside this block. Here's what's happening:

// Speed up with left click
if (currentMouseState.LeftButton == ButtonState.Pressed && previousMouseState.LeftButton == ButtonState.Released)
{
    velocity *= 2.0f;
}

Inside the block, we modify the velocity of the text element. Velocity represents how fast the game element moves.

By multiplying velocity by 2.0f, we effectively double its speed. This means your game element will move twice as fast in response to a left click.

Slowing Down with Right Click: Knowing if we use 2.0f, what variable would we use to slow the speed down? If you guessed 0.5f, that is correct!

// Slow down with right-click
if (currentMouseState.RightButton == ButtonState.Pressed && previousMouseState.RightButton == ButtonState.Released)
{
    velocity *= 0.5f;
}

Similar to the left-click scenario, we adjust the velocity of our game element. However, this time, we multiply it by 0.5f, which reduces its speed to half of its current value. This effectively slows down your game element's movement in response to a right-click.

Addressing Mouse Visibility

You might have noticed that when you move your mouse cursor into the MonoGame window, it disappears. This happens because, by default, MonoGame hides the mouse cursor to provide a clean gaming experience. While this can be useful for some games, it might not suit every situation, especially when you want to interact with the game window. Let's explore this issue and resolve it.

The Issue: Disappearing Mouse Cursor MonoGame hides the mouse cursor to prevent it from interfering with your game's visuals. While this is beneficial for creating immersive gaming experiences, it can be problematic when you want to interact with elements within the game window, such as buttons or text.

Resolution: Showing the Mouse Cursor To make the mouse cursor visible and responsive within your MonoGame window, you can add a simple line of code to your Game1 classes Initializer() method. By setting IsMouseVisible to true, you can ensure the cursor remains visible and behaves as expected:

protected override void Initialize()
{
	IsMouseVisible = true;
}

Defining Text Boundaries

When you want to enable mouse interactions specifically within the boundaries of your text, you need to define the width and height of that text. This allows you to accurately detect mouse clicks within the text area.

Here's how you can define these boundaries:

  1. Declare Integer Variables: In your game class (e.g., Game1.cs), declare two integer variables to store the width and height of your text:

    int textWidth;
    int textHeight;
  2. Calculate Text Dimensions: Inside your LoadContent method (usually located within the LoadContent region), calculate the dimensions of your text using the font.MeasureString method. For example:

    protected override void LoadContent()
    {
        // Other initialization code
    
        // Load your font
        font = Content.Load<SpriteFont>("Fonts/MyFont");
    
        // Calculate text width and height based on the loaded font and text string
        Vector2 textSize = font.MeasureString("Hello, World!");
        textWidth = (int)textSize.X;
        textHeight = (int)textSize.Y;
    
        // Other content loading code
    }
    

Refining Mouse Clicks

In your MonoGame project, you might want to refine mouse interactions, ensuring that the user's click specifically targets an element, like text, before triggering an action. This is a common requirement for many interactive applications. Let's address this issue and explain how to make mouse clicks meaningful by checking if they occur within the boundaries of the text.

The Issue: Clicks Everywhere By default, mouse clicks are detected anywhere within the game window, regardless of where the mouse cursor is positioned. This means that a click could happen outside of your text element, affecting the game's behavior when you might want it to be more precise.

Resolution: Checking Mouse Click Location To ensure that mouse clicks specifically target the text element, you can check the mouse's position against the boundaries of the text area. This way, you'll only trigger an action when the user clicks on the text itself.

Step 1: Determine Text Boundaries Before checking for mouse clicks, you need to establish the boundaries of your text element. These boundaries will help you identify whether a click occurs within the text area.

Rectangle textBounds = new Rectangle((int)position.X, (int)position.Y, textWidth, textHeight);

This line of code creates a rectangular area (textBounds) starting from the X and Y coordinates defined by position.X and position.Y, respectively. The width and height of the rectangle are determined by textWidth and textHeight, which should match the size of your text element. This rectangle serves as a boundary, and you can use it to check if a mouse click falls within the confines of the text element.

Check Mouse Click Position In your Update method, you can compare the mouse's position (represented by currentMouseState.X and currentMouseState.Y) with the text boundaries. If the mouse click falls within these boundaries, you can then execute your desired action.

Here's an example of how to implement this:

// Define the boundaries of your text element (adjust as needed)
Rectangle textBounds = new Rectangle((int)position.X, (int)position.Y, textWidth, textHeight);

// Check if the left mouse button was pressed and if the mouse click occurred within the text boundaries
if (currentMouseState.LeftButton == ButtonState.Pressed && previousMouseState.LeftButton == ButtonState.Released
    && textBounds.Contains(currentMouseState.X, currentMouseState.Y))
{
    // Code to adjust velocity here
}

In this code:

  • textBounds represents the rectangular area where your text is displayed.

  • We check if the left mouse button was pressed and if the mouse click position (represented by currentMouseState.X and currentMouseState.Y) is within textBounds.

  • If both conditions are met, you can execute the code to adjust velocity or any other action you desire.

Text as a Texture for Precise Mouse Interaction

In MonoGame, rendering text as a texture allows for precise mouse interaction with text elements in your game. This method ensures that mouse clicks are detected only when the cursor is positioned over the actual text pixels, even within complex text shapes. You likely already have this partly done, if not here's how to achieve this:

Load a SpriteFont

Declare a SpriteFont variable to hold the loaded font:

SpriteFont font;

What is a SpriteFont?

A SpriteFont in MonoGame is a specially prepared font that can be used to display text in your game. Unlike regular fonts, SpriteFonts are designed for rendering text as textures, making them ideal for creating interactive text elements. They are a fundamental tool for text-based game development in MonoGame.

Next, in the LoadContent method, load your chosen SpriteFont:

protected override void LoadContent()
{
    // Other initialization code

    // Load your font
    font = Content.Load<SpriteFont>("YourFontName");

    // Other content loading code
}

Replace "YourFontName" with the name of the SpriteFont file added to your MonoGame content project. This font will be used to render text.

Creating a Text Texture

Define a Texture2D to store the rendered text:

Texture2D textTexture;

Did you know a Texture2D represent a 2D image or texture that can be displayed on the screen? In MonoGame and similar frameworks, Texture2D objects are created, manipulated, and drawn to the screen using various graphics functions and techniques. They are a fundamental part of the graphics pipeline, enabling game developers to bring their visual ideas to life within the game world.

Now in the LoadContent() method initiate yourtextTexture and render the text onto it:

textTexture = new RenderTarget2D(GraphicsDevice, textWidth, textHeight);
Color[] data = new Color[textWidth * textHeight];
for (int i = 0; i < data.Length; i++)
{
    data[i] = Color.Transparent;
}
textTexture.SetData(data);

// Render the text onto the texture
spriteBatch = new SpriteBatch(GraphicsDevice);
GraphicsDevice.SetRenderTarget(textTexture);
GraphicsDevice.Clear(Color.Transparent);
spriteBatch.Begin();
spriteBatch.DrawString(font, "Hello, World!", Vector2.Zero, Color.White);
spriteBatch.End();
GraphicsDevice.SetRenderTarget(null);

Do not forget, in the Game1 class to update the textTexture to RenderTarget2D

RenderTarget2D textTexture;

Code review

  1. textTexture = new RenderTarget2D(GraphicsDevice, textWidth, textHeight);

    • This line creates a new Texture2D named textTexture.

    • Texture2D is a 2D image container in MonoGame, which we will use to store our rendered text.

    • GraphicsDevice is the device responsible for rendering graphics in MonoGame.

    • textWidth and textHeight are the dimensions of the texture, calculated based on the measured size of your text.

  2. Color[] data = new Color[textWidth * textHeight];

    • This line creates an array named data of type Color.

    • data will hold the color information for each pixel in the texture.

    • The size of the array is determined by multiplying textWidth and textHeight, which represents the total number of pixels in the texture.

  3. for (int i = 0; i < data.Length; i++)

    • This line starts a loop that iterates through all the pixels in the data array.

  4. data[i] = Color.Transparent;

    • Inside the loop, this line sets each pixel's color in the data array to transparent.

    • This effectively initializes the texture with transparent pixels.

  5. textTexture.SetData(data);

    • After the loop, this line sets the color data of the textTexture to the values stored in the data array.

    • It essentially populates the texture with the transparent pixels.

  6. spriteBatch = new SpriteBatch(GraphicsDevice);

    • This line creates a new SpriteBatch.

    • SpriteBatch is a MonoGame class used for efficiently rendering 2D graphics, including textures.

  7. GraphicsDevice.SetRenderTarget(textTexture);

    • This line sets the render target to textTexture.

    • In MonoGame, you can change the render target to which graphics are drawn. In this case, we're directing graphics output to our textTexture.

  8. GraphicsDevice.Clear(Color.Transparent);

    • This line clears the current render target (which is textTexture) with a transparent color.

    • It ensures that our texture starts with a transparent background.

  9. spriteBatch.Begin();

    • This line begins the SpriteBatch. It's the starting point for rendering sprites or text.

  10. spriteBatch.DrawString(font, "Hello, World!", Vector2.Zero, Color.White);

    • This line uses the SpriteBatch to draw text on the current render target (textTexture).

    • font is the loaded SpriteFont used to render the text.

    • "Hello, World!" is the text to be drawn.

    • Vector2.Zero represents the position where the text will be drawn, starting from the top-left corner.

    • Color.White is the color in which the text will be drawn.

  11. spriteBatch.End();

    • This line ends the SpriteBatch after drawing the text.

  12. GraphicsDevice.SetRenderTarget(null);

    • This line sets the render target back to the default, which is the screen.

    • After this line, any further rendering will appear on the game window as usual.

In summary, this code initializes a Texture2D, fills it with transparent pixels, sets it as the render target, draws text onto it using a SpriteBatch, and then resets the render target to the screen. This process allows you to render text with precise boundaries that match the actual text, enabling accurate mouse click detection.

IsMouseOnNonTransparentPixel Method

This method checks if the mouse click occurred on a non-transparent pixel within the textTexture. It verifies the pixel's alpha value to determine if it's greater than 0 (i.e., not transparent).

Insert the IsMouseOnNonTransparentPixel method within the same class (typically right below your existing methods) so that it's accessible and can be used in the rest of your code for handling mouse input and detecting clicks on non-transparent pixels within the textTexture.

private bool IsMouseOnNonTransparentPixel(Point mousePosition)
{
    Color[] pixelColorData = new Color[textWidth * textHeight];
    textTexture.GetData(pixelColorData);

    int x = mousePosition.X - (int)position.X;
    int y = mousePosition.Y - (int)position.Y;

    int index = x + y * textWidth;

    if (index >= 0 && index < pixelColorData.Length)
    {
        return pixelColorData[index].A > 0; // Check if pixel is non-transparent
    }

    return false;
}

Explanation of the Code:

  1. textTexture.GetData(pixelColorData);: This line retrieves the color data from the textTexture and stores it in the pixelColorData array. It effectively captures the color information of every pixel in the texture.

  2. int index = mousePosition.X + mousePosition.Y * textWidth;: Here, we calculate the index of the pixel in the pixelColorData array corresponding to the mouse's position. It takes into account the X and Y coordinates of the mouse position and the width of the texture.

  3. if (index >= 0 && index < pixelColorData.Length) { ... }: This condition checks whether the calculated index is within the valid range of indices for the pixelColorData array. It ensures that we're not accessing an out-of-bounds index.

  4. return pixelColorData[index].A > 0;: Finally, this line checks the alpha value (A component) of the color of the pixel at the calculated index. If the alpha value is greater than 0, it means the pixel is not transparent. In that case, the method returns true, indicating that the mouse click occurred on a non-transparent pixel. Otherwise, it returns false.

perform pixel-perfect collision detection

With the textTexture representing the text, perform pixel-perfect collision detection in the Update method:

if (currentMouseState.LeftButton == ButtonState.Pressed && previousMouseState.LeftButton == ButtonState.Released)
{
    // Check if the mouse click occurred within the text bounds and on a non-transparent pixel
    if (textBounds.Contains(currentMouseState.Position) && IsMouseOnNonTransparentPixel(currentMouseState.Position))
    {
        velocity *= 2.0f; // Speed up
    }
}

By following these steps, you can render text as a texture in MonoGame and enable precise mouse interaction with your text elements, enhancing the gameplay experience.

Full Code

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

namespace HelloWorldXNA
{
	public class Game1 : Game
	{
		GraphicsDeviceManager graphicsManager;
		SpriteBatch spriteBatch;
		RenderTarget2D textTexture;
		SpriteFont font;
		Random random;

		TimeSpan elapsedTime = TimeSpan.Zero;
		Vector2 position;
		Vector2 velocity;
		Color color;

		MouseState currentMouseState;
		MouseState previousMouseState;

		int ticks;
		int frameRate;
		int frameCounter;
		int textWidth;
		int textHeight;

		string text = "Click Me!";

		int[] possibleValues = new int[] { -1, 0, 1 };

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

			frameRate = 60;                                          // Adjust this value to manage frame rate
			frameCounter = 0;

			ticks = (int)((1.0 / frameRate) * 10_000_000);
			this.IsFixedTimeStep = true;
			this.TargetElapsedTime = TimeSpan.FromTicks(ticks);
		}

		protected override void Initialize()
		{
			IsMouseVisible = true;

			position = new Vector2(400, 600);
			velocity = new Vector2(2, 1);
			color = Color.White;
			Window.AllowUserResizing = true; // This was added last minute after the tutorial - allows window resizing
			base.Initialize();
		}

		protected override void LoadContent()
		{
			spriteBatch = new SpriteBatch(GraphicsDevice);
			font = Content.Load<SpriteFont>("Fonts/MyFont");

			// Calc. textWidth and textHeight based on the loaded font and text string
			Vector2 textSize = font.MeasureString(text);
			textWidth = (int)textSize.X;
			textHeight = (int)textSize.Y;

			// Create the textTexture
			textTexture = new RenderTarget2D(GraphicsDevice, textWidth, textHeight);         // Creates new texture with matching dimensions of text
			Color[] data = new Color[textWidth * textHeight];                            // Creates an array to store the pixel color of each pixel
			for (int i = 0; i < data.Length; i++)
			{
				data[i] = Color.Transparent;                                            // Initialize with transparent colors
			}
			textTexture.SetData(data);

			// Render the text onto the texture
			spriteBatch = new SpriteBatch(GraphicsDevice);
			GraphicsDevice.SetRenderTarget(textTexture);
			GraphicsDevice.Clear(Color.Transparent);
			spriteBatch.Begin();
			spriteBatch.DrawString(font, text, Vector2.Zero, Color.White);
			spriteBatch.End();
			GraphicsDevice.SetRenderTarget(null);
		}

		protected override void Update(GameTime gameTime)
		{
			float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;

			// Update Mouse States
			previousMouseState = currentMouseState;
			currentMouseState = Mouse.GetState();

			// Define the boundaries of your text element
			Rectangle textBounds = new Rectangle((int)position.X, (int)position.Y, textWidth, textHeight);

			// Detect left mouse button click
			if (currentMouseState.LeftButton == ButtonState.Pressed && previousMouseState.LeftButton == ButtonState.Released
				&& textBounds.Contains(currentMouseState.X, currentMouseState.Y))
			{
				if (textBounds.Contains(currentMouseState.Position) && IsMouseOnNonTransparentPixel(currentMouseState.Position))
				{
					velocity *= 1.25f; // Speed up
				}
			}

			// Detect right mouse button click
			if (currentMouseState.RightButton == ButtonState.Pressed && previousMouseState.RightButton == ButtonState.Released
				&& textBounds.Contains(currentMouseState.X, currentMouseState.Y))
			{
				if (textBounds.Contains(currentMouseState.Position) && IsMouseOnNonTransparentPixel(currentMouseState.Position))
				{
					velocity *= 0.5f; // Slow Down
				}
			}

			// Move text position
			position += velocity * elapsed * 200; // Multiply by a constant to control speed. E.g., 200

			// Bounce off right and left walls with a slight offset
			if (position.X <= 0 || position.X >= graphicsManager.PreferredBackBufferWidth - 200)
			{
				velocity.X *= -1f;  // Reverse and slightly increase speed
			}

			// Bounce off top and bottom walls with a slight offset
			if (position.Y <= 0 || position.Y >= graphicsManager.PreferredBackBufferHeight - 50)
			{
				velocity.Y *= -1f;  // Reverse and slightly increase speed
			}

			// Clamp position to make sure it stays within screen bounds
			position.X = MathHelper.Clamp(position.X, 0, graphicsManager.PreferredBackBufferWidth - 100);
			position.Y = MathHelper.Clamp(position.Y, 0, graphicsManager.PreferredBackBufferHeight - 50);

			// Change Color
			byte newG = (byte)((color.G + 200 * elapsed) % 256);

			// Update the color
			color.G = newG;
			if (color.G > 255) color.G = 0;

			frameCounter++;
			elapsedTime += gameTime.ElapsedGameTime;

			if (elapsedTime > TimeSpan.FromSeconds(1))
			{
				elapsedTime -= TimeSpan.FromSeconds(1);
				frameRate = frameCounter;
				frameCounter = 0;
			}

			base.Update(gameTime);
		}

		protected override void Draw(GameTime gameTime)
		{
			GraphicsDevice.Clear(Color.CornflowerBlue);

			spriteBatch.Begin();

			// Draw your entire scene, including text and any other elements
			spriteBatch.DrawString(font, text, position, color);
			// Add other elements drawing code here if needed

			spriteBatch.End();

			base.Draw(gameTime);
		}

		private bool IsMouseOnNonTransparentPixel(Point mousePosition)
		{
			Color[] pixelColorData = new Color[textWidth * textHeight];
			textTexture.GetData(pixelColorData);

			int x = mousePosition.X - (int)position.X;
			int y = mousePosition.Y - (int)position.Y;

			int index = x + y * textWidth;

			if (index >= 0 && index < pixelColorData.Length)
			{
				return pixelColorData[index].A > 0; // Check if pixel is non-transparent
			}

			return false;
		}
	}
}

Knowledge Check

  1. What is the purpose of declaring currentMouseState and previousMouseState variables in a MonoGame project?

  2. What does the setting IsMouseVisible to true in the Initialize method of a MonoGame project do?

  3. How can you check if a mouse click occurred within the boundaries of a text element in a MonoGame project?

  4. What is the purpose of rendering text as a texture in MonoGame, and how can you achieve this?

Interactive Challenges

Objective 1: Modify the MonoGame project to change the color of the displayed text when the left mouse button is clicked.

Instructions:

  1. Declare a new Color variable in your Game1 class to store the text color.

  2. In the LoadContent method, initialize the text color variable with an initial color (e.g., Color.White).

  3. In the Update method, check for a left mouse button click similar to the provided code:

    csharpCopy codeif (currentMouseState.LeftButton == ButtonState.Pressed && previousMouseState.LeftButton == ButtonState.Released)
    {
        // Change the text color to a new color (e.g., Color.Red)
        // Ensure the text color variable is updated here.
    }
  4. Update the Draw method to use the new text color when drawing the text.

  5. Test the project and observe how the text color changes when you click the left mouse button.

Objective 2: Implement a basic button interaction using text where the button changes color when hovered over and performs an action when clicked.

Instructions:

  1. Declare a new boolean variable (e.g., isButtonHovered) in your Game1 class to track whether the mouse cursor is over the text button.

  2. In the Update method, check if the mouse cursor is within the boundaries of the text button. You can use the textBounds rectangle and the mouse position.

  3. Update the isButtonHovered variable accordingly based on whether the cursor is over the button.

  4. Modify the Draw method to change the color of the text when isButtonHovered is true, indicating that the mouse cursor is over the button.

  5. Implement a left mouse button click check for the button. When the left mouse button is clicked and isButtonHovered is true, perform an action. For example, you can display a message in the console.

  6. Test the project and verify that the text button changes color when hovered over and performs an action when clicked.

Last updated