简体   繁体   中英

How to keep a ball moving like in pong?

I'm creating a tennis game, similar to pong but will be much more similar to real tennis (ie ability to control the direction and type of your shot). I think I've got the collision detection with the ball and the player figured out, but when the player collides with the ball it moves a few pixels then stops. I need it to keep going like in pong. Not sure if the problem is with the collision detection or just with something else in the code.

import pygame

pygame.init()

# Define some colors
BLACK = (0, 0, 0)
OUT = (193, 58, 34)
COURT = (69, 150, 81)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
SKIN = (232, 214, 162)

ballspeed = 2

# Create the screen
windowsize = (700, 500)
screen = pygame.display.set_mode(windowsize)
pygame.display.set_caption('Tennis')

# Player Sprites
class Player(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("Robert_tennis.png")
        self.rect = self.image.get_rect()
        self.rect.center = (360, 480)
        self.speedx = 0
        self.speedy = 0

    def update(self):
        self.speedx = 0
        self.speedy = 0
        keystate = pygame.key.get_pressed()
        if keystate[pygame.K_LEFT]:
            self.speedx = -4
        if keystate[pygame.K_RIGHT]:
            self.speedx = 4
        self.rect.x += self.speedx
        if self.rect.right > 700:
            self.rect.right = 700
        if self.rect.right < 0:
            self.rect.left = 0
        if keystate[pygame.K_UP]:
            self.speedy = -5
        if keystate[pygame.K_DOWN]:
            self.speedy = 3
        self.rect.y += self.speedy
        if self.rect.y < 235:
            self.rect.y = 235
        if self.rect.y < 0:
            self.rect.y = 0

class Ball(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("tennisball.png")
        self.rect = self.image.get_rect()
        self.rect.center = (360, 325)

    def update(self):
        if tennisball.rect.colliderect(robert):
            self.rect.y -= 2

#Add myself
all_sprites = pygame.sprite.Group()
robert = Player()
tennisball = Ball()
all_sprites.add(robert)
all_sprites.add(tennisball)

carryOn = True
clock = pygame.time.Clock()

while carryOn:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            carryOn = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_x:
                carryOn = False

    all_sprites.update()

    # Fill the screen with a sky color
    screen.fill(OUT)

    # Draw the court
    pygame.draw.rect(screen, COURT, [175, 0, 350, 500])
    pygame.draw.line(screen, WHITE, (170,500), (170,0), 10)
    pygame.draw.line(screen, WHITE, (520,500), (520,0), 10)
    pygame.draw.line(screen, WHITE, (170,130), (520,130), 10)
    pygame.draw.line(screen, WHITE, (170,370), (520,370), 10)
    pygame.draw.line(screen, WHITE, (340,130), (340,370), 10)
    pygame.draw.line(screen, BLACK, (170,250), (520,250), 10)

    # Update
    all_sprites.draw(screen)
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

When you do

def update(self): if tennisball.rect.colliderect(robert): self.rect.y -= 2

then the ball moves only once. In that "moment" when the player hits the ball and the condition is fulfilled. After the ball has moved, the condition is not fulfilled any more and the ball stops.

When the racket hits the ball then you've to change the speed of the ball rather than its position.
Add attributes which store the speed of the ball ( .speedx , .speedy ). Initialize the attributes by 0. Continuously change the position of the ball by it speed in the method .update() . When the racket hits the ball then change the speed:

eg

class Ball(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("tennisball.png")
        self.rect = self.image.get_rect()
        self.rect.center = (360, 325)
        self.speedx = 0
        self.speedy = 0

    def update(self):
        if tennisball.rect.colliderect(robert):
            self.speedy = -2
        self.rect = self.rect.move(self.speedx, self.speedy)

Note, if there is a player at the other side of the court, which hits the ball, then the speed is changed again. The speed can also have an sideward component for a diagonal movement.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM