Pirates Video

by Cameron Albert 11. March 2010 12:22

Here is a video of the Pirates game:

General Purpose Sprite Class

by Cameron Albert 10. March 2010 23:09

On the heels of some great posts by Bill Reiss on Sprites Part 1 and Sprites Part 2 in Silverlight I wanted to post some general base sprite classes that I use. The classes are intended to be used with the SilverSprite framework.

These classes all exist in an assembly I lovingly call the “Shady Engine” (to explain the namespaces)

The base class I used is ingeniously called Sprite. It implements an interface called ISprite. I added the interface in order to create an interface called IPlayer that the main Game class uses.

ISprite.cs

using System.Windows;
using Microsoft.Xna.Framework;

namespace Shady.Sprites
{
    public interface ISprite
    {
        ISprite Owner { get; set; }
        Vector2 Position { get; set; }
        double Rotation { get; set; }
        System.Windows.Point Scale { get; set; }
        double Width { get; set; }
        double Height { get; set; }
        Rect Bounds { get; }
        bool IsActive { get; set; }
    }
}

And here is the Sprite.cs file:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Microsoft.Xna.Framework;

namespace Shady.Sprites
{
    [TemplatePart(Name = PART_RootElement, Type = typeof(Canvas))]
    [TemplatePart(Name = PART_ContentElement, Type = typeof(ContentControl))]
    [TemplatePart(Name = PART_DebugCenter, Type = typeof(Ellipse))]
    [ContentProperty("Content")]
    public class Sprite : Control, ISprite
    {
        public const string PART_RootElement = "PART_RootElement";
        public const string PART_ContentElement = "PART_ContentElement";
        public const string PART_DebugCenter = "PART_DebugCenter";

        protected Canvas RootElement { get; set; }
        protected ContentControl ContentElement { get; set; }
        protected Ellipse DebugCenterElement { get; set; }

        protected TranslateTransform TranslateTransform { get; set; }
        protected RotateTransform RotateTransform { get; set; }
        protected ScaleTransform ScaleTransform { get; set; }

        protected double HalfWidth = 0;
        protected double HalfHeight = 0;

        public ISprite Owner { get; set; }    

        public object Content
        {
            get { return (object)GetValue(ContentProperty); }
            set { SetValue(ContentProperty, value); }
        }
        public static readonly DependencyProperty ContentProperty = DependencyProperty.Register("Content", typeof(object), typeof(Sprite), new PropertyMetadata(null));

        public bool Debug
        {    
            get { return (bool)GetValue(DebugProperty); }
            set { SetValue(DebugProperty, value); }
        }
        public static readonly DependencyProperty DebugProperty = DependencyProperty.Register("Debug", typeof(bool), typeof(Sprite), new PropertyMetadata(false, new PropertyChangedCallback(Sprite.OnDebugPropertyChanged)));
        private static void OnDebugPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var sprite = obj as Sprite;
            if (sprite == null)
                return;

            if (sprite.DebugCenterElement != null)
                sprite.DebugCenterElement.Visibility = (bool)e.NewValue ? Visibility.Visible : Visibility.Collapsed;
        }
            
        public Vector2 Position    
        {
            get 
            { 
                var x = (double)GetValue(Canvas.LeftProperty);
                var y = (double)GetValue(Canvas.TopProperty);
                return new Vector2((float)x, (float)y); 
            }
            set
            {
                SetValue(Canvas.LeftProperty, (double)value.X);
                SetValue(Canvas.TopProperty, (double)value.Y);
            }
        }

        public virtual double Rotation
        {
            get { return this.RotateTransform.Angle; }
            set { this.RotateTransform.Angle = value; }
        }

        public System.Windows.Point Scale
        {
            get { return new System.Windows.Point(this.ScaleTransform.ScaleX, this.ScaleTransform.ScaleY); }
            set
            {
                this.ScaleTransform.ScaleX = value.X;
                this.ScaleTransform.ScaleY = value.Y;
            }
        }

        public new double Width
        {
            get { return base.Width; }
            set
            {
                base.Width = value;
                HalfWidth = Width * 0.5;
                TranslateTransform.X = -HalfWidth;
                if (this.DebugCenterElement != null)
                    Canvas.SetLeft(this.DebugCenterElement, HalfWidth);
            }
        }

        public new double Height
        {
            get { return base.Height; }
            set
            {
                base.Height = value;
                HalfHeight = Height * 0.5;
                TranslateTransform.Y = -HalfHeight;
                if (this.DebugCenterElement != null)
                    Canvas.SetTop(this.DebugCenterElement, HalfHeight);
            }
        }

        public Rect Bounds
        {
            get
            {
                Vector2 position = this.Position;
                return new Rect(position.X - HalfWidth, position.Y - HalfHeight, this.Width, this.Height);
            }
        }

        private WriteableBitmap _bitmap;
        protected internal virtual WriteableBitmap Bitmap
        {
            get
            {
                if (_bitmap == null && this.ContentElement != null)
                {
                    var content = this.ContentElement.Content;
                    if (content != null && content is Image)
                    {
                        _bitmap = new WriteableBitmap((int)this.Width, (int)this.Height);
                        _bitmap.Render((content as Image), new TranslateTransform());
                        _bitmap.Invalidate();
                    }
                }
                return _bitmap;
            }
        }

        private bool _isActive = true;
        public bool IsActive
        {
            get { return _isActive; }
            set
            {
                _isActive = value;
                this.Visibility = _isActive ? Visibility.Visible : Visibility.Collapsed;
            }
        }

        public Sprite()
        {
            this.DefaultStyleKey = typeof(Sprite);

            this.TranslateTransform = new TranslateTransform();
            this.RotateTransform = new RotateTransform();
            this.ScaleTransform = new ScaleTransform();
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            this.RootElement = GetTemplateChild(PART_RootElement) as Canvas;
            this.ContentElement = GetTemplateChild(PART_ContentElement) as ContentControl;
            this.DebugCenterElement = GetTemplateChild(PART_DebugCenter) as Ellipse;

            if (DebugCenterElement != null && !Double.IsNaN(this.Width) && !Double.IsNaN(this.Height))
            {
                Canvas.SetLeft(DebugCenterElement, HalfWidth - 1.5);
                Canvas.SetTop(DebugCenterElement, HalfHeight - 1.5);
            }

            if (this.RootElement != null)
            {
                var group = new TransformGroup();
                group.Children.Add(TranslateTransform);
                group.Children.Add(RotateTransform);
                group.Children.Add(ScaleTransform);

                this.RootElement.RenderTransform = group;
                this.RootElement.RenderTransformOrigin = new System.Windows.Point(0, 0); // At 0,0 because the translate transform positions the sprite.
            }

            this.Initialize();
        }

        public virtual void Initialize()
        {
        }

        public virtual void Update(GameTime gameTime)
        {
        }

        public virtual void Draw(GameTime gameTime)
        {
        }

        /// <summary>
        /// Re-initializes the sprite.
        /// </summary>
        public virtual void Reset()
        {
            this.IsActive = true;
            this.Owner = null;
        }

        protected static void OnDependencyPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var sprite = obj as Sprite;
            if (sprite == null) return;
            sprite.Initialize();
        }
    }
}

Because Sprite is a templated control there is also some XAML to go along with it (You will need to place this in a themes/generic.xaml file):

<Style TargetType="sprites:Sprite">
        <Setter Property="Background" Value="{x:Null}"></Setter>
        <Setter Property="Foreground" Value="{x:Null}"></Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="sprites:Sprite">
                    <Canvas x:Name="PART_RootElement" Background="{TemplateBinding Background}">
                        <ContentControl x:Name="PART_ContentElement"/>
                        <Ellipse x:Name="PART_DebugCenter" Width="3" Height="3" Fill="Red" Visibility="Collapsed"/>
                    </Canvas>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

That is my basic Sprite class, I will post my animated sprite class next.

Tags: , , , ,

Silverlight Games | Silverlight | Game Development | General

Yar, I do be re-visiting Pirates!

by Cameron Albert 10. March 2010 13:03

One of the first games I started building in Silverlight I called Pirates! Since working on Perenthia and various other tasks I have not re-visited the game for a long time. I really would like to get this game finished so I have to decided to spend some time working on it. I hope to include some videos soon that show the game in varied stages of development. The first screen shot displays what currently exists after implementing some path finding and the SilverSprite library:

Here is the post from the game blog: Pirates Game in Silverlight

XNA and Silverlight Development

by Cameron Albert 1. February 2010 13:57

Mad Laumann has a new post up about the development progress of his game Little Longhorn, a tower defense game written for XNA and Silverlight using the SilverSprite framework. I have been following his progress with the game and have been able to play the early versions of it (both XNA and Silverlight) and have found it quite fun and challenging. The game has grown quite a bit over the last few months with game play and graphics improving all the time. Needless to say Mads is becoming an authority on XNA/Silverlight combination platform development so be sure to check out his blog A Silverlight Playground.

Tags: , , ,

Game Development | General | Silverlight | Silverlight Games

SilverMap – A Silverlight Game Tile Map and Editor

by Cameron Albert 10. December 2009 17:31

I am happy to announce that I have uploaded a new project called SilverMap to CodePlex. SilverMap is a tile map control for Silverlight games that uses layered maps where the higher layers are drawn over the lower ones. In addition, individual tiles have a z-index position and can be drawn over one another. You can also place the tiles anywhere on the map, instead of in a tight grid, which is both beneficial and kind of a pain. :)

SilverMap makes use of the WriteableBitmapEx library. I also used Danc's Miraculously Flexible Game Prototyping Tiles while testing and included them as a zip with the project.

The maps that are created can be saved as XML and the layering information is stored with them. You can set the opacity of a tile and in the near future will be able to scale and rotate them. Aside from the editor the SilverMap.UIMap control can be included in your game project and has the ability to load maps from a file stream (useful for maps that download on the fly).

The code is freely available under the Microsoft Public License so feel free to use it your games, whether they are free games or not.

SilverMap Editor

Tags: , , , ,

Game Development | Silverlight Games

Silverlight Tile Map using WriteableBitmap

by Cameron Albert 23. November 2009 12:52

Bill Reiss posted an interesting article and code the other day concerning the WriteableBitmap class and some extension methods. I downloaded the code and wrote a tiling map control using the WriteableBitmap class for my multi-player role playing game. Here is a snippet of the important piece of code that does the rendering:

   1:  private void RenderMap()
   2:  {
   3:      var xPos = _center.X - _halfX;
   4:      var yPos = _center.Y - _halfY;
   5:   
   6:      for (int y = 0; y < _numTilesY; y++)
   7:      {
   8:          for (int x = 0; x < _numTilesX; x++)
   9:          {
  10:              var tile = _tiles[new Point3(xPos, yPos, _zIndex)];
  11:              var terrain = Game.Terrain.Where(t => t.ID == tile.Terrain).FirstOrDefault();
  12:              if (terrain == null)
  13:                  terrain = Game.GetDefaultTerrain();
  14:   
  15:              _surface.Blit(new Point(x * TileWidth, y * TileHeight), 
  16:                  _tileImage, 
  17:                  _tileRect, 
  18:                  terrain.GetColor(), 
  19:                  BlendMode.AlphaBlend);
  20:              xPos++;
  21:          }
  22:          xPos = _center.X - _halfX;
  23:          yPos++;
  24:      }
  25:   
  26:      _surface.Invalidate();
  27:  }

The _surface variable is just a WriteableBitmap instance initialized to the width and height of the map control. The _tiles variable holds a list of the map tiles in range of the _center position. The xPos and yPos are the world coordinates and the terrain instance just holds the color to paint the tile.

The end result looks something like this:

perenthia tile map

Tags: , ,

Game Development | General | Perenthia PBBG | Silverlight Games

A Silverlight Games Star Field

by Cameron Albert 10. August 2009 20:58

Here is a really nice large star field in Silverlight if you are creating a space based game, or even if you are not it is still pretty cool. :)

Tags: ,

Game Development | Silverlight Games | Silverlight 2 Development

Silverlight and Multi-Player Games

by Cameron Albert 9. August 2009 20:31

I have been working on a multi-player library for Silverlight games over the past few months, well, off and on working on it while continuing Perenthia development.

I hope to be able to get the code on CodePlex before too much longer along with a tutorial on how to use it and a demo game.

The library will start with Duplex services but I do have plans to implement sockets in the future. Silverlight’s duplex and socket support is sufficient for RPGs and RTS or really any kind of turn based game but until Silverlight can support UDP sockets it is probably not suited to real time action games.

The goal is that the library can be used with any game engine such as SilverSprite or PlayBits and that it will provide easy to setup and use networking capabilities for your game.

The library is coming along well and I am building a demo game to help with implementation and testing that I hope to have finished in the next week or so.

Game Objects - My Design

by Cameron Albert 15. May 2009 18:34

I thought I would share one of the core concepts I implemented in Perenthia that has been working quite well. Early on in development I decided to create templates and instances in regards to game objects. A template would define common, unchangable properties of an object whereas an instance would be the opposite. An example would be a Sword; there is a template for a Sword that defines its damage value, price, required skill level, etc. 

I have one table that stores all the objects for the game. Since objects being actively used are loaded into memory and the table is indexed for those queries it runs pretty fast. Since I store all of the objects into one table I make heavy use of the XML data type in SQL 2005 to provide a bunch of XML Serialized Key/Value pairs that define the properties of an object. On the code side of things a dictionary provides the underlying data store for properties of the object. For instance, the Sword example above has a Power property that is used in combination with the wielder's skill in swords to determine damage. The Power property just fetches the Power value from the properties dictionary using the property name. This works a lot like the dependency properties, just my collection serializes to XML for database storage. When an object is loaded from the database the xml from the template is retrieved and added to the object, then the object instance xml is dropped into the object, overriding any template properties of the same name.

This property dictionary also allows me to store whether or not the property belongs to a template or instance. If the property belongs to a template then when the instance is serialized and saved to the database those template properties are excluded. Likewise saving a template does not serialize and save the instance properties. This structure allows for a lot of flexibility with my objects and has been working out quite well. I probably would not have used serialization and xml the way I am if I was doing a typical call to the database qith each request as the extra overhead would not have been worth the effort. However, since my objects are loaded into memory and my saves are background threaded I experience a lot of benefit of an easy to use object.

I shuld note that players character data is stored in a separate table from the core objects table. It follows the same design buy allows me to migrate and change data in the objects table without overwriting player data, since players are essentially the same as mobiles. 

Perenthia World Builder in Silverlight

by Cameron Albert 29. April 2009 00:01

I have been working to modify the tool I wrote for building the Perenthia world. The tool started life as a WinForms application, migrated to a WPF application but is now a part of the Silverlight Client UI. Since all of the actions are role based and controlled with permission on the server having it in the main client UI allows me to make use of all of the framework already in place for Perenthia.

The world builder UI connects to the server via WCF services tailored for world building. What this will also give me is the ability to open up the world builder to allow users to create custom dungeons, towns, etc.

Some features of the world builder are a background map of the world so I know where to place rooms, zoom capabilities that scale the map, draggable map and the ability to drag items, creatures, NPCs, etc. onto rooms on the map and configure the properties of each.

Powered by BlogEngine.NET 1.5.0.7
Modified Theme by Mads Kristensen

About the Author

CameronAlbert.com I am Senior Software Development Consultant specializing in Silverlight, WPF and the Microsoft .NET Framework. 

My current project Perenthia is a Silverlight multi-player game based in a fantasy world that combines text adventure games with some moderate graphics

View Cameron Albert's profile on LinkedIn
See how we're connected

Follow cameronalbert on Twitter

 

Recommended Books

Silverlight 4 Business Application Development - Beginner's Guide:

http://www.packtpub.com/microsoft-silverlight-4-business-application-development-beginners-guide/book

Microsoft Silverlight 4 Business Application Development: Beginner’s Guide