Monday, June 29, 2009

ChatNDraw Silverlight Demo

My ChatNDraw Silverlight demo is completed. ChatNDraw is a Silverlight-based chat program that lets you create new chat rooms, chat with others who happen to be logged in, and draw in different colors using a shared blackboard.

ChatNDraw was created using my PrismServer component suite that I just converted to WPF/Silverlight from WinForms (.NET 2.0). I plan to release the source for PrismServer as soon as I can complete the documentation.

ChatNDraw Demo

Friday, June 26, 2009

Rebirth of PrismServer - for Silverlight!

I'm almost finished with the Silverlight/WPF port of PrismServer. I have a live Chat server running now on the following page. I'm still working on the "Draw" part of the "ChatNDraw" Silverlight app, but for now you can help me test the server by logging in and "Chatting"!

Note - if you create an account here, it will become the eventual account you'll use for all SCG Silverlight games.

I wanted to get this news out to allow for some early testing. I do plan on creating a post describing the new PrismServer in more detail, and possibly a revised CodeProject article. For now, my fingers are falling off of my hands so I need a break from coding ;)

http://www.siliconcommandergames.com/ChatNDraw/TestPage.html

Tuesday, June 23, 2009

Death of TurboSprite


Earlier I began porting my object-oriented TurboSprite framework to WPF. This was relatively easy because WPF had the OnRender event and the DrawingContext that corresponds to WinForms Paint/Graphics combo.


When I decided to target Silverlight as the next platform for Silicon Commander Games development, one of the first hurdles was the fact that it did not expose the OnRender/DrawingContext feature of WPF. This forced me to use the animation system(s) built into Silverlight/WPF and abandon further development of TurboSprite.
One of the benefits of encapsulating animation in TurboSprite was its clean, object-oriented design. I could create animatable sprite classes that were self-contained and re-usable.


In Silverlight I am following the same philosphy of design, but using the animation model(s) provided by the framework. Note the plural!


Model 1 - Property Based Animation


This model works by creating Storyboard objects, and then adding animations (like DoubleAnimation, ColorAnimation, etc.) to its Children. You call Begin() to start animating, and can handle the Complete event when the animation is finished. You provide a Duration that controls how long the animation lasts. The Storyboard can have multiple animations in its Children collection. Each animation targets a specific property of a specific object.


I use this method when I need to move an object from one cell to another on the game grid. To simplify the model, I created a base class called SquareGridGameBoard that derives from UserControl. SquareGridGameBoard allows you to set the number of cells that compose the game board, as well as the width and height of each cell. It also provides a visual cell cursor, and a selection band that facilitates selecting a range of cells. SquareGridGameBoard also contains helper methods that make it easy to position, and move, an element on the game board.


The MoveElement helper method encapsulates the plumbing of creating a Storyboard, the animations, and handling the completed event. Here's the code:



//Move an element to another cell
public void MoveElement(UIElement element, int newX, int newY, Duration duration)
{
//Create Storyboard, and remember the element it references
Storyboard sb = new Storyboard();
sb.Completed += MoveCompleted;
_storyboardTargets[sb] = element;


//Animate X coordinate
DoubleAnimation animX = new DoubleAnimation();
animX.To = newX * CellWidth + _cellWidthHalf;
animX.Duration = duration;
sb.Children.Add(animX);
Storyboard.SetTarget(animX, element);
Storyboard.SetTargetProperty(animX, new PropertyPath("(Canvas.Left)"));


//Animate Y coordinate
DoubleAnimation animY = new DoubleAnimation();
animY.To = newY * CellHeight + _cellHeightHalf;
animY.Duration = duration;
sb.Children.Add(animY);
Storyboard.SetTarget(animY, element);
Storyboard.SetTargetProperty(animY, new PropertyPath("(Canvas.Top)"));
sb.Begin();
}


//Animation finished
private void MoveCompleted(object sender, EventArgs e)
{
//what element was being moved?
Storyboard sb = sender as Storyboard;
UIElement element = _storyboardTargets[sb];
_storyboardTargets.Remove(sb);


//push values into properties after animation changes them
double x = Canvas.GetLeft(element);
double y = Canvas.GetTop(element);
sb.Stop();
Canvas.SetLeft(element, x);
Canvas.SetTop(element, y);
}


You can see this in action in the current demo as of Build 7. When you click on a cell of the game map, it creates a random StarShip, but also moves a StarSystem to that location, using the MoveElement method described above.


Model 2 - Frame-Based Animation


Another animation option that Silverlight provides is enabled by creating an event handler for the static CompositionTarget.Rendering event. When you do this, Silverlight calls your handler on each frame of animation. The default frame rate is 60 FPS, but this is adjustable by adding the "maxFramerate" parameter in your HTML.


I use this method to cycle the colors of an array of 10 SolidColorBrushes that draw the Shields around StarSystems. The Ellipse elements that compose the Shields have their Stroke properties set to one of the brushes in this static array. When the color of one of the brushes changes, it impacts all of the Shield Ellipses that used that brush in their Strokes.


You can see the Shield color cycling in action in Build 7 of the demo.


http://www.siliconcommandergames.com/SVSilverlight/TestPage.html


Sometimes it makes sense to use property-based animations, but sometimes frame-rate animations are a more logical choice. There's no need to sacrifice, use both models, and select the one that makes the most sense for each particular animation task in your Silverlight app!

Monday, June 22, 2009

Silverlight Nebula


Today I cracked the problem of how to dynamically generate a bitmap that represents the background of the game map for Solar Vengeance Silverlight. Silverlight does not provide out of the box any class or method that allows you to simply create an offscreen bitmap and render its pixels using drawing methods. In Silverlight 3, this will be addressed by the inclusion of the WriteableBitmap class, but I wanted to move forward in Silverlight 2 and wait until 3 is released before switching to that version for my development.


Fortunately I was not the only one who was having this problem, and I came upon Ian Griffith's weblog posting here (http://www.interact-sw.co.uk/iangblog/2008/11/07/silverlight-writeable-bitmap) where he describes his PngGenerator class. This class suited my needs perfectly, and it looks like I will be able to easily swap in the WriteableBitmap when Silverlight 3 is released.


Now, here's the process flow of my nice new Nebula image in Solar Vengeance Silverlight,



  • I call the BuildScenario method of a Scenario-derived class (in this case Classic).

  • Classic creates some random Nebula in the SVGame object.

  • I create a PngGenerator of 100x100 pixels in size, representing the full number of cells in the map grid.

  • For each cell that contains a Nebula, I set the pixel to a bluish color, otherwise set it to black.

  • I make the image the source for an Image object and add this to the Canvas of the game board, sizing it to the full dimensions of the board (3,500 x 3,500) and setting its Stretch property to Stretch.

I was expecting to see sharp edges in the blown up image, but was surprised and happy to see the blended edges that Silverlight produced. Another hurlde overcome (this time thanks to Ian) in my quest to port Solar Vengeance to Silverlight.


See the latest demo build here:


C:\Silicon Commander\NET3.5\SV.Silverlight\SCG.SolarVengeance\Bin\Debug\TestPage.html



Wednesday, June 17, 2009

Markov Name Generator C# Class

A Markov Chain is a way of generating a result based on the statistical probabilities in a set of sample data. The MarkovNameGenerator class can generate random words (names) based on a set of sample words that it takes as input.

It works by building "chains" that count the number of occurrences of each letter in the alphabet after each group of "N" letters in the sample name. "N" is called the "Order" of the Markov Chain.

The class generates a new name by first selecting a random group of "N" letters to begin the name. It then goes forward letter by letter, examining the Chains and picking a new letter from the pool of letters that followed the previous "N" letter groups in the sample data.

For example, the words "Sally Sells Seashells" breaks down into the following 2-Order Chains:

SA-(L)
AL-(L)
LL-(Y)
LY-(End)
SE-(L,A)
EL-(L,L)
LL-(S,S)
LS-(End,End)
EA-(S)
AS-(H)
SH-(E)
HE-(L)

Note the Chains in yellow. These represent 2 letter pairs that occurred more than once in the sample words. The Chain contains all of the letters that follow the single pair of letters.

Now, when the generator makes a new random name it follows this sequence:

1 - Pick a starting pair of letters randomly:

AS

2 - Pick a random letter in the Chain following AS. In our example the only one is H.

AS->H

3 - Continue picking random letters in the chain until we get an end.

A(SH)->E
AS(HE)->L
ASH(EL)->L
ASHE(LL)->S

Result = Ashells

In this sample, we never encountered the SE pair, but if we had, we would have appended one of the two candidate letters in the chain randomly.

The fun comes when you feed the name generator with a large number of sample names. The generator, particularly when set to an Order of 3, can produce new names that bear a remarkable similarity in style to the sample names, while still being original.

Using the Class

The MarkovNameGenerator class constructor takes 3 arguments:

public MarkovNameGenerator(IEnumerable sampleNames, int order, int minLength)

The first parameter is the collection of sample names. This can be an array or list of strings. Each string can contain one sample name, or a number of samples separated by commas.

The second parameter determines the Order of the Markov Chains, and the last parameter specifies the minimum length of a generated name.

Accessing the NextName property returns a new random name based on the sample data. The class ensures that the same random name is not returned twice.

Call the Reset method to clear out the internal list of previously generated names.

Download

Click here to download the MarkovNameGenerator.cs C# file.

Silverlight Sample App

http://www.siliconcommandergames.com/markov/TestPage.html

Monday, June 15, 2009

Vector or Image?

I'm learning that to take best advantage of the graphical model in WPF/Silverlight I need to shift much of the design work from bitmap based images to vector based graphics. This is especially true in Silverlight which has a much more limitted .NET class library, and no direct support for colorizing images.

In Solar Vengeance, I have a set of grayscale images that represent each StarShip type. When a game begins, SV dynamically generates colorized versions of the images for display. This was easy to do in WinForms and System.Drawing. I haven't found a reasonable solution to this in Silverlight. The WriteableBitmap class that's coming in Silverlight 3 might be a solution, but along the way I have found a better way.

The StarShip graphics for SV are very simple representations, and lend themselves well to vector based graphics. I can create custom classes in Silverlight that render the images using a combination of the simple graphics primitives that Silverlight offers, like Rectangle and Ellipse.

By creating a common StarShip visual base class, I can provide a single "Color" property that gets inherited to the customized rendering classes.

In the latest update of my demo app I render some StarShip types in a list box with a vector based version next to the image based. My work in progress is here ...

http://www.siliconcommandergames.com/SVSilverlight/TestPage.html

Sunday, June 14, 2009

Foray into Silverlight

I finally installed the Visual Studio 2008 Service Pack 1 and the Silverlight 2 development tools. I created my very first Silverlight test project today! Along the way I found something rather alarming. Visual editing of the design surface is not possible for Silverlight apps in Visual Studio 2008! You cannot drag and drop controls on the Window, nor can you edit the properties of controls using the Property Window in VS2008. My XAML chops are getting better every day, but this will really force me to exercise them. I understand the VS2010 might include design time support for Silverlight, which would be most welcome. On the other hand, this might finally push me to get off my behind and get Expression Blend.

Another position was that my fledgling port of the Solar Vengeance logical engine class library ported to Silverlight without any errors or changes needed.

When I develop a game, I always strive to cleanly separate the logical data model from the user interface. I create a .NET Class Library project that contains the logical model of the game, and a separate project for the user interface.

By maintaining this strict seperation it is now much easier for me to port SV to another platform such as WPF and/or Silverlight. I'm also probably going to change how the multiplayer communication works. A beefed up custom PrismServer will use the same SV logical engine to create an instance of the game and serve as the "host" of the game. It will receive the orders from players, process the turn, and send the results back to each client on each Impluse.

I have some challenges ahead if I want to create an SV front end in Silverlight. In particular, Silverlight does not support the DrawingContext and OnRender method which is the basis of my TurboSprite animation system. If I want a Silverlight SV, I will have to leverage its animation model, perhaps building my lightweight framework around Composition.Rendering which lets you get at the animation loop in a WPF/Silverlight app.

For now, here's my first "Hello, World" Silverlight page ...

http://www.siliconcommandergames.com/SVSilverlight/TestPage.html