How to make a cue ball follow an equation in a pool game

Question:

I am writing a python project for a pool game where rather than using a cue stick to hit a ball straight, the user can input a math equation (This will allow the use of exponential absolute and trigonometry etc. For example: y = x, y = exp(x), y = sin(x) etc) which the cue ball will follow. However, I am not sure how to move the cue ball object along the equation of a line.

The cue ball will have a fixed velocity and friction. I have thought about using a graph and centering the origins of the graph to the balls x and y coordinates when the velocity of the cue ball is equal to 0.

The game is written mostly in Pygame, apart form the equation input box where a new window has been created in Tkinter.

If anyone has any knowledge of useful modules for using equations (Rather than just representing data or equations on a graph), that will help.

import pygame
from config import *

class Cueball:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.velocity = pygame.math.Vector2(0,0)
        self.image = pygame.image.load(path.join(CUEBALL_FOLDER, "Cueball.png"))
Asked By: Tobz

||

Answers:

Here is an example where you can type in your equation and the ball position is updated. It uses the Python built-in eval() function. This function should only be used when you can trust your input. There is some very rudimentary filtering but it should not be relied upon to prevent malicious activity:

import pygame
from math import sin, tan, cos

def move(pos, eq, width, height):
    """Eval() the equation to return a new position"""
    x = pos[0] + 1
    if x >= width:
        x = 0  # reset X position
    try:
        y = eval(eq[3:])  # skip "y ="
        if type(y) not in (int, float):
            raise Exception("Unexpected eval() return")
    except:
        x, y = pos  # don't move if equation is invalid
    if abs(y) > (height // 2):  # reset position when off the screen
        return 0, 0
    return x, y


pygame.init()
# grab the first installed font
sys_font = pygame.font.SysFont(None, 37)
clock = pygame.time.Clock()
width, height = 320, 240
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("Movement Equation")
x, y = 0, 0
eq = "y = x"  # initial equation
done = False
while not done:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True
        elif event.type == pygame.TEXTINPUT:
            # very limited input filtering
            if event.text in "0123456789 +-/*x().sintaco":
                eq += event.text
        elif event.type == pygame.KEYUP:
            if event.key == pygame.K_BACKSPACE:
                eq = eq[:-1]
            elif event.key == pygame.K_ESCAPE:
                x, y = 0, 0  # reset position
    # move the ball position
    x, y = move((x, y), eq, width, height)
    # Update text
    text = sys_font.render(eq, True, pygame.Color("turquoise"))
    # Graphics
    screen.fill(pygame.Color("black"))
    # Draw Text in the center
    screen.blit(text, text.get_rect(center=screen.get_rect().center))
    # Draw the ball (shift y axis so zero is in the center)
    pygame.draw.circle(screen, "red", (x, height // 2 - y), 10)
    # Update Screen
    pygame.display.update()
    clock.tick(30)
pygame.quit()

Your question states that the ball will have a fixed velocity and friction, so I don’t understand how trigonometric functions apply. It sounds like you should be using Vector2 as you indicate, but you also want to follow an equation, so that’s what I’ve done. Perhaps it’ll help you develop your own approach. If there’s any take away, it could be to remove your Tkinter dependency.

You can type to add to the equation, Backspace removes the last character and Esc will reset the ball position to the origin. Once the ball moves outside of the screen, it will reset its position.

Movement Equation

Answered By: import random
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.