Sign in to follow this  

XNA: update game service ??

This topic is 2841 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi everyone I have created a little game using the XNA framework.. I am currently trying to clean up my code, but I am having a little trouble. My game consists of many components which all needs to know the keyboard- and mouse state, but to save processing time i would like to just get these states ONCE per update cycle. I have tried adding these states as game.service's in my games main file (Game1.cs), getting the states each time the update is run, and then getting the services in each of the components which needs the states. /------------------------------------------------------------------------- Game1.cs public class Game1 : Microsoft.Xna.Framework.Game { . . private KeyboardState keyboardState; private MouseState mouseState; . . protected override void LoadContent() { Services.AddService(typeof (KeyboardState), keyboardState); Services.AddService(typeof(MouseState), mouseState); . . } protected override void Update(GameTime gameTime) { keyboardState = Keyboard.GetState(); mouseState = Mouse.GetState(); . . } . . } /---------------------------------------------------------------------------- SomeGameComponent { . . private KeyboardState keyboardState; private MouseState mouseState; . . public override void Update(GameTime gameTime) { mouseState = (MouseState)Game.Services.GetService(typeof(MouseState)); keyboardState = (KeyboardState)Game.Services.GetService(typeof(KeyboardState)); . . } /----------------------------------------------------------------------------- I Hope this makes sence.. I cant make this work, since the states i get from my game service dont update.. So my question is, is there a way to update your game services, or do i really have to get the mouse and keyboard states in every component that uses them?? (NB. these arent the only objects i would like shared, but also stuff like my player object and enemyManager). Yours sincerly Anders Nysom

Share this post


Link to post
Share on other sites
Are you sure it's not being updated, or is it just being updated after all your other components? If that is the case you should be able to bump its priority.

You could also make an instance class as pass it as a parameter to all your components.

Personally, as much as I love OO programming, sometimes things just need to get done. I use static classes with static methods (not singletons).

Share this post


Link to post
Share on other sites
Quote:
Original post by BLiTZWiNG
Personally, as much as I love OO programming, sometimes things just need to get done. I use static classes with static methods (not singletons).


Agreed. There's no need to make the state classes services.

Share this post


Link to post
Share on other sites

Aside from the OO concerns, I think the problem is that you're not treating your variables quite the right way. Updating your local variables (the private class members) will not update the values in Services. They're different variables, so you'd have to assign the new values to the ones in Services explicitly. Unfortunately there is no UpdateService method, so your only recourse to store these states directly is to Remove/Add them each frame, which is not something you want to be doing.

Instead the Services architecture, as I understand it, is made to store service providers. There are no set rules for what makes up a service provider, but it'd typically be an object you'd query to get the information you want. For example, you could write a InputStateProvider (verbatim, might not compile):


public class InputStateProvider
{
private MouseState ms = new MouseState();
public MouseState MouseState { get { return ms; }}

private KeyboardState kbs = new KeyboardState();
public KeyboardState KeyBoardState{ get { return kbs; }}

public void Update()
{
ms = Mouse.GetState();
kbs = Keyboard.GetState();
}
}



Then in your Game class you stick it in like:


public class SomeGame : Microsoft.Xna.Framework.Game
{
private InputStateProvider isp = new InputStateProvider();

// The constructor or Initialize is a better place
// to do this, since this will effectively re-add
// the service whenever your device has been lost.
protected override void LoadContent()
{
Services.AddService(typeof(InputStateProvider), isp);
}

protected override void Update(GameTime gameTime)
{
// Note that this order is important. It will make
// sure the service provider is updated before any
// GameComponents hosted in the Game's Components
isp.Update();
base.Update(gameTime);
}



Now in your GameComponents or Game you can call:


InputStateProvider isp = Game.Services.GetService(typeof(InputStateProvider)) as InputStateProvider;
if (isp != null)
{
// do stuff with the input
if (isp.KeyboardState.IsKeyDown(Keys.Space)) DoSomething();
}



Now before anyone says this is a detour, it obviously is. But it is also quite a powerful mechanism to make things available throughout your game. Even in this simple usecase it can be made to be very handy by for example including an IsInputHandled boolean. That would allow GameComponents to check if some other component already acted on the input and they should ignore it this frame.

Share this post


Link to post
Share on other sites
Thank you very much for your great answer, you have been very helpfull!

Now that i know that i cant update the services, the idea of the inputStateProvider is exactly what im looking for :)
I am going to implement this solution as soon as I get home.

Share this post


Link to post
Share on other sites

Glad to hear it was of use [smile]

I've been pondering this a bit and I actually like the idea of an InputServiceProvider myself. With a bit of work it can gracefully solve the issue of 'XNA short term memory loss' Jim described.



namespace InputServiceProviderDemo
{
public class InputStateProvider
{
private MouseState ms = new MouseState();
private MouseState lastMs = new MouseState();
public MouseState CurrentMouseState { get { return ms; } }
public MouseState PreviousMouseState { get { return lastMs; } }

private KeyboardState kbs = new KeyboardState();
private KeyboardState lastKbs = new KeyboardState();
public KeyboardState CurrentKeyboardState { get { return kbs; } }
public KeyboardState PreviousKeyboardState { get { return lastKbs; } }

private GamePadStateCollection gps = new GamePadStateCollection();
private GamePadStateCollection lastGps = new GamePadStateCollection();
public GamePadStateCollection CurrentGamePadStates { get { return gps; } }
public GamePadStateCollection PreviousGamePadStates { get { return lastGps; } }

public InputStateProvider()
{
gps.Add(PlayerIndex.One, new GamePadState());
gps.Add(PlayerIndex.Two, new GamePadState());
gps.Add(PlayerIndex.Three, new GamePadState());
gps.Add(PlayerIndex.Four, new GamePadState());

lastGps.Add(PlayerIndex.One, new GamePadState());
lastGps.Add(PlayerIndex.Two, new GamePadState());
lastGps.Add(PlayerIndex.Three, new GamePadState());
lastGps.Add(PlayerIndex.Four, new GamePadState());
}

public void Update()
{
lastKbs = kbs;
kbs = Keyboard.GetState();

lastMs = ms;
ms = Mouse.GetState();

UpdateGamePad(PlayerIndex.One);
UpdateGamePad(PlayerIndex.Two);
UpdateGamePad(PlayerIndex.Three);
UpdateGamePad(PlayerIndex.Four);
}

private void UpdateGamePad(PlayerIndex index)
{
lastGps[index] = gps[index];
gps[index] = GamePad.GetState(index);
}

public bool KeyWasPressed(Keys key)
{
return lastKbs.IsKeyDown(key) && kbs.IsKeyUp(key);
}

public bool LeftMouseButtonWasClicked()
{
return lastMs.LeftButton == ButtonState.Pressed && ms.LeftButton == ButtonState.Released;
}

public bool RightMouseButtonWasClicked()
{
return lastMs.RightButton == ButtonState.Pressed && ms.RightButton == ButtonState.Released;
}

public bool MiddleMouseButtonWasClicked()
{
return lastMs.MiddleButton == ButtonState.Pressed && ms.MiddleButton == ButtonState.Released;
}

public int GetMouseScrollDelta()
{
return ms.ScrollWheelValue - lastMs.ScrollWheelValue;
}

/// <summary>
/// Was pressed and has been released
/// </summary>
public bool GamePadButtonWasPressed(PlayerIndex index, Buttons button)
{
if (gps[index].IsConnected)
{
return lastGps[index].IsButtonDown(button) && gps[index].IsButtonUp(button);
}
else
{
return false;
}
}
}

public class GamePadStateCollection : Dictionary<PlayerIndex, GamePadState>
{
}
}





I think I'm gonna use this from now on (here's my test demo) seeing how many times I forgot _lastState = state in my code and wondered why the game wasn't responding [rolleyes]

Edited to soup in some GamePad support and edited again after debugging :p


[Edited by - remigius on March 4, 2010 4:53:23 AM]

Share this post


Link to post
Share on other sites

This topic is 2841 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this