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

Silverlight 4 Book Discount Codes!

by Cameron Albert 2. February 2010 13:14

If you plan on pre-ordering Silverlight 4 Business Application Development – Beginner's Guideuse the following codes to save some money!

MsSilver15 – Save 15% off hard copy of the book

MsSilver30 – Save 30% off the eBook

If you are looking to get into Silverlight this is a great intro book. Frank Lavigne starts the book out by getting you involved in the code right away and we try and keep the working code methodology through out. If you learn by doing then you will benefit from the book!

Tags: , ,

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

System.Xml.Linq Extensions

by Cameron Albert 19. January 2010 14:29

I thought I would some extension methods I have been using for a little while now for Linq to Xml. When loading and retrieving the attribute values from XML nodes via Linq there is a bit of code to write to make sure the attribute exists and that the value is a valid data type. Rather than having a bunch of code to do this I simply wrote some extensions that operate on an XElement and are targeted at returning the value of an XAttribute.

Usage:

var element = XElement.Parse("<value x=\"50.5\"/>");
var value = element.GetDoubleValue("x");

Anyway, here is the class for the extensions:

   1:  using System;
   2:  using System.Xml.Linq;
   3:   
   4:  namespace System.Xml.Linq
   5:  {
   6:      public static class XLinqEx
   7:      {
   8:          /// <summary>
   9:          /// Gets a short value for the specified attribute.
  10:          /// </summary>
  11:          /// <param name="element">The element to parse.</param>
  12:          /// <param name="attributeName">The XName of the attribute to parse.</param>
  13:          /// <returns>A short value representation of the attribute value.</returns>
  14:          public static short GetInt16Value(this XElement element, XName attributeName)
  15:          {
  16:              var attribute = element.Attribute(attributeName);
  17:              if (attribute == null)
  18:                  return 0;
  19:   
  20:              short result = 0;
  21:              Int16.TryParse(attribute.Value, out result);
  22:              return result;
  23:          }
  24:   
  25:          /// <summary>
  26:          /// Gets an int value for the specified attribute.
  27:          /// </summary>
  28:          /// <param name="element">The element to parse.</param>
  29:          /// <param name="attributeName">The XName of the attribute to parse.</param>
  30:          /// <returns>An int value representation of the attribute value.</returns>
  31:          public static int GetInt32Value(this XElement element, XName attributeName)
  32:          {
  33:              var attribute = element.Attribute(attributeName);
  34:              if (attribute == null)
  35:                  return 0;
  36:   
  37:              int result = 0;
  38:              Int32.TryParse(attribute.Value, out result);
  39:              return result;
  40:          }
  41:   
  42:          /// <summary>
  43:          /// Gets a long value for the specified attribute.
  44:          /// </summary>
  45:          /// <param name="element">The element to parse.</param>
  46:          /// <param name="attributeName">The XName of the attribute to parse.</param>
  47:          /// <returns>A long value representation of the attribute value.</returns>
  48:          public static long GetInt64Value(this XElement element, XName attributeName)
  49:          {
  50:              var attribute = element.Attribute(attributeName);
  51:              if (attribute == null)
  52:                  return 0;
  53:   
  54:              long result = 0;
  55:              Int64.TryParse(attribute.Value, out result);
  56:              return result;
  57:          }
  58:   
  59:          /// <summary>
  60:          /// Gets a double value for the specified attribute.
  61:          /// </summary>
  62:          /// <param name="element">The element to parse.</param>
  63:          /// <param name="attributeName">The XName of the attribute to parse.</param>
  64:          /// <returns>A double value representation of the attribute value.</returns>
  65:          public static double GetDoubleValue(this XElement element, XName attributeName)
  66:          {
  67:              var attribute = element.Attribute(attributeName);
  68:              if (attribute == null)
  69:                  return 0;
  70:   
  71:              double result = 0;
  72:              Double.TryParse(attribute.Value, out result);
  73:              return result;
  74:          }
  75:   
  76:          /// <summary>
  77:          /// Gets a bool value for the specified attribute.
  78:          /// </summary>
  79:          /// <param name="element">The element to parse.</param>
  80:          /// <param name="attributeName">The XName of the attribute to parse.</param>
  81:          /// <returns>A bool value representation of the attribute value.</returns>
  82:          public static bool GetBooleanValue(this XElement element, XName attributeName)
  83:          {
  84:              var attribute = element.Attribute(attributeName);
  85:              if (attribute == null)
  86:                  return false;
  87:   
  88:              bool result = false;
  89:              Boolean.TryParse(attribute.Value, out result);
  90:              return result;
  91:          }
  92:   
  93:          /// <summary>
  94:          /// Gets a string value for the specified attribute.
  95:          /// </summary>
  96:          /// <param name="element">The element to parse.</param>
  97:          /// <param name="attributeName">The XName of the attribute to parse.</param>
  98:          /// <returns>A string value representation of the attribute value.</returns>
  99:          public static string GetStringValue(this XElement element, XName attributeName)
 100:          {
 101:              var attribute = element.Attribute(attributeName);
 102:              if (attribute == null)
 103:                  return String.Empty;
 104:   
 105:              return attribute.Value;
 106:          }
 107:   
 108:          /// <summary>
 109:          /// Gets a byte array from the base 64 encoded value of the current element.
 110:          /// </summary>
 111:          /// <param name="element">The element to parse.</param>
 112:          /// <returns>A byte array of the base 64 encoded element value.</returns>
 113:          public static byte[] GetByteArray(this XElement element)
 114:          {
 115:              var value = element.Value;
 116:              if (!String.IsNullOrEmpty(value))
 117:              {
 118:                  return Convert.FromBase64String(value);
 119:              }
 120:              return null;
 121:          }
 122:      }
 123:  }

Tags:

Silverlight 4 Business Application Development – Beginner’s Guide

by Cameron Albert 18. January 2010 19:47

For those of you out there wanting to get into Silverlight development but just do not know where to start, Frank LaVigne and I have just about completed our book titled Microsoft Silverlight 4 Business Application Development – Beginner’s Guide(link to pre-order). This book will be ideal for current Windows or ASP.NET developers who want to learn Silverlight and because the book is centered on Business Application Development we will empower you with knowledge so you can recommend Silverlight for the next business project at your company.

Gaining the basics required to develop in Silverlight, make use of data binding, WCF and RIA Services you will be prepared to lead the Silverlight charge at your company. Be warned, once you start developing in Silverlight you will have a hard time going back to normal ASP.NET development.

Tags:

General | Silverlight | Silverlight Business Development

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

Silverlight 3 Book

by Cameron Albert 11. September 2009 13:16

As Frank LaVigne mentions in this post about a Silverlight 3 Book, I have been asked to co-author the book with him. I am honored that he asked me to help with completing the book and will work to deliver a solid book for any .NET developers out there getting their feet wet in the world of Silverlight business development. The book should give you some proof that Silverlight is a viable business tool and not just something for game developers to play with or to make web sites pretty.

Having already had the privilege of peer reviewing the first few chapters this is going to be a great intro to Silverlight, Frank is all about getting right into code!

Tags:

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