$$ \newcommand{\floor}[1]{\left\lfloor{#1}\right\rfloor} \newcommand{\ceil}[1]{\left\lceil{#1}\right\rceil} \renewcommand{\mod}{\,\mathrm{mod}\,} \renewcommand{\div}{\,\mathrm{div}\,} \newcommand{\metar}{\,\mathrm{m}} \newcommand{\cm}{\,\mathrm{cm}} \newcommand{\dm}{\,\mathrm{dm}} \newcommand{\litar}{\,\mathrm{l}} \newcommand{\km}{\,\mathrm{km}} \newcommand{\s}{\,\mathrm{s}} \newcommand{\h}{\,\mathrm{h}} \newcommand{\minut}{\,\mathrm{min}} \newcommand{\kmh}{\,\mathrm{\frac{km}{h}}} \newcommand{\ms}{\,\mathrm{\frac{m}{s}}} \newcommand{\mss}{\,\mathrm{\frac{m}{s^2}}} \newcommand{\mmin}{\,\mathrm{\frac{m}{min}}} \newcommand{\smin}{\,\mathrm{\frac{s}{min}}} $$

Prijavi problem


Obeleži sve kategorije koje odgovaraju problemu

Još detalja - opišite nam problem


Uspešno ste prijavili problem!
Status problema i sve dodatne informacije možete pratiti klikom na link.
Nažalost nismo trenutno u mogućnosti da obradimo vaš zahtev.
Molimo vas da pokušate kasnije.

Очитавање тастера и позиције миша

Једноставан начин да у нашим C# програмима сазнамо која дугмета (тастери) миша су притиснута у одређеном тренутку је да користимо својство формулара MouseButtons. Испитивање вршимо поредећи вредност овог својства са одговарајућим константама. На пример, следећом наредбом се проверава да ли је притиснуто лево дугме миша (при томе остала дугмад могу а не морају бити притиснута у исто време):

if ((MouseButtons & MouseButtons.Left) > 0)
    // ...

Константе које одговарају појединим дугметима миша су редом:

  • MouseButtons.Left за лево дугме

  • MouseButtons.Middle за средње дугме (на многим мишевима ово је заправо точкић, који може и да се притисне као дугме)

  • MouseButtons.Right за десно дугме

  • MouseButtons.XButton1 за прво X дугме (ако постоји, ово дугме се најчешће налази ниско са стране)

  • MouseButtons.XButton2 за друго X дугме (ако постоји, ово дугме је са друге стране)

Вредности својства MouseButtons су комбинације ових константи и зато датом if наредбом ми у ствари проверавамо да ли својство MouseButtons „садржи” константу MouseButtons.Left. Једноставнији услов MouseButtons == MouseButtons.Left би проверавао да ли је тренутно притиснуто искључиво лево дугме и ниједно више, што најчешће није оно што нам треба. На пример, ако је истовремено притиснуто лево и десно дугме, услов наведен у if наредби би био испуњен, а овај други не.

Наредни пример илуструје испитивање стања тастера миша.

Црвени, зелени и плави тастер

Написати програм који мења боју позадине формулара у складу са тиме који тастери миша су притиснути. Нека леви, средњи и десни тастер редом одговарају црвеној, зеленој и плавој компоненти боје позадине. Програм треба да периодично проверава стање ових тастера (користити тајмер). Ако је неки тастер притиснут, компонента одговарајуће боје се повећава, а ако није притиснут онда се смањује.

Програм је прилично кратак. Користимо три целобројне променљиве (Crvena, Zelena, Plava) за опис тренутног стања. Помоћна функција PromeniBoju подешава вредност неке од ове три променљиве у зависности од стања тастера, али тако да вредност променљиве не изађе из опсега (0, 255).

У функцији timer1_Tick позивамо помоћну функцију за сваки тастер и одговорајућу компоненту боје, а затим ажурирамо боју позадине и њен запис у насловној линији програма.

using System;
using System.Drawing;
using System.Windows.Forms;

namespace BojaPozadine
{
    public partial class Form1 : Form
    {
        int Crvena = 0;
        int Zelena = 0;
        int Plava = 0;

        public Form1()
        {
            InitializeComponent();
        }

        private void PromeniBoju(MouseButtons dugme, ref int boja)
        {
            if ((MouseButtons & dugme) > 0)
                boja = Math.Min(255, boja + 5);
            else
                boja = Math.Max(0, boja - 5);
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            PromeniBoju(MouseButtons.Left, ref Crvena);
            PromeniBoju(MouseButtons.Middle, ref Zelena);
            PromeniBoju(MouseButtons.Right, ref Plava);
            BackColor = Color.FromArgb(Crvena, Zelena, Plava);
            Text = string.Format("Boja je ({0}, {1}, {2})", Crvena, Zelena, Plava);
        }
    }
}

Испробајте програм да бисте били сигурни да разумете како ове провере раде. Притискајте различите комбинације тастера и пратите као се мења боја и њен запис у насловној линији.


Друга ствар у вези са стањем миша која нас најчешће интересује је његова позиција. Њу сазнајемо помоћу својства Cursor.Position, које је типа Point (дакле, има поља X и Y). Својство Cursor.Position се може и очитавати и постављати, што значи да постављањем вредности овог својства можемо да преместимо курсор миша на жељену позицију на екрану.

Треба имати на уму да нам својство Cursor.Position даје положај курсора миша у координатном систему екрана, а не прозора. То значи да су кооринате које добијемо растојања од леве и горње ивице целог екрана. Нама је најчешће потребна позиција миша у координатном систему клијентског прозора. Да бисмо добили позицију у координатама прозора, користимо функцију PointToClient. Ова функција као параметар прима тачку у координатном систему екрана а као резултат враћа тачку у координатном систему клијентског прозора. Тако, сажетим писањем

Point mis = PointToClient(Cursor.Position);

у променљивој (објекту) mis добијамо позицију курсора миша у систему клијентског прозора.

Следећи пример показује како ову могућност користимо у програму.

Миш - лептир

Стрелицу која стандардно представља курсор миша, заменити двема сликама лептира, које треба наизменично приказивати на позицији миша.

../_images/interact_butterfly1.png ../_images/interact_butterfly2.png

Кључно место у овом програму је израчунавање позиције слике (све остале идеје су већ виђене у неким од претходних примера). Када очитамо позицију миша, позицију слике лептира одређујемо тако да центар те слике буде на месту курсора миша. То постижемо помоћу ових наредби.

Point mis = PointToClient(Cursor.Position);
PozSlike = new Point(mis.X - slika[0].Width / 2, mis.Y - slika[0].Height / 2);

Осим овога, вреди поменути и наредбу Cursor.Hide(); помоћу које се сакрива стандардни курсор миша (стрелица), тако да она неће бити приказивана.

Следи комплетан програм.

using System;
using System.Drawing;
using System.Windows.Forms;

namespace Leptir
{
    public partial class Form1 : Form
    {
        Image[] slika = { Properties.Resources.Leptir1, Properties.Resources.Leptir2 };
        Point PozSlike;
        int IndeksSlike = 0;

        public Form1()
        {
            InitializeComponent();
            ClientSize = new Size(600, 600);
            Text = "Leptir";
            BackColor = Color.White;
            PozSlike = new Point( ClientSize.Width / 2, ClientSize.Height / 2);
            Cursor.Hide();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {

            // koju sliku treba prikazati
            IndeksSlike = 1 - IndeksSlike;

            // gde treba prikazati sliku
            Point mis = PointToClient(Cursor.Position);
            PozSlike = new Point(mis.X - slika[0].Width / 2, mis.Y - slika[0].Height / 2);

            Invalidate();
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            g.DrawImage(slika[IndeksSlike], PozSlike.X, PozSlike.Y);
        }

    }
}

Вероватно сте приметили да када брже померате миша, лептир мало касни за њим. Ово се дешава зато што се приказује само 5 фрејмова у секунди, па кашњење може буде и до 0.2 секунде.

Ово кашњење се лако елиминише тако што повећамо учесталост приказивања (смањимо интервал тајмера), међутим тада се слике смењују превише често и делује да лептир сувише брзо маше крилима.

Решење је да повећамо учесталост приказивања, а да сваку слику приказујемо током више фрејмова. На тај начин реакција на опмерање миша је брза, а лептир маше крилима довољно споро.

Изаберимо да поставимо интервал тајмера на 20 милисекунди. Да би лептир наставио да маше истом брзином (број замаха по секунди), потребно је сваку слику приказивати по 10 фрејмова. Према томе, у новој верзији програма стање се ажурира нешто другачије (наводимо само део који се разликује):

const int BROJ_FREJMOVA_PO_SLICI = 10;
const int BROJ_SLIKA = 2;

int IndeksFrejma = 0;

// ...

private void timer1_Tick(object sender, EventArgs e)
{
    // Broj_frejmova_u_celom_ciklusu = broj_slika * broj_frejmova_po_slici
    // Prema tome, posle (BROJ_SLIKA * BROJ_FREJMOVA_PO_SLICI) frejmova se prikazivanje ponavlja
    // Zato indeks frejma mozemo da racunamo po modulu  (BROJ_SLIKA * BROJ_FREJMOVA_PO_SLICI)
    IndeksFrejma = (IndeksFrejma + 1) % (BROJ_SLIKA * BROJ_FREJMOVA_PO_SLICI);

    // koju sliku treba prikazati
    IndeksSlike = IndeksFrejma / BROJ_FREJMOVA_PO_SLICI;

    // gde treba prikazati sliku
    Point mis = PointToClient(Cursor.Position);
    PozSlike = new Point(mis.X - slika[0].Width / 2, mis.Y - slika[0].Height / 2);

    Invalidate();
}

Према мишу

Напишите програм у коме се зелена лоптица креће ка мишу.

Помоћ: У овом задатку је кључно како се мењају координате \((x, y)\) центра лоптице. У ситуацији као на слици, желимо да x повећамо за dx, а y да повећамо за dy. У зависности од тога како желимо да се лоптица креће, величине dx, dy могу да се израчунају на разне начине. Један једноставан начин је да изаберемо \(dx = {1 \over 10} (xm - x), dy = {1 \over 10} (ym - y)\).

../_images/interact_towards_mouse.png

Према мишу са трагом

Преправите претходни програм тако да лоптица оставља сиви траг, као na slici dole.

../_images/interact_to_mouse_trace.gif

Помоћ: Кретање лоптице је исто као у претходном примеру. Да бисмо направили траг, потребно је памтити низ од неколико (ми смо користили 20) претходних положаја лоптице.

const int DUZINA_TRAGA = 20;
PointF[] Trag = new PointF[DUZINA_TRAGA];

При израчунавању новог стања, у низу претходних положаја најстарији положај лоптице замењујемо најновијим. Ради тога је потребно да у некој променљивој памтимо индекс најстаријег положаја лоптице (код нас је то променљива IndeksRepa)

Trag[IndeksRepa] = new PointF(LopticaX, LopticaY);
IndeksRepa = (IndeksRepa + 1) % DUZINA_TRAGA;

При цртању трага, за сваки круг користимо боју (nijansa, nijansa, nijansa), где је нијанса пре петље једнака 255 (бела), а у петљи се смањује за одређену вредност, тако да у последњем пролазу кроз петљу постане нула, или што ближе нули (црна).

Покушајте да самостално довршите задатак, а ако вам не иде, наше решење можете да погледате овде или да да отворите преузети пројекат.

using System;
using System.Drawing;
using System.Windows.Forms;

namespace Trag
{
    public partial class Form1 : Form
    {
        const int DUZINA_TRAGA = 20;
        PointF[] Trag = new PointF[DUZINA_TRAGA];
        int IndeksRepa = 0;
        float LopticaX;
        float LopticaY;

        public Form1()
        {
            InitializeComponent();
            ClientSize = new Size(400, 400);
            Text = "Trag";
            BackColor = Color.White;

            LopticaX = ClientSize.Width / 2;
            LopticaY = ClientSize.Height / 2;
            for (int i = 0; i < DUZINA_TRAGA; i++)
                Trag[i] = new PointF(LopticaX, LopticaY);
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            // koordinate pozicije misa
            Point mis = PointToClient(Cursor.Position);

            // loptica se pomera ka misu, za deseti deo rastojanja do misa
            LopticaX += 0.1f * (mis.X - LopticaX);
            LopticaY += 0.1f * (mis.Y - LopticaY);

            // Niz Trag se koristi kao kruzni bafer (svaki put se pregazi najstariji polozaj - rep)
            Trag[IndeksRepa] = new PointF(LopticaX, LopticaY);
            IndeksRepa = (IndeksRepa + 1) % DUZINA_TRAGA;

            Invalidate();
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            int R = 10; // plouprecnik loptice
            int nijansa = 255; // nijansa se menja od bele ka crnoj
            for (int i = 0; i < DUZINA_TRAGA; i++)
            {
                // Trag se iscrtava "od repa ka glavi"
                // (tacka na poziciji IndeksRepa je najstarija, najdalja i najsvetlija,
                // a zatim dolaze sve novije i tamnije tacke)
                Brush cetka = new SolidBrush(Color.FromArgb(nijansa, nijansa, nijansa));
                PointF p = Trag[(IndeksRepa + i) % DUZINA_TRAGA];
                g.FillEllipse(cetka, p.X - R, p.Y - R, 2 * R, 2 * R);
                nijansa -= 12;
            }
        }
    }
}

Ласерски мач

Написати програм који „активира мач” нацртаног лика на притисак левог тастера миша. На слици испод, мач је приказан светло плавом бојом, али само док је тастер миша притиснут.

У горњем левом углу је све време зеленом бојом приказана преостала „енергија” за мач, која се види све време. Када је тастер миша притиснут енергија се троши, а када није притиснут енергија се допуњава, тако да знамо колико ће мач бити моћан ако се активира.

../_images/interact_sword.gif

Сцена је описана тренутном количином енергије и тренутном дужином мача. У програму се за опис сцене користе променљиве DuzinaMaxMacaX, DuzinaMaxMacaY и Energija.

У функцији timer1_Tick за ажурирање фрејма, све активности зависе од стања тастера миша. Ако је тастер притиснут, треба смањити енергију (али не испод 0) и подесити дужину мача сразмерно енергији. Ако тастер није притиснут, треба повећати енергију и дужину мача поставити на 0.

У функцији Form1_Paint за цртање, треба приказати показивач енергије, борца и елентуално мач. Показивач енергије довољно добро изгледа ако се представи помоћу два правоугаоника исте величине, од којих је један попуњен, а други је само оквир.

Који од ова два правоугаоника треба нацртати први и зашто?

Покушајте прво да овај задатак решите сами по датим идејама, а затим погледајте и наше решење овде или у преузетом пројекту.

using System;
using System.Drawing;
using System.Windows.Forms;

namespace LaserskiMac
{
    public partial class Form1 : Form
    {
        const float DuzinaMaxMacaX = 250.0f;
        const float DuzinaMaxMacaY = -170.0f;
        const float MaxEnergija = 100.0f;
        float Energija = 100.0f;
        float DuzinaMacaX;
        float DuzinaMacaY;
        Image Borac = Properties.Resources.Borac;

        public Form1()
        {
            InitializeComponent();
            Text = "Laserski mač";
            BackColor = Color.SkyBlue;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (Control.MouseButtons == MouseButtons.Left)
            {
                Energija = Math.Max(Energija - 0.5f, 0);
                DuzinaMacaX = DuzinaMaxMacaX * Energija / MaxEnergija;
                DuzinaMacaY = DuzinaMaxMacaY * Energija / MaxEnergija;
            }
            else
            {
                Energija = Math.Min(Energija + 3, MaxEnergija);
                DuzinaMacaX = 0;
                DuzinaMacaY = 0;
            }

            Invalidate();
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            Brush cetka = new SolidBrush(Color.LimeGreen);
            Pen crnaOlovka = new Pen(Color.Black);
            Pen olovkaZaMac = new Pen(Color.Cyan, 10);

            // Pokazivac energije
            g.FillRectangle(cetka, 10, 10, 10 + Energija, 15);
            g.DrawRectangle(crnaOlovka, 10, 10, 10 + MaxEnergija, 15);

            // Borac
            int slX = 0, slY = ClientSize.Height - Borac.Height;
            g.DrawImage(Borac, slX, slY);

            // Mac
            int macX = slX + 93, macY = slY + 109; // prednja saka je na (93, 109) u koord. sistemu slike
            g.DrawLine(olovkaZaMac, macX, macY, macX + DuzinaMacaX, macY + DuzinaMacaY);
        }
    }
}

Очи

Написати програм који црта очи, тако да прате положај курсора миша.

../_images/interact_eyes.gif

Свако око можемо приказати помоћу једне веће кружне линије и мањег круга попуњеног црном бојом, који ће представљати зеницу. Кружна линија ће бити непокретна, а црни круг (зеница) ће се померати. Означимо положај курсора миша са M, центар великог круга са O, а центар зенице са C. Да би се стекао утисак да око гледа у стрелицу, тачку C треба поставити тако да тачке M, O и C буду колинеарне.

../_images/interact_eyes_coord.png

То значи да координате тачке C можемо да одредимо помоћу формула \(X_C = X_O + k \cdot (X_M - X_O), Y_C = Y_O + k \cdot (Y_M - Y_O)\), где је k коефицијент који тек треба одредити. Овај коефицијент нам говори за који део вектора \(\vec{OM}\) се померамо од тачке O.

Када је тачка M ван ока, онда мали круг треба да додирује велики изнутра (као на слици). Тада коефицијент k одређујемо као \(k = {r_o - r_z} \over d(M, O)\), где је \(r_o\) полупречник великог круга (ока), \(r_z\) плупречник зенице, а \(d(M, O)\) растојање између тачака M и O. Иста релација важи када је тачка M унутар ока, али на растојању бар \(r_o - r_z\) од центра ока. Када је тачка M на мањем растојању, онда је померамо за цео вектор \(\vec{OM}\) од центра ока, то јест узимамо \(k = 1\). У програму се део који обавља ова израчунавања налази у функцији PolozajZenice.

using System;
using System.Drawing;
using System.Windows.Forms;

namespace Oci
{
    public partial class Form1 : Form
    {
        Point LevoOko, DesnoOko, LevaZenica, DesnaZenica;
        int OkoR, ZenicaR;

        public Form1()
        {
            InitializeComponent();
            Text = "Oči";
            BackColor = Color.White;

            OkoR = ClientSize.Width / 6;                     // poluprečnik oka
            ZenicaR = ClientSize.Width / 10;                 // poluprečnik zenice
            int cx = ClientSize.Width / 2;
            int cy = ClientSize.Height / 2;
            LevoOko = new Point(cx / 2, cy);   // stalni polozaj centra levog oka
            DesnoOko = new Point(3*cx / 2, cy);  // stalni polozaj centra desnog oka
            LevaZenica = new Point(cx - 2 * OkoR, cy);   // pocetni polozaj centra leve zenice
            DesnaZenica = new Point(cx + 2 * OkoR, cy);  // pocetni polozaj centra desne zenice
        }

        private float Rastojanje(Point a, Point b)
        {
            return (float)Math.Sqrt((a.X - b.X) * (a.X - b.X) + (a.Y - b.Y) * (a.Y - b.Y));
        }

        private Point PolozajZenice(Point oko, Point mis)
        {
            float D = Rastojanje(mis, oko);
            float DMax = OkoR - ZenicaR;

            // k je deo vektora (oko, mis) za koji se pomeramo od centra oka
            float k = (D > DMax) ? DMax / D : 1;
            return new Point((int)(oko.X + k * (mis.X - oko.X)), (int)(oko.Y + k * (mis.Y - oko.Y)));
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            LevaZenica = PolozajZenice(LevoOko, PointToClient(Cursor.Position));
            DesnaZenica = PolozajZenice(DesnoOko, PointToClient(Cursor.Position));

            Invalidate();
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;

            Pen olovka = new Pen(Color.Black, 2);
            g.DrawEllipse(olovka, LevoOko.X - OkoR, LevoOko.Y - OkoR, 2 * OkoR, 2 * OkoR);
            g.DrawEllipse(olovka, DesnoOko.X - OkoR, DesnoOko.Y - OkoR, 2 * OkoR, 2 * OkoR);

            Brush cetka = new SolidBrush(Color.Black);
            g.FillEllipse(cetka, LevaZenica.X - ZenicaR, LevaZenica.Y - ZenicaR, 2 * ZenicaR, 2 * ZenicaR);
            g.FillEllipse(cetka, DesnaZenica.X - ZenicaR, DesnaZenica.Y - ZenicaR, 2 * ZenicaR, 2 * ZenicaR);
        }
    }
}

Јо-јо

Написати програм који приказује кретање лоптице тако, као да је везана еластичном нити за курсор миша.

../_images/interact_yoyo.gif

За писање овог програма, поред овде приказаних техника програмирања потребно је и мало знања физике (еластична сила, други Њутнов закон). Погледајте програм, без обавезе да га потпуно разумете. Ако желите, пробајте да мало измените неке константе, па видите како то утиче на рад програма.

using System;
using System.Drawing;
using System.Windows.Forms;

namespace Jojo
{
    public partial class Form1 : Form
    {
        PointF Mis; // U koordinatnom sistemu sveta (u metrima)
        PointF Loptica; // izracunava se za svaki frejm (u koordinatnom sistemu sveta u metrima)
        float BrzinaX, BrzinaY; // izracunava se za svaki frejm (u m/s)

        float DuzinaLastisa = 0.4f; // neistegnutog, u metrima (40 cm)
        const float MasaLoptice = 0.1f; // u kilogramima (100 grama)
        float RLoptice = 0.05f; // poluprecnik loptice u metrima (5 cm)
        const float KoefElasticnosti = 17.38f; // u N/m
        float Dt; // vremenski korak u sekundama (bice procitan is svojstva Interval tajmera)
        const float UPiksele = 200.0f; // Jednom metru odgovara 200 piksela
        const float UMetre = 1.0f / UPiksele;

        public Form1()
        {
            InitializeComponent();
            ClientSize = new Size(400, 400);
            Text = "Jo-jo";
            BackColor = Color.White;

            float cx = ClientSize.Width / 2;
            float cy = ClientSize.Height / 2;
            Loptica = new PointF(cx * UMetre, cy * UMetre);
            BrzinaX = BrzinaY = 0.0f;
            Dt = timer1.Interval * 0.001f; // u sekundama
        }

        private float Rastojanje(PointF a, PointF b)
        {
            return (float)Math.Sqrt((a.X - b.X) * (a.X - b.X) + (a.Y - b.Y) * (a.Y - b.Y));
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            Point m = PointToClient(Cursor.Position); // m.X, m.Y su u pikselima u koordinatnom sistemu prozora
            Mis = new PointF(m.X * UMetre, m.Y * UMetre);
            float d = Rastojanje(Mis, Loptica);
            float ax = 0, ay = 9.81f; // vektor ubrzanja loptice koji potice od tezine loptice
            if (d > DuzinaLastisa)
            {
                // elasticna sila uzrokuje dodatno ubrzanje ka osloncu (misu)
                float istezanje = d - DuzinaLastisa;
                float sila = KoefElasticnosti * istezanje;

                ax += sila * (Mis.X - Loptica.X) / d;
                ay += sila * (Mis.Y - Loptica.Y) / d;
            }

            BrzinaX += ax * Dt; // nova brzina
            BrzinaY += ay * Dt;
            float x1 = Loptica.X + BrzinaX * Dt; // novi polozaj
            float y1 = Loptica.Y + BrzinaY * Dt;

            if (x1 < RLoptice || x1 > ClientSize.Width * UMetre - RLoptice)
            {
                // Odbijanje od levog ili desnog zida
                BrzinaX = -0.9f * BrzinaX;
                Loptica.Y = y1;
            }
            else if (y1 < RLoptice || y1 > ClientSize.Height * UMetre - RLoptice)
            {
                // Odbijanje od gornjeg ili donjeg zida
                Loptica.X = x1;
                BrzinaY = -0.9f * BrzinaY;
            }
            else
            {
                Loptica.X = x1;
                Loptica.Y = y1;
            }

            Invalidate();
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;

            // Nacrtaj lastis
            Pen olovka = new Pen(Color.Black, 2);
            g.DrawLine(olovka, Mis.X * UPiksele, Mis.Y * UPiksele,
                Loptica.X * UPiksele, Loptica.Y * UPiksele);

            // Nacrtaj lopticu
            Brush cetka = new SolidBrush(Color.DarkGreen);
            g.FillEllipse(cetka, (Loptica.X - RLoptice) * UPiksele, (Loptica.Y - RLoptice) * UPiksele,
                (2 * RLoptice) * UPiksele, (2 * RLoptice) * UPiksele);
        }
    }
}