Diskuze: Jak na 2D animaci pohybu?
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.

Člen

Zobrazeno 36 zpráv z 36.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
A co ti na tom přijde těžkého? Prostě jenom budeš měnit obrázky při vykreslování pořád dokola.
Do nejake promenne si ulozis fazi animace, tu fazi budes jednou za cas (podle rychlosti animace) zvysovat a pri vykreslovani vzdy vykreslis tu cast podle faze animace.
Presne to mi prijde tezke. Nemam tuseni, jak zacit, tudiz bych opravdu ocenil aspon nejake postrceni ke spravnemu reseni.
Mam vykresleny zakladni obrazek, tzn. stojici postavu. Potrebuji na stisk tlacitka posouvat postavu (mam) a zaroven menit obrazek.
Pokud to děláš přes WF, tak si zavolej na Form metodu onkeypress, zjisti která klávesa to je, to hoď do podmínky, jestli je to W A S nebo D a tam změň obrázek.
Prijimam titul nooba, ale netusim, co je to WF. Do okna programu vykresluju panacka, chci s nim hybat (to uz mam), akorat mu jeste potrebuji pridat animaci pohybu. Nepouzivam zadne pluginy ani frameworky.
V tom pripade ano, pouzivam Windows Form. Rozpoznavani klaves mam na KeyDown a pohyb funguje (rozpozna WASD).Netusim, jak mam udelat animaci a jak na pohyb tou animaci navazat.
No, tak určitě máš daný nějaký posun po tom stisku wasd, tak u toho vždycky změníš obrázek.
To samozrejme mam, pohybuji po pixelech. Mam ale 3 obrazky pro kazdy pohyb (1. obrazek - leva noha vpred, 2. obrazek - prava noha vpred atd.) a nemuzu zmenit obrazek pri pohybu, musim zacit animaci pri zacatku pohybu.
Tak to vyřeš přes Timer, nastav mu nějaký normální čas a přitom tom to změň
Jednodušší by podle mého bylo jen při každém eventu přičítat nějakou proměnou a podle ní vykreslovat správný obrázek. (jak říkal Luboš Běhounek Satik )
Asi jo, máš pravdu, ale stejně to musí hodit celý i to přičítání do Timeru.
Jo to jo, předpokládal jsem, že už tam nějaký má, asi jsem to blbě
řekl
Edit: bylo myšleno na enes.vint
Předpokládám tedy, že máš na Formuláři PictureBox, ve kterém je panáček.
Přidej si tam Timer, vlastnost Enabled mu nastav na true, Interval třeba na 300, dvakrát na ten Timer klikni - tím se ti vytvoří událost OnTick, ve které budeš měnit fázi animace třeba následujícím kódem (musíš někde třeba u formuláře mít proměnnou typu int s názvem fazeAnimace):
fazeAnimace = fazeAnimace % pocetAnimaci;
Za pocetAnimaci si dosadíš 3, tenhle kód ti zajistí, že se ti animace
bude opakovat pořád dokola.
hned za tu fázi animace si dáš kód, který bude načítat příslušný
obrázek, např něco jako:
PictureBoxPanacek.Load("obrazek"+fazeAnimace+".png");
[me|]13831[/me|]enes.vint[me|]13831[/me|][me|]13831[/me|]
Do formulare vykresluji pomoci metody Paint. Vykreslim zakladni obrazek a pri pohybu chci zakladni obrazek nahrazovat 3 po sobe jdoucimi obrazky.
hoď sem ten kousek kódu, kterým to kreslíš
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics gameWindow = e.Graphics;
{
gameWindow.DrawImage(d_1, xChar, yChar);
}
}
Pres toto vykreslim obrazek a pres souradnice v promennych xChar a yChar s obrazkem pohybuji.
jak nacitas do d1?
nacti si vsechny animace do vice image a pak podle te faze je vykresluj.
Pokud by jsi umel s poli nebo s Listem, mel by jsi nejlepsi nacist ty animace do
pole/listu a pak pri vykreslovani vykreslit image s indexem
fazeAnimace
Vice image mam, viz kod:
// pohyb vpřed
Image w_1 = Properties.Resources.w_stall;
Image w_2 = Properties.Resources.w_1;
Image w_3 = Properties.Resources.w_2;
Image w_4 = Properties.Resources.w_finish;
// pohyb vzad
Image s_1 = Properties.Resources.s_stall;
Image s_2 = Properties.Resources.s_1;
Image s_3 = Properties.Resources.s_2;
Image s_4 = Properties.Resources.s_finish;
// pohyb doprava
Image d_1 = Properties.Resources.d_stall;
Image d_2 = Properties.Resources.d_1;
Image d_3 = Properties.Resources.d_2;
Image d_4 = Properties.Resources.d_finish;
// pohyb doleva
Image a_1 = Properties.Resources.a_stall;
Image a_2 = Properties.Resources.a_1;
Image a_3 = Properties.Resources.a_2;
Image a_4 = Properties.Resources.a_finish;
S listem neumim vubec, s poli trochu. Mohl bys to prosim trochu rozvest?
Napis to opravdu jak pro postizeneho, jinak to asi nepochopim.
treba neco jako
List<Image> animaceW = new List<Image>();
animaceW.Add(Properties.Resources.w_1);
animaceW.Add(Properties.Resources.w_2);
animaceW.Add(Properties.Resources.w_finish);
List<Image> animaceA = new List<Image>();
animaceA.Add(Properties.Resources.a_1);
...
a pak v tom vykreslovani neco jako
gameWindow.DrawImage(animaceW[fazeAnimace], xChar, yChar);
nebo
gameWindow.DrawImage(animaceA[fazeAnimace], xChar, yChar);
apod., podle smeru, kam se diva
Povedlo se mi dostat list do kodu, panacek se ovsem nezobrazil a pouze problikaval pri pohybu. Prikladam me reseni vykreslovani, ktere je pravdepodobne chybne:
List<Image> animationW = new List<Image>();
animationW.Add(w_1);
animationW.Add(w_2);
animationW.Add(w_3);
animationW.Add(w_4);
List<Image> animationS = new List<Image>();
animationS.Add(s_1);
animationS.Add(s_2);
animationS.Add(s_3);
animationS.Add(s_4);
List<Image> animationA = new List<Image>();
animationA.Add(a_1);
animationA.Add(a_2);
animationA.Add(a_3);
animationA.Add(a_4);
List<Image> animationD = new List<Image>();
animationD.Add(d_1);
animationD.Add(d_2);
animationD.Add(d_3);
animationD.Add(d_4);
Graphics gameWindow = e.Graphics;
if (direction == 'n')
{
gameWindow.DrawImage(s_1, xChar, yChar);
}
if (direction == 'w')
{
gameWindow.DrawImage(animationA[animPhase], xChar, yChar);
}
if (direction == 's')
{
gameWindow.DrawImage(animationS[animPhase], xChar, yChar);
}
if (direction == 'a')
{
gameWindow.DrawImage(animationA[animPhase], xChar, yChar);
}
if (direction == 'd')
{
gameWindow.DrawImage(animationD[animPhase], xChar, yChar);
}
S tim, ze po chvilce chozeni "spadne" grafika = objevi se bile preskrtnute pole.
jaky mas ten kod v timeru?
Zkus tohle:
animPhase = (animPhase + 1) % 4;
% je zbytek po deleni
To opravdu pomohlo, dekuju. Uz vse funguje tak, jak ma, akorat pri pohybu nahoru (sipka nahoru) a pri pohybu doprava (sipka doprava) problikava puvodni obrazek, tzn. obrazek, kterej funguje jako pozice kdyz panacek stoji (ta by se mela objevit pouze, kdyz se nedrzi klavesa pohybu a kdyz promenna direction nabyde 'n').
Graphics gameWindow = e.Graphics;
if (direction == 'w')
{
gameWindow.DrawImage(animationW[animPhase], xChar, yChar);
}
if (direction == 's')
{
gameWindow.DrawImage(animationS[animPhase], xChar, yChar);
}
if (direction == 'a')
{
gameWindow.DrawImage(animationA[animPhase], xChar, yChar);
}
if (direction == 'd')
{
gameWindow.DrawImage(animationD[animPhase], xChar, yChar);
}
if (direction == 'n')
{
gameWindow.DrawImage(s_1, xChar, yChar);
}
Nepomohlo ani to, ze jsem to trochu upravil. Taky by mohla byt chyba nekde pri zvedani klavesy, ale tam pracuju pouze s timerem... Achjo.
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Up)
{
movement.Stop();
Refresh();
}
if (e.KeyCode == Keys.Down)
{
movement.Stop();
Refresh();
}
if (e.KeyCode == Keys.Right)
{
movement.Stop();
Refresh();
}
if (e.KeyCode == Keys.Left)
{
movement.Stop();
Refresh();
}
Pridavam kod, kdyby te to bilo do oci, tak me prosim upozorni.
Tak ho nepridavej do tech listu a pak zmen to cislo za % na 3
V listech ten obrazek vubec neni. Jde o ten obrazek s1, ktery ma byt vykresleny pouze, kdyz se panacek nehybe.
tak si musis nejak zjistovat, jestli se prave hybe - treba v keydown si to ulozit do nejake bool promenne
a v keyup si nastavit, ze se uz nehybe
a pak vykreslovat jen jedno nebo druhe.
Takze noob reporting in!
Podarilo se mi vyresit predchozi problem s problikavajicim obrazkem. Nahradil jsem podminku switchem (viz kod) a vse funguje tak, jak ma.
switch (e.KeyCode)
{
case Keys.Up:
yChar -= 2;
movement.Start();
direction = 'w';
Refresh();
break;
case Keys.Down:
yChar += 2;
movement.Start();
direction = 's';
Refresh();
break;
case Keys.Right:
xChar += 2;
movement.Start();
direction = 'd';
Refresh();
break;
case Keys.Left:
xChar -= 2;
movement.Start();
direction = 'a';
Refresh();
break;
}
if (e.KeyCode == Keys.Up)
{
movement.Stop();
direction = 'n';
Refresh();
}
if (e.KeyCode == Keys.Down)
{
movement.Stop();
direction = 'n';
Refresh();
}
if (e.KeyCode == Keys.Right)
{
movement.Stop();
direction = 'n';
Refresh();
}
if (e.KeyCode == Keys.Left)
{
movement.Stop();
direction = 'n';
Refresh();
Problem je tedy vyresen. Dekuji vam za ochotnou pomoc, opravdu si ji vazim a snad budu priste moct poradit nekomu ja. Diky!
Zobrazeno 36 zpráv z 36.