-
-
Notifications
You must be signed in to change notification settings - Fork 102
Riemers3DXNA2flightsim10addingtargets
With our scene set up and our xwing flying through it, it is time to add some targets to shoot at. In this example, we will be using simple sphere models, loaded as we have done before with our xwing.
The "target.x" model can be found in the Assets for the tutorial. It is a simple red sphere, of which the size is exactly 1. Add this .x file to the Content project of your solution, as you have done many times before.
Next, as usual, we will define a variable to store the target Model, as well as a variable that will define the maximum number of targets we will have active at any time, so add the following in the Properties section of our code:
private Model _targetModel;
private const int _maxTargets = 50;
private List<BoundingSphere> _targetList = new List<BoundingSphere> ();
We will also use the last variable to track all of our targets, a List is exceptionally useful here as we will need to be able to add and remove the target from the list while our program is running, and for each target, we also need to store 2 things:
- its position and
- its size
Therefore, a BoundingSphere works perfectly to store a target! Even more, later on, we can use the built-in functionality of the BoundingSphere object to test for collisions.
Next, add this line to our LoadContent method, to load the model file into the targetModel variable:
_targetModel = LoadModel("target");
We will also code a new method called AddTargets, which will create our targets, place them in a random position, and add them to our List:
private void AddTargets()
{
int cityWidth = _floorPlan.GetLength(0);
int cityLength = _floorPlan.GetLength(1);
Random random = new Random();
while (_targetList.Count < _maxTargets)
{
int x = random.Next(cityWidth);
int z = -random.Next(cityLength);
float y = (float)random.Next(2000) / 1000f + 1;
float radius = (float)random.Next(1000) / 1000f * 0.2f + 0.01f;
BoundingSphere newTarget = new BoundingSphere(new Vector3(x,y,z), radius);
if (CheckCollision(newTarget) == CollisionType.None)
{
_targetList.Add(newTarget);
}
}
}
This method works as follows:
- It starts by looking up the size of our city and by creating a new randomizer, from which we will draw random numbers to generate random positions and sizes for our targets.
- In each iteration of the while loop, we will create a new target
- If the newly created target does not collide with the buildings of the city or with any existing targets using the CheckCollision method, the target is added to the List.
We then need to call this method from the end of our LoadContent method:
AddTargets();
Running this code should not give you any problems, but you will not notice a difference either as we are not yet drawing the targets, so add this method to the bottom of our code:
private void DrawTargets()
{
for (int i = 0; i < _targetList.Count; i++)
{
Matrix worldMatrix = Matrix.CreateScale(_targetList[i].Radius) * Matrix.CreateTranslation(_targetList[i].Center);
Matrix[] targetTransforms = new Matrix[_targetModel.Bones.Count];
_targetModel.CopyAbsoluteBoneTransformsTo(targetTransforms);
foreach (ModelMesh modelMesh in _targetModel.Meshes)
{
foreach (Effect currentEffect in modelMesh.Effects)
{
currentEffect.CurrentTechnique = currentEffect.Techniques["Colored"];
currentEffect.Parameters["xWorld"].SetValue(targetTransforms[modelMesh.ParentBone.Index] * worldMatrix);
currentEffect.Parameters["xView"].SetValue(_viewMatrix);
currentEffect.Parameters["xProjection"].SetValue(_projectionMatrix);
currentEffect.Parameters["xEnableLighting"].SetValue(true);
currentEffect.Parameters["xLightDirection"].SetValue(_lightDirection);
currentEffect.Parameters["xAmbient"].SetValue(0.5f);
}
modelMesh.Draw();
}
}
}
This method does the same as our previous DrawModel method, except that its code is iterated for each target in our targetList.
The World matrix that is created for each target sets the position and size of the target. Next, the target is then rendered using the Colored technique, as the vertices in this particular .x file contain only Color and Normal information.
To complete this section, make sure you call the DrawTargets method from within the Draw method:
DrawTargets();
Running this code will now render the targets in your 3D city!
All we have to do now is detect when the xwing crashes against a target. Even more, when this happens, the target should be removed from the targetList (as if collected).
So add the following code to the CheckCollision method before the final "return" statement:
for (int i = 0; i < _targetList.Count; i++)
{
if (_targetList[i].Contains(sphere) != ContainmentType.Disjoint)
{
_targetList.RemoveAt(i);
i--;
AddTargets();
return CollisionType.Target;
}
}
For each target in your targetList, you check if it collides with the BoundingSphere passed to the method. If it does, you remove it from the list and call AddTargets to add a new one in a random position.
2 remarks on this approach:
- When you remove an entry from a List, you should decrement the counter, hence the "i--" line. Otherwise, the following object in the list will not be checked!
- This detects when the xwing crashes into a target, but also makes sure 2 targets will never be added to the same positions. This is because we also call this method from the AddTargets method.
That is it! When you run this code, the targets should be drawn in the city. When you crash your xwing against them, your xwing should be reset to its original position.
What good are targets when you can’t shoot at them? Next chapter we’ll add some bullets.
You can try these exercises to practice what you have learned:
- Try slowing down the rate of fire, cannot have our pilot be too trigger happy
- (advanced) Check the documentation for the Keyboard.IsKeyDown and Button.IsButtonDown and see if you can restrict the player from holding the key/button down. So that the player has to release the key/button to fire again (Tip, check KeyUp/ButtonUp)
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace Series3D2
{
public class Game1 : Game
{
public enum CollisionType { None, Building, Boundary, Target }
//Properties
private GraphicsDeviceManager _graphics;
private SpriteBatch _spriteBatch;
private GraphicsDevice _device;
private Effect _effect;
private Matrix _viewMatrix;
private Matrix _projectionMatrix;
private Texture2D _sceneryTexture;
private int[,] _floorPlan;
private VertexBuffer _cityVertexBuffer;
private int[] _buildingHeights = new int[] { 0, 2, 2, 6, 5, 4 };
private Model _xwingModel;
private Vector3 _lightDirection = new Vector3(3, -2, 5);
private Vector3 _xwingPosition = new Vector3(8, 1, -3);
private Quaternion _xwingRotation = Quaternion.Identity;
private float _gameSpeed = 1.0f;
private BoundingBox[] _buildingBoundingBoxes;
private BoundingBox _completeCityBox;
private Model _targetModel;
private const int _maxTargets = 50;
private List<BoundingSphere> _targetList = new List<BoundingSphere>();
public Game1()
{
_graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
IsMouseVisible = true;
}
protected override void Initialize()
{
// TODO: Add your initialization logic here
_graphics.PreferredBackBufferWidth = 500;
_graphics.PreferredBackBufferHeight = 500;
_graphics.IsFullScreen = false;
_graphics.ApplyChanges();
Window.Title = "Riemer's MonoGame Tutorials -- 3D Series 2";
LoadFloorPlan();
_lightDirection.Normalize();
base.Initialize();
}
private void SetUpCamera()
{
_viewMatrix = Matrix.CreateLookAt(new Vector3(20, 13, -5), new Vector3(8, 0, -7), new Vector3(0, 1, 0));
_projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, _device.Viewport.AspectRatio, 0.2f, 500.0f);
}
private void SetUpVertices()
{
int differentBuildings = _buildingHeights.Length - 1;
float imagesInTexture = 1 + differentBuildings * 2;
int cityWidth = _floorPlan.GetLength(0);
int cityLength = _floorPlan.GetLength(1);
List<VertexPositionNormalTexture> verticesList = new List<VertexPositionNormalTexture>();
for (int x = 0; x < cityWidth; x++)
{
for (int z = 0; z < cityLength; z++)
{
int currentBuilding = _floorPlan[x, z];
//floor or ceiling
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x, _buildingHeights[currentBuilding], -z), new Vector3(0, 1, 0), new Vector2(currentBuilding * 2 / imagesInTexture, 1)));
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x, _buildingHeights[currentBuilding], -z - 1), new Vector3(0, 1, 0), new Vector2((currentBuilding * 2) / imagesInTexture, 0)));
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x + 1, _buildingHeights[currentBuilding], -z), new Vector3(0, 1, 0), new Vector2((currentBuilding * 2 + 1) / imagesInTexture, 1)));
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x, _buildingHeights[currentBuilding], -z - 1), new Vector3(0, 1, 0), new Vector2((currentBuilding * 2) / imagesInTexture, 0)));
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x + 1, _buildingHeights[currentBuilding], -z - 1), new Vector3(0, 1, 0), new Vector2((currentBuilding * 2 + 1) / imagesInTexture, 0)));
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x + 1, _buildingHeights[currentBuilding], -z), new Vector3(0, 1, 0), new Vector2((currentBuilding * 2 + 1) / imagesInTexture, 1)));
if (currentBuilding != 0)
{
//front wall
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x + 1, 0, -z - 1), new Vector3(0, 0, -1), new Vector2((currentBuilding * 2) / imagesInTexture, 1)));
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x, _buildingHeights[currentBuilding], -z - 1), new Vector3(0, 0, -1), new Vector2((currentBuilding * 2 - 1) / imagesInTexture, 0)));
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x, 0, -z - 1), new Vector3(0, 0, -1), new Vector2((currentBuilding * 2 - 1) / imagesInTexture, 1)));
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x, _buildingHeights[currentBuilding], -z - 1), new Vector3(0, 0, -1), new Vector2((currentBuilding * 2 - 1) / imagesInTexture, 0)));
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x + 1, 0, -z - 1), new Vector3(0, 0, -1), new Vector2((currentBuilding * 2) / imagesInTexture, 1)));
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x + 1, _buildingHeights[currentBuilding], -z - 1), new Vector3(0, 0, -1), new Vector2((currentBuilding * 2) / imagesInTexture, 0)));
//back wall
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x + 1, 0, -z), new Vector3(0, 0, 1), new Vector2((currentBuilding * 2) / imagesInTexture, 1)));
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x, 0, -z), new Vector3(0, 0, 1), new Vector2((currentBuilding * 2 - 1) / imagesInTexture, 1)));
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x, _buildingHeights[currentBuilding], -z), new Vector3(0, 0, 1), new Vector2((currentBuilding * 2 - 1) / imagesInTexture, 0)));
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x, _buildingHeights[currentBuilding], -z), new Vector3(0, 0, 1), new Vector2((currentBuilding * 2 - 1) / imagesInTexture, 0)));
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x + 1, _buildingHeights[currentBuilding], -z), new Vector3(0, 0, 1), new Vector2((currentBuilding * 2) / imagesInTexture, 0)));
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x + 1, 0, -z), new Vector3(0, 0, 1), new Vector2((currentBuilding * 2) / imagesInTexture, 1)));
//left wall
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x, 0, -z), new Vector3(-1, 0, 0), new Vector2((currentBuilding * 2) / imagesInTexture, 1)));
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x, 0, -z - 1), new Vector3(-1, 0, 0), new Vector2((currentBuilding * 2 - 1) / imagesInTexture, 1)));
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x, _buildingHeights[currentBuilding], -z - 1), new Vector3(-1, 0, 0), new Vector2((currentBuilding * 2 - 1) / imagesInTexture, 0)));
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x, _buildingHeights[currentBuilding], -z - 1), new Vector3(-1, 0, 0), new Vector2((currentBuilding * 2 - 1) / imagesInTexture, 0)));
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x, _buildingHeights[currentBuilding], -z), new Vector3(-1, 0, 0), new Vector2((currentBuilding * 2) / imagesInTexture, 0)));
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x, 0, -z), new Vector3(-1, 0, 0), new Vector2((currentBuilding * 2) / imagesInTexture, 1)));
//right wall
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x + 1, 0, -z), new Vector3(1, 0, 0), new Vector2((currentBuilding * 2) / imagesInTexture, 1)));
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x + 1, _buildingHeights[currentBuilding], -z - 1), new Vector3(1, 0, 0), new Vector2((currentBuilding * 2 - 1) / imagesInTexture, 0)));
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x + 1, 0, -z - 1), new Vector3(1, 0, 0), new Vector2((currentBuilding * 2 - 1) / imagesInTexture, 1)));
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x + 1, _buildingHeights[currentBuilding], -z - 1), new Vector3(1, 0, 0), new Vector2((currentBuilding * 2 - 1) / imagesInTexture, 0)));
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x + 1, 0, -z), new Vector3(1, 0, 0), new Vector2((currentBuilding * 2) / imagesInTexture, 1)));
verticesList.Add(new VertexPositionNormalTexture(new Vector3(x + 1, _buildingHeights[currentBuilding], -z), new Vector3(1, 0, 0), new Vector2((currentBuilding * 2) / imagesInTexture, 0)));
}
}
}
_cityVertexBuffer = new VertexBuffer(_device, VertexPositionNormalTexture.VertexDeclaration, verticesList.Count, BufferUsage.WriteOnly);
_cityVertexBuffer.SetData<VertexPositionNormalTexture>(verticesList.ToArray());
}
private void LoadFloorPlan()
{
_floorPlan = new int[,]
{
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,1,1,0,0,0,1,1,0,0,1,0,1},
{1,0,0,1,1,0,0,0,1,0,0,0,1,0,1},
{1,0,0,0,1,1,0,1,1,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,1,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,1,1,0,0,0,1,0,0,0,0,0,0,1},
{1,0,1,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,1,0,0,0,1,0,0,0,0,1},
{1,0,1,0,0,0,0,0,0,1,0,0,0,0,1},
{1,0,1,1,0,0,0,0,1,1,0,0,0,1,1},
{1,0,0,0,0,0,0,0,1,1,0,0,0,1,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
};
Random random = new Random();
int differentBuildings = _buildingHeights.Length - 1;
for (int x = 0; x < _floorPlan.GetLength(0); x++)
{
for (int y = 0; y < _floorPlan.GetLength(1); y++)
{
if (_floorPlan[x, y] == 1)
{
_floorPlan[x, y] = random.Next(differentBuildings) + 1;
}
}
}
}
private Model LoadModel(string assetName)
{
Model newModel = Content.Load<Model>(assetName);
foreach (ModelMesh mesh in newModel.Meshes)
{
foreach (ModelMeshPart meshPart in mesh.MeshParts)
{
meshPart.Effect = _effect.Clone();
}
}
return newModel;
}
private void SetUpBoundingBoxes()
{
int cityWidth = _floorPlan.GetLength(0);
int cityLength = _floorPlan.GetLength(1);
List<BoundingBox> bbList = new List<BoundingBox>();
for (int x = 0; x < cityWidth; x++)
{
for (int z = 0; z < cityLength; z++)
{
int buildingType = _floorPlan[x, z];
if (buildingType != 0)
{
int buildingHeight = _buildingHeights[buildingType];
Vector3[] buildingPoints = new Vector3[2];
buildingPoints[0] = new Vector3(x, 0, -z);
buildingPoints[1] = new Vector3(x + 1, buildingHeight, -z - 1);
BoundingBox buildingBox = BoundingBox.CreateFromPoints(buildingPoints);
bbList.Add(buildingBox);
}
}
}
_buildingBoundingBoxes = bbList.ToArray();
Vector3[] boundaryPoints = new Vector3[2];
boundaryPoints[0] = new Vector3(0, 0, 0);
boundaryPoints[1] = new Vector3(cityWidth, 20, -cityLength);
_completeCityBox = BoundingBox.CreateFromPoints(boundaryPoints);
}
private void AddTargets()
{
int cityWidth = _floorPlan.GetLength(0);
int cityLength = _floorPlan.GetLength(1);
Random random = new Random();
while (_targetList.Count < _maxTargets)
{
int x = random.Next(cityWidth);
int z = -random.Next(cityLength);
float y = (float)random.Next(2000) / 1000f + 1;
float radius = (float)random.Next(1000) / 1000f * 0.2f + 0.01f;
BoundingSphere newTarget = new BoundingSphere(new Vector3(x, y, z), radius);
if (CheckCollision(newTarget) == CollisionType.None)
{
_targetList.Add(newTarget);
}
}
}
protected override void LoadContent()
{
_spriteBatch = new SpriteBatch(GraphicsDevice);
// TODO: use this.Content to load your game content here
_device = _graphics.GraphicsDevice;
_effect = Content.Load<Effect>("effects");
_sceneryTexture = Content.Load<Texture2D>("texturemap");
_xwingModel = LoadModel("xwing");
_targetModel = LoadModel("target");
SetUpCamera();
SetUpVertices();
SetUpBoundingBoxes();
AddTargets();
}
private void UpdateCamera()
{
Vector3 cameraPosition = new Vector3(0, 0.1f, 0.6f);
cameraPosition = Vector3.Transform(cameraPosition, Matrix.CreateFromQuaternion(_xwingRotation));
cameraPosition += _xwingPosition;
Vector3 cameraUpDirection = new Vector3(0, 1, 0);
cameraUpDirection = Vector3.Transform(cameraUpDirection, Matrix.CreateFromQuaternion(_xwingRotation));
_viewMatrix = Matrix.CreateLookAt(cameraPosition, _xwingPosition, cameraUpDirection);
_projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, _device.Viewport.AspectRatio, 0.2f, 500.0f);
}
private void ProcessKeyboard(GameTime gameTime)
{
float leftRightRotation = 0;
float upDownRotation = 0;
float turningSpeed = (float)gameTime.ElapsedGameTime.TotalMilliseconds / 1000.0f;
turningSpeed *= 1.6f * _gameSpeed;
KeyboardState keys = Keyboard.GetState();
if (keys.IsKeyDown(Keys.Right))
{
leftRightRotation += turningSpeed;
}
if (keys.IsKeyDown(Keys.Left))
{
leftRightRotation -= turningSpeed;
}
if (keys.IsKeyDown(Keys.Down))
{
upDownRotation += turningSpeed;
}
if (keys.IsKeyDown(Keys.Up))
{
upDownRotation -= turningSpeed;
}
Quaternion additionalRotation = Quaternion.CreateFromAxisAngle(new Vector3(0, 0, -1), leftRightRotation) * Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), upDownRotation);
_xwingRotation *= additionalRotation;
}
private void MoveForward(ref Vector3 position, Quaternion rotationQuat, float speed)
{
Vector3 addVector = Vector3.Transform(new Vector3(0, 0, -1), rotationQuat);
position += addVector * speed;
}
private CollisionType CheckCollision(BoundingSphere sphere)
{
for (int i = 0; i < _buildingBoundingBoxes.Length; i++)
{
if (_buildingBoundingBoxes[i].Contains(sphere) != ContainmentType.Disjoint)
{
return CollisionType.Building;
}
}
if (_completeCityBox.Contains(sphere) != ContainmentType.Contains)
{
return CollisionType.Boundary;
}
for (int i = 0; i < _targetList.Count; i++)
{
if (_targetList[i].Contains(sphere) != ContainmentType.Disjoint)
{
_targetList.RemoveAt(i);
i--;
AddTargets();
return CollisionType.Target;
}
}
return CollisionType.None;
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed ||
Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
// TODO: Add your update logic here
UpdateCamera();
ProcessKeyboard(gameTime);
float moveSpeed = gameTime.ElapsedGameTime.Milliseconds / 500.0f * _gameSpeed;
MoveForward(ref _xwingPosition, _xwingRotation, moveSpeed);
BoundingSphere xwingSpere = new BoundingSphere(_xwingPosition, 0.04f);
if (CheckCollision(xwingSpere) != CollisionType.None)
{
_xwingPosition = new Vector3(8, 1, -3);
_xwingRotation = Quaternion.Identity;
_gameSpeed /= 1.1f;
}
base.Update(gameTime);
}
private void DrawCity()
{
_effect.CurrentTechnique = _effect.Techniques["Textured"];
_effect.Parameters["xWorld"].SetValue(Matrix.Identity);
_effect.Parameters["xView"].SetValue(_viewMatrix);
_effect.Parameters["xProjection"].SetValue(_projectionMatrix);
_effect.Parameters["xTexture"].SetValue(_sceneryTexture);
_effect.Parameters["xEnableLighting"].SetValue(true);
_effect.Parameters["xLightDirection"].SetValue(_lightDirection);
_effect.Parameters["xAmbient"].SetValue(0.5f);
foreach (EffectPass pass in _effect.CurrentTechnique.Passes)
{
pass.Apply();
_device.SetVertexBuffer(_cityVertexBuffer);
_device.DrawPrimitives(PrimitiveType.TriangleList, 0, _cityVertexBuffer.VertexCount / 3);
}
}
private void DrawModel()
{
Matrix worldMatrix = Matrix.CreateScale(0.0005f, 0.0005f, 0.0005f) *
Matrix.CreateRotationY(MathHelper.Pi) *
Matrix.CreateFromQuaternion(_xwingRotation) *
Matrix.CreateTranslation(_xwingPosition);
Matrix[] xwingTransforms = new Matrix[_xwingModel.Bones.Count];
_xwingModel.CopyAbsoluteBoneTransformsTo(xwingTransforms);
foreach (ModelMesh mesh in _xwingModel.Meshes)
{
foreach (Effect currentEffect in mesh.Effects)
{
currentEffect.CurrentTechnique = currentEffect.Techniques["Colored"];
currentEffect.Parameters["xWorld"].SetValue(xwingTransforms[mesh.ParentBone.Index] * worldMatrix);
currentEffect.Parameters["xView"].SetValue(_viewMatrix);
currentEffect.Parameters["xProjection"].SetValue(_projectionMatrix);
currentEffect.Parameters["xEnableLighting"].SetValue(true);
currentEffect.Parameters["xLightDirection"].SetValue(_lightDirection);
currentEffect.Parameters["xAmbient"].SetValue(0.5f);
}
mesh.Draw();
}
}
private void DrawTargets()
{
for (int i = 0; i < _targetList.Count; i++)
{
Matrix worldMatrix = Matrix.CreateScale(_targetList[i].Radius) * Matrix.CreateTranslation(_targetList[i].Center);
Matrix[] targetTransforms = new Matrix[_targetModel.Bones.Count];
_targetModel.CopyAbsoluteBoneTransformsTo(targetTransforms);
foreach (ModelMesh modelMesh in _targetModel.Meshes)
{
foreach (Effect currentEffect in modelMesh.Effects)
{
currentEffect.CurrentTechnique = currentEffect.Techniques["Colored"];
currentEffect.Parameters["xWorld"].SetValue(targetTransforms[modelMesh.ParentBone.Index] * worldMatrix);
currentEffect.Parameters["xView"].SetValue(_viewMatrix);
currentEffect.Parameters["xProjection"].SetValue(_projectionMatrix);
currentEffect.Parameters["xEnableLighting"].SetValue(true);
currentEffect.Parameters["xLightDirection"].SetValue(_lightDirection);
currentEffect.Parameters["xAmbient"].SetValue(0.5f);
}
modelMesh.Draw();
}
}
}
protected override void Draw(GameTime gameTime)
{
_device.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.DarkSlateBlue, 1.0f, 0);
DrawCity();
DrawModel();
DrawTargets();
base.Draw(gameTime);
}
}
}