Ein kleines Problem mit Kollisonen

Übersicht BlitzBasic Allgemein

Neue Antwort erstellen

 

ninjaKANICKL

Betreff: Ein kleines Problem mit Kollisonen

BeitragMo, Sep 09, 2013 1:48
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo erstmal!

Ich habe mich vor kurzem an die Programmierung eines 2D-vertical Shooters (im Stil von "Ikaruga", wers kennt) gewagt. Bislang lief alles top, doch nun stehe ich vor einem Problem, welches ich nicht lösen kann. Folgendes Szenario:

Feindliche Flugzeuge sollen von oben herabfliegen und vom Spieler abgeschossen werden. Wieviele Flugzeuge auf dem Bildschirm sind, ist unterschiedlich - je nach Timer aund Abschuss. Soweit so gut, also.
Die Flugzeuge sind ein "Type" mit Feldern für die aktuelle X- und Y-Position, sowie Energie, usw.
Die Schüsse des Spielers sind ebenfalls ein Type mit X- und Y-Position.
Noch etwas unerfahren, wie ich bin, dachte ich mir nun, ich könnte ganz simpel die Abschüsse programmieren, indem ich einen Befehl wie "ImagesCollide" o. ä. benutze und diesen mit den aktuellen X und Y Koordinaten der Flugzeuge und Schüsse füttere. Kollidieren diese beiden Images, ist der Abschuss geglückt.
Nur leider funktioniert dies nicht. Trotz "Global" Vereinbarung beider Typen(z.B. Global enemy.flugzeug)erkennt BlitzBasic die Objekte nicht mehr, sobald ich X und Y der beiden Typen miteinander abgleichen lasse. Weiss jemand auf Anhieb, woran das liegen könnte? Die Verwendung von Arrays würde vermutlich einfacher sein, kommte aber für diese beiden Types eigentlich eher nicht in Frage.
Danke im Voraus!
 

Kruemelator

BeitragMo, Sep 09, 2013 3:08
Antworten mit Zitat
Benutzer-Profile anzeigen
Was meinst du mit "erkennt BlitzBasic die Objekte nicht mehr"?
ImagesCollide sollte vermieden werden und wenn nötig durch eine eigene Funktion ersetzt werden.
Sonst ist dein Ansatz richtig.
Um Types nutzen zu können muss man
BlitzBasic: [AUSKLAPPEN]
New

für jedes Type einzeln aufrufen.

BladeRunner

Moderator

BeitragMo, Sep 09, 2013 8:19
Antworten mit Zitat
Benutzer-Profile anzeigen
Da unser aller magische Glaskugeln defekt sind bitte ich Dich um einen Beispielcode der dein Problem zeigt.
Wink
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

DAK

BeitragMo, Sep 09, 2013 9:00
Antworten mit Zitat
Benutzer-Profile anzeigen
Kann es sein, dass du beide Objekte mit der gleichen Variablen benennst?
Gewinner der 6. und der 68. BlitzCodeCompo

Starwar

BeitragMo, Sep 09, 2013 9:36
Antworten mit Zitat
Benutzer-Profile anzeigen
Oder nicht/falsch mit For Each durch die Liste läufst? Quellcode bitte Wink

Hubsi

BeitragMo, Sep 09, 2013 16:20
Antworten mit Zitat
Benutzer-Profile anzeigen
Meine Glaskugel ist gerade aus der Reparatur zurück Wink und meint Du hast die beiden For...Each ineinander verschachtelt und versuchst einen gelöschten Schuss (da er getroffen hatte) im nächsten Durchlauf der Flugzeuge nochmal zu prüfen? Wäre so ein ganz typischer Fehler der oft gemacht wird zumindest. Und wie bereits gesagt ist ImgaesCollide zu vermeiden. Selbst wenn es bei Dir funktioniert kannst Du davon ausgehen das schon der erste "Fremd"spieler einen schönen Absturz erleben darf. Gerade für Schüsse reicht in aller Regel eine einfache Punkt-in-Rechteck-Prüfung. Ist zudem auch viel schneller Smile
Den ganzen Doag im Bett umanandflagga und iaz daherkema und meine Hendl`n fressn...
 

ninjaKANICKL

BeitragMo, Sep 09, 2013 20:12
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke erstmal für die Antworten. Die Genaue Meldung, welche Basic mir ausgibt, ist "Objekt does not exist" mit Markierung auf die Kollisionsabfragzeile. Zur Kontrolle habe ich auch sämtliche "Delete" befehle gestrichen und einfach nur versucht, die derzeitige X bzw. Y Position der Schüsse als Text ausgeben zu lassen (als reiner Test, verseht sich) - auch hier gab es die selbe Meldung. Hat auch nichts mit Uploads zu tun - sobald ich die Kollisionsabfrage mit ihren Komponenten streiche, funktioniert alles einwandfrei. Bin mir sicher, dass es irgendwo ein totaler Anfängerfehler ist, bei dem ich mir nachher an den Kopf fasse Embarassed

Hier sind die beiden Code-Teile (hab zur Übersicht die Dinge weggelassen, die keinen Einfluss auf das Problem haben - deshalb wirkt er hier relativ simpel):

Der Code für die abgegebenen Schüsse:
Code: [AUSKLAPPEN]
   ;;;Upload Grafik für "Player":
   Global Player = LoadAnimImage("...", 56, 58,0 ,5)
   MaskImage Player, 0, 0, 0
   Global Player_XPOS = 300
   Global Player_YPOS = 300
 
   ;;;Upload Grafik für "Schuss":
   Global WPN1_SHOT = LoadImage("...")
   MaskImage WPN1_SHOT, 0, 0, 0
   HandleImage WPN1_SHOT, 0, 10

   ;;;Ein Timer, welcher die Frequenz der Schussrate steuert:
   Global WPN1_SHOT_COUNT

   ;;;Type für Schuss mit X/Y_Position, sowie Geschwindigkeit:
   Type SHOT_1
        Field SHOT_X
        Field SHOT_Y
        Field SHOT_SPD
   End Type

   ;;;Vereinbarung für Schuss
   Global WPN1.SHOT_1

   ;;;Ist der Knopf gedrückt, startet der Timer - hat dieser 5 erreicht, wird er zurückgesetzt und es entsteht ein neuer Schuss:
Function WPN_1_SHOT()
   If KeyDown(2) = 1 WPN1_SHOT_COUNT = WPN1_SHOT_COUNT +1
      If WPN1_SHOT_COUNT >= 5
         WPN1_SHOT_COUNT = 0
         WPN1.SHOT_1 = New SHOT_1
         WPN1\SHOT_X = Player_XPOS+10
         WPN1\SHOT_Y = Player_YPOS
         WPN1\SHOT_SPD = 12
   EndIf

   ;;;Schüsse werden abgefeuert:
   For WPN1.SHOT_1 = Each SHOT_1
         WPN1\SHOT_Y = WPN1\SHOT_Y - WPN1\SHOT_SPD
         DrawImage WPN1_SHOT, WPN1\SHOT_X, WPN1\SHOT_Y

   ;;;Wenn ein Schuss den oberen Bildschirmrand erreicht hat, wird er gelöscht:
      If WPN1\SHOT_Y < 0 Delete WPN1.SHOT_1
   Next
End Function


Und der Code für die gegnerischen Fligzeuge, sowie die Kollisionsabfrage:
Code: [AUSKLAPPEN]
;;;Die Grafik für Enemy:
Global ENM_PLANE = LoadAnimImage("...", 56, 58, 0, 5)

;;;Der Timer, welcher die Frequenz der Gegner steuert:
Global PLANE_TIMER

;;;Datei "Player", in der sich die Schuss-Funktion des Spielers befindet (siehe oberen Code):
Include "..."

;;;Enemy-Typ mit X/Y-Position, Frame und Lebensenergie:
Type ENEMY
   Field X
   Field Y
   Field FRAME
   Field LIFE
End Type

;;;Vereinbarung für Enemy:
Global PLANE.ENEMY

;;;Erreicht der Timer 300, wird er zurückgesetzt und ein neuer Gegner taucht auf einer Zufalls-X-Position auf:
Function EnemyPlane()

PLANE_TIMER = PLANE_TIMER +10
If PLANE_TIMER > 300
PLANE_TIMER = 0
PLANE.ENEMY = New ENEMY
PLANE\X = Rnd(139, 448)
PLANE\Y = -60
PLANE\FRAME = 2
PLANE\LIFE = 100
EndIf

;;;Gegner fliegen nach unten und werden gezeichnet:
For PLANE.ENEMY = Each ENEMY
PLANE\Y = PLANE\Y + 5
DrawImage ENM_PLANE, PLANE\X, PLANE\Y, PLANE\FRAME
EndIf

;;;Hab hier mal einfach "ImagesOverlap" genommen. Wenn ENEMY und SHOT sich treffen, sollen beide gelöscht werden:
If ImagesOverlap (ENM_PLANE, PLANE\X, PLANE\Y, WPN1_SHOT, WPN1\SHOT_X, WPN1\SHOT_Y)
Delete PLANE.ENEMY
Delete WPN1.SHOT_1
EndIf

Next
End Function

Xeres

Moderator

BeitragMo, Sep 09, 2013 20:31
Antworten mit Zitat
Benutzer-Profile anzeigen
Mh, als aller erstes muss man hier ein paar Sachen sortieren...
BlitzBasic: [AUSKLAPPEN]
Type SHOT_1
Field SHOT_X
Field SHOT_Y
Field SHOT_SPD
End Type
Ich würde den Typen eindeutig als solchen bezeichnen und die Felder nicht mit dem Prefix benennen, wenn sie doch gar nicht verwechselt werden können. Besser:
BlitzBasic: [AUSKLAPPEN]
Type TShot_Basic ; "T" Symbolisiert immer eine Type-dekleration, Namen sind besser als Nummern
Field X ; Wenn es schon ein shot ist, kann man per "shot/x" darauf zugreifen. "shot/shot_x" liest sich einfach doof
Field Y
Field SPD
End Type

Weiter:
BlitzMax: [AUSKLAPPEN]
Global WPN1.SHOT_1 
Das ist bestenfalls unnötig, schlechtestenfalls verwirrend. Type-Instanzen (richtige Objekte) mögen nicht Global sein, aber jedes Each und First usw. Greifen auf die Globale Type Liste zu - wenn man kein spezielles Objekt darein setzt, würde ich das lassen.
Noch ein no-go:
BlitzBasic: [AUSKLAPPEN]
If KeyDown(2) = 1 WPN1_SHOT_COUNT = WPN1_SHOT_COUNT +1
If WPN1_SHOT_COUNT >= 5
WPN1_SHOT_COUNT = 0
WPN1.SHOT_1 = New SHOT_1
WPN1\SHOT_X = Player_XPOS+10
WPN1\SHOT_Y = Player_YPOS
WPN1\SHOT_SPD = 12
EndIf
Was glaubst du, was da passiert, und was passiert da tatsächlich? Deine Einrückung suggeriert einen anderen Zusammenhang als tatsächlich besteht. Ja, man kann then weglassen. Wenn du das tust, komme aber nicht zu mir wenn du Hilfe willst - ich sehe da schon nicht mehr durch. Besser:
BlitzBasic: [AUSKLAPPEN]
If KeyDown(2) = 1 Then WPN1_SHOT_COUNT = WPN1_SHOT_COUNT +1
If WPN1_SHOT_COUNT >= 5 Then
WPN1_SHOT_COUNT = 0
WPN1.SHOT_1 = New SHOT_1
WPN1\SHOT_X = Player_XPOS+10
WPN1\SHOT_Y = Player_YPOS
WPN1\SHOT_SPD = 12
EndIf

Und dein eigentliches Problem ist: Beim Aufruf von ImagesOverlap ist der Inhalt von "WPN1" bestimmt Null - und nicht mal das ist sicher. Wink
Benutze eine doppelt verschachtelte Schleife:
BlitzBasic: [AUSKLAPPEN]

Local e.Tenemy
Local s.Tshot
For e.Tenemy = Each Tenemy
For s.Tshot = Each Tshot

If (...) Then
e\hp - s\damage
Delete s
EndIf

Next

If e\hp < 0 Then
Delete e ; Das löschen darf erst hier passieren, sonst existiert es ggf. in der innren Schleife beim nächsten Schuss nicht mehr!
EndIf
Next
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)
 

ninjaKANICKL

BeitragDi, Sep 10, 2013 23:06
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke vielmals! Hab mir schon gedacht, dass es wohl etwas mit den Schleifen zu haben könnte. Läuft nun alles prima! Auch danke für die Tipps mit dem Quellcode im Allgemein. Da es sich bei meinem Programm eher um ein kleines Projekt handelt, hab ich mir die Angewohnheit angeeignet, das Programm erst zum Laufen zu bekommen und dann den Quellcode zu "säubern".

Also - danke nochmals für die Hilfestellung.

BladeRunner

Moderator

BeitragMi, Sep 11, 2013 8:20
Antworten mit Zitat
Benutzer-Profile anzeigen
Umgekehrt ist der bessere Weg: Wenn der Code von Beginn an sauber strukturiert ist wird er immer leichter zu warten sein und Fehler schleichen sich nicht so leicht ein.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

Neue Antwort erstellen


Übersicht BlitzBasic Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group