Making an XNA4 Game Installer

by erik on June 27, 2010

XNA4 installer

Putting together a comprehensive, cohesive and (not to mention) usable XNA game installer is no real trivial task. Visual Studio 2008 / 2010 do provide the ability to create a default installer but it is quite “rough” and perhaps best left to creating alpha / beta deploys for quick testing.

David Amador put together an excellent piece on creating an install builder for XNA3.1 games using the well known InnoSetup tool.

Let’s build on the same body of work to enable the ability for creating an installer for XNA4.0 projects.

Prerequisites

  1. Create “C:\Game Development Tools\”
  2. Download vcredist_x86.exe
  3. Download .NET Framework 4.0 (standalone installer)
  4. Use the xnafx40_redist.msi from your XNA4.0 CTP install

Next comes the modified Inno Setup script that David has put together:

; Script generated by the Inno Setup Script Wizard.
; (Then extensively modified by Caliban Darklock.)
; (And yet again modified by David Amador) Should work property with XNA 3.1
; (*wave* modified by Erik Yuzwa) should work for XNA 4.0
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

; Enter the name of your game here
#define MyAppName "Dragons & Dangers"

; Enter the name of your game and a version number here
#define MyAppVerName "Dragons & Dangers"

; Enter the name of your company, or just your name
#define MyCompany "Blue Moon Turtle"

; Enter the URL of your website
#define MyAppURL "http://www.bluemoonturtle.com/"

; Enter the path to your game project - check Visual Studio properties for the path
#define MyAppLocation "C:\MyProjects\DragDang\DragDang"

; Enter the name of your game executable
#define MyAppExeName "DragDang.exe"

; Enter the location where XNA Game Studio is installed
#define MyGameStudioLocation "C:\Program Files (x86)\Microsoft XNA\XNA Game Studio\v4.0"

; Enter the name for the correct version of the XNA Framework MSI
#define XNARedist "xnafx40_redist.msi"

; Enter the location where you have placed the VC and .NET redistributables
#define MyRedistLocation "C:\Game Development Tools"

; search microsoft.com for "visual c++ sp1 redistributable" to get the VC redist
; enter the name of the executable file here
#define VCRedist "vcredist_x86.exe"

; Download latest .NET from http://www.microsoft.com/net/ (download button on menu)
; enter the name of the executable file here
#define DotNetSetup "dotNetFx40_Full_x86_x64.exe"

; Once you've filled in all the variables above and downloaded your redist packages,
; everything under this point should JUST WORK for most XNA projects.

[Setup]
AppName={#MyAppName}
AppVerName={#MyAppVerName}
AppPublisher={#MyCompany}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={pf}\{#MyAppName}
DefaultGroupName={#MyAppName}
OutputBaseFilename={#MyAppName}Setup
Compression=lzma
SolidCompression=yes
SetupIconFile = "C:\MyProjects\DragDang\DragDang\DragDang.ico"
UninstallIconFile = "C:\MyProjects\DragDang\DragDang\DragDang.ico"

[Languages]
Name: english; MessagesFile: compiler:Default.isl

[Tasks]
Name: desktopicon; Description: {cm:CreateDesktopIcon}; GroupDescription: {cm:AdditionalIcons}; Flags: unchecked

[Files]
; DirectX and XNA Framework redistributables
Source: {#MyGameStudioLocation}\Redist\DX Redist\*; DestDir: {tmp}
Source: {#MyGameStudioLocation}\Redist\XNA FX Redist\{#XNARedist}; DestDir: {tmp}

; .NET and VC redistributables - VerifyDotNet35 MUST run BEFORE VerifyDotNet35sp1!
Source: {#MyRedistLocation}\{#DotNetSetup}; DestDir: {tmp}; AfterInstall: VerifyDotNet35
Source: {#MyRedistLocation}\{#VCRedist}; DestDir: {tmp}; AfterInstall: VerifyDotNet35sp1

; The game itself
Source: {#MyAppLocation}\bin\x86\Release\{#MyAppExeName}; DestDir: {app}; Flags: ignoreversion
Source: {#MyAppLocation}\bin\x86\Release\*; DestDir: {app}; Flags: ignoreversion recursesubdirs createallsubdirs

[Icons]
Name: {group}\{#MyAppName}; Filename: {app}\{#MyAppExeName}
Name: {group}\{cm:UninstallProgram,{#MyAppName}}; Filename: {uninstallexe}
Name: {commondesktop}\{#MyAppName}; Filename: {app}\{#MyAppExeName}; Tasks: desktopicon

[Run]
Filename: {tmp}\{#DotNetSetup}; Flags: skipifdoesntexist; Parameters: "/q /noreboot"
Filename: {tmp}\{#VCRedist}; Flags: skipifdoesntexist; Parameters: "/q"
Filename: {tmp}\dxsetup.exe; Parameters: /silent
Filename: msiexec.exe; Parameters: "/quiet /i ""{tmp}\{#XNARedist}"""
Filename: {app}\{#MyAppExeName}; Description: {cm:LaunchProgram,{#MyAppName}}; Flags: nowait postinstall skipifsilent

; The code section doesn't like comments for some reason.
; VerifyDotNet35 removes the .NET setup if you already have .NET 3.5 installed.
; VerifyDotNet35sp1 removes the VC redist if you already have .NET 3.5 SP1, -or-
; if you don't have .NET 3.0 at all (it will be installed along with .NET 3.5).
; Using the skipifdoesntexist flag allows the setup to ignore the missing files.
[Code]
var
  hasDotNet3 :Boolean;
  hasDotNet3sp :Boolean;
  whichDotNet3sp :Cardinal;

procedure VerifyDotNet35();
begin
  hasDotNet3 := RegKeyExists(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5');
	if hasDotNet3 then
      DeleteFile(ExpandConstant('{tmp}\{#DotNetSetup}'));
end;

procedure VerifyDotNet35sp1();
begin
  hasDotNet3sp := RegQueryDWordValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5', 'SP', whichDotNet3sp);
  if (hasDotNet3sp and (whichDotNet3sp > 0)) or not hasDotNet3 then
      DeleteFile(ExpandConstant('{tmp}\{#VCRedist}'));
end;

There you have it. The commenting / description should be straight-forward enough. Just cut&paste this script into an .ISS file and InnoSetup will finish the job for you.

Enjoy, and I hope you found it usefull!

{ 0 comments }

In case you haven’t been closely following the ever-changing mobile market, you may have missed the news that Microsoft is releasing their own smartphone probably close to the christmas 2010 holidays (very speculative on exact dates right now).

Named “Windows Phone 7″, the technical team have seemingly done a tremendous job of cleaning up the current confusion around programming and deploying apps to a Windows mobile device. At last count, there were 4 or 5 SDK’s for mobile development and each one seemed to have their own strengths and weaknesses.

Microsoft has done away with all this for WP7 (thank heavens!)

The XNA framework currently available for the PC and XBox360, will now be extended to support Zune and WP7 devices! This is tremendous news for game and app developers everywhere!

Getting Started

Before we can start cranking out some apps for WP7, you’ll need to:

  1. grab the April refresh of the VS2010 Express for Windows Phone. Go ahead and install it.
  2. check out the code samples for Windows Phone development
  3. We’re interested specifically in the “Hello XNA Framework Sample”
  4. Unzip and open with the new VS2010 Express
  5. You should be able to launch a debug session via the IDE which will pop open the Windows Phone 7 emulator. You should see two squares bouncing around with a sound effect if they touch each other.

hello xna framework output

To make sure we’re on the same starting point, let’s take a look at the sample code. All of the magic for the basic application is happening inside the Game1.cpp file.

Let’s start with the required dependencies for building a windows phone 7 app based on the XNA 4.0 framework.

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Xna.Framework.Media;

If you’ve seen previous XNA based code before then this should be nothing really strange. One of the new references to note is Microsoft.Xna.Framework.Input.Touch which will help us handle (and query) the touch screen interface of the WP7 device.

namespace HelloXnaFramework
{
    ///

    /// This is the main type for your game
    /// 

    public class Game1 : Microsoft.Xna.Framework.Game
    {
         /* our graphics device */
        GraphicsDeviceManager graphics;

        /* our sprite rendering manager */
        SpriteBatch spriteBatch;

        /* texture object */
        Texture2D texture1;

        /* texture object */
        Texture2D texture2;

        /* (x,y) vector for tracking position */
        Vector2 spritePosition1;

        /* (x,y) vector for tracking position */
        Vector2 spritePosition2;

        /* (x,y) vector for holding the sprite speed */
        Vector2 spriteSpeed1 = new Vector2(50.0f, 50.0f);

        /* (x,y) vector for holding the sprite speed */
        Vector2 spriteSpeed2 = new Vector2(100.0f, 100.0f);

        /* height of sprite1 */
        int sprite1Height;

        /* width of sprite1 */
        int sprite1Width;

        /* height of sprite2 */
        int sprite2Height;

        /* width of sprite2 */
        int sprite2Width;

        /* sound effect object */
        SoundEffect soundEffect;

We’re declaring our game class Game1 by inheriting from the Microsoft.Xna.Framework.Game object. This is standard, and you’ll have to do this for any XNA4.0 based project.

Next we have a few object instance declarations. Everything is incredibly readable, but I’ve added some comments to help you out with any “grey” areas.

public Game1()
{
    /* create graphics handle to our display device */
   graphics = new GraphicsDeviceManager(this);
   Content.RootDirectory = "Content";

   // Frame rate is 30 fps by default for Windows Phone.
  TargetElapsedTime = TimeSpan.FromTicks(333333);

   // Pre-autoscale settings.
   graphics.PreferredBackBufferWidth = 480;
   graphics.PreferredBackBufferHeight = 800;
}

Here’s the constructor method for the Game1 object. During initialization of the XNA Framework, the proper display device will be chosen for you automagically. This becomes extremely useful when you’re attempting to port your XNA project across multiple (windows-based) devices.

The framerate will be “locked” on this Game1 sample at 30 frames per second. If we’re holding our WP7 vertically, then the graphics screen is sized at 480×800 (which means if you flip the device horizontally, the display effectively becomes 800×480).

///

/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// 

protected override void LoadContent()
{
  // Create a new SpriteBatch, which can be used to draw textures.
  spriteBatch = new SpriteBatch(GraphicsDevice);

  /* load our two Texture2D objects using the GameThumbnail image */
  texture1 = Content.Load("GameThumbnail");
  texture2 = Content.Load("GameThumbnail");

  /* load the "Windows Ding" media */
  soundEffect = Content.Load("Windows Ding");

  /* set the position for sprite1 */
  spritePosition1.X = 0;
  spritePosition1.Y = 0;

  /* set the starting position for sprite2 */
  spritePosition2.X = graphics.GraphicsDevice.Viewport.Width
        - texture1.Width;

  spritePosition2.Y = graphics.GraphicsDevice.Viewport.Height
        - texture1.Height;

  /* for collision detection, set the "bounds" of our
   * sprite1 and sprite2 objects
   */
  sprite1Height = texture1.Bounds.Height;
  sprite1Width = texture1.Bounds.Width;

  sprite2Height = texture2.Bounds.Height;
  sprite2Width = texture2.Bounds.Width;
}

The overrided LoadContent() method is required in every XNA-based game and should be used to load and/or initialize all of our media, data structures and other game objects. First you need to create the SpriteBatch object based on the chosen GraphicsDevice on our system. Next we’re loading up our two Texture2D objects using the “GameThumbnail” resource. After which, the program is loading the SoundEffect which will be played when our sprite1 and sprite2 collide with each other. Finally, to help us perform proper collision detection calculations, the code sets the width and height of sprite1 and sprite2.

///

/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// 

///
Provides a snapshot of timing values.
protected override void Update(GameTime gameTime)
{
   // Allows the game to exit
   if (GamePad.GetState(PlayerIndex.One).Buttons.Back ==
     ButtonState.Pressed)
    this.Exit();

    // Move the sprite around.
    UpdateSprite(gameTime, ref spritePosition1, ref spriteSpeed1);
    UpdateSprite(gameTime, ref spritePosition2, ref spriteSpeed2);
    CheckForCollision();

    base.Update(gameTime);
}

The Update() function is also critically important to our XNA game. During the application’s main loop within the XNA framework the update method is called once-per-frame. At a bit of a higher level, we are passing references to both sprite1 and sprite2 in the UpdateSprite() method. As you might be able to guess, this method handles the updates to the position of the object based on the current gameTime variable. The gameTime variable is the current state of the internal “heartbeat” timer within XNA. To make sure your game objects update properly, you should be using this variable whenever you’re updating the position of an entity. Finally the collision detection method is executed to check if our sprite1 and sprite2 objects have hit each other.

void CheckForCollision()
{
  BoundingBox bb1 = new BoundingBox(
    new Vector3(spritePosition1.X - (sprite1Width / 2),
    spritePosition1.Y - (sprite1Height / 2), 0),
    new Vector3(spritePosition1.X + (sprite1Width / 2),
    spritePosition1.Y + (sprite1Height / 2), 0));

    BoundingBox bb2 = new BoundingBox(
      new Vector3(spritePosition2.X - (sprite2Width / 2),
      spritePosition2.Y - (sprite2Height / 2), 0),
      new Vector3(spritePosition2.X + (sprite2Width / 2),
      spritePosition2.Y + (sprite2Height / 2), 0));

     if (bb1.Intersects(bb2))
    {
      soundEffect.Play();
    }

}

This is a very simple and straightforward way of performing collision detection within your XNA-based game! First, the application is creating a BoundingBox instance which surrounds sprite1 and sprite2. A bounding box is a data structure within a game which provides an estimate for any collisions. Imagine a rectangle / cube around sprite1 and sprite2. To determine if sprite1 has struck sprite2, the application just needs to test each rectangle for any intersection points. Finally, if these two bounding boxes have collided, then play our sound effect using Play().

///

/// This is called when the game should draw itself.
/// 

///
Provides a snapshot of timing values.
protected override void Draw(GameTime gameTime)
{
  graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

  // Draw the sprite.
  spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend);
  spriteBatch.Draw(texture1, spritePosition1, Color.White);
  spriteBatch.End();

  spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.Opaque);
  spriteBatch.Draw(texture2, spritePosition2, Color.Gray);
  spriteBatch.End();

  base.Draw(gameTime);

}

The final method we need to examine in the HelloXNAFramework is the actual Draw() functionality. At a higher level, the goal of our drawing routine (in any game) is to: draw each and every object that belongs on the screen. In XNA-based projects, to properly draw each object, you need to make sure that the application is using the SpriteBatch instance. To make sure the SpriteBatch object is properly used, you should follow the same sequence for every object you need drawn in a scene:

  1. SpriteBatch.Begin(sorting state of the object, any blending information)
  2. Draw the sprite itself using Draw()
  3. Call SpriteBatch.End() to finish itself up

That’s really all there is to this little XNA-based application. Notice how we really didn’t need any WP7 specific object instances?

If you need any help, please leave a comment

{ 0 comments }

video game basics 101 – adding input

June 21, 2010

Note that this is part of a video game education course entitled “making a video game with C++”. If you get stuck or confused with any material that’s covered, please leave a comment or drop me a note via the contact form! Video Game Basics 101 – Adding Input Welcome back to this training module [...]

Read the full article →

video game basics 101 – adding sprites

June 19, 2010

Note that this is part of a video game education course entitled “making a video game with C++”. If you get stuck or confused with any material that’s covered, please leave a comment or drop me a note via the contact form! Video Game Basics 101 – Adding Sprites Welcome back to this training module [...]

Read the full article →

when game developers enhance and elevate a film franchise

June 19, 2010

Even among gamers, in most cases everyone would tend to agree that movie franchises never seem to translate into strong enough games. A recent “case in point” example is the swath of the Lord of the Rings games from EA (admittedly a few years ago). Can’t really remember much about them today, nor do I [...]

Read the full article →

video game basics 101 – adding font support

June 19, 2010

Note that this is part of a video game education course entitled “making a video game with C++”. If you get stuck or confused with any material that’s covered, please leave a comment or drop me a note via the contact form! Video Game Basics 101 – Adding Font Support Welcome back. In the previous [...]

Read the full article →

video game basics 101 – create your own main class

June 18, 2010

Note that this is part of a video game education course entitled ‘making a video game with C++’. If you get stuck or confused with any material that’s covered, please leave a comment or drop me a note via the contact form! Video Game Basics 101 – Create Your Own Main Class Hi, and welcome [...]

Read the full article →

5 killer ways to get your hands on Windows Phone 7

June 18, 2010

The Windows Phone 7 (WP7) team is on the prowl around the internet to find those developers who are “worthy” enough of getting their hands on a nice shiny new WP7 device from the team! Brandon Watson (*cough* Director of Microsoft’s Azure Cloud Services platform *cough*) himself has these words of wisdom: Ways To Get [...]

Read the full article →

video game basics 101 – add image loading

June 16, 2010

Note that this is part of a video game education course entitled ‘making a video game with C++’. If you get stuck or confused with any material that’s covered, please leave a comment or drop me a note via the contact form! Video Game Basics 101 – Add Image Loading Welcome back to the next [...]

Read the full article →

video game basics 101 – add some logging

June 14, 2010

Note that this is part of a video game education course entitled making a video game with C++. If you get stuck or confused with any material that’s covered, please leave a comment or drop me a note via the contact form! Video Game Basics 101 – Add Some Logging In this installment of the [...]

Read the full article →