Часть 3. ВЫВОД ТЕКСТА И ОТСЧЕТ ВРЕМЕНИ


Рабочие файлы этого урока в (Архиве .zip) и на Github: Вывод текста и отсчет времени.
Изменения в файлах:
models.py → Добавлен новый класс для рисования надписей на экране.
roguelike.py → Определение объекта под указателем мышки, вывод названия объекта по клику и появление текста на заданное время.
Более подробное описание урока Далее...

Поскольку писать уроки намного дольше и сложнее, чем писать код самой игры, я решил изменить форму написания уроков, сделав её поэтапной. Иначе написание уроков отнимает у меня сликшом много времени и не дает развивать сам код своего проекта... Теперь не будет сразу подробного и детального урока, а сначала будет краткое описание, потом со временем оно будет дорабатываться до более подробного и детального вида.. В начале каждого урока теперь будет ссылка на рабочие python-скрипты на Github на текущем этапе разработки, эти скрипты можно скачать, посмотреть код с детальными комментариями и сразу запустить, проверив работу.


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


Для tileset-картинки предметов assets/Items1.png, добавил список имен items1_Names:
items1_Names = ['Ящик', 'Открый ящик', 'Сундук', 'Открый сундук', 'Бочка', 'Открытая бочка', 'Мешочек', 'Мешок', 'Большой мешок']

В models.py добавлен новый класс текстовых объектов-надписей textObj.
class textObj(): ### объекты, которые создаются при необходимости нарисовать текст на экране игры
    def __init__(self, pos, text_str, text_color, exist_time=-1, fontName=None, fontSize=24):
        self.pos = pos #положение на экране
        self.text_str = text_str #строка текста
        self.text_color = text_color #цвет текста
        self.alpha = 255 #прозрачность
        self.exist_time = exist_time #время существования текста до удаления, если -1, то текст постоянный
        self.textVisible = True #показывать или не показывать этот текст
        self.fontName = fontName #шрифт
        self.fontSize = fontSize #размер шрифта
        self.time1 = None #переменная для значений времени

В roguelike.py добавлены новые блоки кода.

При клике на экран игры, функция pygame.event.get() получает событие о нажатии кнопки MOUSEBUTTONDOWN, при котором начинается определение объекта под курсором: функция .collidepoint(...) определяет прямоугольную область объекта, на которой находится указатель мыши, вторая функция img_mask.get_at(...) проверяет прозрачен ли пиксель в месте нажатия мышки. Если клик произошел в непрозрачную область (то есть видимую часть объекта), то у предмета под курсором мыши берется имя и создается новый объект-надпись нашего нового класса textObj. Он заносится в глобальный список всех текстовых надписей-объектов textObjectList[], после чего его переменной timeObj.time1 присваивается текущее время(момент клика мыши), и в последнем параметре указывается число 1500 (время существования надписи в миллисекундах):
for event in pygame.event.get(): ### добавляем свой функционал в цикл получения сообщений от мыши и клавиатуры   
    if event.type == MOUSEBUTTONDOWN: ### если произошло событие - нажатие кнопки мыши
        mouse_pos = event.pos ### Получаем x,y координаты мыши на экране игры
        for curObj in gameObjectList: ### Для всех объектов проверяем попадение курсора мыши в этот объект
            pos_in_mask = mouse_pos[0] - curObj.img_rect.x, mouse_pos[1] - curObj.img_rect.y ### вычисление позиции курсора относительно координат маски прозрачности объекта
            if curObj.img_rect.collidepoint(mouse_pos) and curObj.img_mask.get_at(pos_in_mask) == 1: ### проверяем, находится ли мышь на каком-то объекте, и прозрачен ли пиксель, на котором находится указатель мыши
                new_time_obj = models.textObj([mouse_pos[0],mouse_pos[1]], curObj.objName, (255,255,255) ,1500) ### Создаем текстовый объект с координатами указателя мыши, текстом, равным имени объекта под мышкой, белым цветом шрифта(255,255,255) и временем существования 1500 миллисеукнд
                new_time_obj.time1 = time.time() ### в свойство текстового объекта time1 заносим время, когда этот текст создан                            
                textObjectList.append(new_time_obj) ### Добавляем новую надпись(текстовый объект) в список всех надписей
                break ### после первого найденного объекта под мышью, выходим из цикла, чтобы не появлялось несколько надписей в одном месте

Ближе к концу скрипта roguelike.py, после цикла отрисовки объектов из списка gameObjectList[], сделанном во втором уроке, добавлен похожий цикл отрисовки всех надписей(текстовых объектов textObj):
for indx,_ in enumerate(textObjectList): ### перечисляем все надписи(текстовые объекты из их общего списка)
    textObj = textObjectList[indx] ### работаем с самим объектом, а не копией, как в случае просто for цикла, чтобы не тратить лишнюю память
    if textObj.textVisible == False: ### Если в объекте указана невидимость
        continue ### пропускаем этот объект
    textSurf = pygame.font.SysFont(textObj.fontName, textObj.fontSize).render(textObj.text_str, False, textObj.text_color) ### рисуем текст(создаем поверхность Surface с текстом)
    screen.blit( textSurf, textObj.pos ) ### накладываем поверхность с нарисованным текстом на поверхность экрана, выводя текст на игровой экран
    if textObj.exist_time != -1: ### если у надписи указано время существования(exist_time)
        elapsed = (time.time() - textObj.time1)*1000 ###проверяем сколько миллисекунд прошло со времени создания надписи
        if elapsed > textObj.exist_time: ### если прошло больше времени, чем указано во времени существования (exist_time)
            textObjectList.pop(indx) ### удаляем объект из списка надписей

Функция pygame.font.SysFont(...) делает картинку-поверхность(pygame.Surface), которая представляет из себя надпись, созданную из параметров текущего текстового объекта. Далее эта поверхность с надписью накладывается на поверхность screen(игровой экран) функцией screen.blit(...) в координаты, указанные в textObj.pos.
Также, в этом цикле отрисовки надписей, замеряется время, прошедшее со времени создания надписи и заносится в переменную elapsed. Это значение сравнивается со переменной exist_time надписи (которая задает, сколько миллисекунд надпись будет существовать), если время уже вышло, объект удаляется из списка всех надписей textObjectList[], и таким образом текст исчезает с экрана через указанное время.

Вопросы, замечания и обсуждение в Discord: https://discord.gg/hqx6Kg9

Комментарии