我正在尝试在python中编写一个乒乓球比赛,我能够让球从球垫侧面反弹。但是,我无法让球从垫的顶部和底部反弹。我目前只做左边的垫(pad1)。这是我的代码:
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)
有谁知道怎么做?我最近才学会用python和pygame编程。
答案 0 :(得分:2)
你必须在两个步骤上分开移动和cheking碰撞。首先仅在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()