TileTool — модуль для обучения детей основам разработки игр

от автора

Последнее время из каждого чайника напористо лезет реклама обучения языку Python. И это не удивительно, поскольку Python уверенно занял лидирующее положение в качестве первого языка для изучения программирования. А его простота, обилие вспомогательных модулей и скорость написания кода сделали его лидером для обучения детей программированию, полностью вытеснив, популярные лет 20 назад QBasic и Pascal.

Обучаем играючи…

Последние тренды в обучении детей сводятся к игровым механикам. Чтобы заинтересовать ребенка программированием — преврати обучение в игру или предложи научиться игры создавать. Из-за этой логики одним из самых популярных модулей для Python, используемых в обучении стал Pygame, позволяющий создавать простые и не очень игры, без глубокого погружения в тонкости реализации, что очень удобно для детей в процессе начального освоения программирования.

О чем статья?

В этой статье я хотел бы поделиться с хабравцеми и маленькими хабрятами одним очень удобным дополнением для Pygame, найденным на просторах интернета буквально пару дней назад, но покорившем мое сердце. А все от того, что модуль, о котором пойдет речь, упрощает процесс создания 2D игрушек, делая его простым, наглядным, быстрым и увлекательным.

Маленький ликбез о плиточных играх

Огромное количество плоских 2D игрушек относятся к так называемым «плиточным» играм, в которых основой построения игрового мира служат минимальные элементы — плитки, чаще всего квадратные с нанесенной на них текстурой.

К плиточным играм относятся и Сапёр и легендарный Марио и практически все стратегии на развитие территорий и пошаговые стратегии.

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

Задача программиста нарисовать этот квадратный мир с помощью кода и научить персонажа в этом мире жить. Именно за простое создание игрового мира и отвечает модуль под названием TileTool.

TileTool — может всё или почти всё?

Устанавливаем модуль в командной строке

pip install tiletool

И через минуту мы готовы приступать.

У модуля на данный момент имеется три режима работы, то есть три варианта сборки мира.

  1. Генератор прямоугольников

  2. Создание мира из *.txt или *.csv файлов

  3. Создание мира из файлов *.tmx, созданных в визуальном редакторе плиточных уровней Tiled (https://www.mapeditor.org/ — сайт редактора)

Для начала необходимо создать минимальный каркас проекта на Pygame, выглядит он так:

import pygame #Импортируем модуль Pygame pygame.init() #Инициализируем инструментарий Pygame window=pygame.display.set_mode((700, 640)) #Создаем окно шириной 700 и высотой 640  while True: #Бесконечный цикл, в котором будет "жить" игра for i in pygame.event.get(): #Перебираем все события, происходящие в окне if i.type == pygame.QUIT: #Если событие совпадаем с "закрытием окна", то есть нажатием на креcтикстик pygame.quit() #Выходим из Pygame pygame.display.update() #Обновляем экран 

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

Теперь перейдем к созданию мира и сделаем это тремя разными способами.

Способ №1. Генератор.

TileTool позволяет создать прямоугольную область в виде контура или с заполнением клетками. Для этого до бесконечного цикла создаем объект на базе класса TileTool.

#Импортируем модуль TileTool import tiletool  #Cоздаем первый объект TileTool с шириной в 7 и высотой 5 тайлов #в координатах x=120 и y=120 с включенной заливкой #Необязательный параметр fill принимая значение 1, заполняет весь создаваемый прямоугольник плитками,мии #значение fill=0, оставляет внутреннее пространство пустым Box=tiletool.TileTool((7,5),120,120,fill=1)  #К созданному объекту Box применяем метод fill_dict, связывая таким образом #элементы созданной матрицы с графическими файлами тайлов Box.fill_dict((1,0),('platform2.png','Empty')) 

Тут требуется некоторое пояснение. В результате создания объекта, формируется двумерная матрица или таблица, такого вида:

в ней «1» стоят там, где позднее будут подставлены плитки, а «0» там, где останется пустое пространство.

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

Box.fill_dict((1,0),('platform2.png','Empty')) # (1, 0) - кортеж с возможными значениями матрицы # ('platform2.png','Empty') - соответствующий кортеж замен # цифра 1 из первого котрежа заменится на изображение из файла platform2.png, # цифра 0 заменится на "пустоту"

Всё, прямоугольник создан и заполнен тайлами. Осталось его отобразить в нашем окне.

while True: #Внутри бесконечного цикла к объекту Box применяем метод blit_tiles, в который передаем имя нашего окна Box.blit_tiles(window) 

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

#Добавим в бесконечный цикл строчку: Box.moving_tile((300,300),1,500,'HORIZONTAL',window)  #(300, 300) - левая или верхняя граница при движении платформы #1 - скорость движения #500 - значение правой или нижней границы движения платформы #'HORIZONTAL' или 'VERTICAL' - направление движения горизонтально или вертикально #window - имя окна  #И наша платформа будет двигаться горизонтально от точки (300,300) до (500,300) с минимальной скоростью 1. #Если это слишком быстро, можно настроить частоту кадров с помощью метода tick модуля Pygame  #А чтобы движущийся объект не оставлял за собой след, #над строкой с движением добавим заливку окна черным цветом window.fill((0,0,0))

В результате полный код примера с генератором платформ будет выглядеть так:

import pygame import tiletool  pygame.init() window=pygame.display.set_mode((700, 640)) #creating the window(создаем окно)  Box=tiletool.TileTool((7,5),120,120,fill=0) #Создаем платформу Box.fill_dict((1,0),('platform.png','Empty')) #Связываем графические файл и платформой. Файл platform.png должен содержать изображения тайла и лежать в папке с проектом  while True: window.fill((0,0,0)) #Заливаем окно черным для очистки следа от движущегося объекта    Box.blit_tiles(window) #Отображаем платформу на экране Box.moving_tile((300,300),1,500,'HORIZONTAL',window) #Заставляем платформу двигаться   for i in pygame.event.get():                               if i.type == pygame.QUIT:         pygame.quit() pygame.display.update()

Всего четыре строчки кода, а у нас уже есть движущаяся платформа, которая ко всему прочему, является наследницей класса pygame.sprite.Sprite, что позволяет добавлять ее в группы и проверять коллизии.

Способ 2. Создание мира из *.txt или *.csv файлов

Многие визуальные редакторы миров умеют экспортировать созданные слои, карты в формат csv или txt. Некоторые разработчики пользуются Excel’ем для рисования уровней. О вкусах не спорят. Тем не менее, TileTool прекрасно работает с подобными форматами. Внешне нарисованный в txt мир выглядит как то так:

По сути своей это такая же матрица, что создавалась Генератором в первом примере. Отличие лишь в том, что задача модуля не создать, а прочитать готовую матрицу из файла и связать ее с текстурами тайлов.

#Импортируем модули import pygame import tiletool  pygame.init() #Инициализируем инструментарий Pygame window=pygame.display.set_mode((800, 800)) #Создаем игровое окно #Cоздаем объект на основе csv-файла(файла с разделителем) в координатах(100,100)  Box1=tiletool.TileTool('test.csv',100,100) #Связываем ключи из файла с картинками, для 0 передаем "empty" Box1.fill_dict((42,21,0),('platform.png','platform2.png','empty')) #Cоздаем объект на основе txt-файла с разделителем в координатах(0,0)  Box2=tiletool.TileTool('temp.txt',0,0) #Cвязываем ключи из файла с картинками, для -1 передаем "empty" Box2.fill_dict((10,-1),('platform.png','empty'))  while True: window.fill((0,0,0)) #Размещаем оба объекта в окне Box1.blit_tiles(window) Box2.blit_tiles(window)  #Первый объект заставляем циклично двигаться  Box1.moving_tile((300,500),1,500,'VERTICAL',window)      for i in pygame.event.get():                             if i.type == pygame.QUIT:     pygame.quit() pygame.display.update()

Небольшое замечание по строчке

Box1.fill_dict((42,21,0),(‘platform.png’,’platform2.png’,’empty’))

В файлах txt и csv в открытом виде видны значения, используемые в построении миров. В методе fill_dict в первом кортеже необходимо перечислить все значения используемые в файлах, а во втором кортеже сопоставить значениям имена графических файлов, а чтобы оставить «пустоту», достаточно передать ’empty’.

Как и в первом примере — всего пара строк и из текстовых файлов получаются готовые платформы.

Способ 3. Создание мира из файлов *.tmx (редактор миров Tiled)

Не скрою, это мой любимый способ, поскольку визуальный редактор уровней Tiled в разы упрощает и ускоряет процесс создания больших и сложных уровней для двумерных игрушек. Умеет работать как с плоскими картами, так и с изометрией, что дает возможности создавать псевдо 3D игры.

Редактор "плиточных" уровней Tiled
Редактор «плиточных» уровней Tiled

Проект Tiled содержит в себе файлы *.tsx, *.tmx, графические файлы тайлов.

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

И так, к практике:

import tiletool import pygame  window=pygame.display.set_mode((800, 800))  #Создаем два объекта из одного файла desert1.tmx,  #отличаться объекты будут номером слоя, за который будут отвечать. #Так, Box1 становится хозяином слоя №1 и мы может независимо управлять этим слоем #Box2 становится владельцем слоя №2, который мы позднее заставим двигаться. Box1=tiletool.TileTool('desert1.tmx',0,0,layer=1) Box2=tiletool.TileTool('desert1.tmx',0,0,layer=2) #Нам не нужно вызывать метод fill_dict, так как вся информация о изображениях, #привязанных к ключам, указана в .tsx файле, относящемуся к данному .tmx файлу  while True: window.fill((0,0,0))    Box1.blit_tiles(window)   Box2.blit_tiles(window)        Box2.moving_tile((0,0),1,200,'HoriZONTAL',window)        for i in pygame.event.get():                               if i.type == pygame.QUIT:     pygame.quit()   pygame.display.update() #Oбновляем экран

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

Способ 4 (бонусный):

У модуля TileTool есть еще один приятный метод, позволяющий в пару строк создавать персонажа и нацеливать на него виртуальную камеру, которая будет следить за ним, создавая иллюзию движения. Выглядит это так:

А реализуется примерно так:

import tiletool import pygame window=pygame.display.set_mode((700, 640))  #Cоздаем объект класса TileTool на основе первого слоя .tmx файла. b1=tiletool.TileTool('desert.tmx',0,0,layer=1)  #Загружаем изображение и конвертируем его в подходящий формат, теперь в переменной filename находится файла с изображением нашего героя. filename=pygame.image.load('platform.png').convert_alpha()  #Cоздаем объект класса platforms_objects в координатах x=100,y=200,  #за ним будет следовать камера. Также передаем в метод изображение героя. f1=tiletool.platforms_objects(100,20,filename)  #Cледующие 2 строчки ограничивают частоту кадров в секунду clock = pygame.time.Clock() fps = 300  #Kамера будет следить за объектом f1 в координатах (0-1000) по x и (0-1000) по y.  #При выходе из этих координат объект выйдет за пределы экрана. camera_obj=tiletool.camera(1000,1000,f1)  while True: window.fill((0,0,0)) #Заливаем окно черным для очистки следа от движущегося объекта.   clock.tick(fps) #Настраиваем скорость обновления экрана.  #Oтображаем объект в окне. Необходимо передать объект класса camera во все вызовы blit_tiles.   b1.blit_tiles(window,camera_obj)        #Oтображаем объект platforms_objects в окне.    #Следует передать вызов метода drawCam,    #как в примере вместо свойства rect объекта,    #чтобы объект мог отображаться в координатах, нужных камере.   window.blit(f1.image,camera_obj.drawCam(f1))         for i in pygame.event.get():                               if i.type == pygame.QUIT:      pygame.quit()        # Эти сторочки отвечают за движение объекта, используйте стрелки для движения.   keys = pygame.key.get_pressed()   if keys[pygame.K_LEFT]:   f1.rect.x-=1   elif keys[pygame.K_RIGHT]:   f1.rect.x+=1   elif keys[pygame.K_DOWN]:   f1.rect.y+=1   elif keys[pygame.K_UP]:   f1.rect.y-=1        pygame.display.update() # Oбновляем экран.

Сравнительно недавно я в учебных целях реализовывал один уровень игры Марио, на что у меня ушло около 6 часов чистого времени. Познакомившись с модулем TileTool я решил переписать свой проект с использованием предоставившихся возможностей. Времени ушло 2.5 часа, а код сократился практически вдвое!

Автор модуля заявляет, что в следующих версиях появится поддержка изометрии, что даст возможность упрощать работу над псевдо 3D играми, что было бы очень кстати.

А в качестве заключения, хочу лишний раз подчеркнуть, что наличие огромного числа модулей для Python’a позволяет в разы сократить время прототипирования и разработки практически любых программ. И что тоже немаловажно, дает возможность не углубляться в изучение всего подряд, позволяя сосредоточится на одном узком направлении. На примере TileTool, я не хочу заморачиваться с «рисованием миров» и тратить на это свое время, мне интереснее физика движения, игровая механика, реалистичные коллизии, и на отработке этих элементов я хотел бы сосредоточиться. Те же, кому наоборот интереснее генерировать миры, могут сосредоточиться на изучении этой темы, а для физики движения использовать сторонние модули. Как говорится о вкусах не спорят!

Благодарю за терпение в данном лонгриде. Обзор получился довольно общим, и позволяет в общих чертах познакомиться с модулем, упрощающем жизнь создателей плиточных игрушек. Если стиль изложения и данный модуль вам понравились, с радостью поделюсь со всеми парой подробных и пошаговых статей-мануалов, написанных лично, о том как я с помощью модуля TileTool реализовал игры Марио и Сапёр. А также, если интересно, могу выложить мануал по редактору Tiled.


ссылка на оригинал статьи https://habr.com/ru/post/665042/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *