Nur das rendern, was auf dem Bildschirm angezeigt wird


6

Ich bin ziemlich neu auf dieser Welt, also nimm es mit.

Ich habe ein Gitter von Blöcken in einem Top-Down-2D-Spiel, das mit Slick geschrieben wurde. Die beste Art, daran zu denken, ist die Pokemon-Welt.

Im Moment rendere ich alle Blöcke auf einer bestimmten Karte, unabhängig davon, ob sie gerade auf dem Bildschirm angezeigt werden oder nicht.

Gibt es einen besseren Weg, dies zu tun? Mein Gedanke war vielleicht, ein Bild aus dem zu erstellen, was ich gerendert hätte, und den Abschnitt zu nehmen, der zum Rendern des Bildschirms passt. Ich weiß nicht, wie ich das machen soll, aber ich wollte die Experten konsultieren, bevor ich mich darauf einließ. Vielen Dank! ;)

BEARBEITEN

Ich dachte nur, ich würde hinzufügen, dass Slick eine Möglichkeit hat, mit Clipping in speziellen Fällen sowie mit dem Ansichtsfenster des Bildschirms umzugehen. Weitere Informationen finden Sie auf der Wiki-Seite .


1
Ja, Sie sollten nur das rendern, was auf dem Bildschirm angezeigt wird. Vielleicht auch außen ein wenig Puffer, damit Sie nicht am Rand flackern, wenn sich der Spieler schnell bewegt. Ich weiß nicht, ob Java / Slick eine eingebaute Möglichkeit bietet, dies zu tun. Ich würde mir vorstellen, dass sie es tun.

Antworten:


11

Eine Möglichkeit, dies zu tun, besteht darin, den Begrenzungsrahmen des Blocks mit dem Begrenzungsrahmen der aktuellen Ansicht zu vergleichen (plus ein wenig zur Sicherheit).

Wenn der Block mit der Ansicht interagiert (entweder vollständig im Inneren oder abgeschnitten), zeichnen Sie ihn. Wenn dies nicht der Fall ist - dh ganz draußen ist, dann zeichne nicht.

Diese Prüfung kann sehr schnell durchgeführt werden - insbesondere in 2D. Sie müssen nicht wissen, wie viel von dem Block sichtbar ist - nur, dass ein Teil davon möglicherweise sichtbar ist.

Wenn die maximale X-Koordinate des Blocks kleiner als die minimale X-Koordinate der Ansicht ist oder die minimale X-Koordinate des Blocks größer als die maximale X-Koordinate der Ansicht ist, ist dieser Block definitiv unsichtbar. Der gleiche Test kann an der Y-Koordinate durchgeführt werden.

Wie Joe in seinem Kommentar hervorhebt, ist in dem von Ihnen verwendeten Framework / den Bibliotheken möglicherweise diese Funktionalität integriert.


2

Mach so etwas:

if (renderX >= 0 && renderY >= 0
    && renderX <= container.getWidth() && renderY <= container.getWidth()) {
    //Render
}

Es muss für jedes Objekt benutzerdefiniert sein, da jedes Objekt eine andere Größe hat. Ich rendere jede Gruppe von Komponenten separat. Wenn Sie TiLeD verwenden, ist hier ein schöner Code, den ich erstellt habe:

TiledMap map = mapComp.getMap();

    //Render positions as integers
    int renderX = (int) renderPos.getX();
    int renderY = (int) renderPos.getY();

    //Render offset for map
    int xRenderOffset = renderX % 32;
    int yRenderOffset = renderY % 32;

    //Get the first tile to be rendered
    int firstTileX = (int) -renderX / 32;
    int firstTileY = (int) -renderY / 32;

    //Render tiles only if their indices are greater than 0
    if (firstTileX < 0) {
        xRenderOffset += Math.abs(firstTileX) * 32;
        firstTileX = 0;
    }

    if (firstTileY < 0) {
        yRenderOffset += Math.abs(firstTileY) * 32;
        firstTileY = 0;
    }

    //Get the last tile to be rendered
    int lastTileX = firstTileX + (client.getContainer().getWidth() / 32) + 1;
    int lastTileY = firstTileY + (client.getContainer().getHeight() / 32) + 2;

    //Verify that the last tile is valid
    if (lastTileX > 127) {
        lastTileX = 127;
    }

    if (lastTileY > 127) {
        lastTileY = 127;
    }

    //Check if the map will be visible on the screen
    if (lastTileX >= 0 && lastTileY >= 0) {
        map.render(xRenderOffset, yRenderOffset, firstTileX, firstTileY, lastTileX, lastTileY, 0, true);
        map.render(xRenderOffset, yRenderOffset, firstTileX, firstTileY, lastTileX, lastTileY, 1, true);
        map.render(xRenderOffset, yRenderOffset, firstTileX, firstTileY, lastTileX, lastTileY, 2, true);
        map.render(xRenderOffset, yRenderOffset, firstTileX, firstTileY, lastTileX, lastTileY, 3, true);
    }

32 ist Ihre Kachelbreite und 127 ist Ihre Kartengröße - 1.


Nettes Stück Code, aber ich gehe in diesem Fall nicht mit TiLeD. Ich habe mich entschlossen, meine eigene Art des Umgangs mit Karten zu entwickeln, die mir sehr gut gefallen. Es basiert auf der Textdatei-Implementierung des von Microsoft herausgegebenen Platformer-Starter-Kits. +1. :)
Andy

1

Wenn Ihre Blöcke eine einheitliche Größe haben (wie dies bei den klassischen Pokemon-Spielen der Fall ist) und in einem 2D-Array gespeichert sind, ist es wahrscheinlich am besten, nur for-Schleifen zu erstellen, etwa so:

int startX = playerX - halfWidth;
int startY = playerY - halfHeight;

for( int x = startX , maxX = playerX + halfWidth; x < maxX; ++x )
{
    for( int y = startY , maxY = playerY + halfHeight; y < maxY; ++y )
    {
        DrawBlock( x - startX, y - startY, tiles[x][y] );
    }
}

Dabei sind halfWidth und halfHeight die Hälfte der Breite bzw. Höhe des Bildschirms. Dadurch werden die Aufrufe von DrawBlock auf nur die sichtbaren reduziert. Wenn Sie durch das Raster scrollen, können Sie in jede Richtung eine zusätzliche Kachel zeichnen und Ihre animierten Versatzwerte nach Bedarf zu den DrawBlock-Parametern hinzufügen.

Es sollte erwähnt werden, dass diese Methode die Methode zum Ausschneiden ergänzt, mit der Sie in Ihrer Bearbeitung verknüpft haben. Mit der hier vorgestellten Methode wäre das Ausschneiden hilfreich, wenn Ihre Blöcke nicht den gesamten Bildschirm einnehmen sollten (z. B. gibt es einen Rand um sie herum für eine Benutzeroberfläche), um zu verhindern, dass zusätzliche Blöcke, die für Animationszwecke gezeichnet werden, von über andere Elemente gezogen werden. In diesem Fall würden Sie Ihren Beschneidungsbereich so einstellen, dass er genau der Bereich ist, in dem Ihr Raster angezeigt werden soll, und dann nur die erforderlichen minimalen Blöcke zeichnen.


gute empfehlung! Es scheint jedoch, dass Slick diese Dinge im Hintergrund elegant handhabt, sodass das Hinzufügen meines eigenen Codes zum Umgang mit Clipping nicht erforderlich ist.
Andy
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.