📄 gameengine.cs
字号:
using System;
using System.Configuration;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.Samples.DirectX.UtilityToolkit;
namespace Blockers
{
/// <summary>Main game engine for Blockers game</summary>
public class GameEngine : IFrameworkCallback, IDeviceCreation
{
#region Creation
private Framework sampleFramework = null; // Framework for samples
/// <summary>Create a new instance of the class</summary>
public GameEngine(Framework f)
{
// Store framework
sampleFramework = f;
}
#endregion
#region Constants
public const string GameName = "Blockers";
public static readonly string MediaPath = ConfigurationSettings.AppSettings.Get("MediaPath");
private const float ShowWinningTime = 2.5f;
// Camera constants
private const float MaximumSpeed = 30.0f;
private static readonly Vector3 CameraDefaultLocation = new Vector3(
-2.5f, 25.0f, -55.0f);
private static readonly Vector3 CameraDefaultLookAtLocation = new Vector3(
-2.5f, 0.0f, 0.0f);
private static readonly Vector3 CameraUp = new Vector3(0,1,0);
// Light constants
private static readonly Vector3 SelectLoopyLight = new Vector3(0, 0.0f, 1.0f);
private static readonly Vector3 LevelLight = new Vector3(0, -0.6f, 0.4f);
#endregion
#region Instance Data
// Only allow the close to happen when you want it to
private bool canClose = false;
// Is the level currently being loaded
private bool isLoadingLevel = false;
// The amount of time the 'winning' screen is displayed
private float winningLevelTime = 0.0f;
// What level are we currently playing
private int levelNumber = 1;
// Is the quit menu showing?
private bool isQuitMenuShowing = false;
// The information for the mesh that will display the level
private Mesh levelMesh = null;
private Texture[] levelTextures = null;
// The player's object
private Player player = null;
// The current level
private Level currentLevel = null;
// The main game font
private Font gameFont = null;
// Current camera position
private Vector3 currentCameraPosition;
// Is the main menu currently being shown
private bool isMainMenuShowing = true;
// The main UI screen
private MainUiScreen mainScreen = null;
// The UI Screen for quitting
private QuitScreen quitScreen = null;
// The Selection screen for choosing loopy
private SelectLoopyScreen selectScreen = null;
// Is the selection screen currently being shown
private bool isSelectScreenShowing = false;
// Textures that will be shared throughout UI screens
private Texture buttonTexture = null;
#endregion
#region Debug Information
#if (DEBUG)
private Font debugFont = null;
#endif
#endregion
/// <summary>
/// Called during device initialization, this code checks the device for some
/// minimum set of capabilities, and rejects those that don't pass by returning false.
/// </summary>
public bool IsDeviceAcceptable(Caps caps, Format adapterFormat, Format backBufferFormat, bool windowed)
{
// Skip back buffer formats that don't support alpha blending
if (!Manager.CheckDeviceFormat(caps.AdapterOrdinal, caps.DeviceType, adapterFormat,
Usage.QueryPostPixelShaderBlending, ResourceType.Textures, backBufferFormat))
return false;
// Skip any device that doesn't support at least a single light
if (caps.MaxActiveLights == 0)
return false;
return true;
}
/// <summary>
/// This callback function is called immediately before a device is created to allow the
/// application to modify the device settings. The supplied settings parameter
/// contains the settings that the framework has selected for the new device, and the
/// application can make any desired changes directly to this structure. Note however that
/// the sample framework will not correct invalid device settings so care must be taken
/// to return valid device settings, otherwise creating the Device will fail.
/// </summary>
public void ModifyDeviceSettings(DeviceSettings settings, Caps caps)
{
// This application is designed to work on a pure device by not using
// any get methods, so create a pure device if supported and using HWVP.
if ( (caps.DeviceCaps.SupportsPureDevice) &&
((settings.BehaviorFlags & CreateFlags.HardwareVertexProcessing) != 0 ) )
settings.BehaviorFlags |= CreateFlags.PureDevice;
}
/// <summary>
/// This event will be fired immediately after the Direct3D device has been
/// created, which will happen during application initialization and windowed/full screen
/// toggles. This is the best location to create Pool.Managed resources since these
/// resources need to be reloaded whenever the device is destroyed. Resources created
/// here should be released in the Disposing event.
/// </summary>
private void OnCreateDevice(object sender, DeviceEventArgs e)
{
SurfaceDescription desc = e.BackBufferDescription;
#if (DEBUG)
// In debug mode, use this font to render stats
debugFont = new Font(e.Device, new System.Drawing.Font("Arial", 12));
#endif
// Create the game font
gameFont = new Font(e.Device, new System.Drawing.Font("Arial", 28.0f));
// Create the textures for the UI screens
buttonTexture = TextureLoader.FromFile(e.Device, GameEngine.MediaPath
+ "buttons.png");
// Create the screen for selecting loopy
selectScreen = new SelectLoopyScreen(e.Device, buttonTexture, desc.Width, desc.Height);
selectScreen.Selected += new EventHandler(OnLoopySelected);
// Create the main UI Screen
mainScreen = new MainUiScreen(e.Device, desc.Width, desc.Height);
mainScreen.NewGame += new EventHandler(OnNewGame);
mainScreen.Quit += new EventHandler(OnMainQuit);
// Create the screen for the UI Screen
quitScreen = new QuitScreen(e.Device, buttonTexture, desc.Width, desc.Height);
quitScreen.Cancel += new EventHandler(OnQuitScreenCancel);
quitScreen.QuitGame += new EventHandler(OnQuitScreenQuit);
}
/// <summary>
/// This event will be fired immediately after the Direct3D device has been
/// reset, which will happen after a lost device scenario. This is the best location to
/// create Pool.Default resources since these resources need to be reloaded whenever
/// the device is lost. Resources created here should be released in the OnLostDevice
/// event.
/// </summary>
private void OnResetDevice(object sender, DeviceEventArgs e)
{
SurfaceDescription desc = e.BackBufferDescription;
// Set the transformation matrices
e.Device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4,
(float)desc.Width / (float)desc.Height, 0.1f, 1000000.0f);
e.Device.Transform.View = Matrix.LookAtLH(currentCameraPosition,
CameraDefaultLookAtLocation, CameraUp);
// Set up the lights
// Light 0 will be the level light
e.Device.Lights[0].DiffuseColor = new ColorValue(1.0f, 1.0f, 1.0f, 1.0f);
e.Device.Lights[0].Direction = LevelLight;
e.Device.Lights[0].Type = LightType.Directional;
// Light 1 will be the select loopy light
e.Device.Lights[1].DiffuseColor = new ColorValue(1.0f, 1.0f, 1.0f, 1.0f);
e.Device.Lights[1].Direction = SelectLoopyLight;
e.Device.Lights[1].Type = LightType.Directional;
EnableLights();
// Store the caps to check for texture filtering
Caps caps = sampleFramework.DeviceCaps;
// Set up the filtering mode for the texture
if (caps.TextureFilterCaps.SupportsMinifyAnisotropic)
{
e.Device.SamplerState[0].MinFilter = TextureFilter.Anisotropic;
}
else if (caps.TextureFilterCaps.SupportsMinifyLinear)
{
e.Device.SamplerState[0].MinFilter = TextureFilter.Linear;
}
if (caps.TextureFilterCaps.SupportsMagnifyAnisotropic)
{
e.Device.SamplerState[0].MagFilter = TextureFilter.Anisotropic;
}
else if (caps.TextureFilterCaps.SupportsMagnifyLinear)
{
e.Device.SamplerState[0].MagFilter = TextureFilter.Linear;
}
if (caps.TextureFilterCaps.SupportsMipMapLinear)
{
e.Device.SamplerState[0].MipFilter = TextureFilter.Linear;
}
#if (DEBUG)
// Make sure the debug font resets correctly
debugFont.OnResetDevice();
#endif
// Reset the game font
gameFont.OnResetDevice();
}
/// <summary>
/// This event function will be called fired after the Direct3D device has
/// entered a lost state and before Device.Reset() is called. Resources created
/// in the OnResetDevice callback should be released here, which generally includes all
/// Pool.Default resources. See the "Lost Devices" section of the documentation for
/// information about lost devices.
/// </summary>
private void OnLostDevice(object sender, EventArgs e)
{
#if (DEBUG)
if (debugFont != null)
{
// Make sure the debug font gets rid of any resources
debugFont.OnLostDevice();
}
#endif
if (gameFont != null)
{
// Make sure the game font cleans up resources
gameFont.OnLostDevice();
}
}
/// <summary>
/// This callback function will be called immediately after the Direct3D device has
/// been destroyed, which generally happens as a result of application termination or
/// windowed/full screen toggles. Resources created in the OnCreateDevice callback
/// should be released here, which generally includes all Pool.Managed resources.
/// </summary>
private void OnDestroyDevice(object sender, EventArgs e)
{
#if (DEBUG)
if (debugFont != null)
{
// Cleanup the font
debugFont.Dispose();
debugFont = null;
}
#endif
// Clean up any ui screens
if (quitScreen != null)
{
quitScreen.Dispose();
}
if (selectScreen != null)
{
selectScreen.Dispose();
}
if (mainScreen != null)
{
mainScreen.Dispose();
}
// If the player is null, and you are on the select screen, clean up
// those meshes as well
if ((player == null) && (selectScreen != null))
{
selectScreen.CleanupLoopyMesh();
}
// Clean up the player
if (player != null)
{
player.Dispose();
}
// Clean up the textures used for the UI Screens
if (buttonTexture != null)
{
buttonTexture.Dispose();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -