Mehrere Schüsse

Moderator: Rockford

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

Mehrere Schüsse

Beitrag von Dr. Irata »

Folgendes Problem möchte ich hier mal diskutieren, da ich zwar eine Lösung für mich gefunden habe, die aber recht umständlich und aufwendig und nicht ganz fehlerfrei erscheint:

In Assembler möchte ich einen Player mehrere Schüsse feuern lassen. Also maximal 4 zum Beispiel. Nun fragt man also den Strig0 ab und wenn der gedrückt wurde geht Schuss1 los. Beim nächsten drücken dann Schuss2 usw.
Die laufenden Schüsse sind so lange blockiert, bis sie auf ein Hindernis gestossen sind und eine Aktion auslösen oder hinten aus dem Bildrand rausgelaufen sind und dann wieder für einen neuen Schuss zur Verfügung stehen. So simpel sich das anhört, so kompliziert finde ich die Umsetzung.

Ähnlich wie be den Zufallszahlen könnte ich mir hier etliche sehr gute Ansätze vorstellen... bin gespannt auf Eure Ideen.
Gruß
Peter

Benutzeravatar
cas
Beiträge: 813
Registriert: 18.06.2021 21:01
Wohnort: Solar System
Has thanked: 181 times
Been thanked: 362 times
Kontaktdaten:

Re: Mehrere Schüsse

Beitrag von cas »

Hallo Peter,

ich habe keinen Programmcode, nur Ideen: es gibt die Möglichkeit, das Schüsse nur eine bestimmte Reichweite haben und "verschwinden" und wieder zur Verfügung stehen. Man muss nicht warten, bis die Schüsse den Bildschirmrand erreichen.

Das Hauptprogramm fragt STRIG(0) ab, setzt den Start-Wert (x/y/count) in Variablen/Speicherstellen.

Im VBI werden X oder/und Y angepasst und "count" heruntergezählt. Wenn "count" == 0, wird der Schuss "ausgeschaltet" und steht wieder zur Verfügung. Kollisions-Abfrage kann im VBI oder im Hauptprogramm geschehen, das Hauptprogramm muss sich nicht mit der Verwaltung der Schüsse beschäftigen.

Beste Grüsse

Carsten

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

Re: Mehrere Schüsse

Beitrag von Dr. Irata »

Meine umständliche Lösung sieht aktuell so aus für 2 Schüsse:

Für die gleichmäßige Bewegung nehme ich den VBI - meine Schüsse laufen von rechts nach links, daher muss ich nur den x-Wert incementieren.
Damit der Schuss schneller läuft incrementiere ich 2x!

Diese Routine steht im VBI:

Code: Alles auswählen

			;	m1index:
   			;	0 = kein Schuss
			;	1 =	nur Schuss1 läuft
			;	2 = Schuss1 und 2 laufen
			;	3 = nur Schuss2 läuft
   			
   			#if .byte m1index=#3 .or .byte m1index=#2
			mva xposm2 hposm1
			inc xposm2
			inc xposm2
			#end
   			
			#if .byte m1index=#1 .or .byte m1index=#2
			mva xposm1 hposm0
			inc xposm1
			inc xposm1
			inc m2index
			#end
			
Die folgende längere Routine wird im Hauptprogramm abgearbeitet:

Code: Alles auswählen

							;Schuss1 
			
			#if .byte m1index=#0
			#if .byte strig0=#0
			mva xposp1 xposm1
			ldy yposp1
			iny
			iny
			iny
			iny
			iny
			sty yposm1
			lda #170
			sta (miss1),y
			iny
			sta (miss1),y
			inc m1index
			#end
			jmp ex
			#end
			
			#if .byte m1index=#3
			#if .byte strig0=#0
			mva xposp1 xposm1
			ldy yposp1
			iny
			iny
			iny
			iny
			iny
			sty yposm1
			lda #170
			sta (miss1),y
			iny
			sta (miss1),y
			dec m1index
			#end
			jmp ex
			#end
							;Schuss2

			#if .byte m1index=#1 .and .byte m2index>#40
			#if .byte strig0=#0
			mva xposp1 xposm2
			lda #85
			ldy yposp1
			iny
			iny
			iny
			iny
			iny
			sty yposm2
			sta (miss1),y
			iny
			sta (miss1),y
			inc  m1index
			#end
			#end
ex			
			;	m1index:
   			;	0 = kein Schuss
			;	1 =	nur Schuss1 läuft
			;	2 = Schuss1 und 2 laufen
			;	3 = nur Schuss2 läuft
   			
			#if .byte xposm1>#240
			lda #0 
			sta xposm1
			sta hposm0
			ldy yposm1
			mva #0 (miss1),y
			iny
			mva #0 (miss1),y
			inc m1index
			#if .byte m1index=#2
			lda #0 
			sta m1index
			#end
			#end
			
			#if .byte xposm2>#240 
			lda #0 
			sta xposm2
			sta hposm1
			dec m1index
			ldy yposm2
			mva #0 (miss2),y
			iny
			mva #0 (miss2),y
			#if .byte m1index=#2
			lda #0 
			sta m1index
			sta m2index
			#end
			#end
m1index und m2index beschreiben den Zustand von Schuss1 und Schuss2 - also läuft der jeweilige Schuss gerade.
Wenn die x-Position über 240 ist, dann ist der Bildrand erreicht und der jeweilige Schuss wird auf den entsprechenden Index gesetzt.
Das Gleiche (dann mit einer Aktion) passiert auch. bei einer Kollision, die ich woanders abfrage.

Insgesamt finde ich das zu umständlich programmiert, mir ist aber nichts besseres im Moment eingefallen.
Meine Routine bei Battle of Eris war noch koplizierter...

Benutzeravatar
Kveldulfur
Beiträge: 624
Registriert: 17.08.2021 02:32
Has thanked: 237 times
Been thanked: 163 times
Kontaktdaten:

Re: Mehrere Schüsse

Beitrag von Kveldulfur »

Hi!

Ich möchte hier auch meine Variante vorstellen, wie ich in meinem neuem Spiel die Missiles nutze. Wobei ich wahrscheinlich es noch einmal ändern muss, weil es zuviele mögliche Schüsse sind :-)

Im Prinzip ist es bei mir 3-teilig.

1) Auslöseroutine
2) Bewegungsroutine
3) Kollisionsroutine

Für die Missiles lege ich mir 4 Variablen an, wobei theoretisch 3 reichen würden:
1) X-Position des Missile
2) Y-Position des Missile
3) Flugrichtung des Missile
4) Status des Missile

Der PM-Speicherstart für die Missiles wird in der Variable "Missiles" hinterlegt.

Code: Alles auswählen

PMMemBase		EQU $2000				; $2000 bis $27FF 
Missiles		EQU PMMemBase+$300		
Player0			EQU PMMemBase+$400
Player1			EQU PMMemBase+$500
Player2			EQU PMMemBase+$600
Player3			EQU PMMemBase+$700
MissilesX		.DS 4
MissilesY		.DS 4
MissilesRi		.DS 4
MissilesStat		.DS 4
Die Auslöseroutine:

Diese prüft in einer Schleife, welcher Missile ungenutzt ist (MissilesStat). Der erste ungenutzte Missiles wird im X-Register hinterlegt.

Code: Alles auswählen

		LDX #3				; freien Schuss suchen
@		LDA MissilesStat,X		
		BEQ MissileSetzen		; freier Missile gefunden
		DEX
		BPL @-
		JMP MissileNichtfrei		; es konnte kein freier Missile gefunden werden
Dadurch ist es egal, welcher der Missiles frei geworden ist, er wird gefunden ;-)

Die Routine setzt nun das Missile und die entsprechenden Variablen.

Code: Alles auswählen

MissileSetzen	LDA #1				; Missile als aktiv markieren
		STA MissilesStat,X

		LDA PlayerX			; Missile X setzen
		STA MissilesX,X
		STA HPOSM0,X

		LDA PlayerY			; Missile Y setzen
		STA MissilesY,X
		TAY
		LDA Missiles,Y			; Missiles im Speicher lesen
		ORA ShootPixel,X		; Bits holen
		STA Missiles,Y			; und zurück speichern
		
		und Richtung...
		STA MissilesRi,X
		
		...
		...
ShootPixel	DTA %00000011
		DTA %00001100
		DTA %00110000
		DTA %11000000
		
Da mein Spieler oft auf der selben Höhe seine Schüsse abgibt, ist es wichtig den Missile per ORA hinzuzufügen.

Wenn ein Missile gesetzt wurde, wird es automatisch in der Bewegungsroutine bis zum Bildschirmrand in der angegebenen Richtung bewegt.
Am Rand angekommen, wird das Missile gelöscht und der Status auf Inaktiv gesetzt:

Code: Alles auswählen

ShootOff	LDA #0
		STA MissilesStat,X		; Status auf 0 = Inaktiv
		LDA MissilesY,X			; Y-Position holen
		TAY
		LDA Missiles,Y			; Missile aus Speicher laden
		AND ShootMask,X			; per Maske löschen
		STA Missiles,Y			; zurück sichern
		
		...
		...
		
ShootMask	DTA %11111100
		DTA %11110011
		DTA %11001111
		DTA %00111111		
Wie man ein Missile bewegt und die Kollision prüft, sollte bekannt sein.
Beim Bewegen gehe ich übrigens wieder eine Schleife von 3-0 durch und prüfen über den Status, welcher Missile bewegt werden muss.
Bei der Kollision müssen ebenfalls nur aktive Missiles geprüft werden.

Möchte man den Missile nach 20 Schritten wieder löschen, kann man leicht in einer weiteren Variable die Anzahl der Schritte sich merken und dann den Missile löschen.

Ich hoffe ich konnte so in etwa aufzeigen, wie ich es mache :-)

Grüße
Janko

Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast