📄 dodger.cs
字号:
using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Direct3D = Microsoft.DirectX.Direct3D;
namespace Dodger
{
/// <summary>
/// Structure used to maintain high scores
/// </summary>
public struct HighScore
{
private int realScore;
private string playerName;
public int Score { get { return realScore; } set { realScore = value; } }
public string Name { get { return playerName; } set { playerName = value; } }
}
/// <summary>
/// Summary description for DodgerGame.
/// </summary>
public class DodgerGame : System.Windows.Forms.Form
{
// Constant values for the locations
public const float RoadLocationLeft = 2.5f;
public const float RoadLocationRight = -2.5f;
private const float RoadSize = 100.0f;
private const float MaximumRoadSpeed = 250.0f;
private const float RoadSpeedIncrement = 0.5f;
// Depth locations of the two 'road' meshes we will draw
private float RoadDepth0 = 0.0f;
private float RoadDepth1 = -100.0f;
private float RoadSpeed = 30.0f;
private float elapsedTime = 0.0f;
// Rendering device
private Device device = null;
// Game board mesh information
private Mesh roadMesh = null;
private Material[] roadMaterials = null;
private Texture[] roadTextures = null;
// Game information
private bool isGameOver = true;
private int gameOverTick = 0;
private bool hasGameStarted = false;
private int score = 0;
// Obstacle information
private Obstacles obstacles;
// Car
private Car car = null;
// Fonts
private Direct3D.Font scoreFont = null;
private Direct3D.Font gameFont = null;
// High score information
private HighScore[] highScores = new HighScore[3];
private string defaultHighScoreName = string.Empty;
// Obstacle height constant
private const float ObstacleHeight = Car.Height * 0.85f;
public DodgerGame()
{
this.Size = new Size(800,600);
this.Text = "Dodger Game";
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
LoadHighScores();
}
/// <summary>
/// Here we will load all the default game options
/// </summary>
private void LoadDefaultGameOptions()
{
// Road information
RoadDepth0 = 0.0f;
RoadDepth1 = -100.0f;
RoadSpeed = 30.0f;
// Car data information
car.Location = RoadLocationLeft;
car.Speed = 10.0f;
car.IsMovingLeft = false;
car.IsMovingRight = false;
score = 0;
// Remove any obstacles currently in the game
foreach(Obstacle o in obstacles)
{
// Dispose it first
o.Dispose();
}
obstacles.Clear();
// Add some obstacles
AddObstacles(RoadDepth1);
// Start our timer
Utility.Timer(DirectXTimer.Start);
}
/// <summary>
/// We will initialize our graphics device here
/// </summary>
public void InitializeGraphics()
{
// Set our presentation parameters
PresentParameters presentParams = new PresentParameters();
presentParams.Windowed = true;
presentParams.SwapEffect = SwapEffect.Discard;
presentParams.AutoDepthStencilFormat = DepthFormat.D16;
presentParams.EnableAutoDepthStencil = true;
// Store the default adapter
int adapterOrdinal = Manager.Adapters.Default.Adapter;
CreateFlags flags = CreateFlags.SoftwareVertexProcessing;
// Check to see if we can use a pure hardware device
Caps caps = Manager.GetDeviceCaps(adapterOrdinal, DeviceType.Hardware);
// Do we support hardware vertex processing?
if (caps.DeviceCaps.SupportsHardwareTransformAndLight)
// Replace the software vertex processing
flags = CreateFlags.HardwareVertexProcessing;
// Do we support a pure device?
if (caps.DeviceCaps.SupportsPureDevice)
flags |= CreateFlags.PureDevice;
// Create our device
device = new Device(adapterOrdinal, DeviceType.Hardware, this, flags, presentParams);
// Hook the device reset event
device.DeviceReset += new EventHandler(this.OnDeviceReset);
this.OnDeviceReset(device, null);
// Create our fonts
scoreFont = new Direct3D.Font(device, new System.Drawing.Font("Arial", 12.0f, FontStyle.Bold));
gameFont = new Direct3D.Font(device, new System.Drawing.Font("Arial", 36.0f, FontStyle.Bold | FontStyle.Italic));
}
private void OnDeviceReset(object sender, EventArgs e)
{
device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, this.Width / this.Height, 1.0f, 1000.0f);
device.Transform.View = Matrix.LookAtLH(new Vector3(0.0f, 9.5f, 17.0f), new Vector3(), new Vector3(0,1,0));
// Try to set up a texture minify filter, pick anisotropic first
if (device.DeviceCaps.TextureFilterCaps.SupportsMinifyAnisotropic)
{
device.SamplerState[0].MinFilter = TextureFilter.Anisotropic;
}
else if (device.DeviceCaps.TextureFilterCaps.SupportsMinifyLinear)
{
device.SamplerState[0].MinFilter = TextureFilter.Linear;
}
// Do the same thing for magnify filter
if (device.DeviceCaps.TextureFilterCaps.SupportsMagnifyAnisotropic)
{
device.SamplerState[0].MagFilter = TextureFilter.Anisotropic;
}
else if (device.DeviceCaps.TextureFilterCaps.SupportsMagnifyLinear)
{
device.SamplerState[0].MagFilter = TextureFilter.Linear;
}
// Do we have enough support for lights?
if ((device.DeviceCaps.VertexProcessingCaps.SupportsDirectionalLights) &&
(device.DeviceCaps.MaxActiveLights > 1))
{
// First light
device.Lights[0].Type = LightType.Directional;
device.Lights[0].Diffuse = Color.White;
device.Lights[0].Direction = new Vector3(1, -1, -1);
device.Lights[0].Update();
device.Lights[0].Enabled = true;
// Second light
device.Lights[1].Type = LightType.Directional;
device.Lights[1].Diffuse = Color.White;
device.Lights[1].Direction = new Vector3(-1, 1, -1);
device.Lights[1].Update();
device.Lights[1].Enabled = true;
}
else
{
// Hmm.. no light support, let's just use
// ambient light
device.RenderState.Ambient = Color.White;
}
// Create our road mesh
roadMesh = LoadMesh(device, @"..\..\road.x", ref roadMaterials, ref roadTextures);
// Create our car
car = new Car(device);
// Create our obstacles class
obstacles = new Obstacles();
}
/// <summary>
/// Add a series of obstacles onto a road section
/// </summary>
/// <param name="minDepth">Minimum depth of the obstacles</param>
private void AddObstacles(float minDepth)
{
// Add the right number of obstacles
int numberToAdd = (int)((RoadSize / car.Diameter - 1) / 2.0f);
// Get the minimum space between obstacles in this section
float minSize = ((RoadSize / numberToAdd) - car.Diameter) / 2.0f;
for (int i = 0; i < numberToAdd; i++)
{
// Get a random # in the min size range
float depth = minDepth - ((float)Utility.Rnd.NextDouble() * minSize);
// Make sure it's in the right range
depth -= (i * (car.Diameter * 2));
// Pick the left or right side of the road
float location = (Utility.Rnd.Next(50) > 25) ? RoadLocationLeft : RoadLocationRight;
// Add this obstacle
obstacles.Add(new Obstacle(device, location, ObstacleHeight, depth));
}
}
public static Mesh LoadMesh(Device device, string file, ref Material[] meshMaterials, ref Texture[] meshTextures)
{
ExtendedMaterial[] mtrl;
// Load our mesh
Mesh tempMesh = Mesh.FromFile(file, MeshFlags.Managed, device, out mtrl);
// If we have any materials, store them
if ((mtrl != null) && (mtrl.Length > 0))
{
meshMaterials = new Material[mtrl.Length];
meshTextures = new Texture[mtrl.Length];
// Store each material and texture
for (int i = 0; i < mtrl.Length; i++)
{
meshMaterials[i] = mtrl[i].Material3D;
if ((mtrl[i].TextureFilename != null) && (mtrl[i].TextureFilename != string.Empty))
{
// We have a texture, try to load it
meshTextures[i] = TextureLoader.FromFile(device, @"..\..\" + mtrl[i].TextureFilename);
}
}
}
return tempMesh;
}
private void OnFrameUpdate()
{
// Nothing to update if the game is over
if ((isGameOver) || (!hasGameStarted))
return;
// First, get the elapsed time
elapsedTime = Utility.Timer(DirectXTimer.GetElapsedTime);
RoadDepth0 += (RoadSpeed * elapsedTime);
RoadDepth1 += (RoadSpeed * elapsedTime);
// Check to see if we need to cycle the road
if (RoadDepth0 > 75.0f)
{
RoadDepth0 = RoadDepth1 - 100.0f;
AddObstacles(RoadDepth0);
}
if (RoadDepth1 > 75.0f)
{
RoadDepth1 = RoadDepth0 - 100.0f;
AddObstacles(RoadDepth1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -