Tutorial Kollisionserkennung PM/Character
Moderator: Rockford
- Dr. Irata
- Beiträge: 946
- Registriert: 24.08.2021 14:40
- Has thanked: 113 times
- Been thanked: 275 times
- Kontaktdaten:
Tutorial Kollisionserkennung PM/Character
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
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
- MichaG
- Beiträge: 381
- Registriert: 14.10.2021 12:54
- Has thanked: 388 times
- Been thanked: 111 times
- Kontaktdaten:
Re: Tutorial Kollisionserkennung PM/Character
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
Ex-WAF und Regionalgruppe Thüringen
- Dr. Irata
- Beiträge: 946
- Registriert: 24.08.2021 14:40
- Has thanked: 113 times
- Been thanked: 275 times
- Kontaktdaten:
Re: Tutorial Kollisionserkennung PM/Character
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:
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:
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:
Jetzt noch die fast richtige Höhe einstellen:
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!
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:
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
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
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!
- Dr. Irata
- Beiträge: 946
- Registriert: 24.08.2021 14:40
- Has thanked: 113 times
- Been thanked: 275 times
- Kontaktdaten:
Re: Tutorial Kollisionserkennung PM/Character
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):
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:
Den gefundenen Charakter speichere ich nun in var11 (eine von meinen vielen Variablen)
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 @-
Code: Alles auswählen
sec
lda var2
sbc #40
sta var2
lda var2+1
sbc #0
sta var2+1
lda (var2),y
sta var11
- Dr. Irata
- Beiträge: 946
- Registriert: 24.08.2021 14:40
- Has thanked: 113 times
- Been thanked: 275 times
- Kontaktdaten:
Re: Tutorial Kollisionserkennung PM/Character
... 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...
thats it...
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...
- LarsImNetz
- Beiträge: 156
- Registriert: 24.08.2021 18:27
- Has thanked: 114 times
- Been thanked: 84 times
- Kontaktdaten:
Re: Tutorial Kollisionserkennung PM/Character
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.
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,...
- Dr. Irata
- Beiträge: 946
- Registriert: 24.08.2021 14:40
- Has thanked: 113 times
- Been thanked: 275 times
- Kontaktdaten:
Re: Tutorial Kollisionserkennung PM/Character
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
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
-
- Beiträge: 597
- Registriert: 04.11.2021 15:52
- Has thanked: 53 times
- Been thanked: 122 times
- Kontaktdaten:
Tutorial Kollisionserkennung PM/Character
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
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
- Dr. Irata
- Beiträge: 946
- Registriert: 24.08.2021 14:40
- Has thanked: 113 times
- Been thanked: 275 times
- Kontaktdaten:
Re: Tutorial Kollisionserkennung PM/Character
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
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
- pps
- Beiträge: 566
- Registriert: 18.06.2021 23:05
- Has thanked: 122 times
- Been thanked: 223 times
- Kontaktdaten:
Re: Tutorial Kollisionserkennung PM/Character
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...
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...
- GoodByteXL
- Beiträge: 257
- Registriert: 18.08.2021 12:10
- Has thanked: 6 times
- Been thanked: 56 times
- Kontaktdaten:
Re: Tutorial Kollisionserkennung PM/Character
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.
Online
- Dr. Irata
- Beiträge: 946
- Registriert: 24.08.2021 14:40
- Has thanked: 113 times
- Been thanked: 275 times
- Kontaktdaten:
Re: Tutorial Kollisionserkennung PM/Character
sehr interessanter Artikel - vielen Dank für den Link!
Wer ist online?
Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast