У меня есть корабль, который порождает спрайтов.Есть два типа: рельсовые снаряды и ракеты.Ракеты запускаются правильно, но снаряды из рельсовых орудий всегда появляются на расстоянии около ста пикселей перед кораблем (или, по крайней мере, кажется).Я не уверен, почему это происходит.Кроме того, есть две башни, когда она запускается из одной, она должна установить логическое значение в true, чтобы она запускалась из другой;когда он срабатывает, он устанавливает логическое значение обратно в false и так далее.Это всегда срабатывает из первого.Опять не знаю почему.Я бился головой об этом весь день.Вот мой код:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using ShipBattle.Classes.Ships;
using ShipBattle.Classes.Ships.Fighters;
using ShipBattle.Classes.Ships.Projectiles;
using ShipBattle.Classes.Ships.Projectiles.Tauri;
namespace ShipBattle.Classes.Ships.Fighters
{
public class F302 : Ship
{
const double missileMinimumFiringArc = Utilities.NINETY_DEGREES / 2;
const double missileMaximumFiringArc = Utilities.NINETY_DEGREES + (Utilities.NINETY_DEGREES / 2);
const double railgunMinimumFiringArc = 1.5;
const double railgunMaximumFiringArc = 1.6;
const double MISSILES_ROF = 30.0;
protected List<double> CooldownLeft = new List<double>();
private ContentManager content;
public event ShipFired WeaponFired;
public List<NaquadahEnhancedMissile> missiles;
public List<RailgunRound> railgunRounds;
public int[] MissileAmmo { get; set; }
public int[] RailgunAmmo { get; set; }
//Determines which missile/railgun to fire
bool leftMissile = true;
bool leftRailgun = true;
public F302(Vector2 position, ContentManager Content)
{
content = Content;
Texture = content.Load<Texture2D>(@"Textures\Ships\Tauri\Fighters\F302");
Position = position;
Rotation = 0;
#region Physics Stuff
mass = 19200;
force = 76.3f;
acceleration = (force * 1000) / mass;
maxSpeed = Utilities.GetVelocity(acceleration);
#endregion
#region Hull & Shielding
HullIntegrity = 10;
ShieldStrength = 0;
#endregion
#region Weapons!!!
/*
* [0] = Port Missile
* [1] = Starboard Missile
* [2] = Port Railgun
* [3] = Starboard Railgun
*/
//Setup
missiles = new List<NaquadahEnhancedMissile>();
railgunRounds = new List<RailgunRound>();
MissileAmmo = new int[2];
RailgunAmmo = new int[2];
//Port Missile
WeaponRatesOfFire.Add(MISSILES_ROF);
CooldownLeft.Add(0);
WeaponsEnplacements.Add(new Vector2(14, 5));
WeaponEmplacementOffsets.Add(new Vector2(14, 5));
MissileAmmo[0] = 2;
//Starboard Missile
WeaponRatesOfFire.Add(MISSILES_ROF);
CooldownLeft.Add(0);
WeaponsEnplacements.Add(new Vector2(35, 5));
WeaponEmplacementOffsets.Add(new Vector2(35, 5));
MissileAmmo[1] = 2;
//Port Railgun
WeaponRatesOfFire.Add(7.2);
CooldownLeft.Add(0);
WeaponsEnplacements.Add(new Vector2(24, 0));
WeaponEmplacementOffsets.Add(new Vector2(24, 0));
RailgunAmmo[0] = 10000;
//Starboard Railgun
WeaponRatesOfFire.Add(7.2);
CooldownLeft.Add(0);
WeaponsEnplacements.Add(new Vector2(26, 0));
WeaponEmplacementOffsets.Add(new Vector2(26, 0));
RailgunAmmo[1] = 10000;
#endregion
}
protected override void UpdateProjectiles(Vector2 pos)
{
for (int i = 0; i < missiles.Count; i++)
if (missiles[i].Remove)
missiles.RemoveAt(i);
for (int i = 0; i < railgunRounds.Count; i++)
if (railgunRounds[i].Remove)
railgunRounds.RemoveAt(i);
foreach (NaquadahEnhancedMissile nem in missiles)
nem.Update(enemyPos);
foreach (RailgunRound rr in railgunRounds)
rr.Update(enemyPos);
}
protected override void DrawProjectiles(SpriteBatch spriteBatch)
{
foreach (NaquadahEnhancedMissile nem in missiles)
nem.Draw(spriteBatch);
foreach (RailgunRound rr in railgunRounds)
rr.Draw(spriteBatch);
}
protected override void CheckTarget(Ship target)
{
enemyPos = target.Position;
double distance = Vector2.Distance(Position, target.Position);
Vector2 vector1 = Vector2.Normalize(Position - target.Position);
Vector2 vector2 = new Vector2((float)Math.Cos(Rotation), (float)Math.Sin(Rotation));
double angle = Math.Acos(Vector2.Dot(vector1, vector2));
if (angle > missileMinimumFiringArc && angle < missileMaximumFiringArc)
if (distance < 500)
if (((target.HullIntegrity + target.ShieldStrength) - 10) <= 0)
FireMissiles();
if (angle > railgunMinimumFiringArc && angle < railgunMaximumFiringArc)
FireRailguns();
}
protected void FireMissiles()
{
if (leftMissile)
{
if (CooldownLeft[0] <= 0)
{
if (MissileAmmo[0] > 0)
{
NaquadahEnhancedMissile nem = new NaquadahEnhancedMissile(WeaponsEnplacements[0], Rotation, content);
nem.hit += new ProjectileHit(nem_hit);
missiles.Add(nem);
CooldownLeft[0] = WeaponRatesOfFire[0];
CooldownLeft[1] = WeaponRatesOfFire[1];
MissileAmmo[0]--;
leftMissile = false;
}
}
}
else
if (CooldownLeft[1] <= 0)
{
if (MissileAmmo[1] > 0)
{
NaquadahEnhancedMissile nem = new NaquadahEnhancedMissile(WeaponsEnplacements[1], Rotation, content);
nem.hit += new ProjectileHit(nem_hit);
missiles.Add(nem);
CooldownLeft[0] = WeaponRatesOfFire[0];
CooldownLeft[1] = WeaponRatesOfFire[1];
MissileAmmo[1]--;
leftMissile = true;
}
}
}
private void FireRailguns()
{
if (leftRailgun)
{
if (CooldownLeft[2] <= 0)
{
if (RailgunAmmo[0] > 0)
{
RailgunRound rgr = new RailgunRound(WeaponsEnplacements[2], Rotation, content);
rgr.hit += new ProjectileHit(nem_hit);
railgunRounds.Add(rgr);
CooldownLeft[2] = WeaponRatesOfFire[2];
CooldownLeft[3] = WeaponRatesOfFire[3];
RailgunAmmo[0]--;
leftRailgun = false;
}
}
}
else
if (CooldownLeft[3] <= 0)
{
if (RailgunAmmo[1] > 0)
{
RailgunRound rgr = new RailgunRound(WeaponsEnplacements[3], Rotation, content);
rgr.hit += new ProjectileHit(nem_hit);
railgunRounds.Add(rgr);
CooldownLeft[2] = WeaponRatesOfFire[2];
CooldownLeft[3] = WeaponRatesOfFire[3];
MissileAmmo[1]--;
leftRailgun = true;
}
}
}
protected override void Cooldown()
{
for (int f = 0; f < CooldownLeft.Count; f++)
CooldownLeft[f]--;
}
private void nem_hit(Projectile p, EventArgs e)
{
if (p is NaquadahEnhancedMissile)
{
p.Remove = true;
if (targetShip.ShieldStrength > 0)
targetShip.ShieldStrength -= p.Damage;
else
targetShip.HullIntegrity -= p.Damage;
}
else if (p is RailgunRound)
{
p.Remove = true;
if (targetShip.ShieldStrength > 0)
targetShip.ShieldStrength -= p.Damage / 4;
else
targetShip.HullIntegrity -= p.Damage;
}
}
protected override void CleanupProjectiles()
{
missiles.Clear();
railgunRounds.Clear();
}
}
}
А вот код для класса корабля, от которого все это наследуется:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using ShipBattle.Classes.Ships.Projectiles;
using ShipBattle.Classes.Ships.Projectiles.Tauri;
namespace ShipBattle.Classes.Ships
{
public abstract class Ship
{
public Texture2D Texture { get; set; }
public Vector2 Position
{
get
{
return _position;
}
set
{
_position = value;
}
}
public float Rotation { get; set; }
private Vector2 _position;
protected Ship targetShip;
protected Vector2 enemyPos;
#region Health & Shielding
public float HullIntegrity { get; set; }
public float ShieldStrength { get; set; }
public bool Remove { get; set; }
#endregion
#region Guns
protected List<Vector2> WeaponsEnplacements = new List<Vector2>();
protected List<Vector2> WeaponEmplacementOffsets = new List<Vector2>();
protected List<double> WeaponRatesOfFire = new List<double>();
/// <summary>
/// The rates of fire for all weapons, represented in terms of the delay between frames
/// </summary>
#endregion
#region Targeting Logic
bool hasTarget = false;
protected int targetHashCode;
Vector2 targetShipPosition;
Ship target;
bool evasive = false;
bool hasRandomTrajectory = false;
bool reachedBounds = false;
bool followingRandom = false;
int timeToFaffAbout = 360;
double randomRotation;
#endregion
#region Physics Stuff
float angleA, b, a, speed = 0;
double turningRadius = 10 * (Math.PI / 180);
//Acceleration
protected int mass; // kg
protected float force; // kN, thruster power
protected float acceleration; // m/s^2
//Velocity
protected float maxSpeed; // m/s, calculated using 30-second burn
protected float initialSpeed = 0;
protected float finalSpeed = 0;
protected float time = 0.016666f;
#endregion
public void Update(List<Ship> ships)
{
if (timeToFaffAbout >= 0)
{
timeToFaffAbout = 360;
followingRandom = false;
}
if (!hasTarget)
{
targetShip = GetTarget(ships);
hasTarget = true;
}
else
{
if (targetShip != null)
{
if (Vector2.Distance(Position, targetShip.Position) < 75)
evasive = true;
else
evasive = false;
if (evasive)
{
if (!hasRandomTrajectory)
{
Random random = new Random();
randomRotation = random.Next((int)(Math.PI * 100));
double negative = random.Next(2);
if (negative == 1)
randomRotation *= -1;
Rotation = (float)randomRotation;
hasRandomTrajectory = true;
}
}
else
{
if (!followingRandom)
{
//Rotate the sprite using the turning radius
Rotation = Utilities.TurnToFace(Position, new Vector2(targetShip.Position.X, targetShip.Position.Y), (float)Rotation, (float)turningRadius);
}
}
KeepOnTheScreen();
//Move the sprite, using KINEMATIC PHYSICS, ***!!! -->goes in the direction set by the rotation algorithm
Move();
CheckTarget(targetShip);
UpdateProjectiles(targetShip.Position);
//Stop targeting a dead enemy
if (targetShip.HullIntegrity <= 0)
hasTarget = false;
}
}
//Recalculate the List<Vector2> weapons enplacements based on the current rotation angle
RecalculateWeaponsPositions();
//Cooldown the guns
Cooldown();
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(Texture, Position, null, Color.White, Rotation, new Vector2(Texture.Width / 2, Texture.Height / 2), 0.5f,
SpriteEffects.None, 0.0f);
if (hasTarget)
DrawProjectiles(spriteBatch);
}
/// <summary>
/// Uses trig and the thruster power to move the ship. b is the y distance to move, a is the x distance to move
/// </summary>
private void Move()
{
if (finalSpeed < maxSpeed)
finalSpeed = speed + (acceleration * time);
angleA = Rotation;
b = (float)Math.Cos(angleA) * finalSpeed;
a = (float)Math.Sin(angleA) * finalSpeed;
_position.Y -= b;
_position.X += a;
speed = finalSpeed;
}
/// <summary>
/// Acquires the closes enemy ship
/// </summary>
/// <param name="ships">The ships to search through</param>
/// <returns></returns>
private Ship GetTarget(List<Ship> ships)
{
CleanupProjectiles();
Ship rVal = null;
int distance = int.MaxValue;
float c;
foreach (Ship ship in ships)
{
c = Vector2.Distance(Position, ship.Position);
if (c < distance)
rVal = ship;
}
return rVal;
}
/// <summary>
/// Reorients the positions of all the weapon positions on this ship
/// </summary>
private void RecalculateWeaponsPositions()
{
for (int i = 0; i < WeaponsEnplacements.Count; i++)
{
WeaponsEnplacements[i] = RotateWeapons(WeaponEmplacementOffsets[i]);
}
}
/// <summary>
/// Recalculates the positions of the weapons on this ship based off their default offset and the current angle
/// </summary>
/// <param name="weapon">The weapon position to recalculate</param>
/// <param name="offset">The default offset of that weapon</param>
private Vector2 RotateWeapons(Vector2 offset)
{
Quaternion rotation = Quaternion.CreateFromAxisAngle(Vector3.Backward, (float)Rotation);
return Vector2.Transform(offset, rotation) + Position;
}
/// <summary>
/// Keeps the ship on the screen
/// </summary>
private void KeepOnTheScreen()
{
if (Position.X > 1019 || Position.X < 5 || Position.Y > 761 || Position.Y < 5)
reachedBounds = true;
else
reachedBounds = false;
if (reachedBounds)
{
followingRandom = true;
if (!followingRandom)
Rotation = Utilities.TurnToFace(Position, new Vector2(1024 / 2, 768 / 2), Rotation, (float)turningRadius);
else
timeToFaffAbout--;
}
}
/// <summary>
/// Checks to see if the target ship is within weapons range
/// </summary>
/// <param name="target"></param>
protected abstract void CheckTarget(Ship target);
/// <summary>
/// Decrements the cooldown of all weapons
/// </summary>
protected abstract void Cooldown();
protected abstract void UpdateProjectiles(Vector2 pos);
protected abstract void DrawProjectiles(SpriteBatch spriteBatch);
protected abstract void CleanupProjectiles();
}
}
Если кто-нибудь сможет мне помочь с этим, я буду очень признателен.Спасибо!