In so gut wie jedem Spiel-Code gibt es Funktionen, die nicht jeden Tick feuern dürfen. Eine Schussroutine, die alle drei Frames maximal einen Schuss freigibt. Ein Tasten-Handler, der nicht zehnmal pro Sekunde reagiert, nur weil die Taste lange gedrückt ist. Ein Logger, der nur einmal pro Sekunde Daten schreibt, statt 60-mal.
Mein erster Reflex war, dafür globale Variablen anzulegen. Funktioniert, aber jede Sub schleppt ihren Mini-State im globalen Namespace mit, und Konflikte sind eine Frage der Zeit. STATIC ist die saubere Antwort.
Wie STATIC funktioniert
STATIC deklariert eine Variable innerhalb einer SUB oder FUNCTION, die ihren Wert über Aufrufe hinweg behält. Beim ersten Aufruf wird sie auf 0 (oder den angegebenen Default) initialisiert, danach lebt sie zwischen den Calls weiter, ohne dass sie außerhalb der Sub sichtbar wird.
SUB FireShot()
STATIC INTEGER cooldown
IF cooldown > 0 THEN
INC cooldown, -1
EXIT SUB
END IF
' ... Schuss erzeugen ...
cooldown = 3
END SUB
Drei Frames Cooldown, Code in der einen Sub, kein globales Echo, keine Initialisierung am Programmanfang. Wenn die Sub das erste Mal aufgerufen wird, ist cooldown automatisch 0, und ab da lebt sie da, wo sie hingehört.
Debounce für Tasten
Ein typischer Fall: eine Taste, die einen Toggle umschaltet, soll nicht in jedem Frame umschalten, solange die Taste gehalten wird. Das gleiche Pattern, nur mit dem zustand „gerade gehalten":
SUB CheckMuteKey()
STATIC INTEGER prev_held
IF IsKeyPressed(KEY_M) THEN
IF NOT prev_held THEN
ToggleMute()
END IF
prev_held = 1
ELSE
prev_held = 0
END IF
END SUB
prev_held merkt sich, ob die Taste schon im letzten Frame unten war. Toggle nur am Übergang von „nicht gedrückt" zu „gedrückt". Saubere Edge-Detection ohne globale Hilfsvariable.
Rate-Limit für Logging oder Audio
Wenn etwas pro Sekunde nur einmal passieren soll, statt 60-mal pro Frame, hängt man einen Frame-Counter dran:
SUB LogPerformance()
STATIC INTEGER tick
INC tick
IF tick < 60 THEN EXIT SUB
tick = 0
PRINT "FPS: " + STR$(actual_fps)
END SUB
Dasselbe Muster taugt auch für rhythmische Audio-Trigger oder periodische Updates am HUD. Der eingeschränkte Scope macht das Ganze leicht prüfbar — wenn etwas falsch aussieht, weiß ich, wo der State liegt.
Bei drei oder vier Subs mit eigenem Mini-Cooldown wird der Unterschied zur globalen Variante schnell sichtbar. Mein Code ist seitdem deutlich aufgeräumter, und jede Sub trägt ihren Zustand selbst, statt ihn aus einem globalen Pool zu fischen.