Как мне остановить одновременный выпуск более 1 пули?
import pygame pygame.init()
red = 255,0,0 blue = 0,0,255 black = 0,0,0
screenWidth = 800 screenHeight = 600
gameDisplay = pygame.display.set_mode((screenWidth,screenHeight)) ## screen width and height pygame.display.set_caption('JUST SOME BLOCKS') ## set my title of the window
clock = pygame.time.Clock()
classplayer(): ## has all of my attributes for player 1 def__init__(self,x,y,width,height): self.x = x self.y = y self.height = height self.width = width self.vel = 5 self.left = False self.right = False self.up = False self.down = False
classprojectile(): ## projectile attributes def__init__(self,x,y,radius,colour,facing): self.x = x self.y = y self.radius = radius self.facing = facing self.colour = colour self.vel = 8 * facing # speed of bullet * the direction (-1 or 1)
defdraw(self,gameDisplay): pygame.draw.circle(gameDisplay, self.colour , (self.x,self.y),self.radius) ## put a 1 after that to make it so the circle is just an outline
defredrawGameWindow(): for bullet in bullets: ## draw bullets bullet.draw(gameDisplay)
pygame.display.update()
#mainloop
player1 = player(300,410,50,70) # moves the stuff from the class (when variables are user use player1.var) bullets = []
run = True while run == True: clock.tick(27) for event in pygame.event.get(): if event.type == pygame.QUIT: run = False
for bullet in bullets: if bullet.x < screenWidth and bullet.x > 0and bullet.y < screenHeight and bullet.y > 0: ## makes sure bullet does not go off screen bullet.x += bullet.vel else: bullets.pop(bullets.index(bullet))
keys = pygame.key.get_pressed() ## check if a key has been pressed
## red player movement if keys[pygame.K_w] and player1.y > player1.vel: ## check if that key has been pressed down (this will check for w) and checks for boundry player1.y -= player1.vel ## move the shape in a direction player1.up = True player1.down = False
if keys[pygame.K_a] and player1.x > player1.vel: ### this is for a player1.x -= player1.vel player1.left = True player1.right = False
if keys[pygame.K_s] and player1.y < screenHeight - player1.height - player1.vel: ## this is for s player1.y += player1.vel player1.down = True player1.up = False
if keys[pygame.K_d] and player1.x < screenWidth - player1.width - player1.vel: ## this is for d player1.x += player1.vel player1.right = True player1.left = False
if keys[pygame.K_SPACE]: # shooting with the space bar if player1.left == True: ## handles the direction of the bullet facing = -1 else: facing = 1
iflen(bullets) < 5: ## max amounts of bullets on screen bullets.append(projectile(player1.x + player1.width //2 ,player1.y + player1.height//2,6,black,facing)) ##just like calling upon a function
## level
gameDisplay.fill((0,255,0)) ### will stop the shape from spreading around and will have a background pygame.draw.rect(gameDisplay,(red),(player1.x,player1.y,player1.width,player1.height)) ## draw player pygame.display.update() redrawGameWindow()
pygame.quit()
Когда я стреляю, срабатывает более 1 пули, и я хочу, чтобы одновременно срабатывала только 1 пуля (но не только 1 пуля на экране) Все они стреляют большим скоплением и к тому же слипаются, поэтому я хочу, чтобы они стреляли в разное время Я пробовал использовать задержку clock.tick но из-за этого игра сильно лагает
Я относительно новичок в pygame и не до конца понимаю его, буду признателен за любую помощь, спасибо!
Переведено автоматически
Ответ 1
Общий подход к запуску пуль заключается в сохранении позиций пуль в списке (bullet_list). Когда пуля выпущена, добавьте начальную позицию пули ([start_x, start_y]) в список. Начальная позиция - это позиция объекта (игрока или врага), который выпускает пулю. Используйте for-цикл для перебора всех маркеров в списке. Переместите положение каждого отдельного маркера в цикле. Удалите маркер из списка, который покидает экран (bullet_list.remove(bullet_pos)). По этой причине необходимо выполнить копию списка (bullet_list[:]) (см. Как удалять элементы из списка во время итерации?). Используйте другой for-цикл для blit оставшихся пуль на экране:
bullet_list = []
while run == True: # [...]
for event in pygame.event.get(): if event.type == pygame.QUIT: run = False
if event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE: bullet_list.append([start_x, start_y])
for bullet_pos in bullet_list[:]: bullet_pos[0] += move_bullet_x bullet_pos[1] += move_bullet_y ifnot screen.get_rect().colliderect(bullet_image.get_rect(center = bullet_pos)) bullet_list.remove(bullet_pos)
# [...]
for bullet_pos in bullet_list[:] screen.blit(bullet_image, bullet_image.get_rect(center = bullet_pos))
Состояния, которые возвращаются с помощью pygame.key.get_pressed(), устанавливаются до тех пор, пока нажата клавиша. Это полезно для перемещения игрока. Проигрыватель продолжает двигаться, пока нажата клавиша. Но это противоречит вашим намерениям, когда вы хотите выпустить пулю. Если вы хотите запускать пулю при нажатии клавиши, то можете использовать KEYDOWN событие. Событие происходит только один раз при нажатии клавиши:
while run == True: clock.tick(27) for event in pygame.event.get(): if event.type == pygame.QUIT: run = False
if event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE: if player1.left == True: ## handles the direction of the bullet facing = -1 else: facing = 1 iflen(bullets) < 5: ## max amounts of bullets on screen bx, by = player1.x + player1.width //2 ,player1.y + player1.height//2 bullets.append(projectile(bx, by, 6, black, facing))
# [...]
Если вы хотите реализовать какой-то быстрый запуск, тогда все становится сложнее. Если бы вы использовали состояние pygame.key.get_pressed(), то вы бы создавали по одной пуле в каждом кадре. Это слишком быстро. Вам нужно реализовать некоторый тайм-аут.
При выпуске пули текущее время определяется с помощью pygame.time.get_ticks(). Определите количество миллисекунд для задержки между выстрелами. Добавьте значение dela ко времени и укажите время в переменной (next_bullet_threshold). Пропускайте пули, пока время не превышено:
next_bullet_threshold = 0
run = True while run == True:
# [...]
current_time = pygame.time.get_ticks() if keys[pygame.K_SPACE] and current_time > next_bullet_threshold:
run = True while run: clock.tick(60) current_time = pygame.time.get_ticks() for event in pygame.event.get(): if event.type == pygame.QUIT: run = False
if event.type == pygame.KEYDOWN: iflen(bullet_list) < max_bullets and current_time >= next_bullet_time: next_bullet_time = current_time + bullet_delta_time bullet_list.insert(0, tank_rect.midright)
for i, bullet_pos inenumerate(bullet_list): bullet_list[i] = bullet_pos[0] + 5, bullet_pos[1] if bullet_surf.get_rect(center = bullet_pos).left > window.get_width(): del bullet_list[i:] break
window.fill((224, 192, 160)) window.blit(tank_surf, tank_rect) for bullet_pos in bullet_list: window.blit(bullet_surf, bullet_surf.get_rect(center = bullet_pos)) pygame.display.flip()