WP7 - Sessions, PlayerAgents, PlayerInput

Nov 12, 2011 at 10:56 PM

Hi indiefreaks,

Quite desperately lost with how we're meant to use Sessions, PlayerAgents and PlayerInputs in WP7 games.

I'm probably just missing something obvious, but I can't see any way to create a WP7 game.

Sessions, PlayerAgents etc seem to be wound into the framework in such a way that you can't create them yourself (internal constructors, private setters etc) which leaves me searching in the dark.

Please, please, please give me an example of how to use the framework. I must have spent 6 hours trying to get what looks like an awesome framework to actually work.

Thanks,

Tristan

Coordinator
Nov 14, 2011 at 11:12 AM

Hi TreeUK,

The Logic & Session system is rather complex on its approach as it changes the way one may usually think about game structure. However, once you get how it works, it gives you a tremendous scripting and network abstracted system.

First, I encourage you to look at the Ace on Steroids Tutorials 6, 7 and 8 to get a feel of how to use them: it works exactly the same on Windows, Xbox & WP7.

Then, I have a couple of blog posts and videos on my blog explaining how it works and I recommend you to read them. They are all tagged with the Game Logic tag and you should start from the olders to the newest.
http://indiefreaks.com/tag/game-logic/page/4/

But to summarize, here are the core mechanism:

First, you need to create and add a ISessionManager implementation to your game within your Application.InitializeSunBurn() method. On WP7, the sole supported right now is the LocalSessionManager which can be found in the Indiefreaks.Game.Logic.dll assembly.

Then, you'll want to identify logical players which can be achieved in two different ways. Either using the SessionManager.BeginPlayersIdentification() and EndPlayersIdentification() methods as shown in the Ace on Steroids Tutorials which takes care of identifying Players; or using directly the SessionManager.IdentifyPlayer() method passing in the PlayerIndex value for which you want to identify him.

Once this is done, you can create and start a new Session using the SessionManager.CreateSinglePlayerSession(); method. Just make sure to subscribe to the SessionCreated event so that you can perform a call to SessionManager.CurrentSession.StartSession(). You'll also have primarly hooked the CurrentSession.SessionStarted event to perform your game logic initialization (which would occured preferably in a dedicated GameState).

You then have 2 ways of creating PlayerAgent and NonPlayerAgent instances.

Note that a PlayerAgent and NonPlayerAgent classes inherit from the SunBurn Component system and therefore need to be added to one SceneObject Components collection in order to work.

To create a PlayerAgent, you can either call directly the CurrentSession.CreatePlayerAgent() which asks for an IdentifiedPlayer instance that you can retrieve from the SessionManager.LocalPlayers collection (usually the PlayerOne). The returned instance can then be stored in a field or directly added to the SceneObject or SceneEntity instance you want to control with your PlayerAgent.

The 2nd method (which I used in Ace on Steroids) is to create your own PlayerAgent inherited class and do the same as above but instead of calling the CurrentSession.CreatePlayerAgent() method, you'd call its Generic version. So, say you created a MyPlayer class inheriting from PlayerAgent, you'll create an instance by calling the CurrentSession.CreatePlayerAgent<MyPlayer>(identifiedPlayer).

Once you created your PlayerAgent, you need to add a custom Behavior to gather input and process it to change the attached SceneObject state.

So, you create a new Behavior inherited class, say PlayerInputBehavior for instance and then, you'll want to add in its constructor a Local Command using the AddLocalCommand() method. This method has different signatures but the easiest for now will be to use the one with the unique argument which is the method delegate you'll want to be executed on each frame.

So, you can add a new method to your Behavior such as private object ProcessInput(Command command){} and add a local command with a call to AddLocalCommand(ProcessInput);

Now, in your ProcessInput method, you'll want to retrieve the PlayerInput instance which is actually associated with the current PlayerAgent and this is done simply by storing in a local variable the value returned by a call to ((PlayerAgent)this.Agent).Input.
The WP7 input implementation doesn't yet provide a VirtualGamePad system (which is in the task list for now) but you can retrieve the InputTouches collection as you would normally do by accessing the PlayerInput.Touches collection from the PlayerInput instance you just retrieved.

So you'd ended up having something like:

public class PlayerInputBehavior : Behavior
{
    public PlayerInputBehavior()
    {
         AddLocalCommand(ProcessInput);
    }

    private object ProcessInput(Command command)
    {
        PlayerInput input = ((PlayerAgent)this.Agent).Input;

        var wp7Touches = input.Touches;

        // and now perform whatever you want using the input retrieved....

        // note that you can retrieve the SceneEntity or SceneObject this Behavior is controlling by getting back in the Logic hierarchy like so:
        var playerControlledObject = this.Agent.ParentObject;

        // Then, you can change its World matrix or whatever you want.
    }
}