Game Development Community

dev|Pro Game Development Curriculum

3D Character Selection Screen

by To-mos · 08/15/2011 (12:43 pm) · 6 comments

Since being here with this AWESOME community, I figured I'd give my 2 cents to the you all by creating my first resource. I found that a few people have requested this so I'd give it a shot.

Before we get started I've taken their image check code and put it in a handy function so first add that to the game.
core/scripts/client/helperfuncs.cs
//a function to check for allowed image types
function checkImageType(%image)
{
   if (isFile(%image @ ".png") ||
          isFile(%image @ ".jpg") ||
          isFile(%image @ ".bmp") ||
          isFile(%image @ ".gif") ||
          isFile(%image @ ".jng") ||
          isFile(%image @ ".mng") ||
          isFile(%image @ ".tga"))
      return true;
   else 
      return false;
}
I have provided the modified code for the character screen below.
art/gui/playermenu.gui
//--- OBJECT WRITE BEGIN ---
%guiContent = new GuiControl(playermenuGUI) {
   isContainer = "1";
   Profile = "GuiOverlayProfile";
   HorizSizing = "width";
   VertSizing = "height";
   position = "0 0";
   Extent = "1024 768";
   MinExtent = "8 8";
   canSave = "1";
   Visible = "1";
   tooltipprofile = "GuiToolTipProfile";
   hovertime = "1000";
   canSaveDynamicFields = "1";
      enabled = "1";

   new GuiChunkedBitmapCtrl(options_playerscreen) {
      useVariable = "0";
      tile = "0";
      isContainer = "1";
      Profile = "GuiDefaultProfile";
      HorizSizing = "center";
      VertSizing = "center";
      position = "192 144";
      Extent = "640 480";
      MinExtent = "8 2";
      canSave = "1";
      Visible = "1";
      tooltipprofile = "GuiToolTipProfile";
      hovertime = "1000";
      canSaveDynamicFields = "0";

      new GuiTextListCtrl(options_playerlist) {
         columns = "0";
         fitParentWidth = "1";
         clipColumnText = "0";
         isContainer = "1";
         Profile = "GuiTextArrayProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "17 10";
         Extent = "80 32";
         MinExtent = "8 8";
         canSave = "1";
         Visible = "0";
         tooltipprofile = "GuiToolTipProfile";
         hovertime = "1000";
         canSaveDynamicFields = "0";
      };
      new GuiDynamicCtrlArrayControl() {
         colCount = "3";
         colSize = "108";
         rowCount = "1";
         RowSize = "81";
         rowSpacing = "0";
         colSpacing = "10";
         frozen = "0";
         autoCellSize = "1";
         fillRowFirst = "1";
         DynamicSize = "0";
         Padding = "0 0 0 0";
         isContainer = "1";
         Profile = "GuiDefaultProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "17 10";
         Extent = "347 400";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         tooltipprofile = "GuiToolTipProfile";
         hovertime = "1000";
         internalName = "SmallPreviews";
         canSaveDynamicFields = "0";
      };
      new GuiButtonCtrl() {
         text = "Back";
         groupNum = "-1";
         buttonType = "PushButton";
         useMouseEvents = "0";
         isContainer = "0";
         Profile = "GuiButtonProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "17 426";
         Extent = "83 40";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         Command = "Canvas.popDialog(playermenuGUI);";
         tooltipprofile = "GuiToolTipProfile";
         hovertime = "1000";
         canSaveDynamicFields = "0";
      };
      new GuiObjectView(Player3DView) {
         cameraZRot = "0";
         forceFOV = "0";
         reflectPriority = "0";
         Margin = "0 0 0 0";
         Padding = "0 0 0 0";
         AnchorTop = "1";
         AnchorBottom = "0";
         AnchorLeft = "1";
         AnchorRight = "0";
         isContainer = "0";
         Profile = "GuiDefaultProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "378 80";
         Extent = "251 389";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         tooltipprofile = "GuiToolTipProfile";
         hovertime = "1000";
         canSaveDynamicFields = "0";
      };
      new GuiBitmapButtonCtrl() {
         bitmap = "core/art/gui/images/previous-button";
         groupNum = "-1";
         buttonType = "PushButton";
         useMouseEvents = "0";
         isContainer = "0";
         Profile = "GuiDefaultProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "151 418";
         Extent = "19 56";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "0";
         Command = "options_playermenuWindow.previousPreviews();";
         tooltipprofile = "GuiToolTipProfile";
         hovertime = "1000";
         internalName = "PreviousSmallPreviews";
         canSaveDynamicFields = "1";
            enabled = "1";
            wrap = "0";
      };
      new GuiBitmapButtonCtrl() {
         bitmap = "core/art/gui/images/next-button";
         groupNum = "-1";
         buttonType = "PushButton";
         useMouseEvents = "0";
         isContainer = "0";
         Profile = "GuiDefaultProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "279 418";
         Extent = "19 56";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "0";
         Command = "options_playermenuWindow.nextPreviews();";
         tooltipprofile = "GuiToolTipProfile";
         hovertime = "1000";
         internalName = "NextSmallPreviews";
         canSaveDynamicFields = "1";
            enabled = "1";
            wrap = "0";
      };
   };
};
//--- OBJECT WRITE END ---
Now that we have created our gui element it's time to include it in the start up with a nice little exec.
Change the code in

scripts/client/init.cs
TO
// Load up the shell GUIs
exec("art/gui/mainMenuGui.gui");
exec("art/gui/joinServerDlg.gui");
exec("art/gui/endGameGui.gui");
exec("art/gui/StartupGui.gui");
exec("art/gui/playermenu.gui");
This will tell the engine to start up the new gui with the rest. Now comes the fun part, adding the code to make it "tick" if you will. This code is a modified form of the level selection screen code.
We will want to make a new script file called playermenu.cs

scripts/gui/playermenu.cs
//------------------------------------------------------------------------------
// Torque        Engine
// Copyright (C) GarageGames.com, Inc.
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// global vars
//------------------------------------------------------------------------------


$playerModel["Default"]   =  "art/shapes/actors/Gideon/gideon.dts";


//----------------------------------------
function playermenuGUI::onWake()
{
   options_playerlist.clear();
   options_playerscreen->SmallPreviews.clear();
   %i = 0;
   for(%file = findFirstFile("art/shapes/actors/*.dts"); %file !$= ""; %file = findNextFile("art/shapes/actors/*.dts"))
   {
      //filter out common files
      if (strstr(%file, "/common/") > -1)
         continue;
      
      %playerName = fileBase(%file);

      %PlayerInfoObject = getCharacterInfo(%file);
      
      $playerModel[%i] = %file;
      options_playerlist.addRow(%i++, %playerName TAB %file);
   }

   // Sort our list
   options_playerlist.sort(0);

   // Set the first row as the selected row
   options_playerlist.setSelectedRow(0);

   for (%i = 0; %i < options_playerlist.rowCount(); %i++)
   {
      %player = new GuiBitmapButtonCtrl() {
         internalName = "SmallPreview" @ %i;
         Extent = "108 81";
         bitmap = "art/gui/no-preview.png";
         command = "options_playerscreen.previewSelected(options_playerscreen->SmallPreviews->SmallPreview" @ %i @ ");";
      };

      options_playerscreen->SmallPreviews.add(%player);

      // Set this small preview visible
      if (%i >= 5)
         %player.setVisible(false);

      // Set the level index
      %player.playerIndex = %i;

      %file = getField(options_playerlist.getRowText(%i), 1);

      // Find the preview image
      %characterPreview = filePath(%file) @ "/" @ fileBase(%file) @ "_thumb";

      // Test against all of the different image formats
      if (checkImageType(%characterPreview))
      {
         %player.setBitmap(%characterPreview);
      }
   }

   options_playerscreen->SmallPreviews.firstVisible = -1;
   options_playerscreen->SmallPreviews.lastVisible = -1;

   if (options_playerscreen->SmallPreviews.getCount() > 0)
   {
      options_playerscreen->SmallPreviews.firstVisible = 0;

      if (options_playerscreen->SmallPreviews.getCount() < 6)
         options_playerscreen->SmallPreviews.lastVisible = options_playerscreen->SmallPreviews.getCount() - 1;
      else
         options_playerscreen->SmallPreviews.lastVisible = 4;
   }

   if (options_playerscreen->SmallPreviews.getCount() > 0)
      options_playerscreen.previewSelected(options_playerscreen->SmallPreviews.getObject(0));

   // If we have 5 or less previews then hide our next/previous buttons
   // and resize to fill their positions
   if (options_playerscreen->SmallPreviews.getCount() < 6)
   {
      options_playerscreen->PreviousSmallPreviews.setVisible(false);
      options_playerscreen->NextSmallPreviews.setVisible(false);
   }

   if (options_playerscreen->SmallPreviews.getCount() <= 1)
   {
      // Hide the small previews
      options_playerscreen->SmallPreviews.setVisible(false);
   }
   else
   {
      // Make sure the small previews are visible
      options_playerscreen->SmallPreviews.setVisible(true);
   }
}


function options_playerscreen::previewSelected(%this, %player)
{
   // Set the selected level
   if (isObject(%player) && %player.playerIndex !$= "")
      options_playerlist.setSelectedRow(%player.playerIndex);
   else
      options_playerlist.setSelectedRow(-1);
   
      %id = options_playerlist.getSelectedId();
      %model = getField(options_playerlist.getRowTextById(%id), 1);
      $pref::Player::Model = getField(options_playerlist.getRowTextById(%id), 0)@"PlayerData";
      Player3DView.setModel(%model);
      Player3DView.setOrbitDistance(1);
}

function options_playerscreen::previousPreviews(%this)
{
   %prevHiddenIdx = %this->SmallPreviews.firstVisible - 1;

   if (%prevHiddenIdx < 0)
      return;

   %lastVisibleIdx = %this->SmallPreviews.lastVisible;

   if (%lastVisibleIdx >= %this->SmallPreviews.getCount())
      return;

   %prevHiddenObj  = %this->SmallPreviews.getObject(%prevHiddenIdx);
   %lastVisibleObj = %this->SmallPreviews.getObject(%lastVisibleIdx);

   if (isObject(%prevHiddenObj) && isObject(%lastVisibleObj))
   {
      %this->SmallPreviews.firstVisible--;
      %this->SmallPreviews.lastVisible--;

      %prevHiddenObj.setVisible(true);
      %lastVisibleObj.setVisible(false);
   }
}

function options_playerscreen::nextPreviews(%this)
{
   %firstVisibleIdx = %this->SmallPreviews.firstVisible;

   if (%firstVisibleIdx < 0)
      return;

   %firstHiddenIdx = %this->SmallPreviews.lastVisible + 1;

   if (%firstHiddenIdx >= %this->SmallPreviews.getCount())
      return;

   %firstVisibleObj = %this->SmallPreviews.getObject(%firstVisibleIdx);
   %firstHiddenObj  = %this->SmallPreviews.getObject(%firstHiddenIdx);

   if (isObject(%firstVisibleObj) && isObject(%firstHiddenObj))
   {
      %this->SmallPreviews.firstVisible++;
      %this->SmallPreviews.lastVisible++;

      %firstVisibleObj.setVisible(false);
      %firstHiddenObj.setVisible(true);
   }
}

//----------------------------------------
function getCharacterInfo( %playerFile ) 
{
   %file = new FileObject();
   
   %PlayerInfoObject = "";
   
   if ( %file.openForRead( %playerFile ) ) {
		%inInfoBlock = false;
		
		while ( !%file.isEOF() ) {
			%line = %file.readLine();
			%line = trim( %line );
			
			if( %line $= "new ScriptObject(CharacterInfo) {" )
				%inInfoBlock = true;
			else if( %inInfoBlock && %line $= "};" ) {
				%inInfoBlock = false;
				%PlayerInfoObject = %PlayerInfoObject @ %line; 
				break;
			}
			
			if( %inInfoBlock )
			   %PlayerInfoObject = %PlayerInfoObject @ %line @ " "; 	
		}
		
		%file.close();
	}
   %file.delete();

	if( %PlayerInfoObject !$= "" )
	{
	   %PlayerInfoObject = "%PlayerInfoObject = " @ %PlayerInfoObject;
	   eval( %PlayerInfoObject );

      return %PlayerInfoObject;
	}
	
	// Didn't find our PlayerInfo
   return 0; 
}

About the author

Recent Blogs

• 3D Character Selection Screen

#1
08/15/2011 (2:28 pm)
Thanks for sharing this - do you have any screenshots of it in action?
#2
08/15/2011 (2:42 pm)
Your avatar is the best. Cool resource, too - useful!
#3
08/16/2011 (10:14 am)
Please do not repost resources as blogs.
#4
08/16/2011 (10:59 am)
Sounds great can you please post a video

thanks
#5
08/16/2011 (4:44 pm)
Well done with the resource. I'll be giving it a try.

As Scott says.. post it as a resource.
That way it wont get lost in all the blogs.

Also post some pics or a video of it in action.

Thanks for taking the time to write this up!

#6
06/06/2013 (7:03 pm)
Sorry about this being in the blog section I can't remember why it was here. Maybe it was a blog then I reposted as a resource. If i knew how to remove it I would hah xD