# Код для примера с лого.
init python:

    # Вращаем лого, масштабируя его и увеличивая прозрачность
    # (уменьшая альфа-канал).
    def logo_transform(t, st, at):

        # Повторять каждые 10 секунд.
        st = st % 7.0

        # Это занимает 5 секунд.
        done = min(st / 5.0, 1.0)

        t.xpos = done
        t.xanchor = 1.0 - done
        t.ypos = .5
        t.yanchor = .5
        t.rotate = 360 * done
        t.alpha = 1.0 - done
        t.zoom = 1.0  + done
        
        return 0


# Это код для примера с шарами. Он несколько сложен для восприятия, 
# но большая его часть -- для движения шаров. Только небольшая часть
# этого кода по-настоящему работает с Ren'Py.
init python:
    import math
    
    class Ball(object):
        def __init__(self, filename, x, y, function=None):
            
            self.transform = Transform(child=filename, xpos=x, ypos=y, xanchor=0.5, yanchor=0.5, rotate=0, function=function)
            self.x = x
            self.y = y
            
            MAX_SPEED = 150

            self.dx = renpy.random.uniform(-MAX_SPEED, MAX_SPEED)
            self.dy = renpy.random.uniform(-MAX_SPEED, MAX_SPEED)

            # Скорость вращения.
            self.drotate = renpy.random.uniform(0, 180)
            
    # Это -- вызывается 
    def balls_collide(p1, p2):
        """
        Посмотри, не сталкиваются ли шары.
        Если да, то обработай столкновение.
        """

        DOUBLE_RADIUS = 75
        
        x21 = p2.x - p1.x
        y21 = p2.y - p1.y

        d = math.hypot(x21, y21)

        # Возврат, если слишком далеко.
        if d > DOUBLE_RADIUS:
            return

        vx21 = p2.dx - p1.dx
        vy21 = p2.dy - p1.dy

        # Возврат, если не приближается.
        if (vx21 * x21 + vy21 * y21) > 0:
            return

        # Устраняет деление на ноль.
        if x21 == 0:
            x21 = .00001

        # Рассчитывает столкновение.
        a = y21 / x21
        dvx2 = -(vx21 + a * vy21) / (1 + a * a)

        p2.dx += dvx2
        p2.dy += a * dvx2

        p1.dx -= dvx2
        p2.dy -= a * dvx2

    # Это вызывается первой трансформацией. 
    # Обновляет все трансформации. 
    def balls_update(pilot, st, at):

        global last_time

        RADIUS = 75 / 2 
        LEFT = RADIUS
        RIGHT = 800 - RADIUS
        TOP = RADIUS
        BOTTOM = 600 - RADIUS

        # Управляющий первым шаром в нашем списке, и он -- тот,
        # кто получил last_time обновление.
        if last_time is None:
            dt = 0
        else:
            dt = st - last_time

        last_time = st

        # Обрабатывает текущее столкновение.
        for i in xrange(0, len(balls)):
            for j in xrange(i + 1, len(balls)):
                balls_collide(balls[i], balls[j])
                
        # Базовые движения и отскок от стенок.
        for i in balls:

            i.x += i.dx * dt
            i.y += i.dy * dt

            if i.x < LEFT:
                i.x = LEFT
                i.dx = abs(i.dx)

            if i.x > RIGHT:
                i.x = RIGHT
                i.dx = -abs(i.dx)

            if i.y < TOP:
                i.y = TOP
                i.dy = abs(i.dy)

            if i.y > BOTTOM:
                i.y = BOTTOM
                i.dy = -abs(i.dy)


        # Обновить трансформации.
        for i in balls:

            # Этот код заставляет Ren'Py обновлять различные трансформации.
            # Заметьте, что мы используем абсолютные координаты 
            # для размещения с субпиксельной точностью.
            i.transform.xpos = absolute(i.x)
            i.transform.ypos = absolute(i.y)
            i.transform.rotate = (i.drotate * st) % 360.0
            i.transform.update()

        return 0
            
# Это используется в примере с кнопкой:
init python:
    def button_transform(t, st, at):
        t.rotate = (90 * st) % 360.0
        return 0
    
label demo_transform:

    e "Функция {i}Transform{/i} позволяет Вам поворачивать, масштабировать, двигать и менять альфа-канал объекта."

    e "Всё происходит под контролем функции Python'a, что делает это невероятно гибким, хотя и сложным для не-программиста."

    hide eileen
    with dissolve

    show logo base at Transform(function=logo_transform)
    
    e "Вот простой пример, показывающий, как можно менять изображение по ходу перемещения его по экрану."

    e "Что особенно хорошо в {i}Transform{/i}'е, так это то, что она -- \"единое целое\"."

    e "Если использовать её для поворота, можно масштабировать или менять прозрачность без дополнительных затрат."

    hide logo base
    with dissolve
    
    python:

        last_time = None
        
        # Определяем список шаров.
        balls = [ 
            Ball("eileen_orb.png", 200, 150, function=balls_update),
            Ball("lucy_orb.png", 400, 150),
            Ball("eileen_orb.png", 600, 150),
            
            Ball("lucy_orb.png", 200, 300),
            Ball("lucy_orb.png", 600, 300),

            Ball("eileen_orb.png", 200, 450),
            Ball("lucy_orb.png", 400, 450),
            Ball("eileen_orb.png", 600, 450),
            ]

        # Добавляем трансформу для каждого шара на экран.
        for i, b in enumerate(balls):
            renpy.show("ball%d" % i, what=b.transform)

    with dissolve
            
    e "При использовании более сложных конструкций python'a доступны более продвинутые трюки."

    e "Например, координация более чем одной трансформы разом."

    python:
        for i, b in enumerate(balls):
            renpy.hide("ball%d" % i)


    with dissolve

    python hide:
        ui.transform(function=button_transform, xalign=0.5, yalign=0.5)
        ui.textbutton(u"Работающая Кнопка", clicked=ui.returns(True))
        
    e "Наконец, трансформации могут применяться к кнопкам, и работать даже когда кнопка масштабирована."

    show eileen happy
    with dissolve

    e "С небольшой добавкой кода на Python, трансформации могут мнооогое..."
    
    

    return
        
        
