Pixelgenaue Tilemap Kollision mit Winkeln!?
Übersicht

![]() |
M0rgensternBetreff: Pixelgenaue Tilemap Kollision mit Winkeln!? |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hey Leute.
Ich bins schon wieder mit meiner Tilemap. Hab im Forum durch die Forensuche auch einiges gefunden, aber leider nichts was auf mein Problem passt, da in keinem Beispiel mit Winkeln gearbeitet wurde. Ich habe folgendes Problem: Mein Spieler bewegt sich inzwischen schon in den Mapgrenzen über die Map. Eine Kollisionsabfrage habe ich auch schon eingebaut. Aber das ganze funktioniert noch nicht so richtig. Ich kann je nach "Aufprallwinkel" immernoch in ein unbegehbares Tile "glitchen" bzw oftmals bin ich schon an einer unbegehbaren Stelle, dann schlägt erst die Kollision an. Zurück kann ich dann aber wieder. Die Kollision nach oben und links funktioniert besser als die nach rechts und unten. Hier mal der Code: BlitzMax: [AUSKLAPPEN] Method Move(pscrollx:Float, pscrolly:Float) Das Problem ist wohl auch einfach, die ganze Rechnerei mit den Winkeln. Wäre schön, wenn jemand Abhilfe wüsste. Achja, btw.: Wenn ich mich über die Map bewege, dann sieht es manchmal kurz so aus, als würde das scrollen nicht so ganz flüssig laufen. Woran könnte das denn liegen? Ich lasse nur die TIles zeichnen die zu sehen sind. Lg, M0rgenstern |
||
![]() |
Goodjee |
![]() Antworten mit Zitat ![]() |
---|---|---|
erstmal rate ich dir ein bisschen den code kleiner zu machen
erst die neue position in abhängigkeit von tasten berechnen dann mit der neuen position gucken ob das bewegen erlaubt ist. so schreibst du die kollision selber nur einmal, statt 4 mal das problem bei deiner herangehensweise ist, dass bei zu hohen geschwindigkeiten hinternisse einfach übersprungen werden. bei relativ niedrigen geschwindikeiten passiert das hauptsächlich an kanten, bei hohen kann auch einfach grade durch ein kästchen gesprungen werden. mögliche alternative ist geschwindigkeit runter, in kleineren schritten testen oder linien<>rechteck kollision. vllt liegen deine scrollingruckler nicht am code, sondern nur an der grafikausgabe, sogenanntes tearing |
||
"Ideen sind keine Coladosen, man kann sie nicht recyclen"-Dr. House
http://deeebian.redio.de/ http://goodjee.redio.de/ |
![]() |
XeresModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich nehme an, es liegt an der Abfrage...
Code: [AUSKLAPPEN] (iGameMap[fNewx / iTilesize, fNewy / iTilesize, 2] = 0) ...ob das Tile begehbar ist oder nicht. Du teilst da Float durch Int -> abgerundete Werte werden bevorzugt: Oben & Links.
Vorschlag: Code: [AUSKLAPPEN] (iGameMap[Int(fNewx / Float(iTilesize)), Int(fNewy / Float(iTilesize)), 2] = 0)
Gehst du beim Zeichnen das gesamte Array durch oder auch nur das nötigste? |
||
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus THERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld) |
![]() |
M0rgenstern |
![]() Antworten mit Zitat ![]() |
---|---|---|
Also, Ich hab die Abfrage mal geändert wie Xeres gesagt hat. Hat nichts gebracht
Ich habe auch mal den Spielerspeed von 4 auf 1 runtergeschraubt und das Problem mit der Kollision besteht immernoch. @Goodjee: Was genau meinst du mit Linien/Rect Kollision? @ Xeres: MIt diesem Code lasse ich zeichnen: BlitzMax: [AUSKLAPPEN] For Local iMapXIndex:Int = 0 To (iMapwidth - 1) Lg, M0rgenstern |
||
![]() |
Midimaster |
![]() Antworten mit Zitat ![]() |
---|---|---|
ich hab mir mal den Spaß gemacht und deinen Code etwas gekürzt. Das müsste auch so noch funktionieren:
BlitzMax: [AUSKLAPPEN] Method Move(pscrollx:Float, pscrolly:Float) In einem kürzeren Code sehen andere besser, was Du programmiert hast. Erläuterungen: Die unteren 5 Zeilen sind glaube ich völlig unnötig, da dieser Zustand nicht eintreten kann, wenn voher schon so ordentlich gecheckt wurde: BlitzMax: [AUSKLAPPEN] Rem
Die Berechnung der wirklichen Koordinaten muss nicht ein zweites Mal gemacht werden, weil das Ergebnis ja schon in fNewX bzw fNewY vorliegt: BlitzMax: [AUSKLAPPEN] REM unnötig! das wurde schon berechnet:
Dadurch dass sich dies jetzt immer durch... BlitzMax: [AUSKLAPPEN] fX = fNewx...ersetzen lässt, wird vieles sehr gleich. Es wandert ein großer Teil außerhalb der IF-Vergleiche. Außerdem verwende ich für einige Berechnungen, die häufiger vorkommen, locale Zwischenvariable, z.B. für das "fNewX / iTilesize" BlitzMax: [AUSKLAPPEN] locMapX% = fNewX/iTilesize Ist die Zeile... BlitzMax: [AUSKLAPPEN] If (iGameMap[locMapX, locMapY, 2] = 0) Then ...alles, was du zum Thema "Collision" bis jetzt in deinem Code hast? |
||
![]() |
Noobody |
![]() Antworten mit Zitat ![]() |
---|---|---|
Xeres hat Folgendes geschrieben: Du teilst da Float durch Int -> abgerundete Werte werden bevorzugt: Oben & Links.
Nach den Konvertierungsregeln ("Lower type is always promoted to the upper type") wird der Integer im Divisor zu einem Float umgewandelt und erst danach Dividiert. Wegen abrunden muss man sich also keine Sorgen machen - das kommt erst zu tragen, wenn man Int durch Int teilt ![]() |
||
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun |
![]() |
M0rgenstern |
![]() Antworten mit Zitat ![]() |
---|---|---|
@ Midimaster:
Ich war einfach mal so frei, deinen Code zu Testzwecken zu übernehmen. Folgendes Problem hat sich dadurch ergeben: Der Spieler kann sich jetzt, ausgehend von seiner Startposition nur noch diagonal nach links oben bzw rechts unten bewegen. Irgendwas stimmt da also nicht, werds jetzt erstmal von der Berechnung her in das alte umändern. Ja, diese Zeile ist die einzige die momentan wegen der Kollision drin ist. Warum? Achso: Muss ich vielleicht mit floor/ceil arbeiten? Wenn ja: Wo muss ich was einbauen? Lg, M0rgenstern EDIT: Der neue, gekürzte Code: BlitzMax: [AUSKLAPPEN] Method Move(pscrollx:Float, pscrolly:Float) Die letzten vier Zeilen musste ich drin lassen, da er sonst bei den "Nullpunkten" der Karte schon außerhalb der Karte war. Lg, m0rgenstern |
||
![]() |
XeresModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Danke für den Hinweis, Noobody.
@ M0rgenstern: Code: [AUSKLAPPEN] For Local iMapXIndex:Int = 0 To (iMapwidth - 1) Je größer die Karte wird, desto geringer ist relativ dazu die Anzahl der Tiles, die du Tatsächlich zeichnen willst.
Mit den Scroll Werten, kannst du das doch schon auf den sichtbaren Bereich eingrenzen? Dann entfällt auch die innere Abfrage, ob die Tiles sichtbar sind oder nicht. |
||
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus THERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld) |
![]() |
Midimaster |
![]() Antworten mit Zitat ![]() |
---|---|---|
@Morgenstern...
ja, logisch, du hast recht, Deine Methode erlaubt ja allen 4 Tasten gleichzeitig die Veränderung der fNewX bzw fNewY. Da könnte dann fX bzw fY maximal 4x in einer Methode geändert sein. So wie ich das geschrieben habe, setzt sich immer nur eine der Tasten durch. Der Code muss also so umgebaut werden , dass das Berechnen bereits in jeder der IF-Verzweigungen erfolgen muss, um als Grundlage der nachfolgenden IF-Verzweigung bereits zur Verfügung zu stehen: BlitzMax: [AUSKLAPPEN] Method Move(pscrollx:Float, pscrolly:Float) Der Code würde dadurch nochmals kürzer... |
||
![]() |
M0rgenstern |
![]() Antworten mit Zitat ![]() |
---|---|---|
ALso:
@ Xeres: Ja du hast recht, das müsste besser sein. Habs jetzt auch geändert und habe das Gefühl, dass das ganze schneller ist. "Flüssiger" ist es trotzdem nicht. Also, dieses "Ruckeln", dass man das Gefühl hat die TIles würden "nachrücken" bleibt aber bestehen. Im Editor ist das ganze noch ein wenig deutlicher, auch optisch: Wenn ich dort nach Links scrolle, dann habe ich das Gefühl, dass sich am rechten Rand einiger Tiles ein kleines Stück schwarz zeigt. Wenn ich nach unten scrolle dann am oberen Rand etc. Der neue COde für die Map, hoffe das stimmt so, funktioniert jedenfalls: BlitzMax: [AUSKLAPPEN] Local fscrollX:Float = Player.fX - GraphicsWidth() / 2 Das Problem mit der Kollision besteht aber immernoch und dafür finde ich leider keine Lösung. @ Midimaster: HAst schon Recht. Man kann das ganze kürzer schreiben. Werde ich auch noch tun. Nur ich finde, Codeoptimierung kann man später noch betreiben, wichtiger ist, dass alles erstmal funktioniert. Denn ansonsten bastelt man schonmal stundenlang an funktionierendem Code rum, damits schneller wird obwohl man andere grundlegende Dinge noch nicht implementiert hat. Lg, M0rgenstern |
||
![]() |
Midimaster |
![]() Antworten mit Zitat ![]() |
---|---|---|
Zwei Vorschläges zu den Performance-Problemen:
1. Messe bitte mal mit einem Timer, wie lange das gesamte Zeichnen der Tiles dauert: BlitzMax: [AUSKLAPPEN] MessZeit=MilliSecs() 2. Probier mal nicht genau die passende Anzahl Tile zu malen, sondern beginne jeweils von eines zu früh links bis eines zu viel rechts. Das Gleiche mit oben und unten. zu den Kollisionen: Dein Spieler bewegt sich ja nicht rasternd sondern pixelweise frei über die gerasterte Landschaft. Das heißt er kann auf bis zu 4 Tiles gleichzeitig stehen. Meiner Meinung nach solltest Du mal alle 4 Eckpunkte des Spielers auf Kollision chekcne. Bisher chekcs Du immer die linke obere Ecke (ist ja auch der Draw-Bezugspunkt). Deshalb funktioniert es in diese Richtung bereits sehr gut bisher hattest Du: BlitzMax: [AUSKLAPPEN] If (iGameMap[fNewx / iTilesize, fNewy / iTilesize, 2] = 0) Then wie wäre es mit 4 Tests? BlitzMax: [AUSKLAPPEN] If (iGameMap[fNewx / iTilesize, fNewy / iTilesize, 2] = 0) Then |
||
![]() |
M0rgenstern |
![]() Antworten mit Zitat ![]() |
---|---|---|
ERstmal: VIELEN DANK.
Die Kollision funktioniert jetzt. Kann man sicher noch ein wenig feiner berechnen, aber das kann man ja immernoch machen. Wegen der Zeit die er zum zeichnen braucht: Desto weiter ich in der Kartenmitte bin, desto länger braucht er (logischerweise) um zu zeichnen. Aber selbst da war das höchste, was ich erkennen konnte eine 4. Aber ansonsten zeigt er überweigend eine 2 und am Kartenrand sogar dauerhaft eine 0 an. Ich lasse jetzt immer ein Tile mehr zeichnen: BlitzMax: [AUSKLAPPEN] Local iTilescrollMinx:Int = (fscrollx / itilesize) - 1 Habs einfach überall miteingerechnet. Das "ruckeln" bleibt aber immernoch. Wie gesagt, es ist, als würden sich manche Tiles verschieben. Beim scrollen nach links entsteht an manchen TIles an der rechten Seite ein schwarzer Rand usw. Lg, M0rgenstern |
||
![]() |
Midimaster |
![]() Antworten mit Zitat ![]() |
---|---|---|
Mmhhhmmm....
Alles was Timingmäßig unter 16 ist, ist für das Auge zu schnell. Daran kann es nicht liegen. Wenn Du jetzt immer eine Tile-Reihe mehr zeichnest, kann eigentlich kein schwarzer Rand mehr zu sehen sein. Dann liegt es an der Grafikkarte. Sie zeichnet die Objekte einfach nicht, weil sie glaubt sie wären zu 100% nicht sichtbar. Kannst du mal eine Situation erzeugen, in der du genau so weit läufst (scrollst) und dann stehenbleibst, so dass dieser schwarze Rand für längere Zeit sichtbar bleibt? Oder blitzt er immer nur kurz auf und wird dann beim nächsten Bildaufbau korrigiert? Bewege zu diesem Test die Figur nicht mit der Tastatur-Steuerung, sondern automatisch: BlitzMax: [AUSKLAPPEN] If MoveZeit<MilliSecs() Then So hast du Ruhe und Zeit den Effekt zu beobachten. Wie sieht genau die Main-Schleife mit dem FLIP aus? Lass dir auch die Werte für... iTilescrollMinX iTilescrollMinY iTilescrollMaxX iTilescrollMaxY ...mal ausgeben. Gibt es da manchemal Momente wo es weniger sind? BlitzMax: [AUSKLAPPEN] Print "Flaeche: X=" (iTilescrollMaxX - iTilescrollMinX) + " Y=" + (iTilescrollMaxY - iTilescrollMinY) + " " |
||
![]() |
M0rgenstern |
![]() Antworten mit Zitat ![]() |
---|---|---|
Also.
Ich hab jetzt mal verschiedene Maps getestet. Ergebnis: Wenn Sie nur aus einem einzigen TIle besteht (also z.b. nur Grastile) dann hat man immernoch dieses Gefühl, dass es ein wenig "ruckt" aber die schwarzen Streifen bilden sich nicht. Dann habe ich in die gleiche Map einfach ein großes Viereck mit einem anderen Tile wo dann wieder ein andersartiges VIereck drin ist, eingebaut. Dann sieht man die schwarzen Streifen, bzw man sieht manchmal statt einem schwarzen Streifen die Farbe des einen Tiles in die andere überlaufen. Ich habe hier mal ein Screenshot gemacht. Links am Rand des blauen Vierecks konnte in den Fehler ansatzweise einfangen. Das Problem ist, dass er scheinbar immernoch ein BIld lang bleibt. Also er lässt sich auch nicht dauerhaft nachstellen. Die Fläche, die an Tiles angezeigt wird ist immer gleichbleibend außer (logischerweise) an den Rändern der Karte, wo ja weniger TIles zu zeichnen sind. Es sind immer 34*26 TIles. Hier ist die Hauptschleife: BlitzMax: [AUSKLAPPEN] While Not KeyHit(KEY_ESCAPE) Or AppTerminate() Also, wie gesagt, der Fehler lässt sich nur ganz schlecht einfangen, da er einfach beim nächsten BIldlauf wieder weg ist. Er kommt dann zwar direkt wieder, aber dauerhaft nachstellen geht nicht. Also es scheint nur unwesentlich an der Verschiebung der Tiles zu liegen, da es nicht dauerhaft nachstellbar ist, sondern immernur Frameweise. Lg, M0rgenstern |
||
![]() |
mpmxyz |
![]() Antworten mit Zitat ![]() |
---|---|---|
Wenn du das Bild vergrößerst wirst du keine dunklen Pixel entdecken.
Daher habe ich das Gefühl, dass sich dieses Phänomen mit der Subpixelstruktur deines Bildschirmes erklären lässt. Ein Pixel ist dabei aus diesen Subpixeln aufgebaut: |rot-grün-blau| An der Grenze zwischen dem roten und dem hellblauen Tile sieht die Situation nun so aus: |ROT-grün-blau|rot-GRÜN-BLAU| (Die großgeschriebenen Teile leuchten.) Der fette, nicht leuchtene Teil hat die Größe von einem ganzen Pixel und wirkt deshalb dunkler. An der rechten Seite des Vierecks kann man auch den umgekehrten Effekt beobachten: |rot-GRÜN-BLAU|ROT-grün-blau| Die Stelle wirkt heller. mfG mpmxyz |
||
Moin Moin!
Projekte: DBPC CodeCruncher Mandelbrot-Renderer |
![]() |
Midimaster |
![]() Antworten mit Zitat ![]() |
---|---|---|
spannend wäre in diesem Zusammenhang, ob man dort den Hintergrund sieht oder immer einen schwarzen strich. Färbe mal den CLS Hintergrund in gelb und schau dann nach, ob die striche jetzt gelb sind.
BlitzMax: [AUSKLAPPEN] Cls Ist die Skalierung auf dem Bildschirm garantiert immer 100%? BlitzMax: [AUSKLAPPEN] SetScale 1,1 es sieht ein wenig so aus, als ob es Artifacte im Screenshot gäbe. Kann natürlich jetzt auch vom Hochladen kommen. Wenn es immer nach 1 Pixel verschwindet, kann es tatsächlich an der Graphikkarte liegen. Probier mal testhalber mit FLIP 1 Außerdem hast du das von mir vorgeschlagene Auto-Scrollen mit "+4" gemacht. Nimm dir mal die Zeit und mach es mit "+1"! |
||
![]() |
M0rgenstern |
![]() Antworten mit Zitat ![]() |
---|---|---|
Also. Ich habe jetzt extra ein grelles Gelb für den Hintergrund genommen und folgende Beobachtung gemacht:
Die Streifen bleiben schwarz. Die Skalierung ist auch zu 100% immer 100%, habs extra nochmal eingebaut vor dem Zeichnen der Tiles. Der Grund warum ich + 4 rechne ist folgender: Als ich es mit +1 getestet habe ist der Fehler einfach nicht aufgetreten. Hier ist einfach mal das ganze Paket, damit man sich selbst ein BIld von dem Fehler machen kann: https://www.blitzforum.de/upload/file.php?id=8344 Lg, M0rgenstern EDIT: Mit Flip1 ruckelt das ganze nur noch mehr. |
||
![]() |
XeresModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich kann keine Grafikfehler ausmachen.
Versuche mal die anderen Grafiktreiber durch. Code: [AUSKLAPPEN] SetGraphicsDriver(GLMax2DDriver())
SetGraphicsDriver(D3D7Max2DDriver()) SetGraphicsDriver(D3D9Max2DDriver()) |
||
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus THERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld) |
![]() |
Midimaster |
![]() Antworten mit Zitat ![]() |
---|---|---|
naja, aber das ist doch schon ein Ansatz. Wenn das Ganze mit +1 nicht passiert, dann liegt es an der 4! Sind die Tiles 32x32 groß? Könnte auch ein Rundungsfehler sein...
da ist ja diese Zeile: Code: [AUSKLAPPEN] DrawImage(tiTiles, iMapXIndex * iTilesize - fscrollX, iMapYIndex * iTilesize - fScrolly, iGameMap[iMapXIndex, iMapYIndex, 1])
und ich vermute fScrooX ist eine Float-Variable? Mach mal daraus: BlitzMax: [AUSKLAPPEN] DrawImage(tiTiles, iMapXIndex * iTilesize - Int(fscrollX), iMapYIndex * iTilesize - Int(fScrolly), iGameMap[iMapXIndex, iMapYIndex, 1]) Und du bist sicher, der Fehler tritt nur auf, wenn verschiedene Tiles im Spiel sind? Oder immer bei dem blauen? mach mal, dass alles aus dem blauen tile wäre... |
||
![]() |
M0rgenstern |
![]() Antworten mit Zitat ![]() |
---|---|---|
Also, den letzten Treiber kennt er erst gar nicht.
Mit dem ersten scheints flüssiger zu laufen und mit dem zweiten ändert sich im Prinzip nichts. Also, damit ich dich richtig verstehe: Auf deinem PC siehts nicht nach ruckeln aus und due kannst nichts schwarzes an den Übrergängen zwischen 2 unterschiedlichen TIlearten erkennen? Sind vielleicht Probleme zwischen BMax und Win7 bekannt? Lg, M0rgenstern EDIT: Die Tiles sind 32*32. Der Fehler wird dadurch das ganze in INt zu konvertieren noch ein wenig schlimmer. Der Fehler mit den schwarzen Abständen entsteht nur wenn verschiedene Tiles im Spiel sind. Wenn ich alles aus einer Tile mache, dann hab ich immernoch ein wenig das Gefühl, dass es manchmal kurz "ruckt" aber es gibt keine schwarzen Stellen mehr. Lg, M0rgenstern |
||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group