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

Рейтинг: -1Ответов: 1Опубликовано: 10.02.2023

Мне нужна пушка, которая вращается нажатием стрелок (я уже это сделал), чтобы стрелять "металлическими" шариками, летящими по баллистической траектории (и на них действует сила сопротивления воздуха), и при столкновении с ракетами ("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

Ответы

▲ 0Принят

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

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()