Оценка не меняется в python Pygame - PullRequest
2 голосов
/ 20 марта 2020

Я пытаюсь сделать игру в понг, но счет не меняется, когда мяч уходит с экрана. Другая вещь, которая не совсем правильна, состоит в том, что иногда мяч скользит по веслу, а затем go за пределы экрана, вместо того, чтобы отскакивать от весла. Могу ли я получить помощь по этим проблемам? (в основном первый) Вот мой код:

import pygame as pg
import random
from os import path

img_dir = path.join(path.dirname(__file__), 'img')
snd_dir = path.join(path.dirname(__file__), 'snd')
WIDTH = 1280
HEIGHT = 690
FPS = 60
# define colors 
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (0, 255, 255)
OPPONENT_SPEED = 2.4
# initialize PyGame and create window 
pg.init()
pg.mixer.init()
screen = pg.display.set_mode((WIDTH, HEIGHT))
pg.display.set_caption('PONG!')
clock = pg.time.Clock()
pong_ball_x = [-3, 3]
pong_ball_y = [-3, 3]
font_name = pg.font.match_font('arial')


def draw_text(surf, text, size, x, y):
    font = pg.font.Font(font_name, size)
    text_surface = font.render(text, True, WHITE)
    text_rect = text_surface.get_rect()
    text_rect.midtop = (x, y)
    surf.blit(text_surface, text_rect)


class Player(pg.sprite.Sprite):
    def __init__(self):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.Surface((5, 100))
        self.image.fill(WHITE)
        self.rect = self.image.get_rect()
        self.rect.x = 10
        self.rect.y = HEIGHT / 2
        self.speedy = 0

    def update(self):
        self.speedy = 0
        keys = pg.key.get_pressed()
        if keys[pg.K_s]:
            self.speedy = 5
        if keys[pg.K_w]:
            self.speedy = -5
        self.rect.y += self.speedy
        if self.rect.bottom >= HEIGHT:
            self.rect.bottom = HEIGHT
        if self.rect.top <= 0:
            self.rect.top = 0


class Player2(pg.sprite.Sprite):
    def __init__(self):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.Surface((5, 100))
        self.image.fill(WHITE)
        self.rect = self.image.get_rect()
        self.rect.x = WIDTH - 15
        self.rect.y = HEIGHT / 2
        self.speedy = 0

    def update(self):
        self.speedy = 0
        keys = pg.key.get_pressed()
        if keys[pg.K_DOWN]:
            self.speedy = 5
        if keys[pg.K_UP]:
            self.speedy = -5
        self.rect.y += self.speedy
        if self.rect.bottom >= HEIGHT:
            self.rect.bottom = HEIGHT
        if self.rect.top <= 0:
            self.rect.top = 0


class Opponent(pg.sprite.Sprite):
    def __init__(self):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.Surface((5, 100))
        self.image.fill(WHITE)
        self.rect = self.image.get_rect()
        self.rect.x = WIDTH - 10
        self.rect.y = HEIGHT / 2
        self.speedy = 0

    def update(self):
        if self.rect.bottom >= HEIGHT:
            self.rect.bottom = HEIGHT
        if self.rect.top <= 0:
            self.rect.top = 0

    def opponent_ai(self):
        if self.rect.top < pong_ball.rect.y:
            self.rect.top += OPPONENT_SPEED
        if self.rect.bottom > pong_ball.rect.y:
            self.rect.bottom -= OPPONENT_SPEED


class PongBall(pg.sprite.Sprite):
    def __init__(self):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.Surface((30, 30))
        self.image.fill(WHITE)
        self.rect = self.image.get_rect()
        self.rect.x = WIDTH / 2 - 12.5
        self.rect.y = HEIGHT / 2 - 12.5
        self.speedx = random.choice(pong_ball_x)
        self.speedy = random.choice(pong_ball_y)

    def update(self):
        self.rect.x += self.speedx
        self.rect.y += self.speedy
        if self.rect.top <= 0:
            self.speedy = -self.speedy
        if self.rect.bottom >= HEIGHT:
            self.speedy = -self.speedy
        if self.rect.right <= 0:
            self.rect.x = WIDTH / 2 - 15
            self.rect.y = HEIGHT / 2 - 15
        if self.rect.left >= WIDTH:
            self.rect.x = WIDTH / 2 - 15
            self.rect.y = HEIGHT / 2 - 15

    def bounce(self):
        self.speedx = -self.speedx
    # load all game graphics 


# ball_img = pg.image.load(path.join(img_dir, "white_circle2.png")).convert() 
all_sprites = pg.sprite.Group()
pong_ball_group = pg.sprite.Group()
player = Player()
player2 = Player2()
opponent = Opponent()
pong_ball = PongBall()
all_sprites.add(player)
all_sprites.add(player2)
pong_ball_group.add(pong_ball)
score = 0
score2 = 0
# Game loop 
running = True
while running:
    # process input (events) 
    for event in pg.event.get():
        # check for closing window 
        if event.type == pg.QUIT:
            running = False
    if pong_ball.rect.left == WIDTH - 12.5:
        score = score + 1
    if pong_ball.rect.right == 12.5:
        score2 = score2 + 1
        # update 
    all_sprites.update()
    pong_ball_group.update()
    # check to see if pong ball hit one of the pads 
    hits = pg.sprite.spritecollide(pong_ball, all_sprites, False, False)
    for hit in hits:
        pong_ball.bounce()
        # draw and render 
    screen.fill(BLACK)
    all_sprites.draw(screen)
pong_ball_group.draw(screen)
draw_text(screen, str(score), 50, WIDTH / 2 - 30, 10)
draw_text(screen, str(score2), 50, WIDTH / 2 + 30, 10)
draw_text(screen, "-", 50, WIDTH / 2, 10)
# *after* drawing everything, flip the display 
pg.display.flip()
pg.quit()

1 Ответ

2 голосов
/ 20 марта 2020

Проблема в том, как проверить, что мяч покинул экран. Ваше текущее условие проверки никогда не сработает, так как pong_ball.rect.left никогда не будет равно WIDTH - 12.5, поскольку оно является целым числом.

Простой метод отладки - это просто печать проверяемых вами значений, поэтому добавьте

print(pong_ball.rect.left, WIDTH - 12.5)

Выводит:

1264 1267.5
1267 1267.5
1270 1267.5
1273 1267.5
1276 1267.5
1279 1267.5
625 1267.5
628 1267.5

Когда мяч движется к правой стороне экрана и его позиция затем сбрасывается.

Таким образом, вы видите, что позиция шара движется мимо ваш лимит без активации вашего условия.

Если вы измените сравнение на > и < соответственно, оценка обновится.

Однако это вызовет другую проблему, которая также может быть очевидно из отладочных отпечатков выше. Есть четыре кадра, где условие оценки истинно, потому что проверка позиции сброса в PongBall.update() не имеет 12,5-пиксельной задержки. Это почему свобода существует в первую очередь? Ваша будущая личность может быть благодарна за комментарий.

Но если вы измените сравнение, чтобы удалить буфер размером 12,5 пикселей, оценка не обновится. Это связано с тем, что позиция pong_ball обновляется и сбрасывается в методе update().

Если мы следуем вашему подходу для отскока, мы можем добавить отдельный метод reset к PongBall и назовите это, когда мы соответствуем критериям для оценки.

Итак, ваш класс PongBall теперь:

class PongBall(pg.sprite.Sprite):
    def __init__(self):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.Surface((30, 30))
        self.image.fill(WHITE)
        self.rect = self.image.get_rect()
        self.speedx = random.choice(pong_ball_x)
        self.speedy = random.choice(pong_ball_y)
        self.reset()

    def update(self):
        self.rect.x += self.speedx
        self.rect.y += self.speedy
        if self.rect.top <= 0:
            self.speedy = -self.speedy
        if self.rect.bottom >= HEIGHT:
            self.speedy = -self.speedy

    def reset(self):
        self.rect.x = WIDTH / 2 - 15
        self.rect.y = HEIGHT / 2 - 15

    def bounce(self):
        self.speedx = -self.speedx

Ваш основной l oop меняется и выполняет сброс:

while running:
    # process input (events)
    for event in pg.event.get():
        # check for closing window
        if event.type == pg.QUIT:
            running = False
    # check for score
    if pong_ball.rect.left > WIDTH - 12.5:
        score = score + 1
        pong_ball.reset()
    if pong_ball.rect.right < 12.5:
        score2 = score2 + 1
        pong_ball.reset()
    # update
    ....

Тогда ваш счет должен вести себя правильно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...