In my program, when the keys are pressed, the image of the ship is flipped. I decided to bind the direction of the bullets to the flags of the ship's position. But I ran into the problem that all bullets take the direction of the ship when they are already fired. I need to keep the coordinate of the sprite when it is drawn.
import sys
import pygame
from settings import Settings
from rocket import Rocket
from bullet import Bullet
class Cosmos:
"""Главный класс игры Cosmos"""
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
pygame.display.set_caption('Cosmos')
self.fon_image = pygame.image.load('image/Fon.png')
self.fon = self.fon_image.get_rect()
self.settings = Settings()
self.rocket = Rocket(self.screen, self.settings)
self.bullets = pygame.sprite.Group()
def key_event(self):
"""Обрабатывает нажатие клавиш"""
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
sys.exit()
elif event.key == pygame.K_d:
self.rocket.move_RIGHT = True
elif event.key == pygame.K_a:
self.rocket.move_LEFT = True
elif event.key == pygame.K_w:
self.rocket.move_UP = True
elif event.key == pygame.K_s:
self.rocket.move_DOWN = True
elif event.key == pygame.K_SPACE:
self.fire_bullet()
elif event.type == pygame.KEYUP:
if event.key == pygame.K_d:
self.rocket.move_RIGHT = False
elif event.key == pygame.K_a:
self.rocket.move_LEFT = False
elif event.key == pygame.K_w:
self.rocket.move_UP = False
elif event.key == pygame.K_s:
self.rocket.move_DOWN = False
def fire_bullet(self):
"""Создание нового снаряда и включение его в группу"""
new_bullet = Bullet(self.screen, self.settings, self.rocket)
self.bullets.add(new_bullet)
def run_game(self):
"""Обновляет события игры"""
while True:
self.screen.blit(self.fon_image, self.fon)
self.key_event()
self.rocket.update_rocket()
for bullet in self.bullets.sprites():
bullet.draw_bullet()
self.bullets.update(bullet)
self.rocket.draw_rocket()
pygame.display.flip()
game = Cosmos()
game.run_game()
from pygame.sprite import Sprite
class Bullet(Sprite):
"""Класс для управления снарядами, выпущенными кораблем"""
def __init__(self, screen, settings, rocket):
super().__init__()
self.screen = screen
self.settings = settings
self.rocket = rocket
self.color = self.settings.bullets_color
self.rect = pygame.Rect(0, 0, self.settings.bullets_width, self.settings.bullets_height)
self.rect.midtop = rocket.rect.midtop
self.y = float(self.rect.y)
self.x = float(self.rect.x)
def update(self, bullet):
"""Перемещение снаряда"""
if self.rocket.image == self.rocket.image_right:
bullet.x += 2
if self.rocket.image == self.rocket.image_left:
bullet.x -= 2
if self.rocket.image == self.rocket.image_up:
bullet.y -= 2
if self.rocket.image == self.rocket.image_down:
bullet.y += 2
self.rect.x = self.x
self.rect.y = self.y
def draw_bullet(self):
"""Рисует снаряд"""
pygame.draw.rect(self.screen, self.color, self.rect)
import pygame
class Rocket:
"""Класс для управления кораблём"""
def __init__(self, screen, settings):
self.screen = screen
self.screen_rect = screen.get_rect()
self.settings = settings
self.image = pygame.image.load('image/pixil-frame-0.png')
self.rect = self.image.get_rect()
self.rect.center = self.screen_rect.center
self.x = float(self.rect.x)
self.y = float(self.rect.y)
self.move_RIGHT = False
self.move_LEFT = False
self.move_UP = False
self.move_DOWN = False
self.image_right = pygame.transform.rotate(self.image, -90)
self.image_left = pygame.transform.rotate(self.image, 90)
self.image_up = pygame.transform.rotate(self.image, 0)
self.image_down = pygame.transform.rotate(self.image, 180)
def update_rocket(self):
"""Флаги управления кораблём"""
if self.move_RIGHT and self.rect.right < self.screen_rect.right:
self.image = self.image_right
self.x += self.settings.rocket_speed
if self.move_LEFT and self.rect.left > self.screen_rect.left:
self.image = self.image_left
self.x -= self.settings.rocket_speed
if self.move_UP and self.rect.top > self.screen_rect.top:
self.image = self.image_up
self.y -= self.settings.rocket_speed
if self.move_DOWN and self.rect.bottom < self.screen_rect.bottom:
self.image = self.image_down
self.y += self.settings.rocket_speed
self.rect.x = self.x
self.rect.y = self.y
def draw_rocket(self):
"""Обновляет позицию корабля"""
self.screen.blit(self.image, self.rect)
The problem here is that in Bullet.update
, you use the current image of the rocket to determine in which direction the bullet is going. This means that any change of this image results in a change of direction. Instead of doing this, you should save the current direction upon creating a new Bullet
instance and then use this saved direction to determine the direction of the rocket.
A possible implementation:
class Bullet(Sprite):
"""Класс для управления снарядами, выпущенными кораблем"""
def __init__(self, screen, settings, rocket):
super().__init__()
self.screen = screen
self.settings = settings
self.rocket = rocket
self.color = self.settings.bullets_color
self.rect = pygame.Rect(0, 0, self.settings.bullets_width, self.settings.bullets_height)
self.rect.midtop = rocket.rect.midtop
self.y = float(self.rect.y)
self.x = float(self.rect.x)
if self.rocket.image == self.rocket.image_right:
self.direction = "right"
elif self.rocket.image == self.rocket.image_left:
self.direction = "left"
elif self.rocket.image == self.rocket.image_up:
self.direction = "up"
elif self.rocket.image == self.rocket.image_down:
self.direction = "down"
def update(self, bullet):
"""Перемещение снаряда"""
if self.direction == "right":
bullet.x += 2
if self.direction == "left":
bullet.x -= 2
if self.direction == "up":
bullet.y -= 2
if self.direction == "down":
bullet.y += 2
self.rect.x = self.x
self.rect.y = self.y
def draw_bullet(self):
"""Рисует снаряд"""
pygame.draw.rect(self.screen, self.color, self.rect)