Kollision auf Map

Anfängerfragen zum Programmieren mit PureBasic.
obar
Beiträge: 111
Registriert: 22.11.2007 19:47

Kollision auf Map

Beitrag von obar »

Ich habe nun mal eine kleine Map(16x12) erstellt. Die Tiles sind 50x50 gross.
Ausehen tut sie etwa so:

OOOOOOOOOOOOOOO
OOOOOOOOOOOOOOO
OOOOOOOOOOOOOOO
OOOOOOOOOOOOOOO
==OO===========
OOOOOOOOOOOOOOO
OOOOOOOOOOOOOOO

O --> Wiese
= --> Wasser

Nun soll das Wasser nicht begehbar sein, hab schon diverse Versuche gestartet, ich schaffs aber nicht.


Ich wollt es so, dass die Sprites bis Nummer 10 begehbar sind
und ab 11 nicht mehr.

Code sieht etwa so aus:

Code: Alles auswählen

Global Dim map.l(15,11)

Enumeration

#Wiese = 1

#Wasser = 11

EndEnumeration

Procedure ShowLand(x.l,y.l) 
    For t=0 To 11 
        For n=0 To 15 
           DisplaySprite(Map(n,t),50*n,50*t) 
        Next 
    Next 
EndProcedure

Procedure Steuerung() 
   
  If KeyboardPushed(#PB_Key_Down) 
    
      If AnimFrame > 110 And AnimFrame <= 114 
        If playerY < 600 - SpriteHeight(AnimFrame) 
          
           If map(???????????????????)  < 10
             
          playerY + 2 
          counter + 1 
          If counter > 2 
            AnimFrame + 1  
            If AnimFrame = 115 
              AnimFrame = 111 
            EndIf 
            counter = 0 
          EndIf 
          EndIf
        EndIf 
      Else 
      AnimFrame = 111 
      EndIf 
      EndIf 
  
  EndProcedure 


LoadSprite(#Wiese,  ".\Grafik2\001.png")
LoadSprite(#Wasser, ".\Grafik2\011.png")


For t = 0 To 11
  For n = 0 To 15
     Read map(n,t)   
  Next
Next 


DataSection

map:
Data.l 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
Data.l 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
Data.l 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
Data.l 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
Data.l 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
Data.l 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
Data.l 11,11,1,1,11,11,11,11,11,11,11,11,11,11,11,11
Data.l 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
Data.l 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
Data.l 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
Data.l 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
Data.l 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1



Bitte. Bitte. Helft mir
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Beitrag von STARGÅTE »

na um von der Spielerposition zu einer Feld(MAP) Position zu kommen musst du nur duch 50 teilen:

Code: Alles auswählen

If map(Int(playerX), Int(playerY))  < 10
falls es jetzt nicht ganz passt (also wenns verschoben ist) einfach + oder - 1 rechnen dann funzt es
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
obar
Beiträge: 111
Registriert: 22.11.2007 19:47

Beitrag von obar »

@Stargate

Das klappt leider nicht. Sobald ich nach unten laufe, sagt er Array Index out of bound.
Es ist ja auch so das ich die Map mit DIM(15,11) dimensioniert habe.
PlayerX und PlayerY haben aber einen Startwert von 100.

Sorry, hab noch gesehen das ich durch 50 teilen muss. Ich probiers nochmal und geb Bescheid.
Benutzeravatar
Zaphod
Beiträge: 2875
Registriert: 29.08.2004 00:40

Beitrag von Zaphod »

Doch, das klappt so. Du solltest vor abfragen in einem Array sicherstellen, dass du innerhalb des arrays bleibst.
Weiter musst du halt bedenken, dass du im Prinzip zwischen zwei Koordinatensystemen konvertieren musst. Von deinem Pixelgenauem Koordinatensystem zu map koordinaten konvertierst du durch teilen durch die Tilebreite/Höhe.
Wenn du also eine Bewegung ausführst testest du, ob einer der eckpunkte deines Sprites nach der Bewegung innerhalb eines verbotenen Tiles stehen würde und verhinderst dieses.
Am besten wäre, wenn du dir das Problem mit Stift und Papier erst einmal im Detail bewusst machst, denn ohne zu verstehen was du da tust wirst du nicht zu einer Lösung kommen.
obar
Beiträge: 111
Registriert: 22.11.2007 19:47

Beitrag von obar »

@Zaphod

War woll etwas zu langsam, ich hatte es oben noch korrigiert. Ich hab nicht gesehen das ich duch 50 teilen muss.

Es klappt natürlich.

Code: Alles auswählen

If map(Int(playerX/50), Int(playerY/50)+1)  < 10
Habs jetzt so gemacht. Soweit muss ich sagen war ich auch schon mal.
Ich hab jetzt einfach noch das Problem, dass auf einer Seite immer noch durchs Wasser laufen kann. Ich vermute, dass liegt daran, dass die
Spritebreite nicht berücksichtigt wird. Wie kann ich denn das verhindern?
Benutzeravatar
Zaphod
Beiträge: 2875
Registriert: 29.08.2004 00:40

Beitrag von Zaphod »

Indem du die Spritebreite berücksichtigst... du weißt doch wohl wie breit deine Sprites sind, oder?
obar
Beiträge: 111
Registriert: 22.11.2007 19:47

Beitrag von obar »

Natürlich weiss ich wie breit mein Sprite ist. Ich verstehe aber nicht wie ich diese Information mitgeben soll.

Sprite ist:

Breite 32
Höhe 48

das ist die Zeile die wir bearbeitet haben.

Code: Alles auswählen

If map(Int(playerX/50), Int(playerY/50)+1)  < 10
Hab dann mal sowas probiert:

Code: Alles auswählen

If map(Int(playerX/50)-Int(SpriteWidth(AnimFrame)/32), Int(playerY/50)+1)  < 10 
Aber das bringt nichts, da er rundet und einfach einen Tile weiter nach rechts oder
nach links schiebt. Dann stimmts noch weniger.
Benutzeravatar
Zaphod
Beiträge: 2875
Registriert: 29.08.2004 00:40

Beitrag von Zaphod »

Ok, denk mal über folgendes nach: interessieren dich bei einer Bewegung immer Kollisionen mit allen Ecken oder gibt es einen Zusammenhang zwischen der Bewegungsrichtung und den Spriteecken bei denen es interessant ist, ob sie sich nach der Bewegung eventuell auf einem verbotenem Feld sind?
obar
Beiträge: 111
Registriert: 22.11.2007 19:47

Beitrag von obar »

Ich verstehe was du meinst, wenn ich nach unten gehe ist nur die untere Kante des Sprites wichtig, usw.
Ich habs aber immer noch nicht geschafft. :(
Ist ziemlich frustrierend, hab nun das Prinzip verstanden, an der Ausführung happerts aber noch.
obar
Beiträge: 111
Registriert: 22.11.2007 19:47

Beitrag von obar »

So, Hab nun einige Test's gemacht.
Bin auf Folgendes Ergebnis gekommen.

Code: Alles auswählen

If KeyboardPushed(#PB_Key_Up) 
    
      If AnimFrame > 122 And AnimFrame <= 126 
        If playerY > 0 
        
          If map(Int((playerX+SpriteWidth(AnimFrame))/50), Int(playerY)/50)  < 10 And map(Int(playerX)/50, Int(playerY)/50)  < 10 
            
            playerY - 2
                   
          EndIf
                    
          counter + 1 
          If counter > 2 
            AnimFrame + 1 
            If AnimFrame = 127 
              AnimFrame = 123 
            EndIf 
            counter = 0 
          EndIf 
         
        EndIf
      Else 
      AnimFrame = 123 
      EndIf 
    
  EndIf 
So läufts, das Problem hier ist, dass noch einmal -2 gerechnet wird und die obere kannte des Sprites in den Wassersprite ragt.
So kann ich nicht mehr nach Links oder Rechts, sondern muss zuerst etwas zurücksetzen.



Dann hab ich es so gemacht.

Code: Alles auswählen


If KeyboardPushed(#PB_Key_Up) 
    
      If AnimFrame > 122 And AnimFrame <= 126 
        If playerY > 0 
        
          If map(Int((playerX+SpriteWidth(AnimFrame))/50), Int(playerY)/50)  < 10 Or map(Int(playerX)/50, Int(playerY)/50)  < 10
                                  
            playerY - 2
            
          Else
          
            playerY + 2
          
          EndIf
          
          counter + 1 
          If counter > 2 
            AnimFrame + 1 
            If AnimFrame = 127 
              AnimFrame = 123 
            EndIf 
            counter = 0 
          EndIf 
         
        EndIf
      Else 
      AnimFrame = 123 
      EndIf 

Hier ist das Problem das wenn ich ans Wasser laufe fängt er an zu zappeln, weil immer wieder +2 gerechnet wird. Dafür kann ich wieder nach Links und Rechts steuern.

Sieht aber insgesamt auch nicht gut aus. Hat jemand eine Lösung wie ich dies verhindern kann ???
Antworten