Drinnen und draußen

Der folgende Code zeigt Ihnen, wie Sie Innen- und Außenlevels verbinden können. Das Spiel startet in einem Außenlevel und Sie können ein Haus betreten, das als separates Level geladen wird. Natürlich können Sie das Haus wieder verlassen und kehren damit in das Außenlevel zurück, an der Tür des Hauses (nicht am ursprünglichen Startpunkt). Sie sollten für das Außenlevel ein weniger detailliertes Haus nehmen; ich habe in meinem Beispiel das gleiche Haus verwendet.

function main()
{
    level_load (inandout_wmb);
}

action warlock
{
   player = my;
   while (1)
   {
      my.skill1 = 5 * (key_w - key_s) * time; // 5 = forward / backward movement speed
      my.skill2 = 0;
      my.pan += 5 * (key_a - key_d) * time; // 2 = rotation speed
      vec_set (temp, my.x);
      temp.z -= 3000;
      trace_mode = ignore_you + ignore_passable + use_box;
      my.skill3 = -trace (my.x, temp);
      move_mode = ignore_passable;
      ent_move (my.skill1, nullvector); // moves using skill1..3
      if (key_w + key_s > 0) // one of these 2 keys is pressed?
      {
         ent_cycle("walk", my.skill46); // then animate the warlock!
         my.skill46 += 10 * time; // "walk" animation speed
         my.skill46 %= 100; // loop the animation
      }
      else // the player isn't moving?
      {
         ent_cycle("stand", 0); // then set the first "stand" animation frame for it
      }
      camera.x = my.x - 50 * cos(my.pan); // place the camera 50 quants
      camera.y = my.y - 50 * sin(my.pan); // behind the player
      camera.z = my.z + 50; // and higher
      camera.pan = my.pan; // keep the same pan with the player
      camera.tilt = -5; // and look a bit downwards
      wait (1);
   }
}

Die main Funktion lädt das Außenlevel. Die Action für den Spieler erlaubt ihm die Bewegung mit Hilfe der WASD Tasten. Der Bewegungscode beinhaltet auch Gravitation. Falls einer der Bewegungstasten gedrückt ist, wird die “walk” Animation abgespielt, andernfalls die “stand” Animation. Die Kamera wird 50 Quants hinter dem Spieler und 50 Quants oberhalb plaziert, mit der gleichen Ausrichtung und zeigt etwas nach unten.

action door_level1
{
  while (player == null) {wait (1);} // wait until the player is created
  while (vec_dist(player.x, my.x) > 70) {wait (1);} // wait until the player has come closer than 70 quants
  while (key_any == on) {wait (1);} // wait until the player has released the keys
  vec_set (player_coordinates.x, player.x);
  level_load (houselevel_wmb); // load the house level
}

Die obige Action wird der Tür im Außenlevel zugeordnet; sie wartet bis der Spieler existiert und dann bis der Spieler näher als 70 Quants herangekommen ist. Sobald dies geschehen ist warten wir, bis der Spieler die Tasten losläßt, speichern seine Koordinaten und laden das Innenlevel.

action door_level2 // attached to the door in the second level (indoors)
{
    while (player == null) {wait (1);} // wait until the player is created
    while (vec_dist(player.x, my.x) < 80) {wait (1);} // wait until the player has moved away from the door
    while (vec_dist(player.x, my.x) > 70) {wait (1);} // wait until the player has come closer than 70 quants to the door
    while (key_any == on) {wait (1);} // wait until the player has released the keys
    my = null; // make sure that the lines after level_load are executed
    level_load (inandout_wmb); // load the house level
    wait (3);
    player_coordinates.x -= 50; // make sure that the player appears (50 quants + its initial x) away from the door (hysteresis)
    vec_set (player.x, player_coordinates.x);
    player.pan = 180; // rotate the player in the proper direction (with its back to the door)
}

Die zweite Tür schaltet vom Innenlevel zurück ins Außenlevel; diese wartet bis der Spieler existiert und dann bis er sich von der Tür entfernt hat. Diese Zeile ist notwendig, damit der Spieler nicht mehrmals hin und zurück teleportiert wird. Die nächste Zeile wartet, bis der Spieler sich wieder der Tür nähert, weil er das Haus verlassen möchte. Wir warten wieder bis die Tasten losgelassen werden und setzen den “my” Zeiger auf NULL, damit die Zeilen nach level_load auch ausgeführt werden. Wir subtrahieren 50 Quants von den vorher gesicherten Koordinaten, damit der Spieler etwas von der Tür entfernt steht und erzeugen den Spieler an der Position erneut, mit einem geeigneten pan Winkel.

Nun können Sie riesige Welten erstellen und problemlos Innen- und Außenlevels mischen. Und falls Sie Waffen, Items, etc. transportieren möchten, sehen Sie sich den “Levelwechsel” Coe aus AUM 28 an.

Buchstabenrad

Dieser Code kann Ihnen bei High Scores zugute kommen, wenn der Spieler mit einer etwas eleganteren Methode seinen Namen eingeben soll.

var letter_number = 0; // 0 for "A", 1 for "B", ... , 25 for "Z"

text name_txt
{
    font = adventure_font;
    pos_x = 200;
    pos_y = 560;
    layer = 20;
    string = name_str;
    flags = visible;
}

function main()
{
   level_load (lwheel_wmb);
   wait (3);
   camera.x = 40;
   camera.y = -100;
   camera.z = 2100;
   camera.pan = 90;
   camera.tilt = -90;
}

Ich verwende einen gewöhnlichen Text, um den Text am unteren Bildschirmrand einzublenden und eine einfache Main Funktion, die das Level lädt und die Kamera geeignet plaziert.

action rotating_wheel
{
   str_cpy(name_str, ""); // reset name_str;
    while (1)
    {
       if (key_cur == on)
       {
          while (key_cur == on) {wait (1);}
          my.pan += 360 / 26; // add the angle (sector) that is covered by a letter
          letter_number += 1;
       }
       if (key_cul == on)
      {
         while (key_cul == on) {wait (1);}
         my.pan -= 360 / 26; // subtract the angle (sector) that is covered by a letter
         letter_number -= 1;
      }
     letter_number %= 26;
     if ((key_enter == on) || (key_space == on)) // press space or enter to select a letter
     {
        while (key_enter + key_space > 0) {wait (1);} // wait until the keys are released
        str_for_asc(temp_str, letter_number + 65); // add 65 to turn 0 into 65 ("A"), 1 into 66 ("B") and so on
        str_cat (name_str, temp_str);
      }
     name_txt.pos_x = 400 - str_len(name_str) * name_txt.char_x / 2 ; // center the text on the screen
     wait (1);
   }
}

Das Rad ist eine sehr große Entity, auf der die Buchstaben plaziert sind. Wir setzen name_str zurück und falls der Spieler die rechte Pfeiltaste drückt, warten wir bis diese losgelassen wird und drehen das Rad um einen Winkel, der sich durch eine ganze Drehung (360 Grad) dividiert durch die Anzahl der Sektoren (26) ergibt. Die letzte Zeile erhöht letter_number, eine Variable, die den aktuellen Buchstaben angibt. Etwas Ähnliches geschieht, wenn der Spieler die linke Pfeiltaste drückt, allerdings wird letter_number dann verringert.

Die nächste Codezeile stellt sicher, dass letter_number im Zahlbereich zwischen 0 (“A”) und 25 (“Z”) bewegt. Wenn der Spieler Space oder Enter drückt, wird der aktuelle Buchstabe ausgewählt. Wir warten bis die Tasten losgelassen werden und benutzen dann str_for_asc, um letter_number + 65 in ein Zeichen zu konvertieren. Warum geht das auf diese Weise? Nun, falls “A” ausgewählt ist, dann ist letter_number == 0, falls “B” ausgewählt ist, ist die Variable 1 und so weiter. Auf der anderen Seite wissen wir, dass der ASCII Code für “A” gerade 65 ist und “B” hat den Code 66 usw., daher müssen wir einfach 65 zu letter_number addieren, um den korrekten ASCII Code zu ermitteln.

Mit str_cat fügen wir den Buchstaben an name_str an und zentrieren dann den Text in der Bildschirmmitte, indem wir seine Länge und die Breite eines Zeichens berücksichtigen. Die Auflösung ist 800 Pixel in x-Richtung, also müssen wir nur die Hälfte der Textlänge in Pixeln von 800 / 2 = 400 subtrahieren, um das zu erreichen.