Как сделать баллистическую траекторию для снаряда?

Мне нужна пушка, которая вращается нажатием стрелок (я уже это сделал), чтобы стрелять "металлическими" шариками, летящими по баллистической траектории (и на них действует сила сопротивления воздуха), и при столкновении с ракетами ("Rockets"), которые летят в цель ("Mansion"), сбивать эти самые ракеты и исчезать вместе с ними. Я не могу придумать способ поместить снаряды за дуло пушки и запустить их по баллистической траектории

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

from random import randint
import sys
import pygame
import math

pygame.init()
run = True
width = 1280
height = 720
fps = 30
gameDisplay = pygame.display.set_mode((width, height))
pygame.display.set_caption('Air Defence')
clock = pygame.time.Clock()
pygame.time.set_timer(pygame.USEREVENT, 2000)


background = pygame.image.load('background.png').convert()
background = pygame.transform.smoothscale(background, gameDisplay.get_size())


mansion = pygame.image.load('mansion.png')
mansion = mansion.convert()
mansion.set_colorkey((0, 0, 0))
mansion = pygame.transform.scale(mansion, (mansion.get_width() // 6, mansion.get_height() // 6))


tower = pygame.image.load('tower.png')
tower = tower.convert()
tower.set_colorkey((0, 0, 0))
tower = pygame.transform.scale(tower, (tower.get_width() // 3, tower.get_height() // 3))


def blitRotate(surf, image, pos, originPos, angle):
    image_rect = image.get_rect(topleft=(pos[0] - originPos[0], pos[2] - originPos[2]))
    offset_center_to_pivot = pygame.math.Vector2(pos) - image_rect.center

    rotated_offset = offset_center_to_pivot.rotate(-angle)

    rotated_image_center = (pos[0] - rotated_offset.x, pos[1] - rotated_offset.y)

    rotated_image = pygame.transform.rotate(image, angle)
    rotated_image_rect = rotated_image.get_rect(center=rotated_image_center)

    surf.blit(rotated_image, rotated_image_rect)


def blitRotate2(surf, image, topleft, angle):
    rotated_image = pygame.transform.rotate(image, angle)
    new_rect = rotated_image.get_rect(center=image.get_rect(topleft=topleft).center)

    surf.blit(rotated_image, new_rect.topleft)
    pygame.draw.rect(surf, (255, 0, 0), new_rect, 2)


try:
    image = pygame.image.load('gun.png')
    image = pygame.transform.scale(image, (image.get_width() // 10, image.get_height() // 10))

except:
    text = pygame.font.SysFont('Times New Roman', 50).render('image', False, (255, 255, 0))
    image = pygame.Surface((text.get_width() + 1, text.get_height() + 1))
    pygame.draw.rect(image, (0, 0, 255), (1, 1, *text.get_size()))
    image.blit(text, (1, 1))
w, h = image.get_size()

RIGHT = "to the right"
LEFT = "to the left"
STOP = "stop"

angle = 0
motion = STOP


r = pygame.image.load('rocket.png')
r = r.convert()
r.set_colorkey((0, 0, 0))
r = pygame.transform.scale(r, (r.get_width() // 25, r.get_height() // 25))
score = 5


class rocket(pygame.sprite.Sprite):

    def __init__(self, x, speed, group):
        pygame.sprite.Sprite.__init__(self)
        self.mansion = mansion
        self.image = r
        self.rect = self.image.get_rect(center=(x, -100))
        self.angle = 180 * (math.atan((980 - x) / (height - self.rect.centery))) / math.pi
        self.speed = speed.rotate(-self.angle)
        self.add(group)
        self.image = pygame.transform.rotate(self.image, self.angle)
        self.rect = self.image.get_rect(center=(x, -100))
        self.score = score

    def update(self, *args):
        if self.rect.y < args[0] - 10:
            self.rect.y += self.speed.y
            self.rect.x += self.speed.x
        else:
            self.kill()

        if self.rect.colliderect(mansion_on):
            self.kill()
            self.score -= 1

        # elif self.rect.collidepoint()


def cRockets(group):
    x = randint(20, width - 20)
    speed = pygame.math.Vector2(0, randint(9, 10))
    return rocket(x, speed, group)


rockets = pygame.sprite.Group()
cRockets(rockets)

ground = height - 70
ro = 100

black = (0, 0, 0)
white = (255, 255, 255)


class Bullet(pygame.sprite.Sprite):
    def __init__(self, x, y, speedx, speedy):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((width, height))
        self.image.fill(black)
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y
        self.speedx = speedx
        self.speedy = speedy

    def update(self):
        self.rect.x += self.speedx - 2
        self.rect.y += self.speedy - 9.8
        if self.rect.bottom < 0 or self.rect.right < 0 or self.rect.top > h or self.rect.left > w:
            self.kill()


bullets = pygame.sprite.Group()


while run:
    clock.tick(fps)
    pos = (240, 475)
    gameDisplay.fill(0)
    gameDisplay.blit(background, (0, 0))
    rx = randint(0, 1280)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                motion = LEFT
            elif event.key == pygame.K_RIGHT:
                motion = RIGHT
            # elif event.key == pygame.K_SPACE:
            #     player.shoot()
        elif event.type == pygame.KEYUP:
            if event.key in [pygame.K_LEFT,
                             pygame.K_RIGHT]:
                motion = STOP
        elif event.type == pygame.USEREVENT:
            cRockets(rockets)

    if motion == LEFT:
        blitRotate(gameDisplay, image, pos, (w / 2, h / 2), angle)
        angle += 1
        if angle > 90:
            angle -= 1
    elif motion == RIGHT:
        blitRotate(gameDisplay, image, pos, (w / 2, h / 2), angle)
        angle -= 1
        if angle < -90:
            angle += 1
    elif motion == STOP:
        blitRotate(gameDisplay, image, pos, (w / 2, h / 2), angle)
        angle += 0

    mansion_on = mansion.get_rect(center=(920, 590))
    gameDisplay.blit(mansion, mansion_on)

    tower_on = tower.get_rect(center=(240, 580))
    gameDisplay.blit(tower, tower_on)

    rockets.draw(gameDisplay)
    pygame.display.update()
    pygame.display.flip()
    rockets.update(height)

pygame.quit()
exit()

Вот картинки которые я использовал для кода: background.png gun.png mansion.png rocket.png ![tower.png]]6


Ответы (1 шт):

Автор решения: Girday337

Решил сам, спасибо за "помощь"

from random import randint
import sys
import pygame
import math

pygame.init()
run = True
width = 1280
height = 720
fps = 30
gameDisplay = pygame.display.set_mode((width, height))
pygame.display.set_caption('Air Defence')
clock = pygame.time.Clock()
pygame.time.set_timer(pygame.USEREVENT, 2000)
cooldown = 0

# Отрисовка заднего фона

background = pygame.image.load('background.png').convert()
background = pygame.transform.smoothscale(background, gameDisplay.get_size())

# Отрисовка цели

mansion = pygame.image.load('mansion.png')
mansion = mansion.convert()
mansion.set_colorkey((0, 0, 0))
mansion = pygame.transform.scale(mansion, (mansion.get_width() // 6, mansion.get_height() // 6))
m_rect = mansion.get_rect(center=(920, 590))

# Отрисовка башни ПВО

tower = pygame.image.load('tower.png')
tower = tower.convert()
tower.set_colorkey((0, 0, 0))
tower = pygame.transform.scale(tower, (tower.get_width() // 3, tower.get_height() // 3))

# Пушка ПВО


def blitRotate(surf, image, pos, originPos, angle):
    image_rect = image.get_rect(topleft=(pos[0] - originPos[0], pos[1] - originPos[1]))
    offset_center_to_pivot = pygame.math.Vector2(pos) - image_rect.center

    rotated_offset = offset_center_to_pivot.rotate(-angle)

    rotated_image_center = (pos[0] - rotated_offset.x, pos[1] - rotated_offset.y)

    rotated_image = pygame.transform.rotate(image, angle)
    rotated_image_rect = rotated_image.get_rect(center=rotated_image_center)

    surf.blit(rotated_image, rotated_image_rect)


def blitRotate2(surf, image, topleft, angle):
    rotated_image = pygame.transform.rotate(image, angle)
    new_rect = rotated_image.get_rect(center=image.get_rect(topleft=topleft).center)

    surf.blit(rotated_image, new_rect.topleft)
    pygame.draw.rect(surf, (255, 0, 0), new_rect, 2)


try:
    image = pygame.image.load('gun.png')
    image = pygame.transform.scale(image, (image.get_width() // 6, image.get_height() // 10))

except:
    text = pygame.font.SysFont('Times New Roman', 50).render('image', False, (255, 255, 0))
    image = pygame.Surface((text.get_width() + 1, text.get_height() + 1))
    pygame.draw.rect(image, (0, 0, 255), (1, 1, *text.get_size()))
    image.blit(text, (1, 1))
w, h = image.get_size()

RIGHT = "to the right"
LEFT = "to the left"
STOP = "stop"

angle = 0
motion = STOP

# Спавн ракет

r = pygame.image.load('rocket.png')
r = r.convert()
r.set_colorkey((0, 0, 0))
r = pygame.transform.scale(r, (r.get_width() // 25, r.get_height() // 25))
score = 5
num = 1


class rocket(pygame.sprite.Sprite):

    def __init__(self, x, speed, group, num):
        pygame.sprite.Sprite.__init__(self)
        self.mansion = mansion
        self.image = r
        self.rect = self.image.get_rect(center=(x, -100))
        self.angle = 180 * (math.atan((980 - x) / (590 - self.rect.centery))) / math.pi
        self.speed = speed.rotate(-self.angle)
        self.add(group)
        self.image = pygame.transform.rotate(self.image, self.angle)
        self.rect = self.image.get_rect(center=(x, -100))
        self.score = score
        self.num = num

    def update(self, *args):
        if self.rect.y < args[0] - 10:
            self.rect.y += self.speed.y
            self.rect.x += self.speed.x

        else:
            self.kill()

        if self.rect.colliderect(mansion_on):
            self.kill()
            self.score -= 1


def cRockets(group):
    x = randint(20, width - 20)
    speed = pygame.math.Vector2(0, randint(8, 9))
    return rocket(x, speed, group, num)


rockets = pygame.sprite.Group()
cRockets(rockets)

ground = height - 70
ro = 100

black = (0, 0, 0)
white = (255, 255, 255)

# Пульки

yadro = pygame.image.load('yadro.png')
yadro = yadro.convert()
yadro.set_colorkey((0, 0, 0))
yadro = pygame.transform.scale(yadro, (yadro.get_width() // 50, yadro.get_height() // 50))

delta = 0


class Bullet(pygame.sprite.Sprite):
    def __init__(self, x, y, speed, group):
        pygame.sprite.Sprite.__init__(self)
        self.image = yadro
        self.rect = self.image.get_rect()
        self.delta = delta
        self.delta = (self.delta + angle) + 180
        self.speed = speed.rotate(-self.delta)
        self.add(group)
        self.rect.x = x
        self.rect.y = y

    def update(self):
        self.rect.x += self.speed.x
        self.rect.y += self.speed.y + 1
        self.speed += pygame.math.Vector2(0, 6 * clock.get_time() * 0.001)

        for i in rockets:
            if i.rect.collidepoint(self.rect.x, self.rect.y):
                self.kill()
                i.kill()


def cBullets(group):
    x = 213
    y = 465
    speed = pygame.math.Vector2(0, 20)
    return Bullet(x, y, speed, group)


bullets = pygame.sprite.Group()
cBullets(bullets)


# РЛС


class Radar:

    def __init__(self, dis):
        self.max_distance = dis

    def scan(self):
        global rockets
        results = []
        for r in rockets:
            if math.sqrt((r.rect.x - 300) ** 2 + (900 - r.rect.y) ** 2) <= self.max_distance:
                results.append((r.num, int(math.atan((r.rect.x - 400) / (900 - r.rect.y)) / math.pi * 180),
                                int(math.sqrt((r.rect.x - 400) ** 2 + (900 - r.rect.y) ** 2))))
        return results


RLS = Radar(1000)

# Запуск программы

while run:
    clock.tick(fps)
    pos = (240, 476)
    gameDisplay.fill(0)
    gameDisplay.blit(background, (0, 0))
    rx = randint(0, 1280)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                motion = LEFT
                delta = -1
            elif event.key == pygame.K_RIGHT:
                motion = RIGHT
                delta = 1
            elif (event.key == pygame.K_SPACE) and (pygame.time.get_ticks() >= cooldown + 1000):
                cBullets(bullets)
                cooldown = pygame.time.get_ticks()
            elif event.key == pygame.K_BACKSPACE:
                cRockets(rockets)
                num += 1
        elif event.type == pygame.KEYUP:
            if event.key in [pygame.K_LEFT,
                             pygame.K_RIGHT]:
                motion = STOP
        elif event.type == pygame.USEREVENT:
            cRockets(rockets)
            num += 1

    bullets.draw(gameDisplay)

    if motion == LEFT:
        blitRotate(gameDisplay, image, pos, (w / 2, h / 2), angle)
        angle += 1
        if angle > 88:
            angle -= 1
    elif motion == RIGHT:
        blitRotate(gameDisplay, image, pos, (w / 2, h / 2), angle)
        angle -= 1
        if angle < -90:
            angle += 1
    elif motion == STOP:
        blitRotate(gameDisplay, image, pos, (w / 2, h / 2), angle)
        angle += 0

    if pygame.time.get_ticks() % fps == 0:
        print('SCANNING:', *RLS.scan())

    mansion_on = mansion.get_rect(center=(920, 590))
    gameDisplay.blit(mansion, mansion_on)

    tower_on = tower.get_rect(center=(240, 580))
    gameDisplay.blit(tower, tower_on)

    rockets.draw(gameDisplay)
    pygame.display.update()
    pygame.display.flip()
    bullets.update()
    rockets.update(height)

pygame.quit()
exit()
→ Ссылка