Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon


7. September 2012

 

We are now going to create the MenuScene we saw at the end of part one.  This is a very simple two item menu, that will either start the game or return to the title screen.

 

MenuScene.cs

 

using System;
using Sce.PlayStation.Core;
using Sce.PlayStation.Core.Graphics;
using Sce.PlayStation.Core.Input;

using Sce.PlayStation.HighLevel.GameEngine2D;
using Sce.PlayStation.HighLevel.GameEngine2D.Base;

using Sce.PlayStation.HighLevel.UI;

namespace Pong
{
    public class MenuScene : Sce.PlayStation.HighLevel.GameEngine2D.Scene
    {
        private Sce.PlayStation.HighLevel.UI.Scene _uiScene;
        
        public MenuScene ()
        {
            this.Camera.SetViewFromViewport();
            Sce.PlayStation.HighLevel.UI.Panel dialog = new Panel();
            dialog.Width = Director.Instance.GL.Context.GetViewport().Width;
            dialog.Height = Director.Instance.GL.Context.GetViewport().Height;
            
            ImageBox ib = new ImageBox();
            ib.Width = dialog.Width;
            ib.Image = new ImageAsset("/Application/images/title.png",false);
            ib.Height = dialog.Height;
            ib.SetPosition(0.0f,0.0f);
            
            Button buttonUI1 = new Button();
            buttonUI1.Name = "buttonPlay";
            buttonUI1.Text = "Play Game";
            buttonUI1.Width = 300;
            buttonUI1.Height = 50;
            buttonUI1.Alpha = 0.8f;
            buttonUI1.SetPosition(dialog.Width/2 - 150,200.0f);
            buttonUI1.TouchEventReceived += (sender, e) => {
                Director.Instance.ReplaceScene(new GameScene());
            };
            
            Button buttonUI2 = new Button();
            buttonUI2.Name = "buttonMenu";
            buttonUI2.Text = "Main Menu";
            buttonUI2.Width = 300;
            buttonUI2.Height = 50;
            buttonUI2.Alpha = 0.8f;
            buttonUI2.SetPosition(dialog.Width/2 - 150,250.0f);
            buttonUI2.TouchEventReceived += (sender, e) => {
            Director.Instance.ReplaceScene(new TitleScene());
            };        
                
            dialog.AddChildLast(ib);
            dialog.AddChildLast(buttonUI1);
            dialog.AddChildLast(buttonUI2);
            _uiScene = new Sce.PlayStation.HighLevel.UI.Scene();
            _uiScene.RootWidget.AddChildLast(dialog);
            UISystem.SetScene(_uiScene);
            Scheduler.Instance.ScheduleUpdateForTarget(this,0,false);
        }
        public override void Update (float dt)
        {
            base.Update (dt);
            UISystem.Update(Touch.GetData(0));
            
        }
        
        public override void Draw ()
        {
            base.Draw();
            UISystem.Render ();
        }
        
        ~MenuScene()
        {
            
        }
    }
}

 

The vast majority of code is in the constructor, so let’s take a look ( in pieces ):

 

this.Camera.SetViewFromViewport();
Sce.PlayStation.HighLevel.UI.Panel dialog = new Panel();
dialog.Width = Director.Instance.GL.Context.GetViewport().Width;
dialog.Height = Director.Instance.GL.Context.GetViewport().Height;

 

Once again, MenuScene is inherited from Scene, and we start off by configuring the Camera member to set itself to the same dimensions as the screen.  Next we create a Panel object, which is part of the Sce.PlayStation.HighLevel.UI library.  A panel is a container of other controls.  We want ours to be the full width and height of the display.

 

ImageBox ib = new ImageBox();
ib.Width = dialog.Width;
ib.Image = new ImageAsset("/Application/images/title.png",false);
ib.Height = dialog.Height;
ib.SetPosition(0.0f,0.0f);

 

Next we create an ImageBox, and image box is simply a control that displays an image.  We are creating this to give the illusion that our menu is overlain over our title screen ( where in reality, it is a completely different scene ).  We again want the ImageBox to take up the full dimensions of our panel, so we set it’s Width and Height to the same as the panel.  Next we load the image as an ImageAsset.  ImageAsset is similar to Texture2D, but is specific to the UI library.  This is an annoying trend of the whole PlayStation Mobile library, each library has a tendency to reinvent the wheel… take a look some time at how many degrees to radian functions the SDK has!  Finally we position our imagebox at (0,0), which is the bottom left corner of the screen.   The end result, show the same image that we showed during the title screen.

 

Button buttonUI1 = new Button();
buttonUI1.Name = "buttonPlay";
buttonUI1.Text = "Play Game";
buttonUI1.Width = 300;
buttonUI1.Height = 50;
buttonUI1.Alpha = 0.8f;
buttonUI1.SetPosition(dialog.Width/2 - 150,200.0f);
buttonUI1.TouchEventReceived += (sender, e) => {
    Director.Instance.ReplaceScene(new GameScene());
};

Button buttonUI2 = new Button();
buttonUI2.Name = "buttonMenu";
buttonUI2.Text = "Main Menu";
buttonUI2.Width = 300;
buttonUI2.Height = 50;
buttonUI2.Alpha = 0.8f;
buttonUI2.SetPosition(dialog.Width/2 - 150,250.0f);
buttonUI2.TouchEventReceived += (sender, e) => {
Director.Instance.ReplaceScene(new TitleScene());
};        

 

Next we create a pair of buttons, one to play the game, the other to go back to main menu ( ok… this is brutally superfluous, but what kind of menu has just one menu option!!! Keep in mind, some of this is for demonstration only! ).  We set each one to be 300 pixels wide, 50 pixels in height and 20% transparent.  We then center horizontally and on top of each other vertically.  If either button is clicked we change the scene, either going back to the TitleScene, or going to the GameScene, which is the main scene controlling our game.

 

dialog.AddChildLast(ib);
dialog.AddChildLast(buttonUI1);
dialog.AddChildLast(buttonUI2);
_uiScene = new Sce.PlayStation.HighLevel.UI.Scene();
_uiScene.RootWidget.AddChildLast(dialog);
UISystem.SetScene(_uiScene);
Scheduler.Instance.ScheduleUpdateForTarget(this,0,false);

 

We then add the image box and both buttons to our dialog using AddChildLast(), create a UIScene ( which has *NOTHING* to do with GameEngine2D scenes, by the way ) then set our scene’s RootWidget to our newly created panel.  The UIScene itself can only contain a single control, the RootWidget, which in turn is a container of other widgets.  We then set our newly created scene as the active scene of the UISystem singleton with the call SetScene().  As you can see, the format is very similar to GameEngine2D and the Director/Scene relationship.  We then schedule this scene ( as in GameEngine scene… not the UIScene… confused yet?  Yeah, the naming convention is kind of brutal at times ) to receive updates with a call to ScheduleUpdateForTarget, which will result in the Update() method being called each frame.

 

public override void Update (float dt)
{
    base.Update (dt);
    UISystem.Update(Touch.GetData(0));
    
}

 

Each update, we simply update the UISystem with the current touch data.  It is your applications responsibility to feed input to the UI, which is exactly what we are doing here.

 

public override void Draw ()
{
    base.Draw();
    UISystem.Render ();
}

It is also our game’s responsibility to call the UISystem Render() method each frame we want it displayed.  It is very important that we call the scene base class Draw() method before we call the UISystem.Render(), otherwise the GameEngine rendering process will draw overtop the UI.  Instead of making the main menu separate from the title screen, it would have been easy enough to make the UISystem Update and Render calls only when you want to display the menu, giving you the same end result.

 

In the next part, we will implement yet another different thing named Scene… physics.

 

Programming , , ,

blog comments powered by Disqus

Month List

Popular Comments