Tutorial Kollisionserkennung PM/Character

Moderator: Rockford

Antworten
Benutzeravatar
Dr. Irata
Beiträge: 937
Registriert: 24.08.2021 14:40
Has thanked: 110 times
Been thanked: 268 times
Kontaktdaten:

Tutorial Kollisionserkennung PM/Character

Beitrag von Dr. Irata »

Hallo in die Runde!
Ich möchte an dieser Stelle gerne meine Erfahrungen hinsichtlich der Kollisionserkennung bei Verwendung von PM-Grafik und Charakterlandschaft in einem kleinen offenen Tutorial weitergeben.
An dieser Problematik habe ich jetzt immer wieder seit Wochen gearbeitet und mehrere Lösungsansätze umgesetzt und wieder verworfen, da die Erkennung zu fehlerhaft war.
Am Ende habe ich das Problem ganz anders gelöst und den Code dazu völlig neu konstruiert - der Code ist jetzt sogar schlanker und fast perfekt!
Die Umsetzung ist in MADS-Assembler unter Eclipse - wenn das interessant ist, lege ich hier los!
Grüße
Peter

Benutzeravatar
MichaG
Beiträge: 380
Registriert: 14.10.2021 12:54
Has thanked: 383 times
Been thanked: 111 times
Kontaktdaten:

Re: Tutorial Kollisionserkennung PM/Character

Beitrag von MichaG »

Gerne, deine Programmier-Posts (und die daraus entstehenden Diskussionen) sind immer sehr interessant!
ABBUC-Mitglied aus den 90ern/frühen 2000ern
Ex-WAF und Regionalgruppe Thüringen

Benutzeravatar
Dr. Irata
Beiträge: 937
Registriert: 24.08.2021 14:40
Has thanked: 110 times
Been thanked: 268 times
Kontaktdaten:

Re: Tutorial Kollisionserkennung PM/Character

Beitrag von Dr. Irata »

Alles, was hier folgt, bezieht sich auf Assembler, im Prinzip kann man das aber auch direkt auf andere Sprachen (BASIC) übertragen.

Vorüberlegungen:

Wenn man ein Spiel programmiert, dann muss man sich recht bald Gedanken machen in welchem Grafikmodus dieses Spiel sich bewegen soll. Hier muss man einen guten Kompromiss in Auflösung, Farbmenge, Speicherplatzbedarf und Geschwindigkeit finden. Oft wird man zum ANTIC Mode 4 greifen, da man hier 4 verschiedene Farben mit einer guten Auflösung und einem moderatem Speicherplatzbedarf hat. ANTIC 4 ist Charaktergrafik mit einer Auflösung von 40x24 Zeichen. Jedes Zeichen hat eine Breite von 8x8 Bits, wobei man hier beachten muss, daß wegen der Farben der Charakter man nur eine Breite von 4 Bits auflösen kann. Im Endeffekt kann ich aber nur 40x24 Charakter auf den Bildschirm bringen, was einen Speicherbedarf von 960 Bytes benötigt (in ANTIC 4).

Die Player/Missile-Grafik funktioniert ganz anders. Letztlich hat man hier eine schöne feine Bewegungsauflösung von 256x256 wobei aber horizontal nur der Bereich 48-208 sichtbar ist und vertikal 32-224.

Schießt man nun einen Missile z.B. von einem Raumschiff ab, dann hat man ja zunächst die horizontale Position des Missiles, trifft das Missile auf einen Charakter, dann kommt es zu einer entsprechenden Änderung des Kollisionsregisters dieses Missiles, was man direkt abfragen kann. Kommt es zu einer Kollision, dann springe ich in eine entsprechende Subroutine, wo alles weitere verarbeitet wird... so weit, so gut.

Nun gehen aber die Probleme erst los, denn wenn man das Missile etwas schneller haben möchte, dann wird man 2-3 vertikale Steps nach unten machen und muss ganz genau beachten, was man denn trifft. Man wird also nur einen "in etwa" genauen Wert für die vertikale Ebene bekommen und muss diesen Wert korrigieren, wenn man das getroffene Element z.B. explodieren lassen will. Das Gleiche gilt für die horizontale Position, denn das Missile hat ja eine viel feinere Auflösung, als das Charakterelement. Auch diese Position muss korrigiert werden. Ganz schwierig wird es, wenn man die Element (ich nenne sie Items) aus mehreren Charaktern aufbaut und die Items auch noch verschieden hoch sind und verschieden geformt sind. Meine Items sind z.B. aus 12 bzw. 6 Charaktern aufgebaut. Auf den Bildschirm geprintet werden diese Items meanderförmig von links oben nach rechts unten. Auch die Explosion wird so animiert geprintet, da ich hier die gleiche Printroutine nehme.
Hier 3 Items, alle verschieden aufgebaut:
Bildschirmfoto 2022-05-20 um 11.55.58.png
Meine Korrekturroutine muss also zwingend sicher bei Kollision den linken oberen Startpunkt des Items finden, der kann dann im Item liegen, oder aber auch völlig in der Luft sein. Und hier wird es schwierig...

Aber der Reihe nach!
Zuerst muss man also den Wert des Missiles in den Charakterwert umrechnen:
Vertikale Umrechnung: Y-Wert (-32):8 - z.B. unterste Charakterlinie ist bei ANTIC 4 bei 24. Unterster PM-Bereich liegt ja bei 224. 224-32= 192 -> 192:8=24
Horizontale Umrechnung: X-Wert (-48):4 - z.B. rechte Seite des Bildschirmes bei ANTIC 4 ist bei 40. Weitester rechter Wert des PM-Bereiches ist ja 208. 208-48=160 -> 160:4=40

Folgende Assemblerroutine ist also notwendig:

Code: Alles auswählen

			lda yschuss1	;in ANTIC 4 -32 (sichtbarer Bereich ab 32 und /8
			sec
			sbc #32
			lsr
			lsr
			lsr
			sta yschuss1	
			tax				;y-Position in das x-Register schreiben
			
			lda xschuss1	;x-Position -48 (sichtbarer Bereich)und /4
			sec
			sbc #48
			lsr
			lsr
			tay				;x-Position in das y-Register schreiben
Die jeweiligen umgerechneten Werte schreibe ich in das y- und x-Register zur Weiterverarbeitung.
Praktischerweise geht der horizontale Wert (ich nenne ihn mathematisch ja x-Wert) ins y-Register und der vertikale Wert geht ins x-Register. Das muss man wegen der indirekt indizierten Adressierung so machen!
Dann hole ich meine Bildschirmstartadresse (steht bei var1/var1+1) und speichere die in meine "Arbeitsadresse" var2:

Code: Alles auswählen

			mwa var1 var2		;holen der Bildschirmadresse -> var2
Jetzt noch die fast richtige Höhe einstellen:

Code: Alles auswählen

			clc
@			lda var2		;jetzt die y-Position auf die richtige Höhe stellen
			adc #40
			sta var2
			lda var2+1
			adc #0
			sta var2+1
			dex
			bpl @-			;die y-Position steht in x - Addition von x Zeilen

und schon hat man in etwa die Position, wo man das Item getroffen hat.
Danach kommt die eigentliche Korrektur und Anpassung, bis man die genaue Startadresse hat, wo die animierte Explosion beginnt......

Die Logik dazu folgt im nächsten Post!

Benutzeravatar
Dr. Irata
Beiträge: 937
Registriert: 24.08.2021 14:40
Has thanked: 110 times
Been thanked: 268 times
Kontaktdaten:

Re: Tutorial Kollisionserkennung PM/Character

Beitrag von Dr. Irata »

Meine ganzen Korrekturroutinen zielten darauf ab, den linken und rechten Rand abzufragen - oben und unten, auf Null zu prüfen und so den richtigen Startpunkt zu bekommen. Je mehr Abfragen und je lnger der Code dafür wurde, desto genauer wurde auch der Startpunkt, aber leider gab es immer wieder kleinere und größere Ausreißer.
Was man zwingend braucht - und das hatten wir genau so schon mal kurz auf der NOMAM angesprochen - ist ein klar definierter Startpunkt für x und für y! Und man sollte seine Items dementsprechend vorher (!) ein wenig planen. Gut, wenn die Dinger immer auf dem gleichen Bode stehen. Bei mir ist das tatsächlich der Fall und entspricht Charakter Nr. 2.
Ich gehe also mit der vertikalen zuvor berechneten Position weiter nach unten, bis ich den entsprechenden Boden treffe (Charakter Nr.2):

Code: Alles auswählen

			@			clc
			lda var2
			adc #40
			sta var2
			lda var2+1
			adc #0
			sta var2+1		
			lda (var2),y
			tax
			cpx #2
			bne @-
Jetzt will ich aber schauen, wo ich in der horizontalen Ebene gelandet bin. Ich gehe also jetzt wieder um eine Zeile hoch (klingt irgendwie umständlich und läßt sich sicherlich noch optimieren) und frage ab, was hier drin ist:

Code: Alles auswählen

			sec
			lda var2
			sbc #40
			sta var2
			lda var2+1
			sbc #0
			sta var2+1			
			lda (var2),y
			sta var11
Den gefundenen Charakter speichere ich nun in var11 (eine von meinen vielen Variablen)

Benutzeravatar
Dr. Irata
Beiträge: 937
Registriert: 24.08.2021 14:40
Has thanked: 110 times
Been thanked: 268 times
Kontaktdaten:

Re: Tutorial Kollisionserkennung PM/Character

Beitrag von Dr. Irata »

... und nun nutze ich einen schönen Befehl im MADS-Assembler, der sicherlich fast untypisch für Assembler ist und dem geneigten Assemblerprogrammierer ein Runzeln entlockt. Ich finde ihn aber sehr praktisch:
Den #if ... #end - Befehl.

Im nächsten Schritt frage ich ab, was links unten im Item steht und wenn ich den entsprechenden Charakter gefunden habe muss ich nur noch drei Zeilen hoch gehen und dann habe ich die exakte Startposition für die animierte Explosion.
Den folgenden Code muss man noch optimieren (habe ich erst gestern erstellt).
Ich führe ihn insgesamt dreimal aus - jeweils um ein x-Wert weiter nach links (weil die maximale Breite ja 3 Charakter beträgt und der Schuss ja ganz rechts außen des Item treffen könnte). Diese drei Abfragen kann man als Schleife noch zusammenfassen, was ich hier noch nicht umgesetzt habe...

Code: Alles auswählen

			#if .byte var11=#227 .or .byte var11=#233 .or .byte var11=#111
			sec
			lda var2
			sbc #120
			sta var2
			lda var2+1
			sbc #0
			sta var2+1
			iny
			iny
			#end
			
			dey
			lda (var2),y
			sta var11
			
			#if .byte var11=#227 .or .byte var11=#233 .or .byte var11=#111
			sec
			lda var2
			sbc #120
			sta var2
			lda var2+1
			sbc #0
			sta var2+1
			iny
			#end
			
			dey
			lda (var2),y
			sta var11
			
			#if .byte var11=#227 .or .byte var11=#233 .or .byte var11=#111
			sec
			lda var2
			sbc #120
			sta var2
			lda var2+1
			sbc #0
			sta var2+1
			#end
								;ab hier stimmt die Position des Items
								
			rts
	.endp

thats it...

Benutzeravatar
LarsImNetz
Beiträge: 152
Registriert: 24.08.2021 18:27
Has thanked: 109 times
Been thanked: 80 times
Kontaktdaten:

Re: Tutorial Kollisionserkennung PM/Character

Beitrag von LarsImNetz »

Hallo Peter,
vielen Dank für die Idee, aber ein Fehler:
Du verwendest eine Schleife zur Berechnung der y Position. Warum?
Schon mal an eine kleine Tabelle gedacht?

LG
Lars

Der Code is für atasm/MAC65.

Code: Alles auswählen

reg=0               ; irgendwo in der Zero Page

 lda yschuss1	    ; in ANTIC 4 -32 (sichtbarer Bereich ab 32 und /8
 sec
 sbc #32
 lsr
 lsr
 lsr
 tax		    ; y-Position in das x-Register schreiben lda y

 clc
 lda SAVMSC         ; Screen oben links (88)
 adc yzeile_low,x   ; addiere die nte-Zeile
 sta reg
 lda SAVMSC+1
 adc yzeile_high,x
 sta reg+1

 lda xschuss1
 sec
 sbc #48
 lsr
 lsr
 tay           ; das x-Byte innerhalb der Zeile

 lda (reg),y   ; liefert jetzt das Byte unter der Position yschuss1, xschuss1
 
[...]

; Wie legen eine Tabelle mit 2x24 Bytes an. Hier unvollständig, aber der
; geneigte Leser sollte das erweitern können.
yzeile_low
 .byte <0,<40,<80,<120,<160,<200,... ; bis 920 in 40er Schritten erweitern

yzeile_high
 .byte >0,>40,>80,>120,>160,>200,...


Benutzeravatar
Dr. Irata
Beiträge: 937
Registriert: 24.08.2021 14:40
Has thanked: 110 times
Been thanked: 268 times
Kontaktdaten:

Re: Tutorial Kollisionserkennung PM/Character

Beitrag von Dr. Irata »

Hallo Lars,
das mit der Tabelle hatte ich mir auch schon überlegt und erscheint tatsächlich in vielen Fällen einfacher - wobei die Schleife mit Addition oder Subtraktion wohl zwar zeitaufwendiger ist (wobei ich bei der Kollisionskorrektur keine Zeitnot habe) aber etwas weniger Speicherplatz belegt. Da ich allerdings in meinem Programm etliche Berechnungen mache, wird das mit der Tabelle wohl in der Summe auch weniger Speicher kosten, da man sie ja nur einmal anlegen muss.
Ich werde bei meinem nächsten Projekt darüber nachdenken...
Danke für deine Anregung!!
Liebe Grüße
Peter

Erhard
Beiträge: 555
Registriert: 04.11.2021 15:52
Has thanked: 52 times
Been thanked: 111 times
Kontaktdaten:

Tutorial Kollisionserkennung PM/Character

Beitrag von Erhard »

Hi,

funktioniert dieses IF ... THEN in MADS während das Programm läuft (sprich wird das in echten Maschinencode übersetzt) oder beeinflußt das nur die Kompilierung?

(Ich bin bislang wiederholt am Einarbeitungsaufwand für WUDSN gescheitert und greife trotz des großen Komforts immer wieder auf den Mac/65 zurück).

CU, Erhard

Benutzeravatar
Dr. Irata
Beiträge: 937
Registriert: 24.08.2021 14:40
Has thanked: 110 times
Been thanked: 268 times
Kontaktdaten:

Re: Tutorial Kollisionserkennung PM/Character

Beitrag von Dr. Irata »

Hallo Erhard,
das #if … #end funktioniert wunderbar und wird später in Maschinencode compiliert! Man kann es auch noch mit .pt und .and kombinieren… das macht vieles einfacher!!
Man muss immer dabei beachten, dass dabei code entsteht, der länger ist als der einfache if / end Befehl vermuten lässt. Das kann bei Verzweigungen eine Rolle spielen oder auch bei zeitkritischen Parts…
Einarbeitung WUDSN… verstehe ich!! Das hat mich auch erst scheitern lassen! Am Ende ist es aber einfacher als man denkt und wenn du die Umgebung eingerichtet hast, wirst du Assembler nur noch hier programmieren weil es viel komfortabler ist! Die Fujiama ist ja bald und da können wir dir alles einrichten und erklären! Mac 65 wirst du dann nicht mehr nutzen wollen 😉💪

Benutzeravatar
pps
Beiträge: 529
Registriert: 18.06.2021 23:05
Has thanked: 115 times
Been thanked: 205 times
Kontaktdaten:

Re: Tutorial Kollisionserkennung PM/Character

Beitrag von pps »

OK.

Wieder was gelernt. Ich hatte immer angenommen (und nie getestet ob es anders ist), dass diese if Sachen immer nur zur Assemblierung aktiv sind. Daher habe ich immer brav und ordentlich in ASM selbst gebranched...
PP´s of STARSOFTBerlin__________github|meine Webseite|Demozoo

Benutzeravatar
Dr. Irata
Beiträge: 937
Registriert: 24.08.2021 14:40
Has thanked: 110 times
Been thanked: 268 times
Kontaktdaten:

Re: Tutorial Kollisionserkennung PM/Character

Beitrag von Dr. Irata »

oben muss es natürlich .or heissen 😉

Benutzeravatar
GoodByteXL
Beiträge: 257
Registriert: 18.08.2021 12:10
Has thanked: 6 times
Been thanked: 56 times
Kontaktdaten:

Re: Tutorial Kollisionserkennung PM/Character

Beitrag von GoodByteXL »

Auf einem früheren Blog hatte Landon Dyer mal ein paar interessante Anmerkungen dazu gemacht. Teile davon finden sich in der Beilage zu Magazin #101.

Benutzeravatar
Dr. Irata
Beiträge: 937
Registriert: 24.08.2021 14:40
Has thanked: 110 times
Been thanked: 268 times
Kontaktdaten:

Re: Tutorial Kollisionserkennung PM/Character

Beitrag von Dr. Irata »

das Magazin habe leider nicht🤔

Benutzeravatar
DjayBee
Beiträge: 624
Registriert: 17.08.2021 04:02
Has thanked: 384 times
Been thanked: 175 times
Kontaktdaten:

Re: Tutorial Kollisionserkennung PM/Character

Beitrag von DjayBee »

Prodehl hat geschrieben:
23.06.2022 13:24
das Magazin habe leider nicht🤔
Schau mal da: https://abbuc.de/mitglieder/downloadber ... h-101-110/

Benutzeravatar
Dr. Irata
Beiträge: 937
Registriert: 24.08.2021 14:40
Has thanked: 110 times
Been thanked: 268 times
Kontaktdaten:

Re: Tutorial Kollisionserkennung PM/Character

Beitrag von Dr. Irata »

sehr interessanter Artikel - vielen Dank für den Link!

Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast