#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 Invites { /// /// 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); } } }