Mar 09

Source code: http://www.bluerosegames.com/spacerocks/SpaceRocks_3_Sprites_2.zip

In the last step we created a sprite class based on the Silverlight Templated control. We gave this class X and Y properties to position the sprite. This is a great start and combining that with our game loop from step 1 we could start putting together the basics for a game. In our Space Rocks game, sprites will move based on a velocity. Let’s see how we can add code to the sprite class to take care of this.

Velocities have an X and Y component and to calculate the position at any point in time we can calculate the distance traveled by multiplying the velocity by the time since the last time we set the position and add that to the previous position. This is where the SilverSprite core assembly can help us out. One of the things that this assembly provides for us in the XNA Vector2 data type. A Vector2 is a value data type (aka a struct) with an X and Y value and a bunch of helper methods to let us do game related things like multiplying by a value or adding two Vector2 values together. Let’s implement a Position property on the Sprite class which is of type Vector2 and also create a Velocity property. Add the following to Sprite.cs:

public Vector2 Position
{
    get
    {
        return new Vector2((float)x, (float)y);
    }
    set
    {
        X = value.X;
        Y = value.Y;
    }
}

public Vector2 Velocity { get; set; }

You’ll also need a using statement for the Xna namespace:

using Microsoft.Xna.Framework;

For the Position property under the covers we are actually setting and getting the X and Y properties of the Sprite class. This allows us to use whichever makes the most sense for the task at hand.

One nice thing about using the SilverSprite core library to help us out is that you can start to get an idea about how to do some of the basics in XNA. This looks like it’s going to get more important with Windows Phone 7 Series if there is a game you want to develop that makes more sense to write in XNA. SilverSprite attempts to mimic the XNA APIs and doesn’t require XNA to be installed for you to use it.

Something that’s a little tricky about the Vector2 struct and most other things in XNA is that they use the float data type. Almost everything in Silverlight uses double. So we need to cast between the two when going back and forth. XNA uses float for its values for efficiency since these translate directly to the data structures used by the graphics card.

Let’s add a method to the Sprite class that we can call from our game loop to update the sprite position based on the current velocity and time since the last update.

public void Update(double elapsedSeconds)
{
    Position += Velocity * (float)elapsedSeconds;
}

This is where Vector2 starts to shine. We can simply use addition and multiplication operators and we don’t have to worry about the X and Y components.

Now in the Game class, we’ll make some changes to use the Position and Velocity properties and we’ll keep a reference to the sprite object so that we can reference it in the GameLoop_Update method.

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

namespace SpaceRocks
{
    public partial class Game : UserControl
    {
        Sprite sprite;

        public Game()
        {
            InitializeComponent();
            sprite = new Sprite();
            sprite.Position = new Vector2(100, 50);
            sprite.Velocity = new Vector2(100, 100);
            LayoutRoot.Children.Add(sprite);
        }

        private void GameLoop_Update(object sender, SilverArcade.SilverSprite.SimpleEventArgs<TimeSpan> e)
        {
            double seconds = e.Result.TotalSeconds;
            sprite.Update(seconds);
        }
    }
}

Now the sprite should move diagonally. You can play with the velocity values and see how it behaves. You can even use negative values for the X and Y components of the velocity.

One problem we have is that the sprite now moves right off of the edge of the screen. In our game we want these values to “wrap” and if they get too large or too small, we’ll move them to the other end of the screen. We can do this in our Sprite.Update method.

static Vector2 gameSize = new Vector2(640, 480);

public void Update(double elapsedSeconds)
{
    Position += Velocity * (float)elapsedSeconds;
    if (Position.X > gameSize.X) Position -= new Vector2(gameSize.X, 0);
    if (Position.X < 0) Position += new Vector2(gameSize.X, 0);
    if (Position.Y > gameSize.Y) Position -= new Vector2(0, gameSize.Y);
    if (Position.Y < 0) Position += new Vector2(0, gameSize.Y);
}

Now if you run the game the sprite should wrap when it hits the edge. One thing you’ll probably notice is that the sprite goes off of the end of the game surface. The Canvas panel doesn’t clip to its bounds by default so we can add a Clip property to the game canvas.

<Canvas x:Name="LayoutRoot" Background="Black" Width="640" Height="480">
    <Canvas.Clip>
        <RectangleGeometry Rect="0,0,640,480"/>
    </Canvas.Clip>
</Canvas>

This isn’t necessary if your game fills the entire Silverlight plug-in and has some overhead so only use it if you need it. Now if you run the game the edges should be clipped and you won’t see the sprite go off of the game surface.

In the next post we’ll look at inheriting from the Sprite class and creating the ship for our asteroids game.

Mar 09

Source code: http://www.bluerosegames.com/spacerocks/SpaceRocks_2_Sprites.zip

When we refer to a “sprite” in game development, we’re typically referring to any 2D visual element. Sometimes sprites are defined as only elements that can move but since any element in Silverlight can be moved by repositioning it, the definition still fits. In the Space Rocks game, the sprites will be the ship, asteroids, bullets, particles, and enemy ships.

These elements share some common needs including the following:

  • Movement based on velocity
  • Collision detection
  • Ability to “wrap” when hits edges of screen

The common behaviors of sprites for your game really depends on the game itself and so it’s difficult to create a general purpose sprite class that meets all of your needs. Generally when starting a new game I grab a sprite class I’ve done before that’s closest to what I need and then tweak it for the current game. Odds are that the sprite class we create for this game won’t do exactly what you need but it can be a good starting point to create your own.

I’ve tried a few different techniques for creating a sprite class, but the one I’ve settled on is to use a templated control. Templated controls are nice for sprites because it’s easy to inherit from a base class while still making the sprite look however you want. It’s also easy to edit these templates in Expression Blend to design your sprites.

Let’s create a Silverlight Templated Control called Sprite.cs.

image

When you create this, the class is generated as follows:

using System.Windows.Controls;

namespace SpaceRocks
{
    public class Sprite : Control
    {
        public Sprite()
        {
            this.DefaultStyleKey = typeof(Sprite);
        }
    }
}

The default style key is set to typeof(Sprite) and this corresponds to an entry in Themes/Generic.xaml. This entry looks like this:

<Style TargetType="local:Sprite">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:Sprite">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

You can replace the contents of the ControlTemplate with whatever you want. Let’s just set a couple of properties on the Border so that we have a default sprite that can be displayed if we’re not inheriting it with a custom template.

<ControlTemplate TargetType="local:Sprite">
    <Border
            BorderBrush="{TemplateBinding BorderBrush}"
            BorderThickness="{TemplateBinding BorderThickness}" Width="50" Height="50" Background="Red"/>
</ControlTemplate>

This will display a 50×50 red square.So let’s see how we can add this sprite to our game control. The game control currently had a Grid as its root element. We don’t really need the layout features of a Grid for this game, so we can change the root element to a Canvas. You can also remove the TextBlock we used in the last sample, and make sure to remove the code from the GameLoop_Update method too. This is our new Game.xaml:

<UserControl x:Class="SpaceRocks.Game"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	Width="640" Height="480"
	xmlns:local="clr-namespace:SpaceRocks"
	xmlns:silverSprite="clr-namespace:SilverArcade.SilverSprite;assembly=SilverArcade.SilverSprite.Core">
    <UserControl.Resources>
        <silverSprite:GameLoop x:Key="gameLoop" Update="GameLoop_Update" />
    </UserControl.Resources>
    <Canvas x:Name="LayoutRoot" Background="Black" Width="640" Height="480">
    </Canvas>
</UserControl>

Now to add the sprite. You can add it in XAML, but many times in a game you want to have more control over when your sprites are displayed so let’s add it in code. In the Game constructor after the InitializeComponent() method we’ll create a sprite and add it to the canvas’ children:

using System;
using System.Windows.Controls;

namespace SpaceRocks
{
    public partial class Game : UserControl
    {
        public Game()
        {
            InitializeComponent();
            Sprite sprite = new Sprite();
            LayoutRoot.Children.Add(sprite);
        }

        private void GameLoop_Update(object sender, SilverArcade.SilverSprite.SimpleEventArgs<TimeSpan> e)
        {
        }
    }
}

And here is what it looks like when you run the game:

image 

 

Pretty cool huh? Ok so that’s not very exciting. Let’s see what we can do about positioning this sprite. For elements on a Canvas, you can use the Canvas.Left and Canvas.Top attached properties to position them. To avoid doing GetValue and SetValue all over the place and also to only set the attached properties if something changed, we can add an X and Y property to our sprite class which will set these for us.

using System.Windows.Controls;

namespace SpaceRocks
{
    public class Sprite : Control
    {
        double x, y;
        public Sprite()
        {
            this.DefaultStyleKey = typeof(Sprite);
        }

        public double X
        {
            get
            {
                return x;
            }
            set
            {
                if (x != value)
                {
                    x = value;
                    this.SetValue(Canvas.LeftProperty, x);
                }
            }
        }

        public double Y
        {
            get
            {
                return y;
            }
            set
            {
                if (y != value)
                {
                    y = value;
                    this.SetValue(Canvas.TopProperty, y);
                }
            }
        }
    }
}

By storing off the x and y values we don’t need to call GetValue to get those properties if needed. Now if you add the following lines to the Game constructor:

sprite.X = 100;
sprite.Y = 50;

And run the game again you’ll see that the sprite is positioned according to our X and Y values.

image

Mar 08

Source code: http://www.bluerosegames.com/SpaceRocks/SpaceRocks_1_GameLoop.zip

Most games require a game loop which is simply a method that executes on a timer. This method can contain things like input handling, repositioning sprites, checking for collisions, or spawning particles. In Silverlight there are a few options for this, including using a zero duration Storyboard, a DispatcherTimer, or the CompositionTarget.Rendering event.

We’ll be using the SilverSprite core assembly for this project, you can learn more about it here:

http://blogs.silverarcade.com/silverlight-games-101/08/silverlight-silversprite-not-just-for-xna-games-any-more/

The SilverSprite core assembly contains a general purpose game loop you can use. This game loop uses the CompositionTarget.Rendering event. This event fires once per frame so it’s a good choice for a game loop.

It’s also useful to keep track of how long it’s been since the last time the game loop executed so that you can handle things like running at different frame rates. The SilverSprite game loop does this for you too. This will probably get even more important when Silverlight moves to other platforms like Windows Phone.

First let’s create a new Silverlight application and call it SpaceRocks. Take the defaults for creating a web application.

In order to use the SilverSprite core assembly we need at add a reference to the Silverlight project. The reference we need is to SilverArcade.SilverSprite.dll.

UPDATE: I had a typo in the name of the SilverSprite core assembly. The assembly we really need is SilverArcade.SilverSprite.Core.dll.

You can get this assembly from this link:

http://silversprite.codeplex.com/releases/view/41574

or you can get it from the source code included at the top of this post.

Next in the SpaceRocks project, add a new Silverlight User Control called Game.xaml. It’s a good idea to keep logic out of your MainPage.xaml and just use it as a container for other controls. Then in MainPage.xaml  we’ll add the Game control:

<UserControl x:Class="SpaceRocks.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480"
    xmlns:local="clr-namespace:SpaceRocks">
    <Grid x:Name="LayoutRoot">
        <local:Game VerticalAlignment="Top" HorizontalAlignment="Left"/>
    </Grid>
</UserControl>

Notice the xmlns:local attribute. This tells Silverlight to look in the SpaceRocks namespace to find any elements that start with the local: prefix. Then we add the Game control to the LayoutRoot Grid. In the  Game.xaml we can add our game loop object to the user control’s resources and while we’re in there we can set the width, height, and background color. We’ll also add a TextBlock to display something so that we can see the loop is executing.

<UserControl x:Class="SpaceRocks.Game"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	Width="640" Height="480"
	xmlns:local="clr-namespace:SpaceRocks"
	xmlns:silverSprite="clr-namespace:SilverArcade.SilverSprite;assembly=SilverArcade.SilverSprite.Core">
    <UserControl.Resources>
        <silverSprite:GameLoop x:Key="gameLoop" Update="GameLoop_Update" />
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" Background="Black">
        <TextBlock x:Name="text" Foreground="White"/>
    </Grid>
</UserControl>

Now for the Game control’s code behind file. In the code we’ll implement the GameLoop_Update event and put some code in to increment a number every time it executes and set the TextBlock’s text to that value.

using System;
using System.Windows.Controls;

namespace SpaceRocks
{
    public partial class Game : UserControl
    {
        int count = 0;
        public Game()
        {
            InitializeComponent();
        }

        private void GameLoop_Update(object sender, SilverArcade.SilverSprite.SimpleEventArgs<TimeSpan> e)
        {
            text.Text = count.ToString();
            count++;
        }
    }
}

Now if you run the program (we can’t really call it a game yet) you should see the number change as it gets incremented every time through the game loop.

image

We’ll do more interesting things with the game loop going forward, but this is a good starting point. If this works then we know that the SilverSprite core assembly has been referenced properly and that the game loop is firing once per frame.

Mar 08

The last time I started creating a sample game on this blog, I had to go through creating a game loop, handling keyboard input, dealing with vector mathematics, and a few other low level tasks. Along the way I created a helpers library which people could use to get started with their own games. A good amount of code from these samples made its way into SilverSprite, a free open source library that I created to make it easier to get XNA 2D games running in Silverlight. Because of my work on this library and other life changes such as writing a book and becoming an independent consultant and then finally ending up at Vertigo, this game development blog became almost non-existent. I’m looking to change that now.

Last night I released an Alpha 2 of the SilverSprite library for Silverlight 3.

One of the major changes is that I split out some of the core functionality that I thought would be useful to Silverlight game developers that didn’t need all of the XNA related graphics and content management stuff. This core assembly, named SilverArcade.SilverSprite.Core.dll is 69k, and in your XAP file it will compress down to under 29k. This isn’t a major size hit, and gives you the following:

  • An easy to use game loop class
  • Vector2, Vector3, and Matrix structures
  • MathHelper methods including linear interpolation helpers
  • A color tint pixel shader that can be applied to any element
  • Keyboard input helpers
  • Mouse input helpers

I will also be looking at moving some of the sound effect classes into the core going forward.

Along with this new assembly being available, I’ll be starting over on my Asteroids clone sample using this assembly and will cover its key features as we progress. I look forward to being able to focus on common game development tasks and letting the SilverSprite code assembly take care of a bit of the plumbing.

If you are already familiar with SilverSprite, one of the other major changes with this release is that we are now using the Microsoft.Xna namespaces to make it easier to get XNA code ported over. There are some great free libraries such as physics engines which can be useful for Silverlight games and these are now a whole lot easier to get working. SilverSprite is distributed under the MIT license and is free to use in binary form in any commercial or non-commercial project.

http://silversprite.codeplex.com

Jan 10

I get a huge kick out of other people using things that I’ve created and especially when they do things that I haven’t even imagined and take it to the next level. Adam Kinney posted about doing a torn photo effect with the image blitting methods that I contributed to the open source WriteableBitmapEx project on codeplex. For those not familiar with image blitting, it is when you copy a bitmap into another bitmap as fast as you can.

What’s especially cool about this post is that he was reproducing a tutorial previously done in Flash and it would have been much more difficult without these methods. Even more exciting is that Adam has contributed some extra blending modes that he needed back into the project so everyone can benefit from them. I took at look at the original Flash tutorial and it seems more complicated than the Silverlight version but I don’t know enough about Flash to have more than a general feeling about it.

Here is the final result of Adam’s sample:

torn

Pretty cool and it will take any image and do some random and dynamic effects to make it look torn and crumpled.

Adam’s original post is here: http://adamkinney.wordpress.com/2010/01/09/image-blitting-in-silverlight-with-writeablebitmapex/

Jan 08

This is a video of a presentation I did for the XNA Calgary Users Group recently. It runs about a 30 minutes and is a good introduction to getting started with Silverlight game development and some of the things to watch out for. I also cover using the SilverSprite library to make game development easier for those already familiar with XNA. Please forgive the stuffy nose as I was a bit under the weather when doing this presentation.

Click on the image below to go to the video hosted on Screencast.com

slgamedev

The samples and powerpoint for the presentation can be downloaded at http://www.bluerosegames.com/slgamedev.zip

Jan 07

My laptop has a 16 inch screen with 1920×1080 resolution and my eyes aren’t what they used to be so I run in high DPI mode 125%. This makes all of my icons and text bigger, but it also sets IE to 125% zoom. This is fine for the most part except for some apps that don’t handle it properly. For the most part these apps have been Flash, such as the Radar Map on Weather.com:

http://www.weather.com/weather/map/interactive/USFL0291?from=36hr_topnav_undeclared

Try it with a zoom other than 100% and you’ll see what I mean. One of the worst cases of this I saw was a series of AT&T banner and skyscraper Flash ads that didn’t handle zoom properly and had a lot of black space on the right and bottom. Not the best user experience for your ads. UPDATE: Found an AT&T ad having the issue:

att

For the most part, Silverlight handles this zoom for you and scales your application automatically. I have however run into a couple of Silverlight apps that have issues. Generally it seems to have to do with javascript integration and if you rely on values coming back from Javascript for positioning and don’t take the zoom into account.

A little unrelated, but here is a tip related to browser zoom and Silverlight. If someone has developed a Silverlight app that is too big for you to fit on the screen you can crank down your browser zoom (75%) to make it fit. This is especially useful for netbooks with their lower resolution screens.

Browser zoom issues will become more common as more people on Windows 7 discover the high DPI settings. These have been made easier to get to and understand while the screen resolution settings have been hidden away.

Dec 07

Just a quick note that Rene Schulte has posted the full source code for his WriteableBitmap extensions to CodePlex at 

http://writeablebitmapex.codeplex.com 

He has also included my image blitting extensions that I posted about here:

http://blogs.silverarcade.com/silverlight-games-101/15/silverlight-blitting-and-blending-with-silverlights-writeablebitmap/

Rene’s helpful extensions include methods that draw shapes and lines. Enjoy!

Nov 21

In a recent article in The Register http://www.theregister.co.uk/2009/11/20/silverlight_4_windows_bias/ they make the case that COM support in Silverlight 4 has “crossed a threshold” that will make Silverlight less appealing to developers that want to do cross platform development.

Yes it is true that now there is a feature in Silverlight that is Windows only, but it is still a Beta and not a released product so it is possible that some Mac native integration will come as well. Clearly it would have to be different since Mac doesn’t support COM, but hopefully if added it would be done in such a way that the interfaces on native APIs on both platforms from Silverlight would be similar.

Adobe AIR 2 is also adding native API support, and I don’t have the details on how it all works, but clearly once you start making native calls there are going to be differences in how they are called because no two platforms are identical. One of the top feature requests for AIR 1.0 was native API integration, so this is definitely something people want.

The key point in my opinion is whether COM support makes it harder for someone to develop a cross platform application in Silverlight. I feel the answer is clearly “no”, simply avoid the COM APIs if you want a cross platform application.

You’re not forced to use the COM APIs, but if you want to provide extra functionality on Windows the COM interfaces can come in very handy for things like integration to Microsoft Office, and I look forward to seeing what people come up with using this new feature. There was, by the way, a Windows 7 only feature in Silverlight 3, the ability to use multitouch. And similarly, if you wanted to write a cross platform Silverlight app you would just avoid the multitouch library.

One of the complaints I always has about Java’s “write once run anywhere” approach was that it never took advantage of the strengths of the platform, so it felt like a second class citizen everywhere. I’m pleased to see COM support in Silverlight 4 and hope to see some Mac integration as well. So is Silverlight moving away from cross platform? I don’t think so, and they would be crazy if they did. I’m sure there were a lot of internal discussions on whether to provide this feature and they came to the conclusion that the benefits outweighed any backlash they might get.

Nov 15

Full source code: http://www.bluerosegames.com/BlitWriteableBitmapSample.zip

This post is partially inspired by René Schulte’s series on extending WriteableBitmap. You can see his fantastic posts here:

http://kodierer.blogspot.com/2009/11/drawing-shapes-silverlight.html

The other inspiration for this comes from efforts that I have been making with SilverSprite, an open source library to compile and run 2D XNA games in Silverlight. When rendering a lot of bitmap sprites to the screen using traditional Silverlight techniques of adding Images to the visual tree works fine for tens or even a couple of hundred of sprites, but add more than this and have them all moving around and this technique starts falling short.

There are some other issues as well, such as drawing with a tint or drawing with anything other than alpha blending. For cases such as these, I wanted to be able to offer an alternative and settled upon rendering (“blitting”) images myself to a WriteableBitmap. This functionality will make it into SilverSprite soon, but in the meantime you can take advantage of it now.

Following in René’s footsteps, I have implemented these methods as extension methods on WriteableBitmap. There are some overloads to simplify the call a bit, but they all end up calling this method:

public static void Blit(this WriteableBitmap bmp, Rect destRect, WriteableBitmap source, Rect sourceRect, Color color, BlendMode blendMode) 

Most of these parameters should be clear as to what they do. The part of the source bitmap that is specified is copied to the destination rectangle of the target bitmap. The image is scaled to fill the destination rectangle if the source and destination rectangle differ in size. The two parameters that need a bit more explanation are the color and blend mode.

The color, if not Colors.White, will tint the source image. You can specify a partially transparent color to draw with and the image will be drawn partially transparent.

The blend mode can be AlphaBlend, Additive, Subtractive, or None. AlphaBlend is what you’re used to with Silverlight, but it can be too limiting in some cases. Additive blending can be very useful. Instead of alpha blending the colors, the source and destination red, green, and blue colors are added together to get the resulting color.  Let’s consider 3 fully opaque circles, one each of red, green, and blue. With alpha blending, we get something like this:

 

alphaBlend

Whichever one is drawn last ends up on top. If the circles were partially transparent, the values would be alpha blended. For additive, we get something like this:

additive

The center is white because the red, green, and blue components are added together to make white. for subtractive we can start with a white background and draw:

subtractive

This is exactly what you would get if you inverted the colors in the additive example. This makes sense because we’re subtracting color values instead of adding them, so we’re doing an inverse operation.

Finally, with blend mode None, The source pixels are copied as is to the target, and so the transparent areas of the source image are drawn overwriting the values that were there:

none

 

One place where additive blending is useful is with particles effects. Particle effects look more natural and impressive when using additive blending. Here is an example of using additive blending with particles. The particle emitter follows the mouse. The source code for this sample is included at the top of this post.

preload preload preload