Blake O'Hare .com

Gamelight Tutorial: Part 3 - Images

This tutorial continues on with the codebase of the previous tutorials.

Images are relatively simple. Here is Tokyo:
gamelight_background.jpg

Here is a "Fly Machine":
gamelight_fly_machine.png

Create a folder in your project called "images" and drop these images into it as background.jpg and fly_machine.png.

VERY IMPORTANT: Change the Build Action of these files to Embedded Resource in the Properties panel. If you do not do this, Gamelight won't be able to find them.
gamelight_embedded_resource.png
Done? Good. Add two private fields to your DemoScene called background and player:

private Gamelight.Graphics.Image background =
    new Gamelight.Graphics.Image("images/background.jpg");

private Gamelight.Graphics.Image player =
    new Gamelight.Graphics.Image("images/fly_machine.png");


And now replace the whole contents of your Render function with these two simple calls:

protected override void Render(Gamelight.Graphics.Image gameScreen)
{
    gameScreen.Blit(this.background, 0, 0);
    gameScreen.Blit(
      this.player,
      this.x - this.player.Width / 2,
      this.y - this.player.Height / 2);
}


Hit F5 and you should be good to go:
gamelight_tokyo.png

When you supply a string path to the constructor of Image, it will search all the embedded resources in the local default assembly. The default assembly is the one that contains MainPage.xaml. However, this will not always be the location of the images. Suppose your Gamelight game exists as part of a separate DLL. Or suppose all your images are saved in a separate resource assembly that's used across other apps. Then this won't do.

If you have another assembly with an image in it, you must do two things. First, you must register the assembly. To register an assembly, call Gamelight.Data.Resources.RegisterResourceAssembly with either a reference to the System.Reflection.Assembly you want to register, or simply a System.Type of a type that is defined in that assembly. If you control the external assembly, the latter is the easiest. Suppose I had an assembly called MyResources with a class in it called Class1. I would then call:
Gamelight.Data.Resources.RegisterResourceAssembly(
    typeof(MyResources.Class1));


Once an assembly is registered, the second thing you have to do is supply the name of the assembly to the Image constructor.
private Gamelight.Graphics.Image background =
    new Gamelight.Graphics.Image("images/background.jpg");
...then becomes:
private Gamelight.Graphics.Image background =
    new Gamelight.Graphics.Image(
        "MyResources",
        "images/background.jpg");

However, if all or most of your images are located in this assembly, then you may want to set it as the default assembly. To do that, there is a function called Gamelight.Data.Resources.SetDefaultResourceAssembly which takes in a string name of the resource that you wish to be the default place for Gamelight to look for images.
Gamelight.Data.Resources.SetDefaultResourceAssembly("MyResources");

Once you do this, you no longer have to supply the assembly name to the Image constructor for images in MyResources, but you will need to for things that are in the main assembly.

Random note about paths: Paths are always relative to the root of the assembly. Additionally, it doesn't matter if you use slashes, backslashes, or even periods to delimit the directories. This is because the underlying file path is just periods. When you specify a path with slashes in it, all the slashes are converted into periods before it's handed off to Silverlight. This does create a situation where seemingly unique file names can collide if periods are involved.