#region File Description
//-----------------------------------------------------------------------------
// Tank.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion
#region Using Statements
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
#endregion
namespace PeerToPeer
{
///
/// Each player controls a tank, which they can drive around the screen.
/// This class implements the logic for moving and drawing the tank, and
/// responds to input that is passed in from outside. The Tank class does
/// not implement any networking functionality, however: that is all
/// handled by the main game class.
///
class Tank
{
#region Constants
// Constants control how fast the tank moves and turns.
const float TankTurnRate = 0.01f;
const float TurretTurnRate = 0.03f;
const float TankSpeed = 0.3f;
const float TankFriction = 0.9f;
#endregion
#region Fields
// The current position and rotation of the tank.
public Vector2 Position;
public Vector2 Velocity;
public float TankRotation;
public float TurretRotation;
// Input controls can be read from keyboard, gamepad, or the network.
public Vector2 TankInput;
public Vector2 TurretInput;
// Textures used to draw the tank.
Texture2D tankTexture;
Texture2D turretTexture;
Vector2 screenSize;
#endregion
///
/// Constructs a new Tank instance.
///
public Tank (int gamerIndex,ContentManager content,
int screenWidth,int screenHeight)
{
// Use the gamer index to compute a starting position, so each player
// starts in a different place as opposed to all on top of each other.
Position.X = screenWidth / 4 + (gamerIndex % 5) * screenWidth / 8;
Position.Y = screenHeight / 4 + (gamerIndex / 5) * screenHeight / 5;
TankRotation = -MathHelper.PiOver2;
TurretRotation = -MathHelper.PiOver2;
tankTexture = content.Load ("Tank");
turretTexture = content.Load ("Turret");
screenSize = new Vector2 (screenWidth, screenHeight);
}
///
/// Moves the tank in response to the current input settings.
///
public void Update ()
{
// Gradually turn the tank and turret to face the requested direction.
TankRotation = TurnToFace (TankRotation, TankInput, TankTurnRate);
TurretRotation = TurnToFace (TurretRotation, TurretInput, TurretTurnRate);
// How close the desired direction is the tank facing?
Vector2 tankForward = new Vector2 ((float)Math.Cos (TankRotation),
(float)Math.Sin (TankRotation));
Vector2 targetForward = new Vector2 (TankInput.X, -TankInput.Y);
float facingForward = Vector2.Dot (tankForward, targetForward);
// If we have finished turning, also start moving forward.
if (facingForward > 0)
Velocity += tankForward * facingForward * facingForward * TankSpeed;
// Update the position and velocity.
Position += Velocity;
Velocity *= TankFriction;
// Clamp so the tank cannot drive off the edge of the screen.
Position = Vector2.Clamp (Position, Vector2.Zero, screenSize);
}
///
/// Gradually rotates the tank to face the specified direction.
///
static float TurnToFace (float rotation, Vector2 target, float turnRate)
{
if (target == Vector2.Zero)
return rotation;
float angle = (float)Math.Atan2 (-target.Y, target.X);
float difference = rotation - angle;
while (difference > MathHelper.Pi)
difference -= MathHelper.TwoPi;
while (difference < -MathHelper.Pi)
difference += MathHelper.TwoPi;
turnRate *= Math.Abs (difference);
if (difference < 0)
return rotation + Math.Min (turnRate, -difference);
else
return rotation - Math.Min (turnRate, difference);
}
///
/// Draws the tank and turret.
///
public void Draw (SpriteBatch spriteBatch)
{
Vector2 origin = new Vector2 (tankTexture.Width / 2, tankTexture.Height / 2);
spriteBatch.Draw (tankTexture, Position, null, Color.White,
TankRotation, origin, 1, SpriteEffects.None, 0);
spriteBatch.Draw (turretTexture, Position, null, Color.White,
TurretRotation, origin, 1, SpriteEffects.None, 0);
}
}
}