Game Development Community

Blogging and a Refactored Scoreboard

by kcpdad · 09/14/2008 (6:56 pm) · 1 comments

This is a modified copy of this blog entry

Blogging

I'm using WordPress for blogging. Each blog entry will be replicated as a blog at Garagegames, aka GG. WordPress uses HTML tags while Garagegames uses something called Markup Lite. For now I write the original post in HTML using the WordPress editor and gvim, save it as an html file, then convert to Markup Lite using a series of vim substitution commands wrapped in a function.


The blog uses the Atahualpa 2.01 theme. I changed the PRE tag in the style sheet so it includes code in a box similar to GG Markup Lite, this post was very helpful.
pre     {   
        border: solid 1px blue;
	font-size: 1.3 em; 
 	color: blue; 
	margin: 10px; 
	padding:10px; 
	background: #FFFFB3
        color: blue; 
        font-family: Consolas, Monaco, "Courier New", Courier, monospace; 
        }
Also went back to my last post and replicated my post in the GG blog instead of just linking to my blog. I had to change the New Year's resolution link because my original blog link was to a Wikipedia entry that contained a quote in the URL but Markup Lite does not support quotes in the URL, there is always a gotcha :)

Refactoring the Scoreboard with Build 0.46

Here is the original scoreboard from starter fps.
www.60tons.com/images/starterfps_scoreboard.png
After getting Torque years ago one of the first things I changed was the scoreboard. Starting with script is a good way to learn torque especially if it involves client/server interaction. I added more statistics but in retrospect the logic was too complex because it would send client updates to every client every statistics change even if the scoreboard GUI was not looked at. When testing the last build I noticed that scoring was broken. After reviewing the code I decided it was too complex and badly in need of a rewrite.

This latest build refactors the statistics code to make it simpler with less network traffic. The GUI object is only updated when a player requests the screen. Here is what the statistics screen looks like now, accessible via F1
www.60tons.com/images/scoreboard.pngSome statistics need to be updated more frequently because they are part of the player's HUD, e.g. kills and deaths.

Statistics are part of the client connection object and are initialized in 60tons/server/game.cs when the player joins the server.
function GameConnection::onClientEnterGame(%this)
{
...
        // Initialize statistics
        %this.kills = 0;
        %this.deaths = 0;
        %this.flags = 0;
        %this.suicides = 0;
        %this.teamkills = 0;
        %this.pitstopcaptures = 0;
        %this.reward = 0;
        %this.score = 0;
        %this.w1hit = 0;
        %this.w1fired = 0;
        %this.w2hit = 0;
        %this.w2fired = 0;
        %this.w3hit = 0;
        %this.w3fired = 0;
        %this.w4hit = 0;
        %this.w4fired = 0;
        %this.w5hit = 0;
        %this.w5fired = 0;
        %this.w6hit = 0;
        %this.w6fired = 0;
        %this.w7hit = 0;
        %this.w7fired = 0;
        %this.w8hit = 0;
        %this.w8fired = 0;
        %this.w9hit = 0;
        %this.w9fired = 0;

Statistics are collected using a set of "register" functions that are part of the client connection.
For example in game.cs when a player is killed by another player both a death and a kill are registered.
function GameConnection::onDeath(%this, %sourceObject, %sourceClient, %damageType, %damLoc)
{
...
        %this.registerDeathAndKill(%sourceClient);

Register functions are defined in common/server/clientConnection.cs.
For example
function GameConnection::registerDeathAndKill(%this, %killer)
{
    %this.deaths += 1;
    %this.updateHUDStats();
    %killer.kills += 1;
    %killer.score += $SCORE_KILL;
    %killer.updateHUDStats();
    echo("register death and kill with clients" SPC %this SPC %killer);
}

Some statistics are immediately sent to the client because they need to appear on the HUD
function GameConnection::updateHUDStats(%this)
{
    commandToClient( %this, 'UpdateHUDStatistics', %this.kills, %this.deaths, %this.flags, %this.score);
}

When a player presses F1, it sents a command to the server to get statistics.
Here in server/commands.cs we process the request.
function serverCmdGetStatistics(%callingClient)
{
    %observers = 0;
    %tank1 = 0;
    %tank2 = 0;
    %tank3 = 0;
    %tank4 = 0;

    // Loop through all the client objects
    for(%i = 0; %i < ClientGroup.getCount(); %i++)
    {
        %client = ClientGroup.getObject(%i);
        %record = %client.team TAB %client.nameBase TAB %client.kills TAB %client.deaths TAB %client.flags TAB %client.suicides TAB %client.teamkills TAB %client.reward TAB %client.score;

        switch (%client.team)
        {
            case 0:
                %observers[%observer] = %record;
                %observer++;

            case 1:
                %tanks1[%tank1] = %record;
                %tank1++;

            case 2:
                %tanks2[%tank2] = %record;
                %tank2++;

            case 3:
                echo(">>> %record" SPC %record);
                %tanks3[%tank3] = %record;
                %tank3++;

            case 4:
                %tanks4[%tank4] = %record;
                %tank4++;

            default:
        }
    }


    // %records = "";
    %rc = 0;
    for (%i = 0; %i < %observers; %i++)
    {
        %records = setRecord(%records, %rc++, %observers[%i]);
    }

    for (%i = 0; %i < %tank1; %i++)
    {
        %records = setRecord(%records, %rc++, %tanks1[%i]);
    }
    
    for (%i = 0; %i < %tank2; %i++)
    {
        %records = setRecord(%records, %rc++, %tanks2[%i]);
    }
    
    for (%i = 0; %i < %tank3; %i++)
    {
        %records = setRecord(%records, %rc++, %tanks3[%i]);
    }
    
    for (%i = 0; %i < %tank4; %i++)
    {
        %records = setRecord(%records, %rc++, %tanks4[%i]);
    }

    echo(">>> Record starts");
    echo(%records);
    commandToClient( %callingClient, 'ShowStatistics', %records);
    echo(">>> Record ends");
}

The statistics are sent to the client where there are displayed in the GUI.


Persistent statistics for now are available from the home page

Next Steps

Next up is messing with managed triggers from Plastic Gems and posting some videos.

#1
09/14/2008 (7:46 pm)
very good.I like you blog...