C# simulace stisku klávesy – .NET – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

C# simulace stisku klávesy – .NET – Fórum – Programujte.comC# simulace stisku klávesy – .NET – Fórum – Programujte.com

 

8ndra
~ Anonymní uživatel
4 příspěvky
23. 11. 2012   #1
-
0
-

Ahoj, mam hru kde se pohybuji pomocí šipek a chci tam přidat "nápovědu", když stisknu klávesu [H], tak chci aby se mi opakovala metoda Vyres a každý krok byl zpožděný o 20ms. Mám to řešeno takhle:

 public static bool pomoc = false;  //zjistuje, jestli chci pomoc
        public static bool ZpracujPohyb(Keys tlacitko)
        {
            // promenna vyuzita pro ulozeni vysledku pohybu (zda jsme v cili ci ne)
            bool vysledek = false;
              
            // na zaklade stisknuteho tlacitka proved danou operaci

            if (!pomoc)
            {
                switch (tlacitko)
                {


                    case Keys.Up:
                        vysledek = Bludiste.JdiNahoru();
                        break;
                    case Keys.Down:
                        vysledek = Bludiste.JdiDolu();
                        break;
                    case Keys.Left:
                        vysledek = Bludiste.JdiVlevo();
                        break;
                    case Keys.Right:
                        vysledek = Bludiste.JdiVpravo();
                        break;
                    case Keys.H:
                        vysledek = false;
                        pomoc = true;
                        break;


                }
                // na zaver vratime vysledek pohybu
            }  else {
                
                SendKeys.Send("k");           //simulace klavesy
                vysledek = Bludiste.Vyres();
                Thread.Sleep(20);
                
                
                
                } 
            return vysledek;
        }

myšleno je to tak, že dokud mačkám šipky, tak se pohybuji podle jejich směru, když zmáčku H, tak se mi spustí režim nápovědy a bude se mi každý krok metody Vyres zobrazovat. Takhle jak to mám, tak ta nápověda jede, ale zobrazí se mi až výsledek. Když zmáčknu šipku, zobrazí se mi normálně pohyb. Metoda Vyres je řešena pomocí metod JdiVlevo, JdiVpravo...

Když smažu tu simulaci klávesy SendKeys.Send("k"); tak mi to po stisku jakýkoli klávesy jede jak chci, myslel jsem, že tou simulací to prostě nebude čekat až něco zmáčknu a zmáčkne se to samo

Prosím o nějaký nápad, kdyby to chtěl někdo zkoumat ví, rád pošlu celý kód, myslím, že takhle na webu je to nepřehledný. Děkuju, 8ndra.

Nahlásit jako SPAM
IP: 193.84.36.–
ingiraxo+15
Grafoman
24. 11. 2012   #2
-
0
-

proč vůbec odesíláš klávesu "k" ? nestačilo by jen zavolat fci Vyres() async ?

Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
8ndra
~ Anonymní uživatel
4 příspěvky
24. 11. 2012   #3
-
0
-

Protože mi to přišlo nejjednodušší, což jsem se asi spletl. Když jsem tam neměl tu automatickou klávesu, tak to čekalo na mě, až něco zmáčknu, tak sem myslel, že když tam nějakou pošlu, že to bude mít stejnej efekt. Nevim proč to tak neni, proč se to refreshuje až na konci.

Nahlásit jako SPAM
IP: 77.104.245.–
ingiraxo+15
Grafoman
24. 11. 2012   #4
-
0
-

Nevim jak to celý máš řešený, ale tipnul bych si, že ti to jede ve steným vlákně, takže jestli chceš pozorovat postup řešení (každých 30ms), tak to pusť ve vlastním vlákně nebo async jak jsem psal

takto se ti kompletní stav zaktualizuje, až když skončí funkce Vyres(), což asi nechceš

Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
8ndra0
Duch
24. 11. 2012   #5
-
0
-

Koukal jsme co async znamená a bohužel jsem to nepochopil.

přesně jak píšeš, chci aby se mi ten stav zaktualizoval po každým kroku, ne až na konci.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace KravaNaUteku
{
    // parcialni trida predstavujici hlavni formular aplikace
    public partial class Form1 : Form
    {
        // z repozitare prostredku nacteme do promennych jednotlive pouzite bitmapy 
        Image stena = global::KravaNaUteku.Properties.Resources.dlazdice;
        Image krava = global::KravaNaUteku.Properties.Resources.krava;
        Image vychod = global::KravaNaUteku.Properties.Resources.vychod;
        Image zluta = global::KravaNaUteku.Properties.Resources.zluta;
        Image cervena = global::KravaNaUteku.Properties.Resources.cervena;

        // konstruktor formulare
        public Form1()
        {
           
                InitializeComponent();
                // rekneme tride Bludiste, ze pri volani delegata refresh se bude pouzivat metoda PrekresliBludiste
                Bludiste.refresh += new PanelRefresh(PrekresliBludiste);
            
          
        }

        // event handler udalosti onPaint formulare;
        // slouzi k vykresleni bludiste na Graphics double bufferovaneho panelu
        public void panelDoubleBuffer1_Paint(object sender, PaintEventArgs e)
        {
            // z PaintEventArgs si vezmeme Graphics panelu
            Graphics g = e.Graphics;

            // projdeme celou strukturu bludiste
            for (int y = 0; y < 25; y++)  // radky
            {
                for (int x = 0; x < 35; x++)  // sloupce
                {
                    // pokud je na dane pozici stena, tak ji vykreslime
                    if (Bludiste.JeStena(x,y)) g.DrawImage(stena, x * 25, y * 25);
                    if (Bludiste.Zluta(x, y)) g.DrawImage(zluta, x * 25, y * 25);
                    if (Bludiste.Cervena(x, y)) g.DrawImage(cervena, x * 25, y * 25);
                }
            }

            // nakonec nakreslime kravu na jeji aktualni pozici
            g.DrawImage(krava, Bludiste.pozice.x * 25, Bludiste.pozice.y * 25);
            // a vychod z bludiste
            g.DrawImage(vychod, Bludiste.vychod.x * 25, Bludiste.vychod.y * 25);
        }

        // tato metoda je volana delegatem Bludiste.refresh
        // nedela nic jineho, nez ze metodou Invalidate naseho upraveneho panelu iniciuje jeho prekresleni
        public void PrekresliBludiste()
        {
            panelDoubleBuffer1.Invalidate();
        }

        // event handler pro udalost onKeyDown formulare
        // zpracovava stisk klavesy

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            
            // nacte si informace o stisknute klavese z KeyEventArgs
           
                Keys tlacitko = e.KeyData;

                // zavola metodu, ktera dane tlacitko zpracuje a provede pohyb kravou;
                // metoda vraci bool hodnotu podle toho, zda se dorazilo do cile nebo ne

               bool vysledek = ZpracujPohyb(tlacitko);
            
            // pokud krava dorazila do cile, tak:
            if (vysledek)
            {
                Zabuc();  // zabucime
                MessageBox.Show("Hurá! Kráva je venku.");  // vypiseme hlasku
                Bludiste.NoveBludiste();  // vygenerujeme nove bludiste
                pomoc = false;

            }

        }

        // prehraje zvuk buceni ulozeny v repozitari zdroju
        private void Zabuc()
        {
            System.Media.SoundPlayer sound = new System.Media.SoundPlayer();
            sound.Stream = global::KravaNaUteku.Properties.Resources.buu;
            sound.Play();
        }

        // metoda zpracovavajici pohyb kravy na zaklade stisknute klavesy
        public static bool pomoc = false;  //zjistuje, jestli chci pomoc
        public static bool ZpracujPohyb(Keys tlacitko)
        {
            // promenna vyuzita pro ulozeni vysledku pohybu (zda jsme v cili ci ne)
            bool vysledek = false;
              
            // na zaklade stisknuteho tlacitka proved danou operaci

            if(pomoc)
            {
               // SendKeys.Send("H");
               // vysledek = Bludiste.Vyres();
               // Thread.Sleep(20);


            }
            else
            {
                switch (tlacitko)
                {


                    case Keys.Up:
                        vysledek = Bludiste.JdiNahoru();
                        break;
                    case Keys.Down:
                        vysledek = Bludiste.JdiDolu();
                        break;
                    case Keys.Left:
                        vysledek = Bludiste.JdiVlevo();
                        break;
                    case Keys.Right:
                        vysledek = Bludiste.JdiVpravo();
                        break;
                    case Keys.H:
                        vysledek = false;
                        pomoc = true;
                        break;


                }
                // na zaver vratime vysledek pohybu


                




            }
                return vysledek;
            
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

    }
}

Je to do školy, tak je mi blbý se takhle ptát, ale bohužel s tím nedokážu hnout sám a neznám nikoho kdo by to uměl. Kromě učitele samozřejmě.

Jak to chápu já: na začátku se mi vykreslí bludiště a kód jede až k "private void Form1_KeyDown(object sender, KeyEventArgs e)" což čeká na stisk klávesy, když zmáčknu šipku proběhne mi "ZpracujPohyb", takže podle šipky (třeba vlevo) se mi zavolá "JdiDoleva" v metodě JdiDoleva se mi změní souřadnice a do "vysledek" vrátim false, protože ještě nejsem v cíli, pak mi program skočí znovu na začátek, překreslí se celý bludiště, s novou polohou, a zase vleze do "Form1_KeyDown" a čeká na tlačítko, Teď když zmáčknu H, tak se mi nastaví proměnná pomoc na true, program pujde zas na začátek, bludiště se překreslí. A v tom potřebuju aby mi to skočilo do Vyres() a v podstatě to proběhlo stejně jako je to v tom From1_KeyDown, tedy změnit polohu >vykreslit >změnit polohu>vykreslit... až do cíle a aby to nebylo hned, tak tam bude zpoždění 30ms po každým kroku.

Můj původní nápad byl takový, že v momnetě kdy už chci volat Vyres(), tak nebudu čekat na klávesu, ale budu simulovat její stistk. Asi by bylo lepší v případě pomoc=true se do KeyDown vůbec nedostat, ale to taky nevím jak obejít. Nějak nechápu když jde program od shora dolu, tak do který metody vleze hned jak jí potká, a do kterejch leze jenom když jsou volány.

Je aspoň postup, kterým si myslím, že program jde shodný s tim postupem programu? Děkuju.

Nahlásit jako SPAM
IP: 213.192.6.–
ingiraxo+15
Grafoman
24. 11. 2012   #6
-
0
-

celkem jo, ale Form1_KeyDown nečeká na stisk, ale zachytává stisk (událost)

další věc je (sice to na to nemá vliv), ale když komentuješ takto funkce, třídy apod.,tak používej dokumentační komentáře (3x ///)

to vyřešení ti musí jít v separátním vlákně, pokud to zavoláš takto, tak se ti to vykreslí až když je vše hotovo

můžeš to udělat několika způsoby, nejsnažší způsob je přes async/await z .net4.5 nebo použít ThreadPool nebo normální vlákno, stačí si vybrat...

jde o to, že Thread.Sleep(30) jak tam máš, tak uspí hlavní vlákno a celá aplikace se kvůli tomu "zasekne" a zobrazí se ti až výsledek

jedna možnost je třeba vytvořit tu funkci Vyres() async.. jako 

public async void VyresAsync()
{
    while (/* podminka */)
    {
        // kod pro vyreseni

        await Task.Delay(30);
    }
}

funkce se ti pak spustí async, že nebude program blokovat a uvidíš progress každých 30ms

nebo použij normální vlákno.. nevim co jste všechno brali ve škole

úplně základní použití čistýho vlákna máš jako 

// kde "Vyres" je bezparametrická void funkce
new Thread(new ThreadStart(Vyres)).Start();

ale bude potřeba ošetřit zásah do hlavního vlákna (jinak ThreadCrossOper.)

a pokud ThreadPool, tak třeba takto nějak 

ThreadPool.QueueUserWorkItem(new WaitCallback(o =>
{
    // tvuj kod
}), null);
Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
8ndra0
Duch
24. 11. 2012   #7
-
0
-

ok, děkuju, kouknu na to asi až zítra v noci, ale jenom pro upřesnění přidám jak vypadá to moje vyřeš, protože si myslím, že by mělo zkončit vždy po jendom kroku a pak se zavolat znovu 

public static bool Vyres()
        {    //kdyz je krava na zacatku, tak jde smerem do bludiste
            if (pozice.x == start.x && pozice.y == start.y)
            {
                bludiste[pozice.x, pozice.y] = 2;
                if (pozice.x == 34)
                    JdiVlevo();
                if (pozice.y == 0)
                    JdiDolu();
                if (pozice.y == 24)
                    JdiNahoru();
                if (pozice.x == 0)
                    JdiVpravo();
            }
                //kráva jde nejdřív tam, kde ještě nebyla
            else
            {
                if (bludiste[pozice.x + 1, pozice.y] == 1 || bludiste[pozice.x, pozice.y + 1] == 1 || bludiste[pozice.x - 1, pozice.y] == 1 || bludiste[pozice.x, pozice.y - 1] == 1)
                {
                    
                        bludiste[pozice.x, pozice.y] = bludiste[pozice.x, pozice.y] + 1; //oznacuje zlutou
                        if (bludiste[pozice.x - 1, pozice.y] == 3 || bludiste[pozice.x + 1, pozice.y] == 3 || bludiste[pozice.x, pozice.y - 1] == 3 || bludiste[pozice.x, pozice.y + 1] == 3)
                            bludiste[pozice.x, pozice.y] = bludiste[pozice.x, pozice.y] - 1; //při návratu si neucpu křižovatku

                    if (bludiste[pozice.x + 1, pozice.y] == 1)
                    {
                        JdiVpravo();
                        

                    }
                    else if (bludiste[pozice.x, pozice.y - 1] == 1)
                    {
                        JdiNahoru();
                        
                    }
                    else if (bludiste[pozice.x - 1, pozice.y] == 1)
                    {
                        JdiVlevo();
                        
                    }
                    else if (bludiste[pozice.x, pozice.y + 1] == 1)
                    {
                        JdiDolu();
                        
                    }
                    
                }
                else //tohle řeší slepou uličku
                {
                    if ((bludiste[pozice.x + 1, pozice.y] == 0 && bludiste[pozice.x, pozice.y + 1] == 0 && bludiste[pozice.x, pozice.y - 1] == 0) || (bludiste[pozice.x + 1, pozice.y] == 0 && bludiste[pozice.x - 1, pozice.y] == 0 && bludiste[pozice.x, pozice.y - 1] == 0) || (bludiste[pozice.x - 1, pozice.y] == 0 && bludiste[pozice.x, pozice.y - 1] == 0 && bludiste[pozice.x, pozice.y + 1] == 0) || (bludiste[pozice.x, pozice.y + 1] == 0 && bludiste[pozice.x - 1, pozice.y] == 0 && bludiste[pozice.x - 1, pozice.y] == 0))
                    {
                        bludiste[pozice.x, pozice.y] = bludiste[pozice.x, pozice.y] + 2;
                    }
                    else //kráva jde na krizovatce tam, kde jeste nebyla
                    {
                        bludiste[pozice.x, pozice.y] = bludiste[pozice.x, pozice.y] +1 ;  //oznacuje cervenou
                    }

                    if (bludiste[pozice.x + 1, pozice.y] == 2)
                    {
                         JdiVpravo();
                                                
                        
                    }
                    else if (bludiste[pozice.x, pozice.y - 1] == 2)
                    {
                        JdiNahoru();
                        
                    }
                    else if (bludiste[pozice.x - 1, pozice.y] == 2)
                    {
                        JdiVlevo();
                        
                    }
                    else if (bludiste[pozice.x, pozice.y + 1] == 2)
                    {
                        JdiDolu();
                        
                    }
                }
            }
            

            if (pozice.x == vychod.x && pozice.y == vychod.y)
                return true;
               
                
            return false;
            }   
        
        }

a ještě například

public static bool JdiDolu()
        {
            if (pozice.y < 24)
            {
                if (bludiste[pozice.x, pozice.y + 1] == 1 || bludiste[pozice.x, pozice.y + 1] == 2)
                {
                    pozice.y++;
                    if (refresh != null) refresh();
                }
                if (pozice.x == vychod.x && pozice.y == vychod.y)
                    return true;
            }
            return false;
        }

vím, že u toho vyřeš nejsou ty podmínky uplně pěkně napsaný, a bohužel to zatím nefunguje uplně podle mých představ, ale teď jsem se zaměřil na to vykreslování průběhu, abych to mohl kontrolovat. Ještě dodám, že jsem dostal funkční program s bludištěm a za úkol bylo, aby se kráva z bludiště dostala sama.

Nahlásit jako SPAM
IP: 213.192.6.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 9 hostů

Podobná vlákna

Simulace stisku klávesy — založil vowo

Simulace stisku kláves — založil Vlasta

Délka stisku klávesy — založil Kenda

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý