MonoGame / XNA鼠标偏移

时间:2016-02-16 05:44:18

标签: xna mouse offset monogame getstate

我正在尝试使用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 个答案:

答案 0 :(得分:0)

您的Menu班级正在创建Game1的新实例。这很可能不是您想要的,因为{app}的入口点会Game1实例化。 Game1实例的实例为TitleScreen,而实例又包含Menu类的实例,因此Menu应该没有业务创建自己的游戏。

创建此(其他)实例时,它会调用特定于平台的(Windows)方法,创建一个额外的窗口句柄(从不显示)并配置Mouse.WindowHandle

顺便说一句,手动设置WindowHandle does absolutely nothing in Monogame,所以所有这些来源都在谈论XNA。

所以,有几点评论:

  1. 您可能应该有一个包含当前屏幕的“屏幕管理器”类。在你的游戏类中有一个TitleScreen类型的字段很奇怪,它至少应该是基类型(Screen),这样游戏类就可以透明地绘制和更新每个屏幕。

  2. 如果您需要在任何地方引用游戏类,请不要实例化新游戏类,而是将其传递给构造函数。

  3. m_managerClass是一个字段的错误名称,实际上是Game。同时谷歌的C#命名约定。也许你甚至可能想要下载现有的单一游戏模板,例如检查一些samples online; NetRumble sample似乎实现了一个屏幕管理器。

  4. 删除Mouse.WindowHandle行,默认情况下应将其设置为您的唯一游戏窗口。

  5. tl; dr 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
         }
    }