PSM Tutorial #1 : Explaining the code in a New Project
2012-12-01 4:41 AM
Before we can start drawing an object on the screen we need to setup our Update/Render loop and our graphics context.
Most realtime happen inside a big loop. In the Update/Render loop pattern the logic that drives the game happens in the Update step of the loop. This includes things like checking user input, moving objects, starting and stopping sounds, AI routines and almost anything not related to drawing that happens in a game.
The render step of the game loop pretty much only handles one thing: Drawing objects and graphics on the screen.
So lets get started. Open up Playstation Mobile Studio and start a new Solution. Choose a “PlayStation Mobile Application”. Give your project a name and then hit OK.
At this point you can run the program and you will see a black screen. Exciting! This screen is actually redrawing black many times per second, of course it’s redrawing a black canvas every time so it looks like nothing could be happening.
In the left side of the screen you will see your solution explorer. There is only one source code file here called “AppMain.cs”. Open this file up.
Let’s take a look at the basic program structure for “AppMain.cs”.
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;
namespace Tutorial01_01_GameLoop
{
public class AppMain
{
private static GraphicsContext graphics;
public static void Main (string[] args)
{
Initialize ();
while (true) {
SystemEvents.CheckEvents ();
Update ();
Render ();
}
}
public static void Initialize ()
{
// Set up the graphics system
graphics = new GraphicsContext ();
}
public static void Update ()
{
// Query gamepad for current state
var gamePadData = GamePad.GetData (0);
}
public static void Render ()
{
// Clear the screen
graphics.SetClearColor (0.0f, 0.0f, 0.0f, 0.0f);
graphics.Clear ();
// Present the screen
graphics.SwapBuffers ();
}
}
}
Now let’s analyze the individual portions of this code:
private static GraphicsContext graphics;
public static void Main (string[] args)
{
Initialize ();
while (true)
{
SystemEvents.CheckEvents ();
Update ();
Render ();
}
}
public static void Initialize ()
{
// Set up the graphics system
graphics = new GraphicsContext ();
}
First we have a static member of type GraphicsContext defined. The Graphics Context is a system that handles many graphics related functions, you need it to have any sort of display. Here is a list of some things it can do:
- Give you the width and height of the current device screen (in pixels) - Clear the screen - Draw objects on the screen - Enable and disable graphical features such as transparency
Next we have the main entry point to the program. The first method that is called is Initialize(). Inside Initialize() we only do one thing. Instantiate our GraphicsContext object. It’s important to note you only want to do this once in your program.Instantiatinga GraphicsContext twice will cause a exception to be thrown and crash your program.
Next we have aninfinitewhile loop. This runs continuously until some other event ends the loop causing the end of main to be reached and the program to shut down. Inside this loop we have 3 methods being called. CheckEvents(), Update() and Render().
SystemEvents.CheckEvents ();
What this does is checks to see if any Vita (or Android/Windows) specific events are called and allows them to be processed. This must be in your main game loop.
Update();
This is the update portion of a game loop. Almost all of your game specific code should be in this method. Things like moving objects around, handling user input and playing sounds should be done here.
Render();
The render portion of the game loop should really only be used for drawing things to the screen. So after you have moved an object and handled all the code for your game for this iteration of the loop you draw everything.
Now let’s take a look at the Update() and Render() methods in depth.
public static void Update ()
{
// Query gamepad for current state
var gamePadData = GamePad.GetData (0);
}
public static void Render ()
{
// Clear the screen
graphics.SetClearColor (0.0f, 0.0f, 0.0f, 0.0f);
graphics.Clear ();
// Present the screen
graphics.SwapBuffers ();
}
The default Vita project Update method really does nothing at all but lets take a look anyways. The code is one line:
var gamePadData = GamePad.GetData (0);
What this does is gets the current state of the 1st gamepad connected to the system. In the case of the portable Vita with only one controller it is most likely you will only ever be getting the first gamepad. I think the reason there is an option to select a gamepad is if in the future PSM is extended to support other systems like the PS3 (Hint Hint Sony ).
The code is only getting the gamepad data. It’s not checking for anything so it’s essentially doing nothing.
One other note, you may notice that the keyword “var” is used rather than an explicit definition of the type the GetData() method returns. In some languages this can mean that the type is determined at runtime but with C# if it can determine the type at compile time implicitly then it will. This means typing something like :
var gamePadData = GamePad.GetData (0);
Is exactly the same as writing :
GamePadData gamePadData = GamePad.GetData (0);
Finally we move on to the Render() method. This is where some stuff actually happens :
public static void Render ()
{
// Clear the screen
graphics.SetClearColor (0.0f, 0.0f, 0.0f, 0.0f);
graphics.Clear ();
// Present the screen
graphics.SwapBuffers ();
}
First we set the clear color of our graphics context. What this does is sets the color that the graphics context clears the screen to when you call the clear method. Parameters are passed in Red,Green,Blue,Alpha. So if you were to pass in 1f,0f,0f,0f you would get a red screen. This method could actually be put into the Initialize() method after creating the graphics context since what it does is changes the color of subsequent Clear() calls. So right now calling it in Render() every time is redundant.
Next call is Clear(). This wipes everything off the screen and gives you a blank screen in the color that you last set SetClearColor() to.
Finally the last call is SwapBuffers(). When you are drawing in PSM there are 2 images. The one that you are looking at on the screen and the one you are drawing to which is not visible. So in a Render() method you are actually drawing to an invisible image in the background and when you are finished all your drawing you call SwapBuffers(). What this essentially does is swaps the image that you are viewing on the screen with the image you just drew to allowing only a completely drawn image to ever be shown on the screen. This is done to avoid visual errors and flickering on the screen that can occur if rendering didn’t use this method.
That’s everything for this portion of the tutorial. If you spot any issues, inaccuracies or would like me to better explain a concept please let me know in the comments.
No source code is included with this tutorial because this is the default code PSM will give you when you create a new PSM application project.
In part 2 we will do something more interesting. Draw an image on the screen
Tags: psm_tutorial