ds_grid map* Gigantische Map* Frames reichen nicht aus!

  • GM 8

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • ds_grid map* Gigantische Map* Frames reichen nicht aus!

    Hallo Community,

    Ich habe ein Problem und zwar habe ich eine Gigantische Map durch ein ds_grid erstellt. Durch einen selbst programmierten Screen verzichte ich auf eine größere Größe des Raumes und bleibe bei 800x600 pixel.
    Ich habe Tiles in der Größe von 32 die mit der Variable map_size multipliziert werden und das dann nochmal im Quadrat so das ein Spielfeld ensteht.

    Das Problem liegt jedoch nicht beim erstellen des grids, sondern beim Zeichnen. Ich bekomme schon ab einer map_size von 20 Frameseinbrüche (Das entspricht: 20*20 = 400 Tiles in einer Rastergröße von 640*640 pixel. Allerdings möchte ich die map_size bis zu 400 haben also 400*400 Tiles, was ja eine Menge ist. Ich hatte schon versucht durch eine Abfrage die Tiles nur im Sichtbereich des Raumes zu setzen, was allerdings überhaupt nichts gebracht hatte. In dem Beispiel habe ich es mit Surfaces versucht, davor normal mit Tiles und ganz davor mit einfachen draw methoden. Es kam immer das selbe raus. Ich glaube es liegt an den for Schleifen, allerdings fällt mir grad nicht ein wie ich dieses Problem anders und besser lösen könnte. Ich will nicht auf große Maps verzichten, die muss groß bleiben.

    Hier ein Bild wo ich eine Größe von map_size = 50 habe mit stolzer 1FPS:


    Create Event:
    Spoiler anzeigen

    GML-Quellcode

    1. screen_x = 32; // X-Position des Screens
    2. screen_y = 32; // Y-Position des Screens
    3. screen_speed = 8; // Scrollgeschwindigkeit des Screens
    4. map_size = 50; // Größe der Map (map_size² = Anzahl der Tiles) (Länge oder Breite = map_size*32)
    5. grid = ds_grid_create(map_size,map_size); // erstellt das Grid
    6. for(a=0;a<map_size;a+=1) { for(b=0;b<map_size;b+=1) { // erstellt die einzelnen Felder
    7. ds_grid_add(grid,a,b,1);
    8. } }
    9. sf = surface_create(room_width,room_height); // erstellt ein Surface
    10. surface_set_target(sf);
    11. draw_clear_alpha(0,0);
    12. surface_reset_target();
    Alles anzeigen


    Step Event:
    Spoiler anzeigen

    GML-Quellcode

    1. if(keyboard_check(vk_up)) { screen_y -= screen_speed; }
    2. if(keyboard_check(vk_down)) { screen_y += screen_speed; }
    3. if(keyboard_check(vk_left)) { screen_x -= screen_speed; }
    4. if(keyboard_check(vk_right)){ screen_x += screen_speed; }
    5. surface_set_target(sf);
    6. draw_clear_alpha(0,0);
    7. for (a=0;a<map_size;a+=1) { for (b=0;b<map_size;b+=1)
    8. {
    9. if ds_grid_get(grid,a,b) == 1 // falls an a,b die Value 1 ist, dann...
    10. {
    11. tile_layer_delete_at(1000,screen_x+a*32,screen_y+b*32); // löscht das tile
    12. tile_layer_delete_at(1000,screen_x+a*32+screen_speed+2,screen_y+b*32+screen_speed+2); // behebt einen Bug
    13. tile_add(bg_map,0,0,32,32,screen_x+a*32,screen_y+b*32,1000); // erstellt das tile an der angegebenen Stelle
    14. }
    15. } }
    16. draw_text(0,0,fps); // zeichnet die FPS am Rand
    17. draw_set_blend_mode(bm_normal);
    18. surface_reset_target();
    Alles anzeigen


    Vielen dank schon mal im Voraus! Wenn was nicht verständlich war, bitte nachfragen! ;)
  • Der GM ist in diesem Bereich einfach extrem schwach. Bei 50x50 müssen knapp 2500 Datensätze pro Step durchgegangen werden.
    Außerdem, soweit ich es richtig sehe...

    if ds_grid_get(grid,a,b) == 1 // falls an a,b die Value 1 ist, dann...
    {
    tile_layer_delete_at(1000,screen_x+a*32,screen_y+b*32); // löscht das tile
    tile_layer_delete_at(1000,screen_x+a*32+screen_speed+2,screen_y+b*32+screen_speed+2); // behebt einen Bug
    tile_add(bg_map,0,0,32,32,screen_x+a*32,screen_y+b*32,1000); // erstellt das tile an der angegebenen Stelle
    }


    erstellst du damit mit jedem Step ein Tile, bzw löscht dieses zuvor. Keine Ahnung ob das überhaupt nötig wäre und wie viel Leistung das ernsthaftig zieht.
  • C5_Booster schrieb:

    Der GM ist in diesem Bereich einfach extrem schwach. Bei 50x50 müssen knapp 2500 Datensätze pro Step durchgegangen werden.
    Außerdem, soweit ich es richtig sehe...

    if ds_grid_get(grid,a,b) == 1 // falls an a,b die Value 1 ist, dann...
    {
    tile_layer_delete_at(1000,screen_x+a*32,screen_y+b*32); // löscht das tile
    tile_layer_delete_at(1000,screen_x+a*32+screen_speed+2,screen_y+b*32+screen_speed+2); // behebt einen Bug
    tile_add(bg_map,0,0,32,32,screen_x+a*32,screen_y+b*32,1000); // erstellt das tile an der angegebenen Stelle
    }


    erstellst du damit mit jedem Step ein Tile, bzw löscht dieses zuvor. Keine Ahnung ob das überhaupt nötig wäre und wie viel Leistung das ernsthaftig zieht.


    sobald du in der map scrollt oder sie sich verändert werden sowieso alle steps abgefragt. Das heißt sobald man anfangen würde zu scrollen, würde das Spiel sowieso laggen. Es muss noch eine Elegantere Lösung geben als das. Ich weis das das die Leistung frisst. Ich brauch eine bessere Lösung.
  • Tice schrieb:

    Zeiche nur von (camera.x, camera.y) bis (camera.x + camera.width, camera.y + camera.height) deine Tiles
    Alles drumherum ist ja nicht sichtbar und kann ignoriert werden
    Ambesten direkt mit draw_sprite auf die surface, da das mit den tiles ist viel zu aufwändig ist


    Gesagt getan. Ja es ist um einiges schneller geworden bei 50*50 bekomme ich zwischen 30-45 fps. Gehe ich jedoch höher, wirds gruselig!



    Der neue umgeschriebene Code:
    Spoiler anzeigen

    GML-Quellcode

    1. surface_set_target(sf);
    2. draw_clear_alpha(0,0);
    3. for (a=0;a<map_size;a+=1) { for (b=0;b<map_size;b+=1)
    4. {
    5. switch(ds_grid_get(grid,a,b)) // falls an a,b die Value 1 ist, dann...
    6. {
    7. case 1:
    8. if((screen_x+a*32 < room_width && screen_x+a*32 > -32) && (screen_y+b*32 < room_height && screen_y+b*32 > -32)) {
    9. draw_sprite(_tile_grass,0,screen_x+a*32,screen_y+b*32);
    10. }
    11. break;
    12. }
    13. } }
    14. draw_text(0,0,fps); // zeichnet die FPS am Rand
    15. draw_set_blend_mode(bm_normal);
    16. surface_reset_target();
    Alles anzeigen


    Es muss doch irgendwie schneller gehen. Wieso sinken die Frames. Es wird doch nur ein 800x600 Surface gezeichnet... Einfach diese dauerhaften Abfragen! Geht das nicht anders? Ich glaube es
    würde sich sogar lohnen alles mit instanzen zufüllen und ich hätte mehr leistung!
  • Ich hab eher sowas inner richtung gemeint:

    GML-Quellcode

    1. var cx, cy, width, height;
    2. cx = round(camera.x / blockSize) - 1; //meh gm8.1 erlaubt kein var cx = <val>; ...
    3. cy = round(camera.y / blockSize) - 1;
    4. width = cx + round(camera.width / blockSize) + 1;
    5. height = cy + round(camera.height / blockSize) + 1;
    6. cx = max(0, min(mapWidth-1, cx)); //hält cx zwischen 0 und mapWidth, da es sonst zu 'out of bounds' kommt
    7. cy = max(0, min(mapHeight-1, cy));
    8. width = max(0, min(mapWidth, width));
    9. height = max(0, min(mapHeight, height));
    10. var _x, _y;
    11. for (_x = cx;_x < width; _x += 1) //meh _x++ auch nicht akzeptable, ohje
    12. {
    13. for (_y = cy;_y < height; _y += 1)
    14. {
    15. draw_sprite(sprite, subimg, _x * blockSize, _y * blockSize);
    16. }
    17. }
    Alles anzeigen

    Ungetestet, sollte perfomanter sein, da der code nicht durch den kompletten array gehen muss
    :saint:
  • Es läuft zwar flüssig jedoch wenn man mit der map bei einer 400x400 map oder sonst irgendeiner größe runterscrollt ist nichts zusehen. Er hört nach 25 sprites/kästchen auf. Ich hab das ganze jetzt teilweise so übernommen:

    Hier nochmal das Create Event (immernoch beim alten):
    Spoiler anzeigen

    GML-Quellcode

    1. screen_x = 32; // X-Position des Screens
    2. screen_y = 32; // Y-Position des Screens
    3. screen_speed = 8; // Scrollgeschwindigkeit des Screens
    4. map_size = 400; // Größe der Map (map_size² = Anzahl der Tiles) (Länge oder Breite = map_size*32)
    5. block_size = 32;
    6. grid = ds_grid_create(map_size,map_size); // erstellt das Grid
    7. for(a=0;a<map_size;a+=1) { for(b=0;b<map_size;b+=1) { // erstellt die einzelnen Felder
    8. ds_grid_add(grid,a,b,1);
    9. } }
    10. sf = surface_create(800,600); // erstellt ein Surface
    11. surface_set_target(sf);
    12. draw_clear_alpha(0,0);
    13. surface_reset_target();
    Alles anzeigen


    Das Step Event:
    Spoiler anzeigen

    GML-Quellcode

    1. if(keyboard_check(vk_up)) { screen_y += screen_speed; }
    2. if(keyboard_check(vk_down)) { screen_y -= screen_speed; }
    3. if(keyboard_check(vk_left)) { screen_x += screen_speed; }
    4. if(keyboard_check(vk_right)){ screen_x -= screen_speed; }
    5. var cx, cy, width, height;
    6. cx = round(screen_x / block_size) -1;
    7. cy = round(screen_y / block_size) -1;
    8. width = cx + round(room_width / block_size) +1;
    9. height = cy + round(room_height / block_size) +1;
    10. cx = max(0, min(map_size-1, cx));
    11. cy = max(0, min(map_size-1, cy));
    12. width = max(0, min(map_size, width));
    13. height = max(0, min(map_size, height));
    14. surface_set_target(sf);
    15. draw_clear_alpha(0,0);
    16. var _x, _y;
    17. for (_x = cx;_x < width; _x += 1) { for (_y = cy; _y < height ; _y+=1)
    18. {
    19. switch(ds_grid_get(grid,_x,_y)) // falls an a,b die Value 1 ist, dann...
    20. {
    21. case 1:
    22. draw_sprite(spr_grass,0,_x*block_size,_y*block_size);
    23. break;
    24. }
    25. } }
    26. draw_text(0,0,fps); // zeichnet die FPS am Rand
    27. draw_set_blend_mode(bm_normal);
    28. surface_reset_target();
    Alles anzeigen


    Ich finde es sehr komisch. Irgenwie zeichnet er alles unterhalb und rechts vom Surface garnichts mehr, selbst wenn es reinrutscht...?? Hab die .gmk hochgeladen
    Dateien
    • gigant_map.gmk

      (10,67 kB, 238 mal heruntergeladen, zuletzt: )
  • Kreiere ein Skript "scr_drawlines"

    Quellcode

    1. //Argument0: Snap size.
    2. //Argument1: Starting x position.
    3. //Argument2: Starting y position.
    4. //Argument3: Snap amount.
    5. xi = argument1;
    6. xy = argument2;
    7. repeat(argument3)
    8. {
    9. draw_line(xi,argument2,xi,argument3*argument0+argument2);
    10. draw_line(argument1,xy,argument3*argument0+argument1,xy);
    11. xi+=argument0;
    12. xy+=argument0;
    13. }
    14. draw_line(xi,argument2,xi,argument3*argument0+argument2);
    15. draw_line(argument1,xy,argument3*argument0+argument1,xy);
    Alles anzeigen


    Dann im Draw Event zb.:

    Quellcode

    1. scr_drawlines(60, 0, 0, 6000)


    Dies ist nur fürs SICHTBARE Grid sollte aber mit 100 FPS auf 6000x6000 laufen bzw. auch höher ;).
  • @Sasula
    Es geht darum eine verschiebare Map immer und immerwieder zu zeichnen. Die wird durch die Pfeiltasten bewegt, aber danke, scheint auch interessant zu sein. Allerdings möchte ich ja nicht das grid zeichnen sondern das Aussehen von einer Map. Steht das jetzt ein Haus. Ist da eine Mauer oder einfach nur Wiese, Erde oder sonstetwas.
  • Wenn die Karten oft geändert werden muss: unterteile die Map in geeignete Einzelteile und zeichne diese dann auf eine Surface, immer wenn sich was ändert muss (Dirty-Flag oder ähnliches benutzen), dann das neu gezeichnet werden, dafür kann man das dann immer wieder verwenden. Wenn die Karte nicht geändert werden muss: generell Surface benutzen.
    wupto.net/ Nicht meine Seite!
    We love Koalas.

    GM-D-Spam-o-Meter: 32%