... bräuchte ich für folgendes Problem:
Ich bewege mich in Antic 4 - also Charaktergrafik.
An einer bestimmten Position des Bildschirmes ist ein Zeichen gesetzt. An dieser Position soll jetzt durch z.B. eine Kollision mit einem Player eine Folge von anderen Charaktern gesetzt werden - die Folge ist immer gleich. Nach dem letzten Charakter geht dann ein Leerzeichen an diese Position.
Das soll jetzt aber nicht nur für einen Charakter an einer Stelle funktionieren, sondern für eine fast beliebige Anzahl von Charaktern und die "Folge" darf zwar gleich sein, muss aber unabhängig von den möglichen anderen Treffern laufen!
Klingt eigentlich ganz simpel...
Meine Idee war jetzt... ich höre erstmal, wie ihr das machen würdet... meine Idee ist gefühlt zu aufwendig...
Eine Idee...
Moderator: Rockford
- DjayBee
- Beiträge: 1242
- Registriert: 17.08.2021 04:02
- Has thanked: 948 times
- Been thanked: 491 times
- Kontaktdaten:
Re: Eine Idee...
Soll der Code auch verwalten, ob ein Character überhaupt auf dem Bildschirm vorhanden ist (unabhängig davon, ob gerade eine "Animation" läuft) und an welcher Position er sich befindet oder geht's dir nur um die Verwaltung von beliebig vielen Animationen?
- Kveldulfur
- Beiträge: 1119
- Registriert: 17.08.2021 02:32
- Has thanked: 580 times
- Been thanked: 525 times
- Kontaktdaten:
Re: Eine Idee...
Hallo!
Die Frage ist natürlich wie immer, wie du das Scrolling realisierst. Ist das Spielfeld komplett im RAM vorhanden oder wird es mehr oder weniger dynamisch erzeugt?
Bei [Schranken 3 + 4] habe ich meine geliebten Bomben (von Mr. Robot) eingebaut. Diese explodieren nach einiger Zeit, wenn man darüber gelaufen ist. Bei beiden Spielen ist das Spielfeld komplett im RAM enthalten, womit ich mir also nur merken muss, an welcher Speicherstelle welche aktivierte Bombe steht. Inaktive Bomben sind uninteressant. Wenn der Spieler über eine Bombe läuft, wird diese aktiviert und in eine Tabelle an einer freien Stelle geschrieben.
Dafür habe ich drei Tabellen mit maximal 50 Einträgen:
Tabelle 1: Der Status
0 = inaktiv bzw. frei
1 = Frame 1 + Soundeffekt starten
2 = Frame 2
3 = Frame 3
...
6 = Frame 6 = leeres Feld
7 = wait
8 = wait
9 = reset = Bombe darstellen und Status auf 0 setzen
Tabelle 2: Die Adresse
Hier wird die Adresse einer Bombe hinterlegt, die ich aktiviert habe (Word).
Tabelle 3: Die Zeit
Hier ist ein Zähler enthalten, der immer auf 0 herunterläuft und bei 0 erst das Ereignis (z. B. Framewechsel) auslöst.
Die Zeit nutze ich, weil meine Bomben respawnen. Außerdem kann man so die Animation verlangsamen usw.
50 Einträge bedeuten viel Aufwand. Da bei mir alles immer erst nach dem Bildaufbau ausgeführt wird, wird diese Schleife, in der ich den Status der Tabelle prüfe, alle 1/50 Sekunden ausgeführt. Und damit es nicht so viel Rechenzeit einnimmt, teile ich die Tabelle auf:
1/50 s → Position 0, 3, 6, 9, 12 ...
2/50 s → Position 1, 4, 7, 10, 13 ...
3/50 s → Position 2, 5, 8, 11, 14 ...
... und dann wieder von vorne
Das heißt, die Animation kann sich frühestens alle 3/50 s weiterdrehen. Wenn also eine Animation startet, läuft alles automatisch, bis sie wieder zurückgesetzt ist.
Wenn du das Spielfeld nicht komplett im RAM hast, sondern dynamisch aufbaust, müsste das Konzept dennoch funktionieren, da sich innerhalb des Bildes die Speicherstelle nicht verändert. Ich bin mir da gerade nicht ganz sicher, denke aber schon. Man müsste nur, sobald die Explosion aus dem Bild verschwindet, den Status zwangsweise auf 0 setzen, weil sonst die Explosion oben wieder erscheint
Grüße
Janko
Die Frage ist natürlich wie immer, wie du das Scrolling realisierst. Ist das Spielfeld komplett im RAM vorhanden oder wird es mehr oder weniger dynamisch erzeugt?
Bei [Schranken 3 + 4] habe ich meine geliebten Bomben (von Mr. Robot) eingebaut. Diese explodieren nach einiger Zeit, wenn man darüber gelaufen ist. Bei beiden Spielen ist das Spielfeld komplett im RAM enthalten, womit ich mir also nur merken muss, an welcher Speicherstelle welche aktivierte Bombe steht. Inaktive Bomben sind uninteressant. Wenn der Spieler über eine Bombe läuft, wird diese aktiviert und in eine Tabelle an einer freien Stelle geschrieben.
Dafür habe ich drei Tabellen mit maximal 50 Einträgen:
Tabelle 1: Der Status
0 = inaktiv bzw. frei
1 = Frame 1 + Soundeffekt starten
2 = Frame 2
3 = Frame 3
...
6 = Frame 6 = leeres Feld
7 = wait
8 = wait
9 = reset = Bombe darstellen und Status auf 0 setzen
Tabelle 2: Die Adresse
Hier wird die Adresse einer Bombe hinterlegt, die ich aktiviert habe (Word).
Tabelle 3: Die Zeit
Hier ist ein Zähler enthalten, der immer auf 0 herunterläuft und bei 0 erst das Ereignis (z. B. Framewechsel) auslöst.
Die Zeit nutze ich, weil meine Bomben respawnen. Außerdem kann man so die Animation verlangsamen usw.
50 Einträge bedeuten viel Aufwand. Da bei mir alles immer erst nach dem Bildaufbau ausgeführt wird, wird diese Schleife, in der ich den Status der Tabelle prüfe, alle 1/50 Sekunden ausgeführt. Und damit es nicht so viel Rechenzeit einnimmt, teile ich die Tabelle auf:
1/50 s → Position 0, 3, 6, 9, 12 ...
2/50 s → Position 1, 4, 7, 10, 13 ...
3/50 s → Position 2, 5, 8, 11, 14 ...
... und dann wieder von vorne
Das heißt, die Animation kann sich frühestens alle 3/50 s weiterdrehen. Wenn also eine Animation startet, läuft alles automatisch, bis sie wieder zurückgesetzt ist.
Wenn du das Spielfeld nicht komplett im RAM hast, sondern dynamisch aufbaust, müsste das Konzept dennoch funktionieren, da sich innerhalb des Bildes die Speicherstelle nicht verändert. Ich bin mir da gerade nicht ganz sicher, denke aber schon. Man müsste nur, sobald die Explosion aus dem Bild verschwindet, den Status zwangsweise auf 0 setzen, weil sonst die Explosion oben wieder erscheint
Grüße
Janko
Meine Projekte findest Du hier...
- Dr. Irata
- Beiträge: 1386
- Registriert: 24.08.2021 14:40
- Has thanked: 208 times
- Been thanked: 513 times
- Kontaktdaten:
Re: Eine Idee...
Tatsächlich wird der BS gescrollt mit DL-Manipulation. Das Bild liegt nicht im Speicher, sondern wird dynamisch aufgebaut...
- Dr. Irata
- Beiträge: 1386
- Registriert: 24.08.2021 14:40
- Has thanked: 208 times
- Been thanked: 513 times
- Kontaktdaten:
Re: Eine Idee...
... so etwas ähnliches hatte ich mir gestern schon überlegt, ein Handler, der das alles steuert. Mit einem Speicherbereich, wo die Positionen und der Status gespeichert ist. Mir war klar, daß es so gehen kann, es bedeutet aber leider auch einen großen Rechenaufwand... ich hatte hier auf eine elegante "einfache" Möglichkeit/Idee gehofft.
Janko - wir sprachen damals über dein Zeitproblem... jetzt verstehe ich das! Deine Routine hat da ne Menge zu tun
Leider kann man einem Charakter keinen echten Status mitgeben...
Janko - wir sprachen damals über dein Zeitproblem... jetzt verstehe ich das! Deine Routine hat da ne Menge zu tun
Leider kann man einem Charakter keinen echten Status mitgeben...
- DjayBee
- Beiträge: 1242
- Registriert: 17.08.2021 04:02
- Has thanked: 948 times
- Been thanked: 491 times
- Kontaktdaten:
Re: Eine Idee...
Hast du genug Zeichen im Zeichensatz verfügbar, dass du für jedes unterschiedliche Zeichen alle Bewegungsschritte speichern kannst?
Dann kannst du für jede Instanzierung auf dem Bildschirm ein Statusbyte in einer Tabelle nehmen.
0=ganz normal
1 bis n=Bewegungsschritt
-1 bzw. $ff=Leerzeichen bzw. derzeit nicht aktiv
Die Schritte zählst du dann im VBI rückwärts und wenn du bei 0 ankommst, setzt du es auf -1 und schreibst ein Leerzeichen auf den Schirm.
Das Byte ist dann auch der Zeiger in den Zeichensatz, relativ zum "Hauptzeichen".
Die Adresse des Zeichens würde ich auftrennen in zwei Tabellen. Dadurch kannst du alle Tabellen absolut,X oder absolut,Y adressieren. Das ist schneller als (indirekt),Y und du musst nicht jedes Mal den Pointer in der Zeropage setzen.
Das Schreiben des Zeichens selbst muss dann natürlich trotzdem indirekt erfolgen.
Dann kannst du für jede Instanzierung auf dem Bildschirm ein Statusbyte in einer Tabelle nehmen.
0=ganz normal
1 bis n=Bewegungsschritt
-1 bzw. $ff=Leerzeichen bzw. derzeit nicht aktiv
Die Schritte zählst du dann im VBI rückwärts und wenn du bei 0 ankommst, setzt du es auf -1 und schreibst ein Leerzeichen auf den Schirm.
Das Byte ist dann auch der Zeiger in den Zeichensatz, relativ zum "Hauptzeichen".
Die Adresse des Zeichens würde ich auftrennen in zwei Tabellen. Dadurch kannst du alle Tabellen absolut,X oder absolut,Y adressieren. Das ist schneller als (indirekt),Y und du musst nicht jedes Mal den Pointer in der Zeropage setzen.
Das Schreiben des Zeichens selbst muss dann natürlich trotzdem indirekt erfolgen.
- LarsImNetz
- Beiträge: 226
- Registriert: 24.08.2021 18:27
- Has thanked: 219 times
- Been thanked: 127 times
- Kontaktdaten:
Re: Eine Idee...
Du hast für den Gegenstand x und y für die Screen Position.
Dann einen Status, ob in Animation oder Auflösung oder was auch immer.
Dann einen Index, der zeigt in eine Tabelle welches Zeichen angezeigt werden soll. Für Auflösungsanimation oder ... hier verwende ich am Ende eine Marke, wenn die Animation zu ende sein soll.
Ich nutze hier mal das X-Register für den Gegenstand der sich irgendwo befinden kann.
Es gibt je eine Tabelle für die X und Y Position (hier 5)
Es gibt für jeden Gegenstand einen Status (hier unvollständig) und einen Index als Animationsregister.
Kannst Du bestimmt beliebig erweitern.
Mein Code ist jetzt erst mal auf 5 Character begrenzt, sollte aber schnell genug sein um 100 oder mehr in einer 1/50s zu bewegen. Mach es nicht im VBI!
Ist die Animation zu schnell, setze in der animation_table einen Wert 2 oder 3 mal hintereinander ein. Also .byte 1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,... die 0 am Ende verwenden wir als Marke fürs Ende, der Code reagiert darauf! So musst Du nicht selbst nochmal zählen.
Je nach Status lassen sich unterschiedliche Animationen unterbringen, die paar doppelten Bytes kann man verschmerzen. Beispiel angegeben, animation_table_2 kannst Du selbst.
Kommt es jetzt zu eine Collision, setzt Du an der entsprechenden Position von status ein 'animation_1' oder 'animation_2' und schon sollte die Animation gestartet werden. Es bleibt Dir überlassen, wie Du herausbekommst, mit welchem Gegenstand Du zusammengestoßen bist.
Der Assembler-Code mag nicht optimal sein, aber in Assembler ist mir das mittlerweile egal, der Atari ist dafür immer noch flott genug.
LG
Lars
Dann einen Status, ob in Animation oder Auflösung oder was auch immer.
Dann einen Index, der zeigt in eine Tabelle welches Zeichen angezeigt werden soll. Für Auflösungsanimation oder ... hier verwende ich am Ende eine Marke, wenn die Animation zu ende sein soll.
Ich nutze hier mal das X-Register für den Gegenstand der sich irgendwo befinden kann.
Es gibt je eine Tabelle für die X und Y Position (hier 5)
Es gibt für jeden Gegenstand einen Status (hier unvollständig) und einen Index als Animationsregister.
Kannst Du bestimmt beliebig erweitern.
Mein Code ist jetzt erst mal auf 5 Character begrenzt, sollte aber schnell genug sein um 100 oder mehr in einer 1/50s zu bewegen. Mach es nicht im VBI!
Ist die Animation zu schnell, setze in der animation_table einen Wert 2 oder 3 mal hintereinander ein. Also .byte 1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,... die 0 am Ende verwenden wir als Marke fürs Ende, der Code reagiert darauf! So musst Du nicht selbst nochmal zählen.
Je nach Status lassen sich unterschiedliche Animationen unterbringen, die paar doppelten Bytes kann man verschmerzen. Beispiel angegeben, animation_table_2 kannst Du selbst.
Kommt es jetzt zu eine Collision, setzt Du an der entsprechenden Position von status ein 'animation_1' oder 'animation_2' und schon sollte die Animation gestartet werden. Es bleibt Dir überlassen, wie Du herausbekommst, mit welchem Gegenstand Du zusammengestoßen bist.
Der Assembler-Code mag nicht optimal sein, aber in Assembler ist mir das mittlerweile egal, der Atari ist dafür immer noch flott genug.
LG
Lars
Code: Alles auswählen
screen=254 ; irgend eine Zeropage Adresse (2 Bytes)
animation_1=1
animation_2=2
normal=42
ldx welcher_gegenstand
ldy y,x
lda vertical_screen_position_table_low,y
sta screen
lda vertical_screen_position_table_high,y
sta screen+1
; hier haben wir jetzt in (screen) die vertikale Position
lda status,x
cmp #animation_1
beq is_animation_1
cmp #animation_2
beq is_animation_2
cmp #normal
beq is_normal
[...] ; hier mehr stati eintragen/pflegen...
is normal
lda #1
bne draw_character
is_animation_1
inc index,x
ldy index,x
lda animation_table_1,y
beq animation_ende
; in (screen) ist nur die vertikale Position an 0. Stelle angegeben,
; die horizontale Position kommt über den Index
draw_character
ldy x,x
sta (screen),y
rts
is_animation_2
inc index,x
ldy index,x
lda animation_table_2,y
beq animation_ende
bne draw_character
animation_ende
lda #normal ; die Animation ist zu ende alles zurücksetzen
sta status,x
lda #0
sta index,x
; lda #0 ; doppelt!
beq draw_character ; springt -> immer weil akku:=0
x
.byte 0,0,0,0,0
y
.byte 0,0,0,0,0
status
.byte 0,0,0,0,0
index
.byte 0,0,0,0,0
animation_table_1
.byte 1,2,3,4,5,6,7,8,9,10,0
vertical_screen_position_table_low
.byte <$BC40, <$BC40+40, <$BC40+80...
vertical_screen_position_table_high
.byte >$BC40, >$BC40+40, >$BC40+80...
Wer ist online?
Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast