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.