Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

purpule

Frischling

  • »purpule« ist der Autor dieses Themas

Beiträge: 23

Beruf: Schüler

  • Private Nachricht senden

1

26.06.2015, 19:42

XNA spiel friert nach durchlauf einer while-schleife ein

hi,
ich habe etwas mit xna programmiert. nach aufruf einer funktion wird ein neues objekt einer klasse erzeugt. hierbei handelt es sich um eine kampfszene. ich habe die boolsche variable "IsFighting", um zu prüfen, ob der kampf noch abgewickelt wird oder nicht.
nachdem das objekt der klasse für den kampf erzeugt wurde, geht das programm in folgende schleife:

Quellcode

1
2
3
4
5
while(fight_.IsFighting)
{
fight_.Update();
fight_.Draw(spriteBatch);
}


zu testzwecken soll in der update() methode nur ein tastendruck abgefragt werden, der den kampf unterbricht. in der draw() methode wird nur die textur des gegners gezechnet.

Quellcode

1
2
3
4
5
6
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Begin();
spriteBatch.Draw(enemyTexture, new Rectangle((int)enemyLocation.X, (int)enemyLocation.Y, enemyTexture.Width, enemyTexture.Height), Color.White);
spriteBatch.End();
}


ich habe das programm an vielen punkten anhalten lassen und bin zu der erkenntnis gekommen, dass das programm nach dem ersten schleifendurchlauf einfriert. jedoch habe ich keine ahnung woran das liegen könnte.

2

26.06.2015, 20:01

So ein XNA-Spiel hat bereits einen gewissen Ablauf um Ressourcen zu laden, Logikberechnungen auszuführen und Inhalt auf dem Bildschirm anzuzeigen. Beispielsweise wird bei jedem darzustellenden Bild/Frame die Update() und die Draw()-Methode aufgerufen. In der Draw-Methode wird beispielsweise das aktuelle Bild im Hintergrund gecleared (z.B. auf schwarz gesetzt) und dann werden die einzelnen Bilder gezeichnet. Am Ende der Draw-Methode wird dann diese Bild, worauf gerade gezeichnet wurde, angezeigt. D.h. wenn die Draw-Methode nicht mehr aufgerufen wird, dann wird auch das Bild nicht mehr aktualisiert. Wenn die Update-Methode nicht aufgerufen wird, reagiert z.B. das Spiel nicht mehr auf Eingaben.

Mit deiner Schleife wird zwar die Update und Draw-Methode von "fight" aufgerufen, aber die eigentlichen XNA-Methoden nicht mehr. Dann wird auch das Bild nicht mehr aktualisiert, weil das neu gezeichnete Bild nie angezeigt wird. Und vermutlich werden auch die Eingaben nicht mehr richtig abgefangen, weil der Status gedrückter Tasten nicht mehr aktualisiert wird.

purpule

Frischling

  • »purpule« ist der Autor dieses Themas

Beiträge: 23

Beruf: Schüler

  • Private Nachricht senden

3

27.06.2015, 11:05

hi, danke erstmal für deine antwort.

mir hat jemand gesagt, ich muss die game.draw und -update methoden mit den neuen beiden aus der fight-klasse überschreiben.
ich habe dann die fight klasse von der Microsoft.XNA.Framework.Game klasse abgeleitet und die besagten methoden wie in der game1.cs mit "protected override void" überschrieben.

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
public class Fight : Microsoft.Xna.Framework.Game    {
        #region fields
        public bool IsFighting { get; set; }
        SpriteBatch spriteBatch;
        Texture2D enemyTexture;
        Vector2 enemyLocation;

        private string enemyName;
        private int enemyCount;
        #endregion

        #region constructor
        public Fight(string enemy, int enemycount, ContentManager Content, SpriteBatch spritebatch)
        {
            IsFighting = true;    //gibt an, ob der kampf läuft
            spriteBatch = spritebatch;  //übergibt spritebatch
            enemyName = enemy;
            enemyCount = enemycount;
            enemyLocation.X = 100;      //position der textur
            enemyLocation.Y = 100;
            Load(enemyName, enemyCount, Content);   //ruft load funktion auf
        }
        #endregion

        #region private methods
        private void Load(string enemName, int enemCount, ContentManager Content)   //lädt textur des übergebenen gegners
        {
            switch(enemName)
            {
                case "ork": enemyTexture = Content.Load<Texture2D>("ork"); break;
            }
        }
        #endregion

        #region public methods
        public void DoFightProgress(GameTime gameTime)             //methode, die von außen verwendet wird, um update und draw aufzurufen
        {
            Update(gameTime);
            Draw(gameTime);
        }

        protected override void Update(GameTime gameTime)
        {
            
            if (Keyboard.GetState().IsKeyDown(Keys.F1))             //prüft, ob F1gedrückt wurde
            {
                IsFighting = false;                                 //wenn ja, dann unterbreche kampf
            }
            base.Update(gameTime);
        }
        protected override void Draw(GameTime gameTime)
        {
            spriteBatch.Begin();                                    //spritebatch, der vorerst nur den gegner zeichnet
            spriteBatch.Draw(enemyTexture, new Rectangle((int)enemyLocation.X, (int)enemyLocation.Y, enemyTexture.Width, enemyTexture.Height), Color.White);
            spriteBatch.End();
            base.Draw(gameTime);
        }
        #endregion     }


hier ist nochmal der code meiner klasse.

in der klasse, die das fight-objekt erzeugt, wird folgendes durchgeführt:

C#-Quelltext

1
2
3
4
5
6
private void fight(string enemy, int enemy_count, SpriteBatch spriteBatch, ContentManager Content, GameTime gameTime)        {
            fight_ = new Fight(enemy, enemy_count, Content, spriteBatch);
            while(fight_.IsFighting)
            {
                fight_.DoFightProgress(gameTime);
            }         }


hier wird nur nach einer abfrage die fight-methode aufgerufen, die dann die gesamte kampfhandlung mithilfe der fight-klasse durchführt. wenn IsFighting auf false steht, soll die schleife verlassen werden.


das problem an der sache ist das gleiche. habe ich grundlegend etwas falsch gemacht, oder nur etwas kleines übersehen?

Psyco001

Frischling

Beiträge: 54

Wohnort: Berlin

  • Private Nachricht senden

4

27.06.2015, 11:28

Grob gesagt ist wohl das while dein Problem:

Quellcode

1
2
3
4
5
6
7
8
9
10
GameLoop
{
    [...]
        //hier ist leider eine endlos schleife, die sorgt dafür das du nicht zum Rendern kommst
        while(IsFighting == true)
        { [...] }
    [...]
    Update(); // <-- hier wird deine Eingabe abgefragt
    Draw();
}


dein Programm erreicht nach dem betreten der schleife die update Funktion nicht mehr die ja scheinbar dafür sorgt die eingaben zu bearbeiten
es wäre wahrscheinlich besser dort nur zu prüfen ob IsFighting true ist anstatt daraus gleich eine schleife zu machen

oder anders gesagt ist es wahrscheinlich das dein Spiel nicht nach der Schleife einfriert sondern die schleife der Grund ist warum es einfriert.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Psyco001« (27.06.2015, 11:34)


purpule

Frischling

  • »purpule« ist der Autor dieses Themas

Beiträge: 23

Beruf: Schüler

  • Private Nachricht senden

5

27.06.2015, 11:38

warum erreicht die schleife die update funktion nicht mehr? in der schleife wird fight_.dofightprogress aufgerufen, welches wiederum dann draw und update callt.
ich kann man versuchen, die schleife an einer anderen stelle anders einzusetzen, aber ich brauche die schleife ja, damit der kampf auch weiter läuft^^

Psyco001

Frischling

Beiträge: 54

Wohnort: Berlin

  • Private Nachricht senden

6

27.06.2015, 11:55

>_< stimmt, hab ich wohl oder übel überlesen

purpule

Frischling

  • »purpule« ist der Autor dieses Themas

Beiträge: 23

Beruf: Schüler

  • Private Nachricht senden

7

27.06.2015, 11:57

also ich denke immer noch, dass ich hier einen grundlegenden fehler bei der vererbung der funktionen gemacht habe.

hab die schleife trotzdem nochmal woanders hinverlegt, aber wie zu erwarten verhält sich das programm nicht anders

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

8

29.06.2015, 08:59

Das Problem wurde doch bereits beschrieben:
XNA implementiert für dich die Gameloop (in Psyco001s Pseudocode wäre das die GameLoop), welche automatisch die Update- und Draw-Methoden deiner Game-Klasse aufruft. Du rufst wiederum aus der Update-Methode heraus eigenen Code auf, der eine EndlosSchleife startet. Durch diese Endlosschleife wird die Update-Methode (die, die von XNA aus aufgerufen wurde) nicht mehr verlassen. Dadurch kann XNA sich auch nicht darum kümmern, die angefallenen Zeichenoperationen auch tatsächlich durchzuführen.
Das Problem ist also, wie bereits geschrieben, dass du eine Schleife verwendest. Du musst stattdessen auf andere Art den Zustand des Spiels anpassen, sodass in der Update-Methode des Spiels (die, die direkt von XNA aufgerufen wird) dieser aktualisiert werden kann (richtige Auswertung von Eingaben etc.)
Dass deine Fight-Klasse von Game abgeleitet ist, ist auch Unsinn. Du hast bereits eine Game-Klasse (oder eher: eine andere deiner Klassen erweitert bereits die Game-Klasse) und wirst auch keine weiteren Game-Klassen benötigen.
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

Werbeanzeige