2

For my Dofe Gold i have created a game of pong in pygame, as this was my first time using pygame i did not use sprites as this didnt occur to me. I am now wanting a solution which will allow me to resolve my problem without entirely rewriting my code with sprites. Note: i want this to still be my code so i will not accept a rewritten solution by someone else as this will take away any sense of accomplishment. Many thanks in advance. my code:

import pygame
import random
global vel
run = True
def pong():
    global run
    collision = 0
    pygame.init()
    screen = (600, 600)
    window = pygame.display.set_mode((screen))
    pygame.display.set_caption("Pong")
    x = 300
    y = 590
    coords = (300, 150)
    width = 175
    height = 10
    vel = 10 - selection
    velx = 10
    vely = 10
    while run == True:
        pygame.time.delay(100)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
        keys = pygame.key.get_pressed()        

        if keys[pygame.K_LEFT] and x>0:
            x -= vel
        elif keys[pygame.K_RIGHT] and x<600-width:
            x += vel
        if event.type == pygame.MOUSEBUTTONUP:
            pygame.quit()
            quit()
        paddlecoords = (x, y, width, height)
        window.fill((255, 255, 255))
        ball = pygame.draw.circle(window, (255,0,255), coords,(35), (0))
        paddle = pygame.draw.rect(window, (0, 0, 0), paddlecoords)
        pygame.display.update()
        coords=((int(coords[0])+velx), (int(coords[1])+vely))
        if coords[0]>600-35:
            velx = -velx
        elif coords[0]<35:
            velx = -velx
        elif coords[1]<35:
            vely = -vely
        elif coords[1]>600-35:
            vely = -vely

selection =input("Do you want to play\n1)easy\n2)medium\n3)hard\n4)impossible?\n")
if selection.isdigit():
    if 0 < int(selection) < 5:
        selection = int(selection)
        selection = (selection-1)*2
    else:
        print("must be between 1 and 4")
else:
    print("number must be an integer")
    quit()
pong()
  • Now I never worked with pygame and can't help with that, but: I think global doesn't do what you think it does. I think you want to declare `vel` as a global variable? If so: no need for global, but please consider making it `VEL` (see here for what random actually does https://stackoverflow.com/questions/4693120/use-of-global-keyword-in-python) and here for why you may want to name it `VEL` https://www.python.org/dev/peps/pep-0008/#naming-conventions - see point "Constants" – SV-97 Mar 14 '19 at 17:47
  • If you search on the phrase "Python collision detect", you’ll find resources that can explain it much better than we can in an answer here. Also, note that you have *already* implemented a collision detection between ball and wall. Simply adapt that to ball and paddle. – Prune Mar 14 '19 at 17:50

1 Answers1

0

Since you don't want any code, here's how to do it in words.

Write a function named, say ballHits().

Pass to the function the paddlecoords , the Ball coords and the radius of the ball 35? as radius

Inside this new function, paddlecoords defines a rectangle. The code needs to check whether the edge of the Ball is within this rectangle.

A simple way of implementing this is to work out the co-ordinates of a rectangle (square) that would surround the ball. Since the ball is painted from the centre, this makes it approximately:

[ coords.x - radius,  coords.y - radius,  2 * radius, 2 * radius ]
# the [ x, y, width, height] of a square covering a circle

Using PyGame's rect class, determine if your two rectangles overlap.

A non-simple way of implementing this is to pre-generate the list of edge-pixels for the circle forming the ball. Maybe use something like the Mid-Point Circle Algorithm, centred on (0,0) to give you a list of points you can adjust with the current Ball co-ordinates.

Using the paddle rectangle, and PyGame's rect class determine if any of those points, when offset to the current ball-location, collide with the paddle. This will give you a true collision, rather than an approximation, and will work better for corner-to-corner collisions. It would probably be faster to check a rough collision with the square method above first, and then check the many circle points.

If the code decides there was a collision, return True from the function, and False otherwise.

In you main code, call out to this function, and act on the returned result.

Kingsley
  • 14,398
  • 5
  • 31
  • 53