Pacman Kollisionsabfrage, mathematischer fehler?

Übersicht BlitzBasic Beginners-Corner

Neue Antwort erstellen

 

DasLiebeSushi

Betreff: Pacman Kollisionsabfrage, mathematischer fehler?

BeitragDi, Apr 10, 2007 15:17
Antworten mit Zitat
Benutzer-Profile anzeigen
Moin

Ich arbeite gerade an einem Pacman Klone. Level steht und die Kollision zum Teil auch.

Das Problem scheint aber ein mathematisches zu sein.
Ich hab ein Array/Dim(31,31) in dem meine Spielfigur rumläuft. Die Tiles sind 16x16 gross.

Meine Spielfigur startet @ x256,y320
Die Kollision funktioniert aber nur teilweise und ungenau. Meine Spielfigur (auch 16x16 Pixel) lappt teilweise über die Wände hinaus oder läuft seitlich in eine Wand rein (Leider auch im Tutorial).

Als Referenz für die Kollision habe ich das Jump´n Run Tutorial (tut2) von der "Robsite" genommen.

Hier mal die Robsite Abfrage angepasst auf 16x16 Tiles (Kommentare sind aus dem Tutorial):

Code: [AUSKLAPPEN]

Function PacmanBewegen()         ;Function um die Figur zu bewegen
   If KeyDown(links) Then        ;Falls links gedrückt wird
      If map(Player_pos_x /16,(Player_pos_y +8) /16)=0 Then
          ;wenn Spielerposition / 16, weil die Tiles 16 * 16 groß sind
          ;PosY +8 um die Mitte zu bestimmen
          ;If Bedinung wird nur ausgeführt, wenn kein Tile neben der Figur ist.
         Player_pos_x = Player_pos_x -1
      EndIf
   ElseIf KeyDown(rechts) Then
      If map((Player_pos_x +16) /16,(Player_pos_y +8) /16)=0 Then
         Player_pos_x = Player_pos_x +1
      EndIf
   ElseIf KeyDown(rauf) Then
      If map((Player_pos_x +16) /16,Player_pos_y /16)=0 Then
         Player_pos_y = Player_pos_y -1
      EndIf      
   ElseIf KeyDown(runter) Then
      If map((Player_pos_x +16) /16,(Player_pos_y +8) /16)=0 Then
         Player_pos_y = Player_pos_y +1
      EndIf      
   EndIf
End Function


Die Abfrage des Randes hab ich erstmal entfernt.

Wäre für jede Hilfe dankbar.

MfG

DasLiebeSushi
- "Findet Nemo" wäre unendlich spannender gewesen, hätte Jack Bauer nach ihm gesucht.
- Falls du eine Pistole an Jack Bauers Kopf hälst, zähl bis 10 und nicht bis 3. So hast du 7 Sekunden länger zu leben.
 

BlackTermi

BeitragDi, Apr 10, 2007 16:51
Antworten mit Zitat
Benutzer-Profile anzeigen
Mhh, auf die Gefahr hin mich lächerlich zu machen, weil ich den Fehler der evtl. drin ist nicht sehe, ich sehe da keinen Fehler. Es ist aber auch schwer nur anhand dieses Beispiels etwas dazu zu sagen. Was mich wundert ist allerdings das du sagst das deine startposition an x256,y320 ist und das du dieses dann mit einigen plus Werten (+8 und +16) durch 16 teilst. Denn das Ergebnis bestimmt ja das Array-Feld? (Krumme Zahlen!?)

Und dann zählst du zu der Player_pos_x immer nur einen dazu bzw. einen ab. Während du um die Position im Map-Array zu bestimmen ja durch 16 teilst - daraus schlußfolgere ich das ich also 16 mal drücken muss bis ich ein Feld weiterkomme?

Um deinen Code nachvollziehen zu können wäre es hilfreich wenn du uns z.B. noch die Draw-Funktion dazu schreibst.
 

DasLiebeSushi

BeitragDi, Apr 10, 2007 17:00
Antworten mit Zitat
Benutzer-Profile anzeigen
Das sieht dann so aus:

Code: [AUSKLAPPEN]


Global   levelxpos   =   144      ;Mittig zeichnen bbei 800x600
Global   levelypos   =   44

;---------------------------------------------------------------------------------
;Zeichnet den geladenen Level
;---------------------------------------------------------------------------------
   Function ZeichneLevel()
      For Zeile=0 To 31
         For Spalte=0 To 31
            If Level(Spalte,Zeile) = 001 Then               
               DrawImage   levelstein,levelxpos+Spalte*16,levelypos+Zeile*16
            ElseIf Level(Spalte,Zeile) = 002 Then
               DrawImage   steinlo,levelxpos+Spalte*16,levelypos+Zeile*16
            ElseIf Level(Spalte,Zeile) = 003 Then
               DrawImage   steinro,levelxpos+Spalte*16,levelypos+Zeile*16
            ElseIf Level(Spalte,Zeile) = 004 Then
               DrawImage   steinlu,levelxpos+Spalte*16,levelypos+Zeile*16
            ElseIf Level(Spalte,Zeile) = 005 Then
               DrawImage   steinru,levelxpos+Spalte*16,levelypos+Zeile*16
            ElseIf Level(Spalte,Zeile) = 006 Then
               DrawImage   wandob,levelxpos+Spalte*16,levelypos+Zeile*16
            ElseIf Level(Spalte,Zeile) = 007 Then
               DrawImage   wandun,levelxpos+Spalte*16,levelypos+Zeile*16
            ElseIf Level(Spalte,Zeile) = 008 Then
               DrawImage   wandli,levelxpos+Spalte*16,levelypos+Zeile*16
            ElseIf Level(Spalte,Zeile) = 009 Then
               DrawImage   wandre,levelxpos+Spalte*16,levelypos+Zeile*16
            ElseIf Level(Spalte,Zeile) = 010 Then
               DrawImage   levelsupergold,levelxpos+Spalte*16,levelypos+Zeile*16,goldframe
            EndIf
         Next
      Next
   End Function

;---------------------------------------------------------------------------------
;Lädt die Leveldaten aus einem Array
;---------------------------------------------------------------------------------
   Function LadeLevel()
      Restore leveldaten
      For Zeile=0 To 31
         For Spalte=0 To 31
            Read Level(Spalte,Zeile)
         Next
      Next
   End Function

;#################################################################################
;Verschiedene Daten
;#################################################################################

;Level Daten
;---------------------------------------------------------------------------------
;---------0|--1|--2|--3|--4|--5|--6|--7|--8|--9|-10|-11|-12|-13|-14|-15|-16|-17|-18|-19|-20|-21|-22|-23|-24|-25|-26|-27|-28|-29|-30|-31
;--------------------------------------------------------------------------------------------------------------------------------------
.leveldaten
   Data   002,006,006,006,006,006,006,006,006,006,006,006,006,006,006,006,006,006,006,006,006,006,006,006,006,006,006,006,006,006,006,003
   Data   008,010,000,000,000,000,000,000,000,000,000,000,000,000,000,001,001,000,000,000,000,000,000,000,000,000,000,000,000,000,010,009
   Data   008,000,001,001,001,000,001,001,001,001,000,001,001,001,000,001,001,000,001,001,001,000,001,001,001,001,000,001,001,001,000,009
   Data   008,000,001,001,001,000,001,001,001,001,000,001,001,001,000,001,001,000,001,001,001,000,001,001,001,001,000,001,001,001,000,009
   Data   008,000,001,001,001,000,001,001,001,001,000,001,001,001,000,001,001,000,001,001,001,000,001,001,001,001,000,001,001,001,000,009
   Data   008,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,009
   Data   008,001,001,000,001,001,001,000,001,001,001,001,000,001,001,001,001,001,001,000,001,001,001,001,000,001,001,001,000,001,001,009
   Data   008,001,001,000,001,001,001,000,001,001,001,001,000,001,001,001,001,001,001,000,001,001,001,001,000,001,001,001,000,001,001,009
   Data   008,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,009
   Data   008,000,001,001,001,000,001,001,001,001,000,001,001,001,001,001,001,001,001,001,001,000,001,001,001,001,000,001,001,001,000,009
   Data   008,000,001,001,001,000,001,001,001,001,000,001,001,001,001,001,001,001,001,001,001,000,001,001,001,001,000,001,001,001,000,009
   Data   008,000,001,001,001,000,001,001,001,001,000,000,000,000,000,000,000,000,000,000,000,000,001,001,001,001,000,001,001,001,000,009
   Data   008,000,001,001,001,000,001,001,001,001,000,001,001,001,001,000,000,001,001,001,001,000,001,001,001,001,000,001,001,001,000,009
   Data   008,000,001,001,001,000,001,001,001,001,000,001,000,000,000,000,000,000,000,000,001,000,001,001,001,001,000,001,001,001,000,009
   Data   008,000,000,000,000,000,000,000,000,000,000,001,000,000,000,000,000,000,000,000,001,000,000,000,000,000,000,000,000,000,000,009
   Data   008,001,000,001,001,001,001,001,001,001,000,001,000,000,000,000,000,000,000,000,001,000,001,001,001,001,001,001,001,000,001,009
   Data   008,001,000,001,001,001,001,001,001,001,000,001,000,000,000,000,000,000,000,000,001,000,001,001,001,001,001,001,001,000,001,009
   Data   008,000,000,000,000,000,000,000,000,000,000,001,000,000,000,000,000,000,000,000,001,000,000,000,000,000,000,000,000,000,000,009
   Data   008,000,001,001,001,000,001,001,001,001,000,001,000,000,000,000,000,000,000,000,001,000,001,001,001,001,000,001,001,001,000,009
   Data   008,000,001,001,001,000,001,001,001,001,000,001,001,001,001,001,001,001,001,001,001,000,001,001,001,001,000,001,001,001,000,009
   Data   008,000,001,001,001,000,001,001,001,001,000,000,000,000,000,000,000,000,000,000,000,000,001,001,001,001,000,001,001,001,000,009
   Data   008,000,001,001,001,000,001,001,001,001,000,001,001,001,001,001,001,001,001,001,001,000,001,001,001,001,000,001,001,001,000,009
   Data   008,000,001,001,001,000,001,001,001,001,000,001,001,001,001,001,001,001,001,001,001,000,001,001,001,001,000,001,001,001,000,009
   Data   008,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,009
   Data   008,001,001,000,001,001,001,000,001,001,001,001,000,001,001,001,001,001,001,000,001,001,001,001,000,001,001,001,000,001,001,009
   Data   008,001,001,000,001,001,001,000,001,001,001,001,000,001,001,001,001,001,001,000,001,001,001,001,000,001,001,001,000,001,001,009
   Data   008,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,009
   Data   008,000,001,001,001,000,001,001,001,001,000,001,001,001,000,001,001,000,001,001,001,000,001,001,001,001,000,001,001,001,000,009
   Data   008,000,001,001,001,000,001,001,001,001,000,001,001,001,000,001,001,000,001,001,001,000,001,001,001,001,000,001,001,001,000,009
   Data   008,000,001,001,001,000,001,001,001,001,000,001,001,001,000,001,001,000,001,001,001,000,001,001,001,001,000,001,001,001,000,009
   Data   008,010,000,000,000,000,000,000,000,000,000,000,000,000,000,001,001,000,000,000,000,000,000,000,000,000,000,000,000,000,010,009
   Data   004,007,007,007,007,007,007,007,007,007,007,007,007,007,007,007,007,007,007,007,007,007,007,007,007,007,007,007,007,007,007,005


Die Spielfigur setze ich mit DrawImage.

MfG

DasLiebeSushi
- "Findet Nemo" wäre unendlich spannender gewesen, hätte Jack Bauer nach ihm gesucht.
- Falls du eine Pistole an Jack Bauers Kopf hälst, zähl bis 10 und nicht bis 3. So hast du 7 Sekunden länger zu leben.
 

Krümel

BeitragDi, Apr 10, 2007 19:02
Antworten mit Zitat
Benutzer-Profile anzeigen
um die Kollision korrekt zu ermitteln solltest du "floor" und "ceil" verwenden.
(schau dir mal den Code an)

Ich wüde aber eher den pacman bei tastendruck mit einer schleife immer 16 pixel in die entsprechende Richtung laufen lassen. Damit vehinderst du das er an einer ecke "hängenbleibt"

Code: [AUSKLAPPEN]

Graphics 32*20,32*20,16,2
Global player_pos_x#=0,player_pos_y#=0
Global links=203,rechts=205,rauf=200,runter=208
Dim map(32,32)

For y=0 To 31
For x=0 To 31
   If Rand(0,10)=0 map(x,y)=1
Next
Next

Function PacmanBewegen()         ;Function um die Figur zu bewegen

   
   mapXf=Floor((player_pos_x) / 16.0)
   mapYf=Floor((player_pos_y) / 16.0)
   mapXc=Ceil ((player_pos_x) / 16.0)
   mapYc=Ceil ((player_pos_y) / 16.0)
   
   Rect mapXf*16-8,mapYf*16-8,16,16,0
   Rect mapXc*16-8,mapYc*16-8,16,16,0   

    ;wenn Spielerposition / 16, weil die Tiles 16 * 16 groß sind
    ;PosY +8 um die Mitte zu bestimmen
    ;If Bedinung wird nur ausgeführt, wenn kein Tile neben der Figur ist.
   
   If KeyDown(links) Then        ;Falls links gedrückt wird
      If map(mapXf,mapYf)=0 And map(mapXf,mapYc)=0 Then
      Player_pos_x = Player_pos_x - 1
      EndIf
   ElseIf KeyDown(rechts) Then
      If map(mapXf+1,mapYf)=0 And map(mapXf+1,mapYc)=0 Then
         Player_pos_x = Player_pos_x +1
      EndIf
   ElseIf KeyDown(rauf) Then
      If map(mapXf,mapYf)=0 And map(mapXc,mapYf)=0 Then
      Player_pos_y = Player_pos_y -1
      EndIf     
   ElseIf KeyDown(runter) Then
      If map(mapXf,mapYf+1)=0 And map(mapXc,mapYf+1)=0 Then
         Player_pos_y = Player_pos_y +1
      EndIf     
   EndIf
End Function


While Not KeyHit(1)
   PacmanBewegen()

   Oval player_pos_x-8,player_pos_y-8,16,16´

   For y=0 To 31   
   For x=0 To 31
      If map(x,y)=1 Rect x*16-8,y*16-8,16,16
   Next
   Next
   
   
   Delay 10
   Flip 0
   Cls
Wend
 

DasLiebeSushi

BeitragDi, Apr 10, 2007 21:53
Antworten mit Zitat
Benutzer-Profile anzeigen
Vielen Dank für deine Hilfe. Das mit den Recs als sichtbare Prüfung ist genial Smile.

Hab es nun meiner Version angepasst. Leider berechnet er nur die Kollision nach unten und nach rechts genau. Bei der Kollision links und oben fehlt jeweils 1 Pixel.

Mal schauen ob ich den Fehler finde.

Trotzdem nochmal Danke Wink.

MfG

Sushi
- "Findet Nemo" wäre unendlich spannender gewesen, hätte Jack Bauer nach ihm gesucht.
- Falls du eine Pistole an Jack Bauers Kopf hälst, zähl bis 10 und nicht bis 3. So hast du 7 Sekunden länger zu leben.
 

Krümel

BeitragMi, Apr 11, 2007 7:46
Antworten mit Zitat
Benutzer-Profile anzeigen
stimmt, da ist noch eine kleine ungenauigkeit...

so klappts:

Code: [AUSKLAPPEN]

Graphics 32*20,32*20,16,2
Global player_pos_x#=0,player_pos_y#=0
Global links=203,rechts=205,rauf=200,runter=208
Dim map(32,32)

For y=0 To 31
For x=0 To 31
   If Rand(0,10)=0 map(x,y)=1
Next
Next

Function PacmanBewegen()         ;Function um die Figur zu bewegen

   mapXf=Floor((player_pos_x) / 16.0)
   mapYf=Floor((player_pos_y) / 16.0)
   mapXc=Ceil ((player_pos_x) / 16.0)
   mapYc=Ceil ((player_pos_y) / 16.0)
   Rect mapXf*16-8,mapYf*16-8,16,16,0
   Rect mapXc*16-8,mapYc*16-8,16,16,0   

    ;wenn Spielerposition / 16, weil die Tiles 16 * 16 groß sind
    ;PosY +8 um die Mitte zu bestimmen
    ;If Bedinung wird nur ausgeführt, wenn kein Tile neben der Figur ist.

   
   If KeyDown(links) Then        ;Falls links gedrückt wird
      mapXf=Floor((player_pos_x-1) / 16.0)
      mapXc=Ceil ((player_pos_x-1) / 16.0)
      If map(mapXf,mapYf)=0 And map(mapXf,mapYc)=0 Then
      Player_pos_x = Player_pos_x - 1
      EndIf
   ElseIf KeyDown(rechts) Then
      If map(mapXf+1,mapYf)=0 And map(mapXf+1,mapYc)=0 Then
         Player_pos_x = Player_pos_x +1
      EndIf
   ElseIf KeyDown(rauf) Then
      mapYf=Floor((player_pos_y-1) / 16.0)
      mapYc=Ceil ((player_pos_y-1) / 16.0)
      If map(mapXf,mapYf)=0 And map(mapXc,mapYf)=0 Then
      Player_pos_y = Player_pos_y -1
      EndIf     
   ElseIf KeyDown(runter) Then
      If map(mapXf,mapYf+1)=0 And map(mapXc,mapYf+1)=0 Then
         Player_pos_y = Player_pos_y +1
      EndIf     
   EndIf



End Function


While Not KeyHit(1)
   PacmanBewegen()

   Oval player_pos_x-8,player_pos_y-8,16,16´

   For y=0 To 31   
   For x=0 To 31
      If map(x,y)=1 Rect x*16-8,y*16-8,16,16
   Next
   Next
   
   
   Delay 10
   Flip 0
   Cls
Wend

Neue Antwort erstellen


Übersicht BlitzBasic Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group