如何正确地在对象之间逐渐添加 increasing/decreasing space?

How to properly add gradually increasing/decreasing space between objects?

我试图实现从 space 到另一个类似于加速和减速的过渡,除了我失败了,我从中得到的唯一东西就是这个无限堆的混乱,这是显示此操作的屏幕截图:

你可以在这里看到一个非常黑的圆圈,实际上是 100 或 200 个圆圈堆叠在一起

我使用这段代码得到了这个结果:

def Place_circles(curve, circle_space, cs, draw=True, screen=None):
    curve_acceleration = []
    if type(curve) == tuple:
        curve_acceleration = curve[1][0]
        curve_intensity = curve[1][1]
        curve = curve[0]
        #print(curve_intensity)
        #print(curve_acceleration)
    Circle_list = []
    idx = [0,0]
    for c in reversed(range(0,len(curve))):
        for p in reversed(range(0,len(curve[c]))):
            user_dist = circle_space[curve_intensity[c]] + curve_acceleration[c] * p
            dist = math.sqrt(math.pow(curve[c][p][0] - curve[idx[0]][idx[1]][0],2)+math.pow(curve [c][p][1] - curve[idx[0]][idx[1]][1],2))
            if dist > user_dist:
                idx = [c,p]
                Circle_list.append(circles.circles(round(curve[c][p][0]), round(curve[c][p][1]), cs, draw, screen))

这个地方根据当前曲线的强度(0到2之间的数字,随机)来圈,等于space的量(这里假设在20到30之间,20是索引0、30 是索引 2,这 2 之间的数字是索引 1)。

这创建了您在上面看到的堆栈,这不是我想要的,我还得出结论,我不能使用加速,因为在 2 点之间移动的时间取决于我需要的圆圈数量点击,知道每个点之间有多个圆圈,但无法确定有多少导致我无法使用经典的加速公式。

所以我 运行 在这里没有选择,也没有关于如何从 space 数量过渡到另一个数量的想法。 有什么想法吗?

PS:我放弃了上面的想法并切换回我的 master 分支,但是我在此处创建的分支中仍然可以使用此代码 https://github.com/Mrcubix/Osu-StreamGenerator/tree/acceleration 。 所以现在我回到了没有加速或减速的正常代码。

TL:DR 我无法使用加速,因为我不知道将要放置在两点之间的圆圈数量并使行进时间发生变化(我需要例如点击圆圈每 0.333 秒 180 bpm 一圈)所以我正在寻找另一种方法来生成逐渐变化的 space.

首先,我采用了为 [0 中的每条曲线生成强度的函数; 2] 然后我放弃了加速公式,因为它不可用。 现在我正在使用一种基本算法来确定我可以在曲线上放置的最大圆圈数。

现在我的脚本工作方式如下: 我首先生成一个流(需要以高bpm点击多个圆圈) 这样我就获得了折线的每条曲线(或线段)的长度。 我使用以下函数为每条曲线生成强度:

def generate_intensity(Circle_list: list = None, circle_space: int = None, Args: list = None):
    curve_intensity = []
    if not Args or Args[0] == "NewProfile":
        prompt = True
        while prompt:
            max_duration_intensity = input("Choose the maximum amount of curve the change in intensity will occur for: ")
            if max_duration_intensity.isdigit():
                max_duration_intensity = int(max_duration_intensity)
                prompt = False
        prompt = True
        while prompt:
            intensity_change_odds = input("Choose the odds of occurence for changes in intensity (1-100): ")
            if intensity_change_odds.isdigit():
                intensity_change_odds = int(intensity_change_odds)
                if 0 < intensity_change_odds <= 100:
                    prompt = False      
        prompt = True
        while prompt:
            min_intensity = input("Choose the lowest amount of spacing a circle will have: ")
            if min_intensity.isdigit():
                min_intensity = float(min_intensity)
                if min_intensity < circle_space:
                    prompt = False 
        prompt = True
        while prompt:
            max_intensity = input("Choose the highest amount of spacing a circle will have: ")
            if max_intensity.isdigit():
                max_intensity = float(max_intensity)
                if max_intensity > circle_space:
                    prompt = False
        prompt = True
        if Args:
            if Args[0] == "NewProfile":
                return [max_duration_intensity, intensity_change_odds,  min_intensity, max_intensity]
    elif Args[0] == "GenMap":
        max_duration_intensity = Args[1]  
        intensity_change_odds = Args[2]
        min_intensity = Args[3]
        max_intensity = Args[4]
    circle_space = ([min_intensity, circle_space, max_intensity] if not Args else [Args[0][3],circle_space,Args[0][4]])
    count = 0
    for idx, i in enumerate(Circle_list):
        if idx == len(Circle_list) - 1:
            if random.randint(0,100) < intensity_change_odds:
                if random.randint(0,100) > 50:
                    curve_intensity.append(2)
                else:
                    curve_intensity.append(0)
            else:
                 curve_intensity.append(1)
        if random.randint(0,100) < intensity_change_odds:
                if random.randint(0,100) > 50:
                    curve_intensity.append(2)
                    count += 1
                else:
                    curve_intensity.append(0)
                    count += 1
        else:
            if curve_intensity:
                if curve_intensity[-1] == 2 and not count+1 > max_duration_intensity:
                    curve_intensity.append(2)
                    count += 1
                    continue
                elif curve_intensity[-1] == 0 and not count+1 > max_duration_intensity:
                    curve_intensity.append(0)
                    count += 1
                    continue
                elif count+1 > 2:
                    curve_intensity.append(1)
                    count = 0
                    continue
                else:
                    curve_intensity.append(1)   
            else:
                curve_intensity.append(1)
    curve_intensity.reverse()
    if curve_intensity.count(curve_intensity[0]) == len(curve_intensity):
        print("Intensity didn't change")
        return circle_space[1]
    print("\n")
    return [circle_space, curve_intensity]

有了这个,我得到了2个列表,一个是我指定的间距,第二个是随机生成的强度列表。 从那里我调用另一个函数,将折线、先前指定的间距和生成的强度作为参数:

def acceleration_algorithm(polyline, circle_space, curve_intensity):
    new_circle_spacing = []
    for idx in range(len(polyline)): #repeat 4 times
        spacing = []
        Length = 0
        best_spacing = 0
        for p_idx in range(len(polyline[idx])-1): #repeat 1000 times / p_idx in [0 ; 1000]
            # Create multiple list containing spacing going from circle_space[curve_intensity[idx-1]] to circle_space[curve_intensity[idx]]
            spacing.append(np.linspace(circle_space[curve_intensity[idx]],circle_space[curve_intensity[idx+1]], p_idx).tolist())
            # Sum distance to find length of curve
            Length += abs(math.sqrt((polyline[idx][p_idx+1][0] - polyline[idx][p_idx][0]) ** 2 + (polyline [idx][p_idx+1][1] - polyline[idx][p_idx][1]) ** 2))
        for s in range(len(spacing)): # probably has 1000 list in 1 list
            length_left = Length # Make sure to reset length for each iteration
            for dist in spacing[s]: # substract the specified int in spacing[s]
                length_left -= dist 
            if length_left > 0: 
                best_spacing = s
            else: # Since length < 0, use previous working index (best_spacing), could also jsut do `s-1`
                if spacing[best_spacing] == []:
                    new_circle_spacing.append([circle_space[1]])
                    continue
                new_circle_spacing.append(spacing[best_spacing])
                break
    return new_circle_spacing

有了这个,我得到了一个列表,每个圆圈之间的 space 将被放置, 从那里,我可以再次调用 Place_circles() 并获取新流:

def Place_circles(polyline, circle_space, cs, DoDrawCircle=True, surface=None):
    Circle_list = []
    curve = []
    next_circle_space = None
    dist = 0
    for c in reversed(range(0, len(polyline))):
        curve = []
        if type(circle_space) == list:
            iter_circle_space = iter(circle_space[c])
            next_circle_space = next(iter_circle_space, circle_space[c][-1])     
        for p in reversed(range(len(polyline[c])-1)):
            dist += math.sqrt((polyline[c][p+1][0] - polyline[c][p][0]) ** 2 + (polyline [c][p+1][1] - polyline[c][p][1]) ** 2)
            if dist > (circle_space if type(circle_space) == int else next_circle_space):
                dist = 0
                curve.append(circles.circles(round(polyline[c][p][0]), round(polyline[c][p][1]), cs, DoDrawCircle, surface))
                if type(circle_space) == list:
                    next_circle_space = next(iter_circle_space, circle_space[c][-1])
        Circle_list.append(curve)
    return Circle_list

结果是一个在圆圈之间变化 space 的流(因此加速或减速),唯一需要解决的问题是 pygame 在之后不使用新的一组圆圈更新屏幕我打电话给 Place_circles(),但这是一个问题,我要么尝试自己解决,要么再问 post

此功能的最终代码可在我的存储库中找到:https://github.com/Mrcubix/Osu-StreamGenerator/tree/Acceleration_v02