🎮
The Legend of PyZelda: Breath of the Snakes
  • Обложка
  • Введение
  • Подготовка
  • Пишем уровень
  • Создаём игрока
  • Создание камеры
  • Графика
  • Анимация Линка
  • Оружие героя
  • Интерфейс
  • Монстры
  • Драки с монстрами
  • Музыка
  • Деплой
  • Итоги
Powered by GitBook
On this page

Создаём игрока

Игрок должен уметь передвигаться и сталкиваться с существующими объектами. Сначала запишем его движения: переходим в player.py и прописываем функцию перемещения. Код в player.py:

import pygame
from settings import *
​
class Player(pygame.sprite.Sprite):
    def __init__(self, pos, groups):
        super().__init__(groups)
        self.image = pygame.image.load('../graphic/link.png').convert_alpha()
        self.rect = self.image.get_rect(topleft = pos)
​
        self.direction = pygame.math.Vector2() #обращаемся к направлению через вектор
​
    def input(self): #варьируем кнопки
        keys = pygame.key.get_pressed()
​
        if keys[pygame.K_UP]:
            self.direction.y = -1
        elif keys[pygame.K_DOWN]:
            self.direction.y = 1
        else:
            self.direction.y = 0
​
        if keys[pygame.K_LEFT]:
            self.direction.x = -1
        elif keys[pygame.K_RIGHT]:
            self.direction.x = 1
        else:
            self.direction.x = 0
​
    def update(self):
        self.input()

Тут с кодом достаточно просто. В функции self.direction = pygame.math.Vector2() мы задаём вектор точке. Точка — это наш герой, а его вектор болтается в диапазоне от -1 до 1. Функция keys = pygame.key.get_pressed() позволяет продолжать нажатие и тогда, герой должен разгоняться. Если нажатия нет — вектор равен 0 и герой тормозит. Это очень условное, но приписывание инерции.

Ещё в файле level.py в функции run я записал обновление всех спрайтов. Это строчка кода вида:

self.visible_sprites.update()

Ещё я переписал в том же файле вызов героя. Мне это нужно для глобализации позиции героя. Из строки

Player((x, y), [self.visible_sprites])

Я сделал

self.player = Player((x, y), [self.visible_sprites])

Продолжим прорисовку движений в файле player.py. Создадим ещё один параметр — скорость. Для этого в глобальные параметры (__init__) добавим строчку self.speed = 5

Также напишем функцию move:

def move(self, speed):
        self.rect.center += self.direction * speed

И в update-функции пропишем движения персонажа: self.move(self.speed).

Результат:

Если приглядеться, то по диагонали Линк бежит чуть быстрее. Дело в том, что он бежит по диагонали со скоростью корень из двух, что примерно равно 1.4. Мы прописали скорость вверх, вниз, влево и вправо равной 1, а вот по диагонали из правил математики, можно понять, что длина гипотенузы равна сумме квадратов длин оснований квадрата под корнем, то есть корень из (1^2 + 1^2). Исправим данный баг нормализацией от PyGame (да-да, как в Unity). Исправленная функция движения:

def move(self, speed):
    if self.direction.magnitude() != 0:
        self.direction = self.direction.normalize()
    self.rect.center += self.direction * speed

Теперь вторая проблема. Линк — танк. Он сбивает всё на своём пути. Нам нужны объекты, с которыми он будет сталкиваться Не забывайте, что все объекты у нас — квадраты тайлами.

Сейчас есть проблема — файл player.py не знает о наличии тайлов, которые отображаются через файл уровня. Поэтому дадим файлу новый аргумент. Добавим его в init и назовём obstacle_sprites. Также не забудьте в файле уровня сослаться на obstacle_sprites в отрисовке точки игрока. Для этого в файле level.py замените строку:

self.player = Player((x, y), [self.visible_sprites])

На строку:

self.player = Player((x, y), [self.visible_sprites], self.obstacle_sprites)

В файле игрока создадим метод столкновений под название collision. Функция:

def collision(self, direction):
    if direction == 'horizontal':
        for sprite in self.obstacle_sprites:
            if sprite.rect.colliderect(self.rect):
                if self.direction.x > 0: #двигаем вправо
                    self.rect.right = sprite.rect.left
                if self.direction.x < 0: #двигаем влево
                    self.rect.left = sprite.rect.right
​
    if direction == 'vertical':
        for sprite in self.obstacle_sprites:
            if sprite.rect.colliderect(self.rect):
                if self.direction.y > 0: #двигаем вниз
                    self.rect.bottom = sprite.rect.top
                if self.direction.y < 0: #двигаем вверх
                    self.rect.top = sprite.rect.bottom

В ней всё разделено на две координаты. По горизонтальной оси — x, по вертикальной — y. Если столкновение произошло по горизонтали, то делаем смещения (вправо или влево). Тоже самое по вертикали, но там вниз и вверх. Последний шаг — разделить метод в движении на два варианта: вертикальный и горизонтальный. То есть из строки:

self.rect.center += self.direction * speed

Делаем структуру:

self.rect.x += self.direction.x * speed
self.collision('horizontal')
self.rect.y += self.direction.y * speed
self.collision('vertical')

Получаем героя Хайрула без наклонностей в приведение:

PreviousПишем уровеньNextСоздание камеры

Last updated 1 year ago

Из предыдущей гифки видна следующая задача — создание камеры. Этим и займёмся. .

Ссылка на этот этап