您如何在Pong游戏中预先计算出球的轨迹及其终点?

时间:2019-05-03 19:49:50

标签: python pygame

我正在用Python制作经典的Pong,但是我需要帮助。

对于/在本游戏中,我想计算球的轨迹,因此对于给定的beginPoint(左侧球拍上的弹跳)和角度(绿色),我想计算终点(蓝色X)。所有这些都是为了将​​右桨移至球上,以便您可以自己打Pong。

以下是该问题的图片,以使其更加清晰: https://imgur.com/OySberQ

我试图使用三角函数来提出某种算法,但是只能计算出第一点然后卡住:

def calculateTragectory(beginY, angle):
    distanceX = 0
    direction = ball.directionY
    while True:
        if direction == -1:
            distanceX += (height - beginY) * math.tan(angle)
            direction == 1
        elif direction == 1:
            distanceX += beginY * math.tan(angle)
            direction == -1

这是其余的代码:

import pygame
import random
import math
pygame.init()

width = 1000
height = 600

leftScore = 0
rightScore = 0
delay = 2
paddleSpeed = 2
ballSpeed = 1

paddleWidth = 15
paddleHeight = 70

ballRadius = 10

spacingX = 3*paddleWidth

window = pygame.display.set_mode((width, height))
font = pygame.font.SysFont('Arial', 128)

class Paddle:
    def __init__(self, side):
        # left = true, right = false
        if side:
            self.x = spacingX
        else: self.x = width-spacingX
        self.y = 300

    def move(self, UpOrDown):
        if UpOrDown:
            self.y -= paddleSpeed
        else: self.y += paddleSpeed

    def draw(self):
        pygame.draw.rect(window, (255, 255, 255), (self.x, self.y, paddleWidth, paddleHeight))

class Ball():
    def __init__(self):
        self.x = width/2
        self.y = height/2
        self.directionX = -1
        self.directionY = 1
    def move(self):
        if self.y > height or self.y < 0:
            self.directionY *=-1
        self.x += ballSpeed*self.directionX
        self.y += ballSpeed*self.directionY
    def draw(self):
        pygame.draw.circle(window, (255, 255, 255), (int(self.x), int(self.y)), ballRadius)
    def reset(self):
        self.x = width/2
        self.y = random.uniform(50, 550)
        self.directionX *= -1
def keyInput():
    # Key inputs True = Up, down is False
    keys = pygame.key.get_pressed()
    if keys[pygame.K_w] and leftPaddle.y > 0:
        leftPaddle.move(True)
    if keys[pygame.K_s] and leftPaddle.y < height - paddleHeight:
        leftPaddle.move(False)
    if keys[pygame.K_SPACE]:
        ball.x = width/2
        ball.y = height/2

def collisionDetection():
    if ball.x == leftPaddle.x + paddleWidth + ballRadius and leftPaddle.y <= ball.y <= leftPaddle.y + paddleHeight:
        ball.directionX *= -1
    if ball.x == computerPaddle.x - ballRadius and computerPaddle.y <= ball.y <= computerPaddle.y + paddleHeight:
        ball.directionX *= -1

def scoreUpdate():
    global rightScore, leftScore
    if ball.x <= 0:
        rightScore += 1
        ball.reset()
    elif ball.x >= width:
        leftScore +=1
        ball.reset()
def calculateTragectory(beginY, angle):
    distanceX = 0
    direction = ball.directionY
    while True:
        if direction == -1:
            distanceX += (height - beginY) * math.tan(angle)
            direction == 1
        elif direction == 1:
            distanceX += beginY * math.tan(angle)
            direction == -1

    a = beginPoint * math.tan(angle)

#Init paddles
leftPaddle = Paddle(True)
computerPaddle = Paddle(False)
ball = Ball()
#Game loop:
while True:
    pygame.time.delay(delay)
    ball.move()
    collisionDetection()
    scoreUpdate()
    scoreText_left = font.render(str(leftScore), True, (255, 255, 255))
    scoreText_right = font.render(str(rightScore), True, (255, 255, 255))
    keyInput()
    window.fill((0, 0, 0))
    window.blit(scoreText_left, (350-64, 50))
    window.blit(scoreText_right, (650, 50))
    leftPaddle.draw()
    computerPaddle.y = ball.y
    computerPaddle.draw()
    ball.draw()
    pygame.display.update()

    #Exit
    for event in pygame.event.get():
      if event.type == pygame.QUIT:
         if event.key == pygame.K_ESCAPE:
             pygame.quit()

1 个答案:

答案 0 :(得分:2)

以下是您需要的代码:

# width and height are the width and height you want to calculate the endpoint for
def calculate_tragectory(begin_y, angle):
    x_speed = math.cos(angle)  # calculate the relative x of the angle
    y_speed = math.sin(angle)  # calculate the relative y of the angle
    
    straight_pos = begin_y + width * y_speed / x_speed
    # this is the final position if the ball wouldn't change direction
    
    final_pos = abs(straight_pos) % (2 * height)
    # a negative result just of straight_pos means it bounces one additional time
    # but has no effect on the result.
    # (that's why abs(straight_pos) instead of just straight_pos)
    # if the result is 2 * height it means that the ball has bounced twice
    # and has returned to y position 0.
    
    if final_pos > height:
        final_pos = 2 * height - final_pos
    # if final_pos > height this means that the ball has bounced once and
    # the final position is the remainder to 2 * height.
    
    return final_pos

您要进行的修改:

  • 您需要从宽度中减去桨间距和球半径。
  • 确保将桨的中间设置为此值而不是顶部。
  • 在您的情况下,您实际上并不想输入角度,而是输入 x 和 y 速度:
def calculate_tragectory(begin_y, x_speed, y_speed):
    # input x_speed and y_speed instead of calculating them from the angle
    ...

改进代码的一般提示:

  • 根据python documentation变量和函数应该命名为lowercase_with_underscores
  • 碰撞检测非常糟糕。它经常在视觉上发生碰撞,但仍然穿过桨。