在不同的动画中制作以不同速度移动的winforms图片框动画

e5nszbig  于 2023-03-03  发布在  其他
关注(0)|答案(1)|浏览(161)

如果图像福尔斯第一个if语句中,我尝试让它旋转。这可以工作,但是旋转速度非常快(由于动画是60 fps,所以它旋转60次/秒)。我怎样才能把它分开,使它像其他的一样向下移动,但是旋转又好又慢呢?多线程是这里显而易见的方法,但是我尝试过的任何方法(几乎任何你可以在2小时内从谷歌或chatgpt得到的东西)都会导致访问错误,因为有两个不同的线程修改同一个对象。Here is a short clip to demonstrate the issuehere is the repo,如果这有帮助的话。

public void AniLoop()
        {
            System.Windows.Forms.Timer loop = new System.Windows.Forms.Timer();
            //60fps
            loop.Interval = 16;
            loop.Tick += (object sender, EventArgs e) =>
            {
                Animate(precip_type);
            };
            loop.Start();
        }
        //setup values shared by all precip types 
        static int list_index;
        static List<PictureBox> temp_list;
        static Rectangle hit_detection;
        static bool hit_edge;
        static Random rn_index;
        //shared between all precip types, with rotation added for snow
        public void Animate(string pt)
        {   
            rn_index = new Random();
            rn_index.Next(0, precalculations_list.Count - 1);
            temp_list = picture_boxes.ToList();
            hit_detection = pm.ClientRectangle;
            hit_edge = false;
            foreach (PictureBox pb in temp_list)
            {
                list_index = rn_index.Next(0, precalculations_list.Count - 1);
                pb.Top += added_pix_int + precalculations_list[list_index];
                pb.Left += s_d;
   
                if (pt != "Rain")
                {
                    Image img = pb.Image;
                    img.RotateFlip(RotateFlipType.Rotate90FlipNone);
                    pb.Image = img;

                }

                //when one touches the edge of the screen, clear the list/boxes 
                if (pb.Left < hit_detection.Left ||
                    pb.Right > hit_detection.Right ||
                    pb.Bottom > hit_detection.Bottom)
                {
                    pm.Controls.Remove(pb);
                    picture_boxes.Remove(pb);
                    hit_edge = true;
                }

            }
            //cannot modify collection, so happens afterward
            //todo: check if hit left or right too, if skew is active
            if (hit_edge && picture_boxes.Count < img_count)
            {
                temp_list.Clear();
                AddBoxes();

            }
        }

    };
m1m5dgzv

m1m5dgzv1#

您应该只示例化Random一次。
变更:

static Random rn_index;

收件人:

static Random rn_index; = new Random();

并删除animate()方法中创建Random的行。
如果你想让它们以不同于Tick()事件的速度旋转,你可以创建一个DateTime变量来保存它们下一次应该旋转的时间,只要超过这个时间,就执行旋转并重置为下一个目标时间:

static int rotationDelay = 200;
static DateTime nextRotation = DateTime.Now.AddMilliseconds(rotationDelay);

在animate()中:

bool rotate = (DateTime.Now >= nextRotation);
foreach (PictureBox pb in temp_list)
{
    list_index = rn_index.Next(0, precalculations_list.Count - 1);
    pb.Top += added_pix_int + precalculations_list[list_index];
    pb.Left += s_d;

    if (pt != "Rain" && rotate)
    {
        Image img = pb.Image;
        img.RotateFlip(RotateFlipType.Rotate90FlipNone);
        pb.Image = img;
    }

    //when one touches the edge of the screen, clear the list/boxes 
    if (pb.Left < hit_detection.Left ||
        pb.Right > hit_detection.Right ||
        pb.Bottom > hit_detection.Bottom)
    {
        pm.Controls.Remove(pb);
        picture_boxes.Remove(pb);
        hit_edge = true;
    }

}
if (rotate) {
    nextRotation = DateTime.Now.AddMilliseconds(rotationDelay);
}

相关问题