2016-02-16 3 views
0

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

Я смотрел на других людей, которые имели ту же проблему, но не смогли ее решить. Я пробовал использовать 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(); 
    } 
} 

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

+0

Ссылка не найдена bruh. Добавьте свой код в свой вопрос. (Только соответствующий, минимальный образец) – NSNoob

+0

Извините, я не знал, что относится к проблеме. Я новичок в этом. –

+0

Можете ли вы разместить свою точку входа? 'Program.cs' или что-то такое, которое содержит метод' Main'. – Groo

ответ

0

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

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

И, кстати, установка WindowHandle вручную does absolutely nothing in Monogame, поэтому все эти источники упоминают, что речь идет о XNA.

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

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

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

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

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

Т.Л., др добавить 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 
    } 
} 
+0

Спасибо, Groo. Это исправило это. Я посмотрю на это больше сегодня вечером. Как вы можете видеть, я в настоящее время использую оператор switch в своем классе game1, который переключает публичное перечисление GameState, изменяя текущий экран. Если бы я должен был создать класс диспетчера экрана, я должен просто переместить оператор switch в этот класс? Следуя этой серии, вы узнаете больше https://www.youtube.com/watch?v=TOAGy2S8MC8. Также собираемся раскрыть мои соглашения об именах C# –

+0

@ Коди: идея OOP (т. Е. Наличие одного базового класса 'Screen' или' IScreen') заключается в том, чтобы удалить необходимость в этом операторе switch. Это означает, что у вас есть поле «текущий экран» (например, «currentScreen»), и вы устанавливаете его на какой-либо экземпляр экрана (например, «titleScreen»). Если все экраны наследуются от «Экран», то ваши методы update/draw не заботятся о том, какой экран он имеет, то есть у вас есть только «currentScren.Update (gameTime)» и «currentScreen.Draw (gameTime);», без переключатель. – Groo

+0

Это также означает, что вам не нужна отдельная переменная «игровое состояние» (по крайней мере, не для экранов, возможно, для некоторого фактического конечного автомата на одном экране), поскольку ваше состояние (в терминах текущего экрана) полностью определяется на что указывает «currentScreen». – Groo