Problem mit versetztem Koordinatenursprung

Übersicht BlitzBasic Beginners-Corner

Neue Antwort erstellen

Skabus

Betreff: Problem mit versetztem Koordinatenursprung

BeitragDo, Mai 17, 2007 20:50
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo!

Ich bin gerade auf ein Problem gestoßen was ich nicht ganz lösen
kann und hoffe das von euch jemand vielleicht ne Lösung kennt.

Mein Problem ist folgendes:
Ich habe nun für mein 2D-RPG-Projekt Spielersteuerung und Tilemap
bereits erfolgreich programmiert und auch die Kolision mit unbegehbaren
Tiles habe ich bereits nach einigem Probieren ordentlich programmiert.
Nun habe ich aber ein Problem meine Spielergrafik an meine Kollision anzupassen.

Die Tiles sind 16x16 Pixel groß, die Spielergrafik ist 24x32 groß
(Alles an dem Rpgmakerstandard angelehnt)

Die Tilekollision funktioniert nach genauer Koordinatenberechnung.
Leider finde ich keine Möglichkeit die Spielergrafik so zu versetzen
das sich die die Kollision immer an der jeweilgen Kante der grafik orientiert in welche Richtung der Spieler geht.Das Programm erkennt die
Kollision logischerweise erst wenn die 0,0 Koordinate des Rechtsecks der
Grafik an der jeweiligen Position ist und erkennt dann erst eine Kollision.

Weiß jemand wie ich den Koordinatenursprung der Grafik ändern kann?
Hier noch mein momentaner Code, fals jemand den durchsehen möchte:

ACMain:

Code: [AUSKLAPPEN]


;Include-Dateien

Include "ACHeader.bb"

;Programminitialisierung
Graphics 320,240,16,1  ;Initialisierung des Grafikmodus
SetBuffer BackBuffer() ;Stellt die Ausgabe auf BackBuffer

;Laden der Grafiken
testtile = LoadAnimImage("source\tiles\test.bmp",16,16,0,48)
testchar = LoadAnimImage("source\chars\test.bmp",24,32,0,96)


;Die Hauptschleife, wird beendet sobald leaveGame = 1 ist
While leaveGame = 0

ClsColor 0,255,255
Cls


;Transparenz festlegen
MaskImage testtile,255,0,255
MaskImage testchar,255,0,255

;Aufruf der Spielersteuerung
Spielersteuerung()


;Die Karte wird anhand der vorliegenden Mapinformationen gezeichnet
For x = 0 To 19
For y = 0 To 14

DrawImage testtile,x*16,y*16,testmap(x,y)

Next
Next

;Charackter anzeigen
DrawImage testchar,px,py,pDirGra

;Debuginformationen(Hinweis: Wird noch erweitert und als Console programmiert)
Text 10,10,"Pos X: " + Str(px) + " Pos Y: " + Str(py) + " "
Text 10,20,"TileX: " + Str(tileX) + " TileY: " + Str(tileY) + " "
Text 10,30,"Tilenr.: " + Str(testmap(tileX,tileY)) + " "
Text 10,50,"Result:    " + Str(result) + " "

;Wenn die ESC-Taste gerdrückt wird, wird das Spiel beendet

If KeyHit(ESC) Then leaveGame = 1

;Den Backbuffer anzeigen lassen

Flip

;Wenn das Spiel beendet wird werden noch alle Bilder aus dem Speicher gelöscht

If leaveGame = 1 Then

FreeImage testchar
FreeImage testtile

EndIf

Wend


ACHeader:

Code: [AUSKLAPPEN]


;Konstanten

Const links  = 203 ;Konstanten
Const rechts = 205 ;welche das Nutzen der
Const oben   = 200 ;Pfeiltasten etwas
Const unten  = 208 ;durchschaubarer machen

Const ESC    =   1 ;Konstante für die ESC-Taste


;Globale Variablen

Global leaveGame  = 0           ;Variable die das Beenden des Spiels prüft
Global px#        = 0           ;Bildschirmkoordinate des Spielers auf der X-Achse
Global py#        = 0           ;Bildschirmkoordinate des Spielers auf der Y-Achse
Global pDirStatus = 0           ;Animationsframe
Global pDirGra    = 25          ;tatsächliche Grafik der Spielfigur
Global steps      = MilliSecs() ;Setzt die Schrittzahl auf die Milisekunden seit Systemstart
Global tileX%     = 0           ;Kachel auf dem der Spieler auf der X-Achse steht
Global tileY%     = 0           ;Kachel auf dem der Spieler auf der Y-Achse steht
Global pSpeed     = 1           ;Schnelligkeit des Spielers
Global move       = 0           ;Variable die abspeichert ob eine Bewegung geschehen ist oder nicht
Global mSizeX     = 19          ;Ausweitungsfaktor von X(in Pixel) auf der Karte
Global mSizeY     = 14          ;Ausweitungsfaktor von Y(in Pixel) auf der Karte
Global result#    = 0           ;Enthält das Ergebnis für die Kollisionsprüfung

;Definiert die Maße der Karte und speichert diese in einen Array
Dim testmap(mSizeX,mSizeY)


;Datenfelder werden gesetzt um diese dann in die Mapdaten umzuwandeln
Data 37,38,38,38,39,37,37,37,37,37,37,37,37,37,37,37,37,37,38,37
Data 38,38,38,37,37,37,37,37,37,37,37,37,37,38,37,37,37,38,38,38
Data 38,38,37,37,37,37,37,37,37,37,37,37,38,38,38,37,37,38,37,38
Data 38,38,37,37,37,37,37,37,37,37,37,37,38,38,37,37,37,37,37,38
Data 38,37,37,39,37,37,37,37,37,37,37,38,38,38,37,37,37,37,37,38
Data 37,37,37,37,37,37,37,37,37,37,37,38,38,37,37,37,37,37,37,37
Data 37,37,37,38,37,37,37,37,37,37,37,37,37,37,37,37,38,37,37,37
Data 39,37,37,37,37,39,37,37,38,38,37,37,37,37,37,37,38,38,37,37
Data 37,37,37,37,37,37,37,37,38,38,37,37,37,37,37,38,38,38,37,37
Data 37,37,37,37,37,37,37,38,38,38,38,37,37,37,37,38,38,38,37,37
Data 37,38,38,37,37,37,37,37,37,38,38,37,37,37,38,38,37,37,37,37
Data 38,38,38,37,37,37,37,37,37,38,38,38,37,37,38,38,37,37,37,37
Data 38,38,37,37,37,37,37,37,37,37,38,38,37,37,37,37,37,39,37,37
Data 38,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37
Data 38,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,38



;Liest die Datenfelder aus und speichert sie in den Maparray
For y = 0 To 14
For x = 0 To 19

Read testmap(x,y)

Next
Next


;Hauptfunktion zum Steuern des Spielers.Diese Funktion ist grundlegend wichtig da
;sie Steuerung,Aktionsauslösung,TileKolisionen und eventuell noch andere
;Funktionen regelt

Function Spielersteuerung()

 ;Tastenabfrage
 If KeyDown(links) And px > 0 Then

 ;Prüft ob durch die angesteuerte Bewegung der Spieler mit einem unbegebarem Tile kollidiert
 If TileKollision(links) = False Then

 ;Spielerbewegung
 px = px - pSpeed

 ;Fragt ab ob 100 Milisekunden nach dem letzten Bewegungszyklus vergangen sind und steuert
 ;somit die Bewegungsanimation, welche ansonsten unrealistisch schnel abläuft
 If steps + 100 < MilliSecs() Then

 ;Die momentan aktuelle Spielergrafiknummer wird zugewiesen damit die Richtige angezeigt wird
 If pDirStatus = 0 Then pDirGra = 37
 If pDirStatus = 1 Then pDirGra = 38
 If pDirStatus = 2 Then pDirGra = 36

 ;Die Zeit wird aktualisiert
 steps = MilliSecs()

 pDirStatus = pDirStatus + 1

 EndIf

 ;Fragt ab ob pDirStatus größer als 2 ist.Ist dies der Fall wird der Zähler wieder an den Anfang
 ;der Animation zurückgesetzt damit sie erneut ablaufen kann
 If pDirStatus > 2 Then pDirStatus = 0

 ;Wenn der Spieler das nächstlegende Tile betritt wird die Tileposition aktualisiert
 If (px / 16) < (tileX) Then tileX = tileX - 1

 EndIf
 
 ;Tastenabfrage
 ElseIf KeyDown(rechts) And px < 320 Then

 ;Prüft ob durch die angesteuerte Bewegung der Spieler mit einem unbegebarem Tile kollidiert
 If TileKollision(rechts) = False Then

 ;Spielerbewegung
 px = px + pSpeed

 ;Fragt ab ob 100 Milisekunden nach dem letzten Bewegungszyklus vergangen sind und steuert
 ;somit die Bewegungsanimation, welche ansonsten unrealistisch schnel abläuft
 If steps + 100 < MilliSecs() Then

 ;Die momentan aktuelle Spielergrafiknummer wird zugewiesen damit die Richtige angezeigt wird
 If pDirStatus = 0 Then pDirGra = 13
 If pDirStatus = 1 Then pDirGra = 14
 If pDirStatus = 2 Then pDirGra = 12

 ;Die Zeit wird aktualisiert
 steps = MilliSecs()

 pDirStatus = pDirStatus + 1

 EndIf

 ;Fragt ab ob pDirStatus größer als 2 ist.Ist dies der Fall wird der Zähler wieder an den Anfang
 ;der Animation zurückgesetzt damit sie erneut ablaufen kann
 If pDirStatus > 2 Then pDirStatus = 0

 ;Wenn der Spieler das nächstlegende Tile betritt wird die Tileposition aktualisiert
 If (px / 16) > (tileX +1) Then tileX = tileX + 1

 EndIf

 ElseIf KeyDown(oben) And py > 0 Then

 ;Prüft ob durch die angesteuerte Bewegung der Spieler mit einem unbegebarem Tile kollidiert
 If TileKollision(oben) = False Then

 ;Spielerbewegung
 py = py - pSpeed

 ;Fragt ab ob 100 Milisekunden nach dem letzten Bewegungszyklus vergangen sind und steuert
 ;somit die Bewegungsanimation, welche ansonsten unrealistisch schnel abläuft
 If steps + 100 < MilliSecs() Then

 ;Die momentan aktuelle Spielergrafiknummer wird zugewiesen damit die Richtige angezeigt wird
 If pDirStatus = 0 Then pDirGra = 1
 If pDirStatus = 1 Then pDirGra = 2
 If pDirStatus = 2 Then pDirGra = 0

 ;Die Zeit wird aktualisiert
 steps = MilliSecs()

 pDirStatus = pDirStatus + 1

 EndIf

 ;Fragt ab ob pDirStatus größer als 2 ist.Ist dies der Fall wird der Zähler wieder an den Anfang
 ;der Animation zurückgesetzt damit sie erneut ablaufen kann
 If pDirStatus > 2 Then pDirStatus = 0

 ;Wenn der Spieler das nächstlegende Tile betritt wird die Tileposition aktualisiert
 If (py / 16) < (tileY) Then tileY = tileY - 1

 EndIf 

 ElseIf KeyDown(unten) And py < 240 Then

 ;Prüft ob durch die angesteuerte Bewegung der Spieler mit einem unbegebarem Tile kollidiert
 If TileKollision(unten) = False Then

 ;Spielerbewegung
 py = py + pSpeed

 ;Fragt ab ob 100 Milisekunden nach dem letzten Bewegungszyklus vergangen sind und steuert
 ;somit die Bewegungsanimation, welche ansonsten unrealistisch schnel abläuft
 If steps + 100 < MilliSecs() Then

 ;Die momentan aktuelle Spielergrafiknummer wird zugewiesen damit die Richtige angezeigt wird
 If pDirStatus = 0 Then pDirGra = 25
 If pDirStatus = 1 Then pDirGra = 26
 If pDirStatus = 2 Then pDirGra = 24

 ;Die Zeit wird aktualisiert
 steps = MilliSecs()

 pDirStatus = pDirStatus + 1

 EndIf

 ;Fragt ab ob pDirStatus größer als 2 ist.Ist dies der Fall wird der Zähler wieder an den Anfang
 ;der Animation zurückgesetzt damit sie erneut ablaufen kann
 If pDirStatus > 2 Then pDirStatus = 0

 ;Wenn der Spieler das nächstlegende Tile betritt wird die Tileposition aktualisiert
 If (py / 16) > (tileY + 1) Then tileY = tileY + 1

 EndIf

 Else

 ;Wenn kein Tastendruck registiert wurde,wird die Animation auf die Standanimation gesetzt
 pDirStatus = 0

 EndIf

 Return pDirGra

End Function

;Funktion welche entweder TRUE(1) oder FALSE(0) zurückliefert und somit prüft ob eine
;Kollision mit dem momentan angesteuerten Tile(curTile) stattfinden würde
;tileX udn TileY enthalten die Koordinaten des zu untersuchenden Tile

Function TileKollision(pDir)

 ;Abfrage der Bewegungsrichtung(hier rechts)
 If pDir = rechts Then
 
  ;Die Tileposition für die angesteuerte Bewegung wird berechnet
  result = (px + 1) / 16

    ;Sicherungsabfrage um zu verhindern das der Spieler außerhalb des Maparraybereiches gehen kann
    If tileX < mSizeX Then
 
      ;Abfrage welche prüft ob die berechnete Tileposition auf ein Tile passt welches nicht
      ;begehbar ist.st dies der Fall wird TRUE zurückgeliefert und die Bewegung verhindert
      If testmap(Floor(result),tileY) = 39 Then Return True

    EndIf

 EndIf

 ;Abfrage der Bewegungsrichtung(hier links)
 If pDir = links Then

  ;Die Tileposition für die angesteuerte Bewegung wird berechnet
  result = (px - 1) / 16

   ;Sicherungsabfrage um zu verhindern das der Spieler außerhalb des Maparraybereiches gehen kann
   If tileX > 0

    ;Abfrage welche prüft ob die berechnete Tileposition auf ein Tile passt welches nicht
    ;begehbar ist.st dies der Fall wird TRUE zurückgeliefert und die Bewegung verhindert
    If testmap(Floor(result),tileY) = 39 Then Return True

   EndIf
 
 EndIf

  ;Abfrage der Bewegungsrichtung(hier unten)
  If pDir = unten Then

  ;Die Tileposition für die angesteuerte Bewegung wird berechnet
  result = (py + 1) / 16

   ;Sicherungsabfrage um zu verhindern das der Spieler außerhalb des Maparraybereiches gehen kann
   If tileY < mSizeY Then

    ;Abfrage welche prüft ob die berechnete Tileposition auf ein Tile passt welches nicht
    ;begehbar ist.st dies der Fall wird TRUE zurückgeliefert und die Bewegung verhindert
    If testmap(tileX,Floor(result)) = 39 Then Return True

   EndIf
 
 EndIf

 ;Abfrage der Bewegungsrichtung(hier unten)
 If pDir = oben Then

  ;Die Tileposition für die angesteuerte Bewegung wird berechnet
  result = (py - 1) / 16

   ;Sicherungsabfrage um zu verhindern das der Spieler außerhalb des Maparraybereiches gehen kann
   If tileY > 0 Then

      ;Abfrage welche prüft ob die berechnete Tileposition auf ein Tile passt welches nicht
      ;begehbar ist.st dies der Fall wird TRUE zurückgeliefert und die Bewegung verhindert
      If testmap(tileX,Floor(result)) = 39 Then Return True
   
    EndIf
 
 EndIf


End Function


Bedanke mcih schonmal im Vorraus^^

MfG Ska

[EDIT]

Ich hab auch schon versucht per:

Code: [AUSKLAPPEN]


;Charackter anzeigen
DrawImage testchar,px-16,py-28,pDirGra



eine Korrektur vorzunehme.Wenn cih den Chara dann nach Rechts bewege
oder nach unten funktioniert das Ganze auch halbwegs....

Aber dann kann ich nicht exakt an einem nicht begehbarem Tile vorbeigehen oder die Bewegung von links wird nicht korrekt
ausgeführt.Ich bin gerade etwas ratlos was ich da
machen soll Sad

[/EDIT] [/code]
"In einer so verrückten Welt, kann man um in ihr zu überleben nur eines tun, nämlich eben jenes werden: Ein Verrückter!" -Selbstzitat

aktuelles Projekt: Aves Certim - Der Galgen ist nicht weit!
Ein SNES-RPG mit Handels- und Wirtschaftselemente.
Infos?Hier: http://www.blitzforum.de/worklogs/234/
Besucht meine Seite:
www.seelenfriedhof.de.vu

Skabus

BeitragFr, Mai 18, 2007 11:24
Antworten mit Zitat
Benutzer-Profile anzeigen
So....

Nachdem ich nun stundenlang rumprobiert habe, hab ich die Lösung gefunden:

Code: [AUSKLAPPEN]


Function TileKollision(pDir)

 ;Abfrage der Bewegungsrichtung(hier rechts)
 If pDir = rechts Then

  ;Die Karte wird nach alle Tiles durchsucht
  For y = 0 To mSizeY
  For x = 0 To mSizeX

   ;Wenn die Spielergrafik mit einem nicht begehbarem Tile kollidiert
   If (kollision = ImagesCollide(testtile,x*16,y*16,testmap(x,y),testchar,px-5,py,pDirGra)) = 0 Then
 
     ;Wird true zurückgegeben
     If testmap(x,y) = 39 Then Return True

   EndIf 

  Next
  Next
 
 
 EndIf

 ;Abfrage der Bewegungsrichtung(hier links)
 If pDir = links Then

  For y = 0 To mSizeY
  For x = 0 To mSizeX

   If (kollision = ImagesCollide(testtile,x*16,y*16,testmap(x,y),testchar,px-5,py,pDirGra)) = 0 Then
 
     If testmap(x,y) = 39 Then Return True

   EndIf 

  Next
  Next

 
 EndIf

  ;Abfrage der Bewegungsrichtung(hier unten)
  If pDir = unten Then

  For y = 0 To mSizeY
  For x = 0 To mSizeX

   If (kollision = ImagesCollide(testtile,x*16,y*16,testmap(x,y),testchar,px,py+5,pDirGra)) = 0 Then
 
     If testmap(x,y) = 39 Then Return True

   EndIf 

  Next
  Next
 
 EndIf

 ;Abfrage der Bewegungsrichtung(hier unten)
 If pDir = oben Then

  For y = 0 To mSizeY
  For x = 0 To mSizeX

   If (kollision = ImagesCollide(testtile,x*16,y*16,testmap(x,y),testchar,px,py-5,pDirGra)) = 0 Then
 
     If testmap(x,y) = 39 Then Return True

   EndIf 

  Next
  Next
 
 EndIf


End Function




Jetzt funktioniert das Ganze auch ordnungsgemäß und ohne Probleme.
Nun habe ich aber ein neues Problem:

Er erkennt nun folgerichtig wenn die Spielergrafik mit einem nicht begehbarem Tile kolidiert.
Da ich aber ein Chara hab der nicht auf der Map liegt sondern draufsteht,
sind nur die Füße des Charas auf der Karte aufliegend.
Somit müsste also nur der Fußbereich des Charas geprüft werden, nicht
die Spielergrafik selbst.

Ich dachte ich mach das Ganze mittels eines "Dummys" den ich dann
über den Fupbereich lege und frag dann nur noch die Kolision mit dem
Fußbereich ab.Leider scheint das nicht zu funktionieren.
Oder ich mache was falsch.

Hat jemand ne Idee wie ich dieses Problem lösen könnte?


MfG Ska
"In einer so verrückten Welt, kann man um in ihr zu überleben nur eines tun, nämlich eben jenes werden: Ein Verrückter!" -Selbstzitat

aktuelles Projekt: Aves Certim - Der Galgen ist nicht weit!
Ein SNES-RPG mit Handels- und Wirtschaftselemente.
Infos?Hier: http://www.blitzforum.de/worklogs/234/
Besucht meine Seite:
www.seelenfriedhof.de.vu

BladeRunner

Moderator

BeitragFr, Mai 18, 2007 12:26
Antworten mit Zitat
Benutzer-Profile anzeigen
Mach Dir ein Bild auf dem nur die Fusssohlen 'eingezeichnet' sind, aber welches ansonsten dieselben Masse hat wie deine Playergraphik. Du musst da Bild nicht einzeichnen, es reicht wenn Du dieses Bild bei der Kollisionsprüfung als Quelle angibst.
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

Skabus

BeitragFr, Mai 18, 2007 15:00
Antworten mit Zitat
Benutzer-Profile anzeigen
Dankeschön^^

Ich habs jetzt nochmal ausprobiert.Ich hab das ganze nun so geändert
das es einen Positionsdummy gibt der als Quelle für die Kollision genommen
wird.Die Spielergrafik wird dann nur genau an der Stelle des Positionsdummys
angezeigt.So sieht der Spieler keinen Unterschied und die Kollision
läuft richtig ab.

Falls es aber jemanden gibt der ne Ahnung hat wie man das Ganze etwas
eleganter lösen kann dann wäre ich sehr dankbar wenn er es hier posten
könnte.

Ich meine, es funktioniert perfekt aber ich glaub nicht dass das
wirklich das ist was man "sauberes Programmieren" nennt XD

MfG Ska
"In einer so verrückten Welt, kann man um in ihr zu überleben nur eines tun, nämlich eben jenes werden: Ein Verrückter!" -Selbstzitat

aktuelles Projekt: Aves Certim - Der Galgen ist nicht weit!
Ein SNES-RPG mit Handels- und Wirtschaftselemente.
Infos?Hier: http://www.blitzforum.de/worklogs/234/
Besucht meine Seite:
www.seelenfriedhof.de.vu

BladeRunner

Moderator

BeitragFr, Mai 18, 2007 16:25
Antworten mit Zitat
Benutzer-Profile anzeigen
Es ist ein gebräuchlicher, ressourcenschonender und exakter Weg- was willst Du mehr ?
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

Skabus

BeitragFr, Mai 18, 2007 16:35
Antworten mit Zitat
Benutzer-Profile anzeigen
BladeRunner hat Folgendes geschrieben:
Es ist ein gebräuchlicher, ressourcenschonender und exakter Weg- was willst Du mehr ?
Wink


Stimmt auch wieder XD
Es mutet nur komisch an das man für jedes spielergleiches Objekt
auf der Karte einen Positionsdummy braucht um die Kollision exakt
zu bestimmen.

Aber wenn das ein gebräuchlicher und exakter Weg ist bin ich ja vollends
zufrieden^^


MfG Ska
"In einer so verrückten Welt, kann man um in ihr zu überleben nur eines tun, nämlich eben jenes werden: Ein Verrückter!" -Selbstzitat

aktuelles Projekt: Aves Certim - Der Galgen ist nicht weit!
Ein SNES-RPG mit Handels- und Wirtschaftselemente.
Infos?Hier: http://www.blitzforum.de/worklogs/234/
Besucht meine Seite:
www.seelenfriedhof.de.vu

Neue Antwort erstellen


Übersicht BlitzBasic Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group