Silverlight Development

Packt Publishing, the folks who published our Microsoft Silverlight 4 Business Application Development book have included some of the chapters of that book in a new mashup of their best selling Silverlight books. The new book is called Managing Media and Data in Microsoft Silverlight 4 and features great chapters from several different authors’ Silverlight books, covering the gambit from XAML and layouts to SharePoint integration to REST and RIA services.

In addition, they are also offering a discount on all Microsoft technology books during the month of May so be sure to check that out as well at Packt’s Microsoft Carnival!

Silverlight is still a great technology for business development, it eases deployment issues with distributed software, provides an interactive experience for users via a browser while maintaining the power of C# in the development life cycle.


Countdown to Fall!


Silverlight and Windows Phone 7 Game

With the release of Silverlight 4 RC the Windows Phone 7 developer tools I wanted to take a stab at building a Silverlight application for both the web and phone to see what kind of differences there are between the two. Except for the inability to use the ChildWindow I was able to build out controls and share them between the two applications. The main differences were in the MainPage.xaml that is created, along with the default styles, when you create a new Silverlight application for the web and Windows Phone 7. Of course,

I decided to create a game (called ShapeAttack) to see how it would perform on the phone emulator. Sad to say the performance on the emulator is very poor but I would imagine that it would be better on the physical device but as I do not own a Windows Phone 7 yet the emulator has to do for now. For that reason I would recommend doing this parallel type of development so you can actually test your application.

What I did was create all of the game code in UserControls, including the main game surface, then I linked the files from the standard Silverlight project into the phone project.

The game is very simple and kind of cheesy :D, just click on the shapes to destroy them. And of course you can download the source code for ShapeAttack(2.8MB) or play ShapeAttack online.



Performance Tips for Silverlight on Windows Phone 7

Andy Beaulieu has some helpful performance tips for Windows Phone 7 and Silverlight primarily focused on games of course.


Silverlight Community

Jeff Weber, the guy behind the Farseer Physics Engine, has posted an An Open Letter To Microsoft Regarding The Silverlight Game Development Community. I fully agree and want to add my voice in the request for an XNA-like community site!

From Jeff’s post:

“I hereby request, on behalf of all the future and present Silverlight game developers,  an awesome Silverlight game development portal along the lines of what exists for the XNA Creators Club Online community.”


Bug in Windows Phone 7 Emulator for Multi-Threading

Laurent Bugnion has discovered a bug in the Windows Phone 7 emulator when multi-threading and has posted a workaround:


MIX 10 Sessions

Frank LaVigne has posted a very useful tool to download all of the MIX 10 session content.


Pirates Video

Here is a video of the Pirates game:



General Purpose Sprite Class

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.


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; }    }}
.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt{ background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }

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();        }    }}
.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt{ background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }

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>
.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt{ background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }

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


Yar, I do be re-visiting Pirates!

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

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.


Silverlight 4 Business Application Development – Beginner’s Guide

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.