问题
I'm fairly new to programming, game programming especially. I'm trying to make pong using pygame, but have run into a slight issue. Essentially, the ball hits a paddle, stops, and then keeps going once the paddle is out of the way. Obviously I want the ball to bounce back, but I can't figure out why it won't, when I've coded (what I thought was) the appropriate logic for ball-paddle collisions. Here's my code:
# importing stuff
import sys, pygame
from pygame.locals import *
# starting pygame
pygame.init()
# defining basic colours
white = (255, 255, 255)
black = (0, 0, 0)
# set up the clock
clock = pygame.time.Clock()
# text and such
tFont = pygame.font.SysFont("monospace", 15)
# setting window res and setting display
winX, winY = 600, 300
window = pygame.display.set_mode((winX, winY))
# setting the speed for on screen stuff
playSpeed = 5 # player speed (p1 and p2)
# counts points for each player
# 1 2
points = [0, 0]
# tallies number of times FPS is counted and added to toal amount
fpsCount = 0
fpsTotal = 0
class Ball(object):
def __init__(self, speed):
# set default ball position in screen centre
self.ballX = winX / 2
self.ballY = winY / 2
self.ballSpeed = speed
def move(self):
if points[0] > points[1]: # if p1 has more points than p2
self.ballX -= self.ballSpeed # ball goes to p1's side
elif points[0] < points[1]: # only other condition could be p2 having more points
self.ballX += self.ballSpeed # ball goes to p2's side
elif points[0] == points[1]: # if points are equal
self.ballX -= self.ballSpeed # favour player 1 (change later)
pygame.draw.circle(window, black, (self.ballX, self.ballY), 3)
def collide(self, paddle): # unsure if 'paddle' necessary
# if ball hits top of paddle, bounce to top
# if hits bottom, bounce to bottom
# if ball hits midsection, bounce straight (middle could be about 10px?)
if paddle == playerOne:
self.ballX
self.ballX += self.ballSpeed
class Paddle(object):
# set the player number (1/2) and if it's an AI or real player
def __init__(self, player, aiornot):
if player == 1 and aiornot == False:
self.coords = [[40, 130], [40, 160]]
elif player == 2 and aiornot == False:
self.coords = [[560, 130], [560, 160]]
self.movement = 'stop' # sets default movement
def move(self):
if self.movement == 'down' and self.coords[1][1] < 300:
self.moveDown()
elif self.movement == 'up' and self.coords[0][1] > 0:
self.moveUp()
elif self.movement == 'stop':
self.stop()
# draw the paddle in new position
pygame.draw.line(window, black, self.coords[0], self.coords[1], 10)
# movement functions, for direction and such
def moveDown(self):
self.coords[0][1] += playSpeed
self.coords[1][1] += playSpeed
def moveUp(self):
self.coords[0][1] -= playSpeed
self.coords[1][1] -= playSpeed
def stop(self):
self.coords[0][1] = self.coords[0][1]
self.coords[1][1] = self.coords[1][1]
ball = Ball(playSpeed)
playerOne = Paddle(1, False)
playerTwo = Paddle(2, False)
# main loop
while True:
# event handling for exit
for event in pygame.event.get():
if event.type == QUIT:
# print the average FPS
print round(fpsTotal / fpsCount, 2), "fps (avg)"
pygame.quit()
sys.exit()
# setting direction upon arrow key press
elif event.type == KEYDOWN:
if event.key == K_DOWN:
playerOne.movement = 'down'
elif event.key == K_UP:
playerOne.movement = 'up'
elif event.key == K_s:
playerTwo.movement = 'down'
elif event.key == K_w:
playerTwo.movement = 'up'
# when the key is released, stop moving
elif event.type == KEYUP:
if event.key == K_DOWN or event.key == K_UP:
playerOne.movement = 'stop'
elif event.key == K_s or event.key == K_w:
playerTwo.movement = 'stop'
print "player1:", playerOne.coords
print "player2:", playerTwo.coords
# this is a mess... if the balls x coords = the paddles x coords, and the balls y
# coord is somewhere between the start and end point of the paddle, then do the balls
# collision function on the paddle
if ball.ballX >= playerOne.coords[0][0] and ball.ballX <= playerOne.coords[1][0]: # or ball.ballX == 40
if ball.ballY >= playerOne.coords[0][1] and ball.ballY <= playerOne.coords[1][1]:
ball.collide(playerOne)
print ball.ballX, ball.ballY
# fill the window
window.fill(white)
# redraw the bat with new position
playerOne.move()
playerTwo.move()
# redraw the ball with new position
ball.move()
# set FPS to 60
clock.tick(60)
# for working out average FPS
fpsCount += 1
fpsTotal += clock.get_fps()
# set window title
pygame.display.set_caption("Long Pong")
# render FPS to text, display text
text = tFont.render(str(round(clock.get_fps(), 2)), 8, black)
window.blit(text, (545, 5))
# update display
pygame.display.update()
And also a pastebin here if it's easier to look at/copy.
I appreciate any help with this, I've been able to work out any other problem on my own, but I can't tell what I'm missing here.
回答1:
I hope the below code helps. Although my program was a bit different because every time the ball hit the paddle we had to generate a new ball.
import random
from livewires import games, color
games.init(screen_width = 640, screen_height = 480, fps = 50)
class Ball(games.Sprite):
quit_label = games.Text(value = "Press Q to Quit", size = 25, color = color.white, top = 5, right = 130,
is_collideable = False)
games.screen.add(quit_label)
def update(self):
if self.right > games.screen.width:
self.dx = -self.dx
if self.left < 0:
self.game_over()
if self.bottom > games.screen.height or self.top < 0:
self.dy = -self.dy
#pressing 'q' quits the game
if games.keyboard.is_pressed(games.K_q):
self.game_over()
def bounce(self):
self.dx = -self.dx
def game_over(self):
""" End the game. """
end_message = games.Message(value = "Game Over",
size = 90,
color = color.red,
x = games.screen.width/2,
y = games.screen.height/2,
lifetime = 3 * games.screen.fps,
after_death = games.screen.quit,
is_collideable = False)
games.screen.add(end_message)
self.destroy()
class Paddle(games.Sprite):
image = games.load_image("paddle.bmp")
score = games.Text(value = 0, size = 25, color = color.white, top = 15,
right = games.screen.width - 10, is_collideable = False)
games.screen.add(score)
def __init__(self):
super(Paddle, self).__init__(image = Paddle.image, x = games.mouse.x, bottom = games.screen.height)
def update(self):
""" Move to mouse y position. """
self.y = games.mouse.y
if self.left > 0:
self.left = 10
if self.right > games.screen.height:
self.right = games.screen.height
self.check_catch()
def check_catch(self):
for ball in self.overlapping_sprites:
Paddle.score.value += 1
ball_image2 = games.load_image("ball.bmp")
ball2 = Ball(image = ball_image2,
x = games.screen.width/2,
y = games.screen.height/2,
dx = 1,
dy = 1)
games.screen.add(ball2)
ball.bounce()
def main():
wall_image = games.load_image("background.bmp", transparent = False)
games.screen.background = wall_image
ball_image = games.load_image("ball.bmp")
the_ball = Ball(image = ball_image,
x = games.screen.width/2,
y = games.screen.height/2,
dx = 1,
dy = 1)
games.screen.add(the_ball)
the_paddle = Paddle()
games.screen.add(the_paddle)
games.mouse.is_visible = False
games.screen.mainloop()
# kick it off!
main()
来源:https://stackoverflow.com/questions/25223760/unable-to-fix-broken-ball-movement-in-pygame-pong