Olivier Berg
Olivier Berg

Reputation: 55

Getting end coordinate from starting coordinate and velocity

So I'm creating a little pong game in python (pygame) and I'm trying to create a bot for it... if you have the balls velocity: velocity = [10, 5] the balls x: x = 300 and the y: y = 300 is it possible the calculate where the ball is going to go (also knowing where the edges are where the ball bounces) my code for the game till now: https://pastebin.com/eQRZedqs

import pygame
import sys
 
 
SIZE = (1000, 600)
FRAMES = 60
win = pygame.display.set_mode(SIZE)
clock = pygame.time.Clock()
 
 
class Player:
    def __init__(self, x, y):
        self.size = (15, 120)
        self.x = x
        self.y = y
 
    def draw(self, surface):
        pygame.draw.rect(surface, (255, 255, 255),
                         pygame.Rect((self.x, self.y), self.size))
 
 
class Ball:
    def __init__(self):
        self.x = SIZE[0] // 2
        self.y = SIZE[1] // 2
        self.vel = [-5, 0]
 
    def move(self):
        self.x += self.vel[0]
        self.y += self.vel[1]
        if self.y <= 20 or self.y >= SIZE[1] - 20:
            self.vel[1] *= -1
        if (self.x <= 45 and bot.y < self.y < bot.y + bot.size[1]) or (self.x >= SIZE[0] - 45 and p.y < self.y < p.y + p.size[1]):
            self.vel[0] *= -1
 
    def draw(self, surface):
        pygame.draw.circle(surface, (255, 255, 255), (self.x, self.y), 10)
 
 
class Bot(Player):
    def __init__(self, x, y):
        super().__init__(x, y)
        self.ball_vel = b.vel
        self.ball_x = b.x
        self.ball_y = b.y
 
 
def draw_screen(surface):
    surface.fill((0, 0, 0))
    p.draw(surface)
    b.draw(surface)
    bot.draw(surface)
    b.move()
    pygame.display.update()
 
 
def key_handler():
    keys = pygame.key.get_pressed()
 
    if (keys[pygame.K_UP] or keys[pygame.K_w]) and p.y >= 20:
        p.y -= 5
    elif (keys[pygame.K_DOWN] or keys[pygame.K_s]) and p.y + p.size[1] <= SIZE[1] - 20:
        p.y += 5
 
 
def main_loop():
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
        key_handler()
 
        draw_screen(win)
 
        clock.tick(FRAMES)
 
 
if __name__ == "__main__":
    pygame.init()
    p = Player(SIZE[0] - 45, SIZE[1] // 2 - 60)
    b = Ball()
    bot = Bot(20, SIZE[1] // 2 - 60)
    main_loop()

Upvotes: 1

Views: 192

Answers (1)

Shufi123
Shufi123

Reputation: 233

I'd say add the following function to the Ball class:

class Ball:
    def __init__(self):
        self.x = SIZE[0] // 2
        self.y = SIZE[1] // 2
        self.vel = [-5, 0]
 
    def move(self):
        self.x += self.vel[0]
        self.y += self.vel[1]
        if self.y <= 20 or self.y >= SIZE[1] - 20:
            self.vel[1] *= -1
        if (self.x <= 45 and bot.y < self.y < bot.y + bot.size[1]) or (self.x >= SIZE[0] - 45 and p.y < self.y < p.y + p.size[1]):
            self.vel[0] *= -1
 
    def draw(self, surface):
        pygame.draw.circle(surface, (255, 255, 255), (self.x, self.y), 10)

    # projecting to see in which y the ball will end up (returns the y coordinate)
    def project(self):
        # setting up local variables as to not change the actual position of the ball
        x = self.x
        y = self.y
        vel = self.vel
        # doing practically the same thing as move but with the local x and y
        while x > 45 and x < SIZE[0] - 45:
                x += vel[0]
                y += vel[1]
                if y <= 20 or y >= SIZE[1] - 20:
                    vel[1] *= -1
        return y

Since you have the return value of y, then you can get your bot to move directly there, either in a slow manner or an instant one. If you want to get into quicker solutions, you need to use some physics equations, but in my opinion, this is quick enough (it'll get there pretty quickly). Also, you could alternatively use trigonometry to get the answer, by imagining the velocities as one vector (then you could get the angle of motion relative to the y axis and then use trig to get the final length until the y reaches the border. Repeat that, until you get to the y-axis borders, and you can calculate your x more efficiently (though, once again, there is most probably no need for that, since it should run fast enough).

Upvotes: 2

Related Questions