Заставить пули перемещаться к курсору - PullRequest
0 голосов
/ 03 марта 2020

Ранее я удалил пост, потому что есть похожие посты. Я ценю это, но из-за того, что я так неопытен в pygame (я буквально начал использовать его на прошлой неделе), я не могу придумывать ни кусочки, ни хвосты кода. Кроме того, мне сложно применить свою игру. Во-первых, мне не нужно относиться к движущемуся игроку, так как он всегда будет путешествовать из заданной позиции (400, 450). Кроме того, мне предпочтительно это нужно делать, когда нажата левая кнопка мыши, но если легче использовать клавишу, то это нормально. У меня просто нет опыта использовать прошлые посты и применять их в моей программе. Спасибо. Просто чтобы прояснить, моя игра будет похожа на утиную охоту на шутеров.


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


exec = True

#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


#Instantiation of targets (Module 5)

target_1 = Target(0, 80, 60, 40, 0.5)
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)


#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


while exec:
  pygame.time.delay(1)
  for event in pygame.event.get():
    if event.type == pygame.QUIT:
      exec = False


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

  clock += 1
  target_1.x += target_1.v
  if clock > target_2_threshold:
        target_2.x += target_2.v
  if clock > target_3_threshold:
        target_3.x += target_3.v
  if clock > target_4_threshold:
        target_4.x += target_4.v
  if clock > target_5_threshold:
        target_5.x += target_5.v
  if clock > target_6_threshold:
        target_6.x += target_6.v

  #Fill the background (Module 5)

  window.fill(RED)

  #Redraw each target in every frame (Module 5)

  pygame.draw.rect(window, BLUE, (target_1.x, target_1.y, target_1.h, target_1.w))
  if clock > target_2_threshold:
      pygame.draw.rect(window, BLUE, (target_2.x, target_2.y, target_2.h, target_2.w)) 
  if clock > target_3_threshold:
      pygame.draw.rect(window, BLUE, (target_3.x, target_3.y, target_3.h, target_3.w))
  if clock > target_4_threshold:
      pygame.draw.rect(window, BLUE, (target_4.x, target_4.y, target_4.h, target_4.w))
  if clock > target_5_threshold:
      pygame.draw.rect(window, BLUE, (target_5.x, target_5.y, target_5.h, target_5.w))
  if clock > target_6_threshold:
      pygame.draw.rect(window, BLUE, (target_6.x, target_6.y, target_6.h, target_6.w))

  #Draw the player sprite (Module 6)

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

  pygame.display.update()


pygame.quit()

Ответы [ 2 ]

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

Вот несколько кратких заметок, чтобы вы указали в правильном направлении. Люди часто пишут вопросы, которые составляют « Дай мне кодекс! », поэтому очень открытые и широкие вопросы часто встречаются (совершенно справедливо) с негативом.

Итак ...

Сначала нужно схватить курсор мыши. Это достигается обработкой событий мыши в вашем основном событии -l oop:

while exec:
    #pygame.time.delay(1)   # <-- DON'T DO THIS
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exec = False
        elif event.type == pygame.MOUSEBUTTONUP:    # mouse button released
            mouse_position = pygame.mouse.get_pos()
            # TODO: handle mouse click at <mouse_position>

Примечание: мне нравится использовать MOUSEBUTTONUP вместо DOWN, потому что именно так современные графические интерфейсы имеют тенденцию работа - экранные операции активируются при выпуске, но это зависит от вас.

Теперь у вас есть позиция щелчка, как вы запускаете пулю из нижней центральной части экрана для координат мыши ?

Ну, во-первых, что такое нижний центр? Это половина ширины окна и, возможно, какой-то фактор снизу. В PyGame верхний левый угол экрана - (0, 0), а нижний левый - ( 0, window_height-1 ). Я всегда сохраняю размер окна в переменных, поэтому вычисление этой позиции легко, и это освобождает от необходимости изменения кода при изменении размера окна / экрана.

WINDOW_WIDTH  = 800
WINDOW_HEIGHT = 575

# Firing position is 98% bottom, middle of the window/screen.
start_position = ( ( WINDOW_WIDTH // 2,  int( WINDOW_HEIGHT * 0.98 ) )

Так затем, щелкнув мышью, код должен сделать перемещение пули от start_position до mouse_position. Это можно рассчитать, определив скорость x и y, которую следует применять при каждом обновлении снаряда. Очевидно, что снаряд, движущийся прямо вниз, имеет скорость ( 0, something ), а снаряд, движущийся прямо вправо, имеет скорость ( something, 0 ). Очевидно, что при движении вверх или влево что-то будет отрицательным из-за того, как PyGame выкладывает свои координаты. Дело в том, что есть отдельные компоненты изменения: x для горизонтального движения и y для вертикального.

Чтобы вычислить эту x и y скорость (технически вектор скорости) код должен определить строку от начала до конца, а затем нормализовать ее (причудливый способ сказать «разделить ее по длине»).

Я полагаю, вы знаете, формула длины строки уже, так что эта часть должна быть легкой. Это упрощает вычисления, если код временно смещает обе точки, как если бы исходная точка была на (0,0), поскольку направление остается прежним.

Как только код имеет вектор скорости (x, y), каждая анимация цикл обновления просто добавляет эти скорости компонентов к координате снаряда. Вам может потребоваться сохранить координаты в виде действительных чисел, поскольку добавление небольших чисел (например, 0.2) к целому числу имеет тенденцию отбрасывать изменения. Это потому, что some-integer + 0.2 -> some-integer .

В любом случае, посмотрите, как вы go получите эту информацию. Если проблема сохраняется ... задайте другой вопрос!

1 голос
/ 03 марта 2020

Используйте событие pygame.MOUSEBUTTONDOWN, чтобы получить щелчок мыши и ее положение.

Вы можете использовать pygame.math.Vector2() для создания вектора между мышью и игроком. И затем вы можете использовать normalize() для создания значения, которое вы можете использовать в качестве направления пули.

И сохранять в переменной или перечислять положение пули и направление пули

all_bullets = []

while exec:
  pygame.time.delay(1)
  for event in pygame.event.get():
    if event.type == pygame.QUIT:
      exec = False
    if event.type == pygame.MOUSEBUTTONDOWN:
        if event.button == 1:
            print("[shoot!] mouse position:", event.pos)
            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)

Позже вы можете использовать for -l oop для перемещения каждой пули в списке и сохранения только пуль, которые все еще находятся на экране

  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
    # keep bullet if it is still on screen
    if 0 < item['x'] < 800 and 0 < item['y'] < 575:
          all_bullets_keep.append(item)

  all_bullets = all_bullets_keep

  #print(len(all_bullets), end='\r')

Наконец, вы можете использовать for -l oop для рисования всех пуль

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

По-прежнему необходимо проверять столкновение с целями, но было бы проще, если бы вы держали цели в списке и использовали pygame.Rect () `, чтобы сохранить положение и размер, потому что у него есть специальные методы. проверить столкновения.

Так что теперь у вас есть работа, чтобы использовать списки с тегами и pygame.Rect()


import pygame



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)


exec = True

#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


#Instantiation of targets (Module 5)

target_1 = Target(0, 80, 60, 40, 0.5)
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)


#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 = []

while exec:
  pygame.time.delay(1)
  for event in pygame.event.get():
    if event.type == pygame.QUIT:
      exec = False
    if event.type == pygame.MOUSEBUTTONDOWN:
        if event.button == 1:
            print("[shoot!] mouse position:", event.pos)
            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)   

  clock += 1
  target_1.x += target_1.v
  if clock > target_2_threshold:
        target_2.x += target_2.v
  if clock > target_3_threshold:
        target_3.x += target_3.v
  if clock > target_4_threshold:
        target_4.x += target_4.v
  if clock > target_5_threshold:
        target_5.x += target_5.v
  if clock > target_6_threshold:
        target_6.x += target_6.v

  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
    # keep bullet if it is still on screen
    if 0 < item['x'] < 800 and 0 < item['y'] < 575:
          all_bullets_keep.append(item)

  all_bullets = all_bullets_keep
  #print(len(all_bullets), end='\r')

  #Fill the background (Module 5)

  window.fill(RED)

  #Redraw each target in every frame (Module 5)

  pygame.draw.rect(window, BLUE, (target_1.x, target_1.y, target_1.h, target_1.w))
  if clock > target_2_threshold:
      pygame.draw.rect(window, BLUE, (target_2.x, target_2.y, target_2.h, target_2.w)) 
  if clock > target_3_threshold:
      pygame.draw.rect(window, BLUE, (target_3.x, target_3.y, target_3.h, target_3.w))
  if clock > target_4_threshold:
      pygame.draw.rect(window, BLUE, (target_4.x, target_4.y, target_4.h, target_4.w))
  if clock > target_5_threshold:
      pygame.draw.rect(window, BLUE, (target_5.x, target_5.y, target_5.h, target_5.w))
  if clock > target_6_threshold:
      pygame.draw.rect(window, BLUE, (target_6.x, target_6.y, target_6.h, target_6.w))

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

  #Draw the player sprite (Module 6)

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

  pygame.display.update()


pygame.quit()
...