Animation issue caused by C# parameters passed by reference rather than value, but where?
I'm having trouble with sprite animation in XNA that appears to be caused by a struct passed as a reference value. But I'm not using the ref keyword anywhere. I am, admittedly, a C# noob, so there may be some shallow bonehead error in here, but I can't see it.
I'm creating 10 ants or bees and animating them as they move across the screen. I have an array of animation structs, and each time I create an ant or bee, I send it the animation array value it requires (just [0] or [1] at this time). Deep inside the animation struct is a timer that is used to change frames. The ant/bee class stores the animation struct as a private variable.
What I'm seeing is that each ant or bee uses the same animation struct, the one I thought I was passing in and copying by value. So during Update(), when I advance the animation timer for each ant/bee, the next ant/bee has开发者_JAVA百科 its animation timer advanced by that small amount. If there's 1 ant on screen, it animates properly. 2 ants, it runs twice as fast, and so on. Obviously, not what I want.
Here's an abridged version of the code. How is BerryPicking's ActorAnimationGroupData[] getting shared between the BerryCreatures?
class BerryPicking
{
private ActorAnimationGroupData[] animations;
private BerryCreature[] creatures;
private Dictionary<string, Texture2D> creatureTextures;
private const int maxCreatures = 5;
public BerryPickingExample()
{
this.creatures = new BerryCreature[maxCreatures];
this.creatureTextures = new Dictionary<string, Texture2D>();
}
public void LoadContent()
{
// Returns data from an XML file
Reader reader = new Reader();
animations = reader.LoadAnimations();
CreateCreatures();
}
// This is called from another function I'm not including because it's not relevant to the problem.
// In it, I remove any creature that passes outside the viewport by setting its creatures[] spot to null.
// Hence the if(creatures[i] == null) test is used to recreate "dead" creatures. Inelegant, I know.
private void CreateCreatures()
{
for (int i = 0; i < creatures.Length; i++)
{
if (creatures[i] == null)
{
// In reality, the name selection is randomized
creatures[i] = new BerryCreature("ant");
// Load content and texture (which I create elsewhere)
creatures[i].LoadContent(
FindAnimation(creatures[i].Name),
creatureTextures[creatures[i].Name]);
}
}
}
private ActorAnimationGroupData FindAnimation(string animationName)
{
int yourAnimation = -1;
for (int i = 0; i < animations.Length; i++)
{
if (animations[i].name == animationName)
{
yourAnimation = i;
break;
}
}
return animations[yourAnimation];
}
public void Update(GameTime gameTime)
{
for (int i = 0; i < creatures.Length; i++)
{
creatures[i].Update(gameTime);
}
}
}
class Reader
{
public ActorAnimationGroupData[] LoadAnimations()
{
ActorAnimationGroupData[] animationGroup;
XmlReader file = new XmlTextReader(filename);
// Do loading...
// Then later
file.Close();
return animationGroup;
}
}
class BerryCreature
{
private ActorAnimation animation;
private string name;
public BerryCreature(string name)
{
this.name = name;
}
public void LoadContent(ActorAnimationGroupData animationData, Texture2D sprite)
{
animation = new ActorAnimation(animationData);
animation.LoadContent(sprite);
}
public void Update(GameTime gameTime)
{
animation.Update(gameTime);
}
}
class ActorAnimation
{
private ActorAnimationGroupData animation;
public ActorAnimation(ActorAnimationGroupData animation)
{
this.animation = animation;
}
public void LoadContent(Texture2D sprite)
{
this.sprite = sprite;
}
public void Update(GameTime gameTime)
{
animation.Update(gameTime);
}
}
struct ActorAnimationGroupData
{
// There are lots of other members of this struct, but the timer is the only one I'm worried about.
// TimerData is another struct
private TimerData timer;
public ActorAnimationGroupData()
{
timer = new TimerData(2);
}
public void Update(GameTime gameTime)
{
timer.Update(gameTime);
}
}
struct TimerData
{
public float currentTime;
public float maxTime;
public TimerData(float maxTime)
{
this.currentTime = 0;
this.maxTime = maxTime;
}
public void Update(GameTime gameTime)
{
currentTime += (float)gameTime.ElapsedGameTime.TotalSeconds;
if (currentTime >= maxTime)
{
currentTime = maxTime;
}
}
}
Are you sure that you are using a new ActorAnimation with each creature? I would create a test that has two creatures and set watches for each creature's animation.animation values and step through the updates to see when they are changing. Is it possible your Updates() are getting called multiple times?
精彩评论