PyGame, часть 1 Начало(оригинал)

Это первая часть моего руководства по PyGame расчитанной на новичков. Я буду неторопливо и максимально просто рассказывать Вам об этой библиотеки. Я не буду вдаваться в мелкие детали. Это руководство стоит рассматривать как помощь начинающим программистам игр. Вам необходимо иметь под рукой полную документацию по PyGame. Во время чтения этого руководства, она должна быть у вас под рукой.

Одно маленькое уточнение, я очень ленив. Иногда я даже удивляюсь тому, что я встаю с кровати. Таким образом не удивляйтесь что я буду писать это руководство регулярно. Я буду писать это руководство в то время, когда мои глаза будут открыты.

Что нам необходимо:

  • Python: я использую Python 2.4, доступный по умолчанию в Debian Etch. Другие версии Python'а также должны подойти для решения наших задач
  • Pygame: этот модуль достаточнолегко установить самостоятельно
  • Текстовый редактор: Я рекомендую использовать редактор VIM, про который Вы наверняка слышали много страшных слухов. Не верьте им. Они не верны.

  • Если Вы используете дистрибутив Debian, то установить PyGame можно следующим образом (у вас должны быть права root):
    Эта команда установит этот модуль на Ваш компьютер, а также все необходимые дополнительные библиотеки. Если у Вас стоит другая операционная система, то скорей всего Python и Pygame доступны отдельно в Ваших репозитариях. Вам необходимо скачать и установить их оттуда.

    Что Вам необходимо знать:

    Я предполагаю что Вы уже имеете представление о языке программирования Python.

    Начало:

    Сначало давайте посмотрим на приложение, которое нечего не делает. Или почти нечего. Это приложение показывает просто окно. Также там происходит некоторая обработка событий. Это приложение можно будет использовать как шаблон для приложений рассматриваемых в этом руководстве.

    Вот код этого приложения:

    1 #! /usr/bin/env python
    2 
    3 import pygame
    4 
    5 screen = pygame.display.set_mode((640, 400))
    6 
    7 while  1:
    8     pass


    Прежде всего для использования PyGame Вам необходимо подключить этот модуль. Затем мы создаем окно размером 640 пикселей по горизонтали и 480 по вертикали. При создании окна, вы можете установить очень много параметров, но мы воспользуемся параметрами по умолчанию пока.

    Затем мы запускаем бесконечный цикл. Мы должны это сделать что бы наше окно не закрылось сразу после запуска программы. Если Вы запустите эту программу, то увидете окно размером 640 на 480 пикселей. Обратите внимание что если Вы попытаетесь закрыть приложение нажав на крестик в верхнем правом углу нашего окна, то оно не закроется. Для того, что бы его закрыть Вам необходимо переключиться в консоль, из которого Вы запустили программу и нажать Ctrl+C.

    Задание на дом
  • Создайте окно, шириной 320 пикселей и высотой 200
  • Создайте приложение, в которой пользователь может задать размеры окна из командной строки
  • Создайте приложение, которое сначало спрашивает у пользователя размеры окна а затем создает его
  • Создайте приложение которое вызывает метод set_mode дважды с разными параметрами. Как Вы думаете как поведет себя программа? Запустите программу. Что произошло на самом деле? Вы можете это объяснить?


  • Добавляем обработчик событий Наш первый пример был достаточно прост. Приложение которое мы написали не несет не какого полезного и интересного функционала. Кроме того, для того что бы авершить его работу, нам необходимо переключаться в терминал и нажимать Ctrl+C. Давайте добавим немного кода в это приложение.

    Вот обновленная версия нашего приложения:

     1 #! /usr/bin/env python
     2 
     3 import pygame
    
     4 
     5 screen = pygame.display.set_mode((640, 400))
     6 running = 1
     7 
     8 while running:
    
     9     event = pygame.event.poll()
    10     if event.type == pygame.QUIT:
    11         running = 0
    12 


    Новое в этом примере, то что мы добавили механизм для управления работой цикла. Мы управляем работой цикла с помощью флажка running. Пока флажок равен 1, цикл выполняется. Внутри цикла мы опрашиваем очередь о поступивших событий. Существует различные способы обработки очереди, но мы пока остановимся на таком варианте.

    Существуют различные события которые могут быть обработана PyGame. Одним из таких событий является QUIT, которое происходит когда пользователь нажимает на крестик расположенный в верхнем правом углу нашего приложения..Если происходит это событие, то мы обнуляем флажок running, после чего наш цикл прерывается и как следствие наша программа заканчивает свою работу. Пока все просто.

    Задание на дом
  • Измените первую программу из этой главы так, что бы она также обрабатывала очередь событий
  • Измените Вашу программу так, что бы она заканчивала работать при нажатии на крестик без использования флажка


  • Последние штрихи к нашему шаблону Ну и в заключении, прежде чем начать создавать какие то интересные вещи, мы зададим цвет нашему окну, и добавим ей зеркального отражения. Сначало код:

     1 #! /usr/bin/env python
     2 
     3 import pygame
     4 
     5 screen = pygame.display.set_mode((640, 400))
    
     6 running = 1
     7 
     8 while running:
     9     event = pygame.event.poll()
    10     if event.type == pygame.QUIT:
    
    11         running = 0
    12     screen.fill((0, 0, 0))
    13     pygame.display.flip()
    14 


    Мы добавили только две строки в нашу программу. Сначало мы определили цвет фона нашей поверхности. Цвет задется тремя параметрами: красный, зеленый и синий. Значение может варироваться от 0 до 255. Так как мы задали все значения равными 0, то мы получим черный экран. Поэксперементируйте со значениями красного, зеленного и синего. .

    Затем мы вызываем функцию pygame.display.flip(). Рисовать рисунок на лету на дисплей, не самая хорошая идея. Поэтому мы сначала определяем цвет нашего буфера вывода и только затем делаем его видимым. Таким образом мы можем добиться отсутсвия мерцания в случае использования мультипликации (а до нее мы доберемся обязательно).

    Задание на дом
  • Создайте окно с белым цветом
  • Создайте окно с красным цветом
  • Поэксперементируйте с различными параметрами цвета фона. Если Вы не знакомы с методикой определения цвета с помощью RGB, то разберитесь как с помощью этого метода получать различные цвета
  • Создайте программу, которая спрашивает пользователя значения цветов RGB, затем проверяет их то что они попадают в диапазон от 0 до 255 и тогда выводит его на экран.
  • Создайте программу которая в зависимости от времени устанавливает различную яркость синего цвета. Например ночью экран должен быть черным, а в полдень максимально синим. В промежуточное время цвет экрана должен быть промежуточного цвета между черным и ярко-синим.

  • PyGame, часть 2 Рисуем линии (оригинал)

    Добро пожаловать во вторую часть моего руководства по PyGame. В этой главе мы будем опираться на знания полученные в прошлой главе. Мы по прежнему будем неторопливо во всем разбираться.

    Рисуем линию
    Мы можем нарисовать линию используя метод pygame.draw.line. Также мы можем использовать метод pygame.draw.aaline, который рисует линию используя методы сглаживания и убирая "зубцы". Необходимо помнить что данный метод более медленный.

    Нарисуем голубую линию идущей из точки ( 0, 0 ) в точку ( 200, 100 ) (единицей измерения является пиксель ). в нашем окне:
    pygame.draw.line(screen, (0, 0, 255), (0, 0), (200, 100))
    
    Можно сделать этот код более читаемым:
    blue = 0, 0, 255
    point1 = 0, 0
    point2 = 200, 100
    pygame.draw.line(screen, blue, point1, point2)
    
    Давайте теперь объединим этот код с примером из предыдущей главы. Мы нарисуем две линии, одна пройдет из нежнего левого угла в верхний правый, другая из верхнего левого в нижний правый. Для отрисовки мы используем методы pygame.draw.line и pygame.draw.aaline.
     1 #! /usr/bin/env python
     2 
     3 import pygame
     4 
     5 screen = pygame.display.set_mode((640, 480))
     6 running = 1
     7 
     8 while running:
     9     event = pygame.event.poll()
    10     if event.type == pygame.QUIT:
    11         running = 0
    12 
    13     screen.fill((0, 0, 0))
    14     pygame.draw.line(screen, (0, 0, 255), (0, 0), (639, 479))
    15     pygame.draw.aaline(screen, (0, 0, 255), (639, 0), (0, 479))
    16     pygame.display.flip()
    
    Если Вы запустите эту программу, то увидите черное окно, с голубой буквой "Х".

    Задание на дом
  • Улучшите эту программу. Избавьтесь от не понятных чисел и замените их на переменные. Поэксперементируйте с различными значениями этих переменных. Убедитесь что программа работает предсказуемо.
  • Улучшите эту программу еще раз, объявляя переменные, названные linecolor, topleft, bottomright и так далее. Измените соответсвующим образом программу, чтобы использовать эти переменные.
  • Измените программу так, что бы она рисовала дви линии различного цвета.
  • Напишите программу, которая рисует две прямые: вертикальную и горизонтальную. Они должны пересекаться в центре вашего окна.
  • Напишите программу, которая рисует четыре линии: вертикальная, горизонтальная и 2 по диагонали. Все линии должны быть различного цвета. Размеры окна должны задаваться из командной строчке
  • Напишите программу, которая рисует такую картинку.



  • Перемещение площадей.

    Теперь когда мы знаем как рисовать линии в нашем окне, давайте посмотрим как из можно перемещать. Это достаточно просто. Нам просто необходимо изменять значения переменных, которые хранят координаты линии. Используя цикл, мы будем постоянно из изменять и таким образом заставим линию перемещать вверх вниз.
     1 #! /usr/bin/env python
     2 
     3 import pygame
     4 
     5 y = 0
    
     6 dir = 1
     7 running = 1
     8 width = 800
     9 height = 600
    10 screen = pygame.display.set_mode((width, height))
    11 linecolor = 255, 0, 0
    12 bgcolor = 0, 0, 0
    
    13 
    14 while running:
    15     event = pygame.event.poll()
    16     if event.type == pygame.QUIT:
    17         running = 0
    
    18 
    19     screen.fill(bgcolor)
    20     pygame.draw.line(screen, linecolor, (0, y), (width-1, y))
    21 
    22     y += dir
    23     if y == 0 or y == height-1: dir *= -1
    
    24 
    25     pygame.display.flip()
    


    При каждом проходе цикла мы определяем координату Y линии, увеличивая ее на -1 когда линия идет наверх и 1 когда вниз. Правда просто? Задание на дом
  • Закомментируйте строчку screen.fill(bgcolor) и запустите программу. Что Вы увидите?
  • Модернизируйте программу так, что бы на экране появилась вертикально движущуюся линия.

  • Рисуем цветную полосу

    Ну и в заключении мы нарисуем движущуюся цветную полосу. Как и наш предыдущий пример она будет двигаться.
     1 #! /usr/bin/env python
     2 
     3 import pygame
     4 
     5 y = 0
    
     6 dir = 1
     7 running = 1
     8 barheight = 124
     9 screen = pygame.display.set_mode((800, 600));
    10 
    11 barcolor = []
    12 for i in range(1, 63):
    
    13     barcolor.append((0, 0, i*4))
    14 for i in range(1, 63):
    15     barcolor.append((0, 0, 255 - i*4))
    16 
    17 while running:
    
    18     event = pygame.event.poll()
    19     if event.type == pygame.QUIT:
    20         running = 0
    21 
    22     screen.fill((0, 0, 0))
    23     for i in range(0, barheight):
    
    24         pygame.draw.line(screen, barcolor[i], (0, y+i), (799, y+i))
    25 
    26     y += dir
    27     if y + barheight > 599 or y < 0:
    
    28         dir *= -1
    29 
    30     pygame.display.flip()
    
    В этом примере мы создаем массив colorbar. В него мы заносим цвета от черного к ярко синему и снова к черному. Не забывайте что цвет состоит из трех цветов: красный, зеленный и синий. Т значения цветов варируется от о до 255.

    Если мы хотим получить плавный переход от черного к синему и снова к черному, то по идее мы должны сделать полосу шириной 512 пикселей. Но тогда мы получим очень широкую полосу, почти во все наше окно и не сможем видеть ее движение.

    Так что нам придется уменьшать ширину нашей полосы, что бы увидеть ее движение. Я решил что ширина в 124 пикселя будет вполне достаточной (62 пикселя от черного к синему и 62 от синего к черному). Таким образом за каждый шаг мне надо увеличивать значение цвета на 4 единицы.

    Мы будем использовать длва цикла для заполнения массива со значением цвета. В первом цикле мы будем получать значение цвета от черного к синему. Во втором от синего к черному.

    Запустите теперь эту программу и убедитесь что она работает. Убедитесь что Вам понятна логика ее работы. Поэксперементируйте с ней.

    Задание на дом
  • В приведенном примере очень много не понятных чисел. Устраните этот недостаток этого примера
  • Попробуйте использовать метод pygame.draw.aaline для отрисовки линий. Вы заметили разницу в скорости?
  • Поиграйте с цветом полосы
  • Напишите программу в которой двигаются три полосы различного цвета. При расчете высоты полосы не забудьте учитывать размер Вашего окна

  • В заключении
    В этой главе Вы научились рисовать линии. В дальнейшем мы еще поговорим об отрисовке линий прежде чем перейте к более интересным методам позволяющим загружать и выводить в окно изображения. В следующей главе мы поговорим об обработке событий от мышки.

    Обработка событий от мышки (Оригинал)

    В предыдущей части мы научились рисовать линии. В этой части мы поговорим об обработки событий от мыши. Мы по прежнему будем рассматривать простые примеры.

    В первой чсти нашего руководства мы узнали о событии QUIT. Теперь давайте посмотрим как мы можем определять положение мышки внутри нашего окна. Вот наш пример:
     1 #! /usr/bin/env python
     2 
     3 import pygame
     4 
     5 x = y = 0
    
     6 running = 1
     7 screen = pygame.display.set_mode((640, 400))
     8 
     9 while running:
    10     event = pygame.event.poll()
    
    11     if event.type == pygame.QUIT:
    12         running = 0
    13     elif event.type == pygame.MOUSEMOTION:
    14         print "mouse at (%d, %d)"
    % event.pos
    15 
    16     screen.fill((0, 0, 0))
    17     pygame.display.flip()
    
    Большая часть этого примера Вам должна быть знакома. Новое для начинается с 13 строчки, где мы отрабатываем событие MOUSEMOTION. В 14 строчке мы используем конструкцию event.pos для получения координат курсора мышки по оси X и оси Y.

    Обратите внимание что что значения event.pos показываются относительно верхнего левого угла вашего окна а не всего экрана (если конечно Вы не задали параметры что бы окно заняло весь экран).

    Задание на дом
  • Напишите программу которая выводит позиции указателя мыши в декартовых координатах. Предположим что оси Х и Y проходят через середину экрана. Не забудьте что ось Y направленна вверх, а ось X слева направо.
  • Замените событие MOUSEMOTION на MOUSEBUTTONDOWN. Запустите программу. Переместите указатели на окно и нажмите на кнопку. Что произошло?
  • Представьте себе что окно вашего приложения состоит из квадратов, размерами 32 на 32 пикселями. Напишите программу которую определяет координаты курсора мыши по этим квадратам и выводит их на экран.
  • Напишите программу которая определяет расстояние прямой от центра экрана до курcора мыши.

  • Выполнение одного цикла у меня занимает около 0.02 секунды. Давайте сделаем вот что. Сделаем так, что бы вслед за курсором передвигались декартовы оси.
     1 #! /usr/bin/env python
     2 
     3 import pygame
     4 
     5 x = y = 0
     6 running = 1
     7 screen = pygame.display.set_mode((640, 400))
     8 
     9 while running:
    10     event = pygame.event.poll()
    11     if event.type == pygame.QUIT:
    12         running = 0
    13     elif event.type == pygame.MOUSEMOTION:
    14         print "mouse at (%d, %d)"
    % event.pos
    15 
    16     screen.fill((0, 0, 0))
    17     pygame.display.flip()
    
    В этой программе Вы не увидите нечего нового для себя. Мы уже знаем как задается цвет линии, поэтому давайте ее немного усложним:
     1 #! /usr/bin/env python
     2 
     3 import pygame
     4 
     5 bgcolor = 0, 0, 0
     6 blueval = 0
     7 bluedir = 1
     8 x = y = 0
     9 running = 1
    10 screen = pygame.display.set_mode((640, 400))
    11 
    12 while running:
    13     event = pygame.event.poll()
    14     if event.type == pygame.QUIT:
    15         running = 0
    16     elif event.type == pygame.MOUSEMOTION:
    17         x, y = event.pos
    18 
    19     screen.fill(bgcolor)
    20     pygame.draw.line(screen, (0, 0, blueval), (x, 0), (x, 399))
    21     pygame.draw.line(screen, (0, 0, blueval), (0, y), (639, y))
    22     blueval += bluedir
    23     if blueval == 255 or blueval ==
    0: bluedir *= -1
    24     pygame.display.flip()