Click here to Skip to main content
6,634,665 members and growing! (15,750 online)
Email Password   helpLost your password?
Web Development » Silverlight » General     Intermediate License: The BSD License

SilverStunts - a data driven game in SilverLight

By Antonin Hildebrand

The article discusses concepts of data driven web games. An example game 'SilverStunts' is presented and described in more technical details.
C# (C# 3.0), Javascript, XML, CSS, HTML, XHTML, Windows (Win2K, WinXP, Vista), .NET (.NET 3.5), Visual Studio (VS2008), XAML, Dev
Posted:31 Dec 2007
Views:30,828
Bookmarked:28 times
Unedited contribution
Announcements
Loading...
 
Search    
Advanced Search
Add to IE Search
printPrint   add Share
      Discuss Discuss   Broken Article?Report  
10 votes for this article.
Popularity: 4.65 Rating: 4.65 out of 5
1 vote, 11.1%
1

2

3
1 vote, 11.1%
4
7 votes, 77.8%
5

SilverStunts powered by SilverLight

Contents

Introduction

Making games is a great challenge and fun. Making web games is even more challenging for me. I have been always looking for new technologies and game concepts on the web. The release of SilverLight 1.1 Alpha at MIX'07 conference in April 2007 was a great opportunity to check this new platform and (possibly) push forward a game development on the web. At that time Microsoft had also released tools for SilverLight development: Visual Studio 2008 codename "Orcas" Beta 1 with Tools for Silverlight. I have downloaded the tools and spent several weekends working on a SilverLight game prototype to try some concepts on the new platform.

This article is divided into two parts:

  • In the first part the SilverLight platform is discussed from the game developer's point of view. Also some general concepts suitable for web games are presented.
  • In the second part a SilverStunts game project is described with more technical details. The SilverStunts project is a 2D physics driven game running in SilverLight scriptable with Python including in-game level editor.

The first part may be interesting for general audience interested in SilverLight, games and web trends. No previous SilverLight or programming background is needed.
The second part may be useful for programmers going to implement a game in SilverLight. The code may be used as a skeleton application for a new game project. It contains a novel aproach how to embed IronPython scripting and binding it to game objects. The second part expects C#, HTML and javascript background and reader to be familiar with SilverLight concepts and tools. Good introductory article may be Silverlight 1.1 Fun and Games or other articles in Silverlight section of CodeProject site.

A note just to be clear: Every notice about Silverlight is about version 1.1 (recently renamed to 2.0) which includes promising features for game developers.

Web Games

Browser is becoming solid application platform and many desktop applications tend to move on the web as web technologies are becoming more mature and broadband connectivity is cheaper. Interest about Web2.0 in last few years is about desktop application migration and new possibilites rising on the web (like sharing, collaboration, web services, data clouds and accesibility). And what about games? Are they ready to move to the web?

I think every technology making the web more rich platform may cause game development migration. At least some class of games which can benefit from new features. Let's see what features does SilverLight offer to game developers ...

SilverLight for game developers

SilverLight PROs:

  • Strong platform == .NET is a serious framework, enables language of choice, tons of documentation and huge community, which is source of quality developers
  • Great tools == Visual Studio for programmers and Expression Studio for designers
  • WPF/E (XAML) == accelerated 2D rendering engine for games (vector graphics, images, animations, sounds, fonts, ...)
  • Similarity with XNA == this opens great possibility build game for Web, Desktop and XBox sharing codebase and content
  • Dynamic Language Runtime (DLR) == enables programmers to emmbed scripting into their games (Python, Ruby, JScript, ...)
  • HD Video streaming == usable for cut-scenes and movie-like games
  • Fullscreen support == great playing experience

SilverLight CONs:

  • No low-level TCP/IP networking == Sockets are essential for creating fast network games (peer-to-peer). SilverLight provides classic AJAX-style networking over HTTP.
  • No framebuffer access (per pixel) == This makes sense in vector graphics engine, but game developers need some way to do post-process effects and image transformations. I wish some game related (fullscreen) effects to be introduced in new SilverLight versions.
  • User adoption == At this moment user adoption is slow because of product alpha stage. I'm looking forward how Microsoft will manage to push SilverLight onto users' machines.

Data driven games

A computer game usually contains:

  • a game content - game data like images, sounds, game maps, in-game texts, ...
  • a code implementing game logic - game rules, AI, player movement, storyboard, ...
  • a code implementing game hosting on given platform - keyboard and mouse inputs, rendering, playing sounds, reading files, OS interop, ...

First bullet is obvious and everybody understands it as a piece of data (i.e. zipped folder with images). Second bullet is more tricky. Game logic is a code, but can be also seen as a data. For example if a game logic is implemented as a script and run dynamically using some scriting engine. A script source is just a text, can be downloaded and manipulated like a data. So, let's count scripts into the game data. Third bullet is often called "a game engine". A game engine is code which is responsible for running game content. In other words a game engine is driving game data (including scripts).

Data driven game is a game with clear separation of game data and game engine. This is a very strong concept, but it is usually not very easy to achieve it. In the next sections I'm going to present motivation why you should care about and how it is related to SilverLight.

Motivation

When you think a little about it you may recognize some benefits of the data driven design:

  • game engine reusability
  • game tools reusability
  • game data may be crafted with different tools - game tools may be under independent development cycle
  • game data is portable more easily - we can rewrite an engine and possibly apply some data transformation (i.e. image size reduction)
  • game data can be streamed more easily

But there may be also some drawbacks:

  • data driven design is harder (more expensive) - it may take more time to finish first game, infrastructure maintenancy costs may be too high
  • performance - data driven engine may be slower and may eat more resources
  • platform restrictions - for example it is not viable on very limited platforms
  • data driven design pays off in bigger projects (with possible continuation)
In data driven design a game quality is strongly dependent on a data quality. And this is why tools are more important than engines in this "data driven world".

Data driven SilverLight

Microsoft does not bring SilverLight for game developers in the first place. Microsoft is offering SilverLight as a general platform for rich web applications. Fortunately, users of today's web applications strongly demand bells & whistles from desktop world. Microsoft is pushed to satisfy these demands in this new platform. That is good for games, "rich" means a shiny, faster and more sophisticated platform for games. In effect it means that data driven design becomes more viable in SilverLight and that is an opportunity to move on the edge and create stunning things.

I strongly believe it is possible to implement powerfull data driven 2D game engine in SilverLight. Silverlight contains two key technologies:

  • WPF/E rendering engine - accelerated 2D vector graphics, data driven (XAML is the data)
  • dynamic language runtime (DLR) - scripting engine, data driven (script is the data)

Going this way helps also with tools and portability. Microsoft Expression Studio is offering great foundation of tools for XAML authoring. Microsoft Visual Studio has been a daily bread for many game developers during past years. And what is new, Visual Studio can be turned into custom game editor using Visual Studio Extensibility (Shell). These tools are Widnows based, but their target platforms may be desktop Windows (WPF+.NET), Web (SilverLight) or XBox (XNA). This may open interesting chances to create cross-platform games more easily.

Going for web goodies

The web is strong in accesibility and collaboration. It is not needed to use whole Microsoft's infrastructure to create game data. We can build a game editor directly in the SilverLight and host it on the web for distributed content creation and customization by the crowd. The web community is creative and may be eager to participate on the game data "in the cloud". This enables new models for content creation and managing game life cycle.

And this can also enable new models for game marketing and profit generation. Web gaming and entertainment is significant part of web trends. For example, a novel approach in this field has Kongregate and I can imagine they will open SilverLight section for game creators and players soon. But this discussion is beyond scope of this article, let's see example implementation of data driven game in SilverLight ...


SilverStunts game - a proof of concept

SilverStunts is a simple 2D physics-driven game prototype similar to Elastomania. I was working on it during some weekends of May 2007. My goal was to learn the SilverLight a bit and evaluate it by creating a simple web game.

I've decided to use 2D Physics engine by Chris Cavanagh and ported it to SilverLight back in May. This article isn't about best physics engine for SilverLight. I haven't updated it, although Chris had ported his engine to SilverLight later in May. And as of today (December 2007) I would probably use Farseer Physics Engine for a new project. Physics engines are quite competitive these days and we can expect more to pop when final SilverLight 2.0 is released.

Features

  • Physics-driven 2D game
  • Scrolling
  • Levels loaded on demand
  • In-game editor
  • Live scripting with Python on client-side (using HTML script editor)
  • Game objects skinnable with XAML templates

Live demo

You can see live demo at http://silverstunts.com/cp1/index.html.
The site requires SilverLight 1.1 (Alpha Refresh) and works best with Firefox (IE eats some keyboard shortcuts).
Please folow instructions on the page if you encounter any problems.

Get started

Assuming you have SilverLight 1.1 Alpha Refresh (September) runtime installed on your computer. To run the game in debug mode, please download source code and unzip archive somewhere on your local disk (say C:\SilverStunts). Visual Studio project (C:\SilverStunts\game\SilverStunts.sln) works for Visual Studio 2008 Professional (or Beta2). It should also work for Express Edition of Visual Studio 2008 (not tested). You should also have Microsoft Silverlight 1.1 Tools Alpha for Visual Studio 2008 installed on your computer.

The project is for configured ASP.NET Development Server. We need real web server, because SilverLight in latest version has restriction for downloading local files using downloader object. Before you first run the website in debug mode, please take care to set Web Site setting (right click to C:\SilverStunts\site in Solution Explorer -> Property Pages).

Not you can put breakpoint somewhere (i.e. Page.xaml.cs into GameTick method) and hit F5 for debugging. The page will open in your default web browser.

Project Structure

Sources are divided into 3 projects:

  • SilverStunts - game sources and SilverLight entry point (produces SilverStunts.dll)
  • Physics - sources for physics engine (produces Physics.dll)
  • website - web files, website is "linked" to SilverStunts project, so every build copies Page.xaml into website root and DLLs into ClientBin

Note: due to Python scripting I need DLLs to be located in the root of web site. The problem is that Visual Studio build system always places them into ClientBin and I didn't find out any way how to reconfigure it. I ended up with URL rewriter which is properly configured in site's Web.config. See comments for more details.

Interesting technical details

Here we will discuss some parts of the project I find interesting.

Embedding IronPython scripting

This is the part I'm quite proud of in this project. Embedding IronPython is not very straightforward in the current version. You have to create custom Platform Adaptation Layer (PAL) as is described in this article. Back in May at the time I was investigating possibilites there were no resources on the web talking about these issues.

I have found another way. Very tricky, but it works. The idea is to boot Python subsystem by starting python script from default XAML page. Then inside Python script in 'Loaded' event we can expose .NET functionality and load the SilverStunts assembly dynamically. After then create and init the main page the same way it would be called by SilverLight runtime from XAML page pointing to C# assembly.

Page.xaml contains two lines to run in 'python mode':

<x:Code Source="page.py" Type="text/ironpython" />
<Canvas x:Name="loader" Loaded="onLoaded" />

You can look at Python bootstrapper in page.py:

# this is python code driving our silverlight control
# it acts as a scripting DLR bootstrapper (I was unable to intialize python scripting engine from managed code)
# we load managed assembly and route all relevant actions to it

import sys, clr

SilverStunts = clr.LoadAssemblyByName("SilverStunts, Version=1.0.0.0")

####################################################################
# class suitable for output redirect
class Redirect:
    def __init__(self, kind):
        self.method = SilverStunts.SilverStunts.Page.Current.PrintConsole
        self.kind = kind

    def write(self, s):
        self.method(s, self.kind)

####################################################################

def onLoaded(sender, args):
    # bootstrap page
    global page
    page = SilverStunts.CreateInstance("SilverStunts.Page")
    page.Init(sender.Parent)
    # redirect standard outputs
    sys.stdout = Redirect(SilverStunts.SilverStunts.Page.ConsoleOutputKind.Output)
    sys.stderr = Redirect(SilverStunts.SilverStunts.Page.ConsoleOutputKind.Error)

Note: Redirect magic is here to redirect outputs from python scripting engine into my web-based console.

I have implemented a little wrapper around Microsoft.Scripting.Hosting.ScriptEngine in Shell.cs. You can see there specific details of initializing scripting module and executing Python expressions.

For example calling tick event in level script boils down to:

private delegate bool TickDelegate(int tick, int elapsed);
private TickDelegate tickDelegate;
// initialization 
public void InitLevel(...)
{
    ...
    // wire dynamically loaded python script with tickDelegate
    tickDelegate = shell.Engine.EvaluateAs<TickDelegate>("tick", shell.Module);
    ...
}

// tick event
public void Tick(int tick, int elapsed)
{
    tickDelegate(tick, elapsed); // call into dynamically loaded python script
}

The game loop

In SilverLight you don't get exclusive thread to run your code. The execution thread is borowed from browser. That means when you execute a long running job, the browser may become unresponsive. It is important to return control to the browser as soon as possible.

Your code is called via some event from browser or SilverLight runtime. First chance how to subscribe to events is XAML page initialization event. There you have a chance to subscribe to timers. You can subscribe to HTML Timer or XAML Storyboard. For a game loop the XAML Storyboard is the preferred way. I use similar approach as is it described in A Better Game Loop article. My implementation is in the Timer class.

I run GameTick at speed 60FPS, but rendering is done at half speed.

public void GameTick(TimeSpan timeElapsed)
{
    // this game loop should run at 60FPS
    tick++;

    game.ProcessInputs(keyboard.keys);
    game.Simulate(); // here is simulated physics
    level.Tick(tick, (int)timeElapsed.TotalMilliseconds); // here is executed level script

    // throttle rendering to half speed (30FPS is OK for visuals)
    if (tick % 2 == 0)
    {
        level.UpdateVisuals();
        game.UpdateScrolling();
        renderTick++;
    }

    // this is ugly, but who cares ...
    HandleContinueMessage();
}

Entities, Visuals and plain game objects

When implementing scripting subsystem I wanted script to be the first class citizen in the system. There is a problem with scripting system to keep track what is going inside the scripting box and keep game state updated accordingly. For example: in SilverStunts you have interactive console and you can type and execute margaret = Circle(185, 155, 35) whenever during a game session. This will create a new entity called margaret in Python subsystem. Ok, it is a Python variable, but it has to have some shadow in the game engine and in the renderer to be visible on the screen. Managed C# game core must be notified, that a new entity was created and get a chance to register it in the system. That is why I want to distinguish between Entities, Visuals and plain objects.

  • Plain Object - is raw data structure (for example physics object)
  • Visual - is data structure in C# that acts as a visual representation of Plain Object (it holds Canvas, piece of XAML and rules how to update Canvas)
  • Entity - is data structure in C#, but visible in scripting context, it keeps reference to the visual and plain object

So, entities are top level objects living in C# and visible from script. When a new entity is created from a script we get notified by code entering an entity's constructor. So, possible scenarios are:

  • entity is created from script - constructor is called and corresponding visual and plain objects are created
  • entity is deleted from script - because of garbage collector, destructor may be called with delay. We may call Die() method from script to immediate entity destruction.
  • entity is created by game - game has full control and knows how to update it's state
  • entity is deleted by game - game has full control and knows how to purge the data

You can examine entities implementation in the Entities subfolder of SilverStunts project.

And what about visuals?
I have implemented simple templating system for visuals. Visual templates are located in Visuals.xml and one template may look like this:

...
<Visual Type="CircleParticle">
    <Canvas.RenderTransform>
        <TransformGroup>
            <TranslateTransform X="{CenterOffset.X}" Y="{CenterOffset.Y}"/>
            <TranslateTransform X="{Curr.X}" Y="{Curr.Y}"/>
        </TransformGroup>
    </Canvas.RenderTransform>
    <Ellipse Width="{Diameter}" Height="{Diameter}" Fill="Blue" RenderTransformOrigin="0.5, 0.5"/>
</Visual>
...

This is a piece of XAML extended by binding properties (see them in curly brackets). These are bindings to Plain Object's properties. This XML is loaded as a data on startup and is parsed. Curly brackets are transformed into bindings table (see Bindings class). When a new entity is created some template is assigned to it and a new visual is created based on that template. During gameplay Plain Object's properties will be animated (for example physics engine alters object's position). Visual is able to update Canvas using new values from Plain Object's properties. This is implemented using .NET reflection and code can be found in Visual.cs:

// binding between plain object (source) and visual's content (target)
class Binding
{
    int id;
    string attribute;
    string field;

    public Binding(int id, string attribute, string field)
    {
        this.id = id;
        this.attribute = attribute;
        this.field = field;
    }

    public object GetValue(Object source)
    {
        BindingFlags f = BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
        string[] names = field.Split('.');
        Object value = source;
        for (int i = 0; i < names.Length; i++)
        {
            Type st = value.GetType();
            value = st.InvokeMember("get_" + names[i], f | BindingFlags.InvokeMethod, null, value, new object[] { });
        }
        return value;
    }

    public void SetValue(Object target, Object value)
    {
        BindingFlags f = BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
        Type tt = target.GetType();
        tt.InvokeMember("set_" + attribute, f | BindingFlags.InvokeMethod, null, target, new object[] { value });
    }

    public void Update(Canvas content, Object source)
    {
        Object target = content.FindName(id.ToString());
        Object value = GetValue(source);
        SetValue(target, value);
    }
}

Scrolling

Scrolling is achieved using clipping Canvas. Clipping canvas hides all beyond it's bounding rectangle. Implementation is in ClipCanvas class.
Here is the Game.xaml which defines layout of game scroller using ClipCanvas:

<ss:ClipCanvas x:Name="viewport"
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:ss="clr-namespace:SilverStunts;assembly=SilverStunts.dll"
    Width="1000" Height="600"
    Background="#EEEEEE"
>

    <Canvas x:Name="gui" >
        <!-- here will be inserted game UI elements -->
    </Canvas>
    
    <!-- scrolling canvas for game and editor -->
    <Canvas x:Name="scroller">

        <Canvas x:Name="background">
            <!-- here will be inserted background xaml -->
        </Canvas>

        <Canvas x:Name="world">
            <!-- here will be inserted game entities -->
        </Canvas>

        <Canvas x:Name="foreground">
            <!-- here will be inserted foreground xaml -->
        </Canvas>

        <Canvas x:Name="workspace">
            <!-- here will be inserted editor UI elements (gizmos, etc) -->
        </Canvas>

    </Canvas>

    <Canvas Visibility="Collapsed" x:Name="grid" Opacity="0.1" Width="1000" Height="600">
        <Canvas.Background>
            <!-- SilverLight 1.1ALPHA does not support TileMode property on ImageBrush => need to improvise using image -->
            <ImageBrush ImageSource="images/grid.png" />
        </Canvas.Background>
    </Canvas>

</ss:ClipCanvas>

Scrolling is done applying translation to Canvas named "scroller". You can see the code in Page.xaml.cs in UpdateScrolling method:

TranslateTransform tt = new TranslateTransform();
tt.X = -(cameraX - 500);
tt.Y = -(cameraY - 400);
scroller.RenderTransform = tt;

Note: We have to apply a negative (inverse) camera transformation, because we are moving with the world instead of viewport.

In-game editor

In-game editor is pretty neat. You can get into edit mode by pressing SPACE. You can click on object and it's edit gizmo is displayed (as a gray rectangle). Gizmos have some handles and you can tweak object properties using handles. Of course you can do multiselection and move objects around, copy&paste them or delete them. Changes made to the level visually are reflected into the script editor (see Entities tab). Changes from the script editor are reflected to the game.

Editor is implemented in Editor.cs. Gizmos are implemented in Gizmo.xaml.cs. Each gizmo has to implement this interface:

public interface IGizmo
{
    void Destroy();
    bool HitTest(System.Windows.Input.MouseEventArgs e);
    void HandleMouseLeftButtonDown(object sender, System.Windows.Input.MouseEventArgs e);
    void HandleMouseLeftButtonUp(object sender, System.Windows.Input.MouseEventArgs e);
    void HandleMouseMove(object sender, System.Windows.Input.MouseEventArgs e);
    void Update();
}

Editor is routing mouse events into Gizmos via this interface and gizmos are responsible for affecting object's properties.

Problems encoutered

I've encountered some problems during implementation. I assume these issues will be fixed in final version.
  • Keyboard - some browsers eat keystrokes or react on many of them (I was not able to use F-keys, arrow keys or TAB on IE)
  • Mouse capture - when you have an active mouse capture and you leave a browser window, capture is never released (this is a bug in SilverLight)
  • IronPython embedding - embedding IronPython should be more straightforward in the final version

Conclusion

SilverLight 1.1 is still in alpha so I don't want to do a strict judgement. Making the game and learning SilverLight was a great fun for me. From this experience, I can say that SilverLight is a rich runtime platform and definitely suitable for casual games. In this article I wanted to present that unique SilverLight features like DRL and WPF are great helpers when implementing data driven game engine. I believe in future of SilverLight development and fast acceptation by the end users. Simply I'm fan of SilverLight and the engineering team behind.

Feel free to use my code as a startup skeleton for your game project. You can jump in right now.

Credits

History

  • 31th December 2007 - First public version

License

This article, along with any associated source code and files, is licensed under The BSD License

About the Author

Antonin Hildebrand


Member
I'm a former game developer. I'm excited about web technologies.
Currently, I work on rich internet application powered by ExtJS (client) and Ruby on Rails (server).
Occupation: Web Developer
Location: Czech Republic Czech Republic

Other popular Silverlight articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Layout  Per page   
 Msgs 1 to 4 of 4 (Total in Forum: 4) (Refresh)FirstPrevNext
QuestionSilverlight 2 beta 2 version ? PinmemberBizounours6:54 23 Jun '08  
AnswerRe: Silverlight 2 beta 2 version ? PinmemberAntonin Hildebrand3:21 24 Jun '08  
GeneralTo je nejlepsi! PinmemberDaniel Vaughan3:25 1 Jan '08  
GeneralNazdar! PinmemberJames Ashley15:13 31 Dec '07  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 31 Dec 2007
Editor: Genevieve Sovereign
Copyright 2007 by Antonin Hildebrand
Everything else Copyright © CodeProject, 1999-2009
Web22 | Advertise on the Code Project