Diagonale Bewegung - Kollision funktioniert nicht
Übersicht

dom_dotBetreff: Diagonale Bewegung - Kollision funktioniert nicht |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Ich habe ein Problem mit der Bewegung in einer 2D Tile Engine.
Es funktioniert an sich alles super: Beim Richtungstasten druck bewegt sich die Spielerfigur fließend um die Tilegröße 32 in die jeweilige Richtung und das auch nur wenn sich dort keine Wand oder Ähnliches befindet. Wenn man nun allerdings z.B. die Nach-Oben und Nach-Links-Taste gleichzeitig drückt bewegt sich der Spieler auch in blockierte Felder hinein, solange das Feld direkt über- und das Feld direkt links von der Spielerfigur nicht blockiert ist. Das will ich natürlich nicht. ![]() Weis aber auch nicht wie ich das verhindern soll. Hier mal mein Code für die Bewegung damit ihr direkt seht wie ich das ganze Umgesetzt habe: Code: [AUSKLAPPEN] ;Spieler Steuern
If KeyDown(203) Then Frame = 2 ;Gibt die Blickrichtung an If Level(X1-1,Y1,1) = 0 Then ;Links If Links = 0 Then Links = 1 If X1-SX/32 < 4 Then ;Scrollen SX = SX - 8 EndIf EndIf EndIf If KeyDown(205) Then ;Rechts Frame = 3 If Level(X1+1,Y1,1) = 0 Then If Rechts = 0 Then Rechts = 1 If X1-SX/32 > 20-3 Then SX = SX + 8 EndIf EndIf EndIf If KeyDown(200) Then ;Hoch Frame = 0 If Level(X1,Y1-1,1) = 0 Then If Oben = 0 Then Oben = 1 If Y1-SY/32 < 4 Then SY = SY - 8 EndIf EndIf EndIf If KeyDown(208) Then ;Runter Frame = 1 If Level(X1,Y1+1,1) = 0 Then If Unten = 0 Then Unten = 1 If Y1-SY/32 > 15-3 Then SY = SY + 8 EndIf EndIf EndIf ;Bewegen If Links > 0 Then PX1 = PX1 -8 ani = (ani+1) Mod 12 Links = Links + 1 If Links = 5 Then Links = 0 EndIf EndIf If Rechts > 0 Then PX1 = PX1 +8 ani = (ani+1) Mod 12 Rechts = Rechts + 1 If Rechts = 5 Then Rechts = 0 EndIf EndIf If Oben > 0 Then PY1 = PY1 - 8 ani = (ani+1) Mod 12 Oben = Oben + 1 If Oben = 5 Then Oben = 0 EndIf EndIf If Unten > 0 Then PY1 = PY1 + 8 ani = (ani+1) Mod 12 Unten = Unten + 1 If Unten = 5 Then Unten = 0 EndIf EndIf |
||
![]() |
hazumu-kun |
![]() Antworten mit Zitat ![]() |
---|---|---|
Bei Tilebasierten Spielen ist es üblich diagonale Bewegungen zu verbieten:
BlitzBasic: [AUSKLAPPEN]
|
||
Warum kann es keine omnipotente Macht geben?
Weil diese omnipotente Macht in der Lage sein müsste, einen so schweren Stein zu schaffen, dass sie ihn nicht heben kann -> nicht omnipotent |
![]() |
Hubsi |
![]() Antworten mit Zitat ![]() |
---|---|---|
Es gab mal ein richtig gutes Tutorial für genau Dein Problem, nur finden kann ich es nirgends mehr. Daher poste ich einfach mal ein Stück Code aus meinem aktuellen Projekt. p\x und p\y sind dabei die Spielfigurkoordinaten und die Tiles 32*32 Pixel, ebenso wie der Spieler:
BlitzBasic: [AUSKLAPPEN] u=map((p\x+16)/32,(p\y-2)/32,0) ; oben / up Der dritte Wert im Array ist nur der Layer. Einfach rausschmeissen bei Bedarf. Rückgabewert ist die Nummer des Tiles rund um und unter der Spielfigur. |
||
Den ganzen Doag im Bett umanandflagga und iaz daherkema und meine Hendl`n fressn... |
dom_dot |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
hazumu-kun hat Folgendes geschrieben: Bei Tilebasierten Spielen ist es üblich diagonale Bewegungen zu verbieten
Wäre eine einfache Möglichkeit das Problem zu umgehen aber ich glaube für das Gameplay wäre das am Ende ein großer Verlust. Soll was action-lastiges mit Ausweichen usw. werden.. @ Hubsi Schade! ![]() Aus deinem Code werde ich leider nicht ganz schlau.. Also ich versteh was er tut aber wie muss ich das einbringen damit es mein Problem löst? |
||
![]() |
Hubsi |
![]() Antworten mit Zitat ![]() |
---|---|---|
Du prüfst ob der Spieler nach oben gehen kann (bspw. If u=0) und die Figur wird bedarfsweise nach oben bewegt. Dann prüfst Du ob nach links frei ist und er bewegt sich bedarfsweise nach links. Wenn der Spieler jetzt nach links oben laufen will aber oben eine Mauer oder was weiß ich ist bewegt er sich nur links. Und so weiter eben. | ||
Den ganzen Doag im Bett umanandflagga und iaz daherkema und meine Hendl`n fressn... |
dom_dot |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Argh! Ich glaub ich bin echt zu dumm! ![]() Tut mir leid, ein Beispiel wie du das einbauen würdest? Soll ich erst deinen Code ausführen, dann die Tasten abfragen und in der Tastenabfrage dann die Variable abfragen? Und dann? Im Grunde frage ich in meinem Code ja auch nach der Tastenabfrage ab ob das Tile auf das sich bewegt werden würde begehbar ist. |
||
Pousup |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Wenn du nicht zu 100% auf Tile-to-Tile-Bewegungen setzen willst, hat SpionAtom mir mal eine
schöne Lösung für Pixel-to-Pixel-Bewegungen gezeigt, die bei Tilemaps funktioniert und auch diagonale Bewegungen zulässt. Code: [AUSKLAPPEN] Graphics 600, 600, 0, 2
SetBuffer BackBuffer() timer = CreateTimer(58) Data 10,10 Data 1,1 Data 1,1,1,1,1,1,1,1,1,1 Data 1,0,0,0,0,0,0,0,0,1 Data 1,0,1,0,1,0,1,0,1,1 Data 1,0,0,0,0,0,0,0,0,1 Data 1,1,0,1,0,1,0,1,0,1 Data 1,0,0,0,0,0,0,0,0,1 Data 1,0,1,0,1,0,1,0,1,1 Data 1,0,0,0,0,0,0,0,0,1 Data 1,1,0,1,0,1,0,1,0,1 Data 1,1,1,1,1,1,1,1,1,1 ;Map laden Global mapw, maph, mapg, sx, sy, sg Read mapw, maph Read sx, sy Dim map(mapw, maph) For i = 0 To mapw * maph - 1 Read map(i Mod mapw, i / mapw) Next mapg = 60 ;Map-Tile-Größe sg = 25 ;Spieler-Größe speed = 6 ;Spieler-Geschwindigkeit ;Spielerposition sx = (sx + 0.5) * mapg sy = (sy + 0.5) * mapg Repeat If KeyDown(200) Then If playerOnWall(sx, sy - speed) Then ;Bis zur Mauer gehen sy = sy / mapg * mapg + sg / 2 Else ;Einen ganzen Schritt gehen sy = sy - speed End If End If If KeyDown(208) Then If playerOnWall(sx, sy + speed) Then ;Bis zur Mauer gehen sy = (sy / mapg + 1) * mapg - 1 - sg / 2 Else ;Einen ganzen Schritt gehen sy = sy + speed End If End If If KeyDown(203) Then If playerOnWall(sx - speed, sy) Then ;Bis zur Mauer gehen sx = (sx / mapg ) * mapg + sg / 2 Else ;Einen ganzen Schritt gehen sx = sx - speed End If End If If KeyDown(205) Then If playerOnWall(sx + speed, sy) Then ;Bis zur Mauer gehen sx = (sx / mapg + 1) * mapg - 1 - sg / 2 Else ;Einen ganzen Schritt gehen sx = sx + speed End If End If Cls drawMap Color 255, 255, 0 Rect sx - sg / 2, sy - sg / 2, sg, sg Text 0, 0, playerOnWall(sx, sy) WaitTimer(timer) Flip 0 Until KeyDown(1) End ;Prüfe 4 Eckpunkte des Spielers auf Kollision mit Map() Function playerOnWall(x, y) r = sg / 2 If map((x - r) / mapg, (y - r) / mapg) = 1 Then Return True If map((x + r) / mapg, (y - r) / mapg) = 1 Then Return True If map((x - r) / mapg, (y + r) / mapg) = 1 Then Return True If map((x + r) / mapg, (y + r) / mapg) = 1 Then Return True Return False End Function Function drawMap() Color 255, 255, 255 For i = 0 To mapw - 1 For j = 0 To maph - 1 If map(i, j) Then Rect i * mapg, j * mapg, mapg, mapg, 0 Next Next End Function Ist wie gesagt nicht meine eigene Lösung, sondern die von SpionAtom! |
||
![]() |
Hubsi |
![]() Antworten mit Zitat ![]() |
---|---|---|
So in etwa würde ich das gestalten:
BlitzBasic: [AUSKLAPPEN] ; Pseudocode So oder so ähnlich ![]() |
||
Den ganzen Doag im Bett umanandflagga und iaz daherkema und meine Hendl`n fressn... |
dom_dot |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Ich verzweifle!
@ Pousup Dein Code lässt sich nur sehr schwer mit meinem Gerüst für die Animation verbinden.. Außerdem ist das ja eher dafür gedacht bei Bewegungen um wenige Pixel genau die wände ab zu fragen, wenn ich das richtig verstanden habe. Aber ich habe ja im Grunde nur tileweise-Bewegung.. @Hubsi Bei deinem Code hatte ich erst Probleme weil ich ein MidHandle benutze und meine Spielfigur 64px hoch ist. Musste erstmal darauf kommen deine Werte in der Abfrage entsprechend an zu passen. ![]() Blöderweise verhindert auch diese Abfrage nicht dass der Spieler, bei diagonaler Bewegung in Hindernisse hineinlaufen kann... Wie gesagt: Ich verzweifle! ![]() Wenn der Spieler sich AUF, VOR und RECHTS von einem begehbaren Tile befindet, das Tile OBEN-LINKS von ihm aber nicht begehbar sein sollte fragt er bei gleichzeitigem Tastendruck (OBEN UND LINKS) ob er von seiner aktuellen Position aus nach LINKS gehen kann UND ob er nach OBEN gehen kann. Da beides mit ja beantwortet wird geht er dann nach OBEN UND LINKS also OBEN-LINKS, wo aber eigentlich ein blockiertes Feld ist. Würde es eventuell Sinn machen in jede Richtungstastenabfrage noch jeweils andere Richtungstastenabfragen zu machen die dann überprüfen ob die diagonal liegenden Felder begehbar sind? Wenn ja, wie würde man diese Abfrage am günstigsten umsetzen? Sorry das ich so blöd frage, aber ich bin das Trial and Error sowas von satt! ![]() |
||
Blitzjockey |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Hey, ich habe es noch lange nicht fertig geschrieben, aber es soll ja für Dich ja was übrig bleiben. So ganz Deine Code angepasst habe ich es auch noch nicht, aber was Folgendes macht, ist zumindest Dein Diagonal-problem lösen:
Code: [AUSKLAPPEN] Local Horizontal = (KeyDown(205) - KeyDown(203)) Local Vertical = (KeyDown(200) - KeyDown(208)) If level(x1 + Horizontal, y1 + Vertical, 1) = 0 Then SX = SX + 8 * Horizontal SY = SY + 8 * Vertical end if If Horizontal Then px = px + 8 * Horizontal ani = (ani + 1) Mod 12 End If If Vertical Then py = py + 8 * Vertical ani = (ani + 1) Mod 12 End If Hier sind L,R,O,U ersetzt worden mit Horizontal und Vertical. Hierbei gilt: Horizontal = 1 bei KeyDown(205) oder -1 bei Keydown(203) oder 0 wenn beide oder keine Taste gedruckt wird. Das gleiche gilt für Vertical. Abfrage dann x1 + Horizontal: Hor. = 1 dann gilt X1 + 1. Hor. = -1 dann gilt X1 + (-1), ist ja mathematisch dass gleiche wie X1 - 1. So auch für Vertical. Sollte nun Hor und Ver gleichzeitig bedient werden, werd automatisch dass feld X1 + 1, Y1 + 1 kontrolliert. Oder X1 + (-1), Y1 + (-1) u.s.w. Dann die bewegung, auch hier dass gleiche: SX + 8 * 1 ist ja SX + 8. SX + 8 * -1 ist gleich SX - 8. Evt. Kontrolle auf Boundary-überschreitungen, Scrollen und Animationen kommen dann danach. Dass gleiche Prinzip für Bewegen, nur habe ich da Dein Links = Links + 1, bis 5, dann 0, noch nicht ersetzt durch irgendwass anderes, da ich nicht genau weiss was Du damit vorhasst. Aber wie gesagt, ein bisschen sollte was für Dich übrig bleiben! ![]() Ich hoffe es bringt Dir eine Lösung etwas näher? Schöne Grüße, BlitzJ. (EDIT: Code etwas verlängert..) |
||
GERMAX |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
habe vor x jahren auch mal so ein game geschrieben. sowas wie atomix 2. bei mir war der ganze level in einer 2-d tabelle abgelegt. da braucht man dann nur von der aktuellen position (bei links-oben movement) eine zeile abzuziehen-1 (das funktioniert besonders gut, wenn der level von einer mauer umgeben ist). anschliessend in der tabelle nachgucken, welches tile da drinsteckt.
aber jeder hat halt ein eigenes system. ![]() |
||
Erfolglos begonnene BB-Projekte:TRON/CONVOY/MYSTIC |
dom_dot |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Ich hab mich heute (zum Leidwesen der Philosophie Klausur morgen) wieder viele Stunden mit dem Problem befasst und all eure Ansätze in den verschiedensten Formen ausprobiert aber nicht das gewünschte Ergebnis erzielt, wobei Blitzjockeys Ansatz dennoch ziemlich interessant war. ![]() Das Problem besteht sogar weiterhin wenn ich das diagonale Laufen mit ElseIf in den KeyDown-Abfragen verhindere. Das liegt, glaube ich daran, dass ich mit dem Druck einer Richtungstaste den Schritt nur "auslöse" und er dann von alleine weiter läuft. Das habe ich so gemacht damit ich eine flüssige Animation bekomme. Das kann man auch im von mir ganz am Anfang geposteten Quelltext sehen. Das Problem ist dabei, dass, nachdem ich den Schritt nach oben aktiviert habe und dieser auch als "möglich" Bestätigt wurde ich ganz schnell einen Schritt nach links auslösen kann der dann die Kollision noch abfragt bevor die Spielfigur mit dem Schritt nach oben das obere Tile erreicht hat und dann brav beide Schritte abgearbeitet werden sodass man halt im eigentlich blockiertem Tile oben-links landet. Wie ich das Problem jetzt löse weis ich aber immer noch nicht. ![]() Ich hab schon wirklich viele anscheinend nahe liegende Lösungen ausprobiert die aber meistens darin resultierten das man gar nicht mehr diagonal laufen kann oder im Fall des Doppeltastendrucks die Figur erst einen Schritt in die eine und dann den in die andere Richtung macht. Ich hab jetzt keine Lust mehr mich damit auseinander zu setzen und fange mal an einen Leveleditor zu basteln.. Meine Hoffnung ruht jetzt tatsächlich darin, dass vielleicht einer von euch eine Lösung weis die auch auf mein Konstrukt mit den Animationen usw. anwendbar ist. |
||
Blitzjockey |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
![]() Zusätzlich habe ich da noch eine Frage zu Deine Animation. Du hast ja eh nur 4 Animationen? L,R,O,U aber kein Diagonal oder? Wie Du schon gesagt hast, zumindest beim Diagonalen Loslaufen hätte mein Ansatz geklappt, nur in Dein Situation (Kurswechsel nach dem loslaufen) muss man da wohl ein extra Lösung suchen. Ich habe zwar im Moment kein Code fertig, aber ich möchte das als Ansatz zum Nachdenken schon mal hinstellen: Stell ein Ziel-Position fest. z.b. Beim loslaufen richtung Oben, stellst Du als ZielPosition (X, Y - 1) fest. Diese behälst Du bei, und kontrollierst jeden durchlauf ob diese noch "0" zurückgibt. Der Trick kommt jetzt: Sollte nach dem loslaufen noch ein Kursänderung folgen, wird die Zielposition mitgeändert. z.b. Links: Jetzt gilt zusätzlich X - 1 --> (X - 1, Y - 1). Falsch das jetzt ein 1 zurück gibt, ist dieses neue Ziel nicht begehbar. Nun hast Du 2 optionen: Entweder Du verbietest nur den Links-schwenk,(Es bleibt bei (X, Y - 1) und Du ignorierst einfach den Links-taste (Er lauft weiterhin richtung Oben); Oder Du hällst den ganze Bewegung an. Aber ich denke Option 1 ist da den bessere Ansatz. Viel Erfolg, und lass wissen ob es was gebracht hat! BlitzJ. |
||
GERMAX |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Level(xpos,ypos,levelnr)?
BlitzBasic: [AUSKLAPPEN]
vllt hilft das weiter. |
||
Erfolglos begonnene BB-Projekte:TRON/CONVOY/MYSTIC |
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group