XNA Framework - Попытка корректно перегрузить System.EventHandler - PullRequest
1 голос
/ 02 декабря 2011

Я новичок в C # и XNA. В настоящее время я работаю над меню опций для игры. Меню параметров делает следующее:

  1. Звук (вкл или выкл)
  2. Яркость (Увеличение / Уменьшение)
  3. Табло (Просмотр 5 наивысших баллов)
  4. Элементы управления (показывает, как использовать элементы управления)

В Интернете я нашел код, который обрабатывает яркость, но он был реализован с использованием класса Game.cs. Я пытаюсь использовать этот код в своем классе OptionsMenuScreen.cs (который наследуется от Gamescreen.cs).

Проблема, с которой я столкнулся, заключается в том, что мой EventHandler с именем BrightnessSelected перегружен некоторыми дополнительными параметрами для обработки сенсорного ввода, чтобы пользователь мог осветлить / затемнить экран. Эта перегрузка вызывает некоторые проблемы, поскольку она основана на шаблоне, предоставленном в System.EventHandler, который принимает только один параметр.

Как я могу получить этот шаблон, чтобы я мог его перегрузить? Или есть другой способ сделать это? Я действительно надеюсь, что это имеет смысл, и что я изложил свою проблему не запутанным способом. Всем спасибо!

Код ниже:

#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Xna.Framework.Media;
#endregion

namespace Platformer
{
/// <summary>
/// The options screen is brought up over the top of the main menu
/// screen, and gives the user a chance to configure the game
/// in various hopefully useful ways.
/// </summary>
class OptionsMenuScreen : MenuScreen
{

    #region Fields
    GraphicsDevice graphicsDevice;
    SpriteBatch spriteBatch;
    Texture2D whiteTexture;
    int brightnessStart;
    int contrastStart;
    BlendState brightnessBlend;
    BlendState contrastBlend;

    MenuEntry sound1;
    MenuEntry brightness;
    MenuEntry scoreboard;
    MenuEntry controls;

    static bool soundonoff = true;

    #endregion

    #region Initialization

    /// <summary>
    /// Constructor.
    /// </summary>
    public OptionsMenuScreen()
        : base("Options")
    {
        // Create our menu entries.
        sound1 = new MenuEntry(string.Empty);
        brightness = new MenuEntry(string.Empty);
        scoreboard = new MenuEntry(string.Empty);
        controls = new MenuEntry(string.Empty);

        SetMenuEntryText();

        // Hook up menu event handlers.
        brightness.Selected += brightnessSelected;
        sound1.Selected += sound1Selected;
        scoreboard.Selected += scoreboardSelected;
        controls.Selected += controlsSelected;

        // Add entries to the menu.
        MenuEntries.Add(sound1);
        MenuEntries.Add(brightness);
        MenuEntries.Add(controls);
        MenuEntries.Add(scoreboard);
    }

    protected void Initialize()
    {
        // TODO: Add your initialization logic here


        brightnessStart = 255;
        contrastStart = 128;

        brightnessBlend = new BlendState();
        brightnessBlend.ColorSourceBlend = brightnessBlend.AlphaSourceBlend = Blend.Zero;
        brightnessBlend.ColorDestinationBlend = brightnessBlend.AlphaDestinationBlend            
        = Blend.SourceColor;

        contrastBlend = new BlendState();
        contrastBlend.ColorSourceBlend = contrastBlend.AlphaSourceBlend = Blend.DestinationColor;
        contrastBlend.ColorDestinationBlend = contrastBlend.AlphaDestinationBlend = `Blend.SourceColor;`
    }

    public virtual void LoadContent()
    {
        whiteTexture = new Texture2D(graphicsDevice, 1, 1);
        whiteTexture.SetData<Color>(new Color[] { Color.White });
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(graphicsDevice);
    }

    public virtual void Draw(GameTime gameTime)
    {
        graphicsDevice.Clear(Color.CornflowerBlue);

        // TODO: Add your drawing code here
        spriteBatch.Begin(SpriteSortMode.Immediate, brightnessBlend);
        spriteBatch.Draw(whiteTexture, new Rectangle(0, 0, 480, 800), new Color(brightnessStart, `brightnessStart, brightnessStart, 255));`
        spriteBatch.End();

        spriteBatch.Begin(SpriteSortMode.Immediate, contrastBlend);
        spriteBatch.Draw(whiteTexture, new Rectangle(0, 0, 480, 800), new Color(contrastStart, `contrastStart, contrastStart, 255));`
        spriteBatch.End();

        graphicsDevice.BlendState = BlendState.Opaque;

        base.Draw(gameTime);
    }
    /// <summary>
    /// Fills in the latest values for the options screen menu text.
    /// </summary>
    void SetMenuEntryText()
    {
        sound1.Text = "Sound " + (soundonoff ? "on" : "off");
        brightness.Text = "Brightness ";
        scoreboard.Text = "Scoreboard ";
        controls.Text = "Controls ";
    }

    #endregion

    #region Handle Input

    /// <summary>
    /// Event handler for when the Sound menu entry is selected.
    /// </summary>
    /// 
    protected void Update(GameTime gameTime)
    {

        foreach (TouchLocation t in TouchPanel.GetState())
        {
            if ((t.State == TouchLocationState.Pressed)
                    || (t.State == TouchLocationState.Moved))
            {
                if (t.Position.Y <= 400)
                    brightnessSelected(t, ref brightnessStart);
            }
            else
                brightnessSelected(t, ref contrastStart);
        }
    }
    void sound1Selected(object sender, PlayerIndexEventArgs e)
    {
        soundonoff = !soundonoff;
        SetMenuEntryText();
    }
    /// <summary>
    /// Event handler for when the Brightness menu entry is selected.
    /// </summary>
    void brightnessSelected(object sender, PlayerIndexEventArgs e, TouchLocation t, ref int adjustee)
    {
        if (t.Position.X < 240)
            adjustee -= 3;
        else
            adjustee += 3;

        adjustee = Math.Max(Math.Min(adjustee, 255), 0);
        SetMenuEntryText();
    }

    /// <summary>
    /// Event handler for when the Scoreboard menu entry is selected.
    /// </summary>
    void scoreboardSelected(object sender, PlayerIndexEventArgs e)
    {
        //need to find a way to transition to HighScoreScreen.cs here
        //ScreenManager.AddScreen(new HighScoreScreen(), e.PlayerIndex);
        SetMenuEntryText();
    }

    /// <summary>
    /// Event handler for when the Control menu entry is selected.
    /// </summary>
    void controlsSelected(object sender, PlayerIndexEventArgs e)
    {
        //ScreenManager.AddScreen(new ControlScreen(), e.PlayerIndex);
        SetMenuEntryText();
    }

    #endregion
}
}

1 Ответ

2 голосов
/ 02 декабря 2011

Вы не можете передать ref int adjustee обработчику события и ожидать, что его значение будет возвращено вызываемому объекту.Обработчики событий просто не работают таким образом.Думайте об этом больше как о обратном вызове, который может ответить на событие.

Далее вам нужно создать подкласс EventArgs и добавить к нему свои собственные данные, например, так:

public class MyEventArgs : EventArgs
{
    private string msg;

    public MyEventArgs( string messageData ) 
    {
        msg = messageData;
    }
    public string Message { 
        get { return msg; } 
        set { msg = value; }
    }
}

См. Эту статьюОб обработчиках и аргументах: http://msdn.microsoft.com/en-us/library/db0etb8x.aspx

В вашем случае вам нужно посетить код для MenuEntry и отредактировать тип TEventArgs, который он передает (в этом случае он использует PlayerIndexEventArgs).Вы можете снова создать подкласс PlayerIndexEventArgs или просто переопределить его для своего собственного типа.Я не знаю, что это за класс XNA, и вам, возможно, придется снова подумать о дизайне, если он не имеет смысла.

Когда вы закончите, у вас должно получиться что-то вроде

int _brightness;

void brightnessSelectedEventHandler(object sender, BrightnessEventArgs e)
{
    if (e.touch != null && e.touch.position != null)
    {
        const int TOUCH_POS_THRESHOLD = 240; // this is part of UI and should really be somewhere else, but put it here for convenience
        if (e.touch.position.x < TOUCH_POS_THRESHOLD 
            adjustBrightness(-3);
        else
            adjustBrightness(3);
    }
    SetMenuEntryText();
}

void adjustBrightness(int offset)
{
    _brightness += offset;
}

Обратите внимание, что здесь я просто поместил переменную-член _brightness в ваш класс.Вот как вы «реагируете» на событие - кладете куда-нибудь данные или корректируете значение.Вам нужно подумать о том, где находятся данные и где они должны быть инкапсулированы с точки зрения ОО.

Удачи.

...