Problem mit Listeneinträgen
-
Ich bekomme folgende Fehlermeldung in dieser Zeile des Codes:
int framewidth = texture.Width / sourceRects.Count;
Attempted to divide by zero.
Was ist denn da falsch ? sourceRects.Count dürfte doch eigentlich nicht 0 sein da ich in der Game1 Klasse doch die Anzahl der Listeneinträge angebe(in diesem Fall 10, von 0-9). Oder kann man die Anzahl der Listeneinträge so nicht angeben?
Ich möchte der Animationsklasse nur sagen wie viele Rectangles Einträge die Liste haben soll.Der gesamte Code(Game1 und Animationsklasse):
public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; List<Animation> animations = new List<Animation>(); public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; } protected override void Initialize() { base.Initialize(); } protected override void LoadContent() { spriteBatch = new SpriteBatch(GraphicsDevice); animations.Add(new Animation(new List<Rectangle>(9), Content.Load<Texture2D>("kurzeanim"), TimeSpan.FromSeconds(2), Animation.Animationsablaeufe.vorrück)); } protected override void Update(GameTime gameTime) { foreach (Animation animation in animations) animation.Update(gameTime); base.Update(gameTime); } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); spriteBatch.Begin(); foreach (Animation animation in animations) animation.Draw(spriteBatch); spriteBatch.End(); base.Draw(gameTime); } }
public class Animation { private int _animIndex; public enum Animationsablaeufe { vorwärts, rückwärts, vorrück, rückvor } private void vorwärts(List<Rectangle> sourceRects, int framewidth, int frameheight) { for (int i = 0; i < sourceRects.Count; i++) sourceRects[i] = new Rectangle(i * framewidth, 0, framewidth, frameheight); } private void rückwärts(List<Rectangle> sourceRects, int framewidth, int frameheight) { for (int i = 0; i < sourceRects.Count; i++) sourceRects[i] = new Rectangle((sourceRects.Count - 1 - i) * framewidth, 0, framewidth, frameheight); } private void vorrück(List<Rectangle> sourceRects, int framewidth, int frameheight) { int doppeltelaenge = sourceRects.Count * 2; for (int i = 0; i < sourceRects.Count; i++) sourceRects[i] = new Rectangle(i * framewidth, 0, framewidth, frameheight); for (int normalelaenge = sourceRects.Count; normalelaenge < doppeltelaenge; normalelaenge++) sourceRects[normalelaenge] = new Rectangle((sourceRects.Count - 1 - normalelaenge) * framewidth, 0, framewidth, frameheight); } private void rückvor(List<Rectangle> sourceRects, int framewidth, int frameheight) { int doppeltelaenge = sourceRects.Count * 2; for (int i = 0; i < sourceRects.Count; i++) sourceRects[i] = new Rectangle((sourceRects.Count - 1 - i) * framewidth, 0, framewidth, frameheight); for (int normalelaenge = sourceRects.Count; normalelaenge < doppeltelaenge; normalelaenge++) sourceRects[normalelaenge] = new Rectangle(normalelaenge * framewidth, 0, framewidth, frameheight); } public TimeSpan PassedTime { get; private set; } public List<Rectangle> SourceRects { get; private set; } public Texture2D Texture {get; private set; } public TimeSpan Duration { get; private set; } public Animationsablaeufe Ablauf { get; private set; } public Animation(List<Rectangle> sourceRects, Texture2D texture, TimeSpan duration, Animationsablaeufe animationsablaeufe) { int framewidth = texture.Width / sourceRects.Count; int frameheight = texture.Height; switch (animationsablaeufe) { case Animationsablaeufe.vorwärts: { vorwärts(sourceRects,framewidth,frameheight); break; } case Animationsablaeufe.rückwärts: { rückwärts(sourceRects, framewidth, frameheight); break; } case Animationsablaeufe.vorrück: { vorrück(sourceRects, framewidth, frameheight); break; } case Animationsablaeufe.rückvor: { rückvor(sourceRects, framewidth, frameheight); break; } } SourceRects = sourceRects; Texture = texture; Duration = duration; Ablauf = animationsablaeufe; } public void Update(GameTime dt) { PassedTime += dt.ElapsedGameTime; if (PassedTime > Duration) { PassedTime -= Duration; // zurücksetzen } var percent = PassedTime.TotalSeconds / Duration.TotalSeconds; _animIndex = (int)Math.Round(percent * (SourceRects.Count - 1)); } public void Draw(SpriteBatch batch) { batch.Draw(Texture, new Rectangle(0, 0, Texture.Width / SourceRects.Count, Texture.Height), SourceRects[_animIndex], Color.White); } }
-
Lies dir die Dokumentation durch. Du übergibst die Capacity-Grösse und nicht die List-Grösse. Siehe:
http://ideone.com/WxDt5
List<T>.Capacity
List<T>.Count
Grüssli
-
Ich habe sourceRects.Count jetzt durch sourceRects.Capacity ersetzt und ein paar weitere kleinere Änderungen vorgenommen. Jedoch bekomme ich jetzt folgende Fehlermeldung in dieser Zeile der vorrück Methode:
sourceRects[i] = new Rectangle(i * framewidth, 0, framewidth, frameheight);
Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
Was muss ich tun um 2 for Schleifen in einer Liste zu speichern? Bei der ersten und zweiten Schleife werden 10 Einträge erzeugt. Die zweiten 10 Einträge sollen einfach hinter die der ersten 10 angehängt werden.public class Animation { private int _animIndex; public enum Animationsablaeufe { vorwärts, rückwärts, vorrück, rückvor } private void vorwärts(List<Rectangle> sourceRects, int framewidth, int frameheight) { for (int i = 0; i < sourceRects.Capacity; i++) sourceRects[i] = new Rectangle(i * framewidth, 0, framewidth, frameheight); } private void rückwärts(List<Rectangle> sourceRects, int framewidth, int frameheight) { for (int i = 0; i < sourceRects.Capacity; i++) sourceRects[i] = new Rectangle((sourceRects.Capacity - 1 - i) * framewidth, 0, framewidth, frameheight); } private void vorrück(List<Rectangle> sourceRects, int framewidth, int frameheight) { sourceRects.Capacity = sourceRects.Capacity * 2; for (int i = 0; i < sourceRects.Capacity /2; i++) sourceRects[i] = new Rectangle(i * framewidth, 0, framewidth, frameheight); for (int normalelaenge = sourceRects.Capacity /2; normalelaenge < sourceRects.Capacity; normalelaenge++) sourceRects[normalelaenge] = new Rectangle((sourceRects.Capacity /2 - 1 - normalelaenge) * framewidth, 0, framewidth, frameheight); } private void rückvor(List<Rectangle> sourceRects, int framewidth, int frameheight) { sourceRects.Capacity = sourceRects.Capacity * 2; for (int i = 0; i < sourceRects.Capacity /2; i++) sourceRects[i] = new Rectangle((sourceRects.Capacity /2 - 1 - i) * framewidth, 0, framewidth, frameheight); for (int normalelaenge = sourceRects.Capacity /2; normalelaenge < sourceRects.Capacity; normalelaenge++) sourceRects[normalelaenge] = new Rectangle(normalelaenge * framewidth, 0, framewidth, frameheight); } public TimeSpan PassedTime { get; private set; } public List<Rectangle> SourceRects { get; private set; } public Texture2D Texture {get; private set; } public TimeSpan Duration { get; private set; } public Animationsablaeufe Ablauf { get; private set; } public Animation(List<Rectangle> sourceRects, Texture2D texture, TimeSpan duration, Animationsablaeufe animationsablaeufe) { int framewidth = texture.Width / sourceRects.Capacity; int frameheight = texture.Height; switch (animationsablaeufe) { case Animationsablaeufe.vorwärts: { vorwärts(sourceRects,framewidth,frameheight); break; } case Animationsablaeufe.rückwärts: { rückwärts(sourceRects, framewidth, frameheight); break; } case Animationsablaeufe.vorrück: { vorrück(sourceRects, framewidth, frameheight); break; } case Animationsablaeufe.rückvor: { rückvor(sourceRects, framewidth, frameheight); break; } } SourceRects = sourceRects; Texture = texture; Duration = duration; Ablauf = animationsablaeufe; } public void Update(GameTime dt) { PassedTime += dt.ElapsedGameTime; if (PassedTime > Duration) { PassedTime -= Duration; // zurücksetzen } var percent = PassedTime.TotalSeconds / Duration.TotalSeconds; _animIndex = (int)Math.Round(percent * (SourceRects.Capacity - 1)); } public void Draw(SpriteBatch batch) { batch.Draw(Texture, new Rectangle(0, 0, Texture.Width / SourceRects.Capacity, Texture.Height), SourceRects[_animIndex], Color.White); } }
Und so übergebe ich der Animationsklasse die Parameter:
animations.Add(new Animation(new List<Rectangle>(10), Content.Load<Texture2D>("kurzeanim"), TimeSpan.FromSeconds(2), Animation.Animationsablaeufe.vorrück));
-
...
...
Lies bitte die Dokumentation zu
Capacity
undCount
durch.Oder moment, ich zitiere dir sogar den einen entscheidenden Satz:
Capacity is the number of elements that the List<T> can store before resizing is required, while Count is the number of elements that are actually in the List<T>.
Falls du Fragen dazu hast, dann fühl dich frei dies auch zu tun.
Grüssli
-
Ich weiß was der Unterschied zwischen Count und Capacity ist. Deshalb habe ich Count ja auch durch Capacity ersetzt.
Bei der vorrück Methode soll die Liste mit doppelt so vielen Einträgen gefüllt werden, deshalb habe ich folgende Zeile geschrieben um die Kapazität doppelt so groß zu machen:sourceRects.Capacity = sourceRects.Capacity * 2;
Aus irgendeinem Grund funktioniert das ganze aber nicht.
-
Weil du ganz eindeutig
Count
undCapacity
nicht verstehst.Eine List hat intern ein Array, welches eine bestimmte Grösse hat. Diese Grösse nennt man Capacity. Wenn man eine List erstellt, so hat eine List z.B. intern ein Array mit einer Capacity von 10. Die List ist aber noch leer und es sind somit keine Elemente darin gespeichert. Count ist daher gleich 0. Wenn man nun Elemente hinzufügt, dann nimmt der Wert Count zu. Sobald Count gleich Capacity ist und ein zusätzliches Element der List hinzugefügt wird, so muss das Array intern vergrössert werden. Alle Elemente aus dem alten Array werden in das neue Array kopiert. Der Wert von Capacity steigt auf die Länge des neuen Arrays. Der Wert von Count steigt um eins, weil wir ein Element hinzugefügt haben.
Wenn du also eine List mit einem Capacity Wert von 10 erstellst, dann kannst du 10 Elemente hinzufügen, bevor das interne Array vergrössert werden muss. Die List hat aber aktuell 0 Elemente. Wenn du somit per Index auf irgendetwas zugreifen tust, kommt dir natürlich eine
IndexOutOfRangeException
zugeflogen, da die List leer ist.Grüssli
-
Danke. Ich habe es jetzt verstanden. Nachdem ich den Code der 4 Methoden wie folgt geändert habe läuft das Programm auch. Jedoch habe ich noch ein kleines Problem bei zwei Animationen festgestellt.
vorwärts und rückwärts laufen richtig ab.
Bei vorrück und rückvor werden die Bilder jedoch verzerrt dargestellt. Ich finde aber nicht raus wieso.private void vorwärts(List<Rectangle> sourceRects, int framewidth, int frameheight) { for (int i = 0; i < sourceRects.Capacity; i++) sourceRects.Add(new Rectangle(i * framewidth, 0, framewidth, frameheight)); } private void rückwärts(List<Rectangle> sourceRects, int framewidth, int frameheight) { for (int i = 0; i < sourceRects.Capacity; i++) sourceRects.Add(new Rectangle((sourceRects.Capacity - 1 - i) * framewidth, 0, framewidth, frameheight)); } private void vorrück(List<Rectangle> sourceRects, int framewidth, int frameheight) { sourceRects.Capacity = sourceRects.Capacity * 2; for (int i = 0; i < sourceRects.Capacity /2; i++) sourceRects.Add(new Rectangle(i * framewidth, 0, framewidth, frameheight)); for (int i = 0; i < sourceRects.Capacity /2; i++) sourceRects.Add(new Rectangle((sourceRects.Capacity /2 - 1 - i) * framewidth, 0, framewidth, frameheight)); } private void rückvor(List<Rectangle> sourceRects, int framewidth, int frameheight) { sourceRects.Capacity = sourceRects.Capacity * 2; for (int i = 0; i < sourceRects.Capacity /2; i++) sourceRects.Add(new Rectangle((sourceRects.Capacity /2 - 1 - i) * framewidth, 0, framewidth, frameheight)); for (int i = 0; i < sourceRects.Capacity /2; i++) sourceRects.Add(new Rectangle(i * framewidth, 0, framewidth, frameheight)); }
Hier ist noch das komplette Projekt: http://www.file-upload.net/download-4793993/WindowsGame26.rar.html