amiga-news DEUTSCHE VERSION
.
Links| Forums| Comments| Report news
.
Chat| Polls| Newsticker| Archive
.

amiga-news.de Forum > Programmierung > Koordinatentransformation, Überdeckung [ - Search - New posts - Register - Login - ]

1 -2- 3 [ - Post reply - ]

2006-03-03, 00:07 h

whose
Posts: 2156
User
Zitat:
Original von Reth:

Dieser Aufbau gilt für alle Elemente, auch die Hintergrundtiles, die animiert sein können. Damit geht das ganze Konzept mit Tilearray usw. flöten!

Das ist das ganze Prinzip. Warum einfach, wenns auch kompliziert geht!?

Naja, bin ja selbst schuld!


Hm, machs Dir in Gedanken nicht komplizierter, als es eh schon ist ;)

Die Größe der Tiles ist gar nicht so entscheidend. Du kannst jederzeit die Berechnungen an neue Größen der Tiles anpassen. Abgesehen davon macht es aber auch nicht viel Sinn, die Tilegröße mitten im Spiel zu verändern, oder?

Die Animationen sind auch kein großes Problem. Das Spiel durchläuft ja verschiedene States, einer davon ist halt der "Zeichne den Kram"-State. Erst da kommen die jeweiligen Animationsframes eines Tiles zum Tragen. Wenn sich bei einem animierten Tile das Bild verändert, wird da halt ein Damage für eingetragen und gut. Je nach dem, ob Objekte auf diesem Tile stehen, wird u.U. ein Refresh der benachbarten Tiles benötigt, aber halt nur im Rahmen des ClipRects, welches die betroffenen Objekte samt animiertem Tile umschließt.

Grüße

--
---

:boing: µA1 PPC 750GX-800
:boing: A4000 PPC 604e-233

[ - Answer - Quote - Direct link - ]

2006-03-03, 00:14 h

Reth
Posts: 1858
User
Jetzt kam doch eine Antwort auf den von mir nun schon geänderten Beitrag.

Zitat:
Original von whose:
Zitat:
Original von Reth:
Hm, jetzt hab ich mein Hauptproblem (?) wieder entdeckt.
Ich habe meine Animationsklassen so entworfen, dass sie mit flexiblen Framegrößen umgehen können und ihre aktuelle Höhe und Breite kennen.
Es gibt dazu noch eine maximale Höhe und Breite.
Eine Animation kann aus beliebig vielen Frames mit unterschiedlichen Größen bestehen.

Das macht das Ganze nicht unbedingt leichter (im Hinblick auf Umsetzung von Pixelkoordinaten auf Arraykoordinaten).

Hm, muss ich mir nochmal reinziehen.


Nein, im Grunde ists auch dann genau das Gleiche. Du nimmst als Berechnungsgrundlage halt die dann aktuellen Größen (Position X/Y, Höhe und Breite des Animationsframes) und weißt, was so alles überdeckt wird davon.


Schon, aber durch die unterschiedlichen Framegrößen kann ich keinen einfachen Algorithmus für das Auffinden überdeckter Teile in einem Array hernehmen, da die Breite der Frames unterschiedlich ist und ich daher nicht mehr eine feste Zahl nehmen kann.

Zitat:
Unter anderem erfährst Du dann auch, ob dieses Objekt bereits in einem Damage-Bereich (ClipRect später!) liegt und ob es da noch ganz reinpaßt. Paßts nicht mehr ganz rein, ists an der Zeit, den Damage-Bereich zu vergößern

Nimm Dir dazu auch mal Michas, Thilos und meinen Rat zu Herzen, informier Dich über Sinn und Zweck von ClipRects. Wenn Du diese ClipRects in ihrer Größe so berechnest, daß alle Objekte auf ihren jeweiligen Positionen und in ihren aktuellen Größen da reinpassen, kannst Du für die Ermittlung der betroffenen Tiles (also die unterste Ebene!) sogar ganz simpel die ClipRect-Koordinaten nehmen.


Über ClipRects usw. hab ich schon diverses gelesen, auch etwas Code (aus Amiga intern und autodocs). Aber das Hauptproblem bleibt ja die Ermittlung von Überdeckungen, v.a. wenn die Hintergründe auch animiert sind.

Zitat:
Die Tiles müssen im Refresh dann ja als erstes gezeichnet werden und eben auch durch Clipping beim Zeichnen begrenzt werden, damit nicht am Refresh beteiligte Objekte unbehelligt bleiben.

Auf dieser Grundlage will ich ja auch aufbauen.
Hab mir das so gedacht: Ich unterscheide meine Objekte in statische und bewegliche.
Die beweglichen werden immer neu gezeichnet, nach den statischen.
Die statischen werden dann neu gezeichnet, wenn sie sich ändern.
Beide Objektarten sind mit Layern versehen, die in aufsteigender Reihenfogle gezeichnet werden.
So sollte es erst mal klappen. Wenn das mal tut, kann ich mich ans optimieren machen.
Oder ist das grundverkehrt?

Ciao

[ - Answer - Quote - Direct link - ]

2006-03-03, 00:44 h

Reth
Posts: 1858
User
So langsam entwickelt sich das zum Brainstorming meinerseits.

Ich hab das Gefühl, ich steh auf sämtlichen Schläuchen und wenn ich von einem runtergeh, tret ich auf 2 neue!

Also mal für die statischen Objekte gesprochen, die da Hintergrund oder Gebäude sein können in unterschiedlichen Layern.
Die Gebäude überdecken bis zu 3 Hintergrundobjekte. Ändert ein Gebäude seine Grafik, sind bis zu 3 Hintergrundobjekte betroffen. Diese gilt es zu finden und neu zu zeichnen. Davor wird eine ClipRegion in der Größe des Gebäudes angelegt, damit nicht andere Gebäude betroffen werden, wenn die Hintergründe neu gezeichnet werden. Da Hintergrund und Gebäude unterschiedliche Größen haben, wird es schwierig die Überdeckungen zu ermitteln. Mir fällt da nur ein die 4 Ecken des Gebäudes zu nehmen und überdeckte Hintergründe zu finden.

Finde alles gerade mords kompliziert aufgrunde des Systems, welches ich mir hier gebaut habe.

Ciao

[ - Answer - Quote - Direct link - ]

2006-03-03, 01:46 h

whose
Posts: 2156
User
Zitat:
Original von Reth:
So langsam entwickelt sich das zum Brainstorming meinerseits.

Ich hab das Gefühl, ich steh auf sämtlichen Schläuchen und wenn ich von einem runtergeh, tret ich auf 2 neue!

Also mal für die statischen Objekte gesprochen, die da Hintergrund oder Gebäude sein können in unterschiedlichen Layern.
Die Gebäude überdecken bis zu 3 Hintergrundobjekte. Ändert ein Gebäude seine Grafik, sind bis zu 3 Hintergrundobjekte betroffen. Diese gilt es zu finden und neu zu zeichnen. Davor wird eine ClipRegion in der Größe des Gebäudes angelegt, damit nicht andere Gebäude betroffen werden, wenn die Hintergründe neu gezeichnet werden. Da Hintergrund und Gebäude unterschiedliche Größen haben, wird es schwierig die Überdeckungen zu ermitteln. Mir fällt da nur ein die 4 Ecken des Gebäudes zu nehmen und überdeckte Hintergründe zu finden.


Genau, Du hasts im Grunde erfaßt. Und dabei spielt es keine Rolle, welche Größe z.B. das Gebäude aktuell hat, da Du diese Größe in die Berechnung der Überdeckung aktuell mit hinein nehmen kannst. Die Größen ändern sich ja nicht mitten im Zeichenvorgang sondern schon davor. Also kannst Du auch auf die Größen zurückgreifen bei der Berechnung, selbst für die Ermittlung des betroffenen Tiles. Statt fester Werte nimmst Du einfach die tatsächlichen Werte des Objekts.

Grüße

--
---

:boing: µA1 PPC 750GX-800
:boing: A4000 PPC 604e-233

[ - Answer - Quote - Direct link - ]

2006-03-03, 09:05 h

Reth
Posts: 1858
User
Zitat:
Original von whose:

Genau, Du hasts im Grunde erfaßt. Und dabei spielt es keine Rolle, welche Größe z.B. das Gebäude aktuell hat, da Du diese Größe in die Berechnung der Überdeckung aktuell mit hinein nehmen kannst. Die Größen ändern sich ja nicht mitten im Zeichenvorgang sondern schon davor. Also kannst Du auch auf die Größen zurückgreifen bei der Berechnung, selbst für die Ermittlung des betroffenen Tiles. Statt fester Werte nimmst Du einfach die tatsächlichen Werte des Objekts.

Grüße


Nur darin bestand glaub ich mein Performanceproblem, die Überdeckungen für jedes Objekt zu finden (rekursiv, wenn andere Objekte betroffen waren).
Ein Objekt kann ja ein darunterliegendes überdecken. Wenn es sich aber bewegt, muss ich auch die darüberliegenden berücksichtigen.
Darum hab ich die Layer eingeführt.
Nun brauch ich "nur" noch ne performante Methode, wie ich überdeckte Objekte in unterschiedlichen Layern finde.
Eine Suche über die Objektkoordinaten in einem Tilearray scheidet aus, da ja nicht nur die Hintergründe betroffen sind.

Zur Vereinfachung kann ich ja bei meinen 6-Ecken von ner festen Größe ausgehen, auch wenn sie mal mehrere Animationen und Frames haben. Da es keinen Sinn macht, die Tile-Größe während der Spielzeit zu ändern (zumindest seh ich keinen).

Ciao

[ Dieser Beitrag wurde von Reth am 03.03.2006 um 09:12 Uhr geändert. ]

[ - Answer - Quote - Direct link - ]

2006-03-03, 11:12 h

bubblebobble
Posts: 707
User
Also, du versucht schon bevor du irgendetwas zum laufen gebracht hast das ganze komplett zu optimieren, das geht immer schief.
Mach es, wie ich schon sagte, ganz einfach:

Schreibe eine Funktion drawTiles(x1,y1,x2,y2), die deinen Ausschnitt in einen nicht sichtbaren Rastport malt. Den Ausschnitt blittest du dann nach Beendigung des Zeichnens auf den Screen. Du bekommst dadurch überhaupt kein Problem mit rekusiven Überlappungen.

drawTiles sieht ungefähr so aus:

code:
/* rp ist der versteckte RastPort */
/* scr ist der sichtbare Screen, kann auch Window sein */

drawTiles (int x1,int y1, int x2, int y2) {
  struct Rectangle cliprectMinX = x1,y1,x2,y2;
  struct Region *new_region = NewRegion();

  /* Erzeuge eienen Clip auf den gewünschten Bereich*/
  LockLayer (0,rpLayer); // braucht man nur, wenn es ein Public Screen ist
  if (new_region) {
    if OrRectRegion (new_region, &cliprect) {
      old_region = InstallClipRegion(rpLayer, new_region); 
    }
  }

  /* ... StartTile, Höhe und Breite in Tiles des Rechtecks ermitteln */
  /* ... Tiles in einer verschachtelten For/ For Schleife malen ... */
  For (TileY = StartTile; Tile<StartTile+Höhe*MapBreite; Tile=Tile+MapBreite) {
    For (TileX = TileY; Tile<TileX+Breite; Tile++) {
       ... Hintergrund Tiles malen ...
       ... ggf. Objekte auf dem Tile malen wie Bäume, Mauern, Figuren, nach Hotspot sortiert ...
       ... bewegliche Objekte sollten auch auf dem Tile gespeichert sein,
           und müssen immer mitwandern wenn sie auf ein anderes Tile "treten",
           dafür wäre eine Linked List nicht schlecht pro Tile ...
    }
  }

  /* stelle den alten Clip wieder her... */
  new_region = InstallClipRegion(rpLayer, old_region); 
  if (new_region) DisposeRegion(new_region);
  UnlockLayer (rpLayer);

  /* Blitte das Rechteck auf den Screen */
  BltBitmapRastPort (rpBitmap,x1,y1,scrRastPort,x1,y1,x2,y2,$c);
}



Dann definierst du die eine DamageList, eine Liste mit Rechteck Regionen, die während des Game Loops zerstört werden, z.B. wenn eine Animation einen Frame weiter schaltet, oder wenn sich eine Figur fortbewegt, oder wenn gescrollt wird (einfach den neu hereingescrollten Bereich als damaged definieren), oder am Anfang einfach den ganzen Screen eintragen.

Die Tiles können ja auf deine Aminations Klassen zeigen, dadurch weisst du welches Bild gezeichnet werden muss. So lässt sich ganz einfach bewegtes Wasser machen etc.

In einzelnen Fällen ist das oben natürlich nicht optimal, weil z.B. ein Hintergund gezeichnet wird, der dann aber komplett wieder von einer Figur bedeckt wird oder so. Aber sowas passier nur bei kleinen Ausschnitten, und da ist die Speed egal, bei grossen Ausschnitten wirst du garantiert irgendwo bis auf die hinterste Ebene sehen können, und daher muss sie gezeichent werden.

Das oben ist sehr einfach und bei vielen Objekten sogar effizient.

Wenn du Objekte hast, die sehr hoch sind, sodass sie in andere Tiles hineinragen (z.B. Bäume), dann lässt du die äusserste For Schleife einfach noch eine oder zwei Tile Reihen tiefer laufen. Die nicht sichtbaren Tiles werden zwar versucht zu blitten, aber dank der ClipRegion sofort verworfen. Nur wenn z.B. ein Baum in die ClipRegion hineinragt, wird dieser Teil gezeichnet. Das gleiche kannst du bei Breiten Objekten mit der X Achse machen, ein Tile früher anfangen und ein Tile später aufhören. Das hört sich nach viel overhead an, ist es aber nicht, da es nur CPU Operationen sind. Ein einziger Blit auf die Graka verschlingt schon sehr viel mehr reale Zeit als ein paar Schleifen zu durchlaufen.

Nimm dir bitte die Zeit und schau dir das genau an. So funktioniert das was du machen willst!

--
Thilo Köhler, Author von:
HD-Rec, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, TKUnpacker
Homepage: http://www.hd-rec.de



[ Dieser Beitrag wurde von bubblebobble am 03.03.2006 um 11:23 Uhr geändert. ]

[ - Answer - Quote - Direct link - ]

2006-03-03, 11:56 h

Reth
Posts: 1858
User
@bubblebobble:

Danke, werd ich mir mal reinziehen.

Aber was bedeuten denn die / ?
Z.B. hier:

struct Rectangle cliprectMinX = x1,y1,x2,y2;

oder hier:

old_region = InstallClipRegion(rpLayer, new_region);

Eine Alternative?

[ - Answer - Quote - Direct link - ]

2006-03-03, 12:01 h

bubblebobble
Posts: 707
User
Hoppla! Das kommt vom vielen Amiblitz2 coden.

Das muss natürlich "." oder "->" sein in C, also

struct Rectangle cliprect.MinX = ...

Den Sourcode bitte nicht als syntaktisch korrekt ansehen, der ist nur als Pseudo Code gedacht, den habe ich nur einfach so zusammengeschrieben. Du musst das natürlich überarbeiten.

--
Thilo Köhler, Author von:
HD-Rec, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, TKUnpacker
Homepage: http://www.hd-rec.de


[ - Answer - Quote - Direct link - ]

2006-03-03, 12:05 h

whose
Posts: 2156
User
Zitat:
Original von Reth:
Nur darin bestand glaub ich mein Performanceproblem, die Überdeckungen für jedes Objekt zu finden (rekursiv, wenn andere Objekte betroffen waren).
Ein Objekt kann ja ein darunterliegendes überdecken. Wenn es sich aber bewegt, muss ich auch die darüberliegenden berücksichtigen.
Darum hab ich die Layer eingeführt.
Nun brauch ich "nur" noch ne performante Methode, wie ich überdeckte Objekte in unterschiedlichen Layern finde.
Eine Suche über die Objektkoordinaten in einem Tilearray scheidet aus, da ja nicht nur die Hintergründe betroffen sind.

Zur Vereinfachung kann ich ja bei meinen 6-Ecken von ner festen Größe ausgehen, auch wenn sie mal mehrere Animationen und Frames haben. Da es keinen Sinn macht, die Tile-Größe während der Spielzeit zu ändern (zumindest seh ich keinen).


Hm, evtl. solltest Du darüber nachdenken, den Tiles einen "Sonderstatus" in Deiner Klassenhierarchie zu verpassen. Im Grunde steht und fällt Dein Konzept über die Tiles. Wie ich das meine?

Ich hatte in einem der vorherigen Beiträge geschrieben, daß in Deinem Grafikaufbau die Veränderungen "weitergereicht" werden und sich dadurch der Domino-Effekt ergibt. Das geschieht durch die Tiles!

Im Grunde ists egal, ob ein Objekt ein anderes verdeckt oder nicht, denn die Objekte befinden sich alle zusammen auf einem Tile. Das bedeutet im Endeffekt, daß, wenn ein Tile betroffen ist, bis zu einem gewissen Grad auch alle Objekte auf diesem Tile von der Änderung betroffen sind.

Das "bis zu einem gewissen Grad" ist der Knackpunkt. Wenn ein Objekt auf einem Tile, welches eine Veränderung erfährt, sich nicht im Bereich der Veränderung befindet (also in der Damage Region), und sich selbst auch nicht verändert, braucht es auch nicht neu gezeichnet werden. Das Tile selbst wird ja mittels Clipping gezeichnet, also teilweise, nämlich nur in dem Bereich, wo eine Veränderung stattfindet.

Bei animierten Tiles kommst Du allerdings nicht darum herum, das gesamte Tile samt den darauf befindlichen Objekten neu zu zeichnen. Macht auch nix, denn dadurch erübrigt sich für die darauf befindlichen Objekte die Abfrage, ob die sich in der Damage befinden oder nicht (sie sind es auf jeden Fall). Ggf. sind angrenzende Tiles betroffen, diese werden dann aber, falls sie nicht auch animiert sind, per Clipping gezeichnet.

Eine weitere Vereinfachung wäre es, wenn Du im Tile-Objekt festhältst, ob sich andere Objekte darauf befinden. Wenn der Test nämlich kein weiteres Objekt ergibt, erübrigt sich auch die Abfrage, ob irgendwas im Bereich des Damage ist und neu gezeichnet werden muß.

Du brauchst also "nur", sobald ein Objekt eine Veränderung erfährt, den Bereich der Änderung ermitteln (Damage), schauen, welches Tile in diesem Bereich liegt (Koordinaten aufs Array abbilden) und davon ausgehend weitere Objekte ermitteln, die von der Damage betroffen sind. Dementsprechend vergrößert sich der Damage-Bereich.

Grüße

--
---

:boing: µA1 PPC 750GX-800
:boing: A4000 PPC 604e-233

[ - Answer - Quote - Direct link - ]

2006-03-03, 13:31 h

bubblebobble
Posts: 707
User
@whose
Ja, so ähnlich meinte ich das auch.
Also in der Damage List sind lediglich Rechtecke drin mit x1,y1,x2,y2, mehr nicht, die während dem Gameloop entstanden sind. Also keine Tiles oder Objekt Informationen.
Welche Tiles nun neu zu zeichnen sind kannst du dir dann ja in drawTile() berechnen, und wenn du alle Objekte an die Tiles hängst mittels einer Liste, dann weisst du auch sofort welche Objetke du neu zeichnen musst. Die Listwe sortiert du schon beim Einfügen nach der Y Koordinate, dann kannst du sie in einem Rutsch abarbeiten.

Du zeichnest dann immer stur alles neu. Das ist schon ok. Durch die ClipRegion zeichnest du von einem Tile, was nur zu einem Pixel in deine Fläche hineinragt auch nur ein Pixel, und das geht entsprechend schnell. Vertaue einfach auf das OS, das Clippen mit Layern macht das schon sehr flott. Einen Domino Effekt gibts dadurch nicht.
Scrollen ist dann auch kinderleicht.

--
Thilo Köhler, Author von:
HD-Rec, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, TKUnpacker
Homepage: http://www.hd-rec.de


[ - Answer - Quote - Direct link - ]

2006-03-03, 14:48 h

Reth
Posts: 1858
User
Ja so hab ich das ja auch immer gemeint.
Vor den Listen schrecke ich noch immer ein bischen zurück, da ein Objekt fast immer mehrere andere überdeckt und die Listen ständig umgebaut werden müssten.

Meine Objekte sind eh schon mit Layern versehen (z-Index) und da ich STL-Konstrukte verwende, kommen die automatisch richtig sortiert raus.

Zum Blitten werde ich in einem ersten Versuch immer die gesamte Objektgröße (ca. 30x50 bis 80x80 Pixel) nehmen, dann spar ich erstmal die Clippingberechnungen, die zu den Überdeckungsberechnungen ja noch dazukommen.

Ich muss "nur" ne möglichst performante Methode finden, meine Objekte einzuordnen, so dass sich überdeckende möglichst leicht finden lassen, ohne immer alle zu durchlaufen. Zu jedem Objekt aber ne Überdeckungsliste machen ist m.E. zu viel Aufwand!?
Eine Art der Sortierung ist auf alle Fälle der Layer, dann braucht man nur in den anderen zu suchen. Aber dann? Um Überdeckungen festzustellen, muss ich ja alle Objekte durchgehen. Wenn dann überdeckte gefunden werden, muss ich mit diesen wieder durchgehen. Letzteres kann ich umgehen, wenn ich die ClippingRegions setze (oder zumindest stark einschränken).

Ist ClipBlit eigentlich schneller als BltBitmap?

[ - Answer - Quote - Direct link - ]

2006-03-03, 15:03 h

bubblebobble
Posts: 707
User
Zitat:
Original von Reth:
Ja so hab ich das ja auch immer gemeint.
Vor den Listen schrecke ich noch immer ein bischen zurück, da ein Objekt fast immer mehrere andere überdeckt und die Listen ständig umgebaut werden müssten.

Die müssen nur umgebaut werden, wenn sich die verdeckung Ändert oder eine Figur in ein anderes Tile reinwandert. So gross ist der Aufwand nicht, bei Listen ist das ja einfach, nur Pointer verbiegen.
Oder dynamisch Array, wäre auch eine Lösung. Wenn die Listeneelemente klein sind, als z.B. nur ein Index auf das Objekt, wäre das vermutlich schneller.

Zitat:
Meine Objekte sind eh schon mit Layern versehen (z-Index) und da ich STL-Konstrukte verwende, kommen die automatisch richtig sortiert raus.
Wofür brauchst du einen Z Layer ? Die Y-Koordinate des Hotspots als Sortier- Kriterium reicht vollkommen.

Zitat:
Zum Blitten werde ich in einem ersten Versuch immer die gesamte Objektgröße (ca. 30x50 bis 80x80 Pixel) nehmen, dann spar ich erstmal die Clippingberechnungen, die zu den Überdeckungsberechnungen ja noch dazukommen.
Du must dich um das Clipping überhaut nicht kümmern. Durch InstallClipRegion wird das alles erledigt. Du blittest einfach alles wie du es gewohnt bist.

Zitat:
Ich muss "nur" ne möglichst performante Methode finden, meine Objekte einzuordnen, so dass sich überdeckende möglichst leicht finden lassen, ohne immer alle zu durchlaufen. Zu jedem Objekt aber ne Überdeckungsliste machen ist m.E. zu viel Aufwand!?
Eine Art der Sortierung ist auf alle Fälle der Layer, dann braucht man nur in den anderen zu suchen. Aber dann? Um Überdeckungen festzustellen, muss ich ja alle Objekte durchgehen. Wenn dann überdeckte gefunden werden, muss ich mit diesen wieder durchgehen. Letzteres kann ich umgehen, wenn ich die ClippingRegions setze (oder zumindest stark einschränken).

Ist ClipBlit eigentlich schneller als BltBitmap?

Nein.
Ich verstehe nicht ganz was du mit der Überdeckung hast. Schau dir doch nochmal meinen Code an, der zeichnet einfach alles neu, was in den Damage-Bereich hineinfällt. Das ist viel einfacher.
Die Listen die an den Tiles hängen müssen lediglich nach Y Koordinate sortiert sein, das ist alles.
Du musst dir keine Gedankten über Uberdeckung, Clipping oder sonstwas machen.

--
Thilo Köhler, Author von:
HD-Rec, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, TKUnpacker
Homepage: http://www.hd-rec.de


[ - Answer - Quote - Direct link - ]

2006-03-03, 17:29 h

whose
Posts: 2156
User
@Reth:

Ich denke mal, daß Dein eigentliches Problem dabei ist, daß Du noch nicht verstanden hast, daß ein Spiel dieser Art nur eine (wenn auch recht komplexe) State-machine ist. Es ist überhaupt nicht nötig, daß sich irgendein Objekt während der Bildberechnung in irgendeiner Art und Weise verändert. Alle Objekte haben während der Bildaufbereitung einen definierten Zustand. Und nur um diesen Zustand mußt Du Dich kümmern.

bubblebobble bringt es auf den Punkt: Bei Deinen Objekten ist die Y-Koordinate entscheidend, denn ein Turm "oben im Bild" kann einen Turm "unten im Bild" nie überdecken (zumindest ist es so logisch). Du beginnst mit der Ermittlung der Damage Regions oben im Bild und arbeitest Dich einfach nach unten durch. Ausgangspunkt kann das erste Tile sein, welches verändert werden muß oder das erste andere Objekt, welches eine Veränderung erfährt, falls ein Tile nicht geändert werden braucht, aber ein Objekt auf diesem Tile.

Bei den Tiles liegt der Fall klar, das Tile samt den darauf befindlichen Objekten gehören zu einer Damage Region und deren Größe wird durch alle betroffenen Objekte bestimmt. Da können u.U. Nachbartiles dran beteiligt sein, dazu aber später mehr.

Bei einem Objekt auf einem Tile ist es etwas komplizierter, aber auch nicht soooo kompliziert. Du ermittelst den Bereich, den das Objekt im Bild einnimmt. Das ist Deine aktuelle Damage Region. Dann prüfst Du, ob eins der Nachbartiles von der Veränderung betroffen ist (das können im Fall der Hextiles max. 3 Tiles sein, wenn Du die Objekte nicht zu groß wählst). Wenn nein, brauchst Du nur das ClipRect für dieses Objekt setzen. Als nächstes prüfst Du, ob eins der Objekte auf dem Tile ebenfalls von der Änderung betroffen ist. Wenn ja, erweiterst Du die Damage Region zusätzlich auf dieses Objekt. Nun prüfst Du nochmal, ob ggf. ein Nachbartile in Mitleidenschaft gezogen wird. Wenn nein und alle Objekte auf dem gerade untersuchten Tile abgearbeitet sind, trägst Du Tile sowie alle Objekte nach Layer/Y-Koordinate in eine Zeichenliste ein, die dann abgearbeitet wird.

Du kannst es Dir aber auch noch einfacher machen: Da Du für die Basis jedes Objekts von der linken, unteren Ecke ausgehst, arbeitest Du von Oben nach unten und von rechts nach links. Wenn Du mit Maske blittest, kannst Du platt nach dieser Reihenfolge zeichnen, eine Überdeckungsermittlung ist dann hinfällig, weil sich die korrekte Überdeckung quasi von selbst ergibt. Du solltest nur darauf achten, daß es keine Überdeckungen "nach links" oder "nach oben" gibt, sonst müßtest Du Tiles "im Vorlauf" bearbeiten, damit das linke/obere Nachbar-Tile keins der aktuellen Objekte überzeichnet (das Abschneide-Problem). Durch Verwendung von Clipping kannst Du Dir auch das komplett neu Zeichnen von den rechten Nachbar-Tiles ersparen, sofern dort keine Objekte betroffen sind. Sind Objekte darauf betroffen, mußt Du durch das Clipping aber auch nur das Tile und die betroffenen Objekte neu zeichen, nicht das Tile und alle darauf befindlichen Objekte (Damage Region!). Das spart ein paar Blits.

Grüße

Nachtrag: Wenn Du mit zwei kompletten Puffern arbeitest, mußt Du noch nicht einmal die rechten Nachbartiles teilweise neu blitten, es reicht dann völlig, das korrekte ClipRect im unsichtbaren Puffer aufzusetzen und dann die Objekte innerhalb dieses Rechtecks incl. Tile neu zu zeichnen.

--
---

:boing: µA1 PPC 750GX-800
:boing: A4000 PPC 604e-233


[ Dieser Beitrag wurde von whose am 03.03.2006 um 17:39 Uhr geändert. ]

[ Dieser Beitrag wurde von whose am 03.03.2006 um 17:54 Uhr geändert. ]

[ - Answer - Quote - Direct link - ]

2006-03-03, 18:41 h

bubblebobble
Posts: 707
User
@whose
Auch deine Erklärung/Methode finde ich noch recht kompliziert.
Die DamageRegion muss überhaut nicht "berechnet" oder "überprüft" werden. Die ist doch vorgegeben durch die Objekte, die sich bewegen oder animiert sind.

Gehe so vor:

Also im Gameloop wird erstmal gar nichts gezeichnet.
Es werden nur die neuen Koordinaten z.B. des Spielers berechnet und Animationsstufen weitergeschaltet. Dabei fügt man in die DamageList alle Rechteckigen Bereiche ein, die sich geändert haben, also das alte Rechteck des Spielers, das neue Rechteck des Spielers, das alte Rechteck einer Animation und das neue Rechteck der jetzigen Anim Stufe(falls es anders ist).
Optimierung:
Dabei kann man natürlich überlappende Rechtecke gleich zu einem zusammenfassen, was bei einem sich nicht allzuschnell bewegenden Objekt praktisch immer der Fall ist. (aber auch das kann später kommen).

Wenn der Gameloop fertig ist, also alle Objekte ihren Schritt ausgeführt haben, zeichnest du einfach alle rechteckigen Bereiche aus der DamageList pixelgenau neu mit dem drawTile(). Wenn alle Objekte auf einem Tile nach Y-Koo sortiert sind, kannst du die einfach der Reihe nach malen.

Du musst keine Hintergründe retten, keine Z -layer machen, keine Listen grossartig umschieben, Überlappungen prüfen oder sonstwas.

Dadurch, dass du nur den rechteckigen Bereich, der sich geändert hat, neu malst und eine ClipRegion drumherum legst, brauchst du nichts rekusiv überprüfen etc.

Ich glaube ich muss mal ein Tutorial darüber schreiben ... ;-)


--
Thilo Köhler, Author von:
HD-Rec, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, TKUnpacker
Homepage: http://www.hd-rec.de


[ - Answer - Quote - Direct link - ]

2006-03-03, 19:24 h

whose
Posts: 2156
User
@bubblebobble:

Die Methode haut nur dann hin, wenn Du das komplette Bild neu aufbaust. Genau das wollen wir aber nicht. Was passiert denn, wenn einer der Türme, die in ein anderes Tile hineinragen, einen neuen Status für seine Animation bekommt? Das Tile darüber muß neu gezeichnet werden, die Türme, die ggf. darauf sind aber auch, wenn sie zum Teil von der Animation überdeckt werden. Diese Türme müssen sich ja nicht unbedingt verändern, werden aber "nachträglich" von einer Änderung betroffen. Sähe sonst etwas seltsam aus, wenn Teile des alten Anim-Frames stehen bleiben, oder? Da kommst Du um eine kleine Rekursion bei der Erstellung der Damage Regions nicht herum (auf das Tile drüber und rechts vom aktuellen begrenzt). Das Zeichnen an sich ist kein großes Problem, fein von oben nach unten/rechts nach links.

Das in eine Klassenhierarchie zu fassen, ist bestimmt nicht ganz so simpel wie funktional zu arbeiten wie in AB2 oder C.

Grüße

--
---

:boing: µA1 PPC 750GX-800
:boing: A4000 PPC 604e-233


[ Dieser Beitrag wurde von whose am 03.03.2006 um 20:08 Uhr geändert. ]

[ - Answer - Quote - Direct link - ]

2006-03-03, 20:12 h

bubblebobble
Posts: 707
User
@whose

Nein, da verstehen wir uns etwas falsch.

Eine DamageRegion wird bei mir in Pixeln gemessen (Bildschirm oder Playfield Koordinaten), nicht in Tiles.
Ich markiere keine Tiles sondern direkt die Bildschirmkoordinaten, die neu gezeichnet werden müssen, daher meine Funktion drawTiles().

Wenn ein Turm in ein oberes Tile hineinragt, und sich neu zeichnen muss, dann wird selbstversändlich auch das obere Tile neu geblittet, aber dank ClipRegion eben nur der Teil, der innerhalb des Turm-Bildes ist. Ich blitte nicht das ganze Tile, sondern möglicherweise nur ein paar Pixel davon. Dadurch muss ich auch nicht gucken, was durch dieses Tile wiederum beeinflusst wird, keine Rekursion mölglich. Alles was sich verändert liegt ja in meinem x1,y2,x2,y2 Pixel-Bereich.
Und der wird im Game Loop ermittelt, indem ich z.B. das Turm Bildchen imaginär "blitte", in wirklickeit wird einfach ein eintrag in die DamageList gemacht, die Abmessungen und Zielkoordinaten des Bildes kenne ich ja.

Ich denke diese Arbeitsweise hat nichts mit der Programmiersprache zu tun. Das lässt sich genauso auch in C++ machen.
(wobei angemerkt sei, dass ich C++ in diesem Fall für einen Kropf halte).


--
Thilo Köhler, Author von:
HD-Rec, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, TKUnpacker
Homepage: http://www.hd-rec.de


[ - Answer - Quote - Direct link - ]

2006-03-03, 20:27 h

whose
Posts: 2156
User
Zitat:
Original von bubblebobble:
@whose

Nein, da verstehen wir uns etwas falsch.

Eine DamageRegion wird bei mir in Pixeln gemessen (Bildschirm oder Playfield Koordinaten), nicht in Tiles.
Ich markiere keine Tiles sondern direkt die Bildschirmkoordinaten, die neu gezeichnet werden müssen, daher meine Funktion drawTiles().


Ja, das habe ich schon richtig verstanden. Allerdings meinte ich mit Tiles, daß man ermitteln muß, welches Tile aus dem Array zum neu Zeichnen hergenommen werden muß. Da auch nur Nachbartiles davon beeinflußt werden können, ist es eigentlich einfacher, das Tile-Array als Aufhänger zu nehmen. Darüber lassen sich auch die Türme einfacher verwalten in einer Objekthierarchie.

Zitat:
Wenn ein Turm in ein oberes Tile hineinragt, und sich neu zeichnen muss, dann wird selbstversändlich auch das obere Tile neu geblittet, aber dank ClipRegion eben nur der Teil, der innerhalb des Turm-Bildes ist. Ich blitte nicht das ganze Tile, sondern möglicherweise nur ein paar Pixel davon. Dadurch muss ich auch nicht gucken, was durch dieses Tile wiederum beeinflusst wird, keine Rekursion mölglich. Alles was sich verändert liegt ja in meinem x1,y2,x2,y2 Pixel-Bereich.

Das eigentliche Problem ist, daß nicht nur das Tile überdeckt werden kann sondern ggf. auch eigentlich nicht in der Damage Region erfaßte Türme (weil diese sich ggf. nicht verändern müssen) "nachträglich" in Mitleidenschaft gezogen werden können. Da gibts also auch die Möglichkeit, daß zusätzlich noch ein oder mehrere Türme überdeckt werden. Die müssen dann auch erst einmal ermittelt und zur bisherigen Damage Region hinzugenommen werden. In blöden Konstellationen kann das dazu führen, daß auch noch einmal die Objekte des Tiles über/rechts vom aktuellen Tile untersucht werden müssen. Das Tile innerhalb der gerade ermittelten Damage Region muß eh neu gezeichnet werden, deswegen nehme ich auch als Hilfsmittel die Tile-Basis an. Damit spart man sich ewig lange Koordinaten-Ermittlung von Objekten, ob die sich in der Damage-Region befinden. Es können max. das Tile darüber und das rechts vom gerade in der Damage-Region erfaßten Tile beeinflußt werden, allerdings auch Objekte auf diesen.

Zitat:
Ich denke diese Arbeitsweise hat nichts mit der Programmiersprache zu tun. Das lässt sich genauso auch in C++ machen.
(wobei angemerkt sei, dass ich C++ in diesem Fall für einen Kropf halte).


Das isn anderes Thema ;)

Grüße



--
---

:boing: µA1 PPC 750GX-800
:boing: A4000 PPC 604e-233

[ - Answer - Quote - Direct link - ]

2006-03-03, 20:51 h

bubblebobble
Posts: 707
User
Ok, ich hab ein kleines Bild vorbereitet:

Bild: http://www.hd-rec.de/pics/RefreshISO.png

Das blau umrandete ist ein Rechteck, was in die DamageList eingetragen wird, weil sich der Spieler bewegt hat.

Nach dem Gameloop ist die DamageList voll von solchen Rechtecken, wobei überlappende zusammengefügt werden können. Dadruch wird nichts doppelt gezeichnet.

Jetzt muss einfach nur dieses Rechteck neu gezeichnet werden.
Dafür werden die drei Tiles (ok, eins ist nur ganz wenig mit drin)
komplett neu gezeichnet. Das macht aber nichts, weil die Clipregion, die vorher über das blaue Rechteck gelegt wurde, das meiste abclippt, und die Blitts sehr schnell sind. Der grüne Orb neben dem Spieler würde z.B. komplett verworfen, aber wir blitten ihn, als wenn er da wäre. Also egal was passiert, man braucht nur eine einzige Funktion zum malen.
z.B. das Haus wird auch neu geblittet, dank CliRegion wird aber der Baum nicht zerstört, muss also nicht neu gezeichnet werden, das meintest du doch mit rekusiv gucken, was man noch wiederherstellen muss.

Man würde also alle Tiles ermitteln, die in das Rechteck fallen, und einfach alles neu zeichnen.Natürlich könnte ein weiterer Baum auf dem untern Tile z.B. den Haustür zerstören, aber wegen der ClipRegion passiert das nicht.

Würde ein Baum weiter unten in das Rechteck hineinragen, hätten wir allerdings ein problem. Deshalb kann man die For schleife einfach noch eine Tile Zeile (oder mehr, wenn es höhere Objekte gibt) weiterlaufen lassen. Blitts, die nicht in der ClipRegion liegen, verbrauchen so gut wie keine Rechenzeit.Und das bisschen For Schleife ist auch kein Problem.

So ähnlich funktioniert z.B. AsteroidsTR, und das ist doch recht performant, oder?

--
Thilo Köhler, Author von:
HD-Rec, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, TKUnpacker
Homepage: http://www.hd-rec.de


[ - Answer - Quote - Direct link - ]

2006-03-03, 21:32 h

whose
Posts: 2156
User
Zitat:
Original von bubblebobble:

Würde ein Baum weiter unten in das Rechteck hineinragen, hätten wir allerdings ein problem. Deshalb kann man die For schleife einfach noch eine Tile Zeile (oder mehr, wenn es höhere Objekte gibt) weiterlaufen lassen. Blitts, die nicht in der ClipRegion liegen, verbrauchen so gut wie keine Rechenzeit.Und das bisschen For Schleife ist auch kein Problem.


Jap, das meinte ich mit "kleiner Rekursion". Um da möglichen Bockmist zu vermeiden, müssen wir uns bei Reths Hextiles noch jeweils einmal das Tile darüber und das rechts daneben ansehen, ob ggf. eigentlich unbeteiligte Türme darauf von unserer aktuellen Damage Region erfaßt werden und somit "dazuaddiert" werden müssen, selbst wenn diese Türme sich eigentlich nicht verändern.

Das praktische dabei ist, daß das eben pro Tile, welches unter der aktuellen Damage Region liegt, nur auf die beiden Nachbartiles darüber/rechts davon zutreffen kann, sofern er keine Überdeckungen nach links/unten zuläßt.

Sobald er das doch macht, sind alle Tiles im Umkreis um die Damage Region potentielle Kandidaten für eine Untersuchung, da man nicht voraussagen kann, welche Objekte links/unterhalb betroffen sein könnten, auch wenn sie selbst sich eigentlich nicht verändern.

Die Vorgehensweise von oben nach unten/von rechts nach links bleibt dabei voll erhalten, es ist "nur" jeweils eine Überprüfung nach Oben/Rechts im Nachlauf sowie eine nach Unten/Links im Vorlauf fällig. Dabei kanns aber wieder passieren, daß fast das gesamte Bild neu aufgebaut werden muß, nur weil sich einige wenige Objekte verändern...

Ich würde sagen, Reth sollte die Grafik ein wenig einschränken, was die Überdeckungsmöglichkeiten betrifft. Überdeckung nach links/unten könnte sich da tödlich auswirken, Überdeckung nach rechts/oben ist eigentlich ausreichend, auch für animierte Tiles. Da müßte er dann die Grafik entsprechend anpassen, so daß z.B. sich im lauen Lüftchen wiegende Weizenfelder nicht auf die Tiles links auswirken. Das sollte eigentlich kein Problem sein.

Grüße

--
---

:boing: µA1 PPC 750GX-800
:boing: A4000 PPC 604e-233

[ - Answer - Quote - Direct link - ]

2006-03-05, 00:06 h

Reth
Posts: 1858
User
Hey, hier gehts ja richtig rund!

Danke für eure Beiträge!

@bubblebobble

Das mit dem z-Index (Layer) stellst Du Dir zu kompliziert vor, ist genauso einfach wie Deine Y-HotSpots, es wird einfach ein int-Wert gesetzt.

@whose
Beim Erstellen meines Spielfeldes werden die 6-Ecke in einer Managerklasse so einsortiert, dass jedes 6-Eck seine Nachbarn zugeordnet bekommt, daher ist während der gesamten Spielzeit die 6-Eck Anordnung bekannt.

Zusätzlich hab ich derzeit eh schon einen Algorithmus, der ein 6-Eck zu einer X,y Koordinate ermittelt (noch bevor ich gamedev.net kannte), der mir das 6-Eck zu einem Turm ermittelt (damit auch dessen Nachbarn), damit der Turm die richtigen Resourcen zugeordnet bekommt.

Aus diesen beiden Mechanismen müsste es ja möglich sein, eure Vorschläge umzusetzen. Einerseits Objekte, welche 6-Ecke überdecken in Listen über diese einzutragen, andererseits bei der Änderung von Objekten die 6-Ecke und deren betroffene Nachbarn zu entdecken.
Muss halt meinen Code umbauen, da die 6-Ecke und Türme z.B. derzeit noch z.T. von den Grafiken entkoppelt sind.

Ciao

[ - Answer - Quote - Direct link - ]

2006-03-05, 12:28 h

bubblebobble
Posts: 707
User
Interessant wäre da noch der Ansatz eines Z-Buffers, wie man es in richtigen 3D Berechnungen hat. Dafür müsstest du dir aber einen extra Blit Befehl schreiben.
Beim Z-Buffer blittest du nicht nur auf das sichtbare Bild, sondern auch noch deine Maske in den sog. Z-Buffer, mit jeweils der Z Koordinate pro Pixel. Blitte ich das zweite Bild, werden nur Pixel geblittet, deren Z Koordinate weiter vorne liegen, und auch dort der Z-Buffer neu gesetzt. Am Ende hast du im Z Buffer quasi ein Tiefen Bild.
Aber ich denke das wäre hier übertrieben und nicht so performant, obwohl man dann tatsächlich keine Pixel redundant setzen muss.
Schwierig wird es allerdings, wenn man, wie ich, Alpha Channels benutzt, denn dann gibt es Pixel, die u.U. die Information von ALLEN übereinander geblitteten Objekten brauchen, um die korrekte Farbe zusammen zu mischen.

--
Thilo Köhler, Author von:
HD-Rec, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, TKUnpacker
Homepage: http://www.hd-rec.de


[ - Answer - Quote - Direct link - ]

2006-03-05, 13:46 h

Reth
Posts: 1858
User
@bubblebobble:

Hm, Alpha-Channel wäre für mich auch mal interessant. Momentan erreiche ich "Transparenz", in dem ich z.B. bei den Turm-Cursors nur jedes 2. Pixel setze.

Wieso meinst Du eigentlich, dass C++ hier ein Kropf wäre (bin gern für Argumente offen)? Ich finde sogar, es bietet sich hier an, da man für alles seine Objekte mit ihrem Verhalten definieren kann.
Man muss nur die API des AmigaOS halbwegs gut unterbringen.
Das, was mir glaub derzeit selbst ein wenig im Weg steht ist meine alte Klassenaufteilung.
Habe eine Klasse, die alles im Umgang mit den 6-Ecken macht: Einsortieren, Auffinden, Ecken finden, NAchbarn finden etc. Das alles aber losgelöst von der Grafik, da mein erster Grafikansatz so aussah:
Eine Managerklasse kümmert sich um die Animationen, welche selbst entscheiden, wann sie neu gezeichnet werden müssen und davor den zuvor geretteten Hintergrund wiederherstellen. Entscheidend ist dabei immer die Größe des größten Frames der Animation gewesen.

Nun habe ich mir gedacht, dass ich die Grafiken an die Spielobjekte hänge. Dann gekommt jede Animation eine Liste, in der aufsteigend sortiert die Animationen referenziert werden, welche diese Animation überdecken. Das ist allerdings nur für Hintergrundanimationen interessant, alle anderen haben die Liste umsonst.
Wird nun irgendetwas über den Hintergrund geblittet, wird das entsprechende Tile gesucht und die zu zeichnende Animation an der Stelle ihres Z-Wertes (oder Y-Hotspots) in die Liste eingetragen. Das Tile wird in die Damagelist aufgenommen mit der Clipregion in der größe des sich ändernden Objektes. Nun werden alle Nachbarn des Tiles auf die gleiche Weise geprüft und entsprechend in die Damagelist übernommen. Damit hat sichs dann auch schon.
Methoden zum Auffinden von 6-Ecken zu X,Y-Koordinaten hab ich ja schon. Es bleibt nur ein "Problem" ich muss die Damagelist für alle sich änderenden Objekte mit den Koordinaten vor und nach ihrer Änderung bestimmen, damit an der alten Position alles wieder hergestellt wird.
Für jedes Tile in der Damagelist wird folgendes gemacht:
Das Tile selbst wird geblittet und danach alle Objekte in seiner Liste. Als Clipregion wird zur Vereinfachung das Rechteck genommen, welches alle Objekte in der Liste eines Tiles umfasst (so viele sind das nicht).
Das müsste funktionieren und entspricht dem, was Du und Wolfgang mir ja vorgeschlagen haben.

Ciao

[ Dieser Beitrag wurde von Reth am 05.03.2006 um 20:53 Uhr geändert. ]

[ - Answer - Quote - Direct link - ]

2006-03-06, 15:52 h

bubblebobble
Posts: 707
User
Zitat:
Original von Reth:
@bubblebobble:

Hm, Alpha-Channel wäre für mich auch mal interessant. Momentan erreiche ich "Transparenz", in dem ich z.B. bei den Turm-Cursors nur jedes 2. Pixel setze.

Das ist natürlich sehr oldschool!
Alpha ist aber nicht notwendigerweise für Transparenz Effekte da, sondern vor allem kann man Objekte mit Antialiasing auf den Hintergrund blitten, was ein sehr schönes Bweiches Bild ergibt, man hat also keine Treppchen mehr bei vordergrundobjekten, ähnlich wie Pixelfonts vs. Antialiased Fonts.
Aber auch schatten lassen sich damit gut machen, oder, wenn man die entsprechenden Blit routinen schreibt, auch Beleuchtung etc.
Allerdings brauchst du auf jedenfall 16 oder 24 bit screens.

Zitat:
Wieso meinst Du eigentlich, dass C++ hier ein Kropf wäre (bin gern für Argumente offen)? Ich finde sogar, es bietet sich hier an, da man für alles seine Objekte mit ihrem Verhalten definieren kann.
Ich finde, C++ lohnt sich nur bei großen Projekten mit mehreren Leuten, ansonsten steht es einem mehr im Weg als dass es hilfreich ist. Aber das ist meine persönliche Meinung, weil ich C oder AB2 mehr gewöhnt bin. Wenn man sich gut in C++ auskennt, sieht man das vielleicht anders.

Zitat:
Methoden zum Auffinden von 6-Ecken zu X,Y-Koordinaten hab ich ja schon. Es bleibt nur ein "Problem" ich muss die Damagelist für alle sich änderenden Objekte mit den Koordinaten vor und nach ihrer Änderung bestimmen, damit an der alten Position alles wieder hergestellt wird.
Für jedes Tile in der Damagelist wird folgendes gemacht:

Du bist der sache schon näher, aber ignorierst ziemlich hartnäckig was ich versuche sei mehreren Posts zu vermitteln. Vielleicht drücke ich mich nicht klar genug aus, ist aber auch schwierig ohne Grafiken.

Ich habe mir jetzt aber die Ultimative Lösung ausgedacht, mit der Landschaften auch Hügel und beliebig hohe Objekte haben können, und man beim Refreshen trotzdem effizient bleibt.
Dazu muss ich aber ein paar Grafiken machen.
Grundsätzlich ist es aber so, wie ich weiter oben beschrieben habe, aber das auffinden der neu zu zeichnenden Objekte wird effizienter.

--
Thilo Köhler, Author von:
HD-Rec, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, TKUnpacker
Homepage: http://www.hd-rec.de


[ - Answer - Quote - Direct link - ]

2006-03-06, 16:14 h

Reth
Posts: 1858
User
Zitat:
Original von bubblebobble:
Das ist natürlich sehr oldschool!
Alpha ist aber nicht notwendigerweise für Transparenz Effekte da, sondern vor allem kann man Objekte mit Antialiasing auf den Hintergrund blitten, was ein sehr schönes Bweiches Bild ergibt, man hat also keine Treppchen mehr bei vordergrundobjekten, ähnlich wie Pixelfonts vs. Antialiased Fonts.
Aber auch schatten lassen sich damit gut machen, oder, wenn man die entsprechenden Blit routinen schreibt, auch Beleuchtung etc.
Allerdings brauchst du auf jedenfall 16 oder 24 bit screens.


Dann ist das erstmal nix für mich.

Zitat:
Du bist der sache schon näher, aber ignorierst ziemlich hartnäckig was ich versuche sei mehreren Posts zu vermitteln. Vielleicht drücke ich mich nicht klar genug aus, ist aber auch schwierig ohne Grafiken.

Hm, dachte, Du hast das so gemeint. Man bestimmt das neu zu zeichnende Tile inkl. des Cliprechtecks. Das muss man aber doch bei bewegten Objekten vor und nach der Bewegung machen, denn sie können ja vorher und nachher unterschiedliche Tiles bedecken bzw. während der Bewegung 2 Tiles bedecken. Wenn sich ein Objekt bewegt wird seine alte Position und Größe sowie seine neue Position und seine Größe zur Bestimmung der "beschädigten" Regionen hergenommen, oder nicht?

Zitat:
Ich habe mir jetzt aber die Ultimative Lösung ausgedacht, mit der Landschaften auch Hügel und beliebig hohe Objekte haben können, und man beim Refreshen trotzdem effizient bleibt.
Dazu muss ich aber ein paar Grafiken machen.
Grundsätzlich ist es aber so, wie ich weiter oben beschrieben habe, aber das auffinden der neu zu zeichnenden Objekte wird effizienter.


Da bin ich aber mal gespannt! Mit ist auch noch was eingefallen, wobei C++ bzw. die STL da sehr hilfreich ist, werde ich mal ausprobieren. Das setzt dann Deinen Algorithmus um, hilft aber hoffentlich stark bei der Auffindung "beschädigter" Tiles.

Sind die Bildchen zu Deinen Bsps. denn auch von Dir (das mit der Spielfigur, dem Baum usw.)?

[ - Answer - Quote - Direct link - ]

2006-03-06, 18:01 h

whose
Posts: 2156
User
@Reth:
Zitat:
Hm, dachte, Du hast das so gemeint. Man bestimmt das neu zu zeichnende Tile inkl. des Cliprechtecks. Das muss man aber doch bei bewegten Objekten vor und nach der Bewegung machen, denn sie können ja vorher und nachher unterschiedliche Tiles bedecken bzw. während der Bewegung 2 Tiles bedecken. Wenn sich ein Objekt bewegt wird seine alte Position und Größe sowie seine neue Position und seine Größe zur Bestimmung der "beschädigten" Regionen hergenommen, oder nicht?

Ganz genau. Wenn Du das Ganze jetzt noch aus dem Blickwinkel einer State Machine siehst, hast Du es ganz erfaßt. Du hast einen State und eine State Trasition zum einem neuen State. Die "Beschädigungen" des vorherigen State durch bewegte Objekte dienen zur Herstellung des neuen State genauso wie die Informationen der eigentlichen State Transition (z.B. neue unbewegte Objekte im Bild, neuer Frame einer Objektanimation).

Alles, was sich nicht verändert, bleibt einfach so stehen, wie es vorher auch war. Alles, was sich auf irgendeine Weise verändert (also ganz oder teilweise zu einer Damage Region gehört!), wird zur Herstellung des neuen State neu gezeichnet, und zwar nach vorher definierten Regeln (z.B. von oben nach unten/rechts nach links, die am Mauszeiger klebende Turmgrafik immer als letztes Element usw.).

Grüße


--
---

:boing: µA1 PPC 750GX-800
:boing: A4000 PPC 604e-233

[ - Answer - Quote - Direct link - ]

2006-03-11, 01:53 h

psd
Posts: 12
User
Wow, diesen Thread muß ich mir nochmal in Ruhe reintun. Oder ausdrucken und als Buch binden. Erstmal danke für den Input. :)

[ - Answer - Quote - Direct link - ]

2006-03-13, 16:52 h

bubblebobble
Posts: 707
User
@Reth
Ja, der Screenshot ist von meinem Spiel. Die Figur ist allerdings aus einer (sehr viel) älteren Version, als die Landschaft noch gepixelt war. Jetzt ist sie richtig gezeichnet, was mir besser gefällt, obwohl gepixelt auch seinen Charme hat, aber eben old-school aussieht.

Also so wie ich das jetzt implementieren werde ist etwas kompliziert zu beschreiben, habe jetzt leider auch keine Zeit ein Tutorial mit Bildern vorzubreiten.

Kurz gesagt: Man baut die Landschaft in Tiles auf, so wie gehabt. Allerdings nimmt man nicht das Tile Array, um herauszufinden welches Object neu gezeichnet werden muss, sondern ein nochmals imaginär darüberliegendes Array, was dann auch Rechteckig sein kann. Das Array enthält dann für alle Raster-Rechtecke die Information, welches Objekt darinliegt. Das kann man in aller Ruhe berechnen, bevor das Spiel los geht. Objekte die sich bewegen müssen natürlich geupdated werden, aber das kostet kaum Zeit, das sind ein paar Bytes verschieden.
Muss ich einen Bereich neu zeichnen (es wird grundsätzlich immer alles neu gezeichnet), lege ich ein ClipRect um diesen Bereich, schaue in welche Rechtecke des Raster-Arrays die Refresh-Region hineinragen, und erhalte sofort alle Objekte, die ich dann stumpfsinnig blitte. Das ist alles.

Vorteil: Schnelles auffinden aller Bilder, die neu geblittet werden müssen, und Objekte können beliebig gross/hoch sein. Auch kann man Hügel machen, sodass Tiles "angehoben" werden. Der Refresh engine ist das völlig egal woher die Bildchen kommen, weil sie nur in das Raster-Array schaut.

--
Thilo Köhler, Author von:
HD-Rec, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, TKUnpacker
Homepage: http://www.hd-rec.de


[ - Answer - Quote - Direct link - ]

2006-03-14, 10:23 h

Reth
Posts: 1858
User
Zitat:
Original von bubblebobble:
@Reth
Ja, der Screenshot ist von meinem Spiel. Die Figur ist allerdings aus einer (sehr viel) älteren Version, als die Landschaft noch gepixelt war. Jetzt ist sie richtig gezeichnet, was mir besser gefällt, obwohl gepixelt auch seinen Charme hat, aber eben old-school aussieht.


Lecker, gibts noch mehr davon zu sehen oder testen? Ist das schon "released" oder noch in Entwicklung?

Zitat:
Kurz gesagt: Man baut die Landschaft in Tiles auf, so wie gehabt. Allerdings nimmt man nicht das Tile Array, um herauszufinden welches Object neu gezeichnet werden muss, sondern ein nochmals imaginär darüberliegendes Array, was dann auch Rechteckig sein kann. Das Array enthält dann für alle Raster-Rechtecke die Information, welches Objekt darinliegt. Das kann man in aller Ruhe berechnen, bevor das Spiel los geht. Objekte die sich bewegen müssen natürlich geupdated werden, aber das kostet kaum Zeit, das sind ein paar Bytes verschieden.
Muss ich einen Bereich neu zeichnen (es wird grundsätzlich immer alles neu gezeichnet), lege ich ein ClipRect um diesen Bereich, schaue in welche Rechtecke des Raster-Arrays die Refresh-Region hineinragen, und erhalte sofort alle Objekte, die ich dann stumpfsinnig blitte. Das ist alles.

Vorteil: Schnelles auffinden aller Bilder, die neu geblittet werden müssen, und Objekte können beliebig gross/hoch sein. Auch kann man Hügel machen, sodass Tiles "angehoben" werden. Der Refresh engine ist das völlig egal woher die Bildchen kommen, weil sie nur in das Raster-Array schaut.


Danke für Deine Beschreibung. Gute Idee mit dem imaginären Raster!
So ähnlich hab ich mir das für mich auch überlegt. Aber Du musst immer pro Durchgang alle Objekte prüfen und in Deinem drüberliegenden Array ggf. umhängen (denke mal, es ist ein Array von Zeigern und an jeder x,y-Position liegt ne aufsteigend sortierte Liste mit Zeigern auf die zu blittenden Objekte, oder?). Bin mal gespannt, wie schnell das bei mir wird.

Ich mach folgendes: Dank C++ und der STL nehme ich einen Vector, in dem liegen alle grafischen Objekte (Zeiger). Dazu nehme ich noch 2 3-dimensionale Maps, die 1. (x,y,z) bildet alle sichtbaren grafischen Objekte auf die Postionen der Hintergrundtiles (x,y) ab. An diesen Postionen liegt dann ne Map von Zeigern, der grafischen Objekte, die über dem Tile liegen (ein Objekt kann ja über mehreren Tiles liegen). Da Maps sortiert sind, werden die Zeiger mit ihrer Tiefeninformation als Schlüssel abgelegt, damit hab ich automatisch alle Objekte in der richtigen aufsteigenden Blitreihenfolge.

Die 2. Map (z,x,y) enthält dann alle neu zu zeichnenden Objekte pro Durchgang, diesmal kommt an erster Stelle die Tiefeninfo und dann die genaue x,y-Position der zu blittenden Objekte. Dadurch wird dann Schicht für Schicht übereinander geblittet.

Aufwändig wird wohl die Bestimmung, welche Tiles von einem Objekt überdeckt werden (dazu muss ich x,y-Position und Höhe, Breite des Objektes berücksichtigen, innerhalb dieser Bereiche [x, x+Breite] [y, y+Höhre] wird dann geschaut, über welchen Tiles das Objekt liegt und der Zeiger eingetragen dazu muss dann immer noch das max. ClipRect berechnet werden).

Das müsste eigentlich klappen, hoffe ich!

Ciao
René

[ - Answer - Quote - Direct link - ]

2006-03-14, 15:14 h

bubblebobble
Posts: 707
User
@Reth:
>> Lecker, gibts noch mehr davon zu sehen oder testen? Ist das schon "released" oder noch in Entwicklung?
Ja, davon gibts noch mehr, aber nichts released und noch nichts programmiert. Nur Studien bis jetzt.

Ja, Objekte die sich bewegen muss man "umhängen" im Array, aber egal ob das direkt auf dem Tile array ist oder dem "imaginären", rechteckigen Array. Allerdings kann dann ein Objekt auch in mehreren Arrays sein. Aber ich denke der Overhead lohnt sich. Wieviele sich bewegende Objekte planst du denn? Ich meine nicht feststehende Anims, wie z.B. eine wehende Fahne, weil da kann man einfach die Maximum Größe aller AnimFrames angeben und fix lassen.

Speichern würde ich das ganze in einem dynamischen, eindimensionalen Array pro Rechteck Feld. Das ist also ein Array, was dynamisch erweitert wird, falls es zu klein ist.

Es wird also nicht zwischen Boden-Tile, stehenden Objekten und beweglichen Objekten unterschieden. Alle sind in der gleichen Struktue gespeichert. Wenn sich ein Objekt bewegt, wird diese eben manipuliert.

Die Überdeckung ist eigentlich ganze einfach.Grob wird nach ISO Tiles sortiert, also Objekte auf einem ISO Tile weiter vorne sind auch immer im Bild weiter vorne. Objekten innerhalb eines Tiles gehen dann nach Hotspot. Dadruch kann man z'.B. immer och Zäune entlange der Tilegrenzen machen, wo man einmal davor und einmal dahinter stehen kann. Nur mit Hotspot geht das nicht, das funktioniert nur bei punktuellen Objekten wie Bäumen, Figuren etc.

Bei meiner Methode gibt es aber noch den vorteil, das Tiles höher sein können als andere, ohne mehraufwand. Dadruch lassen sich z.B. sehr hohe Berge machen, sodass die Boden Tiles eigentlich mehrere Tile Ebenen höher liegen (optisch). Gespeichert sind sie aber schon brav auf ihrem Platz im Tile Netz.

--
Thilo Köhler, Author von:
HD-Rec, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, TKUnpacker
Homepage: http://www.hd-rec.de


[ - Answer - Quote - Direct link - ]

2006-03-14, 15:41 h

Reth
Posts: 1858
User
Zitat:
Original von bubblebobble:
Ja, davon gibts noch mehr, aber nichts released und noch nichts programmiert. Nur Studien bis jetzt.


Schade! Wollte mal den Unterschied zwischen gepixelt und gezeichnet begutachten.

Zitat:
Ja, Objekte die sich bewegen muss man "umhängen" im Array, aber egal ob das direkt auf dem Tile array ist oder dem "imaginären", rechteckigen Array. Allerdings kann dann ein Objekt auch in mehreren Arrays sein. Aber ich denke der Overhead lohnt sich. Wieviele sich bewegende Objekte planst du denn? Ich meine nicht feststehende Anims, wie z.B. eine wehende Fahne, weil da kann man einfach die Maximum Größe aller AnimFrames angeben und fix lassen.

Dann muss man aber die Objektarten unterscheiden statisch vs beweglich, damit man bei den statischen Objekten immer den größten Frame als Umriß hernehmen kann (sowas hatte ich in meiner 1. Version schon zum Hintergrund retten).
Wenn man unterscheidet in statische vs. bewegliche Objekte, dann werdens bei mir wohl in einer ersten Version ca. 10 bewegliche Objekte. Wenn man nur in statische vs. veränderliche Objekte unterscheidet, kann sich das Ganze dann auf ca. 30-50 aufschaukeln.

Zitat:
Speichern würde ich das ganze in einem dynamischen, eindimensionalen Array pro Rechteck Feld. Das ist also ein Array, was dynamisch erweitert wird, falls es zu klein ist.

Das ist der Vorteil der STL Container, die sind schon dynamish. Die Vectors und Maps, von denen ich sprach passen sich in der Größe an.

Zitat:
Es wird also nicht zwischen Boden-Tile, stehenden Objekten und beweglichen Objekten unterschieden. Alle sind in der gleichen Struktue gespeichert. Wenn sich ein Objekt bewegt, wird diese eben manipuliert.

Ist das eine Frage, oder machst Du das so bei Dir?

Zitat:
Die Überdeckung ist eigentlich ganze einfach.Grob wird nach ISO Tiles sortiert, also Objekte auf einem ISO Tile weiter vorne sind auch immer im Bild weiter vorne. Objekten innerhalb eines Tiles gehen dann nach Hotspot. Dadruch kann man z'.B. immer och Zäune entlange der Tilegrenzen machen, wo man einmal davor und einmal dahinter stehen kann. Nur mit Hotspot geht das nicht, das funktioniert nur bei punktuellen Objekten wie Bäumen, Figuren etc.

Für Dein "sind weiter vorn" ohne HotSpot brauchst Du doch aber ne z-Information, oder nicht?

Zitat:
Bei meiner Methode gibt es aber noch den vorteil, das Tiles höher sein können als andere, ohne mehraufwand. Dadruch lassen sich z.B. sehr hohe Berge machen, sodass die Boden Tiles eigentlich mehrere Tile Ebenen höher liegen (optisch). Gespeichert sind sie aber schon brav auf ihrem Platz im Tile Netz.

Wie unterscheidet sich das dann im Handling der Tiles, wenn diese unterschiedliche Höhen haben (in der Optik isses ja klar)?

Danke nochmals!

Ciao

[ - Answer - Quote - Direct link - ]


1 -2- 3 [ - Post reply - ]


amiga-news.de Forum > Programmierung > Koordinatentransformation, Überdeckung [ - Search - New posts - Register - Login - ]


.
Masthead | Privacy policy | Netiquette | Advertising | Contact
Copyright © 1998-2024 by amiga-news.de - all rights reserved.
.