"Jetzt kaufen!"

Ihr Spiel ist fertig und Sie haben eine großartige Demo auf Ihre Website gestellt. Aber haben Sie nicht noch etwas vergessen? Genau, Sie sollten den “Jetzt kaufen!” Knopf in Ihre Demo einbauen.

Dies ist eine dieser seltenen Situationen, in denen wir das SDK benutzen; keine Angst, ich habe die DLL mitgeliefert, also müssen Sie nicht eine Zeiel Code schreiben, wenn Sie nicht wollen. Wenn Sie sich fragen, wie man das SDK benutzt, sehen Sie in Aum 31 nach – dort lernen Sie eine neue DLL von Grund auf zu erstellen.

Schauen wir uns die cpp Datei an:

// buynow.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"
#include "a5dll.h"
#include "a5funcs.h"

int nSuccess;

BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    return TRUE;
}

DLLFUNC fixed Exequte(long command)
{
   fixed *temp = (fixed *)a5dll_getwdlobj("temp");
   A4_STRING *my_command = (A4_STRING *)command;
   nSuccess = WinExec (my_command -> chars, SW_MAXIMIZE);
   return INT2FIX(nSuccess);
}

Die roten Zeilen sind von mir, der Rest des Codes stammt vom MS VC++ 6.0 Wizard. Meine “Exequte” Funktion nimmt sich die vordefinierte “temp” Variable (lesen Sie in Aum 31 nach, warum das notwendig ist) und holt sich einen Pointer namens my_command auf den String, welcher der Funktion übergeben wurde. Schließlich verwenden wir WinExec um den String auszuführen und geben das Ergebnis der Operation zurück. Die variable nSuccess liefert einen Wert größer als 31 genau dann, wenn WinExec erfolgreich ist.

Einige fortgeschrittene Programmierer möchten vielleicht CreateProcess benutzen, weil WinExec veraltet ist, aber es funktioniert hier wunderbar und (dies ist ein Geheimnis, von dem sie nicht wollen, dass es publik wird) WinExec ruft CreateProcess auf. Schauen wir uns das Skript an:

var success = 0;
var_nsave dll_handle;

text error_txt
{
   pos_x = 200;
   pos_y = 200;
   layer = 30;
   font = std_font;
   string = "Error while trying to run the command!";
}

panel outro_pan // exit panel
{
   bmap = outro_tga;
   layer = 20;
   pos_x = 120;
   pos_y = 100;
   button = 133, 100, buyme2_tga, buyme1_tga, buyme2_tga, buy_now, null, null;
   button = 133, 180, nothanks2_tga, nothanks1_tga, nothanks2_tga, shut_down, null, null;
   flags = overlay, refresh, visible;
}

Ich habe einen Text definiert, der angezeigt wird sollte WinExec scheitern. “Jetzt laufen!” sollte einfach ein Knopf auf einem Panel sein, der die Funktion buy_now aufruft, wenn er angeklickt wird:

function buy_now()
{
   dll_handle = dll_open ("buynow.dll");
   success = Exequte("C:\\Program Files\\Internet Explorer\\iexplore.exe www.randombyte.com");
   if (success <= 31) // WinExec failed?
   {
      error_txt.visible = on; // show an error message
   }
   dll_close (dll_handle);
}

function shut_down()
{
   exit;
}

Die Funktion oben öffnet die DLL und startet den Internet Explorer mit meiner Seite als Parameter. Beachten Sie bitte die C-typische Notation “\\” für Pfadangaben. Falls WinExec scheitert (success <= 31) zeigen wir die Fehlermeldung an. Drückt der Spieler den “Nein Danke!” Knopf, beendet die Funktion shut_down die Engine.

Das ist alles! Sie sollten outro_pan einschalten, wenn der potentielle Kunde versucht, das Spiel zu beenden. Eine Sache noch: mit der DLL können Sie jede Anwendung öffnen, zum Beispiel...

success = Exequte("C:\\Program Files\\Microsoft Office\\Office10\\winword.exe office.wdl");

Es klappt! Diese Zeile startet Microsoft Word und öffnet die office.wdl zum Bearbeiten.

 

Leuchtkörper

Ich muß zugeben, dass ein düsterer Level in den meisten Fällen besser aussieht als einer, der überall total ausgeleuchtet ist. Sie können die Dramaturgie noch dadurch steigern, indem ein kleiner Bereich des Levels komplett in schwarz gehalten wird und indem Sie dem Spieler einige Leuchtkörper mitgeben, die für einige Sekunden Licht erzeugen. Wie das geht, werden wir uns jetzt ansehen.

starter init_flares()
{
    while (player == null) {wait (1);}
    while (1)
    {
       if (key_f == 1)
       {
            while (key_f == 1) {wait (1);}
            ent_create (flare_pcx, player.x, create_flare);
       }
       sleep (0.1);
    }
}

Die Funktion oben läuft von selbst, wenn das Spiel gestartet wird; sie wartet bis der Spieler existiert und erzeugt dann einen Leuchtkörper jedesmal, wenn die “F” Taste gedrückt wird. Die letzte Codezeile läßt den Code für 100 ms pausieren, so dass nicht mehr als 10 Leuchtkörper pro Sekunde erzeugt werden können, was gut für Ihre Tastatur ist.

function create_flare()
{
    my.burn_time = 10; // this flare lasts for 10 seconds
    my.passable = on;
    my.flare = on;
    my.ambient = 100;
    my.pan = camera.pan;
    my.tilt = camera.tilt;
    my.enable_entity = on;
    my.enable_impact = on;
    my.enable_block = on;
    my.event = show_flare;

Jeder Leuchtkörper wird für 10 Sekunden brennen; burn_time ist ein anderer Name für skill20. Das Sprite für den Leuchtkörper ist passierbar wenn es erzeugt wird, hat das flare Flag gesetzt und einen Ambient von 100. Der Leuchtkörper übernimmt den Pan und Tilt Winkel von der Kamera und reagiert auf Kollision (event_impact) mit anderen Entities und Level Blocks. Die Event Funktion ist show_flare.

    while (my.skill10 == 0)
   {
      if (vec_dist (my.x, player.x) > 50) {my.passable = off;}
      my.skill1 = 50 * time;
      my.skill2 = 0;
      if (my.skill40 < 100)
      {
           my.skill3 = 0;
      }
      else
      {
           my.skill3 = - 5 * (my.skill40 / 100) * time;
      }
      move_mode = ignore_you + ignore_passable;
      my.skill30 = ent_move (my.skill1, nullvector); // get the distance that was covered this frame in skill30
      my.skill40 += my.skill30; // store the distance covered so far in skill40
      wait (1);
   }
}

Der Leuchtkörper bewegt sich bis sein skill10 auf einen Wert ungleich 0 gesetzt wird und verliert das passable Flag sobald der Abstand zur erzeugenden Entity (dem Spieler) größer ist als 50 Quants. Das Sprite bewegt sich mit einer Geschwindigkeit von 50 * time pro Frame; diese Bewegung bezieht Schwerkraft (negative z-Geschwindigkeit in skill3) mit ein, wenn mindestens 100 Quants zurückgelegt wurden. Schauen Sie sich das Bild an, um zu sehen was ich meine.

Der Leuchtkörper ignoriert passierbare Entities, die im Weg sind (z.B. Wasser). Die Distanz, die pro Frame zurückgelegt wurde wird in skill30 gespeichert, die Gesamtstrecke in skill40. Ist letzterer Wert größer als 100 Quants, verringern wir die Höhe des Sprites. Was geschieht, wenn der Leuchtkörper auf etwas trifft? Die show_flare Event Funktion wird starten:

function show_flare()
{
    my.skill10 = 1; // stop moving
    my.passable = on; // become passable
    while (my.burn_time > 0)
    {
       my.lightred = 255;
       my.lightgreen = 200 + random(55);
       my.lightblue = 230;
       my.lightrange = 200 + random(50);
       my.scale_x = 0.9 + random(1) / 10; // scale = 0.9 to 1
       my.scale_y = my.scale_x;
       my.scale_z = my.scale_x;
       my.burn_time -= time / 16;
       wait (1);
    }

Sobald der Leuchtkörper einen Level Block oder eine andere Entity trifft, wird sein skill10 auf 1 gesetzt; auf diese Weise beendet sich die Schleife in der obigen Funktion und das Sprite stoppt die Bewegung. Wir machen den Leuchtkörper passierbar, damit er dem Spieler nicht im Weg ist und lassen ihn dann ein dynamisches weißes Licht erzeugen, mit leichten Variationen bezüglich Reichweite und Farbe. Die Größe des Sprites ändert sich von 0,9 auf 1 und wir ziehen pro Sekunde “1” von der burn_time ab. Ich ändere auch den scale_z Wert, also könnte man auch ein 3D Model für den Leuchtköprer benutzen.

    while (my.scale_x > 0.1)
    {
       my.scale_x -= 0.1 * time;
       my.scale_y = my.scale_x;
       my.scale_z = my.scale_x;
       my.lightrange -= 3 * time;
       wait (1);
    }
    ent_remove (me);
}

Diese neue Schleife beginnt, wenn burn_time kleiner als 0 ist. Die Größe des Sprites und die Lightrange werden verringert bis scale_x kleiner ist als 0,1, dann wird es entfernt. Experimentieren Sie auch mit anderen Sprites, Farben und Reichweiten für Ihre Leuchtkörper!