如何正确地在对象之间添加逐渐增加/减少的空间?

2024-09-24 04:29:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图实现从一个空间量到另一个空间量的转换,这类似于加速和减速,但我失败了,我从中得到的唯一一件事就是这堆乱七八糟的东西,下面是一个屏幕截图,显示了这一点:

enter image description here

你可以在这里看到一个非常黑的圆圈,实际上是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之间的数字,随机)旋转,该强度等于空间量(这里假设20和30之间,20是索引0,30是索引2,2之间的数字是索引1)

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

所以我在这里已经没有选择了,也没有关于如何从一个空间量过渡到另一个空间量的想法了。 有什么想法吗

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

TL:DR我不能使用加速度,因为我不知道将在两点之间放置的圆圈数量,这会使旅行时间发生变化(例如,我需要以每0.333s一个圆圈180 bpm的速度单击圆圈),所以我正在寻找另一种方法来生成逐渐变化的空间


Tags: 代码dist分支空间spacemathcs加速度
1条回答
网友
1楼 · 发布于 2024-09-24 04:29:45

首先,我使用函数生成[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

通过这个,我得到了一个列表,其中每个圆圈之间的空间将被放置, 从那里,我可以再次调用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

结果是一个在圆圈之间有不同间距的流(如此加速或减速),唯一需要解决的问题是pygame在调用Place_circles()后没有用新的圆圈集更新屏幕,但这是一个问题,我将尝试自己解决,或者在另一篇文章中提出

此功能的最终代码可以在my repo上找到:https://github.com/Mrcubix/Osu-StreamGenerator/tree/Acceleration_v02

相关问题 更多 >