Coming up in the next tutorial, we'll demonstrate a way you can organize the objects you want to see on the screen into a hierarchy of nested container objects (Sprites, Components and Screens). We'll create a Screen Manager class that will allow us to easily switch from one Screen to another. We'll also start animating things by having all of our objects implement a scripting interface.
I've been working on real-world stuff for my job this week (and weekend) but I should have time to put together the next tutorial over the next week or so.
![]() | 10/28/07 |
![]() | 10/21/07 |
VB.NET XNA Tutorial 4: Starting an engine, and the VBContentManager
[GSE 1.0 Refresh]
Here's the link to on Vimeo.
This tutorial is a little bit longer and a little bit more involved than the past tutorials. We'll start down the road to separating game logic from game logistics by creating a new project called XNA 2D Engine and moving the "MyGame" class into it. We'll turn the MyGame into a base class to be used with the 2D engine.
We'll introduce the VBContentManager class, my implementation of a ContentManager extended with our "VB Content Pipeline hack" code (there's lots more on that, below). We'll then go on to making a primitive sprite in Photoshop and drawing it to the screen with a SpriteBatch object.
Here is some companion text to go with the video, that describes in detail some code I'll be importing but not spending a lot of time describing in the video:
In a standard C# XNA project, the default game class is created for you with a GraphicsDeviceManager and a ContentManager both instantiated and ready to go. As we saw in Tutorial 3, it's fairly easily make our own class that inherits from the base XNA Game class, create our own GraphicsDeviceManager and quickly reproduce what the C# template generates automatically.
What tutorial 3 did not touch on was the ContentManager, because for us VB'ers, the ContentManager is really the point where the lack of VB support in XNA requires us to do a little bit of legwork, so I held off on the subject until now.
In C#, the ContentManager class loads cross-platform file types (like .xnb files) that MSBuild creates automatically from things like .png or .jpg files that get included in the C# project. The primary issue when using a ContentManager with VB is getting these .xnb files created from our .png or .jpg files, because there is no automatic conversion process built into the IDE.
My approach to solving this problem was to borrow largely what's been documented by Alan Phipps, and from that, create my own ContentManager class called the VBContentManager class. Here's is the VBContentManager class, in it's entirety:
Public Class VBContentManager
Inherits ContentManager
Public Fonts As Hashtable(Of SpriteFont)
Public Textures As Hashtable(Of Texture2D)
Public SubTextures As Hashtable(Of Hashtable(Of Rectangle))
Public Sounds As Hashtable(Of SoundBank)
Private strFakeCSharpProject As String
Private strContentRootFolder As String
Private strPipelineRootFolder As String
Private objContent As List(Of ContentFile)
Private intDupeSound, intDupeTexture, intDupeFont As Integer
Public Enum ContentTypes
Textures = 0
Fonts = 1
Sounds = 2
End Enum
Private Enum ImporterName
TextureImporter = 0
FontDescriptionImporter = 1
XactImporter = 2
End Enum
Private Enum ProcessorName
SpriteTextureProcessor = 0
FontDescriptionProcessor = 1
XactProcessor = 2
End Enum
Public Structure ContentFile
Public ContentType As ContentTypes
Public File As System.IO.FileInfo
Public Name As String
Public Sub New (ByVal ContentType As ContentTypes, ByVal ContentFile As System.IO.FileInfo, ByVal Name As String)
Me .ContentType = ContentType
Me .File = ContentFile
Me .Name = Name
End Sub
End Structure
''' <summary>
''' Creates a new ContentManager which has been extended with functionality to support a Visual Basic (or other non-C#) project
''' </summary>
''' <param name="ServiceProvider">Your game has a .Services property; send that in here.</param>
''' <param name="ContentRootFolder">The root of your content folder, relative to your projects bin\Debug folder.</param>
''' <remarks></remarks>
Public Sub New (ByVal ServiceProvider As IServiceProvider, ByVal ContentRootFolder As String)
MyBase .New(ServiceProvider)
Me .strContentRootFolder = ContentRootFolder
Me .strPipelineRootFolder = ContentRootFolder.Replace("../" , "" )
Me .Fonts = New Hashtable(Of SpriteFont)
Me .Textures = New Hashtable(Of Texture2D)
Me .SubTextures = New Hashtable(Of Hashtable(Of Rectangle))
Me .Sounds = New Hashtable(Of SoundBank)
End Sub
''' <summary>
''' Load all assets that have been compiled by a VBContentManager.
''' </summary>
''' <param name="Compile">Whether or not to have MSBuild compile your game content before attempting to load it</param>
''' <remarks></remarks>
Public Sub LoadPipeline(ByVal Compile As Boolean )
If Compile Then
Me .CompileContent()
End If
For Each obj As ContentFile In Me .objContent
Try
Select Case obj.ContentType
'The pipeline will be compiled into either debug or release, depending upon
'which option is chosen in the IDE. We don't want to use the My namespace
'though, because it does not work with the xbox 360.
Case ContentTypes.Fonts
With obj.File.FullName.ToLower
Me .Fonts.Add(obj.Name, Me .Load(Of SpriteFont)(.Substring(.LastIndexOf("\" & Me .strPipelineRootFolder.ToLower) + 1).Replace(obj.File.Extension.ToLower, "" )))
End With
Case ContentTypes.Sounds
With obj.File.FullName.ToLower
Me .Sounds.Add(obj.Name, Me .Load(Of SoundBank)(.Substring(.LastIndexOf("\" & Me .strPipelineRootFolder.ToLower) + 1).Replace(obj.File.Extension.ToLower, "" )))
End With
Case ContentTypes.Textures
With obj.File.FullName.ToLower
Me .Textures.Add(obj.Name, Me .Load(Of Texture2D)(.Substring(.LastIndexOf("\" & Me .strPipelineRootFolder.ToLower) + 1).Replace(obj.File.Extension.ToLower, "" )))
End With
End Select
Catch ex As Exception
'msgBox("While loading the pipeline, a piece of content called " & obj.Name & " could not be found, and was skipped")
'A new piece of content has been added, but the programmer failed
'to instruct the VBContentPipeline to compile it. So the content
'will not be available during this instance of the Game.
End Try
Next
End Sub
Private Sub CompileContent()
Dim objProcess As Process
Me .objContent = New List(Of ContentFile)
Me .HarvestContent()
If Me .objContent.Count > 0 Then
Me .StartTheFakeCSharpFile()
Me .AddContentToTheFakeCSharpFile()
Me .EndTheFakeCSharpFile()
Try 'to write the fake C# project file to disk
Using TempStreamWriter As System.IO.StreamWriter = New System.IO.StreamWriter(Me .strContentRootFolder & "\VBContentPipeline.csproj" , False )
With TempStreamWriter
.Write(Me .strFakeCSharpProject)
.Close()
End With
End Using
Try 'to shell out to MSBuild.exe, sending it our fake c# project file
objProcess = System.Diagnostics.Process.Start("" "" & Environment.GetEnvironmentVariable("Windir" ) & _
"\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe" "" , "" "" & Me .strContentRootFolder & _
"\VBContentPipeline.csproj" " /verbosity:d /l:FileLogger,Microsoft.Build.Engine;logfile=" "" & _
Me .strContentRootFolder & "\VBPipelineBuild.log" "" )
'wait for that to finish
While Not objProcess.HasExited
Threading.Thread.Sleep(100)
End While
Catch ex As Exception
MsgBox("When building the pipeline and trying to run MSBuild.exe, " & ex.Message)
End Try
Catch ex As Exception
MsgBox("When building the pipeline and trying to create the fake C# file " "" & Me .strContentRootFolder & "\VBContentPipeline.csproj" ", " & ex.Message)
End Try
End If
End Sub
Private Sub HarvestContent()
Dim objRoot As System.IO.DirectoryInfo = New System.IO.DirectoryInfo(Me .strContentRootFolder)
For Each sound As System.IO.FileInfo In objRoot.GetFiles("*.xab" , IO.SearchOption.AllDirectories)
If Me .objContent.Contains(New ContentFile(ContentTypes.Sounds, sound, sound.Name.Replace(sound.Extension, "" ))) Then
Me .intDupeSound += 1
Me .objContent.Add(New ContentFile(ContentTypes.Sounds, sound, sound.Name.Replace(sound.Extension, "" ) & Me .intDupeSound.ToString))
Else
Me .objContent.Add(New ContentFile(ContentTypes.Sounds, sound, sound.Name.Replace(sound.Extension, "" )))
End If
Next
For Each texture As System.IO.FileInfo In objRoot.GetFiles("*.png" , IO.SearchOption.AllDirectories)
If Me .objContent.Contains(New ContentFile(ContentTypes.Textures, texture, texture.Name.Replace(texture.Extension, "" ))) Then
Me .intDupeTexture += 1
Me .objContent.Add(New ContentFile(ContentTypes.Textures, texture, texture.Name.Replace(texture.Extension, "" ) & Me .intDupeSound.ToString))
Else
Me .objContent.Add(New ContentFile(ContentTypes.Textures, texture, texture.Name.Replace(texture.Extension, "" )))
End If
Next
For Each texture As System.IO.FileInfo In objRoot.GetFiles("*.jpg" , IO.SearchOption.AllDirectories)
If Me .objContent.Contains(New ContentFile(ContentTypes.Textures, texture, texture.Name.Replace(texture.Extension, "" ))) Then
Me .intDupeTexture += 1
Me .objContent.Add(New ContentFile(ContentTypes.Textures, texture, texture.Name.Replace(texture.Extension, "" ) & Me .intDupeSound.ToString))
Else
Me .objContent.Add(New ContentFile(ContentTypes.Textures, texture, texture.Name.Replace(texture.Extension, "" )))
End If
Next
For Each texture As System.IO.FileInfo In objRoot.GetFiles("*.gif" , IO.SearchOption.AllDirectories)
If Me .objContent.Contains(New ContentFile(ContentTypes.Textures, texture, texture.Name.Replace(texture.Extension, "" ))) Then
Me .intDupeTexture += 1
Me .objContent.Add(New ContentFile(ContentTypes.Textures, texture, texture.Name.Replace(texture.Extension, "" ) & Me .intDupeSound.ToString))
Else
Me .objContent.Add(New ContentFile(ContentTypes.Textures, texture, texture.Name.Replace(texture.Extension, "" )))
End If
Next
For Each font As System.IO.FileInfo In objRoot.GetFiles("*.spritefont" , IO.SearchOption.AllDirectories)
If Me .objContent.Contains(New ContentFile(ContentTypes.Fonts, font, font.Name.Replace(font.Extension, "" ))) Then
Me .intDupeFont += 1
Me .objContent.Add(New ContentFile(ContentTypes.Fonts, font, font.Name.Replace(font.Extension, "" ) & Me .intDupeSound.ToString))
Else
Me .objContent.Add(New ContentFile(ContentTypes.Fonts, font, font.Name.Replace(font.Extension, "" )))
End If
Next
End Sub
Private Sub StartTheFakeCSharpFile()
Me .strFakeCSharpProject = _
"<Project DefaultTargets=" "Build" " xmlns=" "http://schemas.microsoft.com/developer/msbuild/2003" ">" & vbCrLf & _
"<PropertyGroup>" & vbCrLf & _
"<Configuration Condition=" " '$(Configuration)' == '' " ">Debug</Configuration>" & vbCrLf & _
"<Platform Condition=" " '$(Platform)' == '' " ">x86</Platform>" & vbCrLf & _
"<OutputType>WinExe</OutputType>" & vbCrLf & _
"<AppDesignerFolder>Properties</AppDesignerFolder>" & vbCrLf & _
"<AssemblyName>" & My.Application.Info.AssemblyName & "</AssemblyName>" & vbCrLf & _
"<XnaPlatform>Windows</XnaPlatform>" & vbCrLf & _
"<XnaFrameworkVersion>v1.0</XnaFrameworkVersion>" & vbCrLf & _
"<XNAGlobalContentPipelineAssemblies>Microsoft.Xna.Framework.Content.Pipeline.EffectImporter.dll;" & _
"Microsoft.Xna.Framework.Content." & _
"Pipeline.FBXImporter.dll;Microsoft.Xna.Framework.Content.Pipeline.TextureImporter.dll;" & _
"Microsoft.Xna.Framework.Content.Pipeline.XImporter.dll</XNAGlobalContentPipelineAssemblies>" & vbCrLf & _
"</PropertyGroup>" & vbCrLf & _
"<PropertyGroup Condition=" " '$(Configuration)|$(Platform)' == 'Debug|x86' " ">" & vbCrLf & _
"<OutputPath>" & My.Application.Info.DirectoryPath & "\" & Me .strPipelineRootFolder & "</OutputPath>" & vbCrLf & _
"</PropertyGroup>" & vbCrLf & _
"<ItemGroup>"
End Sub
Private Sub AddContentToTheFakeCSharpFile()
For Each content As ContentFile In Me .objContent
Me .strFakeCSharpProject &= vbCrLf & _
"<Content Include=" "" & content.File.FullName & "" ">" & vbCrLf & _
"<XNAUseContentPipeline>true</XNAUseContentPipeline>" & vbCrLf & _
"<Importer>" & CType (content.ContentType, ImporterName).ToString & "</Importer>" & vbCrLf & _
"<Processor>" & CType (content.ContentType, ProcessorName).ToString & "</Processor>" & vbCrLf & _
"<Name>" & content.Name & "</Name>" & vbCrLf & _
"</Content>"
Next
End Sub
Private Sub EndTheFakeCSharpFile()
Me .strFakeCSharpProject &= _
"</ItemGroup>" & vbCrLf & _
"<Import Project=" "$(MSBuildBinPath)\Microsoft.CSharp.targets" " />" & vbCrLf & _
"<Import Project=" "$(MSBuildExtensionsPath)\Microsoft\XNA\Game Studio Express\v1.0\Microsoft.Xna.ContentPipeline.targets" " />" & vbCrLf & _
"<Import Project=" "$(MSBuildExtensionsPath)\Microsoft\XNA\Game Studio Express\v1.0\Microsoft.Xna.Common.targets" " />" & vbCrLf & _
"</Project>"
End Sub
End Class
In a nutshell, the VBContentManager class uses a supplied directory as a root folder which it scans for content (texture files, XACT sound projects, and spritefonts) in the HarvestContent method. It also has the ability to produce a C# project file that includes information about the harvested content, which it can pass to MSBuild in order to have the corresponding .xnb (et al) files created on your behalf.
To use the VBContentManager class, all you have to do is call the LoadPipeline method in your game's LoadGraphicsContent sub, indicating whether or not the content is already compiled (false) or whether you want to execute the C# hack process (true).
The last thing the LoadPipeline method does for you is it uses the Load method of the underlying ContentManager to import the texture, sound and font files into corresponding typed hash tables, which reside as public members of the VBContentManager. The resources are keyed by filename (no extension) in the respective hash table.
Here is an example of a simple base game class that makes use of the VBContentManager class (you can also watch the video tutorial to see this class being used by a game project).
Public Class MyBaseGame
Inherits Game
Protected objGDM As GraphicsDeviceManager
Protected objCM As VBContentManager
Protected objSB As SpriteBatch
''' <summary>
''' Starts a new game for the XNA 2D Engine
''' </summary>
''' <param name="WindowTitle">The window title when the game is not full-screen</param>
''' <param name="MouseIsVisible">Whether or not the mouse is visible by default</param>
''' <param name="ContentRootFolder">The root of your content folder, relative to your projects bin\debug (or release) folder</param>
''' <remarks></remarks>
Public Sub New (ByVal WindowTitle As String, ByVal MouseIsVisible As Boolean , ByVal ContentRootFolder As String)
Me .objGDM = New GraphicsDeviceManager(Me )
Me .objCM = New VBContentManager(Me .Services, ContentRootFolder)
Me .Window.Title = WindowTitle
Me .IsMouseVisible = MouseIsVisible
End Sub
Protected Overrides Sub LoadGraphicsContent(ByVal loadAllContent As Boolean )
MyBase .LoadGraphicsContent(loadAllContent)
Me .objCM.LoadPipeline(True )
End Sub
Protected Overrides Sub Initialize()
MyBase .Initialize()
Me .objSB = New SpriteBatch(Me .objGDM.GraphicsDevice)
End Sub
End Class
Here is a game that inherits from the above base game class. The root content folder for this game is a peer folder of the project's bin folder. Once you've got all the other stuff sitting in an engine somewhere, this is essentially all you need to do to spawn a new game with a vb content manager, effectively simulating VB support for XNA.
Public Class XNAGameForWindows
Inherits MyBaseGame
Public Sub New ()
MyBase .New("XNA Game for Windows" , True , "../../Content" )
End Sub
End Class
And here's the typed hash table. I wouldn't grab textures & the like out of a hash tables directly from a draw routine, but at the top of your program you can pull them out into discrete references or put them into lists, or whatever. The VBContentManager just makes them available in the hash in a way that's easy for humans to find them (ie. by file name), and you can do whatever you want with them from there.
Public Class Hashtable(Of Type)
Inherits DictionaryBase
Public ReadOnly Property Keys() As ICollection
Get
Return MyBase .Dictionary.Keys
End Get
End Property
Default Public Property Item(ByVal key As String) As Type
Get
Return CType (MyBase .Dictionary(key), Type)
End Get
Set (ByVal value As Type)
MyBase .Dictionary(key) = value
End Set
End Property
Public Overloads Sub Add(ByVal key As String, ByVal obj As Type)
MyBase .Dictionary.Add(key, obj)
End Sub
Public ReadOnly Property Values() As ICollection
Get
Return Dictionary.Values
End Get
End Property
Public Function Contains(ByVal key As String) As Boolean
Return Dictionary.Contains(key)
End Function
Public Sub Remove(ByVal key As String)
Dictionary.Remove(key)
End Sub
End Class
Here's the link to on Vimeo.
This tutorial is a little bit longer and a little bit more involved than the past tutorials. We'll start down the road to separating game logic from game logistics by creating a new project called XNA 2D Engine and moving the "MyGame" class into it. We'll turn the MyGame into a base class to be used with the 2D engine.
We'll introduce the VBContentManager class, my implementation of a ContentManager extended with our "VB Content Pipeline hack" code (there's lots more on that, below). We'll then go on to making a primitive sprite in Photoshop and drawing it to the screen with a SpriteBatch object.
Here is some companion text to go with the video, that describes in detail some code I'll be importing but not spending a lot of time describing in the video:
In a standard C# XNA project, the default game class is created for you with a GraphicsDeviceManager and a ContentManager both instantiated and ready to go. As we saw in Tutorial 3, it's fairly easily make our own class that inherits from the base XNA Game class, create our own GraphicsDeviceManager and quickly reproduce what the C# template generates automatically.
What tutorial 3 did not touch on was the ContentManager, because for us VB'ers, the ContentManager is really the point where the lack of VB support in XNA requires us to do a little bit of legwork, so I held off on the subject until now.
In C#, the ContentManager class loads cross-platform file types (like .xnb files) that MSBuild creates automatically from things like .png or .jpg files that get included in the C# project. The primary issue when using a ContentManager with VB is getting these .xnb files created from our .png or .jpg files, because there is no automatic conversion process built into the IDE.
My approach to solving this problem was to borrow largely what's been documented by Alan Phipps, and from that, create my own ContentManager class called the VBContentManager class. Here's is the VBContentManager class, in it's entirety:
In a nutshell, the VBContentManager class uses a supplied directory as a root folder which it scans for content (texture files, XACT sound projects, and spritefonts) in the HarvestContent method. It also has the ability to produce a C# project file that includes information about the harvested content, which it can pass to MSBuild in order to have the corresponding .xnb (et al) files created on your behalf.
To use the VBContentManager class, all you have to do is call the LoadPipeline method in your game's LoadGraphicsContent sub, indicating whether or not the content is already compiled (false) or whether you want to execute the C# hack process (true).
The last thing the LoadPipeline method does for you is it uses the Load method of the underlying ContentManager to import the texture, sound and font files into corresponding typed hash tables, which reside as public members of the VBContentManager. The resources are keyed by filename (no extension) in the respective hash table.
Here is an example of a simple base game class that makes use of the VBContentManager class (you can also watch the video tutorial to see this class being used by a game project).
Here is a game that inherits from the above base game class. The root content folder for this game is a peer folder of the project's bin folder. Once you've got all the other stuff sitting in an engine somewhere, this is essentially all you need to do to spawn a new game with a vb content manager, effectively simulating VB support for XNA.
And here's the typed hash table. I wouldn't grab textures & the like out of a hash tables directly from a draw routine, but at the top of your program you can pull them out into discrete references or put them into lists, or whatever. The VBContentManager just makes them available in the hash in a way that's easy for humans to find them (ie. by file name), and you can do whatever you want with them from there.
![]() | 10/17/07 |
VB.NET XNA Tutorial 3: Creating a Game class
[GSE 1.0 Refresh]
There is now a . This template automates the steps shown in the video.
First, read this!
There is now a . This template automates the steps shown in the video.
First, read this!
- Video tutorials are now hosted at Vimeo in High Definition
- Be sure to watch them in Full mode
- If your video quality goes all wacky, look in the lower right for a Scaling button and turn Scaling off (this will make life easier on the player and allow the quality to go back up)
- You can't embed HD vids from Vimeo to your website, otherwise I would!
![]() | 10/15/07 |
Vimeo
Vimeo's like YouTube, but Vimeo lets you host HD quality videos that look worlds better than YouTube. The only catch is you can't embed HD quality stuff off-site (you have to watch them directly from Vimeo's website, which I'm sure it's an add-revenue thing that makes it all possible to begin with).
But check out the kind of quality you can get hosted for free, it's pretty cool. This is just my test upload, and if you play it full screen you'll see what I'm talking about:
So from now on any video tutorials I make will be hosted at Vimeo and I've got a namespace setup there which I'll add to the permalinks.
But check out the kind of quality you can get hosted for free, it's pretty cool. This is just my test upload, and if you play it full screen you'll see what I'm talking about:
So from now on any video tutorials I make will be hosted at Vimeo and I've got a namespace setup there which I'll add to the permalinks.
![]() | 10/13/07 |
VB.NET XNA Tutorial 2: Creating an XNA Windows Game project
[GSE 1.0 Refresh]
There is now a . This template automates the steps shown in the video.
Here is a video tutorial that describes very simply how to setup a "game" project for Windows using VB.NET and Visual Studio 2005.
from on .
There is now a . This template automates the steps shown in the video.
Here is a video tutorial that describes very simply how to setup a "game" project for Windows using VB.NET and Visual Studio 2005.
from on .
![]() | 10/12/07 |
VB.NET XNA Tutorial 1: Getting started
First things first; let's get this whole XNA thing straight.
The XNA framework is a managed wrapper for DirectX. So you'll need the latest version of DirectX installed.
XNA comes to you branded in a somewhat vaguely (and soon to be confusingly) named piece of software called "Game Studio Express". The deal is, Microsoft diverted their previous Managed DirectX project into the XNA project; the XNA project grew to include not only a managed wrapper for DirectX, but also some other tools like the Content Pipeline, and XACT. All of this was then wrapped into a software suite - not called XNA - but actually called "Game Studio Express", which was designed specifically to be an "expansion pack" of sorts for Visual C# 2005 Express Edition.
So anyway... what this all means for us VB freaks is that in order to get the managed wrapper for DirectX on our development machines, and in order to have at that Content Pipeline and XACT stuff, we have to do what everybody else has to do: install Visual C# 2005 Express Edition, and then install Game Studio Express. Which is all the more counter-intuitive for us, since our goal is to avoid using C# in the first place because we're too lazy to start using curly braces and semi-colons.
Don't worry. . Enjoy it, involve a beverage perhaps.
Once you've got Game Studio Express installed, your newly acquired C# IDE gains XNA-related project options that no other IDE gets. To learn a little bit about what we're going to be missing out on in terms of XNA-related IDE options, let's go ahead and poke around the C# IDE for a sec. Run the C# IDE, and start a New Project - check out the types of projects you can start:

Go ahead and start a new Windows Game project, just to look around. Pop open the solution explorer and add a new Item to the project; check out what options we have available for creating New Items in the C# IDE:

Using the C# IDE, there are nifty items available like "Sprite Font" and "Game Component":

So those are Game Studio Express IDE hooks, they're just templates for making stuff. Nothing we can't handle ourselves.
Ok, we've seen enough. Cancel all that business and let's move over to our Visual Basic IDE.
Game Studio Express isn't going to do anything for our Visual Basic IDE, so if you go looking for a Windows Game project you're going to be disappointed

Update: The remainder of this tutorial is obsolete. was posted on this blog in November 2007
But, what it has done is installed the managed XNA libraries, the Content Pipeline compiler, and tools like XACT. We've got everything we need to do some serious damage, there's just a couple things we'll have to do that the C# guys don't have to:
In the next article, we'll check out my adaptations of the "Start a new project" and "deal with the Content Pipeline hack" and I'll probably start brushing up against the merits of putting all of this stuff into a common project you can reuse for future games (in other words, we'll start building the engine).
The XNA framework is a managed wrapper for DirectX. So you'll need the latest version of DirectX installed.
XNA comes to you branded in a somewhat vaguely (and soon to be confusingly) named piece of software called "Game Studio Express". The deal is, Microsoft diverted their previous Managed DirectX project into the XNA project; the XNA project grew to include not only a managed wrapper for DirectX, but also some other tools like the Content Pipeline, and XACT. All of this was then wrapped into a software suite - not called XNA - but actually called "Game Studio Express", which was designed specifically to be an "expansion pack" of sorts for Visual C# 2005 Express Edition.
So anyway... what this all means for us VB freaks is that in order to get the managed wrapper for DirectX on our development machines, and in order to have at that Content Pipeline and XACT stuff, we have to do what everybody else has to do: install Visual C# 2005 Express Edition, and then install Game Studio Express. Which is all the more counter-intuitive for us, since our goal is to avoid using C# in the first place because we're too lazy to start using curly braces and semi-colons.
Don't worry. . Enjoy it, involve a beverage perhaps.
Once you've got Game Studio Express installed, your newly acquired C# IDE gains XNA-related project options that no other IDE gets. To learn a little bit about what we're going to be missing out on in terms of XNA-related IDE options, let's go ahead and poke around the C# IDE for a sec. Run the C# IDE, and start a New Project - check out the types of projects you can start:

Go ahead and start a new Windows Game project, just to look around. Pop open the solution explorer and add a new Item to the project; check out what options we have available for creating New Items in the C# IDE:

Using the C# IDE, there are nifty items available like "Sprite Font" and "Game Component":

So those are Game Studio Express IDE hooks, they're just templates for making stuff. Nothing we can't handle ourselves.
Ok, we've seen enough. Cancel all that business and let's move over to our Visual Basic IDE.
Game Studio Express isn't going to do anything for our Visual Basic IDE, so if you go looking for a Windows Game project you're going to be disappointed

Update: The remainder of this tutorial is obsolete. was posted on this blog in November 2007
But, what it has done is installed the managed XNA libraries, the Content Pipeline compiler, and tools like XACT. We've got everything we need to do some serious damage, there's just a couple things we'll have to do that the C# guys don't have to:
- 1. We will need to initiate our own project, rather than use the Game project template. And that means we'll have to create those nifty items like "Game Component" and "Sprite Font" by ourselves, too.
In , Alan Phipps demonstrates how to start an XNA Windows Game using the Visual Studio .NET IDE.
In addition to the advice he gives there, I would suggest removing the System.Drawing reference from your project, as this can create an ambiguity with items of the same name (such as Color and Rectangle) that exist in the XNA namespace.
I also suggest you not wait until tutorial 20 to start making your XNA projects in this way, but hindsight is 20/20. - 2. We'll want to use the Content Pipeline, because it's fairly cool. The Content Pipeline has some rules though - mainly it wants us to convert our resources into a "cross platform format" (something that works on both Windows and XBox360). So for example, if you have a sprite texture that's a .gif file, the Content Pipeline will want that to be an .xnb file. And sounds are even more wacky. If you make a sound resource with XACT, it will actually need to be broken down into 3 files: an .xgs file, .xsb file, and .xwb file. Yea, I know. This sounds crazy already and we haven't even started yet. Hang in there, we're almost done:
The Content Pipeline hassle does seems kind of unnecessarily complicated at first. You'll like it though, I promise (and you don't have to remember those file extensions). Here's the deal: out in your 's .NET 2.0 framework folder there is a program called MSBuild.exe. MSBuild knows how to convert textures (like "spaceship.png") and sound projects you create with XACT into all those .x-blah-blah files for the Content Pipepline. It's actually really easy; MSBuild does all the work for you. You just tell it what you want to convert (pass it file names in a batch) and it converts them all for you.
Now here's the catch; the way you "tell MSBuild to convert stuff in a batch" is to pass it a C# project file. Yea, like "WindowsGame1.csproj". Which kinda makes sense when you remember that all this stuff was designed to work with Visual C# Express Edition projects. MSBuild takes a .csproj file and for each resource it finds described in there, it creates a Content Pipeline .x-whatever file. With C# projects, this call to MSBuild is performed at the time the project is compiled. In XNA marketing lingo they call this "automatic". For us this will be a "manual" process... but we're lazy, so we'll automate it, and at the end of the day it'll end up being just as automatic as the next guy's.
In , Alan Phipps demonstrates how he simply builds a "fake" .csproj file with his resource references in it, and then feeds that file to MSBuild in order to trick it into thinking it's processing a C# XNA project.
Not bad! So I do the same thing, but I chose to integrate this process into my engine with a "compile" flag (rather than have it be a separate project that must be run). I'll show you how I did this in the next tutorial, and between the two you can choose to do it my way, Alan's way, or say "screw this, I'm using C#"
In the next article, we'll check out my adaptations of the "Start a new project" and "deal with the Content Pipeline hack" and I'll probably start brushing up against the merits of putting all of this stuff into a common project you can reuse for future games (in other words, we'll start building the engine).
![]() | 10/11/07 |
VB.NET code posting tool now available
My vb.net source code posting tool is now online and can be found on my personal web server at .
You can optionally assign width and height to the output div and toggle whether or not it scrolls overflow. Here's some output generated by the code posting tool (a chunk of the code posting tool page's own code... run through itself... trippy!
Oh yea, it knows the difference between keywords and properties now, too:
You can optionally assign width and height to the output div and toggle whether or not it scrolls overflow. Here's some output generated by the code posting tool (a chunk of the code posting tool page's own code... run through itself... trippy!
Public Class codeformatter
Inherits Page
Private txtInput, txtOutput, txtWidth, txtHeight As TextBox
Private chkScroll As CheckBox
Private objForm As HtmlForm
Private WithEvents btnFormat As Button
Private Tokens As New System.Collections.Generic.List(Of String)
Private Keywords As New System.Collections.Generic.List(Of String)
Protected Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Me.Init
Me.InitializeControls()
Me.Controls.Add(New LiteralControl("<html><head><title>emachine's vb.net post formatter</title></head><body><center><h1>emachine's vb.net post formatter*</h1>" & _
"<font size=""2"">*now with zero aesthetic appeal</font>"))
Me.Controls.Add(Me.objForm)
With Me.objForm
.Controls.Add(New LiteralControl("<br />Paste from your IDE <font size=""2"">(tip: Ctrl+A, Ctrl+V)</font><br />"))
.Controls.Add(Me.txtInput)
.Controls.Add(New LiteralControl("<br />width:"))
.Controls.Add(Me.txtWidth)
.Controls.Add(New LiteralControl("px, height:"))
.Controls.Add(Me.txtHeight)
.Controls.Add(New LiteralControl("px "))
.Controls.Add(Me.chkScroll)
.Controls.Add(New LiteralControl("<br /><br />"))
.Controls.Add(Me.btnFormat)
.Controls.Add(New LiteralControl("<br /><br />Copy to your blog <font size=""2"">(tip: Ctrl+A, Ctrl+C)</font><br />"))
.Controls.Add(Me.txtOutput)
End With
Me.Controls.Add(New LiteralControl("Preview:<br />"))
'etc.
Inherits Page
Private txtInput, txtOutput, txtWidth, txtHeight As TextBox
Private chkScroll As CheckBox
Private objForm As HtmlForm
Private WithEvents btnFormat As Button
Private Tokens As New System.Collections.Generic.List(Of String)
Private Keywords As New System.Collections.Generic.List(Of String)
Protected Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Me.Init
Me.InitializeControls()
Me.Controls.Add(New LiteralControl("<html><head><title>emachine's vb.net post formatter</title></head><body><center><h1>emachine's vb.net post formatter*</h1>" & _
"<font size=""2"">*now with zero aesthetic appeal</font>"))
Me.Controls.Add(Me.objForm)
With Me.objForm
.Controls.Add(New LiteralControl("<br />Paste from your IDE <font size=""2"">(tip: Ctrl+A, Ctrl+V)</font><br />"))
.Controls.Add(Me.txtInput)
.Controls.Add(New LiteralControl("<br />width:"))
.Controls.Add(Me.txtWidth)
.Controls.Add(New LiteralControl("px, height:"))
.Controls.Add(Me.txtHeight)
.Controls.Add(New LiteralControl("px "))
.Controls.Add(Me.chkScroll)
.Controls.Add(New LiteralControl("<br /><br />"))
.Controls.Add(Me.btnFormat)
.Controls.Add(New LiteralControl("<br /><br />Copy to your blog <font size=""2"">(tip: Ctrl+A, Ctrl+C)</font><br />"))
.Controls.Add(Me.txtOutput)
End With
Me.Controls.Add(New LiteralControl("Preview:<br />"))
'etc.
Oh yea, it knows the difference between keywords and properties now, too:
If ItsAClass.End Then
"No more blue .Ends!"
End If
"No more blue .Ends!"
End If
![]() | 10/10/07 |
Great bugs err alike
So as I've mentioned I'm working on a source-code formatter and it currently has this, uh, "feature" where it doesn't quite know the difference between a keyword and a class member of the same name. Given the input "MyClass.End" where End is a keyword, it will erroneously produce the output "MyClass.End" rather than "MyClass.End".
But today I noticed something which made me feel slightly less dumb about that. If you , check out the 3rd-to-last line of the code block.
Perhaps the xna forum web programmer was :)
But today I noticed something which made me feel slightly less dumb about that. If you , check out the 3rd-to-last line of the code block.
Perhaps the xna forum web programmer was :)
Code posting tool in the works
If I'm going to have a blog about coding I'll probably want to post source code now and then. But I couldn't find a VB.NET source -> HTML formatter anywhere, so I'm writing a little online utility to facilitate a relatively painless/intuitive "copy & paste" from the IDE into HTML for posting/blogging.
It's still beta-ish, just worked on it for an hour or so last night. Here's a sample of it's output, it's my current XNA game's Draw method, copied & pasted from the IDE into the processor, then from the processor into this blog's HTML editor:
Not half bad, considering I was drinking and watching TV while I wrote it. Basically it just sets the font and the spaces to be non-breaking, re-colors keywords, comments and literal strings to the default Visual Studio 2005 IDE colors. No biggie, but oddly enough I couldn't find a (free) tool that does this anywhere online.
It's just about good as-is, before I "release" it I do need to teach it the difference between keywords and properties (i.e., MyClass.End isn't quite right, which you can see did in fact happen on the 3rd to last line in the above sample).
And before I put it out there I want to add some quick options, like whether or not to restrict the dimensions of the output div container, whether or not the container scrolls, and maybe even toss in BBCode support.
Basic doesn't really have that many tokenization characters, maybe half a dozen or so and that's it. So this was pretty easy to tackle. I'm not a C# programmer and I dunno how how many tokenization chars they have, but if it's not too crazy I could add C# support.
The utility won't beautify your code like the IDE does, it just recovers formatting lost in the copy & paste process from the IDE to the web using whatever you paste into it verbatim.
It's still beta-ish, just worked on it for an hour or so last night. Here's a sample of it's output, it's my current XNA game's Draw method, copied & pasted from the IDE into the processor, then from the processor into this blog's HTML editor:
Protected Overrides Sub Draw(ByVal gameTime As Microsoft.Xna.Framework.GameTime)
XNALib.GraphicsDeviceManager.GraphicsDevice.Clear(ClearOptions.Target, Me.objFrameColor, 1.0F, 0)
ScreenManager.Root.Draw(gameTime)
MyBase.Draw(gameTime)
XNALib.RenderDebugOptions()
'calculate fps data
Me.intFrames += 1
Me.objOneSecond += gameTime.ElapsedGameTime
'update this information every [gametime] elapsed second
If Me.objOneSecond.TotalSeconds >= 1 Then
Me.strActualFPS = Math.Round((Me.intFrames / Me.objOneSecond.TotalSeconds) * Me.objOneSecond.TotalSeconds, 1).ToString
Me.objOneSecond -= Me.objOneSecond
Me.intFrames = 0
End If
If XNALib.ShowFPS Then
'render
XNALib.SpriteDrawer.Begin()
XNALib.SpriteDrawer.DrawString(XNALib.Fonts("dialog"), Me.strActualFPS & " fps", Vector2.One, New Color(0, 0, 0, 175))
XNALib.SpriteDrawer.DrawString(XNALib.Fonts("dialog"), Me.strActualFPS & " fps", Vector2.Zero, Color.Red)
XNALib.SpriteDrawer.End()
End If
End Sub
XNALib.GraphicsDeviceManager.GraphicsDevice.Clear(ClearOptions.Target, Me.objFrameColor, 1.0F, 0)
ScreenManager.Root.Draw(gameTime)
MyBase.Draw(gameTime)
XNALib.RenderDebugOptions()
'calculate fps data
Me.intFrames += 1
Me.objOneSecond += gameTime.ElapsedGameTime
'update this information every [gametime] elapsed second
If Me.objOneSecond.TotalSeconds >= 1 Then
Me.strActualFPS = Math.Round((Me.intFrames / Me.objOneSecond.TotalSeconds) * Me.objOneSecond.TotalSeconds, 1).ToString
Me.objOneSecond -= Me.objOneSecond
Me.intFrames = 0
End If
If XNALib.ShowFPS Then
'render
XNALib.SpriteDrawer.Begin()
XNALib.SpriteDrawer.DrawString(XNALib.Fonts("dialog"), Me.strActualFPS & " fps", Vector2.One, New Color(0, 0, 0, 175))
XNALib.SpriteDrawer.DrawString(XNALib.Fonts("dialog"), Me.strActualFPS & " fps", Vector2.Zero, Color.Red)
XNALib.SpriteDrawer.End()
End If
End Sub
Not half bad, considering I was drinking and watching TV while I wrote it. Basically it just sets the font and the spaces to be non-breaking, re-colors keywords, comments and literal strings to the default Visual Studio 2005 IDE colors. No biggie, but oddly enough I couldn't find a (free) tool that does this anywhere online.
It's just about good as-is, before I "release" it I do need to teach it the difference between keywords and properties (i.e., MyClass.End isn't quite right, which you can see did in fact happen on the 3rd to last line in the above sample).
And before I put it out there I want to add some quick options, like whether or not to restrict the dimensions of the output div container, whether or not the container scrolls, and maybe even toss in BBCode support.
Basic doesn't really have that many tokenization characters, maybe half a dozen or so and that's it. So this was pretty easy to tackle. I'm not a C# programmer and I dunno how how many tokenization chars they have, but if it's not too crazy I could add C# support.
The utility won't beautify your code like the IDE does, it just recovers formatting lost in the copy & paste process from the IDE to the web using whatever you paste into it verbatim.
![]() | 10/9/07 |
VB.NET XNA Tutorial 0: Prologue
I hesitated a little bit about doing this VB.NET related XNA blog stuff for a couple of reasons. First, there's a new version of Game Studio Express on the way out shortly (version 2.0) which has support for Visual Studio 2005. That means very soon, you will no longer be required to use Visual C# Express for XNA related IDE features.
But unfortunately, support for Visual Studio 2005 doesn't equate to support for languages other than C#. Here's a , the meat of which is captured in this post by Shawn Hargreaves (one of Microsoft's XNA guys)
So that means for the immediate to long term, we're officially "XNA hackers". I dunno about you but that makes me feel like a rebel.
Anyway, the other reason I thought twice about this was the fact that, over at Alan Phipps's website (which is permalinked right over there in the links area), a lot of this has been explained already. After following the tutorials and gaining a little bit of insight into the process, I've decided I'm going to offer you my take on it. Rather than build a specific application for a specific task (which a lot of tutorials seem to do), here we'll be building something a little more generic; more of an engine that can be used to do "whatever" in 2D. Some of it will be "here's how you do it", and some of it will be me showing up to the party 5 months late with "omg I didn't even know about render targets! Holy crap, now we have to totally rewrite the engine!"
At any rate, you'll have a couple different sources to draw from when it comes to using XNA with VB.NET, and there's really not much of that floating around the net right now.
But unfortunately, support for Visual Studio 2005 doesn't equate to support for languages other than C#. Here's a , the meat of which is captured in this post by Shawn Hargreaves (one of Microsoft's XNA guys)
"... we are only doing IDE work to integrate the XNA Framework into the C# project system, and not currently supporting the project systems for any other languages. In the absence of this IDE work, you miss out on exactly two things:Now, you may be just fine without those things. Maybe you're making a Windows game that doesn't use the Content Pipeline. In that case you don't care about our IDE integration, so the lack of it will not hurt you, and you can use any .NET langauge you like.
- Content pipeline integration
- The ability to deploy and debug on Xbox 360
If you want to use the Content Pipeline, or deploy to Xbox, you can still do that by building your other-language code into an assembly, then using a stub C# project that links with this assembly to build your content, deploy to Xbox, and then call into your real assembly as soon as it starts up. It's a hack, but some people have reported success working this way."
So that means for the immediate to long term, we're officially "XNA hackers". I dunno about you but that makes me feel like a rebel.
Anyway, the other reason I thought twice about this was the fact that, over at Alan Phipps's website (which is permalinked right over there in the links area), a lot of this has been explained already. After following the tutorials and gaining a little bit of insight into the process, I've decided I'm going to offer you my take on it. Rather than build a specific application for a specific task (which a lot of tutorials seem to do), here we'll be building something a little more generic; more of an engine that can be used to do "whatever" in 2D. Some of it will be "here's how you do it", and some of it will be me showing up to the party 5 months late with "omg I didn't even know about render targets! Holy crap, now we have to totally rewrite the engine!"
At any rate, you'll have a couple different sources to draw from when it comes to using XNA with VB.NET, and there's really not much of that floating around the net right now.
![]() | 10/8/07 |
Sub Main()
Just my boring 1st post when setting up the blog. There's nothing real interesting here.
I'm building a 2D engine with XNA, using Visual Basic .NET & Visual Studio 2005. The purpose of the engine will be to provide a front end for a vaporware game I want to write someday in my free time (there's a lot to be blogged about that later), and at the same time, I'll be using the engine to drive some touch-screen applications I'll be writing for my employer. Work on my game is almost entirely conceptual so far, but the engine itself is being used in the real world and being worked on quite regularly.
A significant portion of the engine is actually written, but as I go along I learn new things about XNA and from time to time I change stuff about it. You know how it goes.
So why bother with this blog, since there are so many more knowledgeable people out there than me? I just want to try and help fill the massive gaps in VB.NET XNA examples on the web. Whenever I feel like I've designed something worth mentioning, I'll try to take some time to post examples.
I'm building a 2D engine with XNA, using Visual Basic .NET & Visual Studio 2005. The purpose of the engine will be to provide a front end for a vaporware game I want to write someday in my free time (there's a lot to be blogged about that later), and at the same time, I'll be using the engine to drive some touch-screen applications I'll be writing for my employer. Work on my game is almost entirely conceptual so far, but the engine itself is being used in the real world and being worked on quite regularly.
A significant portion of the engine is actually written, but as I go along I learn new things about XNA and from time to time I change stuff about it. You know how it goes.
So why bother with this blog, since there are so many more knowledgeable people out there than me? I just want to try and help fill the massive gaps in VB.NET XNA examples on the web. Whenever I feel like I've designed something worth mentioning, I'll try to take some time to post examples.
Subscribe to:
Posts (Atom)
