Стрельба из пули в пигме в направлении мыши - PullRequest
1 голос
/ 30 января 2020

Я просто не могу понять, почему моя пуля не работает. Я сделал класс пули, и вот он:

class Bullet:
    def __init__(self):
        self.x = player.x
        self.y = player.y
        self.height = 7
        self.width = 2
        self.bullet = pygame.Surface((self.width, self.height))
        self.bullet.fill((255, 255, 255))

Теперь я добавил несколько функций в свой класс игры, и вот оно:

class Game:
    def __init__(self):
        self.bullets = []

    def shoot_bullet(self):
         if self.bullets:
            for bullet in self.bullets:
                rise = mouse.y - player.y
                run = mouse.x - player.x
                angle = math.atan2(rise, run)

                bullet.x += math.cos(angle)
                bullet.y += math.sin(angle)

                pygame.transform.rotate(bullet.bullet, -math.degrees(angle))
                D.blit(bullet.bullet, (bullet.x, bullet.y))


    def generate_bullet(self):
        if  mouse.is_pressed():
            self.bullets.append(Bullet())

Что я ожидал от кода? если бы Bullet() добавлялось к game.bullets каждый раз, когда я нажимал кнопку мыши, то game.shoot_bullet вычисляло бы угол между игроком и мышью и соответственно стреляло из пули в направлении мыши. Однако в результате получается полный беспорядок, и пули на самом деле не вращаются, не двигаются, они генерируются и странно движутся влево на экране. Я не уверен, что я что-то напутал или метод, который я использовал, совершенно неверен. Спасибо за помощь.

1 Ответ

4 голосов
/ 30 января 2020

Прежде всего pygame.transform.rotate не преобразует объект self, он создает новую повернутую поверхность и возвращает ее.

Что вы хотите сделать, это выстрелить в определенное направление. Направление определяется, когда пуля появляется, но оно не изменяется непрерывно.
Установите начальную позицию пули и вычислите вектор направления в положение мыши:

self.pos = (x, y)
mx, my = pygame.mouse.get_pos()
self.dir = (mx - x, my - y)

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

length = math.hypot(*self.dir)
if length == 0.0:
    self.dir = (0, -1)
else:
    self.dir = (self.dir[0]/length, self.dir[1]/length)

Вычислить угол вектора и повернуть пулю:

angle = math.degrees(math.atan2(-self.dir[1], self.dir[0]))

self.bullet = pygame.Surface((7, 2)).convert_alpha()
self.bullet.fill((255, 255, 255))
self.bullet = pygame.transform.rotate(self.bullet, angle)

Чтобы обновить положение bullet, достаточно масштабировать направление (по скорости) и добавить его к своей позиции:

self.pos = (self.pos[0]+self.dir[0]*self.speed, 
            self.pos[1]+self.dir[1]*self.speed)

Когда вы рисуете пулю, получаете прямоугольник поверхности пули и устанавливаете центр с помощью self.pos

bullet_rect = self.bullet.get_rect(center = self.pos)
surf.blit(self.bullet, bullet_rect)  

См. Пример:

import pygame
import math

pygame.init()
window = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()

class Bullet:
    def __init__(self, x, y):
        self.pos = (x, y)
        mx, my = pygame.mouse.get_pos()
        self.dir = (mx - x, my - y)
        length = math.hypot(*self.dir)
        if length == 0.0:
            self.dir = (0, -1)
        else:
            self.dir = (self.dir[0]/length, self.dir[1]/length)
        angle = math.degrees(math.atan2(-self.dir[1], self.dir[0]))

        self.bullet = pygame.Surface((7, 2)).convert_alpha()
        self.bullet.fill((255, 255, 255))
        self.bullet = pygame.transform.rotate(self.bullet, angle)
        self.speed = 2

    def update(self):  
        self.pos = (self.pos[0]+self.dir[0]*self.speed, 
                    self.pos[1]+self.dir[1]*self.speed)

    def draw(self, surf):
        bullet_rect = self.bullet.get_rect(center = self.pos)
        surf.blit(self.bullet, bullet_rect)  

bullets = []
pos = (250, 250)
run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        if event.type == pygame.MOUSEBUTTONDOWN:
            bullets.append(Bullet(*pos))

    for bullet in bullets[:]:
        bullet.update()
        if not window.get_rect().collidepoint(bullet.pos):
            bullets.remove(bullet)

    window.fill(0)
    pygame.draw.circle(window, (0, 255, 0), pos, 10)
    for bullet in bullets:
        bullet.draw(window)
    pygame.display.flip()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...