XNA in Silverlight mittels SilverSprite
Autor: SteveKr
Inhaltsverzeichnis
- Einleitung
- Die XNA-Anwendung
- Download und Einrichten von SilverSprite
- Silverlight-Projekt erstellen
- Weitergeben
^ Einleitung
Bei SilverSprite handelt es sich um eine Silverlight-Library die Teile des XNA Frameworks wrappt, so dass man XNA-Spiele, die sich auf diese Bereiche beschränken unter Silverlight laufen lassen kann.
Derzeit unterstützt SilverSprite (einfache) 2D-Spiele. Auf Grund fehlender GPU-Unterstützung von Silverlight, allerdings keine Shader.
Codeplex-Projektseite: SilverSprite
Im folgenden werden wir eine XNA-Anwendung unter Silverlight lauffähig machen.
^ Die XNA-Anwendung
Als einfaches Beispiel werden wir in diesem Tutorial einen Frosch verwenden, den man mit den Pfeiltasten steuern kann. Stattdessen kann natürlich auch ein anderes, bereits bestehende sXNA-Projekt verwenden.
Das Beispiel-Projekt besteht aus der Game-Klasse, einer GameObject-Klasse und einem Bild.

Bild 1: Das XNA-Projekt
Erklärungen zum Code sparen wir uns, da er keinerlei Besonderheiten enthält.
GameObject-Klasse
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace XnaTestProject
{
public class GameObject
{
private Texture2D texture;
private Vector2 position;
public GameObject(Texture2D texture, Vector2 position)
{
this.texture = texture;
this.position = position;
}
public void Move(GameTime gameTime)
{
KeyboardState keyState = Keyboard.GetState();
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
float speed = 50.0f;
if (keyState.IsKeyDown(Keys.Left))
{
position.X -= speed * elapsed;
}
if (keyState.IsKeyDown(Keys.Right))
{
position.X += speed * elapsed;
}
if (keyState.IsKeyDown(Keys.Up))
{
position.Y -= speed * elapsed;
}
if (keyState.IsKeyDown(Keys.Down))
{
position.Y += speed * elapsed;
}
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(texture, position, Color.White);
}
}
}
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace XnaTestProject
{
public class GameObject
{
private Texture2D texture;
private Vector2 position;
public GameObject(Texture2D texture, Vector2 position)
{
this.texture = texture;
this.position = position;
}
public void Move(GameTime gameTime)
{
KeyboardState keyState = Keyboard.GetState();
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
float speed = 50.0f;
if (keyState.IsKeyDown(Keys.Left))
{
position.X -= speed * elapsed;
}
if (keyState.IsKeyDown(Keys.Right))
{
position.X += speed * elapsed;
}
if (keyState.IsKeyDown(Keys.Up))
{
position.Y -= speed * elapsed;
}
if (keyState.IsKeyDown(Keys.Down))
{
position.Y += speed * elapsed;
}
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(texture, position, Color.White);
}
}
}
Game-Klasse
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace XnaTestProject
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
GameObject frog;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
frog = new GameObject(Content.Load<Texture2D>("frog"), new Vector2(200, 200));
}
protected override void Update(GameTime gameTime)
{
frog.Move(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
frog.Draw(spriteBatch);
spriteBatch.End();
}
}
}
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace XnaTestProject
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
GameObject frog;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
frog = new GameObject(Content.Load<Texture2D>("frog"), new Vector2(200, 200));
}
protected override void Update(GameTime gameTime)
{
frog.Move(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
frog.Draw(spriteBatch);
spriteBatch.End();
}
}
}

Bild 2: Die erwartete Ausgabe
^ Download und Einrichten von SilverSprite
Nach der Vorarbeit beginnt nun der eigentliche Teil dieses Tutorials. Das Portieren des obigen Projekts mit SilverSprite in eine Silverlight-Anwendung.
Dazu laden wir uns zunächst die neuste Version von SilverSprite auf der Codeplex-Seite herunter:
http://silversprite.codeplex.com/So....tDownloadableCommits.aspx
Von den Projekten in der Projektmappe ist für uns lediglich SilverArcade.SilverSprite von Interesse, das andere ist ein Beispiel Snake-Spiel.

Bild 3: Das SilverSprite-Projekt
Nach dem Ausführen des Projekts erhalten wir eine DLL, die den kompletten SilverSprite-XNA-Wrapper enthält, den wir für unser Projekt benötigen.
^ Silverlight-Projekt erstellen
Nun erstellen wir ein neues Silverlight-Projekt (Template Silverlight Application).

Bild 4: Leeres Silverlight-Projekt
Code hinzufügen
Anschließend fügen wir dem Projekt sämtliche Code-Dateien unseres XNA-Projekts hinzu und binden die SilverSprite-DLL als Referenz ein.
Die Using-Direktiven des XNA-Framework müssen wir durch die von SilverSprite ersetzen.
Aus
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Graphics;
wird
using SilverArcade.SilverSprite;
using SilverArcade.SilverSprite.Graphics;
using SilverArcade.SilverSprite.Graphics;
Und aus
public class Game1 : Microsoft.Xna.Framework.Game
wird
public class Game1 : SilverArcade.SilverSprite.Game
Content-Dateien
Die Handhabung des Contents ist etwas umständlicher. Die Texturen müssen wir als fertig kompilierte XNB-Dateien in einen Content-Ordner fügen. Als Build Action wählen wir Content aus.

Bild 5: Dateieigenschaften für die XNB-Datei
Wichtig: Die Dateien dürfen nicht komprimiert sein. Die Komprimierung für das Content-Projekt kann man in den Projekteigenschaften unter ContentBuild deaktivieren.

Bild 6: Das ehemalige XNA-Projekt unter Silverlight
Page.xaml
Damit unser Spiel gestartet wird öffnen wir nun die Page.xaml-Datei unter ersetzen den dortigen Code durch den Folgenden:
<UserControl x:Class="XnaSilverSpriteTest.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:game="clr-namespace:XnaTestProject">
<Grid x:Name="LayoutRoot" Background="White">
<Canvas>
<game:Game1/>
</Canvas>
</Grid>
</UserControl>
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:game="clr-namespace:XnaTestProject">
<Grid x:Name="LayoutRoot" Background="White">
<Canvas>
<game:Game1/>
</Canvas>
</Grid>
</UserControl>
Wenn wir jetzt das Projekt ausführen sollten wir die gleiche Ausgabe erhalten, die wir von unserem XNA-Projekt gewohnt waren.

Bild 7: Der Frosch im Browser
^ Weitergeben
Auf unseren Webspace müssen wir nun die folgenden Dateien hochladen:
- AppManifest.xaml
- SilverArcade.SilverSprite.dll
- TestPage.html (die HTML-Datei in der das Silverlight-Applet angezeigt wird)
- XnaSilverSpriteTest.dll
- XnaSilverSpriteTest.xap
Das Beispielprojekt im Browser.
Das Spiel läuft in jedem Browser, in dem das Silverlight 2-Plugin installiert ist.

