Tilemap - Bewegung

Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Neue Antwort erstellen

 

CO2

ehemals "SirMO"

Betreff: Tilemap - Bewegung

BeitragFr, Nov 29, 2013 15:08
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo,
Ich habe derzeit ein kleines Problemchen: Ich male eine Tilemap und möchte mich als Spieler darauf bewegen. Nun ist es ein 2-Dimensionaler Side-Scroller, also man bewegt sich nach rechts und links um vorwärts bzw. rückwärts zu laufen. Zudem gibt es die Möglichkeit, an gewissen Stellen auf- bzw. abwärts zu laufen (wenn man sich vor Kollisions-Tiles befindet). Außerdem "springt" man automatisch ein Tile nach oben, wenn ein Hindernis im Weg ist, was ein Tile hoch ist.
Ich habe es jetzt soweit umgesetzt, dass das laufen nach rechts/links soweit funktioniert, komme aber mit hoch/runter total durcheinander. Hier ein Bild zur Veranschaulichung:
user posted image

Läuft man hier mit [A] bzw. [D] nach links bzw. rechts funktioniert alles hundertprozentig. Diese Abstufungen in den Erde-Tiles werden von der Ameise "überspungen", wenn man sie herunterläuft "fällt" sie ebenfalls.
Rechts ist die Kontur eines Baumes (mit einem zugegeben hässlichen Tile Wink). Daran wollte ich das hoch-/runterklettern testen. Allerdings "fällt" die Figur beim hochklettern und absteigen hinter die Kontur...

Hier mal die Routinen:

Links/Rechts BlitzMax: [AUSKLAPPEN]
Local MoveMax:Float = 0.15

' Nach Rechts
If((KeyDown(Set.MoveRight) Or KeyDown(Set.MoveRightAlt)) And Self.PosX < Map.SizeX) ' Will der Spieler nach rechts?
If(CheckMapForTransculentTiles(Map, (Self.PosX + 1), Self.PosY)) ' Ist rechts überhaupt noch Platz?
Self.PosX = Self.PosX + MoveMax
Self.MomFrame = 0
Self.Rotation = 0
Else ' Wenn nicht,...
If(Self.PosY > 1 And Self.Rotation <> 90 And Self.Rotation <> -90) ' Ist darüber noch platz?
If(CheckMapForTransculentTiles(Map, (Self.PosX + 1), (Self.PosY - 1))) ' Prüfe ob darüber Platz ist (Treppe)
Self.PosX = Self.PosX + MoveMax
Self.PosY = Self.PosY - 1
Self.MomFrame = 0
Self.Rotation = 0
EndIf
EndIf
EndIf
EndIf
' Nach Links
If((KeyDown(Set.MoveLeft) Or KeyDown(Set.MoveLeftAlt)) And Self.PosX > 0)
If(CheckMapForTransculentTiles(Map, (Self.PosX - 1), Self.PosY)) ' Ist links überhaupt noch Platz?
Self.PosX = Self.PosX - MoveMax
Self.MomFrame = 1
Self.Rotation = 0
Else
If(Self.PosY > 1) ' Ist darüber noch platz?
If(CheckMapForTransculentTiles(Map, (Self.PosX - 1), (Self.PosY - 1))) ' Prüfe ob darüber Platz ist (Treppe)
Self.PosX = Self.PosX - MoveMax
Self.PosY = Self.PosY - 1
Self.MomFrame = 0
Self.Rotation = 0
EndIf
EndIf
EndIf
EndIf


- PosX, PosY, MomFrame und Rotation sind Variablen der Klasse (Dies ist eine Methode der Klasse)
- "Set." ist eine Settingsklasse, in denen die Tastenbelegung gespeichert wurde
- CheckMapForTransculentTiles() macht Folgendes BlitzMax: [AUSKLAPPEN]
Function CheckMapForTransculentTiles:Byte(Map:TTileMap, PosX:Int, PosY:Int)
If(Map <> Null)
If(PosX < Map.SizeX And PosX >= 0 And PosY < Map.SizeY And PosY > 0)
If(Map.TileData[PosX, PosY] = TILE_AIR Or Map.TileData[PosX, PosY] = TILE_GRASS Or Map.TileData[PosX, PosY] = TILE_NOLEAF45 Or Map.TileData[PosX, PosY] = TILE_NOLEAF135 Or Map.TileData[PosX, PosY] = TILE_NOLEAF225 Or Map.TileData[PosX, PosY] = TILE_NOLEAF315)
Return True
EndIf
EndIf
EndIf
Return False
End Function


Nun folgt mein bisheriger Code zum hoch-/runterklettern BlitzMax: [AUSKLAPPEN]
' Nach Oben
If(KeyDown(Set.MoveUp) Or KeyDown(Set.MoveUpAlt))
If(CheckMapForTransculentTiles(Map, (Self.PosX + 1), Self.PosY) = False) ' Rechts vom Spieler ist ein Aufstieg
If(CheckMapForTransculentTiles(Map, Self.PosX, (Self.PosY - 1))) ' Ist darüber überhaupt noch Platz?
Self.PosY = Self.PosY - MoveMax
Self.MomFrame = 0
Self.Rotation = -90
Else ' Wenn nicht,...
If(Self.PosX > 1) ' Ist daneben noch platz?
If(CheckMapForTransculentTiles(Map, (Self.PosX - 1), (Self.PosY - 1))) ' Prüfe ob links darüber Platz ist (Treppe)
Self.PosY = Self.PosY - MoveMax
Self.PosX = Self.PosX - 1
Self.MomFrame = 0
Self.Rotation = -90
EndIf
EndIf
EndIf
EndIf
EndIf
' Nach Unten
If(KeyDown(Set.MoveDown) Or KeyDown(Set.MoveDownAlt))
If(Self.PosY < (Map.SizeY - 1))
If(Self.PosX > 0 And Self.PosX < Map.SizeX)
If(CheckMapForTransculentTiles(Map, (Self.PosX + 1), Self.PosY) = False) ' Ist Rechts daneben kein Durchlässiges Tile?
Self.MomFrame = 1
Self.Rotation = -90
Self.PosY = Self.PosY + MoveMax
ElseIf(CheckMapForTransculentTiles(Map, (Self.PosX - 1), Self.PosY) = False) ' Ist Links daneben kein Durchlässiges Tile?
Self.MomFrame = 0
Self.Rotation = 90
Self.PosY = Self.PosY + MoveMax
ElseIf(CheckMapForTransculentTiles(Map, (Self.PosX + 1), (Self.PosY - 1)) And CheckMapForTransculentTiles(Map, (Self.PosX + 2), (Self.PosY - 1)) = False)
Self.MomFrame = 1
Self.Rotation = -90
Self.PosY = Self.PosY + MoveMax
Self.PosX = Self.PosX + 1
ElseIf(CheckMapForTransculentTiles(Map, (Self.PosX - 1), (Self.PosY - 1)) And CheckMapForTransculentTiles(Map, (Self.PosX - 2), (Self.PosY - 1)) = False)
Self.MomFrame = 0
Self.Rotation = 90
Self.PosY = Self.PosY + MoveMax
Self.PosX = Self.PosX + 1
EndIf
Else
If(Self.PosX = 0)
Self.MomFrame = 0
Self.Rotation = 90
Self.PosY = Self.PosY + MoveMax
ElseIf(Self.PosX = (Map.SizeX - 1))
Self.MomFrame = 1
Self.Rotation = -90
Self.PosY = Self.PosY + MoveMax
EndIf
EndIf
EndIf
EndIf


Wobei "runter" noch eine alte Version ist, ich wollte aber zuerst das "hochklettern" umsetzen.

Was mache ich bei hoch-/runtersteigen falsch, dass ich in Bereiche gelange, wo man eigentlich nicht hinsoll? Die Figur bewegt sich bei "Tilesteigen" auch ziemlich seltsam, also ändert ihren Winkel immer zwischen 0° und 90°.
mfG, CO²

Sprachen: BlitzMax, C, C++, C#, Java
Hardware: Windows 7 Ultimate 64-Bit, AMX FX-6350 (6x3,9 GHz), 32 GB RAM, Nvidia GeForce GTX 750 Ti
 

PhillipK

BeitragFr, Nov 29, 2013 15:59
Antworten mit Zitat
Benutzer-Profile anzeigen
Wow, das ist ein bissl heftig zu lesen Surprised

Also zuerst einmal eine frage:
In wie fern funktioniert das klettern nicht ?
Du schreibst, das deine Figur "dahinter" fällt - klettert sie denn?

Weiter unten schreibst du, dass sich deine figur beim tile-klettern immer rotiert.
Klingt also, als würde sie zwar am "baum" hochklettern, aber danach runterfallen und zwischenzeitlich zucken.

Dann erkläre mal, was genau das hier macht:
BlitzMax: [AUSKLAPPEN]
			If(Map.TileData[PosX, PosY] = TILE_AIR Or Map.TileData[PosX, PosY] = TILE_GRASS Or Map.TileData[PosX, PosY] = TILE_NOLEAF45 Or Map.TileData[PosX, PosY] = TILE_NOLEAF135 Or Map.TileData[PosX, PosY] = TILE_NOLEAF225 Or Map.TileData[PosX, PosY] = TILE_NOLEAF315)

Klingt als wären das collision flags, welche "begehbare tiles" kennzeichnen. Alles andere ist also statisch.
Stimmen die gesetzten flags soweit für dein Holz? Wenn deine ameise klettert, tippe ich mal auf ja ^^
Aber das nur so am rande.

Das hier verwirrt mich mehr:
BlitzMax: [AUSKLAPPEN]
		If(KeyDown(Set.MoveUp) Or KeyDown(Set.MoveUpAlt))
If(CheckMapForTransculentTiles(Map, (Self.PosX + 1), Self.PosY) = False) ' Rechts vom Spieler ist ein Aufstieg
If(CheckMapForTransculentTiles(Map, Self.PosX, (Self.PosY - 1))) ' Ist darüber überhaupt noch Platz?
Self.PosY = Self.PosY - MoveMax
Self.MomFrame = 0
Self.Rotation = -90
Else ' Wenn nicht,...
If(Self.PosX > 1) ' Ist daneben noch platz?
If(CheckMapForTransculentTiles(Map, (Self.PosX - 1), (Self.PosY - 1))) ' Prüfe ob links darüber Platz ist (Treppe)
Self.PosY = Self.PosY - MoveMax
Self.PosX = Self.PosX - 1
Self.MomFrame = 0
Self.Rotation = -90
EndIf
EndIf
EndIf
EndIf
EndIf


Du fragst ab, ob RECHTS vom spieler ein aufstieg ist (posX + 1 sowie kommentare)
Allerdings ist darin verschachtelt die links-abfrage:
BlitzMax: [AUSKLAPPEN]
					If(Self.PosX > 1) ' Ist daneben noch platz?
If(CheckMapForTransculentTiles(Map, (Self.PosX - 1), (Self.PosY - 1))) ' Prüfe ob links darüber Platz ist (Treppe)


Mein tipp: Packe das ganze in eine funktion mit einer DIR variable für x.

Das hat erstmal 3 Schöne vorteile: 1) Du kannst den selben code für beide richtungen verwenden
2) Du kannst das schöner lösen als mit einem riesen verschachtelten if baum.
3) Du kannst mehr printen Smile

Mal dazu ein pseudo code:
BlitzMax: [AUSKLAPPEN]


Method CheckClimb(dir:Int)
If Self.PosX + dir <= 0 Or Self.PosX + dir >= MAX_X Then Return 'im bezug auf "If(Self.PosX > 1) ' Ist daneben noch platz?"
If CheckMapForTransculentTiles(Map, PosX + dir, PosY - 1) = True Then
Print("[CheckClimb] Direction: "+dir+" - Neben uns ist luft!")
'die geprüfte richtung hat !kein! kletterbares tile
Return 'early out.
EndIf


If CheckMapForTransculentTiles(Map, PosX, PosY - 1) = False Then
Print("[CheckClimb] Direction: "+dir+" - Über uns ist kein platz!")
'Über uns ist kein platz
Return 'early out
EndIf


Print("[CheckClimb] Direction: "+dir+" - Alles passt. Verschiebe Y und setze rotation / frame!")
Self.PosY = Self.PosY - MoveMax
Self.MomFrame = 0
Self.Rotation = -90

End Method


Deinen IF-case kannst du dann wie folgt vereinfachen:
BlitzMax: [AUSKLAPPEN]
If(KeyDown(Set.MoveUp) Or KeyDown(Set.MoveUpAlt))
CheckClimb(-1)
CheckClimb(1)
....


Vielleicht siehst du dann beim printen schon, was da schiefläuft.
So erkennen kann ich nun leider nix, aber vermutungen habe ich trotzdem:

Dein bezugspunkt in den tiles ist oben-links.
Du fragst mit der floatzahl (PosX, PosY) die tileposition ab, was eventuell nach dem ersten gekletterten stück auf ein anderes tile darüber zeigt. ausgehend speziell von den treppen am anfang deines "Baumes"
Die ersten 0.15 schritte sind nach oben getan, wodurch die luft 1 schritt über und 1 schritt rechts von der armeise abgefragt wird. Da greift CheckTransluenceTile() nichtmehr.
Um sowas festzustellen, könntest du zb bei CheckMapForTransluenceTile() ein DrawRect() mit AdditiveBlend zeichnen - undzwar auf die gebrochenen int-koordinaten:
Code: [AUSKLAPPEN]
DrawRect( PosX * TILE_WIDTH, PosY * TILE_HEIGHT, TILE_WIDHT, TILE_HEIGHT)

(innerhalb der CheckTrans dingens Funktion, die PosX:int und PosY:Int parameter verwendet, versteht sich)

wobei du TILE_WIDHT und TILE_HEIGHT anpassen musst und evtl eine kamera verschiebung aufrechnen musst ^^ ABER: Daran kannst du immer sehen, welches tile gecheckt wird. Im code verwendest du noch eine float position, zum abfragen eine gerundete intposition.


Und zu guter letzt noch ein bug, der wahrswcheinlich nie eintreten wird:
Deine ameise prüft links / rechts nach freier fläche beim bewegen. Ist da was im weg, checkt sie das tile darüber zum springen. Aber du fragst nie, ob direkt über ihr platz ist Wink Dh sie würde rein logisch durch ein deckentile gehen können, wenn zb links vom deckentile wieder frei ist Very Happy

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group