Autor Wątek: Loading Screen podczas generowania mapy  (Przeczytany 3516 razy)

Offline Yorb

  • Użytkownik

# Kwiecień 12, 2014, 16:12:12
Witam

Przydał by mi się screen z postępem generowania mapy.

Mapę generuję w

protected override void LoadContent()
ale wiadomo rysowanie odbywa się w

protected override void Draw(GameTime gameTime)
Nie wiem jak to połączyć, próbowałem po prostu zacząć rysowanie w LoadContent()
tzn. wysyłam SpriteBatch do klasy która generuję mapę, i co pewien czas tam próbuje rysować jakiegoś stringa na ekranie ale nic niestety nie widać.

Pseudokod

// w class Game1 : Microsoft.Xna.Framework.Game
LoadContent()
{
     spriteBatch = new SpriteBatch(GraphicsDevice);
     map.GenerateRandomMap(spriteBatch,widith, height);
}

//w class Map
public static void Draw_LoadingScreen(SpriteBatch sp,string status)
{
      sp.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, null, null, null, null);
            sp.DrawString(Game1.testFont,status, new Vector2(100, 100), Color.Red);
      sp.End();
}       

public static void GenerateRandomMap(SpriteBatch sp,int widith, int height)
{
      Draw_LoadingScreen(sp,"Loading....");
      // generowanie
      Draw_LoadingScreen(sp,"Done");
}

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Malkavian Ass...

  • Użytkownik

  • +1
# Kwiecień 12, 2014, 16:17:14
Zapewne wszystko leci w jednym wątku, więc Draw się w ogóle nie wykona, dopóki nie skończy się generowanie mapy.
Masz 2 oczywiste opcje:

1) Wątki -- nie ma się co rozpisywać.
2) Podzielenie generowania mapy na kawałki, które oddają sterowanie po swoim zakończeniu, aby można było coś narysować.

Offline Yorb

  • Użytkownik

# Kwiecień 12, 2014, 16:33:15
A mógłbym dostać jakiś pseudokod/opis z wątkami, jak to wszystko połączyć mniej więcej ?

Offline Malkavian Ass...

  • Użytkownik

# Kwiecień 12, 2014, 16:35:31
1. Deklarujesz dostępną globalnie zmienną przechowującą procenty ukończone.
2. GenerateRandomMap rozpoczyna wątek.
3. Wątek główny czyta ze zmiennej z procentami i je wyświetla.
4. Wątek generatora robi swoje, w międzyczasie uaktualniając zmienną z procentami w zależności od progresu.

Offline Pawelx156

  • Użytkownik

# Kwiecień 12, 2014, 16:57:54

Tu dla przykładu wczytujesz sobie np poziom
   public void LoadLevel()
       {
           GameServices.CurrentLevel = null;         
           if (GameFiles.FileExist(GameServices.ThisGame.Content.RootDirectory + "/Levels/" + this.LevelName + ".lvl"))
           {
               try
               {
                   string patch = GameServices.ThisGame.Content.RootDirectory + "/Levels/" + this.LevelName + ".lvl";               
                   GameServices.CurrentLevel = GameSerializer.Deserialize<Level>(patch, GameServices.DynamicMemory);
                   
               }
               catch { GameServices.CurrentLevel = null; }
           }

       }


Deklarujesz sobie
Thread MiniLoader = null;

A tu jakiś kod w Update

               if (MiniLoader == null) // uruchomienie watku
               {
                   ThreadStart ts = new ThreadStart(LoadLevel);
                   this.MiniLoader = new Thread(ts);
                   MiniLoader.IsBackground = true;
                   this.MiniLoader.Start();

               }
               else
               {

                   this.MiniLoader.Join(10);
                   if (this.MiniLoader.ThreadState == ThreadState.Stopped)
                   {
                           if (GameServices.CurrentLevel != null)
                           {
                               // Tu jeśli wczytywanie się powiodło
                           }
                           else // Tu coś robisz jak się  nie powiedzie
                 

// Tutaj najważniejsze żeby wyjść  i drugi raz do update nie wejść.
                           this.MiniLoader = null;                                 
                   }
               }

Sprawdzone i działające.

Offline Xender

  • Użytkownik

# Kwiecień 12, 2014, 18:02:00
Co do generowania na wątku, to w tym samym czasie drastycznie zmniejszyłbym FPS w wątku rysującym - żeby nie włączał się za często do rysowania tego progressbara (a jeszcze żeby co gorsza nie wywłaszczał wątku generatora). Jak nie zależy Ci na płynności tego paska, to może być to nawet ograniczenie do ~2 FPS.

Offline Yorb

  • Użytkownik

# Kwiecień 12, 2014, 20:02:49
Czy takie coś powinno działać ?

Poprawiłem trochę kod ale dalej nic się nie wyświetla...czarny ekran podczas generowania mapy...

Mam wątpliwości co do tego Joina...gdy dam go po skończeniu generowania w ogóle gra się nie ładuje ale zdaje mi się że tam właśnie powinien być ?

// w class Game
protected override void LoadContent()
{
             // ....
             loading = true;
}

protected override void Update(GameTime gameTime)
{
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            if (loading == true)
            {
                if (thread_mapGenerator == null)
                {
                    thread_mapGenerator = new Thread(() => { tab = Map.GenerateRandomMap(spriteBatch, WithMap, HeighMap, 50, 30); });
                    thread_mapGenerator.Start();
                }
                else
                {
                    thread_mapGenerator.Join();
                    //tab = Map.GenerateRandomMap(spriteBatch,WithMap, HeighMap, 50, 30);
                }

                if (Map.MapHasBeenGenerated == true)
                {
                    map.generateTextures(tab, 32);
                    loading = false;
                    thread_mapGenerator = null;
                }
            }
            // .....
}

// w class Map
public static int[,] GenerateRandomMap(SpriteBatch sp,int sizeX, int sizeY, int baseY, int treePercent)
{
            int[,] tab = new int[sizeX,sizeY];

            Random r = new Random();

            status = "Creating Background";
            //....
            status = "Creating Mountains";
           //...
            status = "Map is Done";
            Thread.Sleep(0);
            MapHasBeenGenerated = true;
            return tab;
}

protected override void Draw(GameTime gameTime)
{
            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, null, null, null, null, camera.transform);

            if (loading == true)
            {
                 spriteBatch.DrawString(testFont,Map.status, new Vector2(100, 100), Color.Red);
            }
            // ...
}

« Ostatnia zmiana: Kwiecień 12, 2014, 21:50:03 wysłana przez Yorb »

Offline Pawelx156

  • Użytkownik

# Kwiecień 13, 2014, 11:59:00
1.  Po co tobie wyrażenia lambda? 
2. O join sobie poczytaj.  W zależności od wartości uzyskasz taki a nie inny fps na głównym wątku.
3. Do ładowania stosuj wątek IsBackground = true;

4. Przykład jaki tobie podałem wyświetla ekran ładowania w około 60 fps i działa w 100%.
5. Wywal te wyrażenia i pisz to po polsku :D Nie stosuj tego tam gdzie nie ma potrzeby.


 

Offline Yorb

  • Użytkownik

# Kwiecień 13, 2014, 13:32:45
Mapę wrzucam do tablicy prosto z funkcji, poza tym ta funkcja jest z parametrami więc co innego jak nie lambda ?

Czegoś nie rozumiem, z tego co wiem Join czeka aż wszystkie wątki zakończą pracę, więc skoro ty masz tam tak

if (MiniLoader == null) // uruchomienie watku
{
     //..
}
else
{
    MiniLoader.Join(10);
    //...
}

To za 1 razem wątek wystartuje a za 2 już poczeka aż się mapa skończy generować, więc gdzie ta współbieżność ?

Offline Pawelx156

  • Użytkownik

# Kwiecień 13, 2014, 14:07:49
Mapę wrzucam do tablicy prosto z funkcji, poza tym ta funkcja jest z parametrami więc co innego jak nie lambda ?

Ok zobaczyłem to teraz. Ale zawsze można gdzieś to jakoś zainicjalizować inaczej, bez wyrażeń.


Czegoś nie rozumiem, z tego co wiem Join czeka aż wszystkie wątki zakończą pracę, więc skoro ty masz tam tak

if (MiniLoader == null) // uruchomienie watku
{
     //..
}
else
{
    MiniLoader.Join(10);
    //...
}

To za 1 razem wątek wystartuje a za 2 już poczeka aż się mapa skończy generować, więc gdzie ta współbieżność ?


Join z parametrem? Bez parametru czekasz aż  watek się wykona całkowicie, potem wykonujesz dalej wątek główny.
Dzięki parametrowi przekazuje pewien czas na wykonanie wątku. I nim mogę sterować sobie ilością FPS w wątku głównym.




Offline Yorb

  • Użytkownik

# Kwiecień 13, 2014, 14:41:12
Z parametrem mi się sypało więc coś nie jest tak...posiedzę jeszcze nad tym.