صورة ثلاثية الأبعاد في الثعبان مع أداء عادي (تقريبًا)

يمكن اعتبار هذه المقالة إجابة على هذا السؤال ، حيث يتعلق الأمر بكتابة شيء من هذا القبيل في C ++ ، موجهًا للمبتدئين ، أي مع التركيز على رمز بسيط للقراءة بدلاً من الأداء العالي.

بعد قراءة المقال ، كان لدي فكرة أن أكرر البرنامج الذي كتبه المؤلف. أنا على دراية بـ C ++ ، لكنني لم أكتب أبدًا أي برامج معقدة عليها ، مفضلاً الثعبان. هنا ولدت الفكرة للكتابة عليها. كنت مهتمًا بشكل خاص بالأداء - كنت على يقين من أن إطارين في الثانية هو الحد الأقصى لثعبان. لقد كنت مخطئ.

صورة

صورة

يمكن العثور على المحاولة الأولى هنا . هنا الرمز مكتوب بالكامل ، لا يحسب الاختلافات اللغوية ، وفقًا لما هو عليهhaqreu. وبسبب هذا ، فإن العرض هو O (n ^ 2) - حلقات متداخلة بشكل أساسي في الزاوية والمسافة:

         # iterating alpha
        alpha = player.view - player.fov / 2
        mapFB.drawRectangle(player.y - 1, player.x - 1, player.y + 1, player.x + 1, Color(255, 0, 0))
        rayNum = 0
        while alpha < player.fov / 2 + player.view:
            # iterating distance
            dist = 0
            x = player.x
            y = player.y
            while 0 < x < mapFB.w - 1 and 0 < y < mapFB.h - 1:
                  ...

وبسبب هذا ، فإن الرمز بطيء إلى حد ما (تمكنت من الحصول على أقل من 3-4 إطارات في الثانية على الجيل الثامن من Intel Core i5).

من الطرق الواضحة لتسريع الأمور وعدم تعقيد الشفرة كثيرًا هو استبدال الحلقة الداخلية بعمليات التعقيد الخطي. لنأخذ في الاعتبار كل شيء من وجهة نظر الرياضيات: نحتاج إلى تحديد نقطة تقاطع الشعاع التي تعطيها إحداثيات اللاعب وزاوية الرؤية ، والكتلة التي تحددها الإحداثيات والحجم (ثابت ، من أجل البساطة). بعد ذلك ، تحتاج إلى تحديد أقرب تحويل وإعادته. أدناه هو الرمز المقابل (الرمز الكامل هنا ):

def block_cross(i, j, k, y_0, alpha, player):
    # cell coordinates
    x_cell = i * H
    y_cell = j * H
    # find collision points
    collisions = []

    if k != 0:
        x = (y_cell - y_0) / k
        y = y_cell
        if x_cell <= x <= x_cell + H and (x - player.x) / cos(alpha) < 0:
            collisions.append((x, y))

    if k != 0:
        x = (y_cell + H - y_0) / k
        y = y_cell + H
        if x_cell <= x <= x_cell + H and (x - player.x) / cos(alpha) < 0:
            collisions.append((x, y))

    x = x_cell
    y = y_0 + x * k
    if y_cell <= y <= y_cell + H and (x - player.x) / cos(alpha) < 0:
        collisions.append((x, y))

    x = x_cell + H
    y = y_0 + (x) * k
    if y_cell <= y <= y_cell + H and (x - player.x) / cos(alpha) < 0:
        collisions.append((x, y))

    # select the closest collision for the block
    dist = 1000 * H
    x = None
    y = None
    for collision in collisions:
        tmp = sqrt((collision[0] - player.x) ** 2 + (collision[1] - player.y) ** 2)
        if tmp < dist:
            dist = tmp;
            x = collision[0]
            y = collision[1]

    return x, y, dist

مثل هذا التغيير البسيط لـ 10 خطوط يعطي تسارعًا بأكثر من الضعف ، أي حوالي 5-6 إطارات في الثانية. لم يعد هذا هزات ، بل صورة متحركة ، لكنها لا تزال بطيئة للغاية.
بحثًا عن أفكار حول تسريع التعليمات البرمجية ، صادفت Cython . باختصار ، هذا مشروع يسمح لك بإعطاء تسريع كبير لرمز بيثون دون تغييره بجدية. لفترة وجيزة عنه - تحت المفسد.

tyts
 cpdef int fun(int num, float val):
    cdef int result
    # do some stuff
    return result

result int( int, , ). , . python-, cdef — python, cython. , python — , :

 cpdef int fun(int num, float val):
    cdef int result
    # do some stuff
    return result

 cdef int fun2(int *arr, float* arr_2):
    cdef int arr_3[10][10]
    # do some stuff
    return result

fun2 python, - fun — .

أعطى Cython بعض التسارع ، وإن كان ضئيلًا - ليس فقط إطارين في الثانية. ومع ذلك ، في الأرقام النسبية ليست هذه صغيرة جدًا - 8-9 صور في الثانية ، أي + 40٪ لأفضل خيار في الثعبان و + 200٪ للخيار مع خوارزمية ساذجة. لا تزال هذه الصورة مضطربة للغاية ، ولكنها طبيعية للأغراض التعليمية. في النهاية ، هدفنا هو أن نكتبها بأنفسنا ونستمتع بالعملية ، ولكن بالنسبة للعبة حقيقية ، من السهل أخذ مكتبة مثل لعبة pygame ، أو إرجاءها بشكل عام واتخاذ شيء أكثر ملاءمة.

ملاحظة: سيكون من المثير للاهتمام رؤية خيارات أخرى لتحسين الشفرة في التعليقات.

Source: https://habr.com/ru/post/undefined/


All Articles