[TUT] Game development 08 - Het renderen van het level

This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

  • Dit is een vervolg op: [TUT] Game development 07 - De empty en grass tile

    Hallo ICTScripters,

    We zijn dan eindelijk op het punt gekomen waar ik denk de trouwen volgers wel op hebben gewacht. In deze tutorial gaan we een random level maken en genereren op het scherm! Maar voor we beginnen gaan we snel inventariseren wat we hebben gemaakt in de vorige 7 tutorials:
    1. Een basis omgeving waarin de client wordt gestart, geupdate en gerenderd.
    2. Een klasse om het scherm te tonen.
    3. Het laden van Spritesheets en Sprites.
    4. Het laden van toetsenbord events en het gebruiken hiervan.
    5. Een primaire level en tile klasse met een grass en lege tile.
    Best veel al dus, daarom is het nu tijd om al deze componenten te gaan gebruiken en daadwerkelijk een level te genereren en renderen. Maak daarom in de package level een nieuwe klasse aan met RandomLevel en vul deze met de volgende code:

    Source Code

    1. public class RandomLevel extends Level {
    2. private static final Random random = new Random();
    3. public RandomLevel(int width, int height) {
    4. super(width, height);
    5. }
    6. @Override
    7. protected void generateLevel() {
    8. for (int y = 0; y < height; y++) {
    9. for (int x = 0; x < width; x++) {
    10. // Generate random tiles between 0 to 3
    11. tiles[x + y * width] = random.nextInt(4);
    12. }
    13. }
    14. }
    15. }
    Display All


    Deze relatief simpele code vult de tiles van het level met een random nummer van 0 tot 3, waarbij het nummer staat voor een Tile. Hiervoor gebruiken we de door Java geschreven Random klasse.

    Momenteel hebben wij nu dus een level die random gegenereerd wordt alleen wordt deze nog niet gerenderd op het scherm. Open daarom de Level klasse en maak daar een nieuwe getTile methoden aan onder de render() methode. Hierin bepalen wij welk tile nummer welke tile bevat:

    Source Code

    1. public Tile getTile(int x, int y) {
    2. // Zorgt ervoor dat alle tiles buiten het level leeg zijn.
    3. if (x < 0 || y < 0 || x >= width || y >= height) return Tile.empty;
    4. // // Stuur een grass tile terug wanneer het tile nummer 0 is.
    5. if (tiles[x + y * width] == 0) return Tile.grass;
    6. // Zorgt ervoor dat er standaard een lege tile wordt terug
    7. // gestuurd wanneer het tile nummer niet bestaat.
    8. return Tile.empty;
    9. }


    Nu moeten we alleen nog de render() methoden aanpassen in de Level klasse om daadwerkelijk alles op het scherm te tonen. Hiervoor gaan we eerst corner pins maken, hiermee definiëren we eigenlijk een viewport binnen het scherm. Om een goed voorbeeld te geven waarom dit nodig is: Stel je wilt een interface maken met aan de rechter kant je inventory zoals Runescape het had, dan willen wij niet dat er meer geladen wordt dan nodig is.

    [Blocked Image: https://raw.githubusercontent.com/michaelbeers/Elysium/master/Afbeeldingen/08_01.jpg]

    Source Code

    1. public void render(int xScroll, int yScroll, Screen screen) {
    2. screen.setOffset(xScroll, yScroll);
    3. int x0 = xScroll >> 4;
    4. int x1 = (xScroll + screen.width) >> 4;
    5. int y0 = yScroll >> 4;
    6. int y1 = (yScroll + screen.height) >> 4;
    7. }


    Waar staat die >> 4 voor?
    >> dit is een binaire operator om een getal te delen wat er dus eigenlijk staat is: xScroll / 1111 of xScroll / 16. We gebruiken dit om beter om te gaan met het geheugen van de client want in een game is het geheugen gebruik toch wel een van de dingen waar je zo efficiënt mogelijk mee moet omgaan, omdat we te maken hebben met soms wel 500 verschillende objecten op je scherm die allemaal stuk voor gerenderd moeten worden.

    Nu rest ons alleen nog het ophalen van de tiles d.m.v. de getTile() methoden die wij hebben aangemaakt

    Source Code

    1. public void render(int xScroll, int yScroll, Screen screen) {
    2. screen.setOffset(xScroll, yScroll);
    3. int x0 = xScroll >> 4;
    4. int x1 = (xScroll + screen.width) >> 4;
    5. int y0 = yScroll >> 4;
    6. int y1 = (yScroll + screen.height) >> 4;
    7. for (int y = y0; y < y1; y++) {
    8. for (int x = x0; x < x1; x++) {
    9. getTile(x, y).render(x, y, screen);
    10. }
    11. }
    12. }
    Display All


    Tot slot gaan we alleen nog even de Game klasse aanpassen om het level te initialiseren.
    Vervang daarom het volgende:

    Source Code

    1. private Thread thread;
    2. private JFrame frame;
    3. private Keyboard key;
    4. private Level level;
    5. private boolean running = false;

    Source Code

    1. public Game() {
    2. Dimension size = new Dimension(width * scale, height * scale);
    3. setPreferredSize(size);
    4. // Initialize all the client components.
    5. this.screen = new Screen(width, height);
    6. this.frame = new JFrame();
    7. this.key = new Keyboard();
    8. this.level = new RandomLevel(64,64);
    9. // Initialize all the client events.
    10. addKeyListener(key);
    11. }
    Display All

    Source Code

    1. public void render() {
    2. BufferStrategy bs = getBufferStrategy();
    3. if (bs == null) {
    4. createBufferStrategy(3);
    5. return;
    6. }
    7. screen.clear();
    8. level.render(x, y, screen);
    9. for (int i = 0; i < pixels.length; i++) {
    10. pixels[i] = screen.pixels[i];
    11. }
    12. Graphics g = bs.getDrawGraphics();
    13. g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
    14. g.dispose();
    15. bs.show();
    16. }
    Display All

    Wanneer je nu de client opstart zul je zien dat het level gerenderd wordt alleen heel erg klein!

    [Blocked Image: https://raw.githubusercontent.com/michaelbeers/Elysium/master/Afbeeldingen/08_02.jpg]

    Dit komt doordat we momenteel de tiles delen door 16 waardoor we elke keer een tile van 1 pixel krijgen. Om dit op te lossen gaan we de pixels van elke tiles vermenigvuldigen met 16. Open daarom de GrassTile en EmptyTile en vermenigvuldig de x- en y coordinaten met 16.

    Source Code

    1. screen.renderTile(x << 4, y << 4, this);


    [Blocked Image: https://raw.githubusercontent.com/michaelbeers/Elysium/master/Afbeeldingen/08_03.jpg]

    Dit was alweer de 8e tutorial. In de volgende tutorial gaan we de zwarte randen repareren die je nu nog tijdens het renderen ziet en gaan we beginnen met entities. Wat een entity is wordt allemaal uitgelegd in de 9e tutorial ;). Inmiddels de github repository weer geupdate en kun je de huidige code downloaden ter vergelijking etc.

    Github EP 08 - Het renderen van het level

    I hope you enjoy!

    Met vriendelijke groet,

    Michael Beers
    Dit was mijn spreekbeurt, zijn er nog vragen?

    1,314 times read

Comments 0