Pages

Tuesday, April 27, 2010

Book Review: Professional Refactoring in C#

I would recommend the book Professional Refactoring in C# & ASP.Net by Danijel Arsenovski for any developer interested in refactoring code. Arsenovski gives clear and documented refactoring improvements for a variety of common code structures, as well as some specific C# version 3.0 features. The book deals strongly with the concept of code "smells" which are the simple heuristics for finding and improving parts of code.

The code smells include finding and refactoring such things as dead code, overexposure, overburdened temporary variable, long methods, procedural design and many others. The book explores setting up a unit testing framework with NUnit to verify the same functionality after refactoring has taken place. This draws some parallels with the Foundations of Programming book I reviewed earlier on its approach to unit testing. While I do enjoy the appeal of a unit testing design and programming strategy it is a bit more difficult to apply to all aspects of game programming (such as player/object synchronization etc), as well as sometimes it can be an issue to test if you are dealing with a tool set that does not take the code directly (like the Unreal scripting).

This book would be useful for any intermediate to expert developers with an interest in C# as it will surely give you food for thought on how to improve your code (which I will see if I can apply to the XNA project (which I will be mentioning later).

Bye for now,
http://michaelhubbard.ca

Saturday, April 17, 2010

Book Review: Foundations of Programming

I finished reading the ebook Foundations of Programming: Building Better Software by Karl Seguin which is available at the previous link. The book focuses on concepts of improving coding practice using some Agile methodologies and incorporating ideas from both the .NET (MSDN) and ALT.NET (abstract concepts with more specific implementations). Seguin brings up good elements of Domain Driven Design vs Data Driven Design where the behavior of the system rather then on the data, which allows for a more flexible system that can be refactored with different data as the needs arise. The book also focuses on Dependency Injection as a way of decoupling certain systems and increasing the ease of Unit Testing those systems. Seguin also suggests that if something is difficult to unit test it is likely that method or function is likely tightly coupled and could be refactored to produce better code (code that is difficult to test means it is likely difficult to use).

While the book does deal with more application specific elements (Object Relational Matching using NHibernate and Rhinomock for the .Net framework) the concept of unit testing when applied to games does bring up some interesting comparisons. The data within games is difficult to test for a majority of reasons (if you ever talk to game testers/QA they will be spending a lot of their time repeating the same things over and over again with only slight alterations on each iteration). One of the difficulties is the complexity of data that comes in at runtime during a game, often relying on art for collision information, state information from a sync server and lots of potential for any sort of race conditions that a unit test would obviously not cover. This does not mean that we should dismiss unit testing but instead focus on testing what we can, by writing code that can be easily unit tested we are likely writing simpler and better encapsulated code then would likely be produced without unit testing. This is also a large benefit for testing (and refactoring) the core elements of the system that do not rely on as much art, server or runtime information. While testing does take time, it is invaluable in helping find issues before they become bugs and incredibly useful in verifying the same behaviors during any refactiong.

As a whole it was a quick and informative read and would recommend this to anyone interested in improving code and an interest in unit testing (plus the price is right :P)

This got me interested in more specific refactoring so I may be looking at more code quality books in the near future.

Bye for now,
Michael Hubbard
http://michaelhubbard.ca

Sunday, April 11, 2010

XNA C# Item Class Template

I thought I would share a simple class template for XNA classes that are not Game Components (for classes that do not require an update etc.). If you copy the code below to a new (empty class called Class1.cs) and then go to File->Export Template (choose Item Template in the wizard) and the class you copied the template info to. After restarting Visual Studio you can now use the template ( Add->New Item-> My Templates).

//-----------------------------------------------------------------------
// Copyright (c) "$safeitemname$". All rights reserved.
// $guid1$

// $username$ $time$
//
// $safeitemname$ :
//

//-----------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace XNAGame
{
class Class1
{
}
}

The above "code" is free and can be modified, updated and used without consent.

Bye for now,
Michael Hubbard
http://michaelhubbard.ca

Tuesday, April 6, 2010

UDK vs XNA: Part 1

In order to give this blog (and my own inane ramblings) some focus I will be looking at comparing the Unreal Development Kit vs XNA from someone in the professional industry, but coming at developing for both of these packages as a newb (my professional experience has mostly been in C/C++ and OpenGL and C# with Unity).

Coming from a Unity background the XNA project was fairly intuitive, with only slight modifications (mostly in options and casing). Unity uses lower case for accessors and variables: Vector2.zero, while XNA uses uppercase: Vector2.Zero. I was surprised by the number of options the XNA color value had (like Color.Wheat), otherwise I felt very at home with Visual Studio (Express) and the C# code. Working through some tutorial code I was able to setup the build of the game to run a simple image to the game window. The major difference up to this point is workflow, without an in-game editor developing for XNA will likely require iterative testing of values to tweak certain elements of the game play instead of runtime tweaking (we could of course write functionality that would expose setting some of these values at runtime, but it would have to be done for every case).

Getting into the UDK was a bit more of a learning curve. The editor itself was fairly intuitive (it is similar in some ways to Maya) but as a newb to Unreal there were of course things that I would have to look up the documentation for. It is far less of a jump in and start coding experience with the UDK and much more of an explore the editor and figuring out the directory structure of a project (as well as installing nFringe) and learning the different tools (Unreal FrontEnd versus Unreal Editor). Reading the documentation on a lack of debugger in the UDK is a bit of an issue, which would slightly favor XNA development (with breakpoints etc) versus a lot of debug statements. Also having to learn the syntax of a new language UnrealScript will likely take some getting used to.

From someone coming from a Unity background XNA seems like a much easier initial conversion to begin coding (especially if using C# with Unity). Howerver Unreal does offer some intriguing options that both XNA and Unity do not appear to have. With a bit more practice with the build process and Unreal editor setup I will try and create some small examples to compare the differences in creating different game play elements.

Until next time...
Michael Hubbard
http://michaelhubbard.ca

End of Part 1.

Monday, April 5, 2010

Book Review: The Making of Second Life

Greetings (true believers :P),

I thought I would include some book reviews of things I have been reading related to technical interests, I try and read a book a week, although sometimes they are more fluff then tech. Somewhere in-between is The Making of Second Life: Notes from the New World by Wagner James Au. The book is an anecdotal approach to the world of Second Life, often giving stories of the more interesting players (those who play as a group in a nursing home, those who make a steady income as in-game Second Life designers, and a lot of talk about furies as well).

I would have preferred a more technical approach to the subject (like how to manage some of the user generated content/customization), but the book does deal with some aspects of 3D worlds that are trying to be replicated in many other projects, namely what kind/how much user customization should be included?. The book does focus on some of the aspects when given complete customization control (like the red-light districts or unusual character customizations) and there is a definite trend towards more 3D virtual world interaction/customization in many projects. Some of those similar (yet different) besides the obvious Sims include JustLeapIn, Hangout.Net and parts of the Google Lively experiment.

While the book does not specifically tackle the issue of how much customization is enough (or too much), it does state that the game is based around this model. Second Life provides options for downloading and modifying textures through skin templates, modeling buildings and setting up new animation, as seen in their Creation Portal. Some of the Second Life players in face can make their entire income through in-game design (and potentially through in-game trading as well).

This book did raise a few concepts I have been thinking about personally as well, such as the industry trend of more levels of user customization. It is difficult (from a developers perspective) to draw a line at how much technical artist expertise is expected of the users... do players really want to modify vertices and set blend weights on their character? If so what players would be willing to spend the time doing this, and would they want to use in game tools, or a third party (professional or freeware) package they are already familiar with? With this growing trend and the impressive technological results of a game like Spore it could only be a matter of time before we see games ambitious enough to try and recreate Maya, XSI or 3DsMax in the browser. While such a feat would be quite interesting, unless it was specifically a game centered around creativity, I would find that level of control would be likely wasted on all but the smallest minority of players (likely the same percentage that are already familiar with other tools).

All-in-all the book was an interesting read, perhaps designated more to those readers interested in the history of Second Life and some more of the odd characters, than those interested in the technical challenges of creating such a virtual world.

Bye for now,
Michael Hubbard
http://michaelhubbard.ca

Sunday, April 4, 2010

Tortoise SVN Client Hooks

Hello,

Been a while and a move (to warm Toronto from cold Vancouver) a new job, place to live, adventure etc. As a game programmer/ technical artist I have an interest in improving pipeline tasks and automating any repetitive tasks. Needless to say working on a computer a lot it sometimes takes a bit of thinking to know where you can improve time and where you need to spend it. For any home project I do (be it big or small) I usually like to keep track of my changes, and spend a lot of time looking at subversion logs.

I use TortoiseSVN as a subversion
client for a while (though I still like the old command line Subversion for Linux)
and I will be looking at some of the other (mostly free) version control systems in
a later post. Tortoise is great in that it is simple to use and is smoothly embedded in the Windows Explorer window/menu system once it has been installed. I don't usually spend much time on the server side (although I imagine that will eventually change) and work with VisualSVN standard server for setting up a simple svn server on my home machine (it would be really good to have something at a different machine though).

Anyway, I thought there were lots of client side svn hooks I would like to hookup (updating a wikipage, trigger a test build, and formatting svn messages). In order to do this I started from the example at the tortoise svn source website: Pre-Commit Hook Example. Thanks to YNot for the SyntaxHighlighter tip.


// License: This code is free software and can be modified, updated, commented
//and sold verbatim without constent.
// The code has no warranty and the author accepts no liability for any issues
//or damage this code may cause, including: hardware, software, wetware, financial,
// psychological, emotional, mental or physical.
//
// Author: Michael Hubbard
//
// This script is a client side tortoise svn pre-commit hook script.
// The script creates a commit message of the following format:
// The FolderDirectory structure is not the whole path and
// splits on the SplitFolderPath (currently set to "Scripts/").
//
// "_FolderDirectory/SubDirectory(s)_"
// "- Message1"
// "- Message2"
// " ... "
// "- MessageN"
//
// To use the script set the TortoiseSvn->Settings->Hook Scripts->Add
// Set client hook scripts to a pre-commit hook
//(this will set the four command line arguments):
// Set the Command line to Execute to: "WScript
//absolutePathToThisScript/SvnFormatMessageHook.js"
//(the WScript is important (Windows Script Host))
// Check the "Wait for the script to finish" checkbox.
//
// Code based on tortoise svn examples at:
// http://code.google.com/p/tortoisesvn/source/browse/branches/1.6.x/
// contrib/hook-scripts/client-side/PreCommit.js.tmpl

// The root path of the scripts (remove any path information
//before this path when formatting directories).
var SplitFolderPath = "Scripts/";

// The minimum number of characters for a title description.
var MinTitleLength = 3;

// Read the file at path into an array .
function ReadPaths(path)
{
var retPaths = new Array();
var fs = new ActiveXObject("Scripting.FileSystemObject");
if (fs.FileExists(path))
{
var file = fs.OpenTextFile(path, 1, false);
var i = 0;
while (!file.AtEndOfStream)
{
var line = file.ReadLine();
retPaths[i] = line;
i++;
}

file.Close();
}

return retPaths;
}

// Write the formatted message to the message path.
function WriteFormattedMessage(formattedMessage, formatMessagePath)
{
var fs = new ActiveXObject("Scripting.FileSystemObject");
if (fs.FileExists(formatMessagePath))
{
var file = fs.OpenTextFile(formatMessagePath, 2, false);
file.write(formattedMessage);
file.Close();
}
}

// Check if the message is already in the formatted type.
function IsValidMessage(commitMessages)
{
if(null == commitMessages || 0 == commitMessages.length)
{
return false;
}

var titleMessage = commitMessages[0];
if(titleMessage.length < MinTitleLength)
{
return false;
}

return '_' == titleMessage.charAt(0) && '_' == titleMessage.charAt(titleMessage.length -1);
}

// Get the formatted message.
function GetFormatMessage(commitMessages, formattedDirectories)
{
if(null == commitMessages || null == formattedDirectories)
{
return null;
}

// Make sure the title has _ before and after the title it.
var title = "_" + formattedDirectories[0] + "_\n";
for(var i = 0; i < commitMessages.length; i++)
{
if("- " != commitMessages[i].substring(0,2))
{
title += "- ";
}

title += commitMessages[i] + "\n";
}

return title;
}

// Get the formatted directories.
function GetFormattedDirectories(commitFiles)
{
var formattedDirectories = new Array();

// The files to commit.
for(var i = 0; i < commitFiles.length; i++)
{
formattedDirectories[i] = GetDirectoryName(commitFiles[i]);
}

return formattedDirectories;
}

// Get the formated sub directory name (not including the file name).
function GetDirectoryName(file)
{
var splitIndex = file.indexOf(SplitFolderPath);
if(splitIndex == -1)
{
return file;
}

// Get the subdirectory (after SplitFolderPath).
var subDirectory = file.substring(splitIndex + SplitFolderPath.length);

// Remove the file (just keep the subdirectory).
subDirectory = subDirectory.substring(0, subDirectory.lastIndexOf("/"));
return subDirectory;
}

// Write a valid message from the commit files (Quit with 0 for success, 1 for error).
function Main()
{
// The script command line arguments from tortoise.
var objArgs = WScript.Arguments;

// Check the number of script arguments is valid or exit.
if (objArgs.length != 4)
{
WScript.Echo("Usage: [CScript | WScript]
SVNFormatMessageHook.js path/to/pathsfile depth path/to/messagefile path/to/CWD");
WScript.Quit(1);
}

var commitFiles = ReadPaths(objArgs(0));
var commitMessages = ReadPaths(objArgs(2));

// Get the formatted directories.
var formattedDirectories = GetFormattedDirectories(commitFiles);

if(!IsValidMessage(commitMessages))
{
var formattedMessage = GetFormatMessage(commitMessages, formattedDirectories);
WriteFormattedMessage(formattedMessage, objArgs(2));
}

WScript.Quit(0);
}

// Entry point to the program.
Main();

Bye for now,
Michael Hubbard

michaelhubbard.ca