COLLISION

Aus C64-Wiki
Wechseln zu: Navigation, Suche
COLLISION
Format: COLLISION <Kollisionsquelle> [,<Zeilennummer>]
Parameter
<Kollisionsquelle>: numerischer Ausdruck im Wertebereich von 1 bis 3
<Zeilennummer>: numerischer Ausdruck im Wertebereich von 0 bis 65535
Einordnung
Typ: Anweisung
Kontext: Sprites
Aufgabe: Kollisionsbehandlungsroutine aktivieren oder deaktivieren
Abkürzung: coL
Verwandte Befehle
BUMP, PEN, TRAP

Anmerkung: Dieser Artikel beschreibt den BASIC-Befehl COLLISION ab Commodore BASIC V7.0 oder höher.


Die Anweisung COLLISION dient dazu, Unterprogramme zur Kollisionsbehandlung festzulegen oder die Kollisionsbehandlung wieder abzuschalten.

Die Anweisung kennt folgende 2 Parameter:

  • <Kollisionsquelle>: gibt an, welche Kollisionsquelle abgefangen wird. Folgende Werte sind erlaubt:
1: Sprite-Sprite-Kollision
2: Sprite-Bildschirm-Kollision
3: Lightpen-Impuls
Andere Werte führen zu einem ?ILLEGAL QUANTITY ERROR.
  • <Zeilennummer>: die Zeilennummer, an der die Kollisionsbehandlungsroutine beginnt. Erlaubt sind die Werte von 0 bis 65535, auch wenn Werte ab 64000 unsinnig sind, da eine Programmzeile maximal mit Zeilennummer 63999 angelegt werden kann. Fehlt der Parameter, so wird die Kollisionsbehandlung für die angegebene Quelle abgeschaltet. Obwohl beliebige numerische Ausdrücke erlaubt sind, sollte immer eine Konstante als Zeilennummer angegeben werden, da bei einem RENUMBER-Aufruf nur solche berücksichtigt und automatisch anpasst werden.

Tritt das angegebene Kollisionsereignis auf, so wird der augenblicklich ausgeführte BASIC-Befehl noch beendet und dann zur festgelegten Zeilennummer verzweigt. Existiert das Sprungziel nicht, wird die Fehlermeldung ?UNDEF'D STATEMENT ERROR IN <Zeilennummer> ausgegeben, wobei <Zeilennummer> die Zeile des zuletzt ausgeführten Befehls meint.
Treten während der Abarbeitung der Kollisionsbehandlungsroutine weitere Kollisionsereignisse auf, werden diese bis zur Beendigung der Routine zurückgestellt. Bei mehreren gleichzeitigen Unterbrechungsanforderungen werden diese nacheinander, aufsteigend nach Nummer der Kollisionsquelle, aufgerufen.

Anmerkungen:

  • Um die Unterbrechungsanforderungen schnell abzuarbeiten, sollten die Routinen möglichst am Anfang des Programms stehen. Ebenso sollten sie möglichst geschwindigkeitsoptimiert programmiert sein.
  • Mit hoher Wahrscheinlichkeit wird während der Abarbeitung der Kollisionsbehandlungsroutine die Unterbrechungsanforderung erneut ausgelöst. Dies ist zu berücksichtigen, um mehrfaches Abarbeiten derselben Kollision zu verhindern.
  • Beim Abschalten einer Kollisionsbehandlungsroutine wird die Registrierung neuer Unterbrechungsanforderungen der passenden Quelle abgeschaltet und zusätzlich (eigentlich unnötigerweise) das Sprungziel auf 0 gesetzt. Tritt nun während des Abschaltens das passende Kollisionsereignis auf, wird nach Abschluss des COLLISION-Befehls trotzdem noch die Kollisionsbehandlung aufgerufen, aber mit Zeilennummer 0. Existiert diese nicht, kommt es zu einem ?UNDEF'D STATEMENT ERROR IN <Zeilennummer>, ansonsten, falls dieser Fall nicht abgefangen wird, zu auf den ersten Blick unerklärlichen Fehlern im Programmablauf. Einige Möglichkeiten, diesen Bug zu umgehen, sind:
  1. Vor Abschalten der Kollisionsbehandlung sicherstellen, dass keine entsprechenden Unterbrechungsanforderungen mehr ausgelöst werden (z.B. durch Abschalten der Sprites).
  2. Abfangen des ?UNDEF'D STATEMENT ERROR durch eine passende TRAP-Routine.
  3. Das Programm mit Zeilennummer 0 beginnen und dort eine Wächtervariable überprüfen:
    0 IF XX THEN RETURN:ELSE XX=1:GOTO 1000
  • Wird ein Programm mittels RUN/STOP -Taste oder dem Befehl STOP unterbrochen und dann wieder fortgesetzt, werden alle Kollisionsabfragen abgeschaltet.
  • COLLISION darf auch im Direktmodus aufgerufen werden, hat dann aber keinen Effekt.

Interna[Bearbeiten]

COLLISION verwendet folgende Adressen im RAM:

4726 ($1276) Flag für Sprite-Sprite-Kollision
4727 ($1277) Flag für Sprite-Bildschirm-Kollision
4728 ($1278) Flag für Lightpen-Impuls
4729-4731 ($1279-$127B) Sprungziele Lowbyte
4732-4734 ($127C-$127E) Sprungziele Highbyte
4735 ($127F) Bitmaske für Kollisionsquelle

Im Hauptrasterzeilen-IRQ wird das IRQ-Register des VIC (Register 25, Adresse $D019) ausgelesen und für jede aktive Interruptquelle, bei der das passende Bit in Adresse 4735 ($127F) gesetzt ist, das entsprechende Flag auf 255 ($FF) gesetzt.

In der BASIC-Hauptschleife wird vor dem Einlesen des nächsten BASIC-Befehls überprüft, ob eines der 3 Kollisionsflags gesetzt ist. Falls ja, wird das Kollisionsflag auf 0 gesetzt, Bit 7 der Bitmaske in 4735 ($127F) gesetzt, die Kollisionsbehandlungsroutine wie ein BASIC-Unterprogramm aufgerufen und anschließend Bit 7 der Bitmaske wieder gelöscht.

Beispiele[Bearbeiten]

Einfach[Bearbeiten]

100 COLLISION 1,1000

Das Programm verzweigt zur Zeile 1000, sobald mindestens 2 Sprites miteinander kollidieren.

200 COLLISION 3

Schaltet die Behandlung von Lightpen-Impulsen ab.

Komplex[Bearbeiten]

Ein kleines Spiel: Manövriere das "Raumschiff" (das gedrehte Quadrat) durch die sich bewegenden Bälle. Das Programm ist ähnlich dem Beispiel bei BUMP, verwendet aber COLLISION zusätzlich zu BUMP.

0 IF XX THEN RETURN: ELSE XX=1:GOTO 150: REM BEI XX<>0 UNERWUENSCHTE KOLLISIONSBEHANDLUNG
20 B=BUMP(2): IF B=0 THEN RETURN: REM BEI FEHLALARM SOFORT ZURUECK
30 DO
40 FOR I=1 TO 7
50 IF B AND BM(I) THEN BEGIN
60 Y=RSPPOS(I,1): IF Y<99 THEN MOVSPR I,180#SP(I): MOVSPR I,+0,60: ELSE MOVSPR I,0#SP(I): MOVSPR I,+0,218
70 BEND
80 NEXT
90 GET K$: IN=INSTR(I$,K$): IF IN THEN MOVSPR 8,-(DX(IN)),-(DY(IN)): IF RSPPOS(8,0)<24 THEN GS=2: EXIT
100 B=BUMP(2) AND NOT B: REM NUR NEUE SPRITE-KOLLISIONEN BERUECKSICHTIGEN
110 LOOP WHILE B
120 RETURN
130 GS=1: REM GAMESTATUS = GAME OVER
140 RETURN
150 REM SPRITES UND VARIABLEN INITIALISIEREN
155 XX=1
160 GRAPHIC 1,1: CIRCLE 1,12,10,5: PAINT 1,12,10: SSHAPE S$,0,0,23,20
170 BOX 1,27,5,37,15,45: SSHAPE R$,24,0,47,20: SPRSAV R$,8
180 I$="{LINKS}{RECHTS}{RAUF}{RUNTER}": DIM DX(4),DY(4): DX(1)=5: DX(2)=-5: DY(3)=5: DY(4)=-5
190 DIM BM(8),SP(8): BM=1
200 FOR I=1 TO 7: BM(I)=BM: BM=BM2*2: SP(I)=1+(I AND 3): SPRSAV S$,I: NEXT
210 DO: REM GRAFIK AUFBAUEN UND SPRITES EINSCHALTEN
220 SCNCLR 1: WIDTH 1: COLOR 1,1
230 BOX 1,0,0,319,12,0,1:BOX 1,0,187,319,199,0,1
240 FOR I=1 TO 7: MOVSPR I,40*I+5,200: MOVSPR I,A(I)#SP(I): SPRITE I,1,I,1: NEXT
250 MOVSPR 8,320,150: SPRITE 8,1,1,0: REM "RAUMSCHIFF" EINSCHALTEN
260 B=BUMP(2): B=0: REM VERALTETE KOLLISIONEN LOESCHEN
270 GS=0
280 COLLISION 1,130: REM SPRITE-SPRITE-KOLLISIONEN
290 COLLISION 2,20: REM SPRITE-BILDSCHIRM-KOLLISIONEN
300 REM HAUPTTEIL
310 DO
320 GET K$: IN=INSTR(I$,K$): IF IN THEN MOVSPR 8,-(DX(IN)),-(DY(IN))
330 IF RSPPOS(8,0)<24 THEN GS=2: EXIT: REM GS (GAMESTATUS) = SIEG
340 LOOP UNTIL GS
350 REM SPRITES AUSSCHALTEN
360 COLLISION 1: COLLISION 2
370 FOR I=1 TO 8: SPRITE I,0: MOVSPR I,0#0: NEXT
380 IF GS=1 THEN CHAR 1,18,8,"GAME": CHAR 1,18,10,"OVER!": ELSE CHAR 1,15,8,"GESCHAFFT!"
390 CHAR 1,10,13,"NOCHMAL SPIELEN (J/N)?"
400 DO: GETKEY K$: LOOP UNTIL K$="J" OR K$="N"
410 LOOP WHILE K$="J"
420 GRAPHIC 0