[B3D] Genaue Kollision für Jump'n'Runs
Übersicht BlitzBasic FAQ und Tutorials
NoobodyBetreff: [B3D] Genaue Kollision für Jump'n'Runs |
So, Jan 25, 2009 20:49 Antworten mit Zitat |
|
---|---|---|
Wie oft hat man sich nicht schon über die Kollision in einem Jump'n'Run den Kopf zerbrochen - zumindest ich schon oft genug.
Die Möglichkeiten sind viele - von ImagesCollide, was nicht auf allen Grafikkarten funktioniert, bis zu Linienkollision (auch Vektorkollision genannt), bei der man ab und an durch den Boden fällt. Ich bin vor kurzem jedoch auf eine andere Methode gekommen, die relativ gut funktioniert und ein paar sehr praktische Eigenschaften zeigt - insbesondere für 2D Jump'n'Runs. Wer das [B3D] im Titel gesehen hat, hat vielleicht schon eine Ahnung, wie diese funktioniert - sie verwendet nämlich die Blitzinterne 3D - Kollision. 3D Kollision für ein 2D - Spiel? Ungewohnt, aber es funktioniert. Im Grunde genommen repräsentieren wir unsere Karte durch eine Ansammlung von Linien (ähnlich wie bei der Linienkollision). Für jede Linie erstellen wir hinter den Kulissen ein 3D - Viereck, auf dem der Spieler stehen kann. Der Spieler selbst ist nämlich ein Würfel, dem ein seiner Grösse entsprechender EntityRadius verpasst wurde. Leider lässt Blitz nur Kugel - X Kollisionen zu, und da unsere Karte definitiv ein Polygon ist, muss für den Spieler halt eine Kugel herhalten. In der Hauptschleife nehmen wir nun die Spielereingaben entgegen, berechnen die Geschwindigkeit des Spielers und bewegen seinen entsprechenden Würfel per MoveEntity. Dann führen wir einmal UpdateWorld aus und lassen die Kollision berechnen - falls der Spieler im Level steckt, so hat ihn UpdateWorld wieder dort hinausbewegt. Die Koordinaten des Spieler lesen wir dann mit EntityX bzw. EntityY vom Würfel wieder aus - gab es keine Kollision, so sind seine neuen Koordinaten einfach NeuePosition = AltePosition + Geschwindigkeit. Fand aber eine Kollision statt, so hat Blitz die neuen Koordinaten berechnet und wir können sie auslesen. Man muss jedoch beachten, dass die Koordinaten den Mittelpunkt des Spielers bezeichnen; man muss dann einfach noch die halbe Höhe und die halbe Breite subtrahieren. Soweit, sogut. Aber was ist, wenn wir den Spieler springen lassen wollen? Da müssen wir irgendwie herausfinden, ob der Spieler den Boden berührt. Und das geht mit CollisionNY. Hat der Spieler nämlich mit seiner Unterseite irgendetwas berührt, so zeigt die Kollisionsnormale nach oben. Zeigt die Kollisionsnormale nach unten, so hat der Spieler die Decke irgendwo berührt - dann sollten wir seine Y - Geschwindigkeit auf 0 setzen, da er sonst an der Decke klebt. Berührt er weder oben noch unten, so beschleunigen wir ihn einfach mit der Gravitation nach unten. Das wars! Mit so wenig Aufwand erhalten wir eine leistungsstarke Kollision, mit der wir sogar schräge Flächen hochlaufen können. Man muss jedoch beachten, dass die Kollisionsflächen nur auf eine Seite hin solid sind - von der anderen Seite her kann man durchlaufen. Man muss also einfach beim erstellen der Kollisionsflächen aufpassen, in welche Richtung sie zeigt. Ist eine Linie falschrum, so muss man einfach Start- und Endpunkt vertauschen und sie sollte wie erwartet funktionieren. Der Vorteil hiervon ist, dass man Plattformen erstellen kann, in die man von unten her hineinspringen kann (wie man es von Super Mario etc. kennt) - mit einer normalen Linienkollision wird das nämlich schwierig. Der einzige Nachteil an dieser Methode liegt daran, dass der Spieler nun halt durch eine Kugel angenähert wird und kein Würfel ist - das sieht ab und zu ein wenig blöd aus. Um das ganze zu veranschaulichen, habe ich hier einen kleinen Beispielcode geschrieben: Code: [AUSKLAPPEN] Graphics3D 800, 600, 0, 2
SetBuffer BackBuffer() AppTitle "Kollisionsdemo" Const GRAVITY# = 0.1 Const PLAYER_WIDTH = 20 Const PLAYER_HEIGHT = 40 Global CollMesh, CollSurface Global PlayerMesh, PlayerX#, PlayerY#, PlayerVX#, PlayerVY# Global TouchBottom, TouchTop, TouchLeft, TouchRight Type TCollFace Field X1# Field Y1# Field X2# Field Y2# Field Index End Type Timer = CreateTimer( 60 ) InitCollision() CreateCollisionFace( 0, 599, 800, 599 ) CreateCollisionFace( 200, 599, 500, 500 ) CreateCollisionFace( 500, 599, 500, 400 ) CreateCollisionFace( 200, 400, 500, 400 ) While Not KeyHit( 1 ) Cls UpdatePlayerCollision() UserInput() Render() Color 255, 255, 0 Rect PlayerX#, PlayerY#, PLAYER_WIDTH, PLAYER_HEIGHT Text 0, 0, TouchRight + " " + TouchTop + " " + TouchLeft + " " + TouchBottom Flip 0 WaitTimer Timer Wend End Function InitCollision() PlayerMesh = CreateCube() EntityRadius PlayerMesh, PLAYER_WIDTH/2., PLAYER_HEIGHT/2. EntityType PlayerMesh, 1 PositionEntity PlayerMesh, 100, -200, 0 CollMesh = CreateMesh() EntityType CollMesh, 2 CollSurface = CreateSurface( CollMesh ) Collisions 1, 2, 2, 2 End Function Function CreateCollisionFace.TCollFace( X1#, Y1#, X2#, Y2# ) Face.TCollFace = New TCollFace Face\X1# = X1# Face\Y1# = Y1# Face\X2# = X2# Face\Y2# = Y2# V1 = AddVertex( CollSurface, X1#, -Y1#, 1 ) V2 = AddVertex( CollSurface, X2#, -Y2#, 1 ) V3 = AddVertex( CollSurface, X2#, -Y2#, 0 ) V4 = AddVertex( CollSurface, X1#, -Y1#, 0 ) AddTriangle CollSurface, V1, V2, V3 AddTriangle CollSurface, V1, V3, V4 Face\Index = V1 Return Face End Function Function UpdatePlayerCollision() MoveEntity PlayerMesh, PlayerVX#, -PlayerVY#, 0 UpdateWorld PlayerX# = EntityX( PlayerMesh, True ) - PLAYER_WIDTH/2. PlayerY# = -EntityY( PlayerMesh, True ) - PLAYER_HEIGHT/2. PositionEntity PlayerMesh, PlayerX# + PLAYER_WIDTH/2., -PlayerY# - PLAYER_HEIGHT/2., 0, True TouchBottom = False TouchTop = False TouchLeft = False TouchRight = False For i = 1 To CountCollisions( PlayerMesh ) If CollisionNY( PlayerMesh, i ) > 0 Then TouchBottom = True If CollisionNY( PlayerMesh, i ) < 0 Then TouchTop = True If CollisionNX( PlayerMesh, i ) > 0.5 Then TouchLeft = True If CollisionNX( PlayerMesh, i ) < -0.5 Then TouchRight = True Next End Function Function UserInput() PlayerJump = KeyHit( 200 ) PlayerXDir = KeyDown( 205 ) - KeyDown( 203 ) If TouchBottom Then If PlayerJump Then PlayerVY# = -5 ElseIf PlayerVY# > 0 Then PlayerVY# = GRAVITY# Else PlayerVY# = PlayerVY# + GRAVITY EndIf If TouchTop And PlayerVY# < 0 Then PlayerVY# = GRAVITY# If PlayerXDir < 0 And ( Not TouchLeft ) Then PlayerVX# = -2 If PlayerXDir > 0 And ( Not TouchRight ) Then PlayerVX# = 2 If Not PlayerXDir Then PlayerVX# = 0 End Function Function Render() Color 255, 0, 0 LockBuffer BackBuffer() For Face.TCollFace = Each TCollFace Line Face\X1#, Face\Y1#, Face\X2#, Face\Y2# Next UnlockBuffer BackBuffer() End Function Da man in Jump'n'Runs bisweilen auch Tilemaps verwendet, habe ich hier noch einen Code geschrieben, der eine Helferfunktion für TileMaps enthält: Code: [AUSKLAPPEN] Graphics3D 800, 600, 0, 2
SetBuffer BackBuffer() AppTitle "Kollisionsdemo" Const GRAVITY# = 0.1 Const PLAYER_WIDTH = 20 Const PLAYER_HEIGHT = 40 Const MAP_WIDTH = 25 Const MAP_HEIGHT = 19 Const GRIDSIZE = 32 Global CollMesh, CollSurface Global PlayerMesh, PlayerX#, PlayerY#, PlayerVX#, PlayerVY# Global TouchBottom, TouchTop, TouchLeft, TouchRight Dim MapData( MAP_WIDTH - 1, MAP_HEIGHT - 1 ) Type TCollFace Field X1# Field Y1# Field X2# Field Y2# Field Index End Type Timer = CreateTimer( 60 ) InitCollision() LoadMap() While Not KeyHit( 1 ) Cls UpdatePlayerCollision() UserInput() Render() Color 255, 255, 0 Rect PlayerX#, PlayerY#, PLAYER_WIDTH, PLAYER_HEIGHT Text 0, 0, TouchRight + " " + TouchTop + " " + TouchLeft + " " + TouchBottom Flip 0 WaitTimer Timer Wend End Function InitCollision() PlayerMesh = CreateCube() EntityRadius PlayerMesh, PLAYER_WIDTH/2., PLAYER_HEIGHT/2. EntityType PlayerMesh, 1 PositionEntity PlayerMesh, 100, -200, 0 CollMesh = CreateMesh() EntityType CollMesh, 2 CollSurface = CreateSurface( CollMesh ) Collisions 1, 2, 2, 2 End Function Function LoadMap() For i = 0 To MAP_HEIGHT - 1 For t = 0 To MAP_WIDTH - 1 Read MapData( t, i ) Next Next For X = 0 To MAP_WIDTH - 1 For Y = 0 To MAP_HEIGHT - 1 If MapData( X, Y ) Then If X > 0 Then If Not MapData( X - 1, Y ) Then CreateCollisionFace( X*GRIDSIZE, ( Y + 1 )*GRIDSIZE, X*GRIDSIZE, Y*GRIDSIZE ) EndIf If Y > 0 Then If Not MapData( X, Y - 1 ) Then CreateCollisionFace( X*GRIDSIZE, Y*GRIDSIZE, ( X + 1 )*GRIDSIZE, Y*GRIDSIZE ) EndIf If X < MAP_WIDTH - 1 Then If Not MapData( X + 1, Y ) Then CreateCollisionFace( ( X + 1 )*GRIDSIZE, Y*GRIDSIZE, ( X + 1 )*GRIDSIZE, ( Y + 1 )*GRIDSIZE ) EndIf If Y < MAP_HEIGHT - 1 Then If Not MapData( X, Y + 1 ) Then CreateCollisionFace( ( X + 1 )*GRIDSIZE, ( Y + 1 )*GRIDSIZE, X*GRIDSIZE, ( Y + 1 )*GRIDSIZE ) EndIf EndIf Next Next End Function Function CreateCollisionFace.TCollFace( X1#, Y1#, X2#, Y2# ) Face.TCollFace = New TCollFace Face\X1# = X1# Face\Y1# = Y1# Face\X2# = X2# Face\Y2# = Y2# V1 = AddVertex( CollSurface, X1#, -Y1#, 1 ) V2 = AddVertex( CollSurface, X2#, -Y2#, 1 ) V3 = AddVertex( CollSurface, X2#, -Y2#, 0 ) V4 = AddVertex( CollSurface, X1#, -Y1#, 0 ) AddTriangle CollSurface, V1, V2, V3 AddTriangle CollSurface, V1, V3, V4 Face\Index = V1 Return Face End Function Function UpdatePlayerCollision() MoveEntity PlayerMesh, PlayerVX#, -PlayerVY#, 0 UpdateWorld PlayerX# = EntityX( PlayerMesh, True ) - PLAYER_WIDTH/2. PlayerY# = -EntityY( PlayerMesh, True ) - PLAYER_HEIGHT/2. PositionEntity PlayerMesh, PlayerX# + PLAYER_WIDTH/2., -PlayerY# - PLAYER_HEIGHT/2., 0, True TouchBottom = False TouchTop = False TouchLeft = False TouchRight = False For i = 1 To CountCollisions( PlayerMesh ) If CollisionNY( PlayerMesh, i ) > 0 Then TouchBottom = True If CollisionNY( PlayerMesh, i ) < 0 Then TouchTop = True If CollisionNX( PlayerMesh, i ) > 0.5 Then TouchLeft = True If CollisionNX( PlayerMesh, i ) < -0.5 Then TouchRight = True Next End Function Function UserInput() PlayerJump = KeyHit( 200 ) PlayerXDir = KeyDown( 205 ) - KeyDown( 203 ) If TouchBottom Then If PlayerJump Then PlayerVY# = -5 ElseIf PlayerVY# > 0 Then PlayerVY# = GRAVITY# Else PlayerVY# = PlayerVY# + GRAVITY EndIf If TouchTop And PlayerVY# < 0 Then PlayerVY# = GRAVITY# If PlayerXDir < 0 And ( Not TouchLeft ) Then PlayerVX# = -2 If PlayerXDir > 0 And ( Not TouchRight ) Then PlayerVX# = 2 If PlayerXDir = 0 Then PlayerVX# = 0 End Function Function Render() Color 255, 0, 0 LockBuffer BackBuffer() For Face.TCollFace = Each TCollFace Line Face\X1#, Face\Y1#, Face\X2#, Face\Y2# Next UnlockBuffer BackBuffer() End Function .MapCollision Data 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 Data 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 Data 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 Data 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 Data 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1 Data 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1 Data 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1 Data 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1 Data 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1 Data 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1 Data 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1 Data 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 Data 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 Data 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 Data 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1 Data 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 Data 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 Data 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 Data 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 |
||
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 |
- Zuletzt bearbeitet von Noobody am So, Jan 25, 2009 21:37, insgesamt einmal bearbeitet
Firstdeathmaker |
So, Jan 25, 2009 21:27 Antworten mit Zitat |
|
---|---|---|
Hmm, spring mal beim obigen Beispielcode von links gegen die Wand und halte die Links-Taste gedrückt. Der Spielerkasten klebt an der Wand.
Und wenn man von der oberen Linie nach links geht, sodass man runterfällt, dann aber sofort wieder nach rechts geht, wird der Spieler wieder auf die obere Linie gesetzt... Aber vom Prinzip her nicht schlecht. |
||
www.illusion-games.de
Space War 3 | Space Race | Galaxy on Fire | Razoon Gewinner des BCC #57 User posted image |
Noobody |
So, Jan 25, 2009 21:40 Antworten mit Zitat |
|
---|---|---|
Hui, das mit dem an-der-Wand-kleben war ein kleiner Flüchtigkeitsfehler meinerseits - ich hatte aus Versehen den Modus 3 statt 2 bei Collisions verwendet.
Ist nun nacheditiert, danke für den Hinweis. Dass man wieder auf die Linie kommt, liegt daran, dass der Spieler eine Kugel ist und nicht ein Würfel. Wenn man sich gegen eine Kante drückt, so rutscht der Spieler wegen seiner runden Oberfläche nach oben. Das ist ein wenig ärgerlich, aber mir kam noch keine Idee, wie man das beheben könnte. |
||
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 |
coolo |
So, Jan 25, 2009 22:21 Antworten mit Zitat |
|
---|---|---|
Toll! Ich finde das Tutorial echt gut, hab nämlich sowas schon lange gesucht. Ich hoffe du machst in Zukunft mehr von dieser Sorte. | ||
http://programming-with-design.at/ <-- Der Preis ist heiß!
That's no bug, that's my project! "Eigenzitate sind nur was für Deppen" -Eigenzitat |
ozzi789 |
Mo, Jan 26, 2009 8:51 Antworten mit Zitat |
|
---|---|---|
Topp, mehr kann ich da nicht sagen, deine Tuts sind eine Bereicherung für uns alle | ||
0x2B || ! 0x2B
C# | C++13 | Java 7 | PHP 5 |
orpheus_2003 |
Di, Feb 17, 2009 18:00 Antworten mit Zitat |
|
---|---|---|
Ich dachte immer ich kann proggen.
Aber nun. Steig ich nicht mehr durch. Das ist mir zu hoch. Bin momentan auch gerade dran in meinem Jump & Run ne Tile Colli zu machen. Aber das hier ist mir zu strange...... Aber Danke fürs erklären. |
||
GazerStar - the beginning
http://gazerstar.lexigame.de/ Wizard (Worktitel) http://wizard.lexigame.de |
orpheus_2003 |
Mo, Sep 21, 2009 18:33 Antworten mit Zitat |
|
---|---|---|
@Noobody
Hi. Ich probier gerade das in mein Game Wizard zu implementieren. Aber irgendwie scheiter ich. Hab es geschafft die Daten zu laden. Er rendert mir auch die Boxen. Kollision funktioniert. Aber lässt sich diese Kollision auch auf scrollende Tilemaps anwenden? So siehts aus momentan: |
||
Noobody |
Mo, Sep 21, 2009 20:43 Antworten mit Zitat |
|
---|---|---|
Klar lässt sich die Kollision auch auf scrollende Tilemaps anwenden - die Frage ist nur, wie dein Scrolling aussieht
Generell sollte das Scrolling ja nur bei der Zeichenroutine eine Rolle spielen und intern immer mit ungescrollten Koordinaten gerechnet werden - falls man es so macht, kann man den Code hier unverändert übernehmen. Andernfalls muss man halt ein wenig tricksen. Entweder, man bewegt das Levelmesh um die Scrollwerte, oder man berechnet die Kollision wie gehabt und rechnet dann irgendwie nach der Kollision um. Ich kann aber nur empfehlen, intern immer mit ungescrollten Werten zu arbeiten, da das sehr viel Arbeit erspart. |
||
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 |
orpheus_2003 |
Mo, Sep 21, 2009 21:14 Antworten mit Zitat |
|
---|---|---|
Hmm.
Aber es ist doch so. Das Level ist in einem Dim gespeichert. (200*200) Die Kollisionsabfrage momentan läuft ja mit Grabimage. Wenn ich jetzt auf Dimabfragen (Box collides) umstelle, muss ich doch die Verschiebung vom Level mitberechnen? Oder muss ich die Mesh jedes mal (das ich momentan im Loadmap gleich auf 200*200 rechne) neu berechnen lassen? Ich bin confused. Kollision ist nicht meines. Pixelgenau geht noch einfach. Aber mit Matrizen, Vektoren und Vertexes. Das ist mir zu hoch. Hab keinen Hochschulabschluss... Das nervt mich jetzt schon seit Anfang. Da hab ich nun meine FPS und steig dafür bei der Kollision aus... So sieht die Begung des Players und des Levels aus... Mapoffset ist die Verschiebung der Tiles.. Code: [AUSKLAPPEN] f CharacterX > 472 Then
If MapX < MapWidth-20 Then ; Check borders MapOffsetX = MapOffsetX - 4 ; Offset for Mapscrolling CharacterX = 472 If MapOffsetX < -30 Then ; Map border If Mapx<164 Then MapOffsetX = 0 ; Offset to 0 MapX = MapX + 1 ; Map scrolling End If EndIf End If End If ; zeichnen If MaptileX(X1,Y1)>-1 Or MaptileY(X1,Y1)>-1 Then DrawImageRect ChipSet, x * 32 + MapOffsetX, y * 32 + MapOffsetY, (MaptileX(X1,Y1)*34)+2, (MaptileY(X1,Y1)*34)+2, 32, 32 |
||
GazerStar - the beginning
http://gazerstar.lexigame.de/ Wizard (Worktitel) http://wizard.lexigame.de |
BIG BUG |
Di, Sep 22, 2009 0:02 Antworten mit Zitat |
|
---|---|---|
Wenn Du nicht riesige Maps hast, dann ist es tatsächlich sinnvoll einfach feste Werte zu haben und nur die "Kamera" über das Level zu bewegen, also das Scrolling wird nur in der Zeichenroutine implementiert.
Bei riesigen Welten wie z.B. für ein Space-Game kann sich hier aber die begrenzte Genauigkeit von Float-Werten als Problem herausstellen, hier müsste man also tatsächlich die ganze Welt um den "Nullpunkt Spieler" bewegen. Für eine einfache horizontale/vertikale Tile Kollision reicht übrigens reine Addition/Subtraktion, also Mathe der Grundschule aus. Das einzige was es sonst zu Verstehen gibt ist das Koordinatensystem, also dass es eine X- und eine Y-Postion im 2D-Raum gibt. |
||
B3D-Exporter für Cinema4D!(V1.4)
MD2-Exporter für Cinema4D!(final) |
orpheus_2003 |
Di, Sep 22, 2009 8:43 Antworten mit Zitat |
|
---|---|---|
Hm.
Irgendwie steh ich auf dem Schlauch. 1. Wenn ich das Scrolling nur auf die Zeichenebene begrenze. Wie prüfe ich die Kollision. Ich muss doch einen Bezug vom Player zu den Maptiles herstellen um Aktionen herbeizuführen Das blöde daran ist die Ungenauigkeit. Da der Level mit einem Offset von +/- 32 scrollt ist die Rückrechnung auf das entsprechende Teil sehr ungenau. Also brauche ich die Mapverschiebung auch bei der Kollisionsabfrage. Daher hat mich die Aussage von Nobody verwundert keine Scrollwerte bei der Kollision zu verwenden? 2. Mit dieser 3D Kollision würde die Kollision des Levels mit dem Player sehr gut funktionieren. Auch die Annäherung mit der Kugel wäre Ideal, da der Player z.B über nen Abhang runterfallen würde. Allerdings habe ich Schwierigkeiten das ganze zu bewegen, da ich mit 3D und Vertex keien Erfahrung habe. 3. Die Prüfung von Tiles zur Kollisionsabfrage des Levels mit dem Player ist mir momentan noch nicht gelungen. Das ganze scheitert an der Ungenauigkeit.... ##### EDIT NACHTRAG ##### Da ja die Imagescollide nicht so richtig geht hab ich mich nun entschieden eine Version ohne Imagescollide zu machen. Dank BIG BUG und seiner Funktion gehts nun prima, ohne Fehler und in Echtzeit mit massig Frames. Hier noch der Code wer ihn braucht: Code: [AUSKLAPPEN] ;replaces ImagesCollide because of MAV bug from BIG BUG Function ImgCollide(image1,xpos1, ypos1, frame1, image2, xpos2, ypos2, frame2=0, mask=0) Local startx, starty, endx, endy, ix, iy Local width1 = ImageWidth(image1) Local height1 = ImageHeight(image1) Local width2 = ImageWidth(image2) Local height2 = ImageHeight(image2) xpos1 = xpos1 - ImageXHandle(image1) ypos1 = ypos1 - ImageYHandle(image1) xpos2 = xpos2 - ImageXHandle(image2) ypos2 = ypos2 - ImageYHandle(image2) startx = xpos2 - xpos1 starty = ypos2 - ypos1 start2x = startx start2y = starty endx = startx + width2 endy = starty + height2 If startx < 0 Then startx = 0 If starty < 0 Then starty = 0 If endx > width1 Then endx = width1 If endy > height1 Then endy = height1 endx = endx - 1 endy = endy - 1 If startx > endx Or starty > endy Then Return 0 LockBuffer ImageBuffer(image1, frame1) LockBuffer ImageBuffer(image2, frame2) For ix = startx To endx For iy = starty To endy If mask <> (ReadPixelFast(ix, iy, ImageBuffer(image1, frame1)) And $00FFFFFF) Then If mask <> (ReadPixelFast(ix-start2x, iy-start2y, ImageBuffer(image2, frame2)) And $00FFFFFF) Then UnlockBuffer ImageBuffer(image1, frame1) UnlockBuffer ImageBuffer(image2, frame2) Return 1 EndIf EndIf Next Next UnlockBuffer ImageBuffer(image1, frame1) UnlockBuffer ImageBuffer(image2, frame2) End Function Thx a lot. Neue Version online... |
||
Xawer23 |
So, Jan 24, 2010 14:24 Antworten mit Zitat |
|
---|---|---|
Boah, das passt gerade wie die Faust aufs Auge in mein Projekt.
Dürfte ich deinen Roh-Code (aus dem 1. post) für meine Zwecke modifizieren und weiterverwenden? würde mir echt total helfen. |
||
Megamag |
So, Jan 24, 2010 14:48 Antworten mit Zitat |
|
---|---|---|
Das ist ein Tutorial und ein Tutorial baut darauf auf, dass LEute den Code nehmen, mit ihm experimentieren und ihn verstehen. Deshalb wird wohl auch keiner etwas dagegen haben, wenn du auf noobody's Code aufbaust | ||
Noobody |
So, Jan 24, 2010 17:21 Antworten mit Zitat |
|
---|---|---|
Selbstverständlich darfst du das | ||
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 |
Xawer23 |
Fr, Jan 29, 2010 15:41 Antworten mit Zitat |
|
---|---|---|
Ich hab da mal eine Frage:
gibt es einen Unterschied zwischen 3D Koordinaten und 2D Koordinate(abgesehen von der Z-Achse)? Denn wenn ich dieses Beispiel in mein Programm einbaue, bleibt die Spielfigur überhalb des Bildschirms hängen(Ywert = -135). Wie kann mann das umrechnen oder mache ich einen anderen Fehler? PS: Danke für das super Tutorial! |
||
Noobody |
Fr, Jan 29, 2010 16:14 Antworten mit Zitat |
|
---|---|---|
In 3D ist im Vergleich zu 2D die Y-Achse invertiert. Das heisst, dass eine 2D-Koordinate von 100, 100 in 3D zu 100, -100 umgewandelt werden muss, um den gleichen Punkt zu bezeichnen.
Das wird im Code von CreateCollisionFace und UpdatePlayerCollision ausgeglichen. Falls du die beiden Funktionen verändert hast, kann es sein, dass bei dir das Level gespiegelt ist - oben ist unten und umgekehrt. Ich würde daher diese beiden Funktionen nochmal durchschauen und überprüfen, ob da nicht irgendwo ein - fehlt. Wenn du den Fehler dann immer noch nicht findest, kannst du ja die relevanten Ausschnitte des Codes hier posten oder mir per PN zukommen lassen, wenn du ihn nicht öffentlich zeigen willst. |
||
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 |
Xawer23 |
Fr, Jan 29, 2010 21:47 Antworten mit Zitat |
|
---|---|---|
Danke für die schnelle freundliche Hilfe.
Ich werde nochmal diesen Aspekt durchchecken und mich dann melden. |
||
Übersicht BlitzBasic FAQ und Tutorials
Powered by phpBB © 2001 - 2006, phpBB Group