Doodle Jump на pygame

    Добрый…
    Хочу рассказать и показать вам свой опыт знакомства с библиотекой pygame — предположительно отличной библиотекой для реализации графичиских приложений (в большей степени игр-аркад) на языке python. Для примера была реализована (частично) игра Doodle Jump.

    Дисклеймер


    • Да, я использовал чужие картинки — мне стыдно и я скоро это исправлю.
    • Персонаж сейчас может только прыгать, но я планирую дописать игру до конца.
    • Да, идея не нова, но прикольно ведь получилось.
    • Да, скорее всего бред — использовать интерпретируемый язык для написания игр.
    • Я не профессиональный программист и это моя не основная деятельность.


    Вместо введения


    Python. Python великолепен в плане документации. Она есть, она понятна, она не лишена отличных примеров. Pygame — не исключение, поэтому предлагаю пока не останавливаться на подробностях реализации этой библиотеки, но необходимо заметить, что ее средства позволяют подгрузить изображение, и просто перемещать его по x и y. Ничего лишнего.

    Архитектура


    Постараемся разработатать архитектуру приложения в лучших традициях ООП. Имеем следующую диаграмму классов:

    Сторонники MVC модели уже плачут, т.к. и логика и представление засунуты в тело класса.
    Имеем 3 локации:
    • StartLocation — здесь крутится меню и приглашение к игре.
    • GameLocation — собственно сабж.
    • ExitLocation — выход, результаты, фанфары-овации.

    Базовый объект Sprite, от которого наследуются все игровые объекты — платформы, кнопки, главный герой и т.д. По схеме все ясно.

    Ключевые моменты


    Events

        def event(self, event):
            if event.type == QUIT:
                sys.exit()
            elif event.type == KEYUP:
                if event.key == K_ESCAPE:
                    # do something
    
    if event.type == MOUSEMOTION:
                for btn in self.buttons:
                    if btn.rect.collidepoint(pygame.mouse.get_pos()):
                    #pass
                        btn.changeState(1)

    С помощью механизма эвентов прозрачно перехватываются нажатия клавиш и манипуляции с мышью.

    Изображения

    
            self.img_l = pygame.image.load('img/doodle_l.png').convert()
            self.image = self.img_l
            self.image.set_colorkey(self.image.get_at((0,0)), RLEACCEL)
            self.rect = self.image.get_rect()
            self.rect.center = (self.x,self.y)

    Подгружаем картинки для спрайтов.

    Столкновения

    self.doodle.getLegsRect().colliderect(spr.getSurfaceRect())

    Метода coliderect возвращает true, если прямоугольники, ограничивающие спрайты пересекаются.

    Пара скриншотов





    ToDo


    • Проработать гемплей
    • Нарисовать новые спрайты
    • Добавить звуки
    • Добавить статистику
    • Поправить алгоритмы расположения платформ
    • Добавить управление стрелками
    • Что еще?


    Вместо послесловия


    Знакомство с pygame можно считать законченым, дудлер прыгает и радуется жизни, но нагрузка процессора при этом стремится к 50-70%, что не есть гуд. Что это, говнокод плохая архитектура приложения или особенности языка — решать вам. Спасибо за внимание.
    Исходники на github.
    Поделиться публикацией

    Похожие публикации

    Комментарии 15

      +3
      Говорите не программист? Вполне себе сносно спроектировали дизайн. Я смотрел сорцы оригинального дудлера на JS. Так вот Ваш код изящнее и чище можете собой гордиться. Чем же вы зарабатываете, если не этим?
        +3
        Спасибо. Но я инженер в телекоме, занимаюсь сетями.
          +1
          И активным сетевым оборудованием.
          +2
          Примерно подобная реакция и у меня была. Почаще бы такие «не программисты» работали в сфере софт-девелопмента
          –4
          >>нагрузка процессора при этом стремится к 50-70%
          помоему это в любой игре будет так — отрисовка ведь постоянная
            +1
            Попалось место где не допрыгнуть :(
              +1
              Добавил в ToDo. В данный момент примитивнейший алгоритм рандомом распологает платформы. Бывает некоторые липнут к стене даже, хотя должны двигаться например.
              0
              Да, жрёт круто. Это в коде что-то не так, python тут ни при чём.
                0
                Измерьте, сколько FPS (кадров в секунду отрисовывается). Если очень много (больше 100, к примеру), то может стоит ограничить. Или если мало FPS, то наверняка не используется двойная буферизация и т.п.
                  +1
                  fps выставляется в коде методом clock()
                +5
                Да, скорее всего бред — использовать интерпретируемый язык для написания игр.

                Ничуть.
                  +3
                  Попробовал отпрофилировать — большая часть времени работает метод {method 'blit' of 'pygame.Surface' objects} — т.е. отрисовка внутри PyGame.

                  >>> p.sort_stats('cumulative').print_stats(10)
                  Wed Oct 19 14:34:27 2011    profile.txt
                  
                           253095 function calls (252783 primitive calls) in 35.892 CPU seconds
                  
                     Ordered by: cumulative time
                     List reduced from 753 to 10 due to restriction <10>
                  
                     ncalls  tottime  percall  cumtime  percall filename:lineno(function)
                          1    0.001    0.001   35.893   35.893 main.py:4(<module>)
                          1    0.050    0.050   35.811   35.811 main.py:32(main)
                      22623   30.889    0.001   30.889    0.001 {method 'blit' of 'pygame.Surface' objects}
                       1797    0.202    0.000   28.373    0.016 locations.py:88(draw)
                        214    0.004    0.000    3.343    0.016 locations.py:37(draw)
                       2011    3.334    0.002    3.334    0.002 {pygame.display.flip}
                       2011    0.310    0.000    0.310    0.000 {method 'tick' of 'Clock' objects}
                          1    0.000    0.000    0.258    0.258 main.py:16(__init__)
                       1796    0.021    0.000    0.231    0.000 sprites.py:68(setX)
                          1    0.063    0.063    0.206    0.206 {pygame.display.set_mode}


                  Так что самый простой способ — снизить FPS (при этом подкорректировав скорость по Y и гравитацию). При 25 FPS, гравитации 1.3 и вертикальной скорости 35 выглядит приемлемо, а процессора жрет заметно меньше (хотя все еще прилично).
                    +2
                    Учту в следующих коммитах. Спасибо.
                    0
                    Надеюсь напишете тут статью когда закончите?!
                    И еще бы добавить возможность управления стрелками. Курсор частенько вылетает за рамки окна… и инопланетянин перестаёт двигаться тогда… а в опасный момент это и подвести может.
                      –2
                      По-моему это великолепно. Именно такими людьми совершаются инновации на сцене видеоигр (т.к. мастодонты не любят рисковать). Ну а известную игру выбрать для начала — это правильно, т.к. есть рабочий образец и есть на что ориентироваться. Пожелаю успехов на этом поприще и жду новых игр!

                      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                      Самое читаемое