2017-12-21 8 views
0

Ich versuche ein Ping-Pong-Spiel in Python zu programmieren, und ich bin in der Lage, den Ball von der Seite des Pads abprallen zu lassen. Allerdings kann ich den Ball nicht von der Ober- und Unterseite des Pads abprallen lassen. Ich mache momentan nur das linke Pad (Pad1). Hier ist mein Code:Ping Pong Pygame Kollision mit der Seite des Pad

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) 

Weiß jemand, wie man das macht? Ich habe erst kürzlich gelernt, in Python und Pygame zu programmieren.

+0

[pygame.Rect()] (http://pygame.org/docs/ref/rect.html) hat Methoden Kollision mit Punkt zu überprüfen (dh per Mausklick.) Oder anderen rect - dh. 'ball_rect.colliderect (paddle_rect)' – furas

+0

können Sie 'Rect' auch zum Blit verwenden -' blit (text, text_rect) '. Um Text in die Mitte des Bildschirms zu legen, können Sie nur einmal 'text_rect.center = screen.get_rect(). Center' ausführen und dann müssen Sie dieses hässliche '(width/2) - text.get_width () // 2, (height/4) - text.get_height() // 2) ' – furas

Antwort

1

Sie müssen Move und Cheking Kollision in zwei Schritten teilen. Bewegen Sie sich erst in X und dann können Sie eine Frontalkollision erkennen. Später bewegen Sie sich in Y und Sie können Seitenkollision erkennen.

Ihr Code ist sehr unordentlich, so dass es viele Änderungen erfordern kann. Sie sollten Code organisieren und bessere Namen für Variablen verwenden, um sie lesbarer zu machen.

Und Sie könnten elif und verschachtelte if verwenden, so wird es sauberer sein.

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