PlayStation?Mobile Development Cookbook
上QQ阅读APP看书,第一时间看更新

Handling the controller's d-pad and buttons

In this recipe, we will look at how to read the device's gamepad's d-pad and button states. The code remains the same regardless of whether it is a physical device or if the controls are emulated.

Getting ready

Load up PlayStation Mobile Studio and create a new project. Add a reference to Sce.PlayStation.GameEngine2D and Sce.PlayStation.GameEngine2D.Base. The complete source for this example can be found in Ch2_Example1.

How to do it...

In the AppMain.cs file of your newly created project, enter the following code:

using System;
using System.Collections.Generic;

using Sce.PlayStation.Core;
using Sce.PlayStation.Core.Environment;
using Sce.PlayStation.Core.Graphics;
using Sce.PlayStation.Core.Input;
using Sce.PlayStation.HighLevel.GameEngine2D;
using Sce.PlayStation.HighLevel.GameEngine2D.Base;

namespace Ch2_Example1
{
  public class AppMain
  {
    public static void Main (string[] args)
    {
      Director.Initialize();
      Scene scene = new Scene();
      scene.Camera.SetViewFromViewport();
      Label label = new Label();
      label.Position = new Vector2(0,Director.Instance.GL.Context.GetViewport().Height/2);
                             
      scene.AddChild(label);
      Director.Instance.RunWithScene(scene,true);
      bool quitApp = false;

      while(!quitApp)
      {
        Director.Instance.Update();
        string currentStatus = "You are currently pressing:\n";
        var pressedButtons = GamePad.GetData(0).ButtonsDown;

        if((pressedButtons & GamePadButtons.Up) == GamePadButtons.Up){
          currentStatus += "Up button";
        }
        if((pressedButtons & GamePadButtons.Left) == GamePadButtons.Left){
          currentStatus += "Left button";
        }
        if((pressedButtons & GamePadButtons.Right) == GamePadButtons.Right){
          currentStatus += "Right button";
        }
        if((pressedButtons & GamePadButtons.Down) == GamePadButtons.Down){
          currentStatus += "Down button";
        }
        if((pressedButtons & GamePadButtons.Cross) == GamePadButtons.Cross){
          currentStatus += "Cross button";
          }

        if((GamePad.GetData(0).ButtonsPrev & GamePadButtons.Cross) == GamePadButtons.Cross){
            quitApp = true;
        }
        label.Text = currentStatus;
        Director.Instance.Render();
        Director.Instance.GL.Context.SwapBuffers();
        Director.Instance.PostSwap();
      }
    }
  }
}

How it works...

The initial code is all about setting up the GameEngine2D classes, which we will cover in detail later in the book. Essentially we just set up our scene then create a new Label object, which we will use to display the current control status on the screen. We then start our scene running and loop until the bool quitApp is set to true.

In our loop, we have to make four required calls using the Director object, which again we will cover later in this chapter. It is the remainder of the loop that is the focus of this recipe.

With each iteration through the loop we clear out our label's text. We then get the current state of our game pad using the following call:

var pressedButtons = GamePad.GetData(0).ButtonsDown;

At this point pressedButtons contains a GamePadButtons enum representing all of the buttons that are currently down. Think of this like a bit field of Boolean values, with the corresponding bit for each button on if the button is currently pressed. Therefore, to test if a certain button is down, we perform a binary and (&) operation, testing it against the button value we want to check.

We check the status of the Up, Left, Right, Down, and Cross buttons and update our label if any of these buttons is currently down. As you can see, the d-pad is basically just a collection of four individual buttons that are either on or off. There are additional buttons to the ones demonstrated here, including the left and right shoulder buttons and the start button. You handle them in the exact same manner. An action very similar to assigning pressedButtons is performed when we make the following call:

if((GamePad.GetData(0).ButtonsPrev & GamePadButtons.Cross) == GamePadButtons.Cross)

This works almost identical to when we checked the down button state, but instead it returns an enum representing buttons that were previously down. So if that button was pressed the prior time you checked input, it will be set. In this case, if the user previously pressed the cross button, we set quitApp to true, causing our program to exit.

The remaining code simply updates the label's text with our updated button status and makes calls to Director that are required if you manually manage your GameEngine2D game loop.

There's more...

In addition to checking if a button is down using ButtonsDown, or if it was previously down using ButtonsPrev, there are also options for checking if a button was released this frame using ButtonsUp, as well as the general Buttons enum, which tells you the button's current status regardless of when it occurred.

The GamePadData struct that GetData() returns also contains a bool named Skip. This value is used to indicate if the input has already been handled elsewhere in code. This is useful as GamePad is globally available, so it is possible that you handle input already in a different part of your code. If so, you can set Skip to true, letting any code that calls GamePad.GetData() again before it is updated know that this input has already been handled elsewhere. The use of Skip is completely optional.

If you are working using the simulator, you may be wondering how exactly you press buttons that don't exist. The following table illustrates the key mappings when running the simulator:

Sadly, you cannot currently emulate analog sticks using the simulator, although an upcoming release intends to add Dual Shock support.

Note

There is currently a bug in PSM Studio that prevents code completion from working for recently added references. You can work around this problem however. After you add a new library reference, save your project and exit PSM Sutdio. Once you restart PSM Studio, code completion should work normally. You can also simply add an additional library reference, then immediately remove it, and code completion will then be working properly. This prevents you from having to restart Studio.

See also

  • See the A game loop, GameEngine2D style recipe in Chapter 3, Graphics with GameEngine2D for more details on how the GameEngine2D portions of this sample work