C# C吉他英雄克隆,注意动画计时

C# C吉他英雄克隆,注意动画计时,c#,C#,我正在使用C创建一个吉他英雄克隆,在同步动画和声音时遇到了一些问题 我现在所做的概述: A读一个文件并得到注释高速公路,注释时间而不是长度这一切都做得正确 注释被放入一个数组中 在歌曲开始之前,我生成一个故事板,读入整个音符数组,然后创建双动画,使矩形对象音符在屏幕上向下滚动。 我将动画的开始时间设置为预期播放时间前1秒,持续时间设置为接近结束,动画持续时间设置为1秒。然而,我所期望的是音符同步播放而不是发生。 以下是创建动画的代码: private void StartNote(MidiNot

我正在使用C创建一个吉他英雄克隆,在同步动画和声音时遇到了一些问题

我现在所做的概述:

A读一个文件并得到注释高速公路,注释时间而不是长度这一切都做得正确 注释被放入一个数组中 在歌曲开始之前,我生成一个故事板,读入整个音符数组,然后创建双动画,使矩形对象音符在屏幕上向下滚动。 我将动画的开始时间设置为预期播放时间前1秒,持续时间设置为接近结束,动画持续时间设置为1秒。然而,我所期望的是音符同步播放而不是发生。 以下是创建动画的代码:

private void StartNote(MidiNoteEvent evnt)
    {
        const double length = 0;
        int[] highwayArray = evnt.Highway;

        for (int i = 1; i <= highwayArray.Length; i++ )
        {
            var highway = highwayArray[i-1];
            if (highway > 0)
            {
                string name = evnt.Time.ToString() + "|" + highway.ToString(); 
                var rect = new Rectangle {Tag=name, Height = length+5, Width = 50 };
                Canvas.SetTop(rect,-6);

                int offset;

                if (i == 1)
                {
                    offset = 20;
                    rect.Fill = new SolidColorBrush(Colors.Green);
                }
                else if (i == 2)
                {
                    offset = 120;
                    rect.Fill = new SolidColorBrush(Colors.Red);
                }
                else if (i == 3)
                {
                    offset = 220;
                    rect.Fill = new SolidColorBrush(Colors.Yellow);
                }
                else if (i == 4)
                {
                    offset = 320;
                    rect.Fill = new SolidColorBrush(Colors.Blue);
                }
                else
                {
                    offset = 420;
                    rect.Fill = new SolidColorBrush(Colors.Orange);
                }

                rect.Margin = new Thickness(offset, 0, 0, 0);

                guitarCanvas.Children.Add(rect);

                var duration = new Duration(TimeSpan.FromSeconds(1));

                var myDoubleAnimation2 = new DoubleAnimation
                                             {Duration = duration, BeginTime = TimeSpan.FromSeconds(evnt.Time-1)};

                _notes.Children.Add(myDoubleAnimation2);

                Storyboard.SetTarget(myDoubleAnimation2, rect);

                // Set the attached properties of Canvas.Left and Canvas.Top
                // to be the target properties of the two respective DoubleAnimations
                Storyboard.SetTargetProperty(myDoubleAnimation2, new PropertyPath("(Canvas.Top)"));

                myDoubleAnimation2.To = guitarCanvas.Height;

                myDoubleAnimation2.Completed += new EventHandler(myDoubleAnimation2_Completed);

                // Begin the animation.
                //sb.Begin();
            }
        }

    }
我不知道如何解决这个问题,我是否误解了动画的工作原理?使用错误的单位?还是完全是别的原因?非常感谢任何提示,即使它完全重写了我如何显示注释。

我建议您使用a并使用绘制事件绘制a,并更改控件的位置以使用事件制作矩形动画

编辑1:提高用户控件的性能并避免闪烁效果

编辑2:计时器在后台工作,要启用和禁用它,您可以编写一个公共字段,如下所示:

private Timer _timer;

public bool TimerEnabled
{
    get { return _timer.Enabled; }
    set { _timer.Enabled = value; }
}

void InitializeTimer()
{
    _timer = new Timer();
    _timer.Interval = 1; //One millisecond
    _timer.Enabled = false;
    _timer.Tick += new EventHandler(_timer_Tick);
}

void _timer_Tick(object sender, EventArgs e)
{
    //Example
    Location = new Point(Location.X, Location.Y + 1);
}

我的答案不是针对C本身,而是针对一般的音频/视频同步。它还取决于用于播放声音的音响系统。对我来说,听起来你遇到的问题是你的动画时钟与音频时钟不同步

通常,当您编写一些必须保持注释流与音频轨迹同步的代码时,您会将动画更新直接绑定到声源上的时钟,而不是依赖渲染器帧事件

在许多动画系统中,当你说播放这个动画时,内部的更新循环很可能会执行一个可变的时间步长动画,将你的对象从a逐渐移动到B再移动到T。这一切都很好,直到你想让事情发生的精度和节奏动作游戏所必需的音频计时一样高。我不会详细介绍它背后的细节,但关键是计时帧的时钟和计时音频的时钟可能不会给出完全相同的时间

解决方案相对简单,尽管我的解释可能不是很好:在每帧的基础上更新注释位置,不要依赖动画系统来获得正确的位置

你知道,因为它们沿着通道滚动,所以每个音符在时间t有一个Y位置p。使用t=音频时钟的时间值,您可以计算在任何给定时间绘制p的位置,例如:p=LanEleLength-t,其中LanEleLength是车道顶部,假设为1.0。然后,音符会随着音频时钟准确地向下滚动超过0。当他们击中或超过0时会发生什么情况取决于显示器


我希望这是有道理的,但我不相信它是有道理的:

你的声音放得怎么样?我用视频做了类似的事情。我把其他动画放在同一个故事板上开始播放视频,这样它们就在同一个计时器上。所以我有一个带有MediaTimeline的故事板,然后将我的其他动画添加到同一个故事板中

工作得很好。只需确保将SlipBehavior设置为在故事板上滑动即可

在单击按钮的操作中,我有:

<BeginStoryboard Name="playVideoSB">
    <Storyboard SlipBehavior="Slip" Completed="Storyboard_Completed" FillBehavior="Stop">
        <MediaTimeline Source="{Binding Filename}" Storyboard.TargetName="video" Name="mediaTime"/>
    </Storyboard>
</BeginStoryboard>

我碰巧使用的是布尔动画,但它应该适用于双打。

有什么特别不起作用?音符计时与音乐计时不同步,尽管我尝试正确设置动画持续时间和开始时间。所有这些都可以在歌曲开始之前完成吗?我认为不可能在歌曲运行时动态计算,因为这会在生成对象时造成少量的延迟。您可以初始化游戏以避免延迟,在歌曲开始之前计算你需要多少个对象,并生成和初始化一个UserControls数组。但是实际的移动是如何完成的?如何在不牺牲性能的情况下平稳地移动用户控件?还有,什么会触发移动的开始?是否会有一个计时器在后台运行,每毫秒滴答一次,看看是否应该播放一个音符?或者有其他方法吗?你到底是如何将视频添加到故事板的?我有点困惑
BooleanAnimationUsingKeyFrames bukf = new BooleanAnimationUsingKeyFrames();
Storyboard.SetTargetProperty(bukf, new PropertyPath(PropertyFoo));

Storyboard.SetTarget(bukf, myObject);

bukf.KeyFrames.Add(new DiscreteBooleanKeyFrame(true, KeyTime.FromTimeSpan(start)));
bukf.KeyFrames.Add(new DiscreteBooleanKeyFrame(false, KeyTime.FromTimeSpan(end)));
playVideoSB.Storyboard.Children.Add(bukf);