C# Habe Probleme mit der Syntax

Cartman999

Lieutenant
Registriert
Aug. 2007
Beiträge
770
Ich bekomme es nicht hin eine neue Instanz von meiner Animation-Klasse zu initialisieren. Ich gehe davon aus dass es an der Syntax liegt. Jedoch habe ich durch googeln kein ähnliches Beispiel gefunden(nur Beispiele ohne Parameter). Ich möchte die Parameter von Animation in der Game1 Klasse manchmal ändern.
Animation-Klasse:
Code:
public class Animation
{
    private int _animIndex;
    public TimeSpan PassedTime { get; private set; }
    public Rectangle[] SourceRects { get; private set; }
    public Texture2D Texture {get; private set; }
    public TimeSpan Duration { get; private set; }

    public Animation(Rectangle[] sourceRects, Texture2D texture, TimeSpan duration)
    {
          for (int i = 0; i < sourceRects.Length; i++)
          {
                sourceRects[i] = new Rectangle((sourceRects.Length - 1 - i) * (Texture.Width / sourceRects.Length), 0, Texture.Width / sourceRects.Length, Texture.Height);
          }

        SourceRects = sourceRects;
        Texture = texture;
        Duration = duration;
    }

    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.Length - 1));
    }

    public void Draw(SpriteBatch batch)
    {
        batch.Draw(Texture, new Rectangle(0, 0, Texture.Width / SourceRects.Length, Texture.Height), SourceRects[_animIndex], Color.White);
    }
}
Game1 Klasse:
Code:
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Animation animation;
Texture2D enemy;
Rectangle[] enemyframes;
TimeSpan time;
animation = new Animation(enemyframes, enemy, time);
In der letzten Zeile von Game1(animation=...) bekomme ich folgende 3 Fehlermeldungen:
Invalid token '=' in class, struct, or interface member declaration
Method must have a return type
Identifier expected

Was ist da falsch?
 
Die Zuweisung in der letzte Zeile kann nicht einfach so im Klassen-Body stehen. Entweder du initialisierst das Datenfeld animation direkt in der Zeile in der es deklariert wird, oder in einer Methode/Konstruktor.

Animation animation = new Animation(enemyframes, enemy, time);

müsste da stehen.

Besser wäre es aber, dies in einer Methode zu tun, NACHDEM die anderen Datenfelder, die du hier als Parameter übergibst, auch initialisiert wurden. Du übergibst hier überall Null als Parameter.
 
Wie kinglouy schon geschrieben hat.

Die zu schließende Klammer in Game1 fehlt scheinbar, oder haste die nicht mitgepostet?
Ist da noch mehr Quelltext?
 
Ich habe das ganze jetzt so geändert:
Code:
public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Texture2D enemy, gegner1, gegner2;
        Rectangle[] enemyframes;
        TimeSpan time;

        Animation animation = new Animation(enemyframes, enemy, time);
     
        private Gegner1()
        {
            enemyframes = new Rectangle[10]; 
            enemy = gegner1;
            time = TimeSpan.FromSeconds(3);
        }
      
        private Gegner2()
        {
            enemyframes = new Rectangle[7]; 
            enemy = gegner2;
            time = TimeSpan.FromSeconds(2);
        }

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }
      
        protected override void Initialize()
        {              
            base.Initialize();
        }
      
        protected override void LoadContent()
        {            
            spriteBatch = new SpriteBatch(GraphicsDevice);
            gegner1 = Content.Load<Texture2D>("kurzeanim");
            gegner2 = Content.Load<Texture2D>("ball");
        }
     
        protected override void Update(GameTime gameTime)
        {
            KeyboardState kbState = Keyboard.GetState();
            if (kbState.IsKeyDown(Keys.A))
            {            
            animation.Update(gameTime);
            }
            base.Update(gameTime);
        }
       
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            spriteBatch.Begin();
            animation.Draw(spriteBatch);   
            spriteBatch.End();

            base.Draw(gameTime);
        }
    }

Jetzt werden die 3 Parameter(enemyframes, enemy, time) rot unterstrichen und ich bekomme folgende Fehlermeldung:
A field initializer cannot reference the non-static field, method, or property 'WindowsGame26.Game1.time'

Wenn alles funktioniert sollen die beiden Animationen(Gegner1 und Gegner2) zum Programmstart geladen werden. Ich habe jetzt noch nichts in die Initialize Methode geschrieben da ich nicht richtig weiß wie ich das am besten machen soll(mit so wenig Code wie möglich, da ich ja irgendwann noch mehr Gegner hinzufüge). Außerdem bekomme ich ja noch immer die Fehlermeldung bei animation.
 
Ich kann mich sasdensas nur anschließen. Schau dir unbedingt noch mal die Grundlagen an.

Insbesondere mit der Objektorientierung hapert es noch. Was die Gegner1 & Gegner2-Konstruktoren in einer Game1-Klasse zu suchen haben, erschließt sich mir nicht. Sollte Visual Studio hier nicht eigentlich meckern? Irgendwas a la Konstruktor ohne dazugehörige Klasse?
 
e-Laurin schrieb:
Was die Gegner1 & Gegner2-Konstruktoren in einer Game1-Klasse zu suchen haben, erschließt sich mir nicht. Sollte Visual Studio hier nicht eigentlich meckern? Irgendwas a la Konstruktor ohne dazugehörige Klasse?
Soweit kommt der Compiler wahrscheinlich gar nicht, weil er sich schon an der Zeile drüber mit der Animation "aufhängt".

Ansonsten @TE, wie schon gesagt: Grundlagen lernen und klein Anfangen. XNA ist nicht unbedingt der leichteste und beste Einstieg in die Programmierwelt.
 
Ich habe den Animationscode jetzt komplett geändert und übergebe der Animationsklasse die Parameter jetzt mit folgender Zeile:
Code:
animations[0] = new Animation(new Rectangle[10], Content.Load<Texture2D>("kurzeanim"), TimeSpan.FromSeconds(2), Animation.Animationsablaeufe.vorrück);
Das Problem ist nur dass vorrück und rückvor nicht richtig funktionieren.
Bei vorrück läuft die Animation nur rückwärts ab(anstatt zuerst vorwärts, dann rückwärts).
Bei rückvor läuft die Animation nur vorwärts ab(anstatt zuerst rückwärts, dann vorwärts).
Ich finde den Fehler aber leider nicht. Ich verstehe nicht was falsch an vorrück und rückvor sein soll:(
Code:
public class Animation
        {            
        private int _animIndex;

        	public enum Animationsablaeufe
		{
			vorwärts, rückwärts, vorrück, rückvor
		}
           
        public TimeSpan PassedTime { get; private set; }
        public 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(Rectangle[] sourceRects, Texture2D texture, TimeSpan duration, Animationsablaeufe animationsablaeufe) 
        {
            int framewidth = texture.Width / sourceRects.Length;
            int frameheight = texture.Height;

            switch (animationsablaeufe)
            {
                case Animationsablaeufe.vorwärts:
                    {
                        for (int i = 0; i < sourceRects.Length; i++)
                        sourceRects[i] = new Rectangle(i * framewidth, 0, framewidth, frameheight);
                        break;
                    }

                case Animationsablaeufe.rückwärts:
                    {
                          for (int i = 0; i < sourceRects.Length; i++)
                          sourceRects[i] = new Rectangle((sourceRects.Length - 1 - i) * framewidth, 0, framewidth, frameheight);
                              break;
                    }

                     case Animationsablaeufe.vorrück:
                    {
                        for (int i = 0; i < sourceRects.Length; i++)                         
                          sourceRects[i] = new Rectangle(i * framewidth, 0, framewidth, frameheight);                         
                        for (int i = 0; i < sourceRects.Length; i++)                          
                          sourceRects[i] = new Rectangle((sourceRects.Length - 1 - i) * framewidth, 0, framewidth, frameheight);                   
                        break;
                    }

                     case Animationsablaeufe.rückvor:
                    {                       
                        for (int i = 0; i < sourceRects.Length; i++)                            
                          sourceRects[i] = new Rectangle((sourceRects.Length - 1 - i) * framewidth, 0, framewidth, frameheight);                                                       
                        for (int i = 0; i < sourceRects.Length; i++)                                
                          sourceRects[i] = new Rectangle(i * framewidth, 0, framewidth, frameheight);                      
                        break;
                    }
            }                 
        SourceRects = sourceRects;
        Texture = texture;
        Duration = duration;
        Ablauf = animationsablaeufe;
  }
 
Wie schon gesagt, scheinen Dir die Grundlagen komplett zu fehlen. Der Code ist völlig verhuntzt.
In den beiden letzten Cases wird das Array sourceRects überschrieben. Also erst werden 10 Dinge reingeladen, anschließend 10 andere Dinge. Es wird also nur die letzte Beladung berücksichtigt.
Aus den Cases machste besser Methoden.

Arbeite z.B. Kapitel 1 - 14 komplett durch: http://openbook.galileocomputing.de...01_001.htm#mj961be4cf36ccf494944afbc70445efdc

Danach paar einfache Programme schreiben. Anschließend ein gutes Buch zur Spieleprogrammierung (XNA) kaufen und lesen.

Wennste das alles gemacht hast, schauste Dir in ein paar Monaten nochmal an, was Du uns hier servierst. Dann wirste merken, wie es uns ergeht, wenn wir dein Code sehen.
 
Zuletzt bearbeitet:
Ehrlich? Der Code ist völliger Murks!

Code:
case Animationsablaeufe.vorrück:
{
for (int i = 0; i < sourceRects.Length; i++)
sourceRects[i] = new Rectangle(i * framewidth, 0, framewidth, frameheight);
for (int i = 0; i < sourceRects.Length; i++)
sourceRects[i] = new Rectangle((sourceRects.Length - 1 - i) * framewidth, 0, framewidth, frameheight);
break;
}
Du hast ein Array, in dem sich Rechtecke befinden. Laut dem Code gehst du bei der ersten For-Schleife das Array durch und ersetzt jeden Eintrag mit einem neuen Rechteck.
Anschließend gehst du das Array nochmal durch und ersetzt wieder jeden Eintrag.
Damit wird alles überschrieben, dass du in der ersten For-Schleife gemacht hast. Sie ist völlig sinnlos.

Zweitens: Warum überschreibst du die Array-Einträge? Es reicht doch, die Rechtecke abzufragen und ihre Größe anzupassen. Das geht sehr viel schneller!

Drittens: Du hast sehr viel redundanten und damit unnötigen Code. Du machst dir das Programmieren damit selber schwer. Der ganze Animation-Konstruktor lässt sich locker auf die Hälfte reduzieren.

Viertens: Worin liegt der Unterschied zwischen Animationsablaeufe.vorwärts und .vorrück (analog die Frage bei der umgedrehten Richtung)? Die machen exakt dasselbe.

Fünftens: Der Fehler mit der Animationsrichtung liegt nicht in der geposteten Klasse. Der liegt irgendwo anders.

Sechstens: Ich vermute es nur, aber kann es sein, dass du Konstruktoren als Methoden missbrauchst? Mir scheint, du erzeugst für jede Animation immer ein neues Objekt, damit der Konstruktor sie dann ausführt. Die Vorstellung ist geradezu gruselig.


Ich empfehle dir ganz, ganz dringend, dir ein Buch (oder e-Book) über Objektorientierung zu besorgen und das durchzuarbeiten. Danach besorgst du dir Lesematerial über Datenstrukturen und Algorithmen und gehst das durch. Und erst dann schaust du dir dein Spiel an und bemerkst, dass du von vorne anfangen musst.

Sry, dass das so hart klingt. Aber du hast einfach zu wenig Grundlagenwissen (und das ist sehr offensichtlich). Das bringt dich später in Teufelsküche, es geht ja jetzt schon mit den Problemen los.
 
Ich wollte das Array nicht mit der zweiten for Schleife überschreiben. Zuerst sollte die erste for Schleife gezeichnet werden, danach die zweite for Schleife. Ist es besser wenn ich die beiden for Schleifen nacheinander in ein Array packe? Das wären dann ja 20 Rectangles in einem Array bei einer sourceRects.Length von 10.
Sollte ich es so machen dass ich für jede der vier möglichen Animationsabläufe eine Methode schreibe und die jeweilige Methode im Case-Block aufrufe?
 
Ist es besser wenn ich die beiden for Schleifen nacheinander in ein Array packe?
Ich verstehe nicht, was du damit meinst.


Sollte ich es so machen dass ich für jede der vier möglichen Animationsabläufe eine Methode schreibe und die jeweilige Methode im Case-Block aufrufe?
Ja und nein.

Wenn es bei den 4 Animationen bleibt, kannst du sie als 4 Methoden schreiben und die per Enum & Case auseinanderhalten und aufrufen.

Sollen später mal mehr viel Animationen dazukommen, dann ist es besser, eine abstraktere Animationsklasse zu schreiben, die dann aus einer Datenbank (bzw. Datei[en]) verschiedene Animationsabläufe ausliest und dann anbietet.
Animationen bestehen ja im Grunde nur aus Transformationen (zB Zoom, Verzerrung), Translationen (Bewegung) und eventuell noch Effekten (zB Farbveränderungen). Diese kann man als Script schreiben (zB "Zoom auf 50%", "10 Sekunden Pause", "Zoom auf 100%") und von der Animationsklasse dann ausführen lassen.
Das bedeutet dann aber, dass die Animationsklasse deutlich komplexer wird. Hat man sie aber dann fertig, kann man dem Spiel unbegrenzt viele Animationen hinzufügen, ohne etwas am Code drehen zu müssen.

Letzteres ist bei größeren Spielen üblich. Man entwickelt eine Engine, die solche und solche Funktionen anbietet, die dann von Scripten gefüttert werden.
 
Ich habe ihm auch schon in einem anderen Thread vor ein paar Wochen gesagt, dass er sich zuerst mal mit den Grundlagen auseinander setzen soll. Aber naja, er lernt halt nicht dazu, damit ist das Ende schon vorprogrammiert...offensichtlich.
 
Warum das? Ist doch ein Spiel also MUSS es doch "unterhaltsamer" als eine WinForm/Komandozeilen Anwendung sein... :)
 
Das was raus kommt, ist unterhaltsamer, jepp. Leider setzt ein XNA-Spiel deutlich mehr Grundwissen voraus, sonst wird es ein so steiniger Weg, dass man die Lust daran verliert.

Tic Tac Toe mit Windows Forms ist ein guter Anfang, bei dem Anfänger schnell Erfolge erzielen. Wenn man das durch hat, programmiert man das selbe unter Verwendung von Canvas als Zeichenfläche noch mal. Danach wäre etwas wie Breakout angesagt. Dann ein Sidescroller oder Jump'n'Run. Und wenn man das hat, steht einem auch nichts im Weg, es auch mit komplizierteren Technologien wie XNA zu versuchen.
Man sollte allerdings klein anfangen und sich langsam steigern. Gerade zu Anfang, wenn man kaum etwas versteht, braucht man viele und einfach zu erreichende Erfolge.
 
Zurück
Oben