views:

39

answers:

3

I try to work on a Force based 2D ship game. I have Forces, that a stored in a Dictionary, for 'Jets' on a ship. So I just have to say the name, the amplitude and let the engine do the acceleration/rotation.

For that I have to rotate the force into the local coordinates of the ship, before I can apply it, but instead only rotating the new force, it also rotates the force stored in the Dictionary. What causes the Force to spin around.

Force f1 = new Force();
f1 = Player.JetsDict["RearRight"];
f1.Position = Vector2.Transform(f1.Position, Matrix.CreateRotationZ(Player.Rotation));

while this code dose not change the instance stored in the dictionary (but I don't want to use it, as its longer, and I got many forces to handle):

Force f1 = new Force();
f1.Position = Player.JetsDict["RearRight"].Position;
f1.Vector = Player.JetsDict["RearRight"].Vector;
f1.Position = Vector2.Transform(f1.Position, Matrix.CreateRotationZ(Player.Rotation));

Why?

Greg the Mad

A: 
Force f1 = new Force();
f1 = Player.JetsDict["RearRight"];

That code resets f1's reference to that of the one in your dictionary. f1 is then an alias to the element of the dictionary. When you change it, you change what's in the dictionary.

What you want is a .clone() function on Force:

Force f1 = Player.JetsDict["RearRight"].clone();

or a copy constructor:

Force f1 = new Force(Player.JetsDict["RearRight"]);
luke
BTW - If you're going to use Cloning (which has other issues), you might want to implement IClonable and make it "Clone()" [instead of clone()].
Reed Copsey
A: 

What gets stored in the dictionary is a reference to the instance of Force (assuming it's a class, not a struct). If you modify the object which the value refers to, then it stays modified.

My guess is that you don't currently have a firm grasp of reference types and value types... I have an article which may help you. This is a really key topic to understand.

It's a bit like two people having the same friend's address in their phonebook: if I look up my friend's address and then paint the front door of their house red, and then you look up the same person's address and visit their house, you'll see a red front door. The important thing is that the house isn't in the phone book - only the address is. Likewise the Force object isn't in the dictionary - only a reference is.

Jon Skeet
A: 

Since Force is defined as a class (class Force), when you get the copy out of the Dictionary, you're just getting a reference to a Force instance - the same Force instance that's stored in the Dictionary. Making a change to members within that reference will be reflected everywhere in your program that uses it.

The only option here is to make a new instance. This is what you're doing in the second case.

However, if the Force is nothing but a Position and a Vector, I would consider making this a struct instead of a class. Structs are always copied by value instead of by reference, which would cause your original code to work the way you expect. If there is more to it, however, a class may still be the best option, in which case the second option is the best potential solution.

You could shorten it, though, by adding a new constructor that took a Force as an argument, and copied the Position + Vecotr. That would let you write:

Force f1 = new Force(Player.JetsDict["RearRight"]);
f1.Position = Vector2.Transform(f1.Position, Matrix.CreateRotationZ(Player.Rotation));
Reed Copsey
OK, thanks that helps a lot. Thanks you, and the others that have commented.
Gregor A. Lamche