Kollision und Sprung 2D ?
Übersicht

![]() |
Raiden93Betreff: Kollision und Sprung 2D ? |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hey,
ich habe mal ein Versuch gemacht und scheitere leider an der Perfekten Kollision zwischen Spieler und Boden könnte mir jemand mal nen Tipp geben wie man es richtig macht? Code: [AUSKLAPPEN] AppTitle "Unlimit Build"
Graphics 800,600,32,2 SetBuffer BackBuffer () Global FPS_Timer = CreateTimer (60) ;World Variablen Global Allow_Gravity = True ;Spieler Variablen Global SpielerAnimX# = 1 Global SpielerAnimY# = 1 Global Sprung# = 0 Global SprungMax# = 10 ;Dim Map Dim map(10,10) Data 1,1,1,1,1,1,1,1,1,1,1 Data 1,0,0,0,0,0,0,0,0,0,1 Data 1,0,0,0,0,0,0,0,0,0,1 Data 1,0,0,0,0,0,0,0,0,0,1 Data 1,0,0,0,0,0,0,0,0,0,1 Data 1,0,0,0,0,0,0,0,0,0,1 Data 1,0,0,0,0,0,0,0,0,0,1 Data 1,0,0,0,0,0,0,0,0,0,1 Data 1,0,0,0,0,1,0,0,0,0,1 Data 1,0,0,0,1,1,0,0,0,0,1 Data 1,1,1,1,1,1,1,1,1,1,1 Map_Initionisieren () Repeat Cls Map_Zeichnen () Spieler_Zeichnen () Gravity () Spieler_Steuerung () Color 255,255,255 Text 10,20,"Sprung: " +Sprung Text 10,0,"SprungMax: " +SprungMax Text 10,50,"SpielerAnimX: "+SpielerAnimX# Text 10,70,"SpielerAnimY: "+SpielerAnimY# Flip (0) WaitTimer (FPS_Timer) Until KeyHit (1) Function Map_Initionisieren () For Y=0 To 10 For X=0 To 10 Read map(X,Y) Next Next End Function Function Map_Zeichnen () For Y=0 To 10 For X=0 To 10 If map(X,Y) = 1 ;Wand Color 255,0,0 Rect X*32,Y*32,32,32,1 End If Next Next End Function Function Spieler_Zeichnen () ;Spieler Zeichnen Color 0,0,255 Rect SpielerAnimX#*32,SpielerAnimY#*32,32,32,1 End Function Function Gravity () If map(SpielerAnimX#,SpielerAnimY#+0.1) = 0 SpielerAnimY# = SpielerAnimY# +0.1 Else Sprung = 0 End If End Function Function Spieler_Steuerung () If KeyDown (205) ;Rechts If map(SpielerAnimX#+0.5,SpielerAnimY#) = 0 SpielerAnimX# = SpielerAnimX# +0.1 End If End If If KeyDown (203) ;Links If map(SpielerAnimX#-0.5,SpielerAnimY#) = 0 SpielerAnimX# = SpielerAnimX# -0.1 End If End If If KeyDown (57) ;Springen If Sprung < SprungMax SpielerAnimY = SpielerAnimY /1.05 Sprung = Sprung +1 End If End If End Function |
||
PhillipK |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Ersteinmal wäre eine Kurze beschreibung nett ![]() Ich persönlich habe kein blitzbasic, aber evtl kann ja einer wie ich doch helfen ![]() Der code sieht mir stark nach nem Mario-ähnlichem spiel aus (Dropdown halt ![]() Mit dem hintergrund nehme ich mal an, das es evtl bei der abfrage ein problem geben könnte. (zumal du nicht genau gesagt hast, was dein problem ist^^) Code: [AUSKLAPPEN] Function Gravity () If map(SpielerAnimX#,SpielerAnimY#+0.1) = 0 SpielerAnimY# = SpielerAnimY# +0.1 Else Sprung = 0 End If End Function Mit Floats für einen Array index wär ich immer vorsichtig. Da könnte dir die rundung ein strich durch die Rechnung machen. Kommt es denn zu einer kollision? Wird hier zb der Else-content ausgeführt (kannst du ein Print dort lesen? Am besten mit deiner momentanen Y koordinate ![]() Aber ich glaube fast nicht, dass das problem ist ^^ Najo, infos? ![]() |
||
![]() |
Raiden93 |
![]() Antworten mit Zitat ![]() |
---|---|---|
ups sorry mehr Infos kommen ![]() |
||
![]() |
darth |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hallo,
vielleicht solltest du dich erstmal ein bisschen in Tilemaps einlesen? Das wäre mein Vorschlag. Du hast ne Map in deinem Array da (das du intonierst, oder ionisierst.. eigentlich heisst es ja initialisieren, aber das sind unwichtige Details). Beim Zeichnen der Map solltest du wissen, wie gross deine Tiles sind. BlitzBasic: [AUSKLAPPEN] Local TX = 32 Wenn du jetzt wissen möchtest, in welchem Tile ein Punkt ist, dann musst du die Welt-Koordinate durch die Tilegrösse dividieren. Ein Beispiel: Code: [AUSKLAPPEN] Deine Map ist 32x32, der Spieler steht bei 50.
1*32 = 32 < 50 2*32 = 64 > 50 -> Der Punkt ist im zweiten Tile! Also: BlitzBasic: [AUSKLAPPEN] tilePosX = playerX /TX Für die Kollision kannst dus beliebig kompliziert machen. Die einfachste Methode ist wohl einfach zu schauen, ob der Spieler nach der Bewegung in einem belegten Tile liegt, dann ist die Bewegung verboten. Das hält natürlich immernoch die Gefahr, dass der Spieler bei zu grossen Bewegungen durch Tiles hindurch"tunneln" kann, aber das ist meist vernachlässigbar (wirklich..). Zur Kollisionsüberprüfung musst du wissen, welche Tiles der Spieler von seiner Position aus belegen kann. Ich mache da meist einfach einen Rahmen von 3x3 um den Spieler rum, ist wahrscheinlich etwas verschwenderisch, aber who cares, ait? BlitzBasic: [AUSKLAPPEN] Function checkCollision(posX, posY) (Kleine Anmerkung: Das ist aus einem Projekt kopiert, die +400/+300 steht da, weil der Spieler immer in der Mitte des Bildschirmes zentriert ist. Darum wird auch -posX/-posY gerechnet, um die Spielerverschiebung einzubinden. Kleines Bisschen Vektorgeometrie, nicht allzu kompliziert. Aber selbst wenn es unklar sein sollte, müsste das Prinzip der Kollision klar werden.) Dann musst du das mit dem Sprung und der Bewegung noch regeln und so! Dazu musst du wissen wann kollidiert wird, wann er auf dem Boden steht und so weiter. Muss man sich zwischenspeichern. BlitzBasic: [AUSKLAPPEN] vY = vY +GRAVITY Und das wärs dann eigentlich auch schon. Wie gesagt.. Lies dich etwas in Tilemaps ein und mach dann von da weiter. Wirklich kompliziert ist es eigentlich nicht. MfG, Darth |
||
Diese Signatur ist leer. |
PhillipK |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Ich persönlich unterstütze die Grundidee, eine art Kollisions-array zu verwenden. Grund ist, das hier später beliebig erweitert werden kann - zb bis zu 32 Flags für verschiedene "effekte" auf den kacheln (schliddern, kollision, under_water etc).
Mit der entsprechenden brechung auf die passende koordinate sollte das kein problem sein. Das 3x3 Raster ist eine Intressante idee. Das lässt sich als grobe vorprüfung nutzen, um zu erfahren "Was ist eigentlich um den Spieler rum los?". Alles in allem klingt darth's lösungsansatz super, ich denke das wird dir weiterhelfen ![]() Hierzu musst du also folgendes machen: Code: [AUSKLAPPEN] Rect SpielerAnimX#*32,SpielerAnimY#*32,32,32,1
Sowas rausballern. Stattdessen deine positionsvariable direkt auf den absoluten koordinaten wert erhöhen ![]() Andersrum beim Tiles abprüfen dann halt: (ich denke, deine tiles sind 32x32 pixel groß?) Code: [AUSKLAPPEN] If map(Int(SpielerAnimX#/32),Int(SpielerAnimY#/32)) = 0
Abfragen. Natürlich solltest du dann auch beim erhöhen einen höheren wert angeben, sonst hast du das gefühl, du spielst eine schildkröte. Zum Springen habe ich noch eine anmerkung (ich weiß grade nicht, ob du soetwas schon benutzt ): Ich nutze immer eine art Schalter-variable die meistens 'onGround' heißt. If Player.onGround = 1 and KeyDown(KEY_SPACE) then Player.speedY = -5.0 Endif -> so in der art zb. nun wird pro frame Player.speedY :*0.7 oder sonstwie gerechnet, um den wert gleichmäßig runterzubrechen. Diesen speedY (und auch speedX) addiere ich anschließend, wie in jedem frame, auf die Spielerposition. Sollte speedY einen gewissen wert überschreiten (zb > -1), kann man überlegen, wie man es weiter schaltet. Hier könntest du zb dein Gravity mit einer abfrage austatten, ob der spieler 'onGround = 0' ist, wenn ja, dann springt er grade (kein gravity). Tritt der fall einer zu niedriegen geschwindigkeit ein, sodass er wieder nach unten gezogen wird, setzt du onGround zb auf -1 (er fällt). -1 deswegen, damit man nicht im sprung einen weiteren sprung aktivieren kann. Ist der spieler irgendwann mit dem boden kollidiert (unter ihm ist ein Tile!), wird onGround = 1 gesetzt und alles kann von vorne beginnen. (Uff, das ist mehr geworden, wie geplant. Ich hoffe ich habe es jetzt nicht zu kompliziert erklärt, da es doch eigentlich recht simpel ist :X ) Mit freundlichem Gruß, Phillipk ![]() |
||
![]() |
Midimaster |
![]() Antworten mit Zitat ![]() |
---|---|---|
weia...das sind ja mal wirklich komplizierte antworten! und sie gehen auch noch so schön am thema vorbei...
also raiden93, dein Code sieht alles gar nicht so schlecht aus. In den Beiträgen der Anderen steckt schon ein bißchen Wahrheit....aber der Grund, warum dein Spieler-Rechteck "durchsackt" liegt nur daran, das du außer acht läßt, das ja das Spieler-Rechteck eine Breite und Tiefe besitzt und du aber nur seine linke obere Ecke auf Kollision checkst. hier siehst du, wie das Rechteck ja noch 32 pixel tiefer hinuntergeht als der punkt SpielerAnimY#*32 BlitzBasic: [AUSKLAPPEN] Function Spieler_Zeichnen () die untere kante deines spieler-rechtecks liegt doch eigentlich schon bei SpielerAnimY#*32+32, oder? In einer genaueren Kollisionsabfrage wirst du deshalb alle 4 Ecken des Spielers auf Kollision checken müssen. das sind die 4 Ecken: 1. links/oben: Map ( SpielerAnimX# , SpielerAnimY# ) 2. rechts/oben: Map ( SpielerAnimX#+1 , SpielerAnimY# ) 3. links/unten: Map ( SpielerAnimX# , SpielerAnimY#+1 ) 4. rechts/unten: Map ( SpielerAnimX#+1 , SpielerAnimY#+1 ) für deinen senkrechten Fall wäre es jetzt ausreichend die 3. oder 4. Ecke zu checken. BlitzBasic: [AUSKLAPPEN] Function Gravity () Da es aber wegen der Verwendung der FLOAT-Variablen zu dem Rundungsfehler kommt, wird das Rechteck nun 16 Pixel zu früh anhalten. Dafür gibt es zwei Lösungen: einfach mit 0.5 als Additionswert arbeiten: BlitzBasic: [AUSKLAPPEN] Function Gravity () oder das Spieler-Rechteck wirklich um den Spielerpunkt herumzeichen: BlitzBasic: [AUSKLAPPEN] Function Spieler_Zeichnen () So malst du das Spieler-Rechteck immer 16 pixel entfernt vom Spieler-Mittelpunkt Code: [AUSKLAPPEN] ***************
* * * * * * * * * * * *************** |
||
![]() |
ZEVS |
![]() Antworten mit Zitat ![]() |
---|---|---|
Für ein bisschen realistischere Physik bräuchtest du außerdem noch eine Variable, die die Geschwindigkeit auf der Y-Achse angibt. Dadurch wird verhindert, dass dein Spieler nach dem Sprung ganz plötzlich schnell nach unten fällt (und das auch noch gleichmäßig). Diese Variable wird einfach immer gesenkt, solange der Spieler sich in der Luft befindet und einmalig auf einen hohen Wert gestellt, wenn er abspringt. Die Berechnung
Zitat: SpielerAnimY = SpielerAnimY /1.05 ist für das Abspringen nämlich völlig unrealistisch: je niedriger der Spieler ist, desto höher springt er. Da fühlt sich die Physik aber schwer gekränkt. Solche Werte wie Allow_Gravity solltest du mit Const![]() ![]() Wieso du die Variablen SpielerAnimX/Y nennst, ist mir schleierhaft, da wird schließlich nichts animiert. ZEVS |
||
![]() |
Raiden93 |
![]() Antworten mit Zitat ![]() |
---|---|---|
ja das lag daran das ich SpielerX hatte und eine SpielerAnimX und die anim war vorher eine Animation vom Spieler die ich aber raus gebaut habe^^. Ich werde mich mal weiter dran versuchen. | ||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group