Как сделать хитбокс в pygame

Добавил пользователь Алексей Ф.
Обновлено: 04.10.2024

pygame - это библиотека модулей для языка Python, созданная для разработки 2D игр.

Для того чтобы установить pygame на свой компьютер необходимо открыть командную строку или терминал и написать команду

pip3 install pygame

После установки необходимо создать новый файл и импортировать модуль pygame и написать шаблон игры

Пользователь может взаимодействовать с нашей игрой. Каждое действие пользователя - это некоторое событие , которое мы можем обработать . Выражение pygame.event.get() - это список событий, произошедших в нашей игре.

Цикл for просто перебирает необработанные события. Каждое событие он присваивает переменной event (можно написать любую другую).

Поговорим о цикле while , основном цикле игры . Как часто он выполняется? Очень и очень часто, это зависит от мощности компьютера. Для обновления экрана в играх часто используют 60 кадров в секунду.

Ограничим количество выполнений цикла.

import pygame
from sys import exit

display = pygame.display. set_mode ( ( 800 , 600 ) )

Методу tick() передается желаемое количество кадров в секунду. Задержку он вычисляет сам. На каждой итерации основного цикла игры секунда делится на 60 и на вычисленную величину выполняется задержка.

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

Функция polygon() рисует произвольную фигуру. Она принимает 3 обязательных параметра (поверхность, цвет и кортеж координат) и 1 необязательный (толщину линий).

import pygame
from sys import exit

display = pygame.display. set_mode ( ( 800 , 600 ) )

FPS = 60
clock = pg.time. Clock ()
while True :
f or event in pygame.event. get ():
if event.type == pygame.QUIT:
pygame. quit ()
exit ()

display - наша поверхность

(255, 0, 0) - красный цвет , почитайте про rgb

( (0, 0), (100, 0), (100, 100), (0, 100) ) - координаты вершин квадрата. Возьмите листочек и нарисуйте его координатах (замените сотню на единицу).

Давайте нарисуем треугольник

import pygame
from sys import exit

display = pygame.display. set_mode ( ( 800 , 600 ) )

(0, 0, 255) - синий цвет

((100, 100), (200, 200), (100, 200)) - координаты вершин нашего треугольник.

Самостоятельно нарисуйте пятиугольник (вам помогут карандаш и лист бумаги)

Рисование окружностей

Чтобы нарисовать окружность нужно вызвать метод circle из модуля draw. Команда выглядит так: pygame.draw.circle(display, color, position, radius).

display - поверхность, на которой рисуем

color - цвет, записанный в кортеже из трех чисел. (еще раз про rgb)

position - координаты точки центра окружности ( кортеж из двух чисел (x, y) )

radius - радиус окружности в пикселях

import pygame
from sys import exit

display = pygame.display. set_mode ( ( 800 , 600 ) )

FPS = 60
clock = pg.time. Clock ()
while True :
f or event in pygame.event. get ():
if event.type == pygame.QUIT:
pygame. quit ()
exit ()

display - наша поверхнотсть для рисования

(255, 255, 0) - желтый цвет

(400, 200) - координаты точки центра (в нашем случае 400 пикселей от верхнего левого угла по горизонтали и 200 пикселей по вертикали)

100 - радиус нашей окружности в пикселях

Объявления переменных для цветов

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

import pygame
from sys import exit

WHITE = ( 255 , 255 , 255 )
BLACK = ( 0 , 0 , 0 )
PURPLE = ( 156 , 39 , 176 )
INDIGO = ( 63 , 81 , 181 )
BLUE = ( 33 , 150 , 243 )
GREEN = ( 76 , 175 , 80 )
YELLOW = ( 255 , 235 , 59 )
ORANGE = ( 255 , 152 , 0 )
GREY = ( 158 , 158 , 158 )

display = pygame.display. set_mode ( ( 800 , 600 ) )

FPS = 60
clock = pg.time. Clock ()
while True :
f or event in pygame.event. get ():
if event.type == pygame.QUIT:
pygame. quit ()
exit ()

Рисование прямоугольников

Для отрисовки прямоугольников можно использовать метод rect.

pygame.draw.rect(display, color, (x, y, width, height) )

color - цвет (теперь можно просто написать имя переменную)

(x, y, width, height) - кортеж из четырех значений. Первые два значения - это координаты верхнего левого угла прямоугольника, а два последних - это ширина и высота.

import pygame
from sys import exit

WHITE = ( 255 , 255 , 255 )
BLACK = ( 0 , 0 , 0 )
PURPLE = ( 156 , 39 , 176 )
INDIGO = ( 63 , 81 , 181 )
BLUE = ( 33 , 150 , 243 )
GREEN = ( 76 , 175 , 80 )
YELLOW = ( 255 , 235 , 59 )
ORANGE = ( 255 , 152 , 0 )
GREY = ( 158 , 158 , 158 )

display = pygame.display. set_mode ( ( 800 , 600 ) )

FPS = 60
clock = pg.time. Clock ()
while True :
f or event in pygame.event. get ():
if event.type == pygame.QUIT:
pygame. quit ()
exit ()

Если ваша творческая натура требует большего, то вот ссылка на документацию модулю draw

Там можно найти рисование линий, дуг, эллипсов.

Большой пример ( запусти его у себя на компьтере:

Продолжаем создание игры с Pygame и Python

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

Мы уже использовали поверхности, но Pygame также предлагает другой класс, Sprite, который предназначен в качестве базового класса для видимых объектов.

В первую очередь нам понадобится создать класс с названием GameObject, который будет инкапсулировать некоторое общее поведение и данные для всех других игровых объектов. Классы, представляющие определенные объекты (например, космический корабль), наследуют от него и расширяют его своим собственным поведением и данными.

Класс GameObject будет хранить следующие данные:

position (положение): Точка в центре объекта на 2D-экране

sprite (спрайт): изображение, используемое для отображения объекта

radius (радиус): значение, представляющее зону столкновения вокруг положения объекта

velocity (скорость): Значение, используемое для движения

Вот графическое представление игрового объекта:

Изображение

Спрайтом будет поверхность, загруженная load_sprite() из предыдущих примеров. Радиус-это целое число, указывающее количество пикселей от центра объекта до края зоны столкновения. Однако для самого положения и скорости потребуется новый тип: вектор.

Векторы похожи на кортежи. В 2D - мире (например, в вашей игре) векторы представлены двумя значениями, указывающими координаты x и y. Эти координаты могут указывать на положение, но они также могут представлять движение или ускорение в заданном направлении. Векторы можно добавлять, вычитать или даже умножать, чтобы быстро обновить положение спрайта. Вы можете прочитать больше о векторах в Векторах в 2-мерном пространстве.

Из-за того, насколько полезны векторы в играх, у Pygame уже есть класс для них: Vector2 в модуле pygame.math. Он предлагает некоторые дополнительные функции, такие как вычисление расстояния между векторами и добавление или вычитание векторов. Эти функции значительно облегчат реализацию вашей игровой логики.

В каталоге space_rocks создайте новый файл с именем models.py. На данный момент он будет хранить класс GameObject, но позже мы добавим классы для астероидов, пуль и космического корабля. Файл должен выглядеть следующим образом:


from pygame.math import Vector2

class GameObject:
def __init__(self, position, sprite, velocity):
self.position = Vector2(position)
self.sprite = sprite
self.radius = sprite.get_width() / 2
self.velocity = Vector2(velocity)

def draw(self, surface):
blit_position = self.position - Vector2(self.radius)
surface.blit(self.sprite, blit_position)

def move(self):
self.position = self.position + self.velocity

def collides_with(self, other_obj):
distance = self.position.distance_to(other_obj.position)
return distance

Первая строка импортирует класс Vector2.

В строке class GameObject создается класс GameObject, который вы будете использовать для представления всех игровых объектов в игре.

Строка def init() конструктор класса GameObject. Для этого нужны три аргумента:

position: Центр объекта

sprite: изображение, используемое для рисования этого объекта

velocity: обновляет положение объекта в каждом кадре

Метод Vector2() гарантируют, что положение и скорость всегда будут представлены в виде векторов для будущих вычислений, даже если кортежи передаются конструктору. Вы делаете это, вызывая конструктор Vector2(). Если ему задан кортеж, то он создаст из него новый вектор. Если ему задан вектор, то он создаст копию этого вектора.

В строке self.radius радиус вычисляется как половина ширины изображения спрайта. В этой программе спрайты игровых объектов всегда будут квадратами с прозрачным фоном. Вы также можете использовать высоту изображения—это не будет иметь никакого значения.

Функция draw(), которая будет рисовать спрайт объекта на поверхности, переданной в качестве аргумента.

Строка blit_position вычисляет правильное положение для размытия изображения. Этот процесс более подробно описан ниже. Обратите внимание, что конструктор Vector2() получает одно число вместо кортежа. В этом случае он будет использовать это число для обоих значений. Таким образом, Vector2(self.radius) является эквивалентом Vector2((self.radius, self.radius)).

Добавим космический корабль. Для чего скопируем изображение космического корабля в assets/sprites:

Структура нашего проекта должна выглядеть следующим образом:

game_project/
|
+-- space_rocks/
+-- __main__.py
+-- game.py
+-- models.py
L-- utils.py
|_
assets/
|
L-- sprites/
L-- space.jpg
|_ spaceship.jpg

Теперь изменим space_rocks/game.py файл:

from models import GameObject
from utils import load_sprite

class SpaceRocks:
def __init__(self):
self._init_pygame()
self.screen = pygame.display.set_mode((800, 600))
self.background = load_sprite("space", False)
self.spaceship = GameObject(
(400, 300), load_sprite("spaceship"), (0, 0)
)

def _process_game_logic(self):
self.spaceship.move()

def _draw(self):
self.screen.blit(self.background, (0, 0))
self.spaceship.draw(self.screen)
pygame.display.flip()

Объект помещаются в середине экрана, используя координаты (400, 300). Положение будет обновляться каждый кадр с помощью _process_game_logic(), и он будет нарисован с помощью _draw().

Запустите эту программу, и вы увидите космический корабль, неподвижно стоящий в середине экрана:

Изображение

Таким образом мы добавили в проект новый класс на основе которого можно отображать объекты игрового пространства.


Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления

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

Порекомендуйте эту статью друзьям:

Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):

Она выглядит вот так:

Комментарии ( 0 ):

Еще одна проблема, которую я недавно пытался решить, - это настройка размера хитбокса плеера. Вот как я пытался изменить размер хит-бокса (Rect's):

После тестирования я обнаружил, что при добавлении/вычитании суммы будет изменяться только ширина и высота, а не значения x или y. Я не совсем уверен, куда идти отсюда. Можете ли вы сказать мне, если есть что-то, что я делаю неправильно, или даже если есть лучшее или простое решение для этого?

Pygame уже предлагает некоторые решения для этого.

Если вы используете обработку коллизий Pygame, (например, pygame.sprite.spritecollide , pygame.sprite.groupcollide или pygame.sprite.spritecollideany ), обратите внимание, что вы можете использовать функцию обратного вызова, используемую для расчета, если два спрайта сталкивающимися (в collided аргумент).

По умолчанию используется pygame.sprite.collide_rect , но в вашем случае вы должны взглянуть на pygame.sprite.collide_rect_ratio :

pygame.sprite.collide_rect_ratio()
Обнаружение столкновений между двумя спрайтами с использованием масштабов, пропорциональных пропорциям.
collide_rect_ratio(ratio) → collided_callable

Вот как реализовано collide_rect_ratio .

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

Поэтому, возможно, вы захотите изменить функцию, чтобы проверить, имеет ли pseudo_rect атрибут pseudo_rect , а затем использовать его вместо атрибута rect .

Затем в ваших классах спрайтов вы можете сделать что-то вроде этого:

если вы хотите придать спрайту больший хитбокс (не забудьте установить атрибут center rect.center в rect.center всего, что вы изменяете в rect ).

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

Я использую pygame.rect.colliderect() , чтобы проверить столкновение hitbox между спрайтами в моей игре, но теперь, когда я вращаю спрайты, я Понимаю, я не могу этого сделать, потому что нет возможности повернуть PyGame rect , так что чекбоксы ушли. р>

Как я должен обрабатывать столкновение в игре с вращающимися спрайтами, если я не хочу использовать маски или идеальное столкновение пикселей? Есть ли способ сделать hitbox, который вращается со спрайтом?

4 ответа

Как уже упоминалось, pygame напрямую не поддерживает поддержку вращающихся hitboxes. Тем не менее, вы можете либо задуматься о кодировании собственных классов полей, не ориентированных по оси, или использовать небольшой обман. Чит в основном вычисляет выровненный по оси hitbox, который полностью содержит ваш спрайт. Это довольно легко вычислить и может быть достаточно хорошим для вашей игры, в зависимости от ваших потребностей, конечно. Я сам использую трюк в своем текущем игровом проекте.

Итак, вот основной план расчета. Вам нужно будет поворачивать каждый угол вашего спрайт-изображения по количеству оборотов, а затем находить самые большие и малые координаты и строить вокруг них поле. Код может выглядеть примерно так в псевдокоде (semi Python):

rotate -функция должна выглядеть примерно так:

Это то, что дает моя быстрая и грязная реализация:

Основываясь на ответе Tyyppi_77 выше, есть несколько подходов, которые вы можете предпринять:

1) Изменение размера окна ударов (как он подсказывает) - хотя вы можете сделать это намного проще, просто используя image.get_rect (), который будет иметь тот же результат.

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

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

Python на практике: используйте pygame для создания начального игрового интерфейса (1)

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

  • Создайте окно Python с синим фоном
    Сначала используйте pycharm для создания файла проекта. Метод именования лучше всего соотносить с проектом, который вы делаете, как известно из названия.
    Сначала создайте пустое окно pygame и установите его цвет фона (цвет фона можно настроить, а цвет RGB получается через Baidu)

Метод pygame.event.get () используется для обнаружения пользовательских событий и определения операций, выполняемых пользователем.
Метод screen.fill () заполняет экран цветом фона.
Код содержит следующие процессы:

  1. Импорт модуля (модули, которые нам нужно использовать в настройках игры ниже, вот два, модуль pygame содержит функции, необходимые для разработки игры, а модуль sys используется для выхода из игры)
  2. Инициализировать игру и создать экранные объекты (установить свойства экрана)
  3. Откройте игровой цикл (обнаруживайте действия пользователя, обновляйте экран)



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

  • Поместите изображение в центр экрана и установите такой же цвет фона
    Добавьте изображение на экран и создайте класс корабля для управления настройками изображения, см. код.
    ship.py

Примечание. Определите метод __init __ (). (Содержит два формальных параметра: self, screen. Метод __init __ () принимает значения этих формальных параметров и сохраняет их в атрибутах экземпляра, созданных в соответствии с этим классом), __ - два символа подчеркивания, и только один вводится изначально. Давно искал ошибку.


Реализуя эти две небольшие функции, мы используем множество методов в модуле pygame и напрямую вызываем методы, которые были установлены в модуле для реализации функций. Это действительно обеспечивает большое удобство, поэтому, когда вы хотите Напишите сложную игру самостоятельно. Важно понимать функции каждого модуля и каждого метода. Конечно, если вы напишете больше, это произойдет естественным образом.
Взгляните на визуализации:

Изображение центрируется, а цвет фона не регулируется. При выборе изображения лучше, если фон будет прозрачным. Формат изображения должен быть растровым (т. е. суффикс .Bmp). Конечно, можно также добиться перемещения картинок вверх, вниз, влево и вправо. Я не буду писать их здесь по очереди. Я расскажу об этом в обновленных блогах. На самом деле, в этих блогах нет технический уровень, просто примечание и добавление некоторого понимания., это удобно для использования в будущем, и, кстати, может углубить впечатление.
Один Леле не так хорош, как остальные: писать - это музыка, комментировать - это музыка, видеть - это музыка, музыка - это самое важное.

Читайте также: