workshop 22

Top  Zurück    Weiter

Globale Variablen. Lokale Variablen.

Wenn Sie den zweiten Workshop (in dem es um Variablen geht) gelesen haben, wundern Sie sich vielleicht, weshalb wir nicht gleich dort globale und lokale Variable behandelt haben. Sind diese Dinge für einen Anfänger so schwer zu verstehen?

Keine Angst, ohne es überhaupt zu wissen, haben Sie nämlich schon die ganze Zeit globale Variablen benutzt. Es war nötig, dass ich zuerst Aktionen und Funktionen erklärte, denn die brauchen wir, um zu verstehen wie lokale Variable funktionieren. Betrachten wir ein Beispiel: Starten Sie SED, öffnen Sie workshop22 und starten Sie variables.c:

w24_01

Sieht wahrlich aus wie eine postapokalyptische Version unseres Planeten! Für´s Level habe ich einen schwarzen, leeren Level genommen und ein Erd-Modell darin plaziert:

///////////////////////////////
#include <acknex.h>
#include <default.c>

///////////////////////////////

var rotation_speed = 0.1;

function mother_earth()
{ 
	while (1)
	{ 
		my.pan += rotation_speed * time_step;
		wait (1); 
	}
}

function main()
{
	vec_set(sky_color,vector(1, 1, 1));	// schwazer Sky
	level_load ("");
	ent_create("earth.mdl", vector(400, 0, 0), mother_earth);
}

Nun, das nenne ich eine nette Skriptdatei! Das Kugel-Modell ändert seinen Pan-Winkel durch Addition von "0.1 * time_step" per Frame, da "rotation_speed" auf 0.1 gesetzt ist. Dabei handelt es sich, wie Sie vermutlich erraten haben, um eine "globale" Variable. Eine Variable, die außerhalb jedweder Aktion oder Funktion definiert ist. Wie ich schon sagte, haben wir, ohne es zu wissen, in allen vorangegangenen Workshops ausschließlich globale Variablen definiert! Starten Sie das Level nun nochmal, holen Sie per [Tab]-Taste die Konsole auf den Bildschirm und tippen Sie die folgende Codezeile ein:

rotation_speed = 5;

Jetzt rotiert die Kugel viel schneller, gell? (Wenn nicht, haben Sie den Code nicht richtig eingegeben). Wir können Die Rotationsgeschwindigkeit über die Konsole steuern, denn die Variable mit dem Namen "rotation_speed" ist ausnahmslos jeder Funktion oder Aktion bekannt; einschließlich der Engine-Funktion, die die Konsole darstellt. So also funktioniert eine "globale" Variable!

Eine "lokale" Variable ist hingegen nur innerhalb der Aktion oder Funktion, die ihre Definition beinhaltet, bekannt. Machen wir unsere globale Variable jetzt mal zu einer lokalen Variablen: schieben Sie die Zeile, die "rotation_speed" definiert in die Aktion namens "mother_earth":

///////////////////////////////
#include <acknex.h>
#include <default.c>
///////////////////////////////

function mother_earth()
{ 
	var rotation_speed = 0.1;
	if (my.y < 0) 
		rotation_speed = 20;
	while (1)
	{ 
		my.pan += rotation_speed * time_step;
		wait (1); 
	}
}

function main()
{
	vec_set(sky_color,vector(1,1,1));	// schwarzer Sky
	level_load ("");
	ent_create("earth.mdl",vector(400,-100,0),mother_earth);
	ent_create("earth.mdl",vector(400,100,0),mother_earth);
}
Nun starten wir das Skript nochmal:

w24_01

Der Planet dreht sich genau wie vorher. Tippen wir nochmal dieselbe Zeile zur Geschwindigkeitsänderung in die Konsole:

rotation_speed = 5;

Diesmal hat sich die Rotationsgeschwindigkeit überhaupt nicht verändert! Die Konsolenfunktion kennt die Variable nicht, denn "rotation_speed" ist jetzt eine lokale Variable und somit nur innerhalb der Aktion namens "mother_earth" bekannt und keine andere Funktion kann auf sie zugreifen.

Wozu sind lokale Variablen denn nun gut? Warum verwenden wir nicht einfach nur globale Variablen? Öffnen und starten Sie variables_2.c:

w24_05

Jetzt haben wir 2 sich drehende Kugeln und sie drehen sich mit unterschiedlicher Geschwindigkeit! Wenn wir auf den Code schauen, stellen wir als erstes fest, daß wir beide Kugeln in der Main-Funktion erstellt haben und beide verwenden dieselbe Aktion:

///////////////////////////////
#include <acknex.h>
#include <default.c>
///////////////////////////////

function mother_earth()
{ 
	var rotation_speed = 0.1;
	if (my.y < 0) 
		rotation_speed = 20;
	while (1)
	{ 
		my.pan += rotation_speed * time_step;
		wait (1); 
	}
}

function main()
{
	vec_set(sky_color,vector(1,1,1));	// schwarzer Sky
	level_load ("");
	wait (2); // warte, bis das Level geladen ist
	ent_create("earth.mdl",vector(400,-100,0),mother_earth);
	ent_create("earth.mdl",vector(400,100,0),mother_earth);
} 

Wir haben in der Funktion mother_earth eine lokale Variable namens rotation_speed definiert. Für die linke Kugel hat rotation_speed einen Wert von 0.1 und für die Rechte hat dieselbe Variable einen Wert von 20. Unsere Aktion mother_earth wird zwei mal aufgerufen: einmal von der rechten und einmal von der linken Kugel. So laufen gleichzeitig zwei verschiedene, voneinander unabhängige Kopien von mother_earth und jede Kopie benutz ihren eigenen Satz an lokalen Variablen. Werfen wir einen Blick auf den Anfang der Aktion:

action mother_earth()
{
  var rotation_speed = 0.1;
  if (my.y < 0)
  rotation_speed = 20;

Die rechte Kugel wurde bei y = -100 plaziert, also ist für diese der Vergleich "if (my.y < 0)" wahr und rotation_speed wird auf 20 gesetzt. Für die linke Kugel ist der Vergleich falsch und rotation_speed wird nicht verändert, sondern bleibt weiterhin 0.1. Diese beiden lokalen Variablen kommen sich in keinster Weise in die Quere und das obwohl sie denselben Namen haben und in derselben Funktion stehen.

Verstehen Sie mich jetzt nicht falsch, auch ich mag globale Variablen! Sie sind immer dann nötig, wenn Daten für alle Aktionen oder Funktionen zur Verfügung stehen müssen! Sie wollen, dass sämtliche Monster Ihres Games einen kleinen Tanz aufführen wenn der Player stirbt? Dann sollten Sie die Gesundheit des Players besser in einer globalen Variablen ausdrücken. Die Monster werden nämlich deren Wert aus ihren eigenen Aktionen oder Funktionen heraus überprüfen wollen. Auf der anderen Seite werden Sie für all die Anweisungen, die nur innerhalb einer Funktion bzw. Aktion stattfinden, lokale Variable verwenden wollen: Animation, Bewegung usw.


Weiter: Der Knochensammler