Мыши MonoGame/XNA

Я пытаюсь использовать Mouse.GetState() для моего выбора меню. В настоящее время он будет выделен только, если я наведу курсор на область слева и вверх от того места, где находится меню. Я использовал DrawString для отображения координат мышки и обнаружил, что точка 0,0 находится не в левом верхнем углу моего монитора или в левом верхнем углу игрового окна. Это было где-то около 100,100 пикселей от верхнего левого угла экрана. Кроме того, 0,0 балла перемещается каждый раз, когда я запускаю программу.

Я смотрел на других людей, у которых была такая же проблема, но не удалось ее решить. Я пытался с помощью Mouse.WindowHandle = this.Window.Handle; в моем Initialize() но это не ничего. У меня есть два монитора, и когда я запускаю игру в полноэкранном режиме, она открывается на моем втором мониторе, поэтому я отключил его, но проблема остается.

вот ссылка на мой код http://pastebin.com/PNaFADqp

Game1 класс:

public class Game1 : Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    SpriteFont spriteFont;

    public const int WINDOW_HEIGHT = 800;
    public const int WINDOW_WIDTH = 600;

    public int tree;

    public TitleScreen titleScreen;
    public SATDemo satDemo;
    public SeparatingAxisTest separatingAxisTest;
    public SATWithAABB sATWithAABB;

    GameState currentState;

    public static Dictionary<string, Texture2D> m_textureLibrary = new Dictionary<string, Texture2D>();
    public static Dictionary<string, SpriteFont> m_fontLibrary = new Dictionary<string, SpriteFont>();

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

    protected override void Initialize()
    {
        Mouse.WindowHandle = this.Window.Handle;
        //enable the mousepointer
        IsMouseVisible = true;
        currentState = GameState.TitleScreen;
        //sets the windows mouse handle to client bounds handle

        base.Initialize();
    }

    public void RequestSATDemo()
    {
        currentState = GameState.RequestSATDemo;
    }

    protected override void LoadContent()
    {
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);


        m_textureLibrary.Add("Pixel", Content.Load<Texture2D>("White_Pixel"));
        m_fontLibrary.Add("Font", Content.Load<SpriteFont>("MotorwerkOblique"));

        titleScreen = new TitleScreen();
        satDemo = new SATDemo();
        separatingAxisTest = new SeparatingAxisTest();
        sATWithAABB = new SATWithAABB();
     }

    public void RequestSeparatingAxisTest()
    {
        currentState = GameState.SeparatingAxisTest;
    }

    public void RequestSATWithAABB()
    {
        currentState = GameState.SATWithAABB;
    }

    protected override void Update(GameTime gameTime)
    {
        MouseTestState = Mouse.GetState();
        switch (currentState)
        {
            case GameState.TitleScreen:
                {
                    titleScreen.Update(gameTime);
                    break;
                }
            case GameState.SeparatingAxisTest:
                {
                    separatingAxisTest.Update(gameTime);
                    break;
                }
            case GameState.SATWithAABB:
                {
                    sATWithAABB.Update(gameTime);
                    break;
                }
            case GameState.Exit:
                {
                    Exit();
                    break;
                }
            default:
                {
                    titleScreen.Update(gameTime);
                    break;
                }
        }

        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
        spriteBatch.Begin();

        spriteBatch.DrawString(m_fontLibrary["Font"], MouseTestState.ToString(), new Vector2(0, 0), Color.White);
        switch (currentState)
        {
            case GameState.TitleScreen:
                {
                    titleScreen.Draw(spriteBatch, spriteFont);
                    break;
                }
            case GameState.SeparatingAxisTest:
                {
                    separatingAxisTest.Draw(gameTime, spriteBatch);
                    break;
                }
            case GameState.SATWithAABB:
                {
                    sATWithAABB.Draw(gameTime, spriteBatch);
                    break;
                }
            case GameState.Exit:
                {
                    Exit();
                    break;
                }
            default:
                {
                    titleScreen.Update(gameTime);
                    break;
                }
        }

        spriteBatch.End(); 
        base.Draw(gameTime);
    }
}

Класс TitleScreen:

public class TitleScreen : Screen
{ 
    List<Button> buttonList = new List<Button>();
    public Menu mainMenu;
    public TitleScreen()
    {
        mainMenu = new Menu(new Vector2(200, 100), buttonList, 0); 
        buttonList.Add(new PushButton("Separating Axis Test"));
        buttonList.Add(new PushButton("SAT With AABB"));
        buttonList.Add(new PushButton("Awesome"));
        buttonList.Add(new PushButton("Awesomere"));
        buttonList.Add(new PushButton("Awesomere")); 
    }

    public override void Update(GameTime gametime)
    {
        mainMenu.Update(gametime);
    }

    public void Draw(SpriteBatch sB, SpriteFont sF)
    {
        mainMenu.Draw(sB, sF); 
    } 
}

Класс PushButton:

public class PushButton : Button
{
    string m_text;
    SpriteFont m_font;
    Color m_static, m_onClick, m_onHover;
    Texture2D m_sprite2D, m_onClick2D;

    static public int Pbuttoncount;

    //click processing
    bool m_clickedInside =  false,
         m_releasedInside = false,
         m_OnClicked =      false,
         selected =         false;

    Rectangle drawRectangle;

    public PushButton(string Text)
    {
        m_text = Text;

        drawRectangle = new Rectangle((int)Menu.m_position.X, (int)Menu.m_position.Y + (15 * Pbuttoncount), 200, 15);
        ButtonRegion = new Rectangle((int)Position.X, (int)Position.Y, 200, 15);
        Pbuttoncount++;
    }

    public PushButton(Rectangle ButtonRegion, SpriteFont Font, string Text, Color Static, Color OnClick, Color OnHover)
    {
        m_buttonRegion = ButtonRegion;
        m_font = Font;
        m_text = Text;
        m_static = Static;
        m_onClick = OnClick;
        m_onHover = OnHover;
        // drawRectangle = ButtonPosition(m_buttonRegion);
     }

    public PushButton(Rectangle ButtonRegion, Texture2D Sprite2D, Texture2D OnClick2D)
    {
        m_buttonRegion = ButtonRegion;
        m_sprite2D = Sprite2D;
        m_onClick2D = OnClick2D;
        //drawRectangle = ButtonPosition(m_buttonRegion);
    }

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

        selected = MouseState(drawRectangle, currentMouse);
        m_clickedInside = ClickInside(currentMouse, m_lastMouseState);
        ReleaseInside(currentMouse, m_lastMouseState);

        if (selected && m_clickedInside && m_releasedInside)
            m_OnClicked = true;
        else
            m_OnClicked = false;

        m_lastMouseState = currentMouse;
    }

    public override void Draw(SpriteBatch spriteBatch, SpriteFont spriteFont, int buttonCount, Vector2 Position)
    {
        spriteBatch.Draw(Game1.m_textureLibrary["Pixel"], new Rectangle((int)Position.X + 10, (int)(Position.Y + 15 * buttonCount), 180, 15), Color.Wheat);

        if (selected)
            spriteBatch.DrawString(Game1.m_fontLibrary["Font"], m_text, new Vector2(Position.X + 15, Position.Y + 15 * buttonCount), Color.Orange);
        else
            spriteBatch.DrawString(Game1.m_fontLibrary["Font"], m_text, new Vector2(Position.X + 15, Position.Y + 15 * buttonCount), Color.Black);
    }
}

Класс меню:

public class Menu
{
    List<Button> m_buttonList;
    float m_transparency;
    public int n = 0;
    public Rectangle buttonRegion, m_menuRegion, m_dimensions;
    static public Vector2 m_position;
    int m_WINDOW_HEIGHT = Game1.WINDOW_HEIGHT;
    int m_WINDOW_WIDTH = Game1.WINDOW_WIDTH;
    private Game1 m_managerClass;

    public Menu(Vector2 Position, List<Button> ButtonList, float Transparency)
    {
        m_position = Position;
        m_buttonList = ButtonList;
        m_transparency = Transparency;
        m_managerClass = new Game1();
    }

    public Rectangle MenuRegion
    {
        get { return m_menuRegion; }
        set { m_menuRegion = value; }
    }

    static public Vector2 Position
    {
        get { return m_position; }
    }

    public void Update(GameTime gametime)
    {
        for (int i = 0; i < m_buttonList.Count; i++)
        {
            m_buttonList[i].Update(gametime);
            if (m_buttonList[0].OnClicked)
            {
                SeperatingAxisTest();
            }
        }
    }

    public void Draw(SpriteBatch sB, SpriteFont sF)
    {
        sB.Draw(Game1.m_textureLibrary["Pixel"], new Rectangle((int)m_position.X - 5, (int)m_position.Y - 10, (m_buttonList[0].ButtonRegion.Width + 10), (m_buttonList[0].ButtonRegion.Height * m_buttonList.Count) + 20), Color.Blue);
        for (int i = 0; i < m_buttonList.Count; i++)
        {
            m_buttonList[i].Draw(sB, sF, i, new Vector2(Position.X, Position.Y));
        } 
    }

    private void SeperatingAxisTest()
    {
        m_managerClass.RequestSeparatingAxisTest();
    }
}

Класс программы:

public static class Program
{
    [STAThread]
    static void Main()
    {
        using (var game = new Game1())
            game.Run();
    }
}

Позвольте мне знать, если вам нужно что-нибудь еще. Я все еще учусь и продам свою душу тебе за ответ.

1 ответ

Решение

Ваш Menu класс создает новый экземпляр Game1, Это, скорее всего, не то, что вы хотите, так как Game1 создается в точке входа для вашего приложения. Game1 Экземпляр имеет экземпляр TitleScreenкоторый в свою очередь имеет экземпляр Menu класс, так что Menu не должно быть бизнеса, создающего собственную игру.

Когда этот (другой) экземпляр создается, он вызывает специфичные для платформы (Windows) методы, создает дополнительный дескриптор окна (который никогда не отображается) и настраивает Mouse.WindowHandle,

И кстати, настройка WindowHandle вручную ничего не делает в Monogame, поэтому все эти источники упоминают, что речь идет о XNA.

Итак, есть несколько замечаний:

  1. Вероятно, у вас должен быть класс "менеджер экрана", который содержит текущий экран. Странно иметь поле типа TitleScreen в вашем игровом классе он должен быть как минимум базового типа (Screen), так что игровой класс рисует и обновляет каждый экран прозрачно.

  2. Если вам нужна ссылка на класс игры в любом месте, не создавайте новый экземпляр, а скорее передавайте его через конструктор.

  3. m_managerClass это плохое имя для поля, которое на самом деле Game, Также Google для C# именования. Возможно, вам даже захочется скачать существующий шаблон игры с монограммой, например, проверить некоторые примеры в Интернете; В примере NetRumble реализован менеджер экрана.

  4. Удалить Mouse.WindowHandle линия, это должно быть установлено в ваше единственное окно игры по умолчанию.

TL; д-р добавить Game1 в качестве параметра, где бы он вам ни понадобился (но только там, где он вам нужен).

abstract class Screen
{
     private readonly Game1 _game;
     public Game1 Game 
     { get { return _game; } }

     public Screen(Game1 game)
     {
         _game = game;
     }
}

class TitleScreen : Screen 
{
     public TitleScreen(Game1 game)
         : base(game)
     { ... }
}

class Menu 
{
     private readonly Screen _screen;

     public Menu(Screen parentScreen, Vector2 pos, List<Button> list, float alpha)
     {
          _screen = parentScreen;
          ...

          // if you need the game instance, just use _screen.Game
     }
}
Другие вопросы по тегам