You are not logged in.

Dear visitor, welcome to Forum64. If this is your first visit here, please read the Help. It explains in detail how this page works. To use all features of this page, you should consider registering. Please use the registration form, to register here or read more information about the registration process. If you are already registered, please login here.

Turrican

Unregistered

1

Monday, September 29th 2003, 3:27pm

Sprite - Hintergrundkollision : $d01f

Hallo!
Ich fuchtel seit einiger Zeit an einer Routine rum, die ein Sprite, dessen Bewegung per Joystick gesteuert wird, an einer Wand (Chars) gestoppt werden soll...
Nur irgendwie funktioniert das nicht so recht...denn das Sprite geht dann einfach weiter durch die Wand, zwar langsamer, aber durch...
Andersherum habe ich das mal geschafft, dass das Sprite gestoppt wurde wenn er auf "nicht-Wand" trifft, also leeren Raum, aber das ist ja nicht Sinn der Sache...

Ich glaub, ich "behandel" das Register $d01f nicht richtig...
Wird ja gelöscht, wenn's gelesen wird, oder?

Danke für Hilfe ;)

tecM0

Unregistered

2

Monday, September 29th 2003, 3:38pm

RE: Sprite - Hintergrundkollision : $d01f

scheinbar bewegst du das sprite erst und prüfst dann obeine kollision da ist.....

diese sprite/sprite bzw. brite/hintergrund resister sind eh für die katz'
kann man nur sehr eingeschränkte sachen mit machen.

wenn du z.b. ein hump'n' run bauen willst solltest du dir eine "eigene"
methode ausdenken...z.b. prüfen wo wände beginnen und ob sich ein
sprite davor bzw. drin befindet...


tec

Turrican

Unregistered

3

Monday, September 29th 2003, 4:16pm

Quoted

scheinbar bewegst du das sprite erst und prüfst dann obeine kollision da ist.....


Yo, so ist das...und,wenn eine Kollision da ist, dann werden die vorherigen Koordinaten wieder gestetzt, oder sollten sie zumindest...

Ist kein Jump 'N Run...
Eher sowas wie Wizard of Wor, nicht vom Spielprinzip, aber eher vom Bildschirmaufbau usw.

Ok, werde mal überlegen, was es für Alternativen gibt...

tecM0

Unregistered

4

Monday, September 29th 2003, 5:05pm

ok, du hast das "level" ja sicher im speicher rumstehen..als 8x8 charblöcke. wenn du die spritekoordinaten durch 8 teilst kannst du
rausbekommen in welchem "levelchar" das sprite gerade ist. jetzt
musst du noch die maximale ausdenung des sprites festlegen und
checken ob das sprite sich in "gängen" oder in "wänden" befindet.

tec

Turrican

Unregistered

5

Monday, September 29th 2003, 11:09pm

Ok Danke!
Werde das mal ausprobieren...
Die Sache mit $D01F hatte sich halt einfacher angehört...

Ist Sprite Sprite Kollision mit $D01E dann auch nicht so der Hammer?

tecM0

Unregistered

6

Tuesday, September 30th 2003, 12:02am

naja,denke mal nicht. ausserdem lässt sich das dann per ActionReplay faken ;D

ich hab's immer per "eigenanbau" gemacht.

tecM0

hannenz

Unregistered

7

Tuesday, September 30th 2003, 5:16pm

ich hab gerade auch ein bisschen mit dem $d01f Register gespielt und musste feststellen, daß die Abfrage schlicht und ergreifend falsch bzw. ungenau ist. Sie reagiert erst, wenn das Sprite schon um ZWEI Koordinaten "im Hintergrund" drin ist bzw. auch andersrum, wieder "raus". Und das ist ja bei weitem nicht Sinn der Sache. Ist aber schon schade, denn wozu gibts denn dann das Register, wenn es einfach zu nix zu gebrauchen ist???! Hat mich schon geärgert. Sowas von Hand zu machen, stelle ich mir eher aufwändig vor, es führt aber wahrscheinlich kein Weg dran vorbei, oder?!

tecM0

Unregistered

8

Tuesday, September 30th 2003, 5:39pm

die kollision basiert auf pixeln. wenn du also ein leeres sprites rumbewegst gibts auch nie eine kollision.

kann es sein das die pixels in deinem sprite erst ab der 2ten
koordinate anfangen?

für ein eigenes system musst du schon etwas gehinschmalz aufwenden,
aber dann weisst du das es geht...und wenn's nicht geht weisst du
auch wer schuld ist ;)

hannenz

Unregistered

9

Wednesday, October 1st 2003, 6:21pm

das mit den Pixeln ist schon klar; ich weiss auch, daß bei MC-Sprites die Bitkombination "01" als transparent gilt, trotzdem... es bleibt dabei.
Noch was anderes zu dem Thema: ich habe 2 wiedersprüchliche Aussagen darüber gelesen, ob das Register beim Lesen automatisch gelöscht wird oder nicht. Im Programmer's Reference Guide, steht, es wird gelöscht, im C64 Intern, es würde NICHT gelöscht (oder wars grad andersrum, is ja egal...) und man müsse das Register nach jedem Auslesen von Hand löschen. Hat jetz zwar damit nix zu tun, aber interessieren würds mich nun schon , welche Aussage stimmt...

biguser

Intermediate

  • "biguser" is male

Posts: 318

Date of registration: Nov 25th 2002

  • Send private message

member since 126 month member since 126 month member since 126 month member since 126 month member since 126 month member since 126 month member since 126 month

10

Wednesday, October 1st 2003, 6:55pm

Hi Turrican...

ich würde das Kollisionsregister als erstes auslesen, und in eine separate Speicheradresse kopieren, und alle weiteren Zugriffe im aktuellen Frame auf die Kopie legen. Nach dem erstellen der Kopie (war glaube besser), sollte das Register gelöscht werden. Beim nächsten Framedurchlauf sollte die Kopie mit einem neuem Wert aus den Kollisionsregistern gefüttert werden. Das gilt für beide Register.

Bei den Sprite-Sprite Kollisionsregister hast du aber eventuell ein Problem. Es sagt dir zwar, das ein Sprite mit einem anderen kollidiert, aber es sagt dir nicht mit welchem. Bei zwei Sprites mag das noch gehen, aber bei drei geht das nicht. Fast jedes bessere Spiel macht das ganze über einen Vergleich der Sprite-Koordinaten.

tecMO: Bist du der Plush tecMO? Warst du nicht mal auf einer der Plushpartys von MeisterV.O. & Ironman?

tecM0

Unregistered

11

Wednesday, October 1st 2003, 7:11pm

Quoted

tecMO: Bist du der Plush tecMO? Warst du nicht mal auf einer der Plushpartys von MeisterV.O. & Ironman?


JA und JA...siehe AVATAR....mein gott, das reimt sich ja ;)

Dr.Creep

Unregistered

12

Wednesday, October 1st 2003, 11:07pm

Quoted

Original von biguser
Es sagt dir zwar, das ein Sprite mit einem anderen kollidiert, aber es sagt dir nicht mit welchem.


Hallo,
nach meinen Informationen kann man durch Auslesen des Registers 30 ($1E) schon feststellen, welche Sprites an einer Sprite-Sprite-Kollision beteiligt sind. Dann sind die entsprechenden Bits in dem Register gestetzt (Vorsicht: Nach dem Auslesen wird das Register automatisch zurüchgesetzt, also Wert zwischenspeichern).

Zuordnung Reg. $1E:

Bit 0: Sprite 0 beteiligt
Bit 1: Sprite 1 beteiligt
Bit 2: Sprite 2 beteiligt
Bit 3: Sprite 3 beteiligt
Bit 4: Sprite 4 beteiligt
Bit 5: Sprite 5 beteiligt
Bit 6: Sprite 6 beteiligt
Bit 7: Sprite 7 beteiligt

Es können nie 3 Sprites geichzeitig kollidieren, zuerst treffen immer 2 aufeinander, da ein Programm sequenziell abgearbeitet wird.
Man muß natürlich auf's Timing bei der Abfrage achten (i.d.R. wird man das per Interrupt steuern).


Gruß,
Dr.Creep

biguser

Intermediate

  • "biguser" is male

Posts: 318

Date of registration: Nov 25th 2002

  • Send private message

member since 126 month member since 126 month member since 126 month member since 126 month member since 126 month member since 126 month member since 126 month

13

Thursday, October 2nd 2003, 11:52am

Ich hab mir das Register mal genauer angeschaut:

Erstmal hab ich eine Website Konsultiert, die den VIC recht genau beschreibt: (http://www.minet.uni-jena.de/~andreasg/c64/c64_vic_html.htm).

Dort steht:

- $d01e Sprite-Sprite-Collision
if sprites collided, here you see which sprites that were;
the corresponding bits gets high(1);
after reading you have to clear the bits because they don't clear themself;

- $d01f Sprite-Background-Collision
if sprites collide with a backgroundsign the corresponding bits get high;
also like in $d01e you've to clear bit's after reading the;


Nun hab ich ein kleines Testprogramm geschrieben.
Das ergebnis ist, das nach dem auslesen des Registers, es schon gelöscht wird. Warum man es selbst nochmal tun soll, weiß ich nicht. Mein Testprogram nutzte 3 Sprites, und die Testumgebung war der Vice Emulator. In der Schnelle hab ich es nicht auf einem echten 64'er getestet. Gab es vielleicht mal einen VIC II der etwas anders bei den Kollisionsregistern reagierte, oder warum sollte man diesen selbst löschen? Insofern stimme ich Dr. Creep zu.

>Es können nie 3 Sprites geichzeitig kollidieren,
>zuerst treffen immer 2 aufeinander, da ein Programm
>sequenziell abgearbeitet wird.
>Man muß natürlich auf's Timing bei der Abfrage achten
>(i.d.R. wird man das per Interrupt steuern).
Der Theorie nach stimmt es, bringt aber einige Probleme mit sich. Es hängt auch etwas von der Codestruktur ab.

1. Bewege ich einen Sprite, und schaue gleich ob er kollidiert, dann mag das gehen.
2. Bewege ich erst alle Sprites, und prüfe danach alle Kollisionen, wirds nicht mehr klappen. Welcher Sprite nun mit welchem? *beiß in Tastatur* Das Programm wird auch sequenziell abgearbeitet, aber es klappt nicht.

Auch erste Methode kann hinterlistig sein.
Gehen wir mal davon aus, wir haben ein Hauptprogramm das sequenziell abgearbeitet wird. Unser Programm befindet sich gerade auf der Rasterzeile #$70. Dort bewegt es Sprite 1 auf Y Position #$c0. Es prüft, ob eine Kollision mit Sprite 2 stattgefunden hat, welches auch bei #$c0 liegt. Das Programm ist jetzt vielleicht in Rasterzeile #$72, durch den Rechenzeitverbrauch, angelangt. Falls man nun prüft, ob eine Kollision stattgefunden hat, bekommt man ein "NEIN" zurück und man verschiebt Sprite 1. Doch warum ist das so? Der VIC setzt die Bits des Kollisionsregisters immer erst dann, wenn er dieses Sprite gerade zeichnet. Das geschieht also erst ab Rasterzeile #$c0. Erst jetzt wird die Kollision ins Register geschrieben. Beim nächsten Framedurchlauf würden wir dann den Wert erhalten, aber zu spät, da wir die Sprites schon ineinander verschoben haben. Wenn man das ganze nun noch mit Sprite 2 & 3 macht, ist der wahnsinn völlig komplett. So passiert es auch bei sequenzieller Abarbeitung, das 3 Sprites gleichzeitig kollidieren können, ohne das das Hauptprogramm es über die Kollisionsregister gleich mitbekommt.

Richtig kompliziert wirds dann, wenn man Spritemultiplexer nutzt. Ich fürchte, das alles was man versucht komplizierter wird, als durch den Vergleich von Koordinaten. Es ist auch besser eine Kollision vorher zu wissen (vor der Speicherung in die eigentlich X & Y Koordinate) und danach die Bewegung des Sprites zu koordinieren. Sicher hängt es auch stark davon ab, was man machen möchte.

Im Grunde wollte ich nur damit sagen, das du nach einer Verschiebung den Kollisionswert nicht sofort bekommst, sondern verzögert. Die Verzögerung ist um so größer, je weiter die Rasterzeilen-Position des Kollisionscodes von der Rasterzeilen-Position des Sprites entfernt ist. Das ist eben das Hauptproblem, welches man beim Vergleich mit Koordinaten nicht hat.

Wenn ich Unrecht habe, lass ich mich gerne belehren. Man lernt nie aus!

Gruss,
BGU / PTV

Dr.Creep

Unregistered

14

Thursday, October 2nd 2003, 3:31pm

@biguser:

Hallo,
Meine Aussage, dass sich bei sequenzieller Abarbeitung eines Programmes nur 2 Sprites berühren können war etwas vorschnell und leider falsch :(.
Habe mir folgendes überlegt: Man hat ein Sprite welches nur aus einer 1 Pixel hohen Linie besteht (Breite 24 Pixel). Außerdem haben wir 7 weitere Sprites die jeweils aus nur einem Pixel bestehen. Die sieben 1-Pixelsprites sind alle dicht nebeneinander angeordnet und das lange "Strichsprite" bewegegt sich z.B. von unten her in Richtung der dicht nebeneinander positionierten übrigen Sprites. Es kommt zu Kollision und es sind alle 8 Sprites beteiligt!
Mit einer kleinen programmtechnischen Maßnahme kann man dennoch feststellen wer mit wem kollidiert ist.

1. Man muß den Intterupt der VIC für die Kollisionsabfrage nutzen
2. Man muß vor der Bewegung eines Sprites dessen Nummer in eine Speicherstelle schreiben

Findet nun z.B. die oben genannte Kollision statt, so wird ein Interrupt ausgelöst, welcher das Kollisionsprogamm aufruft. Hier muß man erstens das Sprite-Sprite-Kollisionsregister auslesen. Wenn man feststellt, dass mehr als ein Sprite an der Kollision beteiligt ist, liest man zusätzlich die Speicherzelle mit der Nummer des zuletzt bewegtem Sprites aus. Nun kann man sicher sein, dass nur das zuletzt bewegte Sprite mit allen anderen kollidiert ist und die übrigen sich (bisher) nicht gegenseitig berührt haben.

Bei der Überlegung bin ich nur von den "normalen" 8 Sprites ausgegeangen und nicht von mehr (über Rasterzeilen Interrupt verdoppelte Sprites).


Gruß,
Dr.Creep

This post has been edited 1 times, last edit by "Dr.Creep" (Oct 2nd 2003, 3:32pm)


Turrican

Unregistered

15

Friday, October 10th 2003, 11:56pm

Danke für die Tips...
Werde mir das alles mal bei Gelegenheit zu Gemüte führen ;)

biguser

Intermediate

  • "biguser" is male

Posts: 318

Date of registration: Nov 25th 2002

  • Send private message

member since 126 month member since 126 month member since 126 month member since 126 month member since 126 month member since 126 month member since 126 month

16

Saturday, October 11th 2003, 10:50am

Hi DR.Creep

Das Problem ist mit dem merken des letzten bewegten Sprites auch nicht getan, fürchte ich. Es bringt immer noch extrem viele Probleme mit sich. Du schließt bei deiner Methode generell immer eine Kollision der anderen Sprites aus. Was ist aber, wenn diese Bonussymbole sind, die sich überlappen dürfen?

Ausserdem hast du immer noch das Problem, das du auf das Ergebniss der Kollision warten musst, da diese erst gesetzt wird, wenn der Sprite gezeichnet wird.

Deine Methode würde funktionieren, wenn man immer nur einen Sprite pro Frame bewegt. Es funktioniert aber nicht bei mehreren im selben Frame. Angenommen du merkst dir den zu bewegenen Sprite, bewegst ihn dann und er überlappt einen anderen Sprite. Du reagierst im Maincode aber nicht auf die Kollision, sondern über den VIC SPR-Collinterrupt. Dieser Korrigiert aber den Sprite noch nicht, da der Rasterstrahl den zu zeichnenden Sprite noch nicht erreicht hat! Dein Maincode macht also einfach weiter, und merkt sich erneut den letzten bewegten Sprite, und somit ist die wichtige Information von der letzten Kollision verloren.

Falls du die Struktur anders meintest, würde ich gerne wissen wie. Ich hab keine Methodik gefunden bei der es akkurat klappt.

Nichts für Ungut.

Dr.Creep

Unregistered

17

Saturday, October 11th 2003, 11:52am

Hallo Big User,
bin in letzter Zeit schon wie wild am experimentieren und programmieren, was Kollisionsabfragen angeht.
Finde das Thema äußerst interessant.

In folgendem hast Du recht: Natürlich wird ein Interrupt erst ausgelöst, wenn eine Kollision erfolgt ist, d.h mindestens eine 1-Pixel Überschneidung stattgefunden hat (wenn auch nur für den Bruchteil einer Sekunde).
Aber ab jetzt greift die programmierte Interrupt-Service-Routine und man kann auf die Kollision reagieren ohne das irgendein weiteres
Sprite auch nur um einen Bildpunkt weiter bewegt wird. Man kann nun z.B. das zuletzt bewegte Sprite, welches ja den Interrupt ausgelöst hat, wieder in die vorherige Positon zurückbewegen (hierzu muß man entweder die Koordinaten oder die Bewegungsrichtung vor der Spritewewegung zwischenspeichern). Erst nach Abarbeitung der interrupt-Routine wird ins Hauptprogramm zurückgekehrt und es wird (eventuell) ein weiteres Sprite bewegt (von dem man sich dann auch wieder die Nummer und Koordinaten vor der Bewegung) zwischenspeichert. Der nächte Interrupt kann ja frühestens nach der Bewegung erfolgen. So gehen keine Informationen verloren.

Wenn sich noch andere Sprites überlappen (und dieses auch dürfen), dann lösen die zwar auch einen Interrupt aus aber man kann ja entsprechen anders darauf reagieren.

Um nochmal auf die Ursprungsfrage zurück zu kommen:
Die Aussage von Hannez, dass die Register nicht zu gebrauchen sind ist falsch. Sie funktionieren perfekt auch eine Überschneidung von nur einem Pixel wird sicher erkannt. Man muß nur eine geeignete Abfrage per Interrupt dafür programmieren (eine einfache Abfrage etwa in Basic ist natürlich viel zu ungenau und führt zu Timingproblemen).

Ich werde mal ein kleines Beispielprogramm schreiben, bei dem man mittels Register und Interrupt ein bewegtes Sprite durch ein Hindernis (Hintergrund) stoppt.

Gruß,
Dr.Creep

biguser

Intermediate

  • "biguser" is male

Posts: 318

Date of registration: Nov 25th 2002

  • Send private message

member since 126 month member since 126 month member since 126 month member since 126 month member since 126 month member since 126 month member since 126 month

18

Saturday, October 11th 2003, 12:43pm

Am meisten würde mich ein Demo interessieren, bei dem alle 8 Sprites unkontrolliert umherfliegen, und bei Berührung sich voneinander abstossen, ohne das sie sich verkeilen. Das halte ich für relativ unmöglich. Ich wüßte nicht, wie man das ordentlich ohne Koordinaten Kollision machen sollte, da man bei solchen Anforderungen immer EINEN Kollisionszustand aller Sprites pro Frame aufbaut, mit dem man dann das Abprallverhalten der Sprites steuert.

Auch scheint mir es unmöglich, das bei der Kollision enstehende Wackeln der Sprites zu beseitigen, da sie bei einer Kollision schon dargestellt und dann zurückgeschoben werden.

Quoted

Aber ab jetzt greift die programmierte Interrupt-Service-Routine und man kann auf die Kollision reagieren ohne das irgendein weiteres Sprite auch nur um einen Bildpunkt weiter bewegt wird

Wieso, der Code der alle Sprites verschiebt, ist doch schon lange durch, und hat in dem Frame alle Sprites verrückt. Der Kollisions IRQ kommt erst viel zu spät.

Angenommen der Maincode verschiebt ALLE Sprites im Rasterbereich von $10 bis $20. Die erste Spritecollision entsteht aber erst bei $100. Viel zu spät um zu reagieren, denn es könnten zig Sprites übereinander liegen. Da nütz es auch nicht, wenn der IRQ den Maincode unterbricht, der vielleicht gerade bei einem möglichen Scroller sein könnte.

Irgendwie hadere ich da an deinem Konzept, oder ich verstehe ein wichtiges Detail nicht ganz. :)

Dr.Creep

Unregistered

19

Saturday, October 11th 2003, 3:04pm

Quoted

Original von biguser
Angenommen der Maincode verschiebt ALLE Sprites im Rasterbereich von $10 bis $20. Die erste Spritecollision entsteht aber erst bei $100.


Ok, wenn man von so schnellen Spritebewegungen ausgeht, dann müßte man das ganze sowieso mit dem Rasterstrahl synchronisieren (auch damit kein lästiges Geflackere entstehen kann), so ist man sicher, dass jedes Sprite pro Bildaufbau maximal um 1 Pixel bewegt wird.

Mit der unkontollierten Bewegung aller Sprites habe ich mir noch keine tieferen Gedanken gemacht, da sehe ich natürlich auch die Gefahr der Verkeilung.
Allerdings, was verstehst Du unter unkontrollierter Bewegung? Dazu ist ein Computer doch gar nicht in der Lage, der Computer hat immer die Kontrolle über die Bewegung, sonst könnte er die Sprites gar nicht darstellen. Oder meinst Du eine (Pseudo-) zufallsgeteuerte Bewegung?

Gruß,
Dr.Creep

biguser

Intermediate

  • "biguser" is male

Posts: 318

Date of registration: Nov 25th 2002

  • Send private message

member since 126 month member since 126 month member since 126 month member since 126 month member since 126 month member since 126 month member since 126 month

20

Saturday, October 11th 2003, 5:13pm

Quoted

was verstehst Du unter unkontrollierter Bewegung?

Unkontrolliert war das falsche Wort. Unkontrollierte Bewegungen gibt es immer dann, wenn sich irgendwo ein Bug eingeschlichen hat :) Ich hätte eher das wort "wild" nehmen sollen. Das passt besser.

Quoted

so ist man sicher, dass jedes Sprite pro Bildaufbau maximal um 1 Pixel bewegt wird.

Ist das nicht eine zu grosse Einschränkung? Was ist, wenn Sprites (BSP: in Shootern) sich auf Sinuskurven bewegen, die ja nicht immer Pixelweise sind.

Quoted

Ok, wenn man von so schnellen Spritebewegungen ausgeht

Oh, ich glaube du hast mich missverstanden. Das Hauptprogramm läuft im "Idealfall" auch synchron zum Bildschirmaufbau. Daher kann es sein, das eine Spritemovement Routine relativ Konstant bei Rasterstrahlposition $10 bis $20 ausgeführt wird, die alle Sprites, je nach ihrer Geschwindigkeit verschiebt. Durch den Rechenzeitverbrauch, wird die ROutine erst in nachfolgenden Rasterzeilen beendet. Die Verschiebung aller Sprites, könnte so ab Rasterzeile $20 beendet sein, ohne das bisher Kollisionen aufgetreten waren.