Pixelgenaue Tilemap Kollision mit Winkeln!?

Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Gehe zu Seite 1, 2  Weiter

Neue Antwort erstellen

M0rgenstern

Betreff: Pixelgenaue Tilemap Kollision mit Winkeln!?

BeitragSa, Apr 10, 2010 1:21
Antworten mit Zitat
Benutzer-Profile anzeigen
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)
fAngle = ATan2(fX - MouseX() - pscrollx, MouseY() + pscrolly - fY)
Local iNumberOfKeys:Int = KeyDown(Key_w) + KeyDown(key_a) + KeyDown(key_s) + KeyDown(Key_d)
Local fOldX:Float = fx
Local fOldy:Float = fy
Local fNewx:Float, fNewy:Float

'Geradeaus
If KeyDown(KEY_W) Then
fNewx = (fX - Sin(fAngle) * (fSpeed / iNumberOfKeys))
fNewy = (fY + Cos(fAngle) * (fSpeed / iNumberOfKeys))

If ((fNewx / iTilesize) <= iMapwidth - 1) And ((fNewx / iTilesize) >= 0) Then
If ((fNewy / iTilesize) <= iMapheight - 1) And ((fNewy / iTilesize) >= 0) Then
If (iGameMap[fNewx / iTilesize, fNewy / iTilesize, 2] = 0) Then

fX = (fX - Sin(fAngle) * (fSpeed / iNumberOfKeys))
fY = (fY + Cos(fAngle) * (fSpeed / iNumberOfKeys))

EndIf
EndIf
EndIf


EndIf

'Links
If KeyDown(KEY_A) Then
fNewx = (fX + Sin(fAngle + 90) * (fSpeed / iNumberOfKeys))
fNewy = (fY - Cos(fAngle + 90) * (fSpeed / iNumberOfKeys))

If ((fNewx / iTilesize) <= iMapwidth - 1) And ((fNewx / iTilesize) >= 0) Then
If ((fNewy / iTilesize) <= iMapheight - 1) And ((fNewy / iTilesize) >= 0) Then
If (iGameMap[fNewx / iTilesize, fNewy / iTilesize, 2] = 0) Then

fX = (fX + Sin(fAngle + 90) * (fSpeed / iNumberOfKeys))
fY = (fY - Cos(fAngle + 90) * (fSpeed / iNumberOfKeys))

EndIf
EndIf
EndIf

EndIf

'Rechts
If KeyDown(KEY_D) Then
fNewx = (fX - Sin(fAngle + 90) * (fSpeed / iNumberOfKeys))
fNewy = (fY + Cos(fAngle + 90) * (fSpeed / iNumberOfKeys))

If ((fNewx / iTilesize) <= iMapwidth - 1) And ((fNewx / iTilesize) >= 0) Then
If ((fNewy / iTilesize) <= iMapheight - 1) And ((fNewy / iTilesize) >= 0) Then
If (iGameMap[fNewx / iTilesize, fNewy / iTilesize, 2] = 0) Then

fX = (fX - Sin(fAngle + 90) * (fSpeed / iNumberOfKeys))
fY = (fY + Cos(fAngle + 90) * (fSpeed / iNumberOfKeys))

EndIf
EndIf
EndIf

EndIf

'Nach hinten
If KeyDown(KEY_S) Then
fNewx = (fX + Sin(fAngle) * (fSpeed / iNumberOfKeys))
fNewy = (fY - Cos(fAngle) * (fSpeed / iNumberOfKeys))

If ((fNewx / iTilesize) <= iMapwidth - 1) And ((fNewx / iTilesize) >= 0) Then
If ((fNewy / iTilesize) <= iMapheight - 1) And ((fNewy / iTilesize) >= 0) Then
If (iGameMap[fNewx / iTilesize, fNewy / iTilesize, 2] = 0) Then

fX = (fX + Sin(fAngle) * (fSpeed / iNumberOfKeys))
fY = (fY - Cos(fAngle) * (fSpeed / iNumberOfKeys))

EndIf
EndIf
EndIf

EndIf

If (fX < 0) Then fX = 0
If ((fX / iTilesize) > iMapwidth - 1) Then fX = ((iMapwidth - 1) * iTilesize)
If (fY < 0) Then fY = 0
If ((fY / iTilesize) > iMapheight - 1) Then fY = ((iMapheight - 1) * iTilesize)



End Method


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

BeitragSa, Apr 10, 2010 1:35
Antworten mit Zitat
Benutzer-Profile anzeigen
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/

Xeres

Moderator

BeitragSa, Apr 10, 2010 1:38
Antworten mit Zitat
Benutzer-Profile anzeigen
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
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)

M0rgenstern

BeitragSa, Apr 10, 2010 2:19
Antworten mit Zitat
Benutzer-Profile anzeigen
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)
For Local iMapYIndex:Int = 0 To (iMapheight - 1)

If ((iMapXIndex * iTilesize - fscrollX) >= 0 - iTilesize / 2) And ((iMapXIndex * iTilesize - fscrollX) <= fGFXWidth + iTilesize / 2) Then
If ((iMapYIndex * iTilesize - fScrolly) >= 0 - iTilesize / 2) And ((iMapYIndex * iTilesize - fScrolly) <= fGFXHeight + iTilesize / 2) Then

DrawImage(tiTiles, iMapXIndex * iTilesize - fscrollX, iMapYIndex * iTilesize - fScrolly, iGameMap[iMapXIndex, iMapYIndex, 1])

EndIf
EndIf

Next
Next


Lg, M0rgenstern

Midimaster

BeitragSa, Apr 10, 2010 9:33
Antworten mit Zitat
Benutzer-Profile anzeigen
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)
fAngle = ATan2(fX - MouseX() - pscrollx, MouseY() + pscrolly - fY)
Local iNumberOfKeys:Float = KeyDown(Key_w) + KeyDown(key_a) + KeyDown(key_s) + KeyDown(Key_d)
Local fNewx:Float, fNewy:Float

'Geradeaus
If KeyDown(KEY_W) Then
fNewx = - Sin(fAngle)
fNewy = + Cos(fAngle)
EndIf
'Links
If KeyDown(KEY_A) Then
fNewx = + Sin(fAngle + 90)
fNewy = - Cos(fAngle + 90))
EndIf
'Rechts
If KeyDown(KEY_D) Then
fNewx = - Sin(fAngle + 90)
fNewy = + Cos(fAngle + 90)
EndIf
'Nach hinten
If KeyDown(KEY_S) Then
fNewx = + Sin(fAngle)
fNewy = - Cos(fAngle)
EndIf

locSpeed# = fSpeed/iNumberOfKeys
fNewX = Fx+FNewX*locSpeed
fNewY = FY+FNewY*locSpeed

locMapX% = fNewX/iTilesize
locMapY% = fNewY/iTilesize

If (locMapX < iMapwidth ) And (locMapX >-1) Then
If (locMapY < iMapheight) And (locMapY > -1) Then
If (iGameMap[locMapX, locMapY, 2] = 0) Then
fX = fNewx
fY = fNewx
EndIf
EndIf
EndIf
End Method




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
Das kann doch total weg! wie soll es zu diesen Zuständen kommen?
If (fX < 0) Then fX = 0
If ((fX / iTilesize) > iMapwidth - 1) Then fX = ((iMapwidth - 1) * iTilesize)
If (fY < 0) Then fY = 0
If ((fY / iTilesize) > iMapheight - 1) Then fY = ((iMapheight - 1) * iTilesize)
End 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:
If ((fNewx / iTilesize) <= iMapwidth - 1) And ((fNewx / iTilesize) >= 0) Then
If ((fNewy / iTilesize) <= iMapheight - 1) And ((fNewy / iTilesize) >= 0) Then
If (iGameMap[fNewx / iTilesize, fNewy / iTilesize, 2] = 0) Then

fX = (fX - Sin(fAngle) * (fSpeed / iNumberOfKeys))
fY = (fY + Cos(fAngle) * (fSpeed / iNumberOfKeys))

EndIf
EndIf
EndIf
End rem



Dadurch dass sich dies jetzt immer durch...
BlitzMax: [AUSKLAPPEN]
				fX = fNewx
fY = 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
locMapY% = fNewY/iTilesize

If (locMapX < iMapwidth ) And (locMapX >-1) Then
If (locMapY < iMapheight) And (locMapY > -1) Then
If (iGameMap[locMapX, locMapY, 2] = 0) Then



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

BeitragSa, Apr 10, 2010 10:01
Antworten mit Zitat
Benutzer-Profile anzeigen
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 Wink
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

BeitragSa, Apr 10, 2010 10:46
Antworten mit Zitat
Benutzer-Profile anzeigen
@ 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)
fAngle = ATan2(fX - MouseX() - pscrollx, MouseY() + pscrolly - fY)
Local iNumberOfKeys:Int = KeyDown(Key_w) + KeyDown(key_a) + KeyDown(key_s) + KeyDown(Key_d)
Local fOldX:Float = fx
Local fOldy:Float = fy
Local fNewx:Float = fx, fNewy:Float = fy
'
'
If KeyDown(KEY_W) Then
fNewx = (fX - Sin(fAngle) * (fSpeed / iNumberOfKeys))
fNewy = (fY + Cos(fAngle) * (fSpeed / iNumberOfKeys))
EndIf

'Links
If KeyDown(KEY_A) Then
fNewx = (fX + Sin(fAngle + 90) * (fSpeed / iNumberOfKeys))
fNewy = (fY - Cos(fAngle + 90) * (fSpeed / iNumberOfKeys))
EndIf

'Rechts
If KeyDown(KEY_D) Then
fNewx = (fX - Sin(fAngle + 90) * (fSpeed / iNumberOfKeys))
fNewy = (fY + Cos(fAngle + 90) * (fSpeed / iNumberOfKeys))
EndIf

'Nach hinten
If KeyDown(KEY_S) Then
fNewx = (fX + Sin(fAngle) * (fSpeed / iNumberOfKeys))
fNewy = (fY - Cos(fAngle) * (fSpeed / iNumberOfKeys))
EndIf

Local MapX:Int = fnewx / itilesize
Local mapy:Int = fnewy / itilesize

If (MapX < iMapwidth - 1) And (MapX > - 1) Then
If (mapy < iMapheight - 1) And (mapy > - 1) Then
If (iGameMap[MapX, mapy, 2] = 0) Then

fX = fNewx
fY = fNewy

EndIf
EndIf
EndIf


If (fX < 0) Then fX = 0
If ((fX / iTilesize) > iMapwidth - 1) Then fX = ((iMapwidth - 1) * iTilesize)
If (fY < 0) Then fY = 0
If ((fY / iTilesize) > iMapheight - 1) Then fY = ((iMapheight - 1) * iTilesize)

End Method


Die letzten vier Zeilen musste ich drin lassen, da er sonst bei den "Nullpunkten" der Karte schon außerhalb der Karte war.
Lg, m0rgenstern

Xeres

Moderator

BeitragSa, Apr 10, 2010 15:31
Antworten mit Zitat
Benutzer-Profile anzeigen
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
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)

Midimaster

BeitragSa, Apr 10, 2010 18:50
Antworten mit Zitat
Benutzer-Profile anzeigen
@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)
fAngle = ATan2(fX - MouseX() - pscrollx, MouseY() + pscrolly - fY)
Local iNumberOfKeys:Float = KeyDown(Key_w) + KeyDown(key_a) + KeyDown(key_s) + KeyDown(Key_d)
Local fNewx:Float, fNewy:Float

locSpeed# = fSpeed/iNumberOfKeys

'Geradeaus
If KeyDown(KEY_W) Then
Berechnen - Sin(fAngle), Cos(fAngle), locSpeed
EndIf
'Links
If KeyDown(KEY_A) Then
Berechnen Sin(fAngle + 90), - Cos(fAngle + 90), locSpeed
EndIf
'Rechts
If KeyDown(KEY_D) Then
Berechnen - Sin(fAngle + 90, Cos(fAngle + 90), locSpeed
EndIf
'Nach hinten
If KeyDown(KEY_S) Then
Berechnen Sin(fAngle), - Cos(fAngle), locSpeed
EndIf
End Method


Method Berechnen(fNewX#, fNewY#, locSpeed#)
fNewX = Fx+FNewX*locSpeed
fNewY = FY+FNewY*locSpeed

locMapX% = fNewX/iTilesize
locMapY% = fNewY/iTilesize

If (locMapX < iMapwidth ) And (locMapX >-1) Then
If (locMapY < iMapheight) And (locMapY > -1) Then
If (iGameMap[locMapX, locMapY, 2] = 0) Then
fX = fNewx
fY = fNewx
EndIf
EndIf
EndIf
End Method


Der Code würde dadurch nochmals kürzer...

M0rgenstern

BeitragSa, Apr 10, 2010 19:38
Antworten mit Zitat
Benutzer-Profile anzeigen
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
Local fScrolly:Float = Player.fY - GraphicsHeight() / 2

Local iTilescrollMinx:Int = fscrollx / itilesize
Local iTilescrollMiny:Int = fscrolly / itilesize
Local iTilescrollMaxX:Int = ((Player.fX + GraphicsWidth() / 2) / itilesize) + 1
Local iTilescrollMaxY:Int = ((Player.fY + GraphicsHeight() / 2) / itilesize) + 1

If iTilescrollMinx < 0 Then iTilescrollMinx = 0
If iTilescrollMiny < 0 Then iTilescrollMiny = 0
If iTilescrollMaxX > (imapwidth - 1) Then iTilescrollMaxX = (imapwidth - 1)
If iTilescrollMaxY > (imapheight - 1) Then iTilescrollMaxY = (imapheight - 1)

For Local iMapXIndex:Int = iTilescrollMinx To (iTilescrollMaxX)
For Local iMapYIndex:Int = iTilescrollMiny To (iTilescrollMaxY)

DrawImage(tiTiles, iMapXIndex * iTilesize - fscrollX, iMapYIndex * iTilesize - fScrolly, iGameMap[iMapXIndex, iMapYIndex, 1])

Next
Next


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

BeitragSo, Apr 11, 2010 1:32
Antworten mit Zitat
Benutzer-Profile anzeigen
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()
For Local iMapXIndex:Int = iTilescrollMinx To (iTilescrollMaxX)
....

Next
MessZeit=MilliSecs()-MessZeit
Print "Messergebnis: " + MessZeit


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
If (iGameMap[(fNewx +iTilesize)/ iTilesize, fNewy / iTilesize, 2] = 0) Then
If (iGameMap[fNewx / iTilesize, (fNewy+iTilesize) / iTilesize, 2] = 0) Then
If (iGameMap[(fNewx+iTilesize) / iTilesize, (fNewy+iTilesize) / iTilesize, 2] = 0) Then
....

M0rgenstern

BeitragSo, Apr 11, 2010 8:56
Antworten mit Zitat
Benutzer-Profile anzeigen
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
Local iTilescrollMiny:Int = (fscrolly / itilesize) - 1
Local iTilescrollMaxX:Int = ((Player.fX + GraphicsWidth() / 2) / itilesize) + 1
Local iTilescrollMaxY:Int = ((Player.fY + GraphicsHeight() / 2) / 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

BeitragSo, Apr 11, 2010 9:18
Antworten mit Zitat
Benutzer-Profile anzeigen
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
MoveZeit = MilliSecs() +1000
PlayerFy =PlayerFy +1
EndIf


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

BeitragSo, Apr 11, 2010 12:28
Antworten mit Zitat
Benutzer-Profile anzeigen
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.

user posted image

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()
WaitTimer(FTimer)
Cls

Local fscrollX:Float = Player.fX - GraphicsWidth() / 2
Local fScrolly:Float = Player.fY - GraphicsHeight() / 2

Local iTilescrollMinx:Int = (fscrollx / itilesize) - 1
Local iTilescrollMiny:Int = (fscrolly / itilesize) - 1
Local iTilescrollMaxX:Int = ((Player.fX + GraphicsWidth() / 2) / itilesize) + 1
Local iTilescrollMaxY:Int = ((Player.fY + GraphicsHeight() / 2) / itilesize) + 1

If iTilescrollMinx < 0 Then iTilescrollMinx = 0
If iTilescrollMiny < 0 Then iTilescrollMiny = 0
If iTilescrollMaxX > (imapwidth - 1) Then iTilescrollMaxX = (imapwidth - 1)
If iTilescrollMaxY > (imapheight - 1) Then iTilescrollMaxY = (imapheight - 1)

If MoveZeit < MilliSecs() Then
MoveZeit = MilliSecs() + 1000
Player.fy = Player.Fy + 4
EndIf

Local MessZeit:Float = MilliSecs()



For Local iMapXIndex:Int = iTilescrollMinx To (iTilescrollMaxX)
For Local iMapYIndex:Int = iTilescrollMiny To (iTilescrollMaxY)

DrawImage(tiTiles, iMapXIndex * iTilesize - fscrollX, iMapYIndex * iTilesize - fScrolly, iGameMap[iMapXIndex, iMapYIndex, 1])

Next
Next

MessZeit = MilliSecs() - MessZeit


For Local obj:TObject = EachIn TObject.TObjectList
If ((Obj.ix * iTilesize - fscrollX) >= 0 - iTilesize / 2) And ((Obj.ix * iTilesize - fscrollX) <= fGFXWidth + iTilesize / 2) Then
If ((Obj.iy * iTilesize - fScrolly) >= 0 - iTilesize / 2) And ((Obj.iy * iTilesize - fScrolly) <= fGFXHeight + iTilesize / 2) Then
obj.Draw(fscrollX, fScrolly)

EndIf
EndIf
Next

Player.Move(fscrollX, fScrolly)
Player.Draw(fscrollX, fScrolly)
DrawImage(tiMouse, MouseX(), MouseY())
DrawText("Playerpos (real): " + Player.fx + " / " + Player.fY, 30, 30)
DrawText("Playerpos (map): " + Player.fx / iTilesize + " / " + Player.fY / iTilesize, 30, 50)
DrawText("Scroll: " + fscrollX + " / " + fScrolly, 30, 70)
'DrawText("Messergebnis: " + MessZeit, 30, 90)
Local FlaecheX:Int = iTilescrollMaxX - iTilescrollMinx
Local FlaecheY:Int = iTilescrollMaxY - iTilescrollMiny
DrawText("Flaeche: X= " + FlaecheX + " Y=" + FlaecheY + " ", 30, 90)

Flip 0
Wend


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

BeitragSo, Apr 11, 2010 13:00
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragSo, Apr 11, 2010 13:09
Antworten mit Zitat
Benutzer-Profile anzeigen
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
SetColor 255,255,0
DrawRect 0,0,GraphicsWidth(),GraphicsHeight()
SetColor 255,255,255
...



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

BeitragSo, Apr 11, 2010 15:39
Antworten mit Zitat
Benutzer-Profile anzeigen
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.

Xeres

Moderator

BeitragSo, Apr 11, 2010 16:01
Antworten mit Zitat
Benutzer-Profile anzeigen
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
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)

Midimaster

BeitragSo, Apr 11, 2010 16:08
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragSo, Apr 11, 2010 16:12
Antworten mit Zitat
Benutzer-Profile anzeigen
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

Gehe zu Seite 1, 2  Weiter

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group