Původní grafické módy využívaly hlavně rozlišení 320x200pixelů a paletu 256barev.
Řádků bylo 200, přibližně stejně bylo i barev, optimální předpoklad pro zaplnění obrazovky ohněm :)
Na spodní řadu obrazovky se umístí několik bodů vysokého jasu a ty se postupně ztmavují, přičemž se bere do úvahy hodnota na předchozím řádku.
Paleta barev by se měla optimálně skládat z přechodu barev
černá - červená 0 až 130
a
červená - žlutá 131 až 254
Můžete zakombinovat i bílou. Záleží na spalovaném materiálu :)
// generování palety barev. Nejdříve odstíny červené, které přejdou v jasně žlutou
IList PALlist = new List();
for (byte i=0;i<255;i++)
{
if (i<130)
PALlist.Add(Color.FromRgb(i, 0, 0));
else
PALlist.Add(Color.FromRgb(i,(byte)(i-130), 0));
}
|
samotné zobrazení realizuji pomocí writeablebitmap takto
BitmapPalette myPalette;
myPalette = new BitmapPalette(PALlist);
wBmp = new WriteableBitmap(xres, yres, 96, 96, PixelFormats.Indexed8, myPalette);
|
zde je potřeba říci, že Writeablebitmap s pixelformatem indexed8 je pomalejší než Bgra32. Já ve verzi pro desktop použil indexed8, ale ve verzi pro Silverlight jsem už paletu nenastavoval a použil jsem rovnou Argb32 (nic jiného Silverlight ani nenabízí)
dále jsem si založil 2 buffery. Jeden s integer hodnotou a druhý byte.
Ten s integer slouží pro samotné generování ohně. Hodnoty větší než 256 mi tak dovolí mít vyšší oheň, nedochází k tak rychému ztmavení. Pole byte potom slouží k samotnému zobrazení výsledku na obrazovku.
int[,] BuffArray1 = new int[yres + 1, xres]; // zde kreslíme samotný oheň
byte[,] BuffArray4 = new byte[yres + 1, xres];
// pole typu integer nejde jednoduše poslat do bitmapy, proto musím bohužel konvertovat
|
Na začátku každého obrazu je potřeba do spodní části obrazovky vegenerovat jasné body.
V mém případě jsem spodní dva řádky nejprve pokryl náhodnou hodnotou barvy 120 - 150, tedy světlé odstíny červené a dále jsem do spodní části umístil několik větších bodů 3x3pixely hodnoty 255, tedy jasně žlutou.
Proměnnou násobič jsem použil pro zvětšení rozsahu barevnosti a tedy i samotné výšky ohně. Pokud bych měl jen 255 řádků, oheň by byl velmi nízký. Místo hodnoty 255 je tak uložena hodnota 510 (podle násobiče = 1 bitový posun vlevo).
// umístím náhodné body jasně červené do spodních dvou řad
for (int i = 0; i < xres; i++)
{
BuffArray1[yres - 1, i] = (byte)rnd.Next(120, 150) << nasobic;
BuffArray1[yres - 2, i] = (byte)rnd.Next(120, 150) << nasobic;
}
// umístím několik větších bodů vysokého jasu žluté také do spodní řady
for (int x = 1; x < rnd.Next(9, 50); x++)
{
int i;
i = rnd.Next(1, xres -1);
BuffArray1[yres - 1, i-1] = 255 << nasobic;
BuffArray1[yres - 1, i] = 255 << nasobic;
BuffArray1[yres - 1, i+1] = 255 << nasobic;
BuffArray1[yres - 2, i - 1] = 255 << nasobic;
BuffArray1[yres - 2, i] = 255 << nasobic;
BuffArray1[yres - 2, i + 1] = 255 << nasobic;
BuffArray1[yres - 3, i - 1] = 255 << nasobic;
BuffArray1[yres - 3, i] = 255 << nasobic;
BuffArray1[yres - 3, i + 1] = 255 << nasobic;
}
|
Samotné generování pixelů ohně je znázorněno na tomto obrázku:
Pixel s křížkem je právě počítaný pixel a 4 zelené pixely jsou použity jako zdrojové pro výpočet hodnoty. Samotný výpočet je jen aritmetický průměr.
Počítá se každý pixel řádku od spodního k hormímu. Hodnota -1 znamená cílené ztmavení o jeden stupeň.
#include
for (int y = yres - 1; y > 0; y--)
for (int x = 1; x < xres - 1; x++)
{
b = (byte)((((BuffArray1[y, x - 1]) + (BuffArray1[y, x + 1]) +
(BuffArray1[y + 1, x]) + (BuffArray1[y , x])) >> 2) - 1);
if (b < 2) b = 2;
BuffArray1[y - 1, x] = b;
}
|
vygenerovaná scéna se zkonvertuje na pole typu byte a pošle na obrazovku. Co se původně jevilo jako nutné zlo se nakonec ukázalo, jako dobrý nástroj k přizpůsobení vzhledu ohně. Schválně si zkuste smazat podmínku ii>254, uvidíte, co se stane a jak toho bylo využito k lepšímu efektu.
for (int y = 0; y < yres; y++)
for (int x = 0; x < xres; x++)
{
if (radioButton3.IsChecked == true)
{
if (BuffArray1[y, x] > 254) BuffArray1[y, x] = BuffArray1[y, x] + 8;
ii = BuffArray1[y, x];
if (ii > 254) ii=254;
BuffArray4[y, x] = (byte)(ii);
}
}
wBmp.WritePixels(new Int32Rect(0, 0, xres, yres-5), BuffArray4, xres, 0);
|
Místo generování náhodných hodnot na spodní stranu obrazovky můžete generovat body ve tvaru nějakého objektu, případně i textu a mít tak hořící nápisy.
© Bura.cz