I've moved my blog

It's official, I've folded my blog, MrPhil Makes Games, into Mr. Phil Games.  I'll be adding all new content there.  For now, all my old posts here will remain here, but I'll eventually move them all over.  Go check it out, it looks great!

DOH!, Pause = Thread.Sleep(42)

So I've been working with .Net for years and today I put something together that made me feel foolish for not already realizing. Especially since I've used Threads before and even timed them out. I just never had the concept of needing to pause my code bump up next to the fact that my “normal” code is in a thread too.  I’ve gotten so used to only dealing with threading stuff in special situations I guess I forget that my everyday code is threading too. So if you want to pause your code for a certain number of milliseconds do this

     System.Threading.Thread.Sleep( milliseconds );

Not:

    DateTime stop = DateTime.Now.AddMilliseconds( milliseconds );
    while( DateTime.Now < stop );

Or some other machination with DateTimes and loops.

Oh well, it not really my fault it is simply a side affect of global warming.

.Net BinaryReader doc correction

What is wrong with this VB.Net code taken from the MS docs?

  ' Create default application settings.
  aspRatio  = 1.3333
  lkupDir   = "C:\AppDirectory"
  saveTime  = 30
  statusBar = False

  If File.Exists(fileName) Then
    Dim binReader As New BinaryReader( _
      File.Open(fileName, FileMode.Open))
      Try
        ' If the file is not empty,         ' read the application settings.         If binReader.PeekChar() <> -1 Then            aspRatio  = binReader.ReadSingle()            lkupDir   = binReader.ReadString()            saveTime  = binReader.ReadInt32()            statusBar = binReader.ReadBoolean()            Return         End If      ' If the end of the stream is reached before reading      ' the four data values, ignore the error and use the      ' default settings for the remaining values.      Catch ex As EndOfStreamException
        Console.WriteLine("{0} caught and ignored. " & _
         "Using default values.", ex.GetType().Name)
     Finally         binReader.Close()      End Try   End If

The code will throw a NullReferenceException if the file doesn't open properly because binReader will be null when the Close() method is called in the Finally block.

Here is the corrected Finally block:

  Finally
    If Not (binReader Is Nothing) Then
       binReader.Close()
    End If
  End Try

This came up for me because I was working with BinaryWriter and the process didn't have read access to the file.  And naturally by throwing the NullReferenceException I started barking up the wrong tree because it was hidding the UnauthorizedAccessException. Hopefully this will help a google traveler.

Source Code Search Engine

Krugle A search engine for source code called Krugle launching in March!

Link (via digg)

Strategy Pattern

Taking Alastair Patrick’s example of applying patterns to game making I present the strategy pattern. The strategy pattern encapsulates behavior allowing flexibility and object composition. This means a group of classes (as ships) can have some behavior in common, but also room for different flavors without having a lot of overrides and duplicate code. Here’s an example in code. Note, I’ve even written it so the behavior can be changed at runtime!

public interface AttackBehavior
{
    void Attack();
}
public class AttackWithNoWeapon : AttackBehavior
{
    public AttackWithNoWeapon()
    {
        //
        // TODO: Add constructor logic here
        //
    }
    public void Attack()
    {
        Console.Out.WriteLine( "No weapon to attack with." );
    }
}
public class AttackWithRedLaser : AttackBehavior
{
    public AttackWithRedLaser()
    {
        //
        // TODO: Add constructor logic here
        //
    }
    public void Attack()
    {
        Console.Out.WriteLine( "Firing red lasers." );
    }
}
public class AttackWithReinforcedIceProjectile : AttackBehavior
{
    public AttackWithReinforcedIceProjectile()
    {
        //
        // TODO: Add constructor logic here
        //
    }
    public void Attack()
    {
        Console.Out.WriteLine( "Firing Reinforced Ice Projectiles " );
    }
}
public interface FlyBehavior
{
    void Fly();
}
public class FlyWithIonEngines : FlyBehavior
{
    public FlyWithIonEngines()
    {
        //
        // TODO: Add constructor logic here
        //
    }
    public void Fly()
    {
        Console.Out.WriteLine( "Moved 4 parsecs." );
    }
}
public class FlyWithNoEngines : FlyBehavior
{
    public FlyWithNoEngines()
    {
        //
        // TODO: Add constructor logic here
        //
    }
    public void Fly()
    {
        Console.Out.WriteLine( "Movement determined by gravity and inertia." );
    }
}
public class FlyWithSolarSails : FlyBehavior
{
    public FlyWithSolarSails()
    {
        //
        // TODO: Add constructor logic here
        //
    }
    public void Fly()
    {
        Console.Out.WriteLine( "Low Solar Wind, move .5 parsecs." );
    }
}
public abstract class Ship
{
    protected FlyBehavior flyBehavior = null;
    protected AttackBehavior attackBehavior = null;

    public Ship()
    {
    }

    public abstract void Display();

    public void PerformFly()
    {
        flyBehavior.Fly();
    }
    public void PerformAttack()
    {
        attackBehavior.Attack();
    }
    public void Repair()
    {
        Console.Out.WriteLine( "Repair teams dispatched, 10% improvement." );
    }
    public void SetFlyBehavior( FlyBehavior fb )
    {
        flyBehavior = fb;
    }
    public void SetAttackBehavior( AttackBehavior ab )
    {
        attackBehavior = ab;
    }
}
public class TerranMarkI : Ship
{
    public TerranMarkI()
    {
        flyBehavior = new FlyWithIonEngines();
        attackBehavior = new AttackWithRedLaser();
    }

    public override void Display()
    {
        Console.Out.WriteLine( "This is a Terran Mark I ship." );
    }

}
public class NeiwckronMkI : Ship
{
    public NeiwckronMkI()
    {
        SetAttackBehavior( new AttackWithNoWeapon() );
        SetFlyBehavior( new FlyWithIonEngines() );
    }
    public override void Display()
    {
        Console.Out.WriteLine( "A Neiwckron Mark I ship." );
    }

}
public class TheMain
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Ship s1 = new TerranMarkI();
        s1.PerformAttack();
        s1.PerformFly();

        Ship s2 = new NeiwckronMkI();
        s2.PerformFly();
        s2.SetFlyBehavior( new FlyWithSolarSails() );
        s2.PerformFly();
    }
}

Object Cloning Using Reflection

Today on Alastair Patrick’s blog he shared a way to use reflection to clone objects which I found really interesting. I took the liberty of expanding the example a little so I could better understand the effects deep and shallow cloning had. I also replaced his main() with a NUnit test.

using System;
using System.Reflection;
using NUnit.Framework;

public class DeepCopyAttribute : Attribute
{
}
public class PrototypeCloner
{   
    public object Clone( object prototype )
    {
        object clone = CreateNewInstance( prototype.GetType() );

        CopyPropertyValuesFromPrototype( clone, prototype );

        return clone;
    }
    private object CreateNewInstance(Type type)
    {
        ConstructorInfo defaultConstructor = type.GetConstructor( new Type[0] );

        return defaultConstructor.Invoke(new object[0]);
    }   
    private bool IsPropertyDeepCopied( PropertyInfo property )
    {   
        if( property.GetCustomAttributes( typeof(DeepCopyAttribute), true).Length
            != 0 )
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    private void CopyPropertyValuesFromPrototype(object clone, object prototype)
    {
        foreach (PropertyInfo property in prototype.GetType().GetProperties())
        {
            if (IsPropertyDeepCopied(property))
            {
                object prototypeProperty = property.GetValue(prototype, null);
                object cloneProperty = Clone(prototypeProperty);
                property.SetValue(clone, cloneProperty, null);
            }
            else
            {
                property.SetValue(clone, property.GetValue(prototype, null), null);
            }
        }
    }
}
public abstract class Weapon
{
}
public class LaserDisruptor: Weapon
{
    public float RateOfFire
    {
        get
        {
            return rateOfFire;
        }
        set
        {
            rateOfFire = value;
        }
    }
    private float rateOfFire = 1000;
}
public abstract class Entity {}
public class SpaceMonkey: Entity
{
    public float Speed
    {
        get
        {
            return speed;
        }
        set
        {
            speed = value;
        }
    }
    private float speed = 5;

    private Weapon deepCopyWeapon = new LaserDisruptor();
    [DeepCopyAttribute()]
    public Weapon DeepCopyWeapon
    {
        get
        {
            return deepCopyWeapon;
        }
        set
        {
            deepCopyWeapon = value;
        }
    }
    private Weapon shallowCopyWeapon = new LaserDisruptor();
    public Weapon ShallowCopyWeapon
    {
        get
        {
            return shallowCopyWeapon;
        }
        set
        {
            shallowCopyWeapon = value;
        }
    }
}
[TestFixture]
public class PrototypeClonerTests
{
    [Test]
    public void Clone()
    {
        SpaceMonkey prototypeObject = new SpaceMonkey();

        PrototypeCloner cloner = new PrototypeCloner();
        Entity clonedObject = null;
        clonedObject = (Entity)cloner.Clone(prototypeObject);

        SpaceMonkey clonedMonkey = (SpaceMonkey)clonedObject;

        // Testing for Equality
            
        Assert.AreEqual( prototypeObject.Speed, clonedMonkey.Speed, "Fail1" );

        // -- This is false because it is a Deep Copy property and this class
        // doesn't override the Equals or == operator so the Assert's
        // AreSame and AreEqual tests have the identical result
        Assert.IsFalse(
            prototypeObject.DeepCopyWeapon  == clonedMonkey.DeepCopyWeapon,
            "Fail2" );

        Assert.AreEqual(
            ((LaserDisruptor)prototypeObject.DeepCopyWeapon).RateOfFire,
            ((LaserDisruptor)clonedMonkey.DeepCopyWeapon).RateOfFire, "Fail3" );

        // -- Are equal, as in the same object because it is the Shallow Copy
        Assert.AreEqual( prototypeObject.ShallowCopyWeapon,
            clonedMonkey.ShallowCopyWeapon,
            "Fail4" );

        Assert.AreEqual(
            ((LaserDisruptor)prototypeObject.ShallowCopyWeapon).RateOfFire,
            ((LaserDisruptor)clonedMonkey.ShallowCopyWeapon).RateOfFire, "Fail5" );
            
        // Testing for Same
        // -- Only the DeepCopyAttribute properties should be the same

        // -- Not same because it is not a referance object (float)
        Assert.IsFalse(
            object.ReferenceEquals( prototypeObject.Speed, clonedMonkey.Speed ),
            "Fail6"  );

        // -- Not same because it is a DeepCopyAttribute
        Assert.IsFalse(
            object.ReferenceEquals( prototypeObject.DeepCopyWeapon,
            clonedMonkey.DeepCopyWeapon),
            "Fail7" );

        // -- Not same because it is not a referance object (float)
        Assert.IsFalse( object.ReferenceEquals(
            ((LaserDisruptor)prototypeObject.DeepCopyWeapon).RateOfFire,
            ((LaserDisruptor)clonedMonkey.DeepCopyWeapon).RateOfFire), "Fail8"  );

        // -- The only referance object that isn't a deep copy Are Same
        Assert.AreSame( prototypeObject.ShallowCopyWeapon,
            clonedMonkey.ShallowCopyWeapon,
            "Fail9" );

        // -- Not same because it is not a referance object (float)
        Assert.IsFalse( object.ReferenceEquals(
            ((LaserDisruptor)prototypeObject.ShallowCopyWeapon).RateOfFire,
            ((LaserDisruptor)clonedMonkey.ShallowCopyWeapon).RateOfFire),
            "Fail10"  );
    }
}

Your Own “Servlet” or HTML Spew Machine

So you want a quick way to spew your own html?

Create an aspx page and remove all the html and then in the code behind replace the Page_Load procedure with:

private void Page_Load(object sender, System.EventArgs e)
{
    Response.Clear();
    Response.ClearHeaders();
    Response.ContentType = "Text/HTML";
    Response.AppendHeader( "your header", "your value" );
    Response.Write( "<html><body>Your spew</body></html>" );
}

Of course you don't have to spew html.

-Mr.Phil

When I am not writing about making games, procrastinating or watching movies I'm working on a science fiction strategy game (sometimes called 4X or empire builder.) Email me questions, ideas and jokes at mrphil (at) mrphilgames . com