Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi [Andorra 2D] Taschenlampe (https://www.delphipraxis.net/154050-%5Bandorra-2d%5D-taschenlampe.html)

sabbert 25. Aug 2010 22:25


[Andorra 2D] Taschenlampe
 
Liste der Anhänge anzeigen (Anzahl: 2)
Nabend zusammen,

ich beschäftige mich schon seit längerem mit Andorra 2D und für mein neues Projekt würde ich gerne eine Taschenlampe "einbauen".

Ich habe mir dazu schon ein paar Gedanken gemacht wie ich da vorgehen könnte...

Undzwar dachte ich erst das ich so eine Art schwarze "Maske" über meine Spiel lege und dann den beleuchteten Bereich freilasse. Also es geht mir um die Darstellung des Beleuchteten Bereiches. Dieser soll recht einfach dargestellt werden. So soll sozusagen nur was angeleuchtet wird vom Spieler gesehen werden habe dazu mal ein sehr einfaches Beispiel angehängt wie ich mir das vorstelle :D:D

Aber es soll z.B. nicht durch eine Wand hindurch geleuchtet werden.
Wie kann man sowas berechnen und dann anzeigen lassen?
Gibt es in Andorra eine Option die das Spiel sozusagen komplett auf "dunkel" stellt, als ob es Nacht wäre?

Hoffe ihr habt Ideen

mfg

igel457 26. Aug 2010 08:20

AW: [Andorra 2D] Taschenlampe
 
Ich würde hierzu den Stencil-Buffer verwenden. Erklärungen hierzu finden sich u.a. hier: http://wiki.delphigl.com/index.php/Stencilbuffer und in der entsprechenden Demo.

Du zeichnest zuerst die komplette Umgebung etwas "dunkler" als normal Mittels "Ambient-Color". Dann aktivierst du den Stencil-Buffer und zeichnest eine "Schablone" unter der die Szene normal gezeichnet werden soll. Dann zeichnest du deine Szene nochmals. Der Code (nicht getestet) sollte ungefähr so aussehen:
Delphi-Quellcode:
AdDraw.Options := AdDraw.Options + [aoLights];
AdDraw.Scene.AmbientColor := Ad_ARGB(255, 64, 64, 128);
//Scene einmal zeichnen
AdDraw.Options := AdDraw.Options - [aoLights];

AdDraw.Options := AdDraw.Options + [aoStencil, aoAlphaMask];

//Dieser Aufruf bewirkt, dass jeder gezeichnete Pixel das unten aufgeführte Ereignis auslöst
AdDraw.AdAppl.SetStencilOptions(0, $FFFF, asfAlways);
//Der Wert des Stencil-Puffers wird um eins erhöht
AdDraw.AdAppl.SetStencilEvent(asePass, asoIncrement);

//Eine Maske mit weißer Farbe zeichnen, in der die Scene später mit normaler helligkeit Gezeichnet wird

AdDraw.Options := AdDraw.Options - [aoAlphaMask];

//Nur dort zeichnen, wo vorher die Maske war
//Nur wenn "Null" kleiner als der Stencilbuffer Wert ist (was für alle Pixel der Fall ist, bei denen die Maske gezeichnet wurde), darf ein neuer Pixel an diese Stelle gezeichnet werden.
AdDraw.AdAppl.SetStencilOptions(0, $FFFF, asfLessThan);
//Der Stencil-Buffer soll nicht mehr verändert werden, also beibehalten ("Keep")
AdDraw.AdAppl.SetStencilEvent(asePass, asoKeep);


//Szene zeichnen

//Um das ganze schöner Aussehen zu lassen, eine transparente Version der Maske zeichnen, die an den Ecken zu weniger Transparent ausblendet

AdDraw.Options := AdDraw.Options - [aoStencil];
Lies dich auf jeden Fall mal im oben genannten Link in das Thema ein, sodass du diese "SetStencil*" Aufrufe verstehst.

Andreas

Edit: Das mit "Nicht durch die Wand hindurch Leuchten" ist etwas komplizierter, du musst hier mit Raytraycing oder Shadowmapping - beides fortgeschrittene Techniken - arbeiten. Am einfachsten ist es wohl, wenn du dein Level in Zellen aufteilst und im Vorneherein mittels Raytracing (geht mit einfacher Vektorarithmetik) berechnest, welche Zellen von welcher Zelle aus angeleuchtet werden können, und du die nicht anleuchtbaren Zellen wieder aus dem Stencilbuffer entfernst indem du über diese z.B. ein Weißes Quadrat zeichnest und mit "asoZero" den Stencilbuffer für diese zurücksetzt.

sabbert 26. Aug 2010 14:03

AW: [Andorra 2D] Taschenlampe
 
Ok danke schonmal für die recht ausführliche Antwort :)

Klingt schon recht anspruchsvoll...:D
Also habe mir den obigen Link mal durchgelesen und weiß jetzt schon ungefähr wofür der StencilBuffer gut ist.

Es soll also eine Maske gezeichnet werden und so soll z.B. nur ein bestimmter Teil gerendert werden, falls ich das so in etwa richtig verstanden habe...

Jetzt wollte ich den Code mal Testen um das besser zu verstehen, aber an sich passiert da noch nichts.

Wenn ich die letzte Zeile weglasse, dann wird glaube ich eine Arte Maske gezeichnet, da ich keine Objekte mehr sehe, als ob diese unter der Maske liegen würden. Aber eine Farbliche Veränderung findet nicht statt

Delphi-Quellcode:
AdDraw.Options := AdDraw.Options - [aoStencil];
Wo muss ich den genannten Code denn einfügen, damit dieser auch gezeichnet bzw übernommen wird?

Habe den zurzeit zwischen
Delphi-Quellcode:
AdDraw.BeginScene;

//Code...

AdSpriteEngine.Move(AdPerCounter.TimeGap / 1000);
AdSpriteEngine.Draw;
AdSpriteEngine.Dead;

AdDraw.EndScene;
in der "OnIdle procedure" stehen.

Edit:

Ich versteh auch noch nicht so ganz wie ich den Bereich einstellen kann wo die Maske gezeichnet wird?!

igel457 26. Aug 2010 16:31

AW: [Andorra 2D] Taschenlampe
 
Gut...

Mit "Szene zeichnen" meine ich AdSpriteEngine.Draw.

Mit "Maske zeichnen" meine ich den Aufruf irgendeiner Zeichenfunktion (z.B. das Zeichnen eines Transparenten Bitmaps, oder das Zeichnen eines Kreises mittels Canvas).

Der Ganze Code muss zwischen AdSpriteEngine.Move und AdSpriteEngine.Dead

sabbert 26. Aug 2010 17:10

AW: [Andorra 2D] Taschenlampe
 
Liste der Anhänge anzeigen (Anzahl: 1)
Geil es funktioniert :D:D:D

Hab mal ein Screenshot angehängt wie das aussieht :)

Habe aus Testzwecken mal ein Rechteck als Maske genommen.

Danke für die Hilfe ;-)


Edit:
So jetzt muss ich versuchen das so zu implementieren das Das "Licht" nicht durch Wände scheint mal schauen :D


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:05 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz