Aaron Fischer Ingenieur, Vater, Heimwerker, Problemlöser

15 Dezember, 2009

Tag 16: Farben und Interaktion

TL;DR:

So wie die Landschaft jetzt ist, sieht sie noch nicht sehr einladend aus. Wir brauchen also noch etwas Farbe. Was momentan auch noch etwas schlecht gelöst ist, ist die Tatsache, dass wir den Landschaftsgenerator nicht richtig testen können, da wir jedes Mal das Programm aufrufen und mit STRG + C wieder schließen müssen. Hier wollen wir uns auch etwas mehr Komfort gönnen.

Gehen wir zuerst an die Farben, dies gestaltet sich recht einfach. Da wir die Y-Werte der Landschaft ja schon haben, müssen wir nur in verschiedenen Abschnitten verschiedenfarbige Striche zeichnen. Ich habe mich für eine grüne Landschaft entschieden, eine Schneelandschaft (passend zur Jahreszeit!) wäre natürlich auch denkbar.

void drawScreen() {
  Uint32 sky = SDL_MapRGB(screen->format, 186, 215, 217);
  Uint32 green = SDL_MapRGB(screen->format, 101, 200, 21);
  Uint32 darkGreen = SDL_MapRGB(screen->format, 52, 99, 14);
  Uint32 ground = SDL_MapRGB(screen->format, 124, 88, 10);

  for (int x=0; x<SCREEN_WIDTH; x++) {
    int y = terrain[x];

    drawLine(x, 0, x, y, sky);
    if (y <= SCREEN_HEIGHT-15) drawLine(x, y, x, y+15, green);
    if (y <= SCREEN_HEIGHT-20) drawLine(x, y+15, x, y+20, darkGreen);
    if (y <= SCREEN_HEIGHT-21) drawLine(x, y+20, x, SCREEN_HEIGHT, ground);
  }
}

Es werden zuerst ein paar Farben für den Himmel, die Grasnarbe und das Erdreich erzeugt. Dies wäre natürlich außerhalb der drawScreen() Funktion besser aufgehoben, doch zur Übersicht habe ich es noch in der Funktion gelassen. Darunter haben wir die gleiche for-Schleife wie zuvor, doch nun zeichnen wir vier separate Linien. Zuerst der Himmel, dann die beiden Grüntöne und dann den Rest in braun.

Hier könnte man nun entweder noch weitere Abstufungen einfügen (beispielsweise am Himmel oder im Erdreich), oder aber andere Elemente einbauen. Man könnte z. B. mit ein paar Kreisen Wolken in den Hintergrund zeichnen, die langsam vorbeiziehen oder kleine Maulwurfgänge in die Erde oder einfach nur ein Muster.

Eine weitere Verbesserung wäre die Grasnarbe, hier könnte man einzelne Grashalme einzeichnen, in dem man bei jedem X-Wert auf Y-Höhe eine zufällig lange Linie zeichnen würde. Der Zufallswerte sollte dann natürlich zwischen ca. 3 und 10 liegen, sonst würden die Proportionen nicht mehr stimmen. Wer sich also hier austoben möchte, nur zu!

eingefärbte Landschaft

Weiter geht es mit der versprochenen Interaktion. Wir wollen mit einem Tastendruck neue Landschaften generieren. Dies ist nicht sehr schwer, da wir das Generieren der Landschaft schon in einer Funktion ausgelagert haben. Zuerst wieder der Programmcode:

  // the main game loop
  while (gameRunning == true) {
    // Check for events
    if (SDL_PollEvent(&event)) {
      // Make it possible to close the game window
      if (event.type == SDL_QUIT) gameRunning = false;

      // Keyboard interaction
      if (event.type == SDL_KEYDOWN) {
        switch (event.key.keysym.sym) {
          case SDLK_RETURN:
            free(terrain);
            terrain = generateTerrain(150.0, 180.0);
            printf("New terrain generated.\n");
            break;
          case SDLK_ESCAPE:
          case SDLK_F10:
            gameRunning = false;
            break;
          default:
            break;
        }
      }
    }

Einiges davon ist ja schon bekannt. Wir haben ja bereits den SDL_QUIT Event abgefangen, um das Programm sauber zu beenden, wenn jemand das X des Fensters drückt oder das Programm mit STRG + C beendet. Nun wollen wir uns den SDL_KEYDOWN Event etwas genauer anschauen. Dieser wird immer ausgelöst, wenn der Benutzer eine Taste nach unten drückt, genau das was wir brauchen. Über event.key.keysym.sym erhalten wir die Taste, die gedrückt wurde.

Wird die Taste SDLK_RETURN gedrückt (also die Entertaste), wollen wir eine neue Landschaft generieren. Hierzu geben wir den reservierten Speicher für die Landschaft wieder frei und generieren eine neue. Da die drawScreen() Funktion auf diese zugreift, müssen wir hier nicht mehr machen.

Um das Programm beenden zu können, definieren wir die Tasten ESC und F10 (wie in vielen Spielen üblich). Wenn diese gedrückt wird, setzen wir wieder gameRunning auf false, um aus dem Game Loop auszusteigen.

Übermorgen bringen wir etwas Ordnung in unser Spiel. Wir werden ein Hauptmenü erstellen und uns mit Game States beschäftigen. Freut euch drauf.