简体   繁体   中英

C# How to Move A Circle Along a Rectangle Path

I need to move a point along a rectangle path at the command of a button. I want it to start at the upper right corner of the rectangle path, but I am not sure how to get it to go all the way around the path and stop at the original point. The screen refreshes at the speed provided by the user in an input box. Thank you in advance!

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Timers;
namespace Assignment_2
{

    public partial class Form1 : Form
    {
        private const int formwidth = 1280;
        private const int formheight = 720;
        private const int ball_a_radius = 10;
        private const int horizontaladjustment = 8;
        private const double ball_a_distance_moved_per_refresh = 1.6;
        private double ball_a_real_coord_x = 515;
        private double ball_a_real_coord_y = 40;
        private int ball_a_int_coord_x;
        private int ball_a_int_coord_y;

        private const double graphicrefreshrate = 30.0;

        private static System.Timers.Timer graphic_area_refresh_clock = new System.Timers.Timer();

        private static System.Timers.Timer ball_a_control_clock = new System.Timers.Timer();
        private bool ball_a_clock_active = false;

        public double speed = 0;

        public Form1()
        {

            InitializeComponent();
            ball_a_int_coord_x = (int)(ball_a_real_coord_x);
            ball_a_int_coord_y = (int)(ball_a_real_coord_y);
            System.Console.WriteLine("Initial coordinates: ball_a_int_coord_x = {0}. ball_a_int_coord_y = {1}.",
                               ball_a_int_coord_x, ball_a_int_coord_y);

            graphic_area_refresh_clock.Enabled = false;  
            graphic_area_refresh_clock.Elapsed += new ElapsedEventHandler(Updatedisplay);


            ball_a_control_clock.Enabled = false; 
            ball_a_control_clock.Elapsed += new ElapsedEventHandler(Updateballa);

            Startgraphicclock(graphicrefreshrate); 
            Startballaclock(speed);    
        }
        public class NumericTextBox : TextBox
        {
        }

            private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void panel2_Paint(object sender, PaintEventArgs e)
        {

        }

        private void panel2_Paint_1(object sender, PaintEventArgs e)
        {
            //Create pen
            Pen blackPen = new Pen(Color.Black, 1);

            //Create rectangle
            Rectangle rect = new Rectangle(125, 50, 400, 400);

            //Draw rectangle to screen
            e.Graphics.DrawRectangle(blackPen, rect);

            Graphics graph = e.Graphics;
            graph.FillEllipse(Brushes.Green, ball_a_int_coord_x, ball_a_int_coord_y, 2 * ball_a_radius, 2 * ball_a_radius);
            base.OnPaint(e);
        }

        public void button7_Click(object sender, EventArgs e)
        {
           speed = Convert.ToInt32(textBox3.Text);

        }

        private void textBox3_TextChanged(object sender, EventArgs e)
        {

        }

        protected void Startgraphicclock(double refreshrate)
        {
            double elapsedtimebetweentics;
            if (refreshrate < 1.0) refreshrate = 1.0;  
            elapsedtimebetweentics = 1000.0 / refreshrate; 
            graphic_area_refresh_clock.Interval = (int)System.Math.Round(elapsedtimebetweentics);
            graphic_area_refresh_clock.Enabled = true;  
        }

        protected void Startballaclock(double updaterate)
        {
            double elapsedtimebetweenballmoves;
            if (updaterate < 1.0) updaterate = 1.0; 
            elapsedtimebetweenballmoves = 1000.0 / updaterate; 
            ball_a_control_clock.Interval = (int)System.Math.Round(elapsedtimebetweenballmoves);
            ball_a_control_clock.Enabled = true;   
            ball_a_clock_active = true;
        }

        protected void Updatedisplay(System.Object sender, ElapsedEventArgs evt)
        {
            Invalidate();  
            if (!(ball_a_clock_active))
            {
                graphic_area_refresh_clock.Enabled = false;
                System.Console.WriteLine("The graphical area is no longer refreshing.  You may close the window.");
            }
        }

        protected void Updateballa(System.Object sender, ElapsedEventArgs evt)
        {
            ball_a_real_coord_x = ball_a_real_coord_x - 5;

            ball_a_real_coord_y = ball_a_real_coord_y - 5;
            ball_a_int_coord_x = (int)System.Math.Round(ball_a_real_coord_x);
            ball_a_int_coord_y = (int)System.Math.Round(ball_a_real_coord_y);


            if (ball_a_int_coord_x >= formwidth || ball_a_int_coord_y + 2 * ball_a_radius <= 0 || ball_a_int_coord_y >= formheight)
            {
                ball_a_clock_active = false;
                ball_a_control_clock.Enabled = false;
                System.Console.WriteLine("The clock controlling ball a has stopped.");
            }

        }

        private void button4_Click(object sender, EventArgs e)
        {
            ball_a_control_clock.Enabled = true;

        }
    }

}

I have a more straightforward way to move a circle. Your code is too long for me to read. See if you like this!

If I were you, I would use a PictureBox . I first create an image of a circle, and then put that image in the PictureBox . Then you can just use a timer to change the position of the PictureBox .

You should set the Interval of the timer to 33 ms, which is roughly 30 fps. This is how you would programme the timer:

Keep a counter to indicate how many pixels the circle has moved. Let's say you want it to move in a 100px x 50px rectangular path.

For every 33ms,
    If the counter is less than 100, 
        increase the X position and the counter by 1, 
    if the counter is between 101 and 150, 
        increase the Y position and the counter by 1, 
    if the counter is between 151 and 250, 
        decrease the X position by 1 and increment the counter
    if the counter is between 251 and 300,
        decrease the Y position by 1 and increment the counter
    if the counter is greater than 300,
        stop the timer

I really don't like drawing stuff on the screen with the OnPaint event. I mean, you are moving a ball! People think of this as changing the x and y positions of a ball, not as deleting the ball at the previous position and drawing it in the new position. Changing the position of the picture box just makes LOTS more sense, don't you think so?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM