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