Diskuze: Arkanoid - odraz míčku od cihel
V předchozím kvízu, Online test znalostí Java, jsme si ověřili nabyté zkušenosti z kurzu.

Vlastník

Zobrazeno 28 zpráv z 28.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Online test znalostí Java, jsme si ověřili nabyté zkušenosti z kurzu.
Nevím jak to myslíš? Dvě pod sebe nebo do sebe?
for (int j = 0; j < 4; j++) {
for (int i = 0; i < 10; i++) {
if((cihly[i][j]))
{
if ((y > (j * 20 + 50))&&(y<(j*20+50+19)))
{
}
if ((x>(i*30+50))&&(x<(i*30+50+29)))
{
}
}
}
}
Přesně tak. Nezkoumal jsem to úplně do detailů, ale takto by to mohlo fungovat:
if ((y > (j * 20 + 50)) && (y < (j * 20 + 50 + 19))) {
cihly[i][j] = false;
score += 1;
smerY *= -1;
} else if ((x > (i * 30 + 50)) && (x < (i * 30 + 50 + 29))) {
cihly[i][j] = false;
score += 1;
smerX *= -1;
}
Takhle to vymaže cihlu i v případě, že s ní míček nekoliduje, stačí, když je na stejné úrovni X nebo Y.
Aha, to jsem nedomyslel. Budou se tedy ty podmínky muset patřičně rozšířit, ale konstrukce ifu zůstane stejná.
Zkus si představit, že míček je v bodě [0, 0] a narazí do něj cihla. Pak už jen uděláš transformaci souřadnic.
Udělej si na okraji cihly jakousi zeď, třeba 5 pixelů tlustou, pro každou stranu jednu. Pak podle toho od který zdi se míček odrazí poznáš jak má změnit směr.
pro levou stranu:
ball.x, ball.y - souřadnice středu míčku
radius - poloměr míčku
block.x, block.y - souřadnice levého horního rohu cihly
block.sizeY - výška cihly
if(ball.x + radius >= block.x && ball.x + radius < block.x + 5 && ball.y + radius >= block.y && ball.y - radius <= block.y + block.sizeY)
{
//odraz
}
Jenom nesmí bejt rychlost míčku větši než tloušťka tý zdi.
Mě tohle fungovalo, jenom sem ještě musel definovat náraz do rohů, což u
mě nebyl problém, protože sem tam dělal různý úhly.
To mi moc nejde
Ale napadlo mě kontrolovat 4 body míčky v jeho "rozích", když ho vezmu jako čtverec. To by mělo fungovat. Ten který bude první kolidovat určí směr odrazu.
Já bych to chtěl nějak jednodušeji, ale koukám, že ta hra není tak jednoduchá, jak jsem myslel. Jak vůbec počítáš ty úhly?
Přes goniometrický funkce. U míčku mam x,y,rychlost a úhel a při každym pohybu spočítam: x += cos(úhel) * rychlost, y -= sin(úhel) * rychlost. U y je - kvůli převrácenej ose y. Při odrazu pak jenom úhel obrátim správnym směrem, a při odrazu od rohu nastavim úhel na +- 45 stupňů správnym směrem.
EDIT: Při odrazu od desky je úhel tim menší na danou stranu, čím je odraz blíž k okraji desky, pokud spadne na prostředek, odrazí se pod úhlem 90 stupňů.
A co kdybys to zjednodušil na kolizi obdélníků?
Pokud bys chtěl ošetřit i ty úhly, tak by to samozřejmě nestačilo, ale v tom případě ani nebude stačit pohyb ve čtyřech směrech.
Nebo můžeš kolize řešit per-pixel, pak podle kolidujícího pixelu i lehce určíš, jak se má míček odrazit.
Rád bych pomohl, zkušenosti mám ale jen s XNA, v jave nedělám a nevím jaké tam máš možnosti oproti např. matematickým pomocným třídám v XNA aj... Zítra bych měl nahrát svoji hru do soutěže. To by ti mohlo pomoci, všechno je tam řešené.
Doporučil bych si ale udělat nějakou širší objektovou strukturu, vše pak bude srozumitelnější, zas tak jednoduché to asi opravdu nebude...
Pocitat 4 rohy je pekne, ale nebude to presny. Udelej si cihle jako novou tridu, ktera bude dedit po Rectangle. Umozni ti to dalsi vyvoj kdy si budes moct dat ruzne druhy cihel a vyresi se ti tim problem s kolizi, protoze Rectangle obsahuje metodu intersects. Pro mene presnejsi a rychlejsi vypocet muzes udelat pro kulicku okraje z Rectanglu a to budes davat jako parametr do te metody. Pokud by jsi to chtel vice presneji tak to bude o neco pomalejsi, vytvoris si okraje pomoci tridy Ellipse2D a instanci pouzijes jako parametr na vytvoreni instance tridy Area ktera ma metodu intersects s rectanglem.
No koukl jsem se ted na kod a doufam ze prijmes mensi objektivni kritiku No doufam ze to nehodlas pouzit
jako ukazku nekde, protoze struktura OOP zadna (trida pojmenovana HerniPlatno a
mas tam prakticky vsechno). Vykreslujes na JPanel ktery je na kresleni nevhodny
(pouziva se Canvas
), navic
pouzivas pasivni renderovani (to znamena ze volas jen metodu repaint a
prepisujes metody na kresleni komponenty) a jeste k tomu volas puvodni metodu
paint, ta se nevola pokud nemas na Conteineru nejaky
komponenty. Dale proc pouzivas Timer? Nejaky padny duvod proc ho pouzivat? Na
herni smycky je naprosto nevhodnej, delaji se pres vlakna, vetsinou jedno kde se
volaji metody na render a aktualizovani herni logiky.
V mnoha věcech máš samozřejmě pravdu, ale je to dělané jako
jednoduchá ukázka nějakého realtimového vykreslování ve Swingu, proto tam
nejsou vlákna atd., určitě to není brané jako vážný pokus o hru
Uprimne je mi jedno jestli se tu nauci spatne nebo dobre praktiky. Jen jsem ti to chtel dat vedet. Jinak swing celkove neni vhodny na kresleni, v nem se spis vylepsovali vlastnosti komponent, jejich moznosti, vzhled a na vykon se nehledelo. Skoro vsechny tridy z AWT byly predelany do Swingu, ale Canvas jako jeden z mala ne, protoze je dost dobry. Takovych navodu na realtimove vykreslovani podobne tomu tvemu je hodne, proste se soustredili jen na jednoduchost a aby to bylo kratke a nikoho neodradilo. Je to fajn nic na to nenamitam, jsem rad kdyz to dela blbe a pak mu muzu vysvetlit proc to ma blbe, akorat kdyz pak podle toho chce udelat nekdo vetsi hru tak se pak divi proc ma maly vykon, pritom duvod je tak prosty, spatne zvoleni trid.
Pro jednoduchou ukázku sis vybral docela složitou hru
No až na ten pitomý odraz je to dost jednoduché, vždyť to má pár
řádků
Ano, dělá to tak hodně lidí a neříkal bych, že je to špatně, je to prostě nejjednodušší cesta jak něco takového udělat. Pokud vím, dal jsi sem i ukázky jak to udělat lépe, rád to u toho zmíním.
Pochopil jsem, že posouváš míček vždy jenom o jeden pixel, v tom případě můžeš udělat něco takovýho.
for (int j = 0; j < 4; j++) {
for (int i = 0; i < 10; i++) {
if((cihly[i][j]))
{
int blockPosY = j * 20 + 50;
int blockPosX = i * 30 + 50;
int blockSizeY = 19;
int blockSizeX = 29;
if(x == blockPosX && y >= blockPosY && y <= blockPosY + blockSizeY) {/*kod*/} //zleva
else if(x == blockPosX + blockSizeX && y >= blockPosY && y <= blockPosY + blockSizeY) {/*kod*/} //zprava
else if(y == blockPosY && x >= blockPosX && x <= blockPosX + blockSizeX) {/*kod*/} //zhora
else if(y == blockPosY + blockSizeY && x >= blockPosX && x <= blockPosX + blockSizeX) {/*kod*/} //zdola
}
}
}
V tom případě můžeš takhle kontrolovat kolizi pro jednotlivý pixely v míčku jestli alespoň jeden z nich je na tý čáře.
Spatne to neni pokud to funguje Pokud neco neplanuju zverejnit nebo je to fakt mala hra tak taky
plytvam vykonem kde se da
Klidne se tam zmin, bude lepsi kdyz budou vedet ze to jde i vykoneji.
Nezapomeň ošetřit rohy, jinak se ti může míček při názaru do dvou
stran najedou odrazit uplně jinak než by měl.
Pokud tedy půjdeš do těch per-pixel kolizí, tak se ty odrazy dají řešit třeba tak, že každý pixel má uloženou svojí normálu, aby jsi věděl, jak se má odraz od toho pixelu provést.
Zobrazeno 28 zpráv z 28.