
; Listing7w1.s	KOLLISIONEN ZWISCHEN SPRITES


	SECTION CipundCop,CODE

Anfang:
	move.l	4.w,a6		; Execbase
	jsr	-$78(a6)	; Disable
	lea	GfxName(PC),a1	; Name lib
	jsr	-$198(a6)	; OpenLibrary
	move.l	d0,GfxBase
	move.l	d0,a6
	move.l	$26(a6),OldCop	; speichern die alte COP

;	Pointen wie immer auf unser PIC

	MOVE.L	#PIC,d0
	LEA	BPLPOINTERS,A1
	MOVEQ	#2-1,D1
POINTBP:
	move.w	d0,6(a1)
	swap	d0
	move.w	d0,2(a1)
	swap	d0
	ADD.L	#40*256,d0
	addq.w	#8,a1
	dbra	d1,POINTBP

;	Pointen auf den Sprite

	LEA	SpritePointers,a1	; Pointer in der Copperlist
	MOVE.L	#MEINSPRITE0,d0		; Adresse des Sprite in d0
	move.w	d0,6(a1)
	swap	d0
	move.w	d0,2(a1)
	add.l	#16,a1

	MOVE.L	#MEINSPRITE2,d0		; Adresse des Sprite in d0
	move.w	d0,6(a1)
	swap	d0
	move.w	d0,2(a1)

	move.l	#COPPERLIST,$dff080	; unsere COP
	move.w	d0,$dff088		; START COP
	move.w	#0,$dff1fc		; NO AGA!
	move.w	#$c00,$dff106		; NO AGA!

mouse:
	cmpi.b	#$ff,$dff006	; Zeile 255?
	bne.s	mouse

	bsr.s	BewegeSprite0	; Bewege das Flugzeug
	bsr.s	BewegeSprite1	; Bewege die Rakete gegen das Flugzeug
	bsr.s	CheckColl	; Kontrolliere die Kollisionen und
				; greife eventuell ein

Warte:
	cmpi.b	#$ff,$dff006	; Zeile 255?
	beq.s	Warte

	btst	#6,$bfe001	; Mouse gedrückt?
	bne.s	mouse

	move.l	OldCop(PC),$dff080	; Pointen auf die SystemCOP
	move.w	d0,$dff088		; starten die alte COP

	move.l	4.w,a6
	jsr	-$7e(a6)	; Enable
	move.l	gfxbase(PC),a1
	jsr	-$19e(a6)	; Closelibrary
	rts

;	Daten

GfxName:
	dc.b	"graphics.library",0,0

GfxBase:
	dc.l	0

OldCop:
	dc.l	0

; Diese Routine bewegt den Sprite, der das Flugzeug darstellt, gradlinig
; um jeweils 2 Pixel nach links. Sie greift auf das Byte HSTART zu

BewegeSprite0:
	subq.b	#1,HSTART0
	rts

;	-		-		-		-

; Dieses Routine bewegt die Rakete. Sie tut das nur, wenn das Flugzeug nah
; genug ist, um getroffen zu werden. Es ist soweit, wenn dessen HSTART $b0
; erreicht hat. Wenn ihr das Flugzeug retten wollt, versucht die Rakete bei
; $AA abzuschießen, also zu früh, oder bei Position $c1, wo es schon zu
; spät ist.

BewegeSprite1:
	cmp.b	#$b0,HSTART0	; Ist das Flugzeug in Schußweite?
	bhi.s	nicht_in_Schussweite ; noch nicht schießen, wenn es zu weit
				     ; weg ist
	subq.b	#1,VSTART2	; laß die Rakete steigen, indem auf das VSTART
	subq.b	#1,VSTOP2	; wie das VSTOP eingewirkt wird
nicht_in_Schussweite:
	rts

;	-		-		-		-

; Diese Routine kontrolliert, ob es eine Kollision gab. Wenn ja, löscht
; sie die beiden Sprites, indem sie deren Pointer in der Copperlist auf


CheckColl:
	move.w	$dff00e,d0 ; liest CLXDAT ($dff00e)
			   ; ein Lesevorgang dieses Register bewirkt
			   ; auch dessen komplette Löschung, es ist deshalb
			   ; ratsam, es sich in d0 zu kopieren, und dann
			   ; dort die Tests durchzuführen
	btst.l	#9,d0
	beq.s	no_coll	 ; wenn keine Kollision, überspringe

	MOVEQ	#0,d0		  ; ansonsten lösche die Sprites
	LEA	SpritePointers,a1 ; Pointer Sprite 0
	move.w	d0,6(a1)	  ; Lösche Spritepointer 0 in der Copperlist
	move.w	d0,2(a1)
	add.w	#16,a1		; Pointer Sprite 2
	move.w	d0,6(a1)	; Lösche Pointer auf Sprite 2 in der Copperlist
	move.w	d0,2(a1)
no_coll:
	rts


	SECTION GRAPHIC,DATA_C

COPPERLIST:
SpritePointers:
	dc.w	$120,0,$122,0,$124,0,$126,0,$128,0 ; SPRITE
	dc.w	$12a,0,$12c,0,$12e,0,$130,0,$132,0
	dc.w	$134,0,$136,0,$138,0,$13a,0,$13c,0
	dc.w	$13e,0

	dc.w	$8E,$2c81	; DiwStrt
	dc.w	$90,$2cc1	; DiwStop
	dc.w	$92,$38		; DdfStart
	dc.w	$94,$d0		; DdfStop
	dc.w	$102,0		; BplCon1
	dc.w	$104,$0024	; BplCon2 - Sprites über den Bitplanes
	dc.w	$108,0		; Bpl1Mod
	dc.w	$10a,0		; Bpl2Mod

		    ; 5432109876543210
	dc.w	$100,%0010001000000000	; Bit 13 an 2 Bitplane Lowres

BPLPOINTERS:
	dc.w $e0,0,$e2,0	; erstes Bitplane
	dc.w $e4,0,$e6,0	; zweites Bitplane

	dc.w	$180,$000	; COLOR0	; schwarzer Hintergrund
	dc.w	$182,$005	; COLOR1	; COLOR 1 des Bitplane
	dc.w	$184,$a40	; COLOR1	; COLOR 2 des Bitplane
	dc.w	$186,$f80	; COLOR1	; COLOR 3 des Bitplane

	dc.w	$1A2,$06f	; COLOR17, also COLOR1 des Sprite0
	dc.w	$1A4,$0c0	; COLOR18, also COLOR2 des Sprite0
	dc.w	$1A6,$0c0	; COLOR19, also COLOR3 des Sprite0

	dc.w	$1AA,$444	; COLOR21, also COLOR1 des Sprite2
	dc.w	$1AC,$888	; COLOR22, also COLOR2 des Sprite2
	dc.w	$1AE,$0c0	; COLOR23, also COLOR3 des Sprite2

	dc.w	$FFFF,$FFFE	; Ende der Copperlist


; *********** Hier ist der Sprite: Klarerweise ist er in CHIP RAM! ************

MEINSPRITE0:		; Länge 6 Zeilen
VSTART0:
	dc.b 180	; Vertikale Anfangsposition (von $2c bis $f2)
HSTART0:
	dc.b $d8	; Horizontale Anfangsposition (von $40 bis $d8)
VSTOP0:
	dc.b 186	; 180+6=186
VHBITS:
	dc.b $00
	dc.w	$0008,$0000
	dc.w	$1818,$0000
	dc.w	$2C28,$1010
	dc.w	$7FF8,$0000
	dc.w	$3FC0,$0000
	dc.w	$01F0,$0000
	dc.w	$0000,$0000

MEINSPRITE2:		; Länge 16 Zeilen
VSTART2:
	dc.b 224	; Vertikale Anfangsposition (von $2c bis $f2)
HSTART2:
	dc.b $86	; Horizontale Anfangsposition (von $40 bis $d8)
VSTOP2:
	dc.b 240
	dc.b 0
	dc.w	$0200,$0000
	dc.w	$0200,$0000
	dc.w	$0200,$0000
	dc.w	$0000,$0200
	dc.w	$0000,$0700
	dc.w	$0000,$0700
	dc.w	$0500,$0200
	dc.w	$0200,$0500
	dc.w	$0500,$0200
	dc.w	$0200,$0500
	dc.w	$1540,$0200
	dc.w	$0200,$1DC0
	dc.w	$0000,$1FC0
	dc.w	$0000,$1740
	dc.w	$0500,$0200
	dc.w	$0000,$0000
	dc.w	$0000,$0000

;	Bild der Startrampe

PIC:
	incbin	"Landschaft.raw"

	end

In  diesem Beispiel sehen wir, wie man die Kollision zwischen zwei Sprites
registrieren kann.
Wir haben zwei Objekte, die sich kreuzen. Achtet darauf, daß wir  für  die
zwei  Objekte  die  Sprites  0 und 2 gewählt haben, also zwei Sprites, die
verschiedenen Paaren angehören. Das erlaubt uns zum Einen  die  Verwendung
von  zwei  verscheidenen Farbpaletten, ist aber andererseits notwendig, um
die Kollisionen überhaupt erkennen zu können. Denn  es  ist  nur  möglich,
Kollisionen  zwischen  Sprites  aus verschiedenen Gruppen zu erkennen, und
nicht zwischen Sprites aus ein und demselben Paar. Um  eine  Kollision  zu
erkennen  muß  nur ein Bit im Register CLXDAT kontrolliert werden, wie wir
schon in der Lektion gehört haben.

Wenn dieses Bit auf  1  steht,  dann  hat  sich  effektiv  eine  Kollision
zugetragen.  In unserem Beispiel beschränken wir uns lediglich darauf, die
beiden Sprites zu löschen, indem wir die Pointer auf 0 zeigen lassen.  Ihr
könnt  es  natürlich  verbessern,  indem  ihr  eine  schöne  Explosion
dazuzeichnet. Es ist sehr einfach. Als  erstes  zeichnet  ihr  euch  einen
Sprite,  der  eine  Explosion darstellt, und fügt ihn im Listing ein (Aber
bitte in die SECTION, die in  die  CHIP  kommt!!).  Dann  modifiziert  die
Routine  CheckColl:  wenn  eine  Kollision  auftritt,  dann  ersetzt  die
folgenden Zeilen


	MOVEQ	#0,d0		  ; ansonsten lösche die Sprites
	LEA	SpritePointers,a1 ; Spritepointer 0
	move.w	d0,6(a1)	  ; lösche Spritepointer0 in der Copperlist
	move.w	d0,2(a1)

durch diese

	MOVE.L	#EXPLOSIONS_SPRITE,d0	; Adresse des Explosionssprite
	LEA	SpritePointers,a1	; Spritepointer 0
	move.w	d0,6(a1)	  ; verändert Spritepointer 0 in der Copperlist
	swap	d0
	move.w	d0,2(a1)

dadurch wird das Bild des Flugzeuges durch das der Explosion ersetzt.  Ihr
müßt  dann  natürlich  noch  die  Byte,  die  die  Position des Flugzeuges
kontrollieren, in die Kontrollbytes der Explosion kopieren. Das könnt  ihr
nun  aber  schon alleine. Ihr müßt nur bei VSTOP etwas aufpassen: wenn die
Explosion eine andere Höhe hat als das Flugzeug, dann könnt ihr nicht  nur
das  alte  VSTOP  einsetzen,  sondern  ihr  müßt  es  anpassen.  Aber  nix
schwieriges.

In diesem Beispiel haben wir gezielt sehr einfache Bahnen gewählt  (gerade
Linien),  um  den  Mechanismus  der  Kollision besser zu zeigen. Ihr könnt
statt dieser Routinen auch solche mit Tabellen einsetzen, wie wir  sie  in
einigen vorigen Beispielen verwendet haben.


