Zwischen Maps wechseln - Ansätze?

Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Neue Antwort erstellen

M0rgenstern

Betreff: Zwischen Maps wechseln - Ansätze?

BeitragDo, Mai 03, 2012 8:35
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo Leute,
Ich steh mal wieder vor einem verdammt blöden Problem.
Undzwar: Bei meinem Spiel besteht ein ein Level aus mehreren Karten. Bei diesen Karten ist es so: Man soll von einer Karten durch ein Portal o.ä. zu einer anderen Karten kommen. Jede Karten ist eine normale, kleine Tilemap.
Mein Problem ist jetzt: Ich habe zwar einen Ansatz, wie sich das umsetzen lassen würde, aber ich glaube der Ansatz ist nicht gut.
Jetzt wollte ich bei euch mal nachfragen, was ihr von dem Ansatz haltet und wie ihr es machen würdet.

Hier sein erstmal die Klasse für ein Level und die Übergänge zwischen den Karten:

BlitzMax: [AUSKLAPPEN]
Type TWorldPart
Field _tlMaps:TList
Field _tlPassages:TList

'Die Karten, die zum Level gehören:
Method Maps:TList()
Return _tlMaps
End Method

'Setzt die Liste:
Method SetMaps(ptlMaps:TList)
_tlMaps = ptlMaps
End Method

'Die Übergänge im Level:
Method Passages:TList()
Return _tlPassages
End Method

'Gibt den Übergang mit der entsprechenden Nummer zurück:
Method PassageWithNumber:TPassage(piNumber:Int)
For Local pass:TPassage = EachIn Passages()
If(pass.Number() = piNumber) Then Return pass
Next
Return Null
End Method

'Setzt die Liste mit den Übergängen:
Method SetPassages(ptlPassages:TList)
_tlPassages = ptlPassages
End Method

'Überschreibt den Übergang mit der Nummer piNumber mit dem Übergang ptpPassage
Method SetPassageWithNumber(ptpPassage:TPassage, piNumber:Int)
For Local pass:TPassage = EachIn Passages()
If(pass.Number() = piNumber) Then pass = ptpPassage.Copy()
Next
End Method

'Konstruktor:
Function Create:TWorldPart()
Local worldPart:TWorldPart = New TWorldPart

worldPart.SetMaps(New TList)
worldPart.SetPassages(New TList)

Return worldPart
End Function

'Diese Methode wird dafür sorgen, dass der Spieler zum anderen Level übergeht.
Method ChangeLevel(ptpPassage:TPassage)

End Method
End Type

Type TPassage
Field _iNumber:Int
Field _ttmDestinationMap:TTileMap
Field _v2dDestinationMapPosition:TVector2D
Field _v2dMapPosition:TVector2D
Field _v2dRealPosition:TVector2D
Field _tgiImage:TGameImage
Field _sCurrentWorldName:String
Field _twpWorldPart:TWorldPart

'Die Nummer des Übergangs
Method Number:Int()
Return _iNumber
End Method

'Ändert die Übergangsnummer
Method __SetNumber(piNumber:Int)
_iNumber = piNumber
End Method

'Die Karte zu der der Übergang führt.
Method DestinationMap:TTileMap()
Return _ttmDestinationMap
End Method

'Setzt die Zielkarte auf pttmDestinationMap
Method __SetDestinationMap(pttmDestinationMap:TTileMap)
_ttmDestinationMap = pttmDestinationMap
End Method

'Der Spieler startet auf der anderen Karte mit dieser Position.
Method DestinationMapPosition:TVector2D()
Return _v2dDestinationMapPosition
End Method

'Ändert die Position wo der Spieler auf der anderen Karte startet.
Method SetDestinationMapPosition(pv2dDestinationMapPosition:TVector2D)
_v2dDestinationMapPosition = TVector2D.CreateFromVector(pv2dDestinationMapPosition)
End Method

'X-Position des Startpunktes auf der Zielkarte
Method DestinationX:Int()
Return DestinationMapPosition().X()
End Method

'Setzt die X-Position des Startpunktes auf der Zielkarte
Method SetDestinationX(piDestinationX:Int)
_v2dDestinationMapPosition.SetX(piDestinationX)
End Method

'Y-Position des Startpunktes auf der Zielkarte
Method DestinationY:Int()
Return DestinationMapPosition().Y()
End Method

'Setzt die Y-Position des Startpunktes auf der Zielkarte
Method SetDestinationY(piDestinationY:Int)
_v2dDestinationMapPosition.SetY(piDestinationY)
End Method

'Die Position des Übergangs auf der Karte.
Method MapPosition:TVector2D()
Return _v2dMapPosition
End Method

'Setzt die Position des Übergangs.
Method SetMapPosition(pv2dMapPosition:TVector2D)
_v2dMapPosition = TVector2D.CreateFromVector(pv2dMapPosition)
End Method

'Die Position des Übergangs, umgerechnet.
Method RealPosition:TVector2D()
Return _v2dRealPosition
End Method

'Setzt die umgerechnete Position des Übergangs.
Method SetRealPosition(pv2dRealPosition:TVector2D)
_v2dRealPosition = TVector2D.CreateFromVector(pv2dRealPosition)
End Method

'Das Bild des Übergangs.
Method Image:TGameImage()
Return _tgiImage
End Method

'Setzt das Bild des Übergangs.
Method SetImage(ptgiImage:TGameImage)
_tgiImage = ptgiImage
End Method

'Der Name der Welt zu dem der Übergang gehört.
Method CurrentWorldName:String()
Return _sCurrentWorldName
End Method

'Übergibt dem Übergang dn aktuellen Namen der Welt.
Method SetCurrentWorldName(psCurrentWorldName:String)
_sCurrentWorldName = psCurrentWorldName
End Method

'Der Level zu dem der Übergang gehört.
Method WorldPart:TWorldPart()
Return _twpWorldPart
End Method

'Übergibt dem Übergang den Level zu dem er gehört.
Method __SetWorldPart(ptwpWorldPart:TWorldPart)
_twpWorldPart = ptwpWorldPart
End Method

'Konstruktor für einen Übergang.
Function Create:TPassage(piNumber:Int, pttmDestinationMap:TTileMap, piDestinationX:Int, piDestinationY:Int, pv2dMapPosition:TVector2D, pv2dRealPosition:TVector2D, psCurrentWorldName:String, ptwpWorldPart:TWorldPart)
Local pass:TPassage = New TPassage

pass.__SetNumber(piNumber)
pass.__SetDestinationMap(pttmDestinationMap)
pass.SetDestinationMapPosition(TVector2D.Create(piDestinationX, piDestinationY))
pass.SetMapPosition(pv2dMapPosition)
pass.SetRealPosition(pv2dRealPosition)

'Bild laden, das zur aktuellen Welt gehört.
Local sPath:String = "Data/gfx/levels/objects/WORLD/passage.png"
sPath = sPath.Replace("WORLD", psCurrentWorldName)
pass.SetCurrentWorldName(psCurrentWorldName)

pass.SetImage(TGameImage.LoadAnimated(sPath, 5, 120))

pass.__SetWorldPart(ptwpWorldPart)

Return pass
End Function

'Kopiert einen Übergang.
Method Copy:TPassage()
Return TPassage.Create(Number(), DestinationMap(), DestinationX(), DestinationY(), MapPosition(), RealPosition(), CurrentWorldName(), WorldPart())
End Method

'Sorgt dafür, dass die Karte geändert wird, wenn der Spieler das Tile mit dem Übergang betritt.
Method StepsOn(pv2dPlayerMapPosition:TVector2D)
If(Int(pv2dPlayerMapPosition.X()) = Int(MapPosition().X())) Then
If(Int(pv2dPlayerMapPosition.Y()) = Int(MapPosition().Y())) Then
WorldPart().ChangeLevel(Self)
EndIf
EndIf
End Method

'Updated den Übergang.
Method Update()
Image().Update(, RealPosition())
End Method

'Malt den Übergang.
Method Draw()
Image().Draw()
End Method
End Type


So würde ich das momentan umsetzten. Nur habe ich das Gefühl, dass das irgendwie unnötig kompliziert ist. Was meint ihr? Wie würdet ihr das machen?
Wäre super, wenn mir jemand ein paar Tipps geben würde.

Lg, M0rgenstern
 

PhillipK

BeitragDo, Mai 03, 2012 10:08
Antworten mit Zitat
Benutzer-Profile anzeigen
Unnötig kompliziert? Vielleicht.
Würde ich es einfacher machen? Ja!

Solltest du es ändern? Nein!

Du hast dir doch die mühe schon gemacht - der ansatz sieht (vom groben drüberlesen) ganz ordentlich aus und bietet enorm spielraum, um hinterher noch was zu verfeinern.

Mein ansatz wäre simpel:
Bei Tilemaps arbeite ich immer mit "aktionsfeldern", sprich ein weiterer array der über die map gelegt werden kann.
Bei jedem schritt wird das tile unter dem spieler und die zugehörige aktion zusammengefrickelt die aktion evtl ausgeführt.
So eine aktion kann dann zb mit ChangeMap(obj:Object) hinterlegt werden, wobei obj ein Dummytype ist, was beliebig interpretiert werden kann - oder einfach ein string.

dh eine kachel kann den Mapchange-wert "12|18" haben (beispiel - vielleicht als koordinaten zu interpretieren, typ ist string) und ChangeMap wertet das dann aus Smile
 

Lador

BeitragDo, Mai 03, 2012 16:16
Antworten mit Zitat
Benutzer-Profile anzeigen
Also ich habs bei Iliran so gemacht, dass ich in einer separaten Datei alle "Verbindungen" zwischen Maps gespeichert habe. Eine Instanz des TVerbindungs-Types beinhaltet grob Position, Breite und Länge der Stellen und die Namen der beiden Maps. Während des Hauptprogramms wird dann einfach abgefragt, ob die Spielerposition und seine aktuelle Map mit derer der Verbindung übereinstimmt und dann notfalls teleportiert. Sehr simpel also, sehr wenig Aufwand und auch wenig Code. Den Übergang kann man auch noch mit netten Effekten verzieren, damit es nicht so sprunghaft wirkt.

Ehrlichgesagt habe ich mir deinen Code nicht angesehen, da er mir gleich zu lange war. ^^ Mein Beispiel ist in meinem Spiel auf den Übergang zwischen der (einzigen) großen Outdoor-Map, und den Indoor-Maps ausgelegt, würde sich aber sicher auch auf deine Situation übertragen lassen. Hast du es denn schon einmal ausprobiert? Für die Leser mit wenig Zeit könntest du auch kurz beschreiben, was dein Code macht.

MFG Lador
Mein aktuelles Projekt:
2D-Rollenspiel "Iliran"
Screenshot | Worklog
Fortschritt: ca. 70%

M0rgenstern

BeitragDo, Mai 03, 2012 16:55
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke euch beiden.

Also, was mein Code macht: Ein Level hat eine Liste mit TileMaps und eine Liste mit Übergängen. Jeder Übergang hat nochmal ein Bild, eine Ziel-Tilemap und eine Zielposition. Wenn der Spieler auf dem Tile steht, auf dem auch der Übergang steht, dann wird er an die entsprechende Position auf der anderen Tilemap teleportiert.

@Lador: Getestet habe ich es noch nicht, da ich den Mapeditor grade erst schreibe, was sich ohne MaxGui irgendwie als extrem unschön erweist. Aber mit Maxgui habe ich irgendwie keine Tastaturabfragen richtig umsetzen können, die ich aber brauchte um die Kamera zu bewegen...
Die Übergänge, die du ansprichst machen mir am meisten Kopfschmerzen... Aber das werde ich wahrscheinlich mit GameStates umsetzen...

Lg, M0rgenstern
 

Lador

BeitragFr, Mai 04, 2012 21:44
Antworten mit Zitat
Benutzer-Profile anzeigen
Was genau meinst du mit GameStates? Ich hab einfach einen "schwarzen Bildschirm" (also entweder ein Rechteck so groß wie der Bildschirm oder eine Bilddatei) mit Alpha-Blending (Transparenz) drüber gezeichnet, also den Wert von 0 bis 1 flüssig gesteigert. Wenn der Wert bei 1 ist, dann wieder flüssig zu 0 sinken lassen.

Schön finde ich aber auch, wenn man einen Screenshot der aktuellen Map macht und dann langsam mit Alpha-Blending in die zu wechselnde Map übergehen lässt. Ist aber etwas schwieriger. Sind halt grafische Effekte, meines Wissens nach zu Beginn eines Projekts eher noch Kleinigkeiten. Aber ich glaube jeder, der alles früh genug plant, ist ein guter Programmierer (nicht so wie ich ^^).

MFG Lador
Mein aktuelles Projekt:
2D-Rollenspiel "Iliran"
Screenshot | Worklog
Fortschritt: ca. 70%

M0rgenstern

BeitragFr, Mai 04, 2012 22:37
Antworten mit Zitat
Benutzer-Profile anzeigen
Naja.
Ich arbeite im kompletten Spiel mit Gamestates. (Gabs hier im Forum sogar ein Modul dazu, das ich benutze.)
Ein Gamestate ist in dem Fall einfach ein Zustand in welchem sich das Spiel befinden kann. Jeder Gamestate hat eine Load, eine Execute und eine End Methode. Die load methode wird aufgerufen, wenn zu diesem Gamestate gewechselt wird, die Execute methode wird aufgerufen, solange der Gamestate der aktuell genutzte ist und die End Methode halt wenn der Gamestate ausgeschaltet und durch einen anderen Ersetzt wird.
Ich hätte dann einen Gamestate MapChange oder so geschrieben, der in der Load Methode die aktuelle Karte und die nächste Karte bekommt und in seiner Execute Methode halt überblendet. Wenn er mit überblenden fertig ist, dann gehe ich wieder in den Gamestate der fürs Spiel selbst verantwortlich ist.

Lg, M0rgenstern

(Ich plane bei diesem Projekt gerne sehr viel im Voraus, weil ich nicht will, dass es wieder wegen inflexibilität oder schlechter Planung verworfen wird)

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group