Avatar
tomkrata
Člen
Avatar
tomkrata:

Snažím se udělat remake hry achtungdiekurwe, kde jde o to, nenarazit do stěn a do protihráčů, vítězí poslední přeživší. "Hra" zatím vypadá nějak takto, viz obr. S hlavičkou manipuluji jako s objektem ovál, který posouvám na základě mačkání kláves. V metodě paint vždy vykreslím nejprve červený ovál, posunu ho a vykreslím žlutý. Jak tedy zjistím kolizi mezi hlavičkou a již vykresleným, nikde nezapsaným, objektem?

 
Odpovědět 25. dubna 18:36
Avatar
gcx11
Redaktor
Avatar
Odpovídá na tomkrata
gcx11:

Ahoj, co podle barvy pixelu? Než někam ovál posuneš, tak zjistíš, jestli je tam něco jiného než černá.

 
Nahoru Odpovědět  +3 25. dubna 18:39
Avatar
tomkrata
Člen
Avatar
Odpovídá na gcx11
tomkrata:

Ahoj, díky za odpověd. Rozhodně to vyzkouším.

 
Nahoru Odpovědět  +1 25. dubna 19:00
Avatar
Bohumír záviš
Redaktor
Avatar
Odpovídá na gcx11
Bohumír záviš:

Výborný nápad mohu jedině doporučit :-)

 
Nahoru Odpovědět 25. dubna 19:06
Avatar
Lubor Pešek
Člen
Avatar
Lubor Pešek:

Osobně bych to dělal pomocí zjišťování componenty. Podle barvy pixelů je to dobré, ale zkoušel jsem si zahrát tu hru a zajímalo by mě, jak bys ošetřil ty bonusy, co se dají vzít. Jinou barvou než všechny ostatní?:) Řešil bych to asi tak, že plátno (tak to určitě i máš) bude nějaký panel nebo frame a hadi budou componenta. Pokaždé by ses tedy ptal, jestli na následujícím místě má panel nějakou componentu (přímo je na to metoda getComponentAt(x, y)). Tím máš ošetřený i případ, pokud by se ti pomíchali barvičky. Navíc bys měl nezávislého hada, kterému můžeš dát volbu jakékoliv barvy.
Podobnou otázku jsem řešil, když jsem si programoval tetris:) taky jsem to řešil barvou, ale potom to dělalo neplechu. Jde to, ale řešit případ díky barvě je dost sprosté.

Editováno 25. dubna 19:50
Nahoru Odpovědět 25. dubna 19:50
Existují dva způsoby, jak vyřešit problém. Za prvé vyhoďte počítač z okna. Za druhé vyhoďte okna z počítače.
Avatar
tomkrata
Člen
Avatar
Odpovídá na Lubor Pešek
tomkrata:

Ahoj, vyzkoušel jsem tuhle metodu, ale program mi vyhodnocuje všechny pozice v panelu jako nenulove. Jak mám zjistit, že se tam nachází konkrétní componenta?

 
Nahoru Odpovědět 26. dubna 9:15
Avatar
Lubor Pešek
Člen
Avatar
Lubor Pešek:

Ideální by bylo, kdybys sem postnul kód. Chyba může být leckde a navíc to není zas až tak jednoduché, protože musíš přesně specifikovat tu kterou komponentu hledáš (proto je to čistčí, protože barevnou komponentu můžeš mít jakoukoli, ale když chceš třeba jen jednu komponentu, tak ji hledáš podle jména nebo classy.

Nahoru Odpovědět 26. dubna 10:13
Existují dva způsoby, jak vyřešit problém. Za prvé vyhoďte počítač z okna. Za druhé vyhoďte okna z počítače.
Avatar
tomkrata
Člen
Avatar
Odpovídá na Lubor Pešek
tomkrata:
public void paintComponent(Graphics g)
{
    paintFrame(g);
    if (poprvy)
    {
        zapisAngly();
        poprvy = false;
    }
    for (int i = 0; i < pocetHracu; i++)
    {
        if (hrac[i] != null)
        {
            if (zacatek && pocet < 100)
            {
                hrac[i].released = true;
                pocet++;
                hrac[i].oval.paintOval(g);
                posunKruh(hrac, i, g, hrac[i].doleva, hrac[i].doprava, hrac[i].released);
                hlavicka[i] = new Hlavicka(hrac[i].oval.getX(), hrac[i].oval.getY(), hrac[i].oval.getVelikost());
                hlavicka[i].paintHlavicka(g);
            }
            if (mezernik)
            {
                hrac[i].oval.paintOval(g);
                posunKruh(hrac, i, g, hrac[i].doleva, hrac[i].doprava, hrac[i].released);
                hlavicka[i] = new Hlavicka(hrac[i].oval.getX(), hrac[i].oval.getY(), hrac[i].oval.getVelikost());
                hlavicka[i].paintHlavicka(g);
            }
        }
    }
    repaint();
}

Tady vykresluju ty hady na základě kláves.
Ale ty ovaly, které vykreslím si nikam nezapisuju. Měl bych?

 
Nahoru Odpovědět 26. dubna 11:51
Avatar
Lubor Pešek
Člen
Avatar
Lubor Pešek:

fuj:)

předpokládám, že tuto metodu máš v jediné třídě. Tito hadi jsou krásným příkladem využítí OOP - had jedna třída, plocha druhá třída, skore třetí třída, bonusové objekty čtvrtá třída. Ve třídě had bys měl vykreslovat hada. To kolik si jich vytvoříš, to už je věc programu.

Navíc nezapouzdřuješ. Kdybys k tomu přidával novou třídu (prostě to nějak vylepšoval), tak se omylem překlepneš a zavoláš třeba atribut hada - oval a už ti to bude dělat neplechu.

Přiznám se, že teď si to zkouším taky, je to pěkný nápad. Jediné, co teď řeším, je pohyb hada:) nechci se smířit s tím, že budu dělat 9 větví podmínky pro změnu pohybu.
Jinak divaj, zkus přemýšlet objektově:

1. co může být objekt? (už jsem to psal, ale tak zopakuju:) ))
a) had
b) prostředí
c) skore
d) bonusy
Co jsem tím teď dokázal? už teď je jasné, že mám nějakou strukturu projektu. Můžu postupně dělat každou třídu zvlášť bez obav, že poku...teda pokazím to, co už mám hotovo. Další věc můžu několika způsoby řešit ten tvůj problém s narážením.
2. Rozhodnu se, jestli si udělám speciální třídu Main, která bude obsahovat metodu main(String[]). Výhoda programátora je, že je to jen a jen na tobě. Jestli chceš udělat samostatný projekt, ve kterém bude tato hra a si líný jako já dělat další třídy:D tak metodu main pichni do třídy prostředí. Jestli uděláš další hry (člověče, dostihy, poker atd.) Tak se nová spouštěcí třída přímo nabízí, protože do budoucna si v ní můžeš definovat třeba GUIčko, kterým si budeš volit hru. Je to fakt na tobě (mě osobně se to na programování líbí - můžeš dělat podle sebe, co chceš:) )
Ale pochopitelně měl bys dodržovat moderní techniky OOP. Zapozdření, komentáře, konečnost, determinovanost atd. atd. prostě vlastnosti OOP.
3. Vezmi si papír a tužku!!! to je to nejdůležitější co musíš u programování dělat. Pokresli a popiš si aspoň 13 papírů obrázkami, jak chceš, aby program výsledně vypadal, co má jednotlivá třída umět a jak bude vlastně sloužit a komu. No a takový vývojový diagramek není vůbec špatný. Nemyslím ten klasický, jak má fungovat cyklus, ale abys měl vazby, kdo s kým bude komunikovat (třídy).
4. No a za 4. už můžeš přímo programovat. Hlavně nezapomeň koentovat svoje nové metody, atributy atd. Z toho kousku kódu jsem nepochopil, co jsou proměnné zacatek, pocet, co je metoda zapisAngly, atd. atd. Pochopitelně komentovat metodu repaint() je blbost, komentuješ jen to, co jsi sám vytvořil, co na netu není a případně, pokud přepisuješ metodu, proč a k čemu to je. Máš 3 druhy komentářů, tak je využívej. Komentáře jsou sice pracné psát, ale když se podíváš na nějaký kód bez komentu, tak nevíš, co měl ten dotyčný na mysli. Jestli chceš, sice jsem tam udělal pár chyb (až teď jsem si toho všiml:D), ale postnul jsem svůj kód do ticketu "Posloupnost vláken" tak se můžeš mrknout, že co sám říkám, to dělám;)

No a taková rada od zkušených programátorů (ne ode mě:D). Nepoužívej české názvy proměnných. Já to dělám taky a je to chyba. Programování je anglická záležitost, musíme se to naučit:D

Zkus to překopat podle toho, co jsem ti napsal a pak postni buď celé třídy nebo kod s komenty.

Jo a ještě k tomu:) díky tomu, že to budeš mít v třídách, tak si můžeš vybrat, jestli bude vlákno ve třídě had (což je podle mě rozumné) nebo bude hada ovládat třída prostředí atd. já osobně bych navrhoval a taky to tak zkusím, abys samostatně hýbal hadem a to, jestli narazil nebo ne si bude taky kontrolovat sám. Had bude prostě hledat na nějakém prostředí překážku (bude se ptát třeba panelu ve třídě prostředí:

if(!panel.getComponentAt(had.getX(), had.getY() + 1) == null){ // ! se používá pro negaci, takže pokud na
                                                                                                    // místě o jeden pixel níž není volno, tak:
        had.stuj(); //v metodě stuj si definuj zastavení vlákna
}

No a další věc, buď si okraj olemuješ dalším objektem, takže naráz do okraje půjde už touhle podmínkou (což je možná i dobré, protože když jsem si to zkoušel hrát, tak ty okraje někdy mizeli a mohls projít na druhou stranu) nebo přetížíš tuhle podmínku další větví. Je to fakt na tobě a pokud budeš dodržovat OOP principy, tak budeš šikovný;)

Nahoru Odpovědět  +1 26. dubna 12:35
Existují dva způsoby, jak vyřešit problém. Za prvé vyhoďte počítač z okna. Za druhé vyhoďte okna z počítače.
Avatar
Lubor Pešek
Člen
Avatar
Lubor Pešek:

Ty jo, ty komentáře je fakt děs psát, ale velmi důležité:)
No tak jestli chceš, můžeš se mrknout, jak jsem to udělal já. Rozhodně nejsem spokojený se svým řešením pohybu, ale funguje to, jaks chtěl a je to připravené na další rozšíření (více hadů, umělá inteligence, okraje, bonusy, atd.)
Hlavní třída Prostredi, ve které se to odehrává, a která obsahuje metodu main

import java.awt.Color;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Prostredi extends JFrame {
//###################-ATRIBUTY-###################
//==========KONSTANTNI ATRIBUTY TRIDY==========
//===========PROMENNE ATRIBUTY TRIDY===========
//========KONSTANTNI ATRIBUTY INSTANCI=========
//=========PROMENNE ATRIBUTY INSTANCI==========

    private JFrame frame; //Hlavní okno programu, které i obsahuje KeyAdapter
    private Had had;  //Hlavička hada. Had nemá tělo, pouze hlavu (kdo chce, ať si to přejmenuje na hlavu:D)
    private JPanel panel; //Panel, který je dobrý pouze na černé pozadí
//####################-STATIC-####################
//============STATICKY KONSTRUKTOR=============
//=========STATICKE PRISTUPOVE METODY==========
//==============STATICKE METODY================
//=================MAIN METODA=================

    public static void main(String[] args) {
        Prostredi prostredi = new Prostredi();
    }
//###################-INSTANCE-###################
//=================KONSTRUKTOR=================

    /**
     * V konstruktoru metoda initt vytvoří herní prostředí, po kterém se bude
     * had pohybovat. V konstruktoru se pouze inicializuje a nastaví had
     * (později může být speciální metoda třeba vytvorHady() pro vytvoření více
     * hadů) a spustí se jeho vlákno
     *
     */
    public Prostredi() {
        initt();
        had = new Had(panel);
        panel.add(had);
        had.setSize(10, 10);
        had.setLocation(100, 30);
        had.setPosun(0, 1);
        had.start();
    }
//=============PRISTUPOVE METODY===============
//===================METODY====================

    private void initt() {
        frame = new JFrame();
        frame.setSize(500, 500);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        panel = new JPanel();
        panel.setLayout(null);  //nastavil jsem "žádný" layout, protože mi to mrcha špatně počítala
        panel.setBackground(Color.black);
        frame.add(panel);
        frame.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent evt) {
                if (evt.getKeyCode() == 39) {
                    doprava();  //metoda doprava zachycuje možné stavy a nastavuje nový vektor pohybu
                } else if (evt.getKeyCode() == 37) {
                    doleva();   //stejně jako metoda doprava, tak i metoda doleva zachycuje možné stavy a nastavuje nový vektor pohybu
                }
            }
        }
        );
    }
//###############-SOUKROME METODY-################
//=====STATICKE SOUKROME A POMOCNE METODY======
//==========SOUKROME A POMOCNE METODY==========

    /**
     * Ne příliš povedená definice otáčení hada je realizována pomocí metody
     * doprava(). Nejdříve mě napadlo řešení otočení pomocí stavů, ale takto
     * řešit jednu komponentu je ještě větší zločin, než switch-ovaná definice.
     * Řešení pomocí switchů mi příjde procesorově úspornější, protože rozhodně
     * nemusíme procházet všechny možné stavy a zrychlíme tak větvení.
     *
     * Metoda vždy zjistí hodnotu bývalé vektorové souřadnice X (zjišťuje to
     * pomocí metody getPosunX()) a potom zjistí bývalou vektorovou souřadnici Y
     * (kterou zjišťujeme podobnou metodou getPosunY()).
     *
     * Když metoda zjistí stav, ve kterém se právě had nachází, tak nastaví nové
     * vektorové souřadnice, které otočí hada o 1 pixel "doprava"
     *
     */
    private void doprava() {
        switch (had.getPosunX()) {
            case -1:
                switch (had.getPosunY()) {
                    case -1:
                        had.setPosun(0, -1);
                        break;
                    case 0:
                        had.setPosun(-1, -1);
                        break;
                    case 1:
                        had.setPosun(-1, 0);
                }
                break;
            case 0:
                switch (had.getPosunY()) {
                    case -1:
                        had.setPosun(1, -1);
                        break;
                    case 1:
                        had.setPosun(-1, 1);
                }
                break;
            case 1:
                switch (had.getPosunY()) {
                    case -1:
                        had.setPosun(1, 0);
                        break;
                    case 0:
                        had.setPosun(1, 1);
                        break;
                    case 1:
                        had.setPosun(0, 1);
                }
        }
    }

    /**
     * Metoda doleva() má stejnou definici, jako metoda doprava, pouze otáčí na
     * jinou stranu
     *
     */
    private void doleva() {
        switch (had.getPosunX()) {
            case -1:
                switch (had.getPosunY()) {
                    case -1:
                        had.setPosun(-1, 0);
                        break;
                    case 0:
                        had.setPosun(-1, 1);
                        break;
                    case 1:
                        had.setPosun(0, 1);
                }
                break;
            case 0:
                switch (had.getPosunY()) {
                    case -1:
                        had.setPosun(-1, -1);
                        break;
                    case 1:
                        had.setPosun(1, 1);
                }
                break;
            case 1:
                switch (had.getPosunY()) {
                    case -1:
                        had.setPosun(0, -1);
                        break;
                    case 0:
                        had.setPosun(1, -1);
                        break;
                    case 1:
                        had.setPosun(1, 0);
                }
        }
    }
//############-SOUKROME KONSTRUKTORY-#############
//===============SOUKROME TRIDY================
//==============TESTOVACI METODY===============
}

Třída Had, u které ovádáš hlavičku

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.JPanel;

public class Had extends JComponent implements Runnable {
//###################-ATRIBUTY-###################
//==========KONSTANTNI ATRIBUTY TRIDY==========
//===========PROMENNE ATRIBUTY TRIDY===========
//========KONSTANTNI ATRIBUTY INSTANCI=========

    private final JPanel panel; // Při vytváření nového hada ve Třídě Prostredi, předáváme hadovi panel, abychom na něj mohli vytvořit barieru z této třídy
//=========PROMENNE ATRIBUTY INSTANCI==========
    private Thread vlakno;
    private boolean jede = true; // Logickou proměnnou jede pouožíváme pro while cyklus, který zajišťuje pohyb hada vpřed. Pokud had narazí, proměnná zneguje a had zastaví
    private int x, y;   //proměnné x a y používá had pro práci s budoucí pozicí. Do proměnných se ukládají souřadnice, které představují krok, o který se had posune (hodnoty nabývají od -1 do 1)
//####################-STATIC-####################
//============STATICKY KONSTRUKTOR=============
//=========STATICKE PRISTUPOVE METODY==========
//==============STATICKE METODY================
//=================MAIN METODA=================
//
//    public static void main(String[] args) {
//        new Had();
//    }
//###################-INSTANCE-###################
//=================KONSTRUKTOR=================

    /**
     * V konstruktoru hada pouze předáme panel a pak s ním můžeme pracovat:)
     *
     * @param panel // panel představuje plátno ze třídy Prostredi, na které
     * vykreslujeme hada a barieru
     */
    Had(JPanel panel) {
        this.panel = panel;
    }
//=============PRISTUPOVE METODY===============

    /**
     * Návratová metoda getPosunY() vrací hodnotu, o kterou se had posune vpřed
     * po souřadnici Y
     *
     * @return y //y představuje hodnotu, o kterou se had posune po Y-nové
     * souřadnici
     */
    public int getPosunY() {
        return y;
    }

    /**
     * Návratová metoda getPosunY() vrací hodnotu, o kterou se had posune vpřed
     * po souřadnici X
     *
     * @return x //x představuje hodnotu, o kterou se had posune po X-nové
     * souřadnici
     */
    public int getPosunX() {
        return x;
    }

//===================METODY====================
    /**
     * Paint(Graphics) metoda je zděděná metoda třídy JComponent a díky ní
     * nakreslíme hlavičku hada a nstavíme mu barvu
     *
     * @param g
     */
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.setColor(Color.yellow);
        g.fillOval(0, 0, 10, 10);
    }

    /**
     * Vláknovou třídu run používáme pro pohyb hada. Obsahuje while cyklus,
     * který běží dokud had nenarazí, což hlídá metoda getComponentAt(x,y),
     * která nám zjišťuje, co je "pod námy". Jestli hodnota null, nenarazili
     * jsme, jestli nějaké jméno, narazili jsme a rozbili si hubu
     */
    @Override
    public void run() {
        while (jede) {
            try {
                Thread.sleep(30);   //prodleva, která určuje rychlost hada (nedoporučuju nastavovat na hodnotu 1 :D)
                Bariera bariera = new Bariera(Color.blue); // při každém pohybu hada vytváříme novou barieru. Bariera je jeden oválek o velikosti hlavy hada a tím způsobuje, že had roste
                panel.add(bariera); //díky předanému panelu můžeme i v této třídě kreslit na panel třídy Prostredi
                bariera.setSize(10, 10);
                bariera.setLocation(getX(), getY());
                bariera.setName("BOOM"); //já a moje názvy:D prostě bariera musí obsahovat nějaký název:) když bariera nemá název (takže má null název) tak přes ní had může přejet
                /**
                 * důležitá podmínka, která nám zjišťuje, jestli had narazil
                 * nebo ne. Zjišťujeme budoucí pozici (nebo můžeme zjišťovat
                 * aktuální pozici s tím, že had se do bariery/zdi "zaboří")
                 */
                if (panel.getComponentAt(getX() + getPosunX(), getY() + getPosunY()).getName() != null) {
                    jede = false;
                }
                setLocation(getX() + getPosunX(), getY() + getPosunY()); //posun hada
            } catch (InterruptedException ex) {
            }
        }
    }

    public void start() {
        if (vlakno == null || !vlakno.isAlive()) {
            vlakno = new Thread(this);
            vlakno.start();
        }
    }

    /**
     * Metodu setPosun používáme v tlačítku ve třídě Prostredi a díky ní
     * nastavíme změnu pohybu. Určíme vektorové souřadnice, kterými se má had
     * vydat z aktuální pozice
     *
     * @param x //nová vektorová souřadnice X
     * @param y //nová vektorová souřadnice Y
     */
    public void setPosun(int x, int y) {
        this.x = x;
        this.y = y;
    }
//###############-SOUKROME METODY-################
//=====STATICKE SOUKROME A POMOCNE METODY======
//==========SOUKROME A POMOCNE METODY==========
//############-SOUKROME KONSTRUKTORY-#############
//===============SOUKROME TRIDY================
//==============TESTOVACI METODY===============
}

No a třída Bariera, která slouží jako hadův ocásek

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JComponent;

public class Bariera extends JComponent {

//###################-ATRIBUTY-###################
//==========KONSTANTNI ATRIBUTY TRIDY==========
//===========PROMENNE ATRIBUTY TRIDY===========
//========KONSTANTNI ATRIBUTY INSTANCI=========
    private final Color color;  //Díky tomu, že máme proměnnou color a inicializujeme ji v konstruktoru, tak můžeme v každém novém hadovi nastavovat barvu jeho ocásku.
//=========PROMENNE ATRIBUTY INSTANCI==========
//####################-STATIC-####################
//============STATICKY KONSTRUKTOR=============
//=========STATICKE PRISTUPOVE METODY==========
//==============STATICKE METODY================
//=================MAIN METODA=================
//
//    public static void main(String[] args) {
//        new Bariera();
//    }
//###################-INSTANCE-###################
//=================KONSTRUKTOR=================

    /**
     * V konstruktoru předáváme barvičku pro hadův ocásek:)
     *
     * @param barva //barva, kterou bude mít hadův ocásek
     */
    Bariera(Color barva) {
        color = barva;
    }
//=============PRISTUPOVE METODY===============
//===================METODY====================

    /**
     * Třída bariera se používá jenom proto, aby udělala hadovi ocásek:)
     *
     * @param g //Grafický parametr, který předáváme automaticky metodě předka
     * paint(g);
     */
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.setColor(color);
        g.fillOval(0, 0, 10, 10);
    }
//###############-SOUKROME METODY-################
//=====STATICKE SOUKROME A POMOCNE METODY======
//==========SOUKROME A POMOCNE METODY==========
//############-SOUKROME KONSTRUKTORY-#############
//===============SOUKROME TRIDY================
//==============TESTOVACI METODY===============
}

Pokud by někoho napadlo lepší řešení toho otáčení, tak sem s ním rád se přiučím. (mě totiž nic lepšího nenapadá:( )
Jinak jediné, co se mi v rychlosti nepodařilo debugnout, tak je "žádná" prodlevá při držení tlačítek v metodě keyPressed(Ke­yEvent). Zatím jsem neměl důvod tuto prodlevu řešit - ve svých programech jsem nedržel tlačítka, pouze stiskl:) ale jdu se na to podívat, jak se to dělá.

Akceptované řešení
+20 Zkušeností
+1 bodů
Řešení problému
Nahoru Odpovědět  ±0 26. dubna 18:13
Existují dva způsoby, jak vyřešit problém. Za prvé vyhoďte počítač z okna. Za druhé vyhoďte okna z počítače.
Avatar
Lubor Pešek
Člen
Avatar
Lubor Pešek:

A ještě jenom... všechno ostatní už je otázka ladění, zkoušel jsem si narazit do zni a vyhodí mi to exception, protože se ptáš panelu na getComponentAt(x, y) v místech, kde už není, proto to vyhodí NullPointerEx­ception, což je ale dobré:) ošetři to výjimkou a máš i narážení do zdi:)
A ještě k tomu otáčení - dělá to takové hrany a ne pěkný oblouček. To by se dalo uděla tak, že bys to nepočítal na 8 způsobů, kam to může zatočit, ale třeba bys počítal vektorovou trasu z pixelu 0,0 na pixel 8,8. Bylo by to pracnější a už by ses musel pohrát víc s tím otáčením (protože tímhle způsobem to dělat dokolečka o velikosti 8 pixelů, tak ti to vychází na 62 větví jenom pro x souřadnici. A myslím si, že by tě jeblo, kdybys to měl vypisovat:D Takže pohrát si tady s tímto a máš vyřešené:)

Nahoru Odpovědět 26. dubna 18:25
Existují dva způsoby, jak vyřešit problém. Za prvé vyhoďte počítač z okna. Za druhé vyhoďte okna z počítače.
Avatar
tomkrata
Člen
Avatar
tomkrata:

No páni. Takovouhle reakci jsem teda nečekal:D. Moc ti děkuju za všechny ty rady, určitě budu odteď vytvářet hry tímto stylem. Jsem lehký začátečník, takže si opravdu každé rady velmi cením, zejména této:). Zkusím ten program tedy překopat a využít spíše ty třídy, ale asi mi to chvilku potrvá. Jinak otáčení dělám přes goniometrické funkce. Když nedržím nic na klávesnici, jede to nějakým směrem, a když zatočím, najdu si střed kružnice, okolo kterého se bude otáčet.

public void posunKruh(Hrac[] hrac, int i, Graphics g, boolean doleva, boolean doprava, boolean released)
    {
        if (hrac[i] != null && !isCollision(hrac[i]))
        {
            double tempX = hrac[i].oval.getX();
            double tempY = hrac[i].oval.getY();
            if (doleva)
            {
                double uhel = (angle[i] -= rychlostAnglu / pocetHracu) + curAngle[i];
                double centerX = hrac[i].oval.getPrvniX() - Math.cos(curAngle[i] + Math.toRadians(90)) * vzdalenostCentra;
                double centerY = hrac[i].oval.getPrvniY() - Math.sin(curAngle[i] + Math.toRadians(90)) * vzdalenostCentra;
                hrac[i].oval.setX(centerX - (hrac[i].oval.getPrvniX()-centerX)*Math.cos(uhel) - (hrac[i].oval.getPrvniY()-centerY)*Math.sin(uhel));
                hrac[i].oval.setY(centerY - (hrac[i].oval.getPrvniX()-centerX)*Math.sin(uhel) + (hrac[i].oval.getPrvniY()-centerY)*Math.cos(uhel));
            }
            else if (doprava)
            {
                double uhel = (angle[i] += rychlostAnglu / pocetHracu) - curAngle[i];
                double centerX = hrac[i].oval.getPrvniX() + Math.cos(curAngle[i] + Math.toRadians(90)) * vzdalenostCentra;
                double centerY = hrac[i].oval.getPrvniY() + Math.sin(curAngle[i] + Math.toRadians(90)) * vzdalenostCentra;
                hrac[i].oval.setX(centerX + (hrac[i].oval.getPrvniX()-centerX)*Math.cos(uhel) - (hrac[i].oval.getPrvniY()-centerY)*Math.sin(uhel));
                hrac[i].oval.setY(centerY + (hrac[i].oval.getPrvniX()-centerX)*Math.sin(uhel) + (hrac[i].oval.getPrvniY()-centerY)*Math.cos(uhel));
            }
            else if (released)
            {
                curAngle[i] = angle[i];
                hrac[i].oval.setX((Math.toDegrees(rychlost)) * Math.cos(angle[i]) + hrac[i].oval.getX());
                hrac[i].oval.setY((Math.toDegrees(rychlost)) * Math.sin(angle[i]) + hrac[i].oval.getY());
                hrac[i].oval.setPrvniX(hrac[i].oval.getX());
                hrac[i].oval.setPrvniY(hrac[i].oval.getY());
            }
        }
    }

tuhle metodu předělám trochu elegantněji a příště tam už budou i ty poznámky:D.

 
Nahoru Odpovědět 26. dubna 19:51
Avatar
tomisoka
Redaktor
Avatar
Odpovídá na Lubor Pešek
tomisoka:

No, nevím, ale nezdá se mi, že mít komentář delší než samotný kód je dobrý nápad.
Například toto:


/**
* V konstruktoru předáváme barvičku pro hadův ocásek:)
*
* @param barva //barva, kterou bude mít hadův ocásek
*/

Proč se mi zdá, že jsi mi podal 2 totožné informace?


// Při vytváření nového hada ve Třídě Prostredi, předáváme hadovi panel, abychom na něj mohli vytvořit barieru z této třídy

Koho zajímá, že ty to používáš zrovna ve třídě Prostredi? Co když to budu používat jinou třídou? Nereferuj na jiné třídy, které nejsou v kódu.


/**
 * Třída bariera se používá jenom proto, aby udělala hadovi ocásek:)
 *
 * @param g //Grafický parametr, který předáváme automaticky metodě předka
 * paint(g);
 */
@Override
public void paint(Graphics g) {

Zase zbytečná informace, prakticky jsi popsal co je ten parametr za typ/třídu (což můžeme vidět v parametrech fce) a říkáš, že se to předá předkovi té třídy (což lze jednoduše poznat například podle "super.paint(g);", sice to je až ve fci, ale člověka co nečte samotnou třídu (jen chce vědět co dělá navenek) to stejně nezajímá). A "Třída bariera se používá jenom proto, aby udělala hadovi ocásek:)" by se neměla povalovat u nějaké random fce, měla by být třeba na začátku třídy.


private final Color color;//Díky tomu, že máme proměnnou color a inicializujeme ji v konstruktoru, tak můžeme v každém novém hadovi nastavovat barvu jeho ocásku.

z toho udělej:

private final Color color;//barva ocásku

Rychle, stručně, výstižně. Nikdo nechce číst tvoje kecy okolo.


Je nutno uznat, že:

//###################-ATRIBUTY-###################
//==========KONSTANTNI ATRIBUTY TRIDY==========
//===========PROMENNE ATRIBUTY TRIDY===========
//========KONSTANTNI ATRIBUTY INSTANCI=========
//=========PROMENNE ATRIBUTY INSTANCI==========

je zajímavý systém, který by to mohl trochu zpřehlednit. Zase na druhou stranu, je zbytečné tam mít několik takovýchto kategorií, přičemž je nevyužívat. Doporučil bych je tam dát až dle potřeby.


Ještě k těm doporučením, na co by jsi doporučoval tu třídu "skore"? Přijde mi celkem zbytečná vzhledem k tomu, že bude obsahovat 1 hodnotu...


Mimochodem tady je ten kód na otáčení:

//vec2i je 2D(x,y) int vector
vec2i oldMv = vec2i(x,y);
vec2i oldMv90deg = vec2i(-oldMv.y, oldMv.x);
//vec2i oldMv90deg = vec2i(-oldMv.y, oldMv.x); pro opačný směr

vec2i newMv = oldMv + oldMv90deg; //nový směr, otočeno o 45°

//pokud jsou původní pohyby souběžně s osou, např.:
//vec2i(1,1) = vec2(1,0) + vec2(0,1); vše je v pořádku
//pokud nejsou, např.:
//vec2i(0,2) = vec2(1,1) + vec2(-1,1);
//jak je vidět, je dvoujnásobné délky, musíme ho zkrátit

if(newMv.x==0 || newMv.y==0)
        newMv/=2;

Uprav si dle potřeby.

Pokud by ses rozhodl i pro jiné úhly, použij float vectory a na ně goniometrické fce. Už teď ti to vytváří menší nesmysl - pohyb diagoniálně je rychlejší(√2) než po řádcích (1).

 
Nahoru Odpovědět  +1 26. dubna 20:49
Avatar
Lubor Pešek
Člen
Avatar
Lubor Pešek:

I já děkuju za vyjádření. Je fakt, že od jisté doby to s komentáři přeháním, ale má to svůj důvod. Podívej, já si na to chci zvyknout, protože například teď je všechno jasné - kód je jednoduchý a třeba jak jsem popisoval ten konstruktor, tak máš recht, zkušený programátor je hned v obraze a z větší části by komentář ani nepotřeboval.

Já svými komenty dávám najevo svůj postup přemýšlení (třeba ta reference na jinou třídu), tím jsem chtěl naznačit, způsob, že využívám tu komponentu tímhle způsobem. Jak jsem psal na začátku - osobně beru programování, jako výhodu, že si můžeš zvolit svůj libovolný postup. Jenže říkám si pro sebe dvě ale.

Ale, pokud už teď budu psát stručné komentáře, tak si na to zvyknu a budu to dělat i v případech složitějších programů a tam mi to bude prd platné. A neexistují rozdíli mezi lehkým a náročným programem. Přesně takhle jsem si to říkal celkově u komentářů. "ááále, proč komentovat blbou metodu posunVpravo(int) však je jasné na co to je". No a potom jsem nedělal komentáře nikdy. Už u těch lehkých prográmků se člověk k tomu musí dokopat. (aspoń já su takový, že to musím dodržovat). A ty píšeš přesné a výstižné postřehy, takže soudím, že nejsi junior (a vážím si toho, že sis našel čas a vyjádřil ses ke mě) a tak sám určitě nejlíp víš, jak jsou komentáře nezbytné. Možná máš pravdu, že by stačily více stručné, ale jak jsem řekl, tak do nich vkládám i své úvahy. Myslím, že na škodu to není.

No a druhé ale - proč tam dávám úvahy? protože už se mi doopravdy stalo, že jsem po x letech otevřel zdroják, který fungoval, ale chtěl jsem program vylepšit no a trošku jsem nepochopil, co jsem vlastně měl na mysli a proč je to a to takhle.

Jinak ještě k tomu zdvojenému komentu, který říká to samé:) já trošku rozděluju komentář popisující metodu a komentář pro parametr. Jsou to naprosto stejné věci, já vím, ale zase to beru s ohledem na ostatní. Někteří čtou celý popis metody, druhým (jako třeba tobě) stačí stručné a jasné vyjádření, co se po nich chce a k čemu metoda slouží. Proto si stačí přečíst parametr a hned jim to dojde.

Jo a k té třídě Bariera - to uznávám, že to nepatří k metodě, ale do popisu třídy. Trklo mě to taky, ale pozdě.) to je fakt, to je blbost. A ten popis parametru jsem udělal z povinnosti:D netbeans mi to vygeneroval, tak jsem se chtěl předvést:D takže v tom máš pravdu.

No a nakonec to moje rozvrhování tříd pomocí těch bloků - já jsem si takto nastavil šablonu nových tříd v NetBeans i v Eclipsu (v BlueJ to za mě udělal Ruda Pecinovský:D - mám to od něj) a je fakt, že jsou tam prázdné bloky, ale já to neřeším. Je to moje šablona a snažím se ji dodržovat (i když sem tam se mi to nepodaří, hlavně když nechám automaticky vygenerovat metody). Chci psát pěkné programy, tak se učím komentovat vše co můžu (i když to možná dost přeháním) a hlavně aby měla třída nějaký styl. Taky mě serštve, když si otevřu kód a jsou pod sebou návratová metoda, main metoda, statická, dvě instanční, návratová atd. atd. Kurnik, když hledám definovanou metodu, tak se podívám - aha, je to návratová, tak se podívám na začátek kódu.

Jak jsem psal, mám to od Rudy pecinovského a to taky doporučuju tomkratovi (a všem). Jeho učebnice (myslíme objektově v jazyku Java) má cca 600 stránek, ale čte se rychle a doopravdy můžu říct, že pokud zvládnete a správně pochopíte vše, co v ní je, tak jste kvalifikovaní Java Junioři. Já si ji párkrát celou prošel (pokaždé jsem se přenaučil to, co jsem se naučil blbě:D) A popravdě díky ní mě vzali jako programátora. Teď to nejen využívám, ale učím se další a další věci (snad trošku 1% z programování umím:D)

Nahoru Odpovědět 26. dubna 22:55
Existují dva způsoby, jak vyřešit problém. Za prvé vyhoďte počítač z okna. Za druhé vyhoďte okna z počítače.
Avatar
Lubor Pešek
Člen
Avatar
Lubor Pešek:

kua a jak můžeš vidět, tak v kecání a komentářích se vcelku vyžívám-.-

Nahoru Odpovědět 26. dubna 22:55
Existují dva způsoby, jak vyřešit problém. Za prvé vyhoďte počítač z okna. Za druhé vyhoďte okna z počítače.
Avatar
Lubor Pešek
Člen
Avatar
Lubor Pešek:

Jo a ještě to skore... tak vycházel jsem z té hry achtung die kurve, kde se pohybuje 6 hadů. Takže by si to mohla zpracovávat samostatná komponenta

Nahoru Odpovědět 26. dubna 22:57
Existují dva způsoby, jak vyřešit problém. Za prvé vyhoďte počítač z okna. Za druhé vyhoďte okna z počítače.
Avatar
Lubor Pešek
Člen
Avatar
Odpovídá na tomisoka
Lubor Pešek:

Pokud by ses rozhodl i pro jiné úhly, použij float vectory a na ně goniometrické fce. Už teď ti to vytváří menší nesmysl - pohyb diagoniálně je rychlejší(√2) než po řádcích (1).

s tím už mám zkušenost a řešil jsem to podle kvadrantů. Je to proto, protože obecně vychází goniometrická funkce z osy Y, takže při změně kvadrantu (v 45°) musíme změnit orientační osu na osu X.

Řešil jsem to u skákajících balonků, který umístší na místo A, potáhneš myškou do místa B, pustíš a podle toho, jaká je vzdálenost a směr, tak určíš rychlost a dráhu balonku. Když jsem používal pouze neupravenou goniometrickou funkci, tak to taky pomaličku letělo rovně, ale jak se to blížilo zlomového bodu (víc v ose Y), tak to zrychlilo:D dělalo to sice krásný slow motion efekt při "přeskočení", ale úmysl takový nebyl:D

Ale už dost spamu, ticket poradil (autorovi i mě) tak hlavně já už tu končím:)

Nahoru Odpovědět 26. dubna 23:11
Existují dva způsoby, jak vyřešit problém. Za prvé vyhoďte počítač z okna. Za druhé vyhoďte okna z počítače.
Avatar
JMS
Člen
Avatar
Odpovídá na Lubor Pešek
JMS:

Ty tvoje komentáře, to je fakt extrém. Kód nemá obsahovat tunu komentářů, kód má být čitelný a samopopisující, tedy volit správně názvy proměnných a metod, aby se v něm dalo lehce orientovat. Nikoho nebaví číst desítky řádků komentářů :)

 
Nahoru Odpovědět 27. dubna 19:22
Avatar
Lubor Pešek
Člen
Avatar
Odpovídá na JMS
Lubor Pešek:

Tak očividně jsi neupravoval cizí kod a když už, tak jedno třídný v nějaké jednoduché aplikaci. Než aby nikoho nebavilo číst desítky kódu, tak spíš nikoho nebaví přemýšlet, co měl ten dotyčný tehdy namysli. Osobně nenávidím update cizího programu, protože víc, než updatem, tak víc času ztratím na tom, abych pochopil, co je která proměnná zač. (a nevím jak ty, ale já se ve třech proměnných s názvy tool, myTool a resources vážně hned tak nevyznám a když máš projekt, kde je 25 tříd a v průměru v každé cca 30 metod, tak je to šílený humus)

Když upravuješ cízí kódy, tak se nemáš vymýšlet jak co funguje a přemýšlet k čemu taková proměnná je, ale přidávat vlastní kód. Někdy ti předám nějakou Java classu z našeho projektu a zkus se v něm vyznat. Uvědom si, že programování nekončí tím, že napíšeš int i = 2;

Nahoru Odpovědět 27. dubna 20:51
Existují dva způsoby, jak vyřešit problém. Za prvé vyhoďte počítač z okna. Za druhé vyhoďte okna z počítače.
Avatar
tomisoka
Redaktor
Avatar
Odpovídá na Lubor Pešek
tomisoka:

Ale on nemluví o tom, že by se aktuální kód neměl komentovat. On tvrdí, že názvy tříd, funkcí a proměnných by měly být komentáře sama sebe, pak můžeš kdekoli kde s tím pracuješ hned poznat co to dělá. A to není zrovna jednoduché.
V tomto ideálním kódu by se mělo komentovat, jen nějaká upřesnění, např.:

int direction;
//0 = left; 1 = up; 2 = right; 3 = down;

Nebo vysvětlení nějaké složitější logiky programu, kterou nepoznáš během pár desítek sekund.

Mimochodem 30 metod v jedné třídě je většinou humus samo o sobě.

 
Nahoru Odpovědět  +1 27. dubna 21:19
Avatar
Lubor Pešek
Člen
Avatar
Lubor Pešek:

https://docs.oracle.com/…raphics.html

Namátko vybraná třída, která mě hned napadla. Ještě že tam mají max. 7 metod, 30 by bylo už fakt moc....

Nahoru Odpovědět 27. dubna 22:37
Existují dva způsoby, jak vyřešit problém. Za prvé vyhoďte počítač z okna. Za druhé vyhoďte okna z počítače.
Avatar
tomisoka
Redaktor
Avatar
Odpovídá na Lubor Pešek
tomisoka:

Ano, proto jsem napsal většinou. Pokud se na ty metody podíváš trochu pozorněji, tak si všimneš, že je tam třeba 6 funkcí, jejichž účel je prakticky to samé, jen s jinými parametry (vykreslit ovál, nebo polygon?). A z hlediska složitosti pochopení bych tyto metody počítal jako jednu.

Jinak bylo to spíše myšleno, že průměrné množství metod by nemělo být 30. Někdy se tam takto veliká třída může objevit ( hlavně když je tam několikrát jen trošku upravená metoda), ale je lepší se tomu vyhnout a rozhodně se to nehodí pro celý projekt.

 
Nahoru Odpovědět 27. dubna 23:55
Avatar
Lubor Pešek
Člen
Avatar
Lubor Pešek:

:) trošku mě připomínáš jednoho z mojich šéfů:D neumí programovat, tak ho povýšili, aby nám do toho nekecal. Největší hlod, co z něj teď vylezlo, byl jeho návrh na rozhraní třídy.
"Kód bude obsahovat 200 řádků, tak" a ten vůl navrhl, že budou bohatě stačit dvě metody.... Takových teoretiků je plná prdel.
Divej, ukončíme to, protože nadpis topicu je o pomoci se stavem, kdy had narazí. To je vyřešeno a toto už je jen flame. Prostě já dělám třeba až moc komentářů, je to můj problém, až mi to nařídí šéf, že to chce stručněji, tak se podřídím. Vy byste mě za to vykleštili už teď. Hotovo tečka, kašlem na to jo? nebo kdyžtak si dáme sraz a zajdem na pívko (teda v mém případě kofču, su abstinent;) ).

Nahoru Odpovědět 28. dubna 0:47
Existují dva způsoby, jak vyřešit problém. Za prvé vyhoďte počítač z okna. Za druhé vyhoďte okna z počítače.
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 23 zpráv z 23.