Создание целей исчезают при столкновении с пулей, используя списки - PullRequest
1 голос
/ 24 марта 2020

Я разрабатываю небольшую игру-шутер для школьных курсовых работ. Я попал в тупик после полутора часов итераций и тестирования. Если вы видите код ниже, я использовал списки, чтобы сделать так, чтобы при попадании пуль в цель они удалялись из списка и больше не печатались с «pygame.draw.rect», но, похоже, это намного сложнее для цели, как я сделал это, используя OOP, а не одну функцию. Я попытался скопировать списки с целями, поместив оператор «IF» в те же места и т. Д. c. но в итоге я получаю тот же результат: цель поражена, и напечатано «удар». Пуля исчезает, но цель - нет. Я использую язык только около месяца, так что, хотя я все больше привыкаю к ​​нему, я все еще не эксперт, и я действительно зашел в тупик здесь. Любая помощь будет принята с благодарностью. Это может быть случай, когда мне придется полностью переосмыслить свой подход и радикально изменить свой код, но, возможно, есть кое-что, что вы можете увидеть, чего я не могу. Спасибо за любую помощь. (Извините за запутанность кода, это после многих изменений и итераций. Также обратите внимание, что в настоящее время я только кодировал, чтобы проверить его на target_1, чтобы сэкономить время)

import pygame

#Setting window dimensions and caption. (Module 1)

pygame.init()
window = pygame.display.set_mode((800, 575))
pygame.display.set_caption("TARGET PRACTICE")

#Colour variables. (Module 1)

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (200, 0, 0)
GREEN = (0, 200, 0)
BLUE = (0, 0, 200)

#py_clock tracks framerate of program for other 'pygame.time' commands. (Module 8)

py_clock = pygame.time.Clock()

#Target class created. (Module 5)

class Target:
  def __init__(self, x, y, h, w, v):
    self.x = x
    self.y = y
    self.h = h
    self.w = w
    self.v = v

  def hit(self):
    print('hit')
    all_bullets_keep.remove(item)
    all_targets.remove(all_targets[0])
    pass



#Instantiation of targets. (Module 5)

target_1 = Target(0, 80, 60, 40, 0.05)
target_2 = Target(0, 100, 60, 40, 0.5)
target_3 = Target(0, 50, 60, 40, 0.5)
target_4 = Target(0, 75, 60, 40, 0.5)
target_5 = Target(0, 45, 60, 40, 0.5)
target_6 = Target(0, 85, 60, 40, 0.5)


#Instantiation of hitboxes. (Module 9)

target_hbx1 = Target(-5, 75, 70, 50, 0.05)
target_hbx2 = Target(-5, 95, 70, 50, 0.5)
target_hbx3 = Target(-5, 45, 70, 50, 0.5)
target_hbx4 = Target(-5, 70, 70, 50, 0.5)
target_hbx5 = Target(-5, 40, 70, 50, 0.5)
target_hbx6 = Target(-5, 80, 70, 50, 0.5)


#Declaring variables to be used in the while loop. (Module 5)

clock = 0

target_2_threshold = 500
target_3_threshold = 1000
target_4_threshold = 1500
target_5_threshold = 2000
target_6_threshold = 2500



#Setting player sprite dimension variables. (Module 6)

player_sprite_x = 357.5
player_sprite_y = 450
player_sprite_h = 125
player_sprite_w = 85

#all_bullets list to store bullets made by function inside loop. (Module7)

all_bullets = []

all_targets = []

all_targets.append(target_1)
all_targets.append(target_2)
all_targets.append(target_3)
all_targets.append(target_4)
all_targets.append(target_5)
all_targets.append(target_6)

#Variables to track and limit shooting function. (Module 9.5)

bullet_delay = 1500 
next_bullet_time = 0


exec = True

while exec:

  #current_time uses a pygame_time command to track ticks. (Module 9.5)

  current_time = pygame.time.get_ticks()

  for event in pygame.event.get():
    if event.type == pygame.QUIT:
            exec = False


    #'IF' statement to trigger the shooting function. (Module 7)

    if event.type == pygame.MOUSEBUTTONDOWN:

        #Condition set to only trigger the below code if the current_time is greater than the next_bullet time. (Module 9.5)

        if event.button == 1 and current_time > next_bullet_time:

            next_bullet_time = current_time + bullet_delay

            dx = event.pos[0] - (player_sprite_x+ player_sprite_w//2)
            dy = event.pos[1] - player_sprite_y
            direction = pygame.math.Vector2(dx, dy).normalize()
            bullet = {'x': player_sprite_x+42, 'y': player_sprite_y, 'direction': direction}
            all_bullets.append(bullet)




 #Defines movement of targets and sets delay between drawings. (Module 5)   



  for item in all_targets:
    target_1.x += target_1.v
    target_hbx1.x += target_hbx1.v
    if clock > target_2_threshold:
        target_2.x += target_2.v
        target_hbx2.x += target_hbx2.v
    if clock > target_3_threshold:
        target_3.x += target_3.v
        target_hbx3.x += target_hbx3.v
    if clock > target_4_threshold:
        target_4.x += target_4.v
        target_hbx4.x += target_hbx4.v
    if clock > target_5_threshold:
        target_5.x += target_5.v
        target_hbx5.x += target_hbx5.v
    if clock > target_6_threshold:
        target_6.x += target_6.v
        target_hbx6.x += target_hbx6.v





  #all_bullets_keep list combined with FOR loop retains only bullets in the arena. (Module 7)

  all_bullets_keep = []

  for item in all_bullets:
    item['x'] += item['direction'][0] # item['direction'][0] * 2
    item['y'] += item['direction'][1] # item['direction'][1] * 2

    if 0 < item['x'] < 800 and 0 < item['y'] < 575:
          all_bullets_keep.append(item)

  all_bullets = all_bullets_keep

  #Fill the background (Module 5)

  window.fill(RED)

  #Redraw each target in every frame. (Module 5)

  all_targets_keep = []

  for item in all_targets:
   pygame.draw.rect(window, BLUE, (target_1.x, target_1.y, target_1.h, target_1.w))
   pygame.draw.rect(window, BLUE, (target_hbx1.x, target_hbx1.y, target_hbx1.h,target_hbx1.w), 2)
   if 0 < target_1.x < 800 and 0 < target_1.y < 575:
     all_targets_keep.append(target_1)
   if clock > target_2_threshold:
      pygame.draw.rect(window, BLUE, (target_2.x, target_2.y, target_2.h, target_2.w)) 
      pygame.draw.rect(window, BLUE, (target_hbx2.x, target_hbx2.y, target_hbx2.h,target_hbx2.w), 2)
      all_targets_keep.append(target_2)
   if clock > target_3_threshold:
      pygame.draw.rect(window, BLUE, (target_3.x, target_3.y, target_3.h, target_3.w))
      pygame.draw.rect(window, BLUE, (target_hbx3.x, target_hbx3.y, target_hbx3.h,target_hbx3.w), 2)
      all_targets_keep.append(target_3)
   if clock > target_4_threshold:
      pygame.draw.rect(window, BLUE, (target_4.x, target_4.y, target_4.h, target_4.w))
      pygame.draw.rect(window, BLUE, (target_hbx4.x, target_hbx4.y, target_hbx4.h,target_hbx4.w), 2)
      all_targets_keep.append(target_4)
   if clock > target_5_threshold:
      pygame.draw.rect(window, BLUE, (target_5.x, target_5.y, target_5.h, target_5.w))
      pygame.draw.rect(window, BLUE, (target_hbx5.x, target_hbx5.y, target_hbx5.h,target_hbx5.w), 2)
      all_targets_keep.append(target_5)
   if clock > target_6_threshold:
      pygame.draw.rect(window, BLUE, (target_6.x, target_6.y, target_6.h, target_6.w))
      pygame.draw.rect(window, BLUE, (target_hbx6.x, target_hbx6.y, target_hbx6.h,target_hbx6.w), 2)
      all_targets_keep.append(target_6)


  all_targets = all_targets_keep

  #Draw the player sprite. (Module 6)





  pygame.draw.rect(window, BLUE, (player_sprite_x, player_sprite_y, player_sprite_w, player_sprite_h))

  #Draw each item in all_bullets. (Module 7)

  for item in all_bullets:
    pygame.draw.rect(window, BLUE, (item['x']-5, item['y']-5, 10, 10))
    b_hitbox = (item['x']-10, item['y']-10, 20, 20)
    pygame.draw.rect(window, BLUE, b_hitbox, 2)

  for item in all_bullets_keep:
    if item['y']-30 < (target_hbx1.y) + (target_hbx1.h) and item['y']+30 > target_hbx1.y:
      if item['x']+10 > target_hbx1.x and item['x']-30 < (target_hbx1.x) + (target_hbx1.w):
        target_1.hit()





  pygame.display.update()
  #tick_busy_loop limits number of times the game can refresh per second. (Module 8)

  py_clock.tick_busy_loop(120)

pygame.quit()

1 Ответ

2 голосов
/ 25 марта 2020

В вашем коде есть несколько мелких ошибок. Я думаю, что цель не исчезает из-за того, что происходит со списком all_targets_keep. Похоже, что код повторно добавляет цель в список «держать», независимо от того, был ли он достигнут или нет.

Ваш подход к использованию класса для хранения всего кода Target - хорошая идея. Но весь код таргетинга по-прежнему распространяется по вашему основному l oop. Это вызывает помехи в коде и усложняет задачу.

Перемещая этот код в класс, он освобождает код от «особого случая» для каждой из целей. Цель знает все о себе и может выполнить любой тест внутри себя. Например, рисование цели на экране.

class Target:
    def __init__(self, x, y, h, w, v, threshold):
        self.x = x
        self.y = y
        self.h = h
        self.w = w
        self.v = v
        self.threshold = threshold
        self.hit = False

    def draw( self, window ):
        # body
        pygame.draw.rect( window, BLUE, ( self.x, self.y, self.w, self.h ), 0 )
        # hit-box
        pygame.draw.rect( window, BLUE, ( self.x-5, self.y-5, self.w+10, self.h+10 ), 1 )

Когда цель имеет функцию-член для рисования, весь этот код рисования уходит, превращаясь в одну простую функцию. Тогда рисунок всех целей становится:

  clock += 1
  for item in all_targets:
      if ( clock > item.threshold and not item.hit ):
          item.draw( window )

«Хитбокс» цели также является просто функцией существующих точек, нет необходимости хранить их отдельно. Таким же образом, используя PyGame rect , цель может проверить, не была ли она поражена пулей:

class Target:
    ...

def collidesWith( self, bullet_pos ):
    # hit-box is 5 pixels offset from target
    target_rect = pygame.Rect( self.x-5, self.y-5, self.w+10, self.h+10 )
    self.hit    = target_rect.collidepoint( bullet_pos )
    return self.hit

В любом случае, вы добились хорошего прогресса. Но то, что комментатор @importrandom говорит, правда: на самом деле было бы проще (в конце концов) для вас использовать классы PyGame sprite . Они уже заботятся о большом количестве кода, который вы пишете сами. Если вы не хотите, это нормально, это ваш код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...