ThreeDWorld - General Steps for creating a game
Tutorials
Sample Content Build file
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Set Paths here -->
<PropertyGroup>
<!-- the output directory where built assets will be placed -->
<OutputDirectory>..\ContentBuild\Content</OutputDirectory>
<!-- the executable used to import each asset (this can be reused for any content build) -->
<AssetImporter>AssetImporter.exe</AssetImporter>
<!-- the executable used to update the Silverlight asset project with the assets that were built (this can be reused for any content build) -->
<ContentBuild>ContentBuild.exe</ContentBuild>
<!-- the Silverlight project that will hold the built assets -->
<ContentBuildProject>..\ContentBuild\ContentBuild.csproj</ContentBuildProject>
<!-- the root path for each asset in the build -->
<ContentBuildRoot>..\ContentBuild</ContentBuildRoot>
<!-- path to directx shader compiler (current setting assumes it is in the path environment variable) -->
<ShaderCompiler>fxc.exe</ShaderCompiler>
</PropertyGroup>
<!-- Add Content Build Assemblies here -->
<ItemGroup>
</ItemGroup>
<!-- Add Shader Assets here (expects the extension to be hlsl and the file must be in the root of the asset directory) -->
<ItemGroup>
<ShaderAsset Include="BlockVertex">
<Entry>VSMain</Entry>
<Profile>vs_2_0</Profile>
</ShaderAsset>
<ShaderAsset Include="BlockPixel">
<Entry>PSMain</Entry>
<Profile>ps_2_0</Profile>
</ShaderAsset>
<ShaderAsset Include="ModelVertex">
<Entry>VSMain</Entry>
<Profile>vs_2_0</Profile>
</ShaderAsset>
<ShaderAsset Include="ModelPixel">
<Entry>PSMain</Entry>
<Profile>ps_2_0</Profile>
</ShaderAsset>
<ShaderAsset Include="SkyVertex">
<Entry>VSMain</Entry>
<Profile>vs_2_0</Profile>
</ShaderAsset>
<ShaderAsset Include="SkyPixel">
<Entry>PSMain</Entry>
<Profile>ps_2_0</Profile>
</ShaderAsset>
</ItemGroup>
<!-- Add Source Assets here -->
<ItemGroup>
<SourceAsset Include="bigfont.png">
<Importer>ThreeDContentPipeline.SpriteFontImporter</Importer>
</SourceAsset>
<SourceAsset Include="XnaLogo.png">
<Importer>ThreeDContentPipeline.Texture2DImporter</Importer>
</SourceAsset>
<SourceAsset Include="Cube.xml">
<Importer>ThreeDContentPipeline.MeshImporter</Importer>
</SourceAsset>
</ItemGroup>
<!-- No need to modify this unless you know what you are doing -->
<Target Name="Build">
<RemoveDir Directories="$(OutputDirectory)"/>
<Exec Command="$(AssetImporter) "@(Assembly)" "$(OutputDirectory)" "%(SourceAsset.Identity)" "%(SourceAsset.Importer)" "%(SourceAsset.Arguments)""/>
<Exec Command="$(ShaderCompiler) /LD /T %(ShaderAsset.Profile) /E %(ShaderAsset.Entry) /Zpr /Fo "$(OutputDirectory)\%(ShaderAsset.Identity).asset" "%(ShaderAsset.Identity).hlsl""/>
<Exec Command="$(ContentBuild) "$(ContentBuildProject)" "$(OutputDirectory)" "$(ContentBuildRoot)""/>
</Target>
</Project>
Sample main page code behind
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using ThreeDWorld;
namespace ThreeDTutorial01
{
public partial class MainPage : UserControl
{
Game1 _Game;
public MainPage()
{
InitializeComponent();
// Need to do this to make the input system work
Input.SetSource(this);
}
private void DrawingSurface_Loaded(object sender, RoutedEventArgs e)
{
_Game = new Game1();
}
private void DrawingSurface_Draw(object sender, DrawEventArgs e)
{
_Game.OnDraw(e);
}
private void DrawingSurface_Unloaded(object sender, RoutedEventArgs e)
{
_Game.Dispose();
}
}
}
Sample Game subclass
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using ThreeDWorld;
namespace ThreeDTutorial01
{
// This is the class that handles all game loading, updating and drawing logic
public class Game1 : Game
{
// The object used to render text
SpriteFont _Font;
// A cube mesh
Mesh _Cube;
// Pixel shader for rendering cube
PixelShader _PixelShader;
// Vertex shader for rendering cube
VertexShader _VertexShader;
// Texture mapped on to cube
Texture2D _Logo;
// used for calculating mouse movement delta
Vector2 _LastMousePosition;
public Game1()
{
// load when created
Load();
}
private void Load()
{
// load the font to display text with
_Font = Content.Load<SpriteFont>("bigfont");
// load the cube mesh
_Cube = Content.Load<Mesh>("Cube");
// load the pixel shader
_PixelShader = Content.Load<PixelShader>("ModelPixel");
// load the vertex shader
_VertexShader = Content.Load<VertexShader>("ModelVertex");
// load the texture to map onto the cube
_Logo = Content.Load<Texture2D>("XnaLogo");
// initialize the last mouse position to the current mouse position
_LastMousePosition = Input.MousePosition;
// initialize the camera
Camera.Position = new Vector3(60, 60, 60);
Camera.Target = Vector3.Zero;
Camera.Up = new Vector3(-1, 1, -1);
Camera.CalcTransform();
}
protected override void Update(float elapsedTime, float totalTime)
{
// compute the mouse movement delta
Vector2 delta = _LastMousePosition - Input.MousePosition;
// if the left mouse button is down then rotate the camera around it's target based on the calculated delta
if (Input.LeftMouseDown)
{
Camera.RotateAroundTarget(delta * 0.01f);
// need to re-calculate the camera transform when ever it changes
Camera.CalcTransform();
}
// set the last mouse position to the current mouse position, for the next time around
_LastMousePosition = Input.MousePosition;
}
protected override void Draw(float elapsedTime, float totalTime)
{
// text to display at top center of screen
string text = "ThreeD Tutorial 01";
// size of the text
Vector2 size = _Font.MeasureText(text);
// holds the light position. the position is aligned with the camera, but about 25 percent closer to the cube then the camera
Vector3 lightPosition = Camera.Position * 0.75f;
// holds ambient and diffuse color of cube
Vector3 ambientColor = new Vector3(0, 0, 0);
Vector3 diffusColor = new Vector3(1, 1, 1);
// the cube asset is a unit cube so scale to a 50 unit cube
Matrix world = Matrix.CreateScale(50, 50, 50);
// the inverse transpose of the world matrix is required for lighting calculations
Matrix worldInverseTranspose = Matrix.Transpose(Matrix.Invert(world));
// set the camera matrices
Matrix view = Camera.View;
Matrix projection = Camera.Projection;
// clear the color and depth buffers
GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1, 0);
// set the current vertex and pixel shaders
GraphicsDevice.SetVertexShader(_VertexShader);
GraphicsDevice.SetPixelShader(_PixelShader);
// set the vertex shader constants. the registers must match up with the register tags in the shader code (see the respective shader code).
GraphicsDevice.SetVertexShaderConstantFloat4<Matrix>(0, ref world);
GraphicsDevice.SetVertexShaderConstantFloat4<Matrix>(4, ref worldInverseTranspose);
GraphicsDevice.SetVertexShaderConstantFloat4<Matrix>(8, ref view);
GraphicsDevice.SetVertexShaderConstantFloat4<Matrix>(12, ref projection);
// set the pixel shader constants. the registers must match up with the register tags in the shader code (see the respective shader code).
GraphicsDevice.SetPixelShaderConstantFloat4<Vector3>(0, ref lightPosition);
GraphicsDevice.SetPixelShaderConstantFloat4<Vector3>(1, ref ambientColor);
GraphicsDevice.SetPixelShaderConstantFloat4<Vector3>(2, ref diffusColor);
// set the texture. the texture index must match the texture register setup in the pixel shader (see the respective shader code).
GraphicsDevice.Textures[0] = _Logo;
// draw the cube
_Cube.Draw();
// draw the info text
SpriteBatch.Begin();
SpriteBatch.DrawText(_Font, text, new Vector2(400, 32) - size * 0.5f, new Vector3(1, 1, 1), 1);
SpriteBatch.End();
}
}
}