1
votes

Okay so I'm starting to make a main menu for a small flash game and to do this I want to use the mouse to click on buttons etc. I have a button class in which I create two rectangles: a rectangle for the button and a rectangle for the mouse based on its X and Y, 1 pixel by 1 pixel. I use Rectangle.Intersects to check if they are touching before seeing if left mouse button is down. Problem is, the thing the mouse position is relative to changes every time so no matter where the mouse button is on the screen, it's never the same co-ordinates as in a different build in that exact same position. I seriously just need ideas now as I'm running out. If I didn't explain it very well or you need further details to help please ask - I WOULD BE SO GRATEFUL.

  • Will post back if I find an answer

Update - Okay here's the button class

    class OnScreenButton
    {
    public Texture2D texture;
    Vector2 position;
    Rectangle rectangle;

    Color colour = new Color(255, 255, 255, 255);

    public Vector2 size;

    public OnScreenButton(Texture2D newtexture, GraphicsDevice graphics)
    {
        texture = newtexture;

        // ScreenW = 500, ScreenH = 600
        // Img W = 80, Img H = 20
        size = new Vector2(graphics.Viewport.Width / 10, graphics.Viewport.Height / 30);
        size = new Vector2(texture.Width, texture.Height);

    }

    bool down;
    public bool isClicked;

    public void Update(MouseState mouseState)
    {
        rectangle = new Rectangle((int)position.X, (int)position.Y, (int)size.X, (int)size.Y);

        Rectangle mouseRectangle = new Rectangle(mouseState.X, mouseState.Y, 1, 1);

        if (mouseRectangle.Intersects(rectangle))
        {
            if (colour.A == 255)
            {
                down = false;
            }
            if (colour.A == 0)
            {
                down = true;
            }
            if (down)
            {
                colour.A += 3;
            }
            else
            {
                colour.A -= 3;
            }
            if (mouseState.LeftButton == ButtonState.Pressed)
            {
                isClicked = true;
            }

        }
        else if (colour.A < 255)
        {
            colour.A += 3;
            isClicked = false;
            colour.A = (255);
        }
    }

    public void SetPosition(Vector2 newPos)
    {
        position = newPos;
    }

    public void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(texture, rectangle, colour);
    }
    }
    }

(Sorry for weird formatting, brand new to stack overflow and the posting is still a little confusing) Here is some other code I think is relevent...

Game.1 initializing stuff

GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;

    protected override void Initialize()
    {
        // TODO: Add your initialization logic here
        Mouse.WindowHandle = Window.Handle;
        base.Initialize();
    }

    public Main()
    {
        graphics = new GraphicsDeviceManager(this);

        Content.RootDirectory = "Content";
    }

    KeyboardState keyboardState;
    MouseState mouseState;

Main menu update routine...

private void UpdateMainMenu(GameTime gameTime)
    {
        // Button options
        if (buttonPlay.isClicked == true)
        {
            CreateNewGame();
            currentGameState = GameState.playing;
        }
        buttonPlay.Update(mouseState);

        if (buttonExit.isClicked == true)
        {
            this.Exit();
        }
        buttonExit.Update(mouseState);

        // Press enter to play
        if (keyboardState.IsKeyDown(Keys.Enter))
        {
            CreateNewGame();
            currentGameState = GameState.playing;
        }
    }

Here's thee draw routine for main menu...

public void DrawMainMenu()
    {
        spriteBatch.Draw(mainMenuBackground, new Vector2(0, 0), Color.White);
        buttonPlay.Draw(spriteBatch);
        buttonExit.Draw(spriteBatch);
        spriteBatch.DrawString(playerAmmoFont, String.Format("{0}", mouseState), new Vector2(0, 0), Color.White);
    }

okay that's all I can think of

UPDATE - Okay so I know a few things that aren't the problem... The whole of my button class is fine, I made a new project and inserted all the relevant code into it and it worked absolutely perfectly so I'm starting to think its something to do with the code positioning and the graphics device stuff although I still don't have a clue how to fix it.

  • the window appears at the same spot every time
  • there is no pattern to the change in coordinates at all
  • this is really annoying

UPDATE - OKAY. I spent a long time writing down the coordinates that I got each time I ran the code and stuck to cursor in the top right corner of the screen. Here is what I got.

  • (-203, -225)
  • (-253, -275)
  • (-53, -75)
  • (-103, -125)
  • (-153, -175)
  • (-203, -225)
  • (-253, -275)
  • (-53, -75)
  • (-103, -125)
  • (-153, -175)
  • (-203, -225)
  • (-253, -275)
  • (-53, -75)
  • (-103, -125)
  • (-153, -175)
  • (-203, -225)
  • (-253, -275)
  • (-53, -75)
  • (-103, -125)
  • (-153, -175)
  • (-203, -225)
  • (-78, -100)
  • (-128, -150)
  • (-178, -200)
  • (-228, -250)
  • (-28, -50)
  • (-53, -75)
  • (-103, -125)
  • (-153, -175) < AND FROM HERE THE PATTERN LOOPS ROUND.

I just don't get how the same code can execute a different bug on different executions like this.

Also, mouse.Wheel doesn't go up or down whereas it works on the project that I made to test the relevant code where the mouse position was relevant to the top left pixel of the game window.

UPDATE - EVEN MORE DAMN COMPLICATIONS - So I just rand it a few times again and the offset values are offset... the increase is the same but I got values like (-178, -200) then (-228, -250). I have also discovered that the mouse is not relative to the game window what so ever, if I jam the mouse in the top right corner of the screen and check the coordinates, then move the game window and do the same again, the coordinates don't change. Please please please help me, or tell me if I'm being stupid, or something. Thanks.

2
Can't tell anything without code.deathismyfriend
Code would help, and it is not flash if it is in XNA :PCyral
Yeah sorry, you know what I mean though :Pgeorgeous
okay I fixed it, I created a new instance of Main.cs, oops #noobgeorgeous
I am face-palming reading this. I want to delete this question but will leave it for historical reasons. "a small flash game"; I was using XNA/C#.georgeous

2 Answers

0
votes

The mouse coordinates are relative to the monitor. Here is my general button class to try and work for your situation.

public class Button
{  
    public event EventHandler<EventArgs> Clicked;

    public Vector2 Position { get; set;}

    public Texture2D Texture { get; set;}

    public Color Tint { get; set; }

    public float Scale { get; set; }
    public float Rotation { get; set; }        

    public int Width
    {
        get
        {
            if (texture == null)
                return 0;
            else
                return texture.Width;
        }
    }

    public int Height
    {
        get
        {
            if (texture == null)
                return 0;
            else
                return texture.Height;
        }
    }

    private void OnClick()
    {
        if (Clicked != null)
            Clicked(this, EventArgs.Empty);
    }

    public Button(Vector2 position, Texture2D texture)
        : base(parent)
    {
        Position = position;      
        Texture = texture;   

        Tint = Color.White; 

        Scale = 1.0f;
        Rotation = 0.0f;  
    }

    public bool HandleClick(Vector2 vector)
    {
        if (vector.X >= Position.X)
        {
            if (vector.X <= Position.X + Width)
            {
                if (vector.Y >= Position.Y)
                {
                    if (vector.Y <= Position.Y + Height)
                    {
                        OnClick();
                        return true;
                    }
                }
            }
        }

        return false;
    }

    public bool HandleEntered(Vector2 vector)
    {
        if (vector.X >= Position.X)
        {
            if (vector.X <= Position.X + Width)
            {
                if (vector.Y >= Position.Y)
                {
                    if (vector.Y <= Position.Y + Height)
                    {
                        return true;
                    }
                }
            }
        }

        return false;
    }

    public override void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(Texture, Position, null, Tint, Rotation, Vector2.Zero, Scale, SpriteEffects.None, 0.0f); 
    }

Declare a button:

Button btn = new Button(position where you want the button, texture for the button);

btn.Clicked += () => { /* Handle button clicked code here */ };

In your update method inside your main game:

public void Update (GameTime gameTime)
{
    MouseState mouseState = Mouse.GetState();

    if(mouseState.LeftButton == ButtonState.Pressed) // check if mouse is clicked
    {
        btn.HandleClicked(new Vector2(mouseState.X, mouseState.Y)); // If true then the button clicked event will fire
        // Here you can also change the color of the button if the button is currently clicked
    }

    // Here you can change the color of the button if the mouse is hover over the control
    // Example: 
    btn.Tint = btn.HandleEntered(new Vector2(mouseState.X, mouseState.Y)) ? Color.White * 0.75f : Color.White;
}

Note: You can also use a rectangle for the button to adjust its size instead of strictly using the textures dimensions. Hope this gives some insight.

0
votes

So here's what was going on: I had a bullet class in my game for every bullet shot. In this class I check whether the bullets hits nothing, hits the asteroid, or destroys the asteroids. If the latter is true then I would increment playerScore by 5. PlayerScore was a Game1 attribute so I thought the easiest way to do this would be to create a new Game1 in bullet.cs to allow me to refer to the variable. Deleting the "Main mainGame = new Main():" in Bullet.cs fixed this issue and I think the issue was coming from a new graphics device being made every single time I fired a single bullet.