Schüsse springen

Übersicht BlitzBasic Beginners-Corner

Neue Antwort erstellen

 

Backbuffer

Betreff: Schüsse springen

BeitragMi, Jul 30, 2008 10:25
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo zusammen,
bei dem Spaceshooter den programmiere ist mir folgendes aufgefallen: Manchmal treffen die Schüsse das Ziel nicht. Zuerst dachte ich, dass es nur Einbildung ist, schließlich werden die Kollisionen pixelgenau überprüft. Jetzt glaube ich den Fehler gefunden zu haben.

Jeder Schuss hat eine Geschwindigkeit, die angibt, wieviel pixel er sich pro frame bewegt. Ist das Ziel nun kleiner als diese Geschwindigkeit, dann springt der Schuss sozusagen über das Ziel.

Wie kann ich das änder?
 

da_poller

BeitragMi, Jul 30, 2008 10:38
Antworten mit Zitat
Benutzer-Profile anzeigen
vieleicht wenn der abstand kleiner als geschwindigkeit ist als treffer gelten lassen...

ansonsten müsste es eig über imagescollide gehen... oder machst du das ohne images?

Jean

BeitragMi, Jul 30, 2008 11:14
Antworten mit Zitat
Benutzer-Profile anzeigen
Mach doch den Schuss einfach in der Kollisionsabfrage um den "Sprung pro Frame" länger. Einfach anstelle von IMAGESCOLLIDE IMAGERECTCOLLIDE verwenden, da du dort die Länge / Breite des Schusses selbst definieren kannst. So sollte es klappen.
 

Backbuffer

BeitragMi, Jul 30, 2008 12:42
Antworten mit Zitat
Benutzer-Profile anzeigen
da_poller hat Folgendes geschrieben:
vieleicht wenn der abstand kleiner als geschwindigkeit ist als treffer gelten lassen...

ansonsten müsste es eig über imagescollide gehen... oder machst du das ohne images?

Ich verwende imagescollide. Das Problem ist eben nur das in der einen Abfrage, der Schuss vor dem Schiff ist und in der nächsten Abfrage ist er bereits hinter dem Schiff, so dass die Bilder nicht kollidieren, obwohl der Schuss "durch" das Schiff geflogen ist.

Jean hat Folgendes geschrieben:
Mach doch den Schuss einfach in der Kollisionsabfrage um den "Sprung pro Frame" länger. Einfach anstelle von IMAGESCOLLIDE IMAGERECTCOLLIDE verwenden, da du dort die Länge / Breite des Schusses selbst definieren kannst. So sollte es klappen.

Eigentlich eine gute Idee, aber es wirft ein anderes Problem auf. Wenn der Schuss sehr lang und schmal ist (Phaser-Strahl), würde ein Schuss der den Gegner in schräger Richtung knapp verfehlt zu einer Kollision führen.

kriD

BeitragFr, Aug 01, 2008 0:36
Antworten mit Zitat
Benutzer-Profile anzeigen
versuch doch mal mehrere zwischenstufen der flugbahn der schüsse auf kollision mit dem objekt zu überprüfen..

angenommen die geschwindigkeit des schusses beträgt 8, und das objekt ist nur 3 breit, dann "springt" der schuss ja meißtens über das objekt hinweg, weil es nie mit ihm kollidiert.

wenn du nun aber die geschwindigkeit (8) noch weiter aufteilst und pro frame dann zB 4 oder 8 kollisionsberechnungen machst, also praktisch die flugbahn des geschosses auf kollision überprüfst (am besten mit ner for-schleife), dann bekommst du sicherlich eine kollision.

du nimmst also an, dass dan geschoss die geschwindigkeit 1 hat und überprüfst auf kollision, danach nimmst du an, es habe die geschwindigkeit 2, dann 3 usw und mit jeder geschwindigkeit auf kollision prüfen..

dies hat allerdings den nachteil, dass so häufiges imagescollide-nutzen ziemlich performance frisst.

lg kriD
[/code]
Wenn ich du wäre, wäre ich lieber ich!

ToeB

BeitragFr, Aug 01, 2008 10:35
Antworten mit Zitat
Benutzer-Profile anzeigen
Wenn du es so machst, wie kriD beschrieben hat, würd ich das so machen :

Code: [AUSKLAPPEN]
For s.schuss = Each schuss
For i = 1 to 8 ;8 ist hier die end geschwindigkeit...
s\x = s\x + s\Cosin*i
s\y = s\y + s\Sinus*i
If RectsOverlap(VordersterPunktdesschusses_x,-_y,1,1,colobj_x,colobj_y,3,3) then bla.
Next


So kann man es machen, geht warscheinlich auch noch einfacher...

mfg ToeB
Religiöse Kriege sind Streitigkeiten erwachsener Männer darum, wer den besten imaginären Freund hat.
Race-Project - Das Rennspiel der etwas anderen Art
SimpleUDP3.0 - Neuste Version der Netzwerk-Bibliothek
Vielen Dank an dieser Stelle nochmal an Pummelie, welcher mir einen Teil seines VServers für das Betreiben meines Masterservers zur verfügung stellt!
 

Backbuffer

BeitragFr, Aug 01, 2008 16:21
Antworten mit Zitat
Benutzer-Profile anzeigen
Also, ich habe versucht euren Vorschlag umzusetzen, bin aber auf neue Probleme gestoßen.

Wenn ich den Schuss in Zwischenschritten prüfe führt das dazu, dass ich zwei Positionswerte des Schusse habe. Eimal, die wo er tatsächlich gemalt wird und einmal die fiktiven die ich für die collisionsabfrage verwende. Das führt dann aber effektiv dazu, dass das was man sieht nicht mit dem übereinstimmt, was berechnet wird. Z.B. wird das Schiff jetzt zwar getroffen, der Schuss ist aber optisch gesehen schon weiter und verschwindet damit erst hinter dem Schiff.

Zwar könnte man diese Problem sicherlich irgendwie beheben, aber ich glaube nicht, dass es auf Dauer gut ist, wenn das was angezeigt wird etwas anderes ist als das, womit gerechnet wird.

Vielleicht finde ich noch eine andere Lösung.

Moundblack

BeitragFr, Aug 01, 2008 20:08
Antworten mit Zitat
Benutzer-Profile anzeigen
Wie wäre es, wenn du deinen ganzen Code mal postest? Wink ...vielleicht können wir dir dann besser weiterhelfen! Smile
Lg Thomas
 

Backbuffer

BeitragFr, Aug 01, 2008 22:31
Antworten mit Zitat
Benutzer-Profile anzeigen
Also ich weiß nicht, ob der Code hier wirklich weiter hilft. Aber schaden kanns auch nicht.

Hier wird der Schuss erstellt:
Code: [AUSKLAPPEN]
If KeyDown(57) Then
   
      
      shot.t_Shot = New t_Shot ;hier wird der schuss erstellt
      
      If player\current_weapon = 0 And player\blaster = 1 Then shot\t_weaponstyle = blaster
      If player\current_weapon = 1 And player\ionbolt= 1 Then shot\t_weaponstyle = ionbolt
      If player\current_weapon = 2 And player\laser= 1 Then shot\t_weaponstyle = laser
      If player\current_weapon = 3 And player\phaser= 1 Then shot\t_weaponstyle = phaser
      
      
      
      shot\deltax =player\xspeed
      shot\deltay = player\yspeed
      shot\direction = player\heading ;Schussrichtung ist Blickrichtung des Schiffes
      shot\xpos = player\xpos-shot\deltax+Cos(shot\direction)*8 ;Schuss ensteht auf Spielerposition mit kleinen Abstand (8 pixel), dessen Richtung vom Winkel abhängt
      shot\ypos = player\ypos-shot\deltay+Sin(shot\direction)*8 ;Schuss ensteht auf Spielerposition mit kleinen Abstand, (8 pixel)dessen Richtung vom Winkel abhängt
      
      

      
      shot\owner = player\ship_id ;Besitzer des Schusses ist der Spieler

                  
      If player\timer_shot < MilliSecs() And player\cur_energy >= shot\t_weaponstyle\energy_cost Then
         PlaySound shot\t_weaponstyle\sound
         player\timer_shot = MilliSecs() + shot\t_weaponstyle\firerate
         player\cur_energy = player\cur_energy - shot\t_weaponstyle\energy_cost
         If player\cur_energy < 0 Then player\cur_energy = 0
                  
               
         Else Delete shot
      End If            
   End If
   End If
End Function


Und hier ist die Kollisionsabfrage:
Code: [AUSKLAPPEN]
Function test_collision()
   For shot.t_Shot = Each t_Shot ;jeder Schuss wird durchlaufen
      
      
      shot\xpos = shot\deltax + shot\xpos + Cos(shot\direction) * shot\t_weaponstyle\speed                 
      shot\ypos = shot\deltay + shot\ypos + Sin(shot\direction) * shot\t_weaponstyle\speed
      
      
      
      
      ;Position des Schuss wird durch Geschwindigkeit in Winkelrichtung modifiziert, shot\delta ist die Geschwindigkeit des Raumschiffes (so wird ein "nachziehen" des Schusses im Schrägflug verhindert)

      player = First t_Ship ;Zeile damit die ship\... variablen gelesen werden können
         

      If shot\owner = player\ship_id Then ;wenn schuss von Spieler abgefeuert wurde
         
         
         

          DrawImage shot_gfx(Floor(shot\direction/imagestep)*imagestep, shot\t_weaponstyle\image), shot\xpos+player\xdistance, shot\ypos+player\ydistance



         ;Schuss wird an relativer position gemalt, dabei wird die Schussrichtung auf den nächsten imagestep gerundet,
          For ship.t_ship = Each t_ship ;jeder Gegner wird durchgegangen
             If ship\player=0 And ImagesCollide (shot_gfx(Floor(shot\direction/imagestep)*imagestep, shot\t_weaponstyle\image), shot\xpos, shot\ypos,0, ship_gfx(Floor(ship\heading/imagestep)*imagestep,ship\t_shipstyle\image,ship\image_booster), ship\xpos, ship\ypos,0) Then
               ;die Bilder vom Schuss und vom Gegner werden auf den absoluten Positionen auf Kollision verglichen
               If ship\cur_shield > shot\t_weaponstyle\damage Then
                  PlaySound shield_hit_sfx
                  DrawImage shield_gfx(ship\t_shipstyle\size), ship\xpos+player\xdistance, ship\ypos+player\ydistance
                  ship\cur_shield=ship\cur_shield-shot\t_weaponstyle\damage ;bei treffer wird gegnerschild um Waffenschaden reduziert
                  If ship\cur_shield < 0 Then ship\cur_shield = 0
                  shot\remove=1 ;Schuss wird zum löschen vorgemerkt
               Else If 0 < ship\cur_shield < shot\t_weaponstyle\damage Then
                     PlaySound hull_hit_sfx
                     DrawImage hit_gfx, ship\xpos+player\xdistance, ship\ypos+player\ydistance            
                     ship\cur_hull = ship\cur_hull+ship\cur_shield-shot\t_weaponstyle\damage
                     ship\cur_shield = 0
                     shot\remove=1 ;Schuss wird zum löschen vorgemerkt   
               Else
                  If ship\cur_shield <= 0 Then
                     PlaySound hull_hit_sfx
                     DrawImage hit_gfx, ship\xpos+player\xdistance, ship\ypos+player\ydistance
                     ship\cur_hull=ship\cur_hull - shot\t_weaponstyle\damage ;bei treffer wird gegnerschild um Waffenschaden reduziert
                     shot\remove=1 ;Schuss wird zum löschen vorgemerkt
                  End If
               End If
               
               
                If ship\cur_hull <= 0 Then ;wenn Gegner kein rumpf mehr hat
               
               explosion.t_explosion= New t_explosion
               explosion\next_frame = 1
               explosion\max_frame = 16
               explosion\xpos=ship\xpos
               explosion\ypos=ship\ypos
               ship\remove = 1 ;Gegner wird zum löschen vorgemerkt
                           
               End If
             End If
         Next
      
         If Sqr((shot\xpos-player\xpos)^2+(shot\ypos-player\ypos)^2   ) > shot\t_weaponstyle\range  Then shot\remove = 1
      ;wenn Schuss die Waffenreichweite überschreitet wird er zum löschen vorgemerkt
      Else
      
      
      
         For ship.t_ship = Each t_ship
            If shot\owner = ship\ship_id Then ;wenn schuss von Gegner abgefeuert wurde
               ;ship.t_ship = Object.t_ship(ship\ship_id)
               If Sqr((shot\xpos-ship\xpos)^2+(shot\ypos-ship\ypos)^2) > shot\t_weaponstyle\range  Then shot\remove = 1
               ;wenn Schuss die Waffenreichweite überschreitet wird zum löschen vorgemerkt
               
               ;For player.t_ship = Each t_ship ;für jedes Spielerschiff ein durchlauf
                  
                  DrawImage shot_gfx(Floor(shot\direction/imagestep)*imagestep, shot\t_weaponstyle\image), shot\xpos+player\xdistance, shot\ypos+player\ydistance

                  ;Schuss wird gemalt
               
                  If ImagesCollide (shot_gfx(Floor(shot\direction/imagestep)*imagestep,shot\t_weaponstyle\image), shot\xpos, shot\ypos,0, ship_gfx(Floor(player\heading/imagestep)*imagestep,player\t_shipstyle\image,player\image_booster), player\xpos, player\ypos,0) Then
                  ;die Bilder vom Schuss und vom Spieler werden auf den absoluten Positionen auf Kollision verglichen
                  
                     If player\cur_shield > shot\t_weaponstyle\damage Then
                        PlaySound shield_hit_sfx
                        DrawImage shield_gfx(player\t_shipstyle\size), screenwidth/2, screenheight/2
                        player\cur_shield=player\cur_shield-shot\t_weaponstyle\damage ;bei treffer wird gegnerschild um Waffenschaden reduziert
                        If player\cur_shield < 0 Then player\cur_shield = 0
                        shot\remove=1 ;Schuss wird zum löschen vorgemerkt
                     Else If 0 < player\cur_shield < shot\t_weaponstyle\damage Then
                        PlaySound hull_hit_sfx
                        DrawImage hit_gfx, screenwidth/2, screenheight/2
                        player\cur_hull = player\cur_hull+player\cur_shield-shot\t_weaponstyle\damage
                        player\cur_shield = 0
                        shot\remove=1 ;Schuss wird zum löschen vorgemerkt   
                     Else
                        If player\cur_shield <= 0 Then
                        PlaySound hull_hit_sfx
                        DrawImage hit_gfx, screenwidth/2, screenheight/2
                        player\cur_hull=player\cur_hull-shot\t_weaponstyle\damage ;bei treffer wird gegnerschild um Waffenschaden reduziert
                        shot\remove=1 ;Schuss wird zum löschen vorgemerkt
                        End If
                     End If         
               
                     If player\cur_hull <= 0 Then ;wenn spieler kein rumpf mehr hat
                        player_dead = 1
                        explosion.t_explosion= New t_explosion
                        explosion\next_frame = 1
                        explosion\max_frame = 16
                        explosion\xpos=player\xpos
                        explosion\ypos=player\ypos
                        ;player\remove = 1 ;Gegner wird zum löschen vorgemerkt

                        ;ship\remove = 1 ;Gegner wird zum löschen vorgemerkt
                     End If
                  End If
               ;Next
            End If
         Next
      End If
   Next
End Function

ToeB

BeitragSo, Aug 03, 2008 12:08
Antworten mit Zitat
Benutzer-Profile anzeigen
villeichnt kannst du je wenn du bei 8 pixeln pro schleife einfach bei pixel 4 und 8 was malen, dann wieder bei 4 und dann bei 8...

mfg ToeB
Religiöse Kriege sind Streitigkeiten erwachsener Männer darum, wer den besten imaginären Freund hat.
Race-Project - Das Rennspiel der etwas anderen Art
SimpleUDP3.0 - Neuste Version der Netzwerk-Bibliothek
Vielen Dank an dieser Stelle nochmal an Pummelie, welcher mir einen Teil seines VServers für das Betreiben meines Masterservers zur verfügung stellt!

BladeRunner

Moderator

BeitragSo, Aug 03, 2008 14:25
Antworten mit Zitat
Benutzer-Profile anzeigen
Dein Problem (flasche Zeichenposition) lässt sich ganz einfach lösen wenn Du das Zeichnen der Schüsse erst nach der Kollisionsprüfung vornimmst.
Du machst die schrittweise Kollisionsprüfung (Wobei als Schrittweite für die Kollision die kleinste Seitenlänge eines Gegner genügt). Sollte die einen Treffer ergeben wird als Schussposition die Position eingesetzt bei der der Treffer erfolgte (und die Kollisionsprüfung verlassen).
So hast Du Kollision und korrekte Position unter einem Hut.
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 Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group