what I am trying to do is to have a class for my game which is called "Items" and contains every item that exists in the game. Since I am making a starship-game, there are instances like "Starship" and "Weapon" in my class. Now, when I initialize an enemy for example, I want this enemy to have his "Starship"-Instance have the same values as one of the Starships listed in "Items". I tried to just write
this.Ship = Items.Testhip;
into the Enemy-Class, but it wouldn't work. So I searched the internet for another possibility and found the IClonable Interface. But it doesn't work properly for me. Here is some important code:
Items Class
public static class Items
{
private static Starship _testship;
public static Weapon _testWeapon;
public static List<Weapon> Weaponlist = new List<Weapon>();
public static List<Weapon> WeaponList { get { if (!_initialized) return null; Weaponlist.RemoveAll(c => c.BulletTexture != null); Weaponlist.Add((Weapon) TestWeapon); return Weaponlist; } }
private static bool _initialized;
public static object Testship
{
get { if (!_initialized) return null; return _testship.Clone(); }
}
public static object TestWeapon
{
get { if (!_initialized) return null; return _testWeapon.Clone(); }
}
public static void Initialize()
{
_initialized = true;
_testWeapon = new Weapon(WeaponType.Projectil, Graphics.BulletTexture, 25, 250, 10000, 1000, 15000, 3000, 400, 1200, 4, new Vector2(0, 0));
_testship = new Starship("test", 12000, 5000, Graphics.StarfighterXI, WeaponList, new Shield(), new Motor(), 1, 0, 0, 0, 0.1f, AttackAngle.Small);
}
}
These are lines from the Player Class:
public static void Initialize()
{
Ship = (Starship) Items.Testship;
Ship.Weapons.First(c => c.BulletTexture != null).Name = "PLAYER WEAPON!";
}
The same goes for the Enemy Class since I want them both to have a similar strong ship for the tests:
public void Initialize()
{
Ship = (Starship) Items.Testship;
Ship.Weapons.First(c => c.BulletTexture != null).Name = "ENEMY WEAPON!";
}
From Starship:
public class Starship : ICloneable
{
public string Name { get; set; }
public Vector3 LoadedWorld { get; set; }
public Texture2D Texture { get; set; }
public Vector2 Position { get; set; }
public Vector2 Origin { get; private set; }
public int MaxHP { get; set; }
private int HP { get; set; }
public int Cost { get; set; }
public List<Weapon> Weapons = new List<Weapon>();
public Shield Shield { get; set; }
public Motor Motor { get; set; }
public int MaxProjectilLaunchers { get; set; }
public int MaxRocketLaunchers { get; set; }
public int MaxPlasmaWeapons { get; set; }
public int MaxHEWs { get; set; }
public int ProjectilLaunchers { get; set; }
public int RocketLaunchers { get; set; }
public int PlasmaWeapons { get; set; }
public int HEWs { get; set; }
public float Rotation { get; set; } //Rotation, die das Schiff braucht, um sich zu bewegen
public float FinalRotation { get; set; } // Rotation, die das Schiff aktuell hat
public float RotationVelocity { get; set; } //Rotations-Velocity, um die sich die Rotation pro Frame ändern soll
public bool? IsRotationg { get; set; }
public float AttackAngle { get; set; }
//-----------------------------------------------------------------------------------------------------
public Starship(string name, int cost, int baseHP, Texture2D texture, List<Weapon> weapons, Shield shield, Motor motor, int maxProjectilLaunchers, int maxRocketLaunchers, int maxPlasmaWeapons, int maxHEWs, float rotationVelocity, AttackAngle attackAngle)
{
Name = name;
Cost = cost;
MaxHP = baseHP;
Position = new Vector2(0, 0); //todo: position muss richtig gesetzt werden, auch wenn das schiff feindlich ist!!!
Texture = texture;
Weapons = weapons;
Shield = shield;
Motor = motor;
MaxProjectilLaunchers = maxProjectilLaunchers;
MaxRocketLaunchers = maxRocketLaunchers;
MaxPlasmaWeapons = maxPlasmaWeapons;
MaxHEWs = maxHEWs;
RotationVelocity = rotationVelocity;
IsRotationg = null;
AttackAngle = attackAngle == StarshipsRevolution.AttackAngle.Small ? 1.0f : 1.5f;
Origin = new Vector2(Texture.Width / 2, Texture.Height / 2);
foreach (var item in weapons)
{
if (item.WeaponType == WeaponType.Projectil) ProjectilLaunchers++;
if (item.WeaponType == WeaponType.Rocket) RocketLaunchers++;
if (item.WeaponType == WeaponType.Plasma) PlasmaWeapons++;
if (item.WeaponType == WeaponType.HEW) HEWs++;
MaxHP += item.MaxHP; //todo wenn die waffe gewechselt wird wert verändern
}
if (ProjectilLaunchers > MaxProjectilLaunchers || RocketLaunchers > MaxRocketLaunchers || PlasmaWeapons > MaxPlasmaWeapons || HEWs > MaxHEWs)
throw new Exception(String.Format("Das Raumschiff {0} wurde mit zu vielen Waffen initialisiert.", name));
HP = MaxHP;
}
//-----------------------------------------------------------------------------------------------------
public void Update(GameTime gameTime)
{
foreach (var item in Weapons)
item.Update(gameTime);
//Schild und Motor updaten
}
//-----------------------------------------------------------------------------------------------------
public void Shoot(WeaponType weaponType, Vector2 position)
{
Vector2 direction = Position + Origin - position; //todo muss eventuell noch in die schleife verschoben werden, weil man sonst vielleicht nach hinten schiessen kann
direction.Normalize();
float rotation = (float)Math.Atan2(-direction.X, direction.Y);
if (rotation >= Rotation - AttackAngle && rotation <= Rotation + AttackAngle)
{
foreach (var item in Weapons.Where(c => c.WeaponType == weaponType && c.FirerateTimer >= c.Firerate))
item.Shoot(position);
}
}
/// <summary>
/// Sets a new Position for the ship or rotate it if it doesn't look into the right direction.
/// </summary>
/// <param name="position">The position the ship should be set at</param>
/// <returns>True, if it could directly set a new position, and false, if it had to rotate</returns>
public bool RotateOrMove(Vector2 position)
{
//Rotation setzen, die das Raumschiff am Ende haben soll
if (IsRotationg == null)
{
Vector2 direction = Position - position;
direction.Normalize();
FinalRotation = (float)Math.Atan2(-direction.X, direction.Y);
IsRotationg = true;
}
//Wenn die Rotation erreicht wurde, setze FinalRotation auf null
if (Equals(FinalRotation, Rotation))
IsRotationg = false;
//Wenn FinalRotation auf null ist, darf die Position gesetzt werden, da die Rotation ja dann stimmt
if (IsRotationg == false)
{
Position = position;
return true;
}
else
{ //Wenn
Rotation = CurveAngle(Rotation, FinalRotation, RotationVelocity);
return false;
}
}
//-----------------------------------------------------------------------------------------------------
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(Texture, Position + Origin, null, Color.White, Rotation, Origin, 1, SpriteEffects.None, 0);
}
private float CurveAngle(float from, float to, float step)
{
if (step == 0) return from;
if (from == to || step == 1) return to;
Vector2 fromVector = new Vector2((float)Math.Cos(from), (float)Math.Sin(from));
Vector2 toVector = new Vector2((float)Math.Cos(to), (float)Math.Sin(to));
Vector2 currentVector = Slerp(fromVector, toVector, step);
return (float)Math.Atan2(currentVector.Y, currentVector.X);
}
private Vector2 Slerp(Vector2 from, Vector2 to, float step)
{
if (step == 0) return from;
if (from == to || step == 1) return to;
double theta = Math.Acos(Vector2.Dot(from, to));
if (theta == 0) return to;
double sinTheta = Math.Sin(theta);
return (float)(Math.Sin((1 - step) * theta) / sinTheta) * from + (float)(Math.Sin(step * theta) / sinTheta) * to;
}
public object Clone()
{
return MemberwiseClone();
}
}
and Weapon:
public object Clone()
{
return MemberwiseClone();
}
As you saw above, the player's weapon gets named "PLAYER WEAPON" when it is initialized. And the Enemy's Weapon gets named "ENEMY WEAPON". But after that, the player weapon will have the name "ENEMY WEAPON" too, so I guess the values are references? By the way, all properties and members and everything change their values when they are changed by the other instance.
Hope you understand my problem and know something to do :)