JnR mit Tiles, aber sauberem (Pixel) Scrolling



  • Hi Leute nun stehe ich da und habe keine Ahnung mehr.

    Ich möchte ein Jump´n Run Spiel proggen und mache gerade die Vorarbeit,
    (Pflichtenheft). Ich habe mich entschieden "Tiles" zu verwenden mit einer
    Matrix von 16x16 je Tile.

    Aber ich möchte gerne saubere bewegungen des Hintergrunds und der Figuren,
    und nicht das ganze um 16 Pixel springen lassen, mache ich das aber Pixelgenau,
    stimmen die Tiles-Matrixen nicht mehr pasgenau übereinander.

    Meine 1. Überlegung ist die Matrix auf 4x4 Pixel zu setzten dann wird es flüßiger,
    aber auch mehr Speicher.

    Meine 2. Überlegung, die Spielfigur als letztes rein zu Blitten und vorweg an
    desen Position das drunterliegende Rect mit der Spielfigur zu Vergelichen,
    Pixel für Pixel, und darauf zu Reagieren, als Leerraum wäre Schwarz (0,0,0),
    was ichauch für Colorkeying benutze um dort einen anderen Hintergrund durch-
    scheinen zu lassen, etc.
    Aber das ist zu Rechenintensiv.

    Hat jemand einen Vorschlag für (nahezu) saubere Bewegungen, aber einfacher Abfrage
    mittels Tiles und 2D-Arrays?

    gruß MiC++ha



  • tipp: man kann auch ein teiltile (xD) malen



  • Hmmmm, ja kann man aber das ist nicht die Richtung.

    Ich habe mir jetzt überlegt jedem Tile eine Mittelpunkt koordinate zu geben,
    diese ja einfach erechnet werden kann und je nach wichtung zum letzten oder
    nächsten Tile zu reagieren.
    Ich bin sogar am überlegen die Tile-Matrix auf 8x8 zu setzten, so würde für
    das Menschliche Auge eine nahezu Pixelgenaue abfrage ergeben, aber ich mach erst
    paar Test mit 16x16 und guck wie mein Auge das sieht, da bei 8x8 die Arrays
    schon viel Speicher fressen.

    Das Ausrechnen der pixelgenauen Position eines Tiles zwischen 2 anderen ist
    sehr einfach und geht schnell, somit halte ich das für die beste Lösung im
    Moment, oder hat jemand anderes eine bessere Idee, so bin ich für jeden
    Vorschlag offen.

    gruß MiC++ha



  • ich versteh zwar immernoch net dein problem, aber vielleicht hilft dir das ja:

    http://www.gamedev.net/reference/programming/features/gpgenesis8/



  • Das Problem ist die Abfrage der Tile-Koordinaten,
    eine Figur kann und soll am Rand eines Abgrund stehen können (z.B. X-Tile:21)
    geht es aber 1-2 Pixel Vorwärts, stürzt es ab, da ab dieser Position Tile:22
    gültig ist, mit anderen Worten geht es hier um Kolisionsabfragen bezogen auf
    der Laufebene, und dies sollte nahezu Pixelgenau sein.

    Aber ich habe schon eine gute Lösung mir überlegt, werde das mal überarbeiten
    und bissel Ausreifen und hier reinschreiben. Diese Lösung kann man dann auch
    für gewisse Game-Events und Effekte etc. Verwenden.

    gruß MiC++ha



  • sry ich verstehs immernoch net: was fürn abgrund? was hat die kollisionsabgrage mit scrolling zutun? Warum stürzt dein programm ab? Weil die Figur in nen abgrund geht? warum ist dann der abgrund nicht einfach unbegehbar? oO

    Erklär mal genau, wie du es bisher machst (wie wird figurpos gespeichert, wie kollision abgefragt, usw.) und wo da ein fehler auftaucht (z.b. bei deinem "abgrund" beispiel).

    edit: "Das Problem ist die Abfrage der Tile-Koordinaten" Von der Figur? tileX = Figur.x / 16; tileY = Figur.y / 16 😛
    Nun hat deine Figur die x Koordinate 351 --> tileX = 21
    Figur soll 1 pixel nach rechts gehn:
    --> zug möglich? --> neue koordinate wäre 352 --> tileX = 22 --> tilearray[tileX][tileY].begehbar --> false --> figur fällt net in abgrund
    xD



  • Genau das ist das Problem, ja so ist es richtig wie du es beschreibst, und
    gemacht habe ich noch gar nichts, es ist erst auf Papier.

    Nur bei dieser (üblichen?) Methode würde die Figur schon in den Abgrund fallen,
    obwohl er noch 8 Pixel Platz hat bei einer 16x16 Matrix und der Boden bis zur
    Mitte reicht bei diesem Tile, also muß das prog wissen was anbach ist.
    Beispiel:
    Alle Tiles mit gewissen Events sind gespeichert.
    Spieler steht auf Tile-Nr. 121, normaler Boden, geht nach rechts und nach der
    rechnung erscheint als Kol.-Tile der nächste mit z.B. der Nr. 212 und diesem
    Tile ist ein Event zugeordnet der Abgefragt wird, der giebt aus das er nach
    rechts noch 8 Pixel Platz hat bevor er fällt. und so weiter.
    Das ist meine bisherige Überlegung.

    Aber nochmal zum besseren Verständnis meiner Frage:
    Ich möchte Bewegungen und Abfragen nahezu Pixelgenau vollbringen, so das
    eine Spielerfigur auch am Rand eines Tiles stehen kann wenn der Rand in der
    Mitte des Tiles ist, ohne sofort zu stürtzen.
    Eine 1x1 Pixel Map würde Speicher fressen, daher tendiere ich auf 16x16, so in
    der Mitte des Üblichen, bei einer Auflösung von 640x480.
    Nun kommt die Spielfigur auf das nächste Tile und dies ist für jene Boden/Kolisions-
    Abfrage zuständig, aber was ist es und wie stehts mit der Balance zum vorherigem, kann er noch paar Pixel vor, wackelt er da er fast das
    Gleichgewicht verliert etc....? Ich denke sowas kann man mit einer Event-verarbeitung
    für gewisse Tiles am besten lösen.

    Darum ging es mir Hauptsächlich, bei Pixelgenauem Übergang von einem Tile zum anderen
    richtig und Pixelgenau zu reagieren. Meine Frage war Blöd gestellt.
    Denn wenn ich die Figur von Tile zu Tile springen lasse ist eine Abfrage immer
    Perfekt, aber nicht Pixelgenau und ruckelig.

    gruß MiC++ha



  • also dein abgrund ist kleiner als ein tile (daher das abgrundtile beinhaltet auch begehbare fläche)? Naja dann musste die Kollisionsabfrage irgendwie anderes machen. Z.b. könnteste noch ein Teilrechteck für das jeweilige tile definieren, dass festlegt wo ca. der abgrund ist und dann dies bei der kollision abfragen. Oder du machst ein Array, dass so groß ist wie der Bildschirm Pixel hat und vom typ bool ist und beinhaltet, welcher Pixel begehbar ist und welcher nicht 😉 Dann wärs Pixelgenau ~~



  • Siehe FAQ, 2D-Scrolling

    Bye, TGGC (Der Held ist zurück!)



  • TGGC schrieb:

    Siehe FAQ, 2D-Scrolling

    Bye, TGGC (Der Held ist zurück!)

    Bitte Thread lesen (nicht nur topic).



  • life schrieb:

    also dein abgrund ist kleiner als ein tile (daher das abgrundtile beinhaltet auch begehbare fläche)? Naja dann musste die Kollisionsabfrage irgendwie anderes machen. Z.b. könnteste noch ein Teilrechteck für das jeweilige tile definieren, dass festlegt wo ca. der abgrund ist und dann dies bei der kollision abfragen. Oder du machst ein Array, dass so groß ist wie der Bildschirm Pixel hat und vom typ bool ist und beinhaltet, welcher Pixel begehbar ist und welcher nicht 😉 Dann wärs Pixelgenau ~~

    Du könntest auch ne Maske erstellen, für jeden Tiletyp, dann setzt du für deinem Character zwei bis 3 Vertices fest, nun überprüfst du alle Vertices ob einer in der weißen Farbe der Maske ist. Wenn das dann bei 3 Vertices nur der vordere ist oder nur der hintere dann fällt er nicht, aber wenn 2 Vertices: vorne und in der mitte oder hinten und in der mitte frei liegen, schubst du den Chara nen bischen nach vorne so dass das aussieht als würde er kippen und er fällt bei 3 frei-liegenden dann runter....whaaaa....

    Wenn du das mit den Tiles so machst:

    for(int.....)
    {
      for(int....)
      {
         BlitTile(x,y);
      }
    }
    

    dann musst du einfach scrollen:

    for(int.....)
    {
      for(int....)
      {
         BlitTile(x-Cam.x,y-Cam.y);
      }
    }
    

    Normalerweise müssten dann keine übergänge oder sonstwas sein. 🙄

    Wenn das da oben alles falsch ist, liegt es daran das ich nicht weiß was JnR ist 😃



  • Timm schrieb:

    Du könntest auch ne Maske erstellen, für jeden Tiletyp, dann setzt du für deinem Character zwei bis 3 Vertices fest, nun überprüfst du alle Vertices ob einer in der weißen Farbe der Maske ist. Wenn das dann bei 3 Vertices nur der vordere ist oder nur der hintere dann fällt er nicht, aber wenn 2 Vertices: vorne und in der mitte oder hinten und in der mitte frei liegen, schubst du den Chara nen bischen nach vorne so dass das aussieht als würde er kippen und er fällt bei 3 frei-liegenden dann runter....whaaaa....

    entspricht ja dem boolarray, nur das bei dir false weiße Farbe ist und true schwarze Farbe 😛

    edit: aber am besten für jeden tiletyp nen eigenes 16x16 boolarray (spart memory xD)



  • Eure Ideen klingen nicht schlecht, aber leider nicht Optimiert.
    Zu viel Speicher etc.

    Also ich denke das mit dem Events für einige Tiles ist schon was und
    gut Ausbaufähig, da man z.B. dann auf einen Tile ein Schalter setzten kann
    der weiter hinten im Spielfeld eine Tür öffnet.

    Ich denke mir das so, ich habe z.B. 32 Tiles mit Events, von Absturz bis Schalter
    über Feuer und Laserwand etc.
    Gesamt habe ich 256 Tiles, die Event-Tiles setzte ich am Anfang von 0-31, der
    Rest dahinter.
    Liegt der Spieler mit ein paar Pixel auf ein Event-Tile wird dieser Verarbeitet
    und geprüft ob er z.B. schon am Rand des Abgrunds steht oder die Laserwand berührt.
    Wenn ja - Action.
    Dazu müßen für jedes Event Routinen aufgerufen werden, diese Stehen in einem
    Array[32], folglich also eine einfache Art ziemlich genau zu Handeln.

    Ich bin gestern hier mal auf ein Thread gestossen wo eine Spielfigur einen
    Berg oder Schräge hochlaufen soll, das ist dann auch einfach:
    Berg-Tile = Event-Tile, Event->gehe_auch_ein_pix_hoch()

    Die Sache ist nur die, und das war ja ansich auch meine Grundfrage, das die
    Tiles der Spielfigur nicht voll gefüllt sind, seine Füsse sind schmaler als
    sein Hip, der äussere Pixel seines Bauches kann als Abfrage bei einer Feuerwand
    dienen, aber nicht für einen Abgrund, denn da steht er noch am Rand, also
    werde ich mich am Mittelpunkt halten und von da aus die Position der Füsse,
    Bauch, Arme, Schädel etc.
    Es kann ja nicht sein das er in den Abgrund fällt weil er einen großen Sombreo-
    Hut aufhat 😉

    gruß MiC++ha

    PS:
    @life
    Ein Bool ist oft (oder immer) ein Byte groß, eine Schwarz/Weiß Bitmap kommt da
    :8 mal besser, also 1/8 an Speicher als ein Boolarray, gecheckt wird
    dann auf Bit-ebene. Wobei 0 = Leerraum wäre, 1 = da ist was (Boden,Wand). Aber
    in meinen Fall könnte ich mir das auch ersparen da ich die Farbe Schwarz RGB(0,0,0)
    als Leerraum verwende (Tranzparent, bzw. Colorkeying), so brauche ich stehts
    nur darauf zu testen, aber das wird komplizierter und Unübersichtlicher als mit
    Tiles und halt Events-Tiles.



  • mach wie dus für richtig hälst 😉

    btw. bool ist doch ein bit groß?! 0 oder 1 wofür brauch ich da ein byte? oO
    Außerdem willste ja deine bitmap auch irgendwie in dein programm laden und dafür brauchste dann mindestens genausoviel speicher 😉 Im Prinzip würd ich es so machen, dass ich eine bitmap mit der kollisionsinformation einlade und dann beim entsprechenden tiletyp (z.b. abgrund) als (static) bool array abspeicher. Selbst wenn du 100 unterschiedliche tiletypen gleichzeitig intialisiert haben müsstest, bräuchste dafür grademal 100*16^2 bits = 25600 bits = 3200bytes = 3,2kb. Also das ist lächerlich wenig memory auslastung 😉



  • life schrieb:

    mach wie dus für richtig hälst, aber wie willste abfragen wann das event ausgelöst wird?

    Wenn die Spielfigur nach rechts läuft so wird geprüft ob sich das rechts-äussere Tile
    sich um mind. 1pix auf ein Event-Tile befindet, und wenn ja ob dessen Bedinnungen
    erfüllt werden für eine Reaktion, also relativ einfach.

    life schrieb:

    btw. bool ist doch ein bit groß?! 0 oder 1 wofür brauch ich da ein byte? oO

    Eine Bool-Variable belegt einen Speicherbereich der Adressierbar sein muß,
    Logisch, da man aber nur Bytes Adressiert und nicht einzellne Bit´s, belegt
    es einen Byte. Anders gesagt, der kleinste Zugriff ist ein Byte mit seinem Inhalt.



  • Wenn die Spielfigur nach rechts läuft so wird geprüft ob sich das rechts-äussere Tile
    sich um mind. 1pix auf ein Event-Tile befindet, und wenn ja ob dessen Bedinnungen
    erfüllt werden für eine Reaktion, also relativ einfach.

    rechts-äussere tile? rechteck um die spielfigur? oO Also wie auch immer, wie willste die informationen abspeichern, wo der abgrund ist? Das muss doch in dein event-tile drinstehen und irgendwie muss die informartion auch gespeichert werden und da du es pixelgenau haben willst, kannste ja nicht einfach ein kollisionsrechteck angeben. Also wie willste das machen?

    Anders gesagt, der kleinste Zugriff ist ein Byte mit seinem Inhalt.

    und wie willste dann deine bitmap abspeichern? Oder willste jedesmal von festplatte lesen? Also da würd ich schon lieber die paar kb memoryverbrauch in kauf nehmen 😉


  • Mod

    bool operator[](unsigned int pt)
    {
        return m_Array[pt>>3]&(1<<(pt&3));
    }
    

    und schon hast du zugriff auf jedes einzelne bit (btw, es gibt auch assembler funktionen die einzelnen bits in die branchflags laden).

    rapso->greets();



  • @rapso
    Danke für die Antwort, aber wie ich mit Bit´s & Byte´s umzugehen habe weiß ich
    schon seit, ähhh, vielen Jahren.
    Hier gehts um eine vernünftige Positions-/Kolisionsabfrage die möglichst genau
    ist und so gut wie Pixel getreu.

    Fakt ist, das ich keine Zusätzliche Map brauche, ob Array oder Bitmap. Da die
    begehbare Ebene Schwarz RGB(0,0,0) als Freiraum, bzw. frei beweglicher
    Raum gildet, somit ist eine Kolisionsbitmap überflüssig.
    Und ich brauche keine Submaps für jedes Map sondern nur für die, wo es angebracht
    ist, also jene die ich mit Event-Tile beschimpfe. Dazu benötige ich aber auch nicht
    wieder eine Map sondern nur Parameter und Routinen.

    Ich will eine Spielebene von (Screen 640x480) 19.200 x 1.920 Pixel, Tiles sind
    16x16, also Tiles-Array[X=1200][Y=120] (~140KB bei 256 Tiles), die Tiles-Bitmap
    ist (True-Color) 192KB groß.
    Nun bewegt sich die Spielfigur, bestehend aus 3(X) x 5(Y) Tiles nach rechts, das
    Tile unten-rechts tritt mitt mind. einem Pixel das nächste Tile des Hintergrunds
    und dieses ist ein Event-Tile, nun prüfe ich anhand von gegebenen Parametern
    ob das ereignis des Event-tiles statt findet oder nicht.
    Durch die Klasse der spielfigur weiß die Event-Routine das das mittlere Tile
    der Spielfigur zuständig ist für z.B. den Abgrund, also wird nichts passieren
    ausser das mittlere Tile befindet sich auf diesem Event-Tile, wenn das dann so
    ist wird geprüft wie viele Pixel spielraum noch sind, bevor er stürtzt, ausser
    er springt (Steuerung) etc.

    Daher:
    Wenn Tile != EventTile -> weiter
    wenn Tile == EventTile -> Prüfe(Event Verarbeiten())
    etc.

    Also alles sogar einfach und Übersichtlich ohne zusätzliche Map´s oder so.
    Erst auf Tile checken und dann ob Event, wenn ja inns Detail gehen.

    gruß MiC++ha


Anmelden zum Antworten