2017-12-21 4 views
0

나는 파이썬으로 ping pong 게임을 프로그래밍하려고하고 있는데, 패드를 옆으로 튀게 할 수 있습니다. 그러나 나는 공을 패드의 상단과 하단에서 튀게 만들 수 없습니다. 현재는 왼쪽 패드 (pad1) 만하고 있습니다. 여기 내 코드는 다음과 같습니다.Ping Pong 파이 게임과 패드의 충돌

import sys, pygame, random, math 
pygame.init() 

width, height = 1200, 675 

screen = pygame.display.set_mode((width, height), pygame.RESIZABLE) 
clock = pygame.time.Clock() 


FPS = 120 

xmb1 = False 
xmf1 = False 
ymb1 = False 
ymf1 = False 

xmb2 = False 
xmf2 = False 
ymb2 = False 
ymf2 = False 

squareh = 275 
squarew = 35 
squares = 3 

x1 = 100 
y1 = (height/2) - (squareh/2) 

x2 = width - 100 - squarew 
y2 = (height/2) - (squareh/2) 

BLACK = (0,0,0) 
WHITE = (255,255,255) 

font = pygame.font.SysFont("arial", 30) 

text = font.render("Press Space to start", True, WHITE) 
text3 = font.render("3", True, WHITE) 
text2 = font.render("2", True, WHITE) 
text1 = font.render("1", True, WHITE) 
startt = font.render("Start!", True, WHITE) 

text3b = False 
text2b = False 
text1b = False 
starttb = False 

start = False 
startballmove = False 

bx = width/2 
by = height/2 
br = 40 
bms = 6 
bxm = random.randint(-bms, bms) 
bym = random.randint(-bms, bms) 

btc = by 
blc = bx 
bbc = by + br + br 
brc = bx + br + br 

circle=pygame.Surface((br * 2, br * 2)) 
circle.fill((0, 0, 0)) 
pygame.draw.circle(circle, WHITE , (br, br), br, 0) 
circle.set_colorkey((0, 0, 0)) 

pad1 = pygame.Rect(x1, y1, squarew, squareh) 
pad2 = pygame.Rect(x2, y2, squarew, squareh) 

while 1: 
    if start and not text1b and not text2b and not text3b and not starttb and not startballmove: 
     text3b = True 
     pygame.time.set_timer(pygame.USEREVENT, 1000) 
    for event in pygame.event.get(): 
     if event.type == pygame.QUIT: 
      pygame.display.quit() 
      sys.exit() 
     elif event.type == pygame.KEYDOWN: 
      # pad 2 check if key is down 
      if event.key == pygame.K_UP: 
       ymb2 = True 
      if event.key == pygame.K_DOWN: 
       ymf2 = True 
      # pad 1 check if key is down 
      if event.key == pygame.K_w: 
       ymb1 = True 
      if event.key == pygame.K_s: 
       ymf1 = True 
      if event.key == pygame.K_SPACE: 
       start = True 
     elif event.type == pygame.KEYUP: 
      #pad 2 check if key goes up 
      if event.key == pygame.K_UP: 
       ymb2 = False 
      if event.key == pygame.K_DOWN: 
       ymf2 = False 
      # pad 1 check if key goes up 
      if event.key == pygame.K_w: 
       ymb1 = False 
      if event.key == pygame.K_s: 
       ymf1 = False 
     # check if window has been resized 
     if event.type == pygame.VIDEORESIZE: 
      width = event.dict['size'][0] 
      height = event.dict['size'][1] 
      screen = pygame.display.set_mode((width, height), pygame.RESIZABLE) 
     if event.type == pygame.USEREVENT: 
      # check if start should be hidden 
      if starttb: 
       starttb = False 
       startballmove = True 
      # check if start should be showed 
      if text1b and not text2b and not text3b: 
       text1b = False 
       text2b = False 
       text3b = False 
       starttb = True 
      # check if 1 should be showed 
      if text2b and not text3b and not text1b: 
       text3b = False 
       text2b = False 
       text1b = True 
      # check if 2 should be showed 
      if text3b and not text2b and not text1b: 
       text3b = False 
       text2b = True 
       text1b = False 

    # check if pad 1 is out of bounds and move it  
    if ymb1 and not (y1 <= 0): y1 -= squares 
    if ymf1 and not (y1 + squareh >= height): y1 += squares 
    if y1 > (height - squareh) + 1: y1 -= squares 

    # check if pad 2 is out of bounds and move it  
    if ymb2 and not (y2 <= 0): y2 -= squares 
    if ymf2 and not (y2 + squareh >= height): y2 += squares 
    if y2 > (height - squareh) + 1: y2 -= squares 

    # put pads in center if game has not started 
    if not start: 
     # pad 1 
     x1 = 75 
     y1 = (height/2) - (squareh/2) 
     # pad 2 
     x2 = width - 75 - squarew 
     y2 = (height/2) - (squareh/2) 
     #ball 
     bx = width/2 - br 
     by = height/2 - br 

    # put pads in center in x if game has started 
    else: 
     # pad 1 
     x1 = 75 
     # pad 2 
     x2 = width - 75 - squarew 
    # if ball has not started moving center it 
    if not startballmove: 
     bx = width/2 - br 
     by = height/2 - br 
    # check if movement variables are 0 
    while bxm == 0 or bym == 0: 
     if bxm == 0: 
      bxm = random.randint(-6, 6) 
     if bym == 0: 
      bym = random.randint(-6, 6) 

    screen.fill(BLACK) 
    # draw starting text if game has not started 
    if not start: 
     screen.blit(text,((width/2) - text.get_width() // 2, (height/4) - text.get_height() // 2)) 
    # put 3 on screen 
    if start and text3b: 
     screen.blit(text3,((width/2) - 15, (height/4) - (text.get_height()/2))) 
    # put 2 on screen 
    if start and text2b: 
     screen.blit(text2,((width/2) - 15, (height/4) - (text.get_height()/2))) 
    # put 1 on screen 
    if start and text1b: 
     screen.blit(text1,((width/2) - 15, (height/4) - (text.get_height()/2))) 
    # put start on screen 
    if start and starttb: 
     screen.blit(startt,((width/2) - (text.get_width()/8), (height/4) - (text.get_height()/2))) 
    # check if ball is out of bounds 
    btc = by 
    blc = bx 
    bbc = by + br + br 
    brc = bx + br + br 
    if start and startballmove: 
     # screen 
     if btc <= 0: 
      bym = bym * -1 
      print("top side") 
     if bbc >= height: 
      bym = bym * -1 
      print("bottom side") 
     if blc <= 0: 
      bxm = bxm * -1 
      print("left side") 
     if brc >= width: 
      bxm = bxm * -1 
      print("right side") 
     # left pad 
     pad1 = pygame.Rect(x1, y1, squarew, squareh) 
     if pad1.collidepoint(int(bx), int(by)): 
      bxm = bxm * -1 
      bx += abs(bxm) 
      print("Collision") 
    # move ball 
    if start and startballmove: 
     bx += bxm 
     by += bym 
    # draw circle if game start 
    if start: 
     screen.blit(circle, (int(bx), int(by))) 
    # draw pad 1 
    pad1 = pygame.Rect(x1, y1, squarew, squareh) 
    pygame.draw.rect(screen, WHITE, pad1, 0) 
    # draw pad 2 
    pad2 = pygame.Rect(x2, y2, squarew, squareh) 
    pygame.draw.rect(screen, WHITE, pad2, 0) 

    pygame.display.flip() 
    clock.tick(FPS) 

누구에게이 방법을 알고 있습니까? 나는 최근에 파이썬과 파이 게임으로 프로그래밍하는 법을 배웠다.

+0

[pygame.Rect()] (http://pygame.org/docs/ref/rect.html) 점 (. 즉, 마우스 클릭) 또는 다른 RECT와의 충돌을 확인하는 방법이있다. 'ball_rect.colliderect (paddle_rect)' – furas

+0

당신은'blit (text, text_rect)'blit에'Rect'을 사용할 수 있습니다. 텍스트를 화면 가운데에 놓으려면'text_rect.center = screen.get_rect(). center' 명령을 한 번만 쓸 수 있습니다. 그러면이 추악한'(width/2) - text.get_width()를 반복해서 계산할 필요가 없습니다.) // 2, (높이/4) - text.get_height() // 2)' – furas

답변

1

두 단계로 이동 및 체킹 충돌을 분할해야합니다. 먼저 X로만 이동하면 전방 충돌을 인식 할 수 있습니다. 나중에 Y로 이동하면 측면 충돌을 인식 할 수 있습니다.

코드가 너무 복잡하여 많은 변경이 필요할 수 있습니다. 변수를보다 잘 읽을 수 있도록 코드를 구성하고 더 나은 이름을 사용해야합니다.

elif을 사용하고 if을 중첩하면 더 깨끗합니다. 즉, -

import sys 
import pygame 
import random 
import math 

# --- constants --- (UPPER_CASE_NAMES) 

BLACK = (0, 0, 0) 
WHITE = (255, 255, 255) 

FPS = 60 

SQUARE_HEIGHT = 275 
SQUARE_WIDTH = 35 
SQUARE_SPEED = 3 

BALL_R = 40 

# --- main --- 

window_width = 1200 
window_height = 675 

# - init - 

pygame.init() 

screen = pygame.display.set_mode((window_width, window_height), pygame.RESIZABLE) 
screen_rect = screen.get_rect() 

# - text - 

font = pygame.font.SysFont("arial", 30) 

# - text - press space - 

text_press_space = font.render("Press Space to start", True, WHITE) 
text_press_space_rect = text_press_space.get_rect() 
text_press_space_rect.centerx = screen_rect.centerx 
text_press_space_rect.centery = screen_rect.height // 4 

# - text - count down - 

text_1 = font.render("1", True, WHITE) 
text_1_rect = text_1.get_rect() 
text_1_rect.centerx = screen_rect.centerx 
text_1_rect.centery = screen_rect.height // 4 


text_2 = font.render("2", True, WHITE) 
text_2_rect = text_2.get_rect() 
text_2_rect.centerx = screen_rect.centerx 
text_2_rect.centery = screen_rect.height // 4 

text_3 = font.render("3", True, WHITE) 
text_3_rect = text_3.get_rect() 
text_3_rect.centerx = screen_rect.centerx 
text_3_rect.centery = screen_rect.height // 4 

text_start = font.render("Start!", True, WHITE) 
text_start_rect = text_start.get_rect() 
text_start_rect.centerx = screen_rect.centerx 
text_start_rect.centery = screen_rect.height // 4 

display_text_3 = False 
display_text_2 = False 
display_text_1 = False 
display_text_start = False 

# - ball - 

ball = pygame.Surface((BALL_R * 2, BALL_R * 2)) 
# circle.fill(BLACK) # not need it because surface is black as default 
ball.set_colorkey(BLACK) 
pygame.draw.circle(ball, WHITE , (BALL_R, BALL_R), BALL_R, 0) 
ball_rect = ball.get_rect() 
ball_rect.center = screen_rect.center 

ball_speed = 6 

ball_speed_x = ball_speed * random.choice([1, -1]) 
ball_speed_y = ball_speed * random.choice([1, -1]) 

ball_move = False 

# - pads - 

pad1_rect = pygame.Rect(0, 0, SQUARE_WIDTH, SQUARE_HEIGHT) 
pad1_rect.left = 100 
pad1_rect.centery = screen_rect.centery 
pad1_move_up = False 
pad1_move_down = False 

pad2_rect = pygame.Rect(0, 0, SQUARE_WIDTH, SQUARE_HEIGHT) 
pad2_rect.right = screen_rect.right - 100 
pad2_rect.centery = screen_rect.centery 
pad2_move_up = False 
pad2_move_down = False 

# --- mainloop --- 

play_start = False 

clock = pygame.time.Clock() 

while True: 

    for event in pygame.event.get(): 
     if event.type == pygame.QUIT: 
      pygame.quit() 
      sys.exit() 
     elif event.type == pygame.KEYDOWN: 
      # pad 2 check if key is down 
      if event.key == pygame.K_UP: 
       pad2_move_up = True 
      elif event.key == pygame.K_DOWN: 
       pad2_move_down = True 
      # pad 1 check if key is down 
      elif event.key == pygame.K_w: 
       pad1_move_up = True 
      elif event.key == pygame.K_s: 
       pad1_move_down = True 

      elif event.key == pygame.K_SPACE: 
       if not play_start: 
        play_start = True 
        pygame.time.set_timer(pygame.USEREVENT, 1000) 
        display_text_3 = True 

     elif event.type == pygame.KEYUP: 
      #pad 2 check if key goes up 
      if event.key == pygame.K_UP: 
       pad2_move_up = False 
      elif event.key == pygame.K_DOWN: 
       pad2_move_down = False 
      # pad 1 check if key goes up 
      elif event.key == pygame.K_w: 
       pad1_move_up = False 
      elif event.key == pygame.K_s: 
       pad1_move_down = False 

     # check if window has been resized 
     if event.type == pygame.VIDEORESIZE: 
      window_width = event.dict['size'][0] 
      window_height = event.dict['size'][1] 
      screen = pygame.display.set_mode((window_width, window_height), pygame.RESIZABLE) 
      screen_rect = screen.get_rect() 

     if event.type == pygame.USEREVENT: 
      if display_text_3: 
       display_text_3 = False 
       display_text_2 = True 
      elif display_text_2: 
       display_text_2 = False 
       display_text_1 = True 
      elif display_text_1: 
       display_text_1 = False 
       display_text_start = True 
      elif display_text_start: 
       display_text_start = False 
       ball_move = True 

    # - moves (without draws) - 

    # move paddle 1 

    if pad1_move_up and pad1_rect.top > 0: # > screen_rect.top: 
     pad1_rect.y -= SQUARE_SPEED 
     if pad1_rect.top < 0: 
      pad1_rect.top = 0 

    if pad1_move_down and pad1_rect.bottom < screen_rect.bottom: 
     pad1_rect.y += SQUARE_SPEED 
     if pad1_rect.bottom > screen_rect.bottom: 
      pad1_rect.bottom = screen_rect.bottom 

    # move paddle 2 

    if pad2_move_up and pad2_rect.top > 0: # > screen_rect.top: 
     pad2_rect.y -= SQUARE_SPEED 
     if pad2_rect.top < 0: 
      pad2_rect.top = 0 

    if pad2_move_down and pad2_rect.bottom < screen_rect.bottom: 
     pad2_rect.y += SQUARE_SPEED 
     if pad2_rect.bottom > screen_rect.bottom: 
      pad2_rect.bottom = screen_rect.bottom 

    # check if ball is out of bounds 
    if play_start: 

     # move ball 
     if ball_move: 
      ball_rect.x += ball_speed_x 

      # check FRONT collision with pads 

      if pad1_rect.colliderect(ball_rect): 
       #if 
       ball_rect.left = pad1_rect.right 
       ball_speed_x = -ball_speed_x 
       print("Front collision right pad") 

      if pad2_rect.colliderect(ball_rect): 
       ball_rect.right = pad2_rect.left 
       ball_speed_x = -ball_speed_x 
       print("Front collision left pad") 

      ball_rect.y += ball_speed_y 

      # check SIDE collision with pads 

      if pad1_rect.colliderect(ball_rect): 
       # move from top 
       if ball_speed_y > 0: 
        ball_rect.bottom = pad1_rect.top 
        print("Top collision right pad") 

       # move from bottom 
       else: # elif ball_speed_y < 0: 
        ball_rect.top = pad1_rect.bottom 
        print("Bottom collision right pad") 
       # change both or only Y (depends on what effect you need) 
       ball_speed_x = -ball_speed_x 
       ball_speed_y = -ball_speed_y 

      if pad2_rect.colliderect(ball_rect): 
       # move from top 
       if ball_speed_y > 0: 
        ball_rect.bottom = pad2_rect.top 
        print("Top collision left pad") 

       # move from bottom 
       else: # if ball_speed_y < 0: 
        ball_rect.top = pad2_rect.bottom 
        print("Bottom collision left pad") 
       # change both or only Y (depends on what effect you need) 
       ball_speed_x = -ball_speed_x 
       ball_speed_y = -ball_speed_y 

      # check collision with border 

      if ball_rect.left <= 0: # <= screen_rect.left: 
       ball_speed_x = -ball_speed_x 
       print("left side") 
       print("point for left player") 
       # move ball to center 
       ball_rect.center = screen_rect.center 
       ball_speed_x = ball_speed * random.choice([1, -1]) 
       ball_speed_y = ball_speed * random.choice([1, -1]) 
      if ball_rect.right >= screen_rect.right: 
       ball_speed_x = -ball_speed_x 
       print("right side") 
       print("point for right player") 
       # move ball to center 
       ball_rect.center = screen_rect.center 
       ball_speed_x = ball_speed * random.choice([1, -1]) 
       ball_speed_y = ball_speed * random.choice([1, -1]) 


      if ball_rect.top <= 0: # <= screen_rect.top: 
       ball_speed_y = -ball_speed_y 
       print("top side") 
      if ball_rect.bottom >= screen_rect.bottom: 
       ball_speed_y = -ball_speed_y 
       print("bottom side") 


    # - draws (without moves) - 

    screen.fill(BLACK) 

    if not play_start: 
     screen.blit(text_press_space, text_press_space_rect) 
    else: # if play_start: 
     if display_text_3: 
      screen.blit(text_3, text_3_rect) 
     if display_text_2: 
      screen.blit(text_2, text_2_rect) 
     if display_text_1: 
      screen.blit(text_1, text_1_rect) 
     if display_text_start: 
      screen.blit(text_start, text_start_rect) 

     screen.blit(ball, ball_rect) 

    # draw pads 
    pygame.draw.rect(screen, WHITE, pad1_rect, 0) 
    pygame.draw.rect(screen, WHITE, pad2_rect, 0) 

    pygame.display.flip() 

    clock.tick(FPS) 

# --- end --- 

pygame.quit() 
관련 문제