Silverlight and Windows Phone 7 Game

by Cameron Albert 27. March 2010 14:25

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.

ShapeAttack

Silverlight Community

by Cameron Albert 24. March 2010 23:03

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.”

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

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 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.

Client/Server Communication Data Formats

by Cameron Albert 5. January 2009 23:41

While developing Perenthia I tried several different communication formats from sending JSON serialized objects back and forth to sending byte arrays containing mostly integers indicating what should be loaded and displayed, what commands to execute etc. What I eventually settled on was a bit of a hybrid. I've created a simple set of "tags" that can be sent to and from the server. The tags are nothing more than pipe delimited strings contained within curly braces and there are a limited number of tags that provide simplicity yet flexibility with the data that is transmitted. The tags are represented in C# by tag objects allow me to create them, query them, etc.

A simple command tag for the SAY command might look like this: {CMD|SAY|"Hello World!"}

I wrote a custom tag writer class that parses the tag objects into strings to be sent to the client and likewise a tag reader that reads the strings sent from the client and parses them into tag objects.

The client can only send commands to the server but the server sends commands, messages and objects to the client. The commands are all the same, the CMD text then the one word name of the command and then a list of arguments, messages are system, chat and tell messages but objects have a bit more information. For instance, an object tag encompasses several different types starting with a base ACTOR, a PLACE, a PLAYER and a PROP or property. The ACTOR, PLACE and PLAYER tags all define the ID, Name and Descriptions of the objects, with some additional data per type but the PROP tag defines the object id of its owner and a name/value pair. An example of a PLAYER tag with properties for x, y and z coordinates might be:

{OBJ|PLAYER|3756|"Aldarian"|"My character description..."}

{OBJ|PROP|3756|"X"|45}

{OBJ|PROP|3756|"Y"|26}

{OBJ|PROP|3756|"Z"|0}

The client can find and parse the player tag and then find the properties associated with that player instance. The way the server works now it will send the full player tag once logged in and a character is selected and then from then on out it just sends property updates.

Using this type of tag structure allows quite a bit of flexibility for the client. I could choose to write a very simple client that only displays MSG tags, much like a MUD, I could write a simple 2D interface client and display and move sprites about the map using the properties from the server, etc. Once Perenthia is up and running I will probably post some information on the tags and how to talk with the server should someone feel the need to write their own client. :)

Almost Alpha Time!

by Cameron Albert 24. December 2008 00:42

For those waiting, Perenthia is almost ready for alpha. I have a few more things to complete and then the first phase of the Alpha will be ready. Hopefully you have had time to look over the various races, attributes and skills on the Perenthia web site and will be ready to create a character and begin your journey.

Here is a list of the remaining tasks I need to complete before Alpha, this does not include testing and fixing bugs with these features, just implementing them:

  • Spellcasting (Basic framework is in place, just need to define some spells and test them out)
  • Monster drops, including currency, gold, silver, etc. (They don't drop anything right now, stingy)
  • Help (Just need the framework in place as the help will get compiled during the alpha)
  • Quests (May not finish these for the first phase of alpha, want to try and keep it simple to start)
  • Some UI cleanup (got some windows not responding to updates from the server)
  • Content (Need to finish adding monsters to the dungeon, just the one dungeon for alpha)

I thought I would include a couple of screen shots along with this update. The first is a shot of the map window of the world builder tool I wrote for managing the places and things within the Perenthia world. This is the shot of the Alpha testing area, a small village called "Delcor". This view is actually a windows forms application with a WPF (ElementHost) control for rendering the map. The little red dots are NPCs that I can actually drag around into other rooms on the map after I create them, makes for moving the monsters in the dungeon a lot easier. :)

This second shot is the game user interface showing the same map that I was working on in the screen shot above.


Silverlight Game Contest

by Cameron Albert 23. August 2008 00:01

I thought I would take a little break from working on Perenthia and take part in a Silverlight Game Contest for a sports theme game. This will push out the alpha release date a little but I need a little change of pace.

I am a little late in deciding to do this but figured I would give it a try and see if I can come up with something fun by September 8th. I have an idea for a simple game, hopefully I can make it fun to play because I know it will be fun to build.

Once the game is finished I will also post the source code.

Storyboards not DispatchTimers for Silverlight Game Loops

by Cameron Albert 20. June 2008 16:55

Tags: ,

Game Development | Silverlight 2 Development | Silverlight Games

Just an Update

by Cameron Albert 10. June 2008 00:05

I am still plugging along on my games, working mostly on Perenthia and checking out the new stuff in Silverlight 2 beta 2. I want to try and get the Perenthia beta 2 up and running by the middle or end of the summer, free time permitting.

 I haven't blogged much lately but I have been working on a lot of stuff. I will try and get some posts together to outline some of the stuff I have taken advantage of in developing Perenthia such as adding files as links in Visual Studio and then using partial classes to separate server and client logic and multi-threading in Silverlight and how to avoid cross thread access, which you will get exceptions on now in SL 2 beta 2. I will also try and get some screen shots of Perenthia, quite a bit has changed since the last screen shot I posted and I would like to get some of the new ones up.

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. 

I have released an iPhone game called the Adventures of Puppyman that was built using ExEn and am currently working on a WP7 and iPhone version of Perenthia soon to be released.

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