Kollision auf einer 2d Tilemap

Übersicht BlitzBasic FAQ und Tutorials

Neue Antwort erstellen

DivineDominion

Betreff: Kollision auf einer 2d Tilemap

BeitragDo, Aug 19, 2004 0:47
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich sehe hier dutzende Kollisionsfragen auftauchen, und das macht mir Angst... Ich dneke daher, dass es für mich an der Zeit ist, euch allen zu zeigen, wie sowas verdammt einfach mit einem Array gelöst wird Smile Ich erhebe keinerlei Anspruch auf "coolnes" dieser Methode - ich würde auch lieber Types mit reinnehmen oder sowas, aber es soll ja einfach bleiben und einen Einstieg ermöglichen.

Also, steigt ein.


Teil 1 - die Map

Ich gehe davon aus, dass ihr eure Maps in einem Array speichert:
Code: [AUSKLAPPEN]
Dim map( hoehe, breite )


Das ist die einfachste Methode für Tilemaps; ein Array. Warum erst die Höhe und dann die Breite? Das ist, eigentlich, erst einmal total Wurscht. Ich kann nur aus Erfahrung sprechen und euch sagen: gewöhnt euch lieber an "erst Y und dann X"-Denken, was dem üblichen Koordinatenkram ja völlig widerspricht, denn es kommt öfter vor, dass man nach "Zeilen" sortieren will (also die Y-Achse entlang) als nach "Spalten". Zum Beispiel, wenn ihr auf ein Tile einen großen Baum setzt, der nur dieses eine Tile reserviert, und wenn der Spieler drunterher laufen soll, dann ist es wichtiger, zeilenweise zu vergleichen. Bei BlitzBasic ist das noch recht egal, unter Umständen verlangen andere Sprachen, dass ihr erst alle Zeilen (Y) definiert und die dann mit je einer Zeile Inhalt befüllt, also Arrays verschachtelt. Da wird's erst richtig relevant. Auch, wenn euch das jetzt wohl total egal ist, ich schreibe hier und ich bestimme das halt so! Smile

Für diesen Beitrag nehme ich einfach mal eine Tilegröße von 16x16 Pixel, weil ich das so schön finde Smile Drum definieren wir auch gleich mal eine Konstante mit entsprechendem Wert, damit man den Code später in Worten lesen kann (Konstanten werden meist in Großbuchstaben geschrieben, ist auch nett sich das anzugewöhnen):
Code: [AUSKLAPPEN]
Const TILESIZE = 16


Für das Beispiel ist die Karte 100x100 Tiles groß.
Code: [AUSKLAPPEN]
Const MAP_WIDTH = 100
Const MAP_HEIGHT = 100


Jetzt gehts ans Eingemachte. Ein wenig Theorie jetzt:


Teil 2 - Layer

Die meisten die sowas wie Kollision verwenden machen entweder ein Rollenspiel oder ein Jump&Run. Für Letzteres sind mehrere Layer (zu Deutsch: "Ebene" oder meinetwegen auch "Schicht") nicht zwingend notwendig, aber gewiss ne nette Sache.
Darum gehe ich vom komplexeren Fall aus, einem Rollenspiel - oder einem beliebigen anderen Spiel mit mehreren Ebenen und draufsicht; WiSim oder Strategie z.B.

Eine Ebene enthält die Werte (Nummern der Frames) unserer Bodentiles. Die ist Flächendeckend und kann deswegen mit dem etwas schnelleren Befehl DrawBlock gemalt werden.
Darauf malen wir die Figuren.
Eine andere Ebene, diesmal ÜBER den Figuren, soll den KRam dadrunter verdecken. Man kann drunter herlaufen und durch Transparenz sieht man durch die Tiles durch. Z.b. schräge Häuserdächer, Baumkronen, Laternenpfähle und so weiter.

Die Map muss daher um eine dritte Dimension erweitert werden, die die Ebenen angibt. Man entwickelt also "Tiefe". Für die Maße verwende ich mal die Konstanten von oben:
Code: [AUSKLAPPEN]
Dim map( MAP_HEIGHT, MAP_WIDTH, 1 ) ;0 und 1 = 2 Ebenen


Das ganze könnte man z.B so malen:
Code: [AUSKLAPPEN]
;Boden, Layer Nr. 0
For y = 0 to MAP_HEIGHT
  For x = 0 to MAP_WIDTH
    DrawBlock Bild, x * TILESIZE, y * TILESIZE, map( y, x, 0 )
  Next
Next

;Spieler malen
DrawImage Spieler, PlayerX * TILESIZE, PlayerY * TILESIZE

;Drüberzeichnen, Layer Nr. 1
For y = 0 to MAP_HEIGHT
  For x = 0 to MAP_WIDTH
    DrawBlock Bild, x * TILESIZE, y * TILESIZE, map( y, x, 1 )
  Next
Next


Ich gehe davon aus das ihr es schon wisst, aber trotzdem: Das multiplizieren (*) mit TileSizebewirkt, dass eine Position, die in Tiles gemessen wird, für die Grafiken umgerechnet wird. Wir speichern in dem Map-Array 100*100 Tiles und nicht 100*100 Pixel! Darum müssen wir mit dem Multiplizieren den passenden Abstand zwischen den Tiles erst mal schaffen, um die Karte überhaupt darstellen zu können.

Beim Spieler ist es genau das selbe. Der bewegt sich nicht flüssig sondern hüpft von Tile zu Tile.
Das ist gut.
Dann kann man nämlich einfach die Spielerposition zum "navigieren" auf der Karte verwenden ohne vorher zurückrechnen zu müssen und es entstehen so keine Probleme mit der Position AUF einem Tile und der Kollision bla bla bla. Ist eben einfacher zu erklären Smile

Okay, also haben wir jetzt was zum malen. Auf in die Kollision!


Teil 3 - die Kollision

Wir müssen das Array erweitern. Ein neuer Layer kommt drauf:
Code: [AUSKLAPPEN]
Dim map( MAP_HEIGHT, MAP_WIDTH, 2 ) ;0, 1, 2 = 3 Layer


Die neue Ebene enthält keine Tiledaten, sondern 0 und 1 - False und True.
Das wird unsere Kollision.
Wir markieren das gesamte dargestellte Tile als "blockiert", wenn wir den Wert der neuen Ebene auf 1 oder true setzen (kommt das gleiche bei raus) - und das ist auch gut so, denn die Kollision durch Abfrage der Framenummer (if map(y,x,2) < 4 then Kollision = false - so etwa, igitt!) ist nicht sehr schlau. Erstmal ändern sich die Tilesets ständig und zweitens... Ist es eben unschön Wink

Also haben wir in "Layer 2" lediglich die Daten für die Kollision. Das ist gewiss eine verflucht große Platzverschwendung wenn die Map erstmal wächst, aber es fällt eben nicht auf - nicht einmal bei 100*100 Tiles großen Karten. Und nur durch diesen Layer den RAM zu sprengen müsst ihr erst mal schaffen - es taugt also durchaus für ein vollwertiges Spiel!


Teil 4 - Kollisionsabfrage

Jetzt muss das ganze auch funktionieren. Also schnell ein paar neue Kosntanten am Anfang einfügen, für Tastendruck, damit man den Code wörtlich lesen kann und nicht so viele Zahlen hat:
Code: [AUSKLAPPEN]
Const KEY_UP = 200
Const KEY_DOWN = 208
Const KEY_LEFT = 203
Const KEY_RIGHT = 205


Spielerposition schonmal global machen, wenn wir schon am Anfang des Codes sind:
Code: [AUSKLAPPEN]
Global PlayerX, PlayerY


Okay, die Spielerbewegung ist dann ganz einfach. Wir bewegen den Spieler ja bloß von Tile zu Tile und müssen keine Pixelbrechberechnungen machen, drum einfach die Position um 1 erhöhen.
Code: [AUSKLAPPEN]
If KeyDown( KEY_UP )
  PlayerY = PlayerY - 1
Endif

If KeyDown( KEY_RIGHT )
  PlayerX = PlayerX + 1
EndIf

If KeyDown( KEY_DOWN )
  PlayerY = PlayerY + 1
EndIf

If KeyDown( KEY_LEFT )
  PlayerX = PlayerX - 1
Endif


Der Spieler läuft jetzt. Weil keine Begrenzung drin ist und das ganze in Tilesprüngen gemacht wird, flitzt er verdammt schnell auf der Karte umher. Aber mit einem beherzten Timer in der Hauptschleife oder eine schicken Animation später, dann geht das wohl.

Jetzt haben wir die Bewegung. Nun kommt die Abfrage. Nur für die etwas Planlosen unter uns noch einmal aufgeführt:
Über dem Spieler: y = PlayerY - 1
Unter dem Spieler: y = PlayerY + 1
Links vom Spieler: x = PlayerX - 1
Rechts vom Spieler: x = PlayerX + 1

Das sollte aber wirklich nicht nötig gewesen sein Wink

Nun fragen wir also mal schnell ab. Der abzufragende LAyer ist der dritte, hat also die Nummer "2" (man zählt ja von 0 an beim Programmieren und so). Also einfach nur den Wert (True oder 1, False oder 0) in eine temporäre Variable speichern.
Diese Abfrage muss VOR die Tastenabfragen!
Code: [AUSKLAPPEN]
;Werte (True/1 bzw. False/0) auslesen
KollisionOben = map( PlayerY - 1, PlayerX, 2 )
KollisionRechts = map( PlayerY, PlayerX + 1, 2 )
KollisionUnten = map( PlayerY + 1, PlayerX, 2 )
KollisionLinks = map( PlayerY, PlayerX - 1, 2 )


Damit haben wir die Tiles, die den Spieler direkt umgeben, abgefragt und deren Wert gespeichert. Jetzt kombinieren wir das ganze:

Code: [AUSKLAPPEN]
 If KeyDown( KEY_UP )
  If KollisionOben = False
    PlayerY = PlayerY - 1
  Endif
Endif

If KeyDown( KEY_RIGHT )
  If KollisionRechts = False
    PlayerX = PlayerX + 1
  EndIf
EndIf

If KeyDown( KEY_DOWN )
  If KollisionUnten = False
    PlayerY = PlayerY + 1
  EndIf
EndIf

If KeyDown( KEY_LEFT )
  If KollisionLinks = False
    PlayerX = PlayerX - 1
  EndIf
Endif


Damit wäre die Kollision Abgefragt.
Und somit eine Bewegung in die entsprechende Richtung geblockt!

Ihr könnt nun gegen Wände laufen - ganz offiziell! Smile

Ich hoffe es half einigen von euch vielleicht noch zu einem Einstieg, einem Geistesblitz oder sonstwas. Kommentare gern gesehen.

Extra für Fortgeschrittene - Kollision in einer Variable speichern

Mir persönlich wären die vier Variablen für Kollision oben, unten etc. zu blöd Smile Ich mache mir das leben schwer, mit BIT-OPERANDEN.
Das sind: And, Or und Xor.

Das Prinzip ist vereinfach folgendes:
Code: [AUSKLAPPEN]
;Wert zuweisen
a = 16

;Werte draufrechnen. 2 und 4 kommen auf unsere 16
b = a Or 2 Or 4

;Werte entfernen wenn vorhanden. Wenn nicht werden sie draufgerechnet, wie bei Or
c = a Xor 16

;Werte abfragen. Die Zahl enthält noch immer "2" und "4", die 16 ist jetzt raus. Gibt also einen Wert ungleich 0
d = c And 4


Vielleicht anfänglich etwas schwer zu verstehen und es liegt nicht an mir euch zu erklären wie das Prinzip geht, mit den 0en und 1en, den Bits, aber ich kann euch die Schritte rasch aufzählen. Eine genaue ERklärung gibt es auf www.blitzbase.de
Ihr nehmt 0 und 1 als Startwert und verdoppelt dann immer:
0, 1, 2, 4, 8, 16, 32, ...

Warum? Ganz einfach:
Addiert mal alle Werte bis VOR die 32, also 1+2+4+8+16. Das ergibt 31. Die nächste zahl ist 32.
Addiert mal alle Werte bis VOR die 8, also 1+2+4. Das ergibt 7.
Wir haben so Zahlen die man addieren kann und so die Abstände zwischen den einzelnen Stationen füllen.

Wozu der ganze Mist?

Ich wollte die Richtungen in EINER Variable speichern. Darum definiere ich 4 Konstanten am Anfang des Codes, die die merkmale der Bit-Schritte von oben aufweisen, also entsprechende Abstände haben:
Code: [AUSKLAPPEN]
Const OBEN = 1
Const RECHTS = 2
Const UNTEN = 4
Const LINKS = 8


Damit kann ich das auch besser veranschaulichen.
Gelten alle 4 Kollisionen, ist der Spieler also umzingelt, rechnen wir nach dem obigen Beispielen:
Code: [AUSKLAPPEN]
Umzingelt = OBEN Or RECHTS Or UNTEN Or LINKS

Das Ergebnis gleicht einer Addition: Es ist 15.

Ist der Spieler nun von Links und Rechts blockiert, wäre das LINKS Or RECHTS, ergibt 10. 10 ist eine Zahl, die von keiner Richtung verwendet wird (darum ja diese Bit-Schrittweite zwischen den Werten - damit sowas NICHT passiert). Man muss also nur prüfen, welche Zahlen in 10 rein passen ohne einen Restwert zu ergeben. Das sind eben nur RECHTS und LINKS. Alle anderen passen nicht genau.

Das ist das Prinzip der ganzen Geschichte. Hier also die Kollisionsabfrage mit Bits Smile

Code: [AUSKLAPPEN]
;Werte (True/1 bzw. False/0) auslesen
KollisionOben = map( PlayerY - 1, PlayerX, 2 )
KollisionRechts = map( PlayerY, PlayerX + 1, 2 )
KollisionUnten = map( PlayerY + 1, PlayerX )
KollisionLinks = map( PlayerY, PlayerX - 1 )

Kollision = 0 ;Zurücksetzen
If KollisionOben Then Kollision = Kollision Or OBEN
If KollisionRechts then Kollision = Kollision Or RECHTS
If KollisionUnten Then Kollision = Kollision Or UNTEN
If KollisionLinks Then Kollision = Kollision Or LINKS


Wir sparen keine einzige Zeile, ich weiß. Ist auch nur zum Veranschaulichen und ich dachte mir, dass es vielleicht ganz praktisch ist, wenn man das mal kurz anführt. Warum? Weil man so nicht nur die 4 Kollisonsrichtungen in einer Variable speichern könnte, sondern auch andere Informationen, wie z.B. ob dort ein Gegner steht (der einen dann in einen Kampf verwickelt etc).
Das macht dann aber nur Sinn, wenn man diese Informationen auf diese Art und Weise auch in der Map speichert. Um zusätzliche Layer zu sparen - ich benutze das Prinzip im Spiel "RUNEndemo", was ich für den 2D Contest gemacht habe, um Effekte in einer einzigen Variable zu speichern und die dann in die Map zu schreiben.

Jetzt prüfen wir aber erstmal, ob man damit kollidiert. Wir blockieren nicht mehr nach den tmeporären Variablen sondern mit einer Bit-Operation als Abfrage ("Abfragen" mit And, wie oben im Beispiel). Das muss dann aber in Klammern, weil BB sonst denkt dass wir zwei Bedingungen haben und nicht die Zahl "prüfen" wollen.

Code: [AUSKLAPPEN]
 If KeyDown( KEY_UP )
  If ( Kollision And OBEN ) = False
    PlayerY = PlayerY - 1
  Endif
Endif

If KeyDown( KEY_RIGHT )
  If ( Kollision And RECHTS ) = False
    PlayerX = PlayerX + 1
  EndIf
EndIf

If KeyDown( KEY_DOWN )
  If ( Kollision And UNTEN ) = False
    PlayerY = PlayerY + 1
  EndIf
EndIf

If KeyDown( KEY_LEFT )
  If ( Kollision And LINKS ) = False
    PlayerX = PlayerX - 1
  EndIf
Endif



Das müsste prächtig funktionieren Smile

Wie gesagt, eigentlich ist die Verwendung hierfür nicht so prall. Die temporären Variablen reichen vollkommen aus und lassen sich auch besser lesen. anwenden würde ich das dann eher so:
Code: [AUSKLAPPEN]
Const KOLLISION = 1
Const EFFEKT = 2
Const EFFEKTBLA = 4

Kollision_Aktiv = map( y, x, 2 ) And KOLLISION
Effekt_An = map( y, x, 2 ) And EFFEKT
Effektbla_An = map( y, x, 2 ) And EFFEKTBLA


Setzen kann man diese sogenannten "Flags" (hier: Eigenschaften für das Tile) mittels Xor ganz gut. Dann wird das nämlich immer an und ausgeschaltet, je nachdem.

So, das war's jetzt aber wirklich Smile


Update 2008-09-20
Ich hatte ursprünglich Y und X in der Definition und bei Abfragen von Werten aus dem "map"-Array vertauscht, muss wohl betrunken gewesen sein damals …
christian.tietze@gmail.com - https://christiantietze.de
macOS
  • Zuletzt bearbeitet von DivineDominion am Sa, Sep 20, 2008 22:10, insgesamt 2-mal bearbeitet
 

Blitzkrieg Bop

BeitragDo, Aug 19, 2004 14:03
Antworten mit Zitat
Benutzer-Profile anzeigen
Nicht komplett durchgelesen, aber sehr schön, das mal jemand sowas macht. Izewind's Tut's sind ja net so der Burner(vom Code her) Wink

*Edit:
Wie wäre es dann gleich mit ner kleinen Geschichte zum Scrolling? Dann wäre das sehr gut.
~ Hey Ho Let's Go ~

DivineDominion

BeitragSo, Jan 16, 2005 12:57
Antworten mit Zitat
Benutzer-Profile anzeigen
Teil 5 - Pixelweise Bewegung des Spielers

Es gibt Tage, da möchte man einfach mal ein Spiel bauen, bei dem man NICHT von Kachel zu Kachel springt.
Oben sah es so in etwa aus:
Code: [AUSKLAPPEN]

PlayerX = PlayerX + 1
;...
DrawImage Spieler, PlayerX * TILESIZE, PlayerY * TILESIZE


Das ist aber nun mal sehr weit hinter'm Mond heutzutage. Also sollte man die Bewegungen etwas weicher machen, nicht hüpfen sondern gehen!

Das Geheimnis ist eigentlich keins. Die meisten von euch tun es nämlich sowieso schon:
Code: [AUSKLAPPEN]
PlayerX = PlayerX + 2
;...
DrawImage Spieler, PlayerX, PlayerY


Die Position wird also nicht durch das "* TILESIZE" umgerechnet sondern bleibt Pixelgenau bestehen. Genau wie bei Mousebewegungen und sowas eben Smile

Die Kollision dann wieder zugreifen zu lassen ist dabei kein so schweres Stück Arbeit, wie manche denken.

Es wird die Position einfach wieder in Tiles umgerechnet, damit man mit den Werten wieder in dem map-Array arbeiten kann. Und das geht sehr fix folgendermaßen:
Code: [AUSKLAPPEN]
PlayerTileX = PlayerX / TILESIZE
PlayerTileY = PlayerY / TILESIZE


So. Schon fertig Smile

Was nun fehlt, ist die Kollision anders zu schreiben:
Code: [AUSKLAPPEN]
;Werte (True/1 bzw. False/0) auslesen
KollisionOben = map( PlayerTileY - 1, PlayerTileX, 2 )
KollisionRechts = map( PlayerTileY, PlayerTileX + 1, 2 )
KollisionUnten = map( PlayerTileY + 1, PlayerTileX, 2 )
KollisionLinks = map( PlayerTileY, PlayerTileX - 1, 2 )


Was ist anders? Eigentlich nur die Variablen, die wir nutzen, um auf das Array zuzugreifen. Mit PlayerX, dem Pixelwert, kann man nicht viel anfangen. Hat man eine 10x10 Map wäre die Größe bei TILESIZE=16 immerhin 160x160 Pixel! Wenn man jetzt den Spieler bewegt und PlayerX=10 ist, dann ist er sichtbar kaum bewegt. Er ist nicht einmal vom ersten Tile runter! Aber der Wert ist, da es eben Pixel sind, hoch genug um beim nächsten Schritt das Array zu sprengen.
Darum nutzt man nicht die Pixelposition in einem Tilearray.
christian.tietze@gmail.com - https://christiantietze.de
macOS

Rob_

BeitragMi, März 16, 2005 2:15
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi divine!

Ich hab dein Tut mal durch gearbeitet weil ich mit den JumpTut auf der robsite nicht klargekommen bin, Evil or Very Mad ich habe mir bei deinem mehr erhofft!
Ich habs ja extra gesucht! Und das ist dabei rausgekommen:

BlitzBasic: [AUSKLAPPEN]
Graphics 320,240,32,2
SetBuffer BackBuffer()
frame_blocker = CreateTimer(30)

tile_set = LoadAnimImage( \"tile_set.bmp\",16,16,0,19 )
player = LoadImage( \"player.bmp\" )

MaskImage tile_set,255,0,255
MaskImage player,255,0,255


Const tilesize = 16

Const map_width = 100
Const map_height = 14


Const key_up = 200
Const key_down = 208
Const key_left = 203
Const key_right = 205

Global player_x#, player_y#


Dim map( map_width, map_height, 2 )



While Not KeyHit(1)
WaitTimer ( frame_blocker )
Cls
ClsColor 0,50,200


collision_up = map( player_y - 1, player_x, 2 )
collision_right = map( player_y, player_x + 1 , 2 )
collision_down = map( player_y + 1, player_x, 2 )
collision_left = map( player_y, player_x - 1 , 2 )


If KeyDown( key_up )
If collision_up = False
player_y = player_y - .2
EndIf
EndIf

If KeyDown( key_right )
If collision_right = False
player_x = player_x + .2
EndIf
EndIf

If KeyDown( key_down )
If collision_down = False
player_y = player_y + .2
EndIf
EndIf

If KeyDown( key_left )
If collision_left = False
player_x = player_x - .2
EndIf
EndIf

For x = 0 To map_width
For y = 0 To map_height
DrawBlock tile_set, x * tilesize, y * tilesize, map( x, y, 0 )
Next
Next

For x = 0 To map_width
For y = 0 To map_height
DrawBlock tile_set, x * tilesize, y * tilesize, map( x, y, 1 )
Next
Next

DrawImage player, player_x * tilesize, player_y * tilesize

Flip
Wend
End


Aber ich kriege eine fehler meldung:

"Array index out of bounds"

und der gebugger zeigt mir hier drauf:

BlitzBasic: [AUSKLAPPEN]

collision_up = map( player_y - 1, player_x, 2 ) ; Hier fängt der halt an
collision_right = map( player_y, player_x + 1 , 2 )
collision_down = map( player_y + 1, player_x, 2 )
collision_left = map( player_y, player_x - 1 , 2 )


Wieso den? Ich hab mich schon gefreud das ich endlich ein gutes
Kollisions Tut für jumpinruns gefunden habe!
AMD Athlon 64 3500+ | Infineon 1 GB DDR RAM | nVidia Geforce 7800 GTX
 

Dreamora

BeitragMi, März 16, 2005 2:21
Antworten mit Zitat
Benutzer-Profile anzeigen
Das ist normal

Player_x und Player_y sind 0

-> -1 <0 was ein nicht erlaubter Array Index ist.

Musst also überprüfen ob +- 1 bei player_x und player_y erlaubte Werte sind und nur dann auslesen.
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.

otta

BeitragMi, März 30, 2005 22:03
Antworten mit Zitat
Benutzer-Profile anzeigen
hm...also irgendwie hab ich hier jetzt was nicht kapiert...!

Also die Frage die sich mir jetzt stellt ist folgende:

wenn ich jetzt meine tilemap da fertig hab und will den zweiten Layer drüber legen und dann dritten für die Kollisoionen, muss ich für jeden Lyer neue map dataen anlegen oder liesßt der die Daten aus dem einen map data abschnitt? Wenn ja dann Frag ich mich halt wie ich die "true/false" Werte für die map festlegen....



danke für die aufmerksamkeit!

Jan_

Ehemaliger Admin

BeitragDo, März 31, 2005 7:45
Antworten mit Zitat
Benutzer-Profile anzeigen
otta hat Folgendes geschrieben:
wenn ich jetzt meine tilemap da fertig hab und will den zweiten Layer drüber legen und dann dritten für die Kollisoionen, muss ich für jeden Lyer neue map dataen anlegen oder liesßt der die Daten aus dem einen map data abschnitt? Wenn ja dann Frag ich mich halt wie ich die "true/false" Werte für die map festlegen....


Ok, deine Frage ist etwas schwer verständlich.

Ich hoffe mal, ich kann dir Helfen,

Du legst in dem Arrey Map, ein 3Dimensionales Feld an.
Zitat:

Dim map( MAP_WIDTH, MAP_HEIGHT, Layer_anzahl-1 )

Und dann greifst du darauf zu.

BlitzBasic: [AUSKLAPPEN]

links_oben_im_3ten_Layer=map(0,0,2)


Man beachte, das 0 der 1. Layer ist
1 der 2. Layer und 2 der 3. Layer

nun, rechnen wir einen Layer für die Kollisionen dazu,
BlitzBasic: [AUSKLAPPEN]

Dim map( MAP_WIDTH, MAP_HEIGHT, Layer_anzahl-1+1 )

=
BlitzBasic: [AUSKLAPPEN]

Dim map( MAP_WIDTH, MAP_HEIGHT, Layer_anzahl)



so, nun wollen wir ja kollisionen eintragen:
BlitzBasic: [AUSKLAPPEN]

Print Int(True)
Print Int(False)


so, True und false sind allso nur 1 und 0.
--> wir können ne Menge dort in den Kollisionslayer eintragen z.B. Wasser, Wand ,....
BlitzBasic: [AUSKLAPPEN]

Const Kol_WAsser%=2,Kol_Wand%=1
map( 3, 14, Layer_anzahl) =Kol_Wasser%
map( 5, 14, Layer_anzahl) =Kol_Wand%
map( 6, 14, Layer_anzahl) =Kol_Wand%


Das liest du aber am besten aus einer Map datei, oder zur not ausm Datafeld.

Ich hoffe, ich konnte helfen.
between angels and insects

otta

BeitragDo, März 31, 2005 13:41
Antworten mit Zitat
Benutzer-Profile anzeigen
ja gut danke für die Hilfe trotz meiner umständlichen Fragestellung. Aber eine Frage um noch mal sicherzugehen, die Kollisions daten werden dann quasi in einem neuen Dim Feld eingetragen das dann einfach über das oder die beiden anderen drüber gelegt wird?!?

Jan_

Ehemaliger Admin

BeitragDo, März 31, 2005 14:52
Antworten mit Zitat
Benutzer-Profile anzeigen
Nein, ein Dim FEld, hat Belibig viele Dimensionen.
-->

du machst 2D, für den X,Y des Tiles.
und 3D, damit du noch mehrere Ebenen Speichern kannst.

So geht das:
Dim map(1D,2D,3D,4D,5D,6D)

darum brauchen wir 3D:
Dim map(breite,höhe,tiefe)

und die anderen Tiles
Werden dann in die Tiefe gespeichert, auch der Kollisionslayer

z.B.Wir wollen ein Tile, mit Gras, Zaun, und darüber Blätter eines Baumes. und wegen dem Zaun, die Kollisionen auf true.
Ich sage jetzt mal, der Kollisionslayer ist die nummer 5 in der Tiefe.

map(x,y,0)=Gras_image
map(x,y,1)=Zaun_image
map(x,y,2)=Blätter_image
map(x,y,5)=1; Für Kollisionen
between angels and insects

otta

BeitragDo, März 31, 2005 17:42
Antworten mit Zitat
Benutzer-Profile anzeigen
aahhh, ok jetzt ist mir das Licht aufgegangen, danke Very Happy !
AthlonXP 2800+, Radeon 9600XT,160GBHDD,512 MB DDR Ram (neuer Rechner neues Glück;))

Aktuelles Projekt:
momentan Projektlos
 

hc_tom

BeitragDi, Nov 08, 2005 23:53
Antworten mit Zitat
Benutzer-Profile anzeigen
hi bei mir funktioniert das mit der kollision nicht...

1) die layers sind alle korrekt daran kann es nicht liegen
2) es kann nur noch an der if-abfrage liegen, die kollisionspunkte berechnet er korrekt
3) ich habe mir überlegt, ob es nicht schon zu spät dafür ist, die kollision erst nach dem tastendruck zu prüfen, aber nach einer änderung, hat es auch nix gebracht
4) vielleicht sieht ein außenstehender den fehler eher, ich find ihn nicht.

danke Smile

BlitzBasic: [AUSKLAPPEN]
Include \"inc_scancodes.bb\"

Graphics 640,480,16,2

SetBuffer BackBuffer()

Global tile = LoadImage (\"img/tile.bmp\")
Global img_player = LoadImage (\"img/player.bmp\")

MaskImage tile,255,0,255
HandleImage img_player,0,0




Global player_x = 0
Global player_y = 0
Global player_dx = 1
Global player_dy = 1

Const TILE_HEIGHT = 32
Const TILE_WIDTH = 32

Const MAP_TILES_X = 20
Const MAP_TILES_Y = 15


Dim map (MAP_TILES_X,MAP_TILES_Y,1)

Restore mapdata
For y = 0 To MAP_TILES_Y - 1
For x = 0 To MAP_TILES_X -1
Read map(x,y,0)
Next
Next

;------------------------------------------------------------------------------

Repeat

Cls

If(player_x > 0 And player_y > 0) Then

kollision_oben = map(player_x, player_y - 1,1)
kollision_unten = map(player_x, player_y + 1,1)
kollision_rechts = map(player_x + 1, player_y,1)
kollision_links = map(player_x - 1, player_y,1)

EndIf

update_player()
draw_map()
draw_map2()
DrawImage img_player,player_x * TILE_WIDTH, player_y * TILE_HEIGHT


Text 0,0 ,\"k_oben:\"+kollision_oben

Flip

Until KeyHit(KeyEscape)

End

;--------------------------------------------------------------------------------

Function draw_map()

For y = 0 To MAP_TILES_Y - 1
For x = 0 To MAP_TILES_X - 1

If map(x,y,0) = 1 Then

DrawImage tile, x * TILE_WIDTH, y * TILE_HEIGHT
map(x,y,1) = 1

EndIf

Next
Next

End Function

Function draw_map2()

For y = 0 To MAP_TILES_Y - 1
For x = 0 To MAP_TILES_X - 1

If map(x,y,1) = 1 Then

Rect (x * TILE_WIDTH) + TILE_WIDTH / 2, y * (TILE_HEIGHT) + TILE_HEIGHT / 2, 5,5,1

EndIf

Next
Next

End Function

Function update_player()


If KeyHit(KeyArrowUp)=1 Then

If kollision_oben <> 1 Then
player_y = player_y - 1

EndIf

EndIf

If KeyHit(KeyArrowDown)=1 Then

If kollision_unten = 0 Then
player_y = (player_y) + 1
EndIf

EndIf

If KeyHit(KeyArrowLeft)=1 Then

If kollision_links = 0 Then
player_x = (player_x) - 1
EndIf

EndIf

If KeyHit(KeyArrowRight)=1 Then

If kollision_rechts = 0 Then
player_x = (player_x) + 1
EndIf


EndIf

End Function


.mapdata
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 0,3,1,1,1,2,0,0,0,0,0,0,0,0,3,1,1,1,2,0
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,3,1,1,1,2,0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 0,3,1,1,1,2,0,0,0,0,0,0,0,0,3,1,1,1,2,0
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1

Living Dead

BeitragFr, Nov 25, 2005 23:16
Antworten mit Zitat
Benutzer-Profile anzeigen
Jetz hätt ich aber auch mal ne Frage:
Also im Tutorial wurde die Map ja mit dem X Wert in der ersten Dimension und dem Y Wert in der zweiten Deklariert.
Nun steht da aber auch folgendes:
BlitzBasic: [AUSKLAPPEN]
;Werte (True/1 bzw. False/0) auslesen 
KollisionOben = map( PlayerY - 1, PlayerX, 2 )
KollisionRechts = map( PlayerY, PlayerX + 1, 2 )
KollisionUnten = map( PlayerY + 1, PlayerX, 2 )
KollisionLinks = map( PlayerY, PlayerX - 1, 2 )

Dabei wird in der ersten Dimension der Y-Wert des Spielers
verrechnet und in der zweiten der X-Wert. Wieso geht das und was bringt das Question ???
Das Leben ist der Weg.
Der Tod ist das Ziel.
 

Tanatos

BeitragFr, Sep 08, 2006 21:21
Antworten mit Zitat
Benutzer-Profile anzeigen
Habe es mal mit der Pixel by Pixel Bewegung + kollision versucht allerdings funktioniert das ganze ein wenig sonderbar... aber schaut es euch selbst am besten mal an:

Code: [AUSKLAPPEN]

Const XMAX=640
Const YMAX=480

Const ESC=1
Const AUF=200
Const AB=208
Const LINKS=203
Const RECHTS=205
Const TILESIZE=20

Global posx=2*20
Global posy=18*20

Dim map(19,19)
Restore level
For y=0 To 19
For x=0 To 19
Read map(x,y)
Next
Next


Graphics XMAX,YMAX,0,2
SetBuffer BackBuffer()


Repeat

drawmap()
moveplayer()


Flip
Cls
Until KeyHit(ESC)
End

Function moveplayer()
If KeyDown(AUF)    And map(posx/20,posy/20-1)=0 Then posy = posy - 1
If KeyDown(AB)     And map(posx/20,posy/20+1)=0 Then posy = posy + 1
If KeyDown(LINKS)  And map(posx/20-1,posy/20)=0 Then posx = posx - 1
If KeyDown(RECHTS) And map(posx/20+1,posy/20)=0 Then posx = posx + 1

Color 125,0,0 : Oval posx,posy,TILESIZE,TILESIZE
End Function

Function drawmap()
   For y=0 To 19
   For x=0 To 19
   If map(x,y)=0 Then Color 0,0,0 : Rect x*TILESIZE,y*TILESIZE,TILESIZE,TILESIZE
   If map(x,y)=1 Then Color 255,255,255 : Rect x*TILESIZE,y*TILESIZE,TILESIZE,TILESIZE
   Next
   Next
End Function


.level
Data 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,1
Data 1,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,1
Data 1,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,1,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,1
Data 1,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,1
Data 1,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,1
Data 1,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,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,0,1
Data 1,0,0,1,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,1
Data 1,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,1,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,1
Data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
 

Düsi

BeitragMo, Aug 11, 2008 12:25
Antworten mit Zitat
Benutzer-Profile anzeigen
So... auch wenn das nun schon etwas älter es, es ist ja noch immer ungeklärt. Smile

Damit die Collision so nicht klappen kann ist eigentlich klar.
user posted image

Die Position der Figur liegt oben links, wenn also diese ecke in ein freies Feld geht, die restliche Figur jedoch noch in einem CollisionsTile ist, denkt das Programm damit der Weg frei ist, da ja die Ecke mit der Position frei ist.

Demnach musste der Code so lauten:

Code: [AUSKLAPPEN]
Const XMAX=640
Const YMAX=480

Const ESC=1
Const AUF=200
Const AB=208
Const LINKS=203
Const RECHTS=205
Const TILESIZE=20

Global posx=2*20
Global posy=18*20

Dim map(19,19)
Restore level
For y=0 To 19
For x=0 To 19
Read map(x,y)
Next
Next


Graphics XMAX,YMAX,0,2
SetBuffer BackBuffer()


Repeat

drawmap()
moveplayer()


Flip
Cls
Until KeyHit(ESC)
End

Function moveplayer()
   Local TileX
   Local TileY
   Local TileX2
   Local TileY2
   
   If KeyDown(AUF) Then
      TileX = posx/TILESIZE
      TileY = posy/TILESIZE
      
      TileX2 = (posx+TILESIZE)/TILESIZE
      TileY2 = posy/TILESIZE
   ElseIf KeyDown(AB) Then
      TileX = posx/TILESIZE
      TileY = (posy+TILESIZE)/TILESIZE
      
      TileX2 = (posx+TILESIZE)/TILESIZE
      TileY2 = (posy+TILESIZE)/TILESIZE
   ElseIf KeyDown(LINKS) Then
      TileX = posx/TILESIZE
      TileY = posy/TILESIZE
      
      TileX2 = posx/TILESIZE
      TileY2 = (posy+TILESIZE)/TILESIZE
   ElseIf KeyDown(RECHTS)
      TileX = (posx+TILESIZE)/TILESIZE
      TileY = posy/TILESIZE
      
      TileX2 = (posx+TILESIZE)/TILESIZE
      TileY2 = (posy+TILESIZE)/TILESIZE
   EndIf   
      
      
   If KeyDown(AUF) Then
      If map(TileX, TileY) = 0 Then
         If map(TileX2, TileY2) = 0 Then
            posy = posy - 1
         EndIf
      EndIf
   ElseIf KeyDown(AB)
      If map(TileX, TileY) = 0 Then
         If map(TileX2, TileY2) = 0 Then
            posy = posy + 1
         EndIf
      EndIf
   ElseIf KeyDown(LINKS) Then
      If map(TileX, TileY) = 0 Then
         If map(TileX2, TileY2) = 0 Then
            posx = posx - 1
         EndIf
      EndIf
   ElseIf KeyDown(RECHTS) Then
      If map(TileX, TileY) = 0 Then
         If map(TileX2, TileY2) = 0 Then
            posx = posx + 1
         EndIf
      EndIf
   EndIf

   Color 125,0,0
   Oval posx,posy,TILESIZE,TILESIZE
End Function

Function drawmap()
   For y=0 To 19
   For x=0 To 19
   If map(x,y)=0 Then Color 0,0,0 : Rect x*TILESIZE,y*TILESIZE,TILESIZE,TILESIZE
   If map(x,y)=1 Then Color 255,255,255 : Rect x*TILESIZE,y*TILESIZE,TILESIZE,TILESIZE
   Next
   Next
End Function


.level
Data 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,1
Data 1,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,1
Data 1,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,1,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,1
Data 1,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,1
Data 1,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,1
Data 1,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,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,0,1
Data 1,0,0,1,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,1
Data 1,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,1,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,1
Data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1


Prüfen, ich welche Richtung man möchte und dann jeweils die Position der zwei ecken diese in diese Richtung liegen nehmen und diese dann auf eine Collision prüfen. Smile

MfG

BigPingu

BeitragMo, Aug 18, 2008 13:36
Antworten mit Zitat
Benutzer-Profile anzeigen
@Düsi
Leider kann man weder nach in keine Richtung wenn man eine Wand berührt nur in die entgegengesetzte.
Bsp: Man ist Links an einer wand, man kann nicht anch oben und nicht nach unten, nur nach rechts.
Meine Projekte:
Blockhead : 80%
VideoGameTycoon : 40%
 

Phlox

BeitragMo, Aug 18, 2008 14:13
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich hab eine Frage:
Wieso wird die ganze Map jedesmal neu gezeichnet? Man könnte ja nur die
animierten Teile neu zeichnen und den Rest als Image speichern.

DivineDominion

BeitragSa, Sep 20, 2008 22:32
Antworten mit Zitat
Benutzer-Profile anzeigen
@BigPingu/Düsi/Tanatos:
Ich habe BlitzBasic leider nicht mehr ohne weiteres zur Hand und kann das leider nicht testen. Mich wundert dein Ansatz auch etwas, Düsi, denn mir fiel eher folgendes auf:


Code: [AUSKLAPPEN]
If KeyDown(AUF)    And map(posx/20,posy/20-1)=0 Then posy = posy - 1


Einmal übersetzt in viele Variablen:


Code: [AUSKLAPPEN]

TileX = posx/20
TileY = posy/20
KollisionOben = False
If map(TileX, TileY - 1) > 0 Then KollisionOben = True

If KeyDown(AUF) And KollisionOben = False Then posy = posy - 1


Erst einmal wird die Position des Spielers in Tiles umgerechnet und dann wird im Tile darüber nachgeschaut, ob der Weg frei ist. Die Idee ist gut, nur: befindet sich der Spieler von Anfang an an "Y = 35", also an "TileY = 1", auf diesem Tile aber 15 Pixel unter dem oberen Rand, so kann er trotzdem nicht mehr hinauf gehen. Ich würde stattdessen beim Test bereits einen Pixel abziehen und diese zu testende Position in Tiles umrechnen (und so am Grenzpixel durch "(TestY=posy-1)/20" auf das Tile darüber kommen).

Ob das jetzt wirklich das Problem ist bzw. zur Lösung beiträgt – ich hoffe es einfach mal Very Happy



@Phlox

Deine Frage ist nicht unberechtigt. Diese Vorgehensweise ist bei zunehmender Mapgröße nicht sehr effizient. Wenn noch mehr Layer dazukommen, dann prost Mahlzeit. Fällt heute rechentechnisch zwar kaum auf, aber man verschenkt da am Ende wahrscheinlich nötige Ressourcen.

Stattdessen würde ich den Zeichenbereich auf den Bildschirm eingrenzen (ich nenne das mal "Viewport" oder auch Schaufenster, meine damit aber nicht den meiner Meinung nach völlig unnützen Befehl von BB!). Du kannst die Maße der Auflösung dafür ja hernehmen (ScreenWidth() und ScreenHeight(), wenn ich mich nicht irre) und durch TILE_SIZE teilen. Schon weißt du, wie viele Tiles auf den Bildschirm passen und kannst die Schleife entsprechend eingrenzen.

Eine Map, die größer ist als der Bildschirm, ist aber sowieso bloß sinnvoll, wenn du Scrollen kannst, sich also der Spieler bewegt und die "Kamera" (der Mittelpunkt des Viewports) ihn verfolgt. Dann musst du für die For-Schleifen beim zeichnen auch ScrollX/TILE_SIZE und ScrollY/TILE_SIZE als Startpunkt nehmen und die Bildschirmmaße aufaddieren, um den sichtbaren Bereich richtig einzugrenzen.

So. Dieses Ergebnis könntest du jetzt in einem großen Bild speichern. Das schon vorher ohne Grenzen zu tun, wäre keine gute Idee: würdest du die Map komplett in ein Bild malen, verschenkst du Ressourcen, und ein Riesenbild zu zeichnen dauert immer länger als nur so viel, wie auf den Monitor passt. Auch, wenn es viele viele kleine Tiles und Objekte sind.

Nur den aktuellen Bildschirmausschnitt zu speichern (was ja, wie wir uns geeinigt haben (Wink) besser ist, als die ganze Map) lohnt sich andererseits aber auch nicht: du weißt, dass der Spieler sich bewegen wird, die Map scrollen muss, der Bildschirmausschnitt (Viewport) sich verändert und du das Pufferbild also ständig aktualisieren müsstest, wenn gescrollt wird – dann, finde ich, lohnt sich das gar nicht erst. Durch ständiges Neumalen des Bildes verschenkst du bloß wieder Zeit: statt die Kleinteile auf den Monitor zu pinseln klatscht du erst alles in ein großes Bild und malst dann erst das sichtbar für den Spieler, malst also zwei mal die gleiche Fläche. Zu sagen "Okay, dann mach ich das nur, wenn sich der Spieler nicht bewegt" geht aber auch nicht: denn das wären meistens nur wenige Sekunden, wenn überhaupt, der Mehrwert sinkt also weiter.

Wo so eine Technik Anwendung finden könnte, das ist beim Hauptmenü, bei Einkauf-Menüs bei Rollenspielen o.ä.
christian.tietze@gmail.com - https://christiantietze.de
macOS

Dottakopf

BeitragFr, Jul 10, 2009 13:52
Antworten mit Zitat
Benutzer-Profile anzeigen
ist zwar schon älter, ...allerdings wurde die pixel by pixel bewegung hier letztendlich nicht "wirklich" bugfrei gezeigt/niedergeschrieben.

Daher möchte ich diesen Code posten:
Code: [AUSKLAPPEN]

;infos
;Verantwortlich für den kas= Dottakopf
;tile size = 32
;map size 12x12
;Pixel to Pixel bewegung


Graphics 800,600,16,2
SetBuffer BackBuffer()
timer = CreateTimer(60)


;globals
Global hero_px = 64
Global hero_py = 64
Global hero_speed = 2



;arry
Dim tile_map(20,20)
For y = 0 To 11
   For x = 0 To 11
      Read tile_map(x,y)
   Next
Next



;//////////////////////////////////////////////////// MAIN LOOP \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
Repeat
Cls


      draw_map()
      update_hero()


WaitTimer(timer)
Flip
Until KeyHit(1)
;//////////////////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\




Function update_hero()

      
         ;ermittelt welche umliegenden tiles der spieler besetzt
         ty1 = Floor(hero_py/Float(32)) ;tile abgerundet
         ty2 = Ceil(hero_py/Float(32))  ;tile aufgerundet
         
         tx1 = Floor(hero_px/Float(32)) ;tile abgerundet
         tx2 = Ceil(hero_px/Float(32))  ;tile aufgerundet
         
         

         ;OBEN
         If KeyDown(200) Then
            If tile_map( tx1 , (hero_py-hero_speed) /32) = 0 And  tile_map( tx2 , (hero_py-hero_speed) /32) = 0  Then
               hero_py = hero_py - hero_speed
            Else
               hero_py = hero_py + hero_speed 
               hero_py = (hero_py/32)*32
            End If      
         End If
         
         ;UNTEN
         If KeyDown(208) Then
            If tile_map( tx1 , (hero_py+hero_speed)/32+1) = 0 And  tile_map( tx2 , (hero_py+hero_speed)/32+1) = 0 Then
               hero_py = hero_py +hero_speed
            Else
               hero_py = hero_py - hero_speed
               hero_py = (hero_py/32+1)*32
            End If   
         End If
         
         ;links
         If KeyDown(203) Then
            If tile_map( (hero_px -hero_speed)/32 , ty1) = 0 And tile_map( (hero_px-hero_speed)/32 , ty2 ) = 0 Then
               hero_px = hero_px -hero_speed
            Else
               hero_px = hero_px+hero_speed
               hero_px = (hero_px/32)*32
            End If
         End If
         
         ;rechts
         If KeyDown(205) Then
            If tile_map( (hero_px+hero_speed  )/32+1 , ty1) = 0 And  tile_map( (hero_px+hero_speed)/32+1 , ty2 ) = 0
               hero_px = hero_px +hero_speed
            Else
               hero_px = hero_px - hero_speed
               hero_px = (hero_px/32+1)*32
            End If


         End If
         
         ;hero malen
         Color 0,0,255:Rect hero_px,hero_py,32,32,1

End Function
;----------------------------------------------------------------------------------------------------------------------------



Function draw_map()
   Color 200,200,200
   For x = 0 To 11
      For y = 0 To 11
         If tile_map(x,y)<>0 Then Rect x*32,y*32,32,32,tile_map(x,y)
      Next
   Next
End Function
;----------------------------------------------------------------------------------------------------------------------------



.level
Data 1,1,1,1,1,1,1,1,1,1,1,1
Data 1,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,1,0,0,1,0,0,0,1
Data 1,0,0,0,0,1,1,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,0,0,1
Data 1,0,0,0,0,0,0,0,0,1,0,1
Data 1,0,0,1,1,1,0,0,0,1,1,1
Data 1,0,0,0,0,1,0,0,0,1,0,1
Data 1,0,0,0,0,1,0,0,0,0,0,1
Data 1,1,1,1,1,1,1,1,1,1,1,1


Die Geschwindigkeit ist varriabel , allerdings geht das hin und wieder auf die kosten der Genauigkeit.

Bugs :
hero_speed = 3 mag er an engen druchgängen irgendwie nicht so richtig.
Schafft man es das der Spieler und das hinderniss sich genau an den Kanten berühren, springt der Spieler manchmal etwas seltsam.


Gruß
Dottakopf
Rechtschreibfehler gelten der allgemeinen Belustigung!

Neue Antwort erstellen


Übersicht BlitzBasic FAQ und Tutorials

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group