Лабораториска вежба 7 - finki-mk/VP GitHub Wiki

Moving Ball

Опис на задачата

Во оваа задача треба да се имплементира цртање на топче кое се движи во рамките на ограничен правоаголник со одредена ширина и висина.

Класа за топче

Најпрво ќе дефинираме класа Ball која ќе го претсавува објектот топче кое ќе се исцртува на екран.

Во оваа класа ќе се чуваат информации за позицијата на топчето (X, Y), радиусот, брзината со која се движи, како и аголот под кој ќе почне да се движи (0, 2Pi). Исто така ќе се чува и објект од класата Rectangle во кој ќе се чуваат границите во кои ќе се движи топчето.

Затоа што топчето почнува да се движи под некој агол, неговите брзини по X и Y оските се посебни компоненти и се пресметуваат со едноставна тригонометрија.

public float X { get; set; }
public float Y { get; set; }

public float Radius { get; set; }

public float Velocity { get; set; }
public float Angle { get; set; }

public Rectangle Bounds;
        
private float velocityX;
private float velocityY;

Конструктор

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

public Ball(float x, float y, float radius, float velocity, float angle)
{
    X = x;
    Y = y;
    Radius = radius;
    Velocity = velocity;
    Angle = angle;
    velocityX = (float)Math.Cos(Angle) * Velocity;
    velocityY = (float)Math.Sin(Angle) * Velocity;
}

Метод за движење

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

public void Move()
{
    float nextX = X + velocityX;
    float nextY = Y + velocityY;
    if (nextX - Radius <= Bounds.Left || (nextX + Radius >= Bounds.Right))
    {
        velocityX = -velocityX;
    }
    if (nextY - Radius <= Bounds.Top || (nextY + Radius >= Bounds.Bottom))
    {
        velocityY = -velocityY;
    }
    X += velocityX;
    Y += velocityY;
}

Метод за исцртување

Овој метод прима аргументи четката Brush со која ќе се црта и објект од класата Graphics врз кој ќе се црта.

public void Draw(Brush brush, Graphics g)
{
    g.FillEllipse(brush, X - Radius, Y - Radius, Radius * 2, Radius * 2);
}

Имплементација на формата во која ќе се исцртува

Кодот на формата за исцртување.

   Timer timer;
   Ball ball;
   Graphics graphics;
   Brush brush;
   Pen pen;
   Rectangle bounds;
   Bitmap doubleBuffer;
   static readonly int FRAMES_PER_SECOND = 30;
   public Form1()
   {
        InitializeComponent();
        bounds = new Rectangle(10, 10, this.Bounds.Width - 40, this.Bounds.Height - 60);
        doubleBuffer = new Bitmap(Width, Height);
        graphics = CreateGraphics();
        ball = new Ball(Width / 2, Height / 2, 20, 10, (float)(Math.PI / 4));
        ball.Bounds = bounds;
        Show();
        brush = new SolidBrush(Color.Blue);
        pen = new Pen(Color.Red);
        timer = new Timer();
        timer.Tick += new EventHandler(timer_Tick);
        timer.Interval = 1000 / FRAMES_PER_SECOND;
        timer.Start();
    }

     void timer_Tick(object sender, EventArgs e)
     {
         Graphics g = Graphics.FromImage(doubleBuffer);
         g.Clear(Color.White);
         g.DrawRectangle(pen, bounds);
         ball.Draw(brush, g);
         ball.Move();
         graphics.DrawImageUnscaled(doubleBuffer, 0, 0);
     }