Tutorials‎ > ‎

[PS Vita] Rock-Paper-Scissor Game

posted Dec 6, 2012, 11:53 PM by William Surya Permana   [ updated Aug 15, 2016, 11:24 PM by Surya Wang ]

Objective

Using PSM Studio, we can create a rock-paper-scissor game. This program will contains background music and sound effect playing, data saving and loading, gamepad respoinding. And of course this program will also contains text and image show like in previous tutorial.

This game seperated to three main screens, the title screen, the select arena screen, and the gameplay screen. For more detail, look at this screenshots below:

Main menu view

Select arena view (after selecting New Game)

Transition before and after gameplay

Gameplay view (waiting user input)

Gameplay view (after user input or time’s up)

Paused gameplay view

For more detail, you can also download the solution below and try it for yourself.

Image ScaleType

There are five image scaletype that we can use in PSM, there are NinePatch, Stretch, AspectInside, AspectOutside, and Center. This game use some of those image scale types. For more detail, see the comparison below:

Audio

In PSM SDK, audio is separated into two types, background music and sound effect. These are the differences:
  Background music Sound effect
Supported extension .mp3 .wav
Support multiple player No Yes
Audio class Bgm Sound
Audio player class BgmPlayer SoundPlayer

Game Input

To get gamepad input in our application, we can use ‘GamePad.GetData (0)’. If gdp is ‘GamePad.GetData (0)’, then to get the buttons currently pressed, we can use ‘gdp.Buttons’ which will return an unsigned integer, according to this table:
Buttons Alias Value Decimal Value
GamePadButtons.Left 20 1
GamePadButtons.Up 21 2
GamePadButtons.Right 22 4
GamePadButtons.Down 23 8
GamePadButtons.Square 24 16
GamePadButtons.Triangle 25 32
GamePadButtons.Circle 26 64
× GamePadButtons.Cross 27 128
START GamePadButtons.Start 28 256
SELECT GamePadButtons.Select 29 512
L GamePadButtons.L 210 1024
R GamePadButtons.R 211 2048
Enter GamePadButtons.Enter 216 65536
Back GamePadButtons.Back 217 1301072

Codes

To create program like that, we can use this code:
using Sce.PlayStation.Core.Environment; using Sce.PlayStation.Core.Graphics; using Sce.PlayStation.Core.Audio; using Sce.PlayStation.Core.Imaging; using Sce.PlayStation.HighLevel.UI; using System; using Sce.PlayStation.Core.Input; namespace NewApp { public class AppMain { static GraphicsContext graphics; static int time; static int scenecounter; static Scene scene; static string raygunfont; static string unifont; static string bgm1; static string bgm2; static string choice1; static string choice2; static Bgm bgm; static BgmPlayer bgmp; static Sound sfx; static SoundPlayer sfxp; static ImageBox titlebg; static Label titletext; static Label titlemenu1; static Label titlemenu2; static Label help; static Label arenatext; static Label arenaselect; static Label arenamenu1; static Label arenamenu2; static Label arenamenu3; static Label arenamenu4; static Label arenamenu5; static ImageBox arenaimg1; static ImageBox arenaimg2; static ImageBox arenaimg3; static ImageBox arenaimg4; static ImageBox arenaimg5; static ImageBox mainbg; static ImageBox mainhelp; static ImageBox imgp; static ImageBox imgc; static Label pausebg; static Label pausetext; static Label scorep1; static Label scorep2; static Label scorec1; static Label scorec2; static Label status; static bool continueselected; static int waittime; static int scorep; static int scorec; static int round; static int choicep; static int choicec; static int bg; public static void LoadData() { string[] data = null; if (System.IO.File.Exists("/Documents/data.txt")) data = System.IO.File.ReadAllLines("/Documents/data.txt"); if (data != null && data.Length == 4){ round = int.Parse(data[0].Trim()); scorep = int.Parse(data[1].Trim()); scorec = int.Parse(data[2].Trim()); bg = int.Parse(data[3].Trim()); } else { ClearData(); } } public static void SaveData() { string[] data = new string[4] { round+"", scorep+"", scorec+"", bg+"" }; System.IO.File.WriteAllLines("/Documents/data.txt", data); } public static void ClearData(){ round = 1; scorep = 0; scorec = 0; bg = 0; } public static void Main (string[] args) { Initialize (); while (true) { SystemEvents.CheckEvents (); Update (); Render (); } } public static void Initialize () { graphics = new GraphicsContext(); UISystem.Initialize(graphics); scene = new Scene(); raygunfont = "/Application/resources/raygun.ttf"; unifont = "/Application/resources/unifont.ttf"; bgm1 = "/Application/resources/Heaven01.mp3"; bgm2 = "/Application/resources/Boss01.mp3"; choice1 = "/Application/resources/choice1.wav"; choice2 = "/Application/resources/choice2.wav"; waittime = 5; titlebg = new ImageBox(); titlebg.SetSize(graphics.Screen.Width, graphics.Screen.Height); titlebg.ImageScaleType = ImageScaleType.AspectOutside; titlebg.Image = new ImageAsset("/Application/resources/title.jpg"); titletext = new Label(); titletext.SetSize(graphics.Screen.Width, graphics.Screen.Height / 2); titletext.HorizontalAlignment = HorizontalAlignment.Center; titletext.Font = new UIFont(raygunfont, 64, FontStyle.Bold); titletext.Text = "Rock - Paper - Scissor"; titletext.TextShadow = new TextShadowSettings(){ Color = new UIColor (.5f,.5f,0,1), HorizontalOffset = 4, VerticalOffset = 4 }; titlemenu1 = new Label(); titlemenu1.SetSize(graphics.Screen.Width, 100); titlemenu1.HorizontalAlignment = HorizontalAlignment.Center; titlemenu1.Y = graphics.Screen.Height / 2 ; titlemenu1.Font = new UIFont(unifont, 32, FontStyle.Bold); titlemenu1.Text = "New Game"; titlemenu2 = new Label(); titlemenu2.SetSize(graphics.Screen.Width, 100); titlemenu2.HorizontalAlignment = HorizontalAlignment.Center; titlemenu2.Y = graphics.Screen.Height / 2 + 50; titlemenu2.Font = new UIFont(unifont, 32, FontStyle.Bold); titlemenu2.Text = "Continue"; help = new Label(); help.SetSize(graphics.Screen.Width, graphics.Screen.Height); help.HorizontalAlignment = HorizontalAlignment.Center; help.VerticalAlignment = VerticalAlignment.Bottom; help.Font = new UIFont(unifont, 16, FontStyle.Regular); help.LineBreak = LineBreak.Word; arenatext = new Label(); arenatext.SetSize(graphics.Screen.Width, 100); arenatext.HorizontalAlignment = HorizontalAlignment.Center; arenatext.Y = 100; arenatext.Font = new UIFont(unifont, 32, FontStyle.Bold); arenatext.Text = "SELECT ARENA"; arenaselect = new Label(); arenaselect.Y = -9999; arenaselect.SetSize(graphics.Screen.Width / 5, 200); arenaselect.BackgroundColor = new UIColor(1,1,0,1); arenamenu1 = new Label(); arenamenu1.SetSize(graphics.Screen.Width / 5, 100); arenamenu1.SetPosition(0*graphics.Screen.Width / 5, graphics.Screen.Height / 2 + 50); arenamenu1.HorizontalAlignment = HorizontalAlignment.Center; arenamenu1.Font = new UIFont(unifont, 16, FontStyle.Bold); arenamenu1.Text = "Grassland"; arenamenu2 = new Label(); arenamenu2.SetSize(graphics.Screen.Width / 5, 100); arenamenu2.SetPosition(1*graphics.Screen.Width / 5, graphics.Screen.Height / 2 + 50); arenamenu2.HorizontalAlignment = HorizontalAlignment.Center; arenamenu2.Font = new UIFont(unifont, 16, FontStyle.Bold); arenamenu2.Text = "Beach"; arenamenu3 = new Label(); arenamenu3.SetSize(graphics.Screen.Width / 5, 100); arenamenu3.SetPosition(2*graphics.Screen.Width / 5, graphics.Screen.Height / 2 + 50); arenamenu3.HorizontalAlignment = HorizontalAlignment.Center; arenamenu3.Font = new UIFont(unifont, 16, FontStyle.Bold); arenamenu3.Text = "Town"; arenamenu4 = new Label(); arenamenu4.SetSize(graphics.Screen.Width / 5, 100); arenamenu4.HorizontalAlignment = HorizontalAlignment.Center; arenamenu4.SetPosition(3*graphics.Screen.Width / 5, graphics.Screen.Height / 2 + 50); arenamenu4.Font = new UIFont(unifont, 16, FontStyle.Bold); arenamenu4.Text = "Village"; arenamenu4.Visible = false; arenamenu5 = new Label(); arenamenu5.SetSize(graphics.Screen.Width / 5, 100); arenamenu5.HorizontalAlignment = HorizontalAlignment.Center; arenamenu5.SetPosition(4*graphics.Screen.Width / 5, graphics.Screen.Height / 2 + 50); arenamenu5.Font = new UIFont(unifont, 16, FontStyle.Bold); arenamenu5.Text = "Ship"; arenaimg1 = new ImageBox(); arenaimg1.SetSize(graphics.Screen.Width / 5 - 10, 150); arenaimg1.SetPosition(0*graphics.Screen.Width / 5 + 5, graphics.Screen.Height / 2 - 75); arenaimg1.ImageScaleType = ImageScaleType.AspectOutside; arenaimg1.Image = new ImageAsset("/Application/resources/001-Grassland01.jpg"); arenaimg2 = new ImageBox(); arenaimg2.SetSize(graphics.Screen.Width / 5 - 10, 150); arenaimg2.SetPosition(1*graphics.Screen.Width / 5 + 5, graphics.Screen.Height / 2 - 75); arenaimg2.ImageScaleType = ImageScaleType.AspectOutside; arenaimg2.Image = new ImageAsset("/Application/resources/005-Beach01.jpg"); arenaimg3 = new ImageBox(); arenaimg3.SetSize(graphics.Screen.Width / 5 - 10, 150); arenaimg3.SetPosition(2*graphics.Screen.Width / 5 + 5, graphics.Screen.Height / 2 - 75); arenaimg3.ImageScaleType = ImageScaleType.AspectOutside; arenaimg3.Image = new ImageAsset("/Application/resources/013-PostTown01.jpg"); arenaimg4 = new ImageBox(); arenaimg4.SetSize(graphics.Screen.Width / 5 - 10, 150); arenaimg4.SetPosition(3*graphics.Screen.Width / 5 + 5, graphics.Screen.Height / 2 - 75); arenaimg4.ImageScaleType = ImageScaleType.AspectOutside; arenaimg4.Image = new ImageAsset("/Application/resources/023-FarmVillage01.jpg"); arenaimg5 = new ImageBox(); arenaimg5.SetSize(graphics.Screen.Width / 5 - 10, 150); arenaimg5.SetPosition(4*graphics.Screen.Width / 5 + 5, graphics.Screen.Height / 2 - 75); arenaimg5.ImageScaleType = ImageScaleType.AspectOutside; arenaimg5.Image = new ImageAsset("/Application/resources/030-Ship01.jpg"); mainbg = new ImageBox(); mainbg.SetSize(graphics.Screen.Width, graphics.Screen.Height); mainbg.ImageScaleType = ImageScaleType.AspectOutside; mainhelp = new ImageBox(); mainhelp.SetSize(355*1.25f, 48*1.25f); mainhelp.SetPosition((graphics.Screen.Width-355*1.25f)/2,graphics.Screen.Height-48*1.25f-10); mainhelp.ImageScaleType = ImageScaleType.Stretch; mainhelp.Image = new ImageAsset("/Application/resources/help.png"); imgp = new ImageBox(); imgp.SetSize(100*3.5f, 75*3); imgp.Y = (graphics.Screen.Height-75*3)/2; imgp.ImageScaleType = ImageScaleType.Stretch; imgc = new ImageBox(); imgc.SetSize(100*3.5f, 75*3); imgc.Y = (graphics.Screen.Height-75*3)/2; imgc.ImageScaleType = ImageScaleType.Stretch; pausebg = new Label(); pausebg.SetSize(graphics.Screen.Width, graphics.Screen.Height); pausebg.BackgroundColor = new UIColor(0,0,0,0.5f); pausetext = new Label(); pausetext.SetSize(graphics.Screen.Width, 100); pausetext.HorizontalAlignment = HorizontalAlignment.Center; pausetext.Y = 100; pausetext.Font = new UIFont(unifont, 32, FontStyle.Bold); pausetext.Text = "GAME PAUSED"; scorep1 = new Label(); scorep1.SetSize(graphics.Screen.Width / 3, 50); scorep1.SetPosition(0*graphics.Screen.Width / 3, 0); scorep1.Font = new UIFont(unifont, 16, FontStyle.Regular); scorep1.Text = " Player:"; scorep1.TextColor = new UIColor(0.5f, 0.5f, 1, 1); scorep1.TextShadow = new TextShadowSettings(); scorep1.HorizontalAlignment = HorizontalAlignment.Left; scorep2 = new Label(); scorep2.SetSize(graphics.Screen.Width / 3, 60); scorep2.SetPosition(0*graphics.Screen.Width / 3, 30); scorep2.Font = new UIFont(raygunfont, 64, FontStyle.Regular); scorep2.TextColor = new UIColor(0.5f, 0.5f, 1, 1); scorep2.TextShadow = new TextShadowSettings(); scorep2.HorizontalAlignment = HorizontalAlignment.Left; scorec1 = new Label(); scorec1.SetSize(graphics.Screen.Width / 3, 50); scorec1.SetPosition(2*graphics.Screen.Width / 3, 0); scorec1.Font = new UIFont(unifont, 16, FontStyle.Regular); scorec1.Text = "Computer: "; scorec1.TextColor = new UIColor(1, 0.5f, 0.5f, 1); scorec1.TextShadow = new TextShadowSettings(); scorec1.HorizontalAlignment = HorizontalAlignment.Right; scorec2 = new Label(); scorec2.SetSize(graphics.Screen.Width / 3, 60); scorec2.SetPosition(2*graphics.Screen.Width / 3, 30); scorec2.Font = new UIFont(raygunfont, 64, FontStyle.Regular); scorec2.TextColor = new UIColor(1, 0.5f, 0.5f, 1); scorec2.TextShadow = new TextShadowSettings(); scorec2.HorizontalAlignment = HorizontalAlignment.Right; status = new Label(); status.SetSize(graphics.Screen.Width / 3, 100); status.X = 1*graphics.Screen.Width / 3; status.Font = new UIFont(unifont, 32, FontStyle.Regular); status.TextShadow = new TextShadowSettings(); status.HorizontalAlignment = HorizontalAlignment.Center; scene.RootWidget.AddChildLast(titlebg); scene.RootWidget.AddChildLast(titletext); scene.RootWidget.AddChildLast(titlemenu1); scene.RootWidget.AddChildLast(titlemenu2); scene.RootWidget.AddChildLast(arenatext); scene.RootWidget.AddChildLast(arenaselect); scene.RootWidget.AddChildLast(arenamenu1); scene.RootWidget.AddChildLast(arenamenu2); scene.RootWidget.AddChildLast(arenamenu3); scene.RootWidget.AddChildLast(arenamenu4); scene.RootWidget.AddChildLast(arenamenu5); scene.RootWidget.AddChildLast(arenaimg1); scene.RootWidget.AddChildLast(arenaimg2); scene.RootWidget.AddChildLast(arenaimg3); scene.RootWidget.AddChildLast(arenaimg4); scene.RootWidget.AddChildLast(arenaimg5); scene.RootWidget.AddChildLast(mainbg); scene.RootWidget.AddChildLast(mainhelp); scene.RootWidget.AddChildLast(imgc); scene.RootWidget.AddChildLast(imgp); scene.RootWidget.AddChildLast(scorec1); scene.RootWidget.AddChildLast(scorec2); scene.RootWidget.AddChildLast(scorep1); scene.RootWidget.AddChildLast(scorep2); scene.RootWidget.AddChildLast(status); scene.RootWidget.AddChildLast(pausebg); scene.RootWidget.AddChildLast(pausetext); scene.RootWidget.AddChildLast(help); UISystem.SetScene(scene); bgm = new Bgm(bgm1); bgmp = bgm.CreatePlayer(); bgmp.Loop = true; bgmp.Play(); } public static void Update(){ var gpd = GamePad.GetData(0); if (scenecounter == 0){ titletext.Visible = true; titlemenu1.Visible = true; titlemenu2.Visible = true; arenatext.Visible = false; arenaselect.Visible = false; arenamenu1.Visible = false; arenamenu2.Visible = false; arenamenu3.Visible = false; arenamenu4.Visible = false; arenamenu5.Visible = false; arenaimg1.Visible = false; arenaimg2.Visible = false; arenaimg3.Visible = false; arenaimg4.Visible = false; arenaimg5.Visible = false; mainbg.Visible = false; mainhelp.Visible = false; pausebg.Visible = false; pausetext.Visible = false; scorec1.Visible = false; scorec2.Visible = false; scorep1.Visible = false; scorep2.Visible = false; status.Visible = false; imgc.Visible = false; imgp.Visible = false; help.Text = "UP | DOWN: Move Selection START: Confirm"; imgp.X = -100*3.5f; imgc.X = graphics.Screen.Width; imgc.Image = null; imgp.Image = null; scenecounter = 1; } else if (scenecounter == 1){ if (gpd.ButtonsDown == GamePadButtons.Up || gpd.ButtonsDown == GamePadButtons.Down){ continueselected = !continueselected; sfx = new Sound(choice1); sfxp = sfx.CreatePlayer(); sfxp.Play(); } if (continueselected) { titlemenu1.TextColor = new UIColor (1,1,1,1); titlemenu2.TextColor = new UIColor (1,1,0,1); } else { titlemenu1.TextColor = new UIColor (1,1,0,1); titlemenu2.TextColor = new UIColor (1,1,1,1); } if (gpd.ButtonsDown == GamePadButtons.Start){ sfx = new Sound(choice2); sfxp = sfx.CreatePlayer(); sfxp.Play(); if(continueselected){ LoadData(); scenecounter = 4; } else { int t = bg; ClearData(); bg = t; scenecounter = 2; } } } else if (scenecounter == 2) { titletext.Visible = false; titlemenu1.Visible = false; titlemenu2.Visible = false; arenatext.Visible = true; arenaselect.Visible = true; arenamenu1.Visible = true; arenamenu2.Visible = true; arenamenu3.Visible = true; arenamenu4.Visible = true; arenamenu5.Visible = true; arenaimg1.Visible = true; arenaimg2.Visible = true; arenaimg3.Visible = true; arenaimg4.Visible = true; arenaimg5.Visible = true; help.Text = "LEFT | RIGHT: Move Selection START: Confirm SELECT: Cancel"; if(bg==0) bg = 3; scenecounter = 3; } else if (scenecounter == 3) { if (gpd.ButtonsDown == GamePadButtons.Left || gpd.ButtonsDown == GamePadButtons.Right){ sfx = new Sound(choice1); sfxp = sfx.CreatePlayer(); sfxp.Play(); } if (gpd.ButtonsDown == GamePadButtons.Start || gpd.ButtonsDown == GamePadButtons.Select){ sfx = new Sound(choice2); sfxp = sfx.CreatePlayer(); sfxp.Play(); } if (gpd.ButtonsDown == GamePadButtons.Left) bg--; else if (gpd.ButtonsDown == GamePadButtons.Right) bg++; else if (gpd.ButtonsDown == GamePadButtons.Start) scenecounter = 4; else if (gpd.ButtonsDown == GamePadButtons.Select) scenecounter = 0; if (bg < 1) bg = 5; if (bg > 5) bg = 1; arenaselect.SetPosition((bg-1)*graphics.Screen.Width / 5, graphics.Screen.Height / 2 - 80); arenamenu1.TextColor = new UIColor (1,1,1,1); arenamenu2.TextColor = new UIColor (1,1,1,1); arenamenu3.TextColor = new UIColor (1,1,1,1); arenamenu4.TextColor = new UIColor (1,1,1,1); arenamenu5.TextColor = new UIColor (1,1,1,1); if(bg==1) arenamenu1.TextColor = new UIColor (0,0,0,1); if(bg==2) arenamenu2.TextColor = new UIColor (0,0,0,1); if(bg==3) arenamenu3.TextColor = new UIColor (0,0,0,1); if(bg==4) arenamenu4.TextColor = new UIColor (0,0,0,1); if(bg==5) arenamenu5.TextColor = new UIColor (0,0,0,1); } else if (scenecounter == 4) { titletext.Visible = false; titlemenu1.Visible = false; titlemenu2.Visible = false; arenatext.Visible = false; arenaselect.Visible = false; arenamenu1.Visible = false; arenamenu2.Visible = false; arenamenu3.Visible = false; arenamenu4.Visible = false; arenamenu5.Visible = false; arenaimg1.Visible = false; arenaimg2.Visible = false; arenaimg3.Visible = false; arenaimg4.Visible = false; arenaimg5.Visible = false; help.Text = ""; if (bg==1) mainbg.Image = new ImageAsset("/Application/resources/001-Grassland01.jpg"); if (bg==2) mainbg.Image = new ImageAsset("/Application/resources/005-Beach01.jpg"); if (bg==3) mainbg.Image = new ImageAsset("/Application/resources/013-PostTown01.jpg"); if (bg==4) mainbg.Image = new ImageAsset("/Application/resources/023-FarmVillage01.jpg"); if (bg==5) mainbg.Image = new ImageAsset("/Application/resources/030-Ship01.jpg"); mainbg.Alpha = 0; mainbg.Visible = true; time = 0; scenecounter = 5; } else if (scenecounter == 5) { if (mainbg.Alpha < 1) { mainbg.Alpha += 0.01f; bgmp.Volume -= 0.01f; } else { bgm = new Bgm(bgm2); bgmp.Dispose(); bgmp = bgm.CreatePlayer(); bgmp.Loop = true; bgmp.Play(); scorec1.Visible = true; scorec2.Visible = true; scorep1.Visible = true; scorep2.Visible = true; status.Visible = true; mainhelp.Visible = true; imgc.Visible = true; imgp.Visible = true; titlebg.Alpha = 0; scenecounter = 6; } } else if (scenecounter == 6) { if(bgmp.Status == BgmStatus.Playing) time++; if(time<=waittime*60) { scorec2.Text = scorec+" "; scorep2.Text = " "+scorep; status.Text = "Round: "+round+"\n" + "Time: "+(waittime - time/60); if((gpd.Buttons & GamePadButtons.Square) != 0) { choicep = 1; time=waittime*60; }; if((gpd.Buttons & GamePadButtons.Cross) != 0) { choicep = 2; time=waittime*60; }; if((gpd.Buttons & GamePadButtons.Circle) != 0) { choicep = 3; time=waittime*60; }; } else if(time==(waittime*60)+1) { Random rnd = new Random(); if(choicep==0) choicep = rnd.Next(3)+1; var t = choicec; choicec = rnd.Next(3)+1; if(choicec==t || choicec==choicep) choicec = rnd.Next(3)+1; imgp.Image = new ImageAsset("/Application/resources/"+choicep+"1.png"); imgc.Image = new ImageAsset("/Application/resources/"+choicec+"2.png"); switch (choicep){ case 1 /*rock*/: switch (choicec) { case 2: scorec++; break; case 3: scorep++; break; }; break; case 2 /*paper*/: switch (choicec) { case 3: scorec++; break; case 1: scorep++; break; }; break; case 3 /*scissor*/: switch (choicec) { case 1: scorec++; break; case 2: scorep++; break; }; break; }; round++; choicep = 0; SaveData(); } else { if(imgp.X < 0){ imgp.X+=5; imgc.X-=5; } else { if(time>(waittime+3)*60) { imgp.X = -100*3.5f; imgc.X = graphics.Screen.Width; time=0; } } } if (gpd.ButtonsDown == GamePadButtons.Start || gpd.ButtonsDown == GamePadButtons.Select){ sfx = new Sound(choice2); sfxp = sfx.CreatePlayer(); sfxp.Play(); } if (gpd.ButtonsDown == GamePadButtons.Select) { pausebg.Visible = false; pausetext.Visible = false; help.Text = ""; titlebg.Alpha = 1; mainbg.Alpha = 1; scorec1.Visible = false; scorec2.Visible = false; scorep1.Visible = false; scorep2.Visible = false; status.Visible = false; mainhelp.Visible = false; imgc.Visible = false; imgp.Visible = false; scenecounter = 7; } else if (gpd.ButtonsDown == GamePadButtons.Start && bgmp.Status == BgmStatus.Playing) { pausebg.Visible = true; pausetext.Visible = true; help.Text = "START: Resume SELECT: Go to Main Menu"; bgmp.Pause(); } else if (gpd.ButtonsDown == GamePadButtons.Start && bgmp.Status == BgmStatus.Paused) { pausebg.Visible = false; pausetext.Visible = false; help.Text = ""; bgmp.Play(); } } else if (scenecounter == 7) { if (mainbg.Alpha > 0) { mainbg.Alpha -= 0.01f; bgmp.Volume -= 0.01f; } else { bgm = new Bgm(bgm1); bgmp.Dispose(); bgmp = bgm.CreatePlayer(); bgmp.Loop = true; bgmp.Play(); bg = 0; scenecounter = 0; } } } public static void Render(){ graphics.Clear (); UISystem.Render (); graphics.SwapBuffers (); } } }

Explanation

In line 11-65, we create the object and variable that we will use later, like:
  • [Line 11] GraphicsContext graphics as the main graphics
  • [Line 12-13] int scene and int time as scene flag (main menu, select arena, gameplay, etc.) and timer countdown in main gameplay respectively
  • [Line 14] Scene scene as the main scene
  • [Line 16-21] 3 string raygunfont, unifont, bgm1, bgm2, choice1, choice2 for storing the file path of two fonts, two background music, and two sound effect respectively
  • [Line 23-24] Bgm bgm for background music and its player BgmPlayer bgmp
  • [Line 25-26] Sound sfx for sound effect and its player SoundPlayer sfxp
  • [Line 27-30] ImageBox titlebg and three Label (titletext, titlemenu1, and titlemenu2 respectively) for main menu view background, title, and ‘New Game’ and ‘Continue’ text respectively
  • [Line 31] Label help which always appear in the center bottom of the screen
  • [Line 33-44] Label arenatext as select area header text; Label arenaselect as background of selected arena; Label arenamenu1, arenamenu2, arenamenu3, arenamenu4, arenamenu5 as arena description text below of the arena image from ImageBox arenaimg1, arenaimg2, arenaimg3, arenaimg4, and arenaimg5
  • [Line 46-56] Four ImageBox: mainbg as gameplay background, mainhelp as button help in gameplay, imgp for player hand, and imgc for computer hand; Seven Label: pausebg as transparent black background when the gameplay is paused, pausetext for showing ‘Game Paused’ text, scorep1 for showing ‘Player’ text, scorec1 for showing ‘Computer’, scorep2 for showing player score, scorec2 for showing computer score, and status for showing current round and timer countdown
In line 67-80, we create LoadData function to save player’s progress
  • [Line 68] Preparing an array of string named data
  • [Line 69-70] If file ‘data.txt’ in folder ‘Documents’ is exist, fill data with lines from it.
  • [Line 72-79] If there are four lines of text in the file,
    • Set variable round with the first line of the file
    • Set variable scorep with the second line of the file
    • Set variable scorec with the third line of the file
    • Set variable bg with the fourth line of the file
    But, if the file is null or not contains four lines of text, it will call function ClearData
In line 82-90, we create SaveData function to save player’s progress
  • [Line 83-88] Create an array of string named data, contains the value of variable round (current round), scorep (current player score), scorec (current computer score), and bg (current selected arena)
  • [Line 89] Write the array into file ‘data.txt’ in ‘Documents’ folder
In line 92-97, we create ClearData function to reset variable round (current round), scorep (current player score), scorec (current computer score), and bg (current selected arena)

In Initialize function, we create new object, set the value and properties of the following object:
  • [Line 109-111] Initialize graphics in UI system and create a scene
  • [Line 113-118] Set the value of raygunfont, unifont, bgm1, bgm2, choice1, and choice2 with the file locations
  • [Line 120] Set the value of waittime with 5
  • [Line 122-125] Create the object of titlebg, and set the following properties:
    • Size: Full screen
    • Scaling: AspectOutside
    • Image: from file ‘title.jpg’ in folder ‘resources’
  • [Line 127-136] Create the object of titletext, and set the following properties:
    • Size: Screen width x Half of screen height
    • Horizontal alignment: Center
    • Font: using raygunfont 64pt in bold
    • Text: ‘Rock - Paper - Scissor’
    • Text shadow: Yellow (0.5,0.5,0) with 4px horizontal and vertical offset
  • [Line 138-150] Create the object of titlemenu1 and titlemenu2, and set the following properties:
    • Size: Screen width x 100px
    • Position: 0, Half of screen height for titlemenu1 and 0, Half of screen height + 50px for titlemenu2
    • Horizontal alignment: Center
    • Font: using unifont 32pt in bold
    • Text: ‘New Game’ for titlemenu1 and ‘Continue’ for titlemenu2
  • [Line 152-157] Create the object of help, and set the following properties:
    • Size: Full screen
    • Horizontal alignment: Center
    • Vertical alignment: Bottom
    • Font: using unifont 16pt regular
    • Line break: after a word
  • [Line 160-165] Create the object of arenatext, and set the following properties:
    • Size: Screen width x 100px
    • Position: 0, 100
    • Horizontal alignment: Center
    • Font: using unifont 32pt in bold
    • Text: ‘SELECT ARENA’
  • [Line 167-170] Create the object of arenaselect, and set the following properties:
    • Size: A fifth of screen width x 200px
    • Position: 0, -9999 (not visible in screen)
    • Background color: Yellow (1,1,0)
  • [Line 172-206] Create the object of arenamenu1, arenamenu2, arenamenu3, arenamenu4, and arenamenu5, and set the following properties:
    • Size: A fifth of screen width x 100px
    • Position: N times a fifth of screen width x A half of screen height + 50px, where n is 0 for arenamenu1, 1 for arenamenu2, 2 for arenamenu3, 3 for arenamenu4, and 4 for arenamenu5
    • Horizontal alignment: Center
    • Font: using unifont 16pt in bold
    • Text: ‘Grassland’ for arenamenu1, ‘Beach’ for arenamenu2, ‘Town’ for arenamenu3, ‘Village’ for arenamenu4, and ‘Ship’ for arenamenu5
  • [Line 208-236] Create the object of arenaimg1, arenaimg2, arenaimg3, arenaimg4, and arenaimg5, and set the following properties:
    • Size: A fifth of screen width – 10px x 150px
    • Position: N times a fifth of screen width + 5px x A half of screen height – 75px, where n is 0 for arenamenu1, 1 for arenamenu2, 2 for arenamenu3, 3 for arenamenu4, and 4 for arenamenu5
    • Scaling: AspectOutside
    • Image: from file ‘001-Grassland01.jpg’ for arenaimg1, ‘005-Beach01.jpg’ for arenaimg2, ‘013-PostTown01.jpg’ for arenaimg3, ‘023-FarmVillage01’ for arenaimg4, and ‘030-Ship01’ for arenaimg5 in folder ‘resources’
  • [Line 240-242] Create the object of mainbg, and set the following properties:
    • Size: Full screen
    • Scaling: AspectOutside
  • [Line 244-248] Create the object of mainhelp, and set the following properties:
    • Size: 1.25x of original image size (355px x 48px)
    • Position: Center bottom of the screen
    • Scaling: Stretch image
    • Image: from file ‘help.png’ in folder ‘resources’
  • [Line 250-258] Create the object of imgp and imgc, and set the following properties:
    • Size: 3.5 times of image width x 3 times of image height (100px x 75px)
    • Position: Left middle of the screen for imgp and Right middle for imgc, so those not visible to user
    • Scaling: Stretch image
  • [Line 260-262] Create the object of pausebg, and set the following properties:
    • Size: Full screen
    • Color: Transparent black (0,0,0) Alpha: 0.5
  • [Line 265-270] Create the object of paustext, and set the following properties:
    • Size: Screen width x 100px
    • Position: 0, 100
    • Horizontal alignment: Center
    • Font: using unifont 32pt in bold
    • Text: “GAME PAUSED”
  • [Line 272-279 and Line 289-296] Create the object of scorep1 and scorec1, and set the following properties:
    • Size: A third of screen width x 50px
    • Position: N times a third of screen width, 0px where N is 0 for scorep1 and 2 for scorec1
    • Horizontal alignment: Left for scorep1 and Right for scorec1
    • Font: using unifont 16pt regular
    • Text: “Player:” for scorep1 and “Computer” for scorec1
    • Color: Light blue (0.5, 0.5, 1) for scorep1 and Light red (1, 0.5, 0.5) for scorec1
    • Text shadow: Default text shadow
  • [Line 281-287 and Line 298-304] Create the object of scorep2 and scorec2, and set the following properties:
    • Size: A third of screen width x 60px
    • Position: N times a third of screen width, 30px where N is 0 for scorep2 and 2 for scorec2
    • Horizontal alignment: Left for scorep2 and Right for scorec2
    • Font: using raygunfont 64pt regular
    • Color: Light blue (0.5, 0.5, 1) for scorep1 and Light red (1, 0.5, 0.5) for scorec1
    • Text shadow: Default text shadow
  • [Line 306-311] Create the object of status, and set the following properties:
    • Size: A third of screen width x 100px
    • Position: A third of screen width, 0px
    • Horizontal alignment: Center
    • Font: using raygunfont 64pt regular
    • Text shadow: Default text shadow
  • [Line 313-342] Add all the UI objects above in scene, and set Scene scene as the scene of UISystem
  • [Line 344-347] Create the object of bgm from file stated in variable bgm1, create the player of bgm and store it in variable bgmp, play the bgm
In Update function, we define all of the animations logic:
  • First, we get all the gamepad input
  • Next, we separate the scenes into eight part:
    • 0 for main menu initialization
    • 1 for main menu
    • 2 for select arena screen initialization
    • 3 for select arena screen
    • 4 for gameplay initialization
    • 5 for animation transition from main menu or select arena to gameplay
    • 6 for gameplay
    • 7 for animation transition from gameplay to main menu
  • When the scenecounter is 0
    • Show all Label needed for main menu
    • Hide all Label and ImageBox for other scene
    • Set help text to: “UP | DOWN: Move Selection START: Confirm”
    • Set the imgp to the left of the screen and imgc to the right of the screen
    • Set the imgp and imgc image to null
    • Lastly, go to scene 1
  • When the scencounter is 1
    • If user press Up or Down, negate the value of continueselected and play a sound effect from file stated in choice1
    • Set the color of selected menu to Yellow (1,1,0) and the other to White (1,1,1)
    • If user press Start, play a sound effect from file stated in choice2. After that, if the selected menu is Continue, then call function LoadData and go to scene 4. But if the selected menu is New Game, then call function ClearData and go to scene 2
  • When the scenecounter is 2
    • Hide all Label for main menu
    • Show all Label and ImageBox for arena select screen
    • Set help text to: “LEFT | RIGHT: Move Selection START: Confirm SELECT: Cancel”
    • Move the cursor the third arena (center) if there are no data of previous played arena
    • Lastly, go to scene 3
  • When the scenecounter is 3
    • If user press Left or Right, play a sound effect from file stated in choice1
    • If user press Select or Start, play a sound effect from file stated in choice2
    • If user press Left, subtract the value of variable bg
    • If user press Right, add the value of variable bg
    • If user press Select, go to scene 0
    • If user press Start, go to scene 4
    • If bg is more than 5, set the bg to 1. If bg is less than 1, set the bg to 5
    • Set the position of arenaselect to N times a fifth of screen width, A half of screen height – 80px, where N is current bg subtracted by 1
    • Set all of the arena description color to White (1,1,1)
    • Set the selected arena description color to Black (0,0,0)
  • When the scenecounter is 4
    • Hide all Label and ImageBox for main menu and select arena screen
    • Set the help text to an empty string
    • Set the mainbg image from file ‘001-Grassland01.jpg’ if selected bg is 1, ‘005-Beach01.jpg’ if selected bg is 2, ‘013-PostTown01.jpg’ if selected bg is 3, ‘023-FarmVillage01’ if selected bg is 4, and ‘030-Ship01’ if selected bg is 5 in folder ‘resources’
    • Show the mainbg with full transparency
    • Reset the variable time to 0
    • Lastly, go to scene 5
  • When the scenecounter is 5
    • When mainbg is not full opaque, add its Alpha and subtract the volume of background music
    • When mainbg is already opaque, change the background music from the file stated in variable bgm2, show all Label and ImageBox needed in the gameplay, set the titlebg to transparent, and lastly go to scene 6
  • When the scenecounter is 6
    • If the game is not paused, add the value of variable time every frame
    • If current time is less than or equals to 5 seconds (300 frames, frame rate is 60fps),
      • Update the text for player score, computer score, round and time
      • If user press Square then set the choicep to 1 and kill the wait time
      • If user press Cross then set the choicep to 2 and kill the wait time
      • If user press Circle then set the choicep to 3 and kill the wait time
    • If the current time is 301 frames
      • Random the player choice if player not choosing any option
      • Random the computer choice
      • If player choice is the same as computer choice, or the computer choice is the same as the previous choice, try to rerandom computer choice
      • Set the player and computer hand image according to the choice choosen
      • Add the player or computer score according to Rock-Paper-Scissor game rule
      • Add the round
      • Reset the value of variable choicep to 0
      • Call function SaveData
    • If the current time is more than 301 frames
      • If the X position of player hand is not 0, move the player hand to the right and move the computer hand to the left by 5px each frame
      • Else, if time already 3 seconds passed again, move the player hand to the left and computer hand to the right so those not visible to user
    • If user press Select or Start, play sound effect from file stated in variable choice2
    • If user press Select, hide all Label and ImageBox needed in gameplay, set the titlebg to opaque, help text to an empty string, and go to scene 7
    • If user press Start and current gameplay is not paused, show the pausebg and pausetext, set the help text to “START: Resume SELECT: Go to Main Menu”, and pause the background music
    • If user press Start and current gameplay is paused, hide the pausebg and pausetext, set the help text to an empty string, and resume playing the background music
  • When the scenecounter is 7
    • When mainbg is not full transparent, subtract its Alpha and subtract the volume of background music
    • When mainbg is already transparent, set the backgroundmusic to file stated in variable bgm1, reset the bg variable to 0, and lastly go to scene 0
In Render function, we render all the animations.

This is the end of the tutorial. Hope you can understand how to create a rock-paper-scissor game in PS Vita using PSM Studio.
ċ
[PS Vita] Rock-Paper-Scissor Game.zip
(5113k)
William Surya Permana,
Dec 6, 2012, 11:53 PM