redyugi 5 Junior Poster in Training

I have recently redid an earlier version of my version of Pong. However, I am having a slight issue with it. Whenever the ball hits the opposing paddle and then hits the bottom, the ball travels along the bottom until the player paddle hits it. I have tried for days to fix it but it seems I cannot on my own. Any help would be greatly appreciated.

I was going to implement vectors into but I still am not good with them so..

This is a font module, for easy changing of fonts. It is used below so I will include it here

Text.py

import pygame
import random
from pygame.font import Font as Rfont
import pygame.gfxdraw
pygame.init()

def randcolor():
    c1 = random.randint(0, 255)
    c2 = random.randint(0, 255)
    c3 = random.randint(0, 255)
    print (c1, c2, c3)
    return (c1, c2, c3)

def randcoor(x, y):
    co1 = random.randint(0, x)
    co2 = random.randint(0, y)
    return (co1,  co2)

class Font(Rfont):
    def __init__(self,  name,  size):
        self.font = Rfont(name,  size)
        self.name_of_font = name
    def get_name(self):
        return self.name_of_font
    def render(self,  text,  i,  color):
        return self.font.render(text,  i,  color).convert()
    def get_height(self):
        return self.font.get_height()
    def get_width(self):
        return self.font.get_width()
    def get_size(self):
        return (self.font.get_width(),  self.font.get_height())

class Text(object):
    def __init__(self,  text,  fonts=[pygame.font.get_default_font()], sizes=[20],  main=(pygame.font.get_default_font(), 20),
                color=(0, 0, 0)):
        self.fonts = {}
        for w, i in enumerate(fonts):
            self.fonts[i] = {}
            self.fonts[i][sizes[w]] = Font(i,  sizes[w])
        self.current_font = self.fonts[main[0]][main[1]]
        self.text = self.current_font.render(text,  0,  color)
        self.color = color
        self.words = text
    def change_text(self,  new):
        self.text = self.current_font.render(new,  0,  self.color)
        self.words = new
    def change_font(self,  new,  size=20):
        if self.fonts.has_key(new):
            if self.fonts[new].has_key(size):
                self.current_font = self.fonts[new][size]
                self.text = self.current_font.render(self.words,  0,  self.color)
            else:
                self.change_size(size,  new)
        else:
            self.add_font(new,  size)
            self.current_font = self.fonts[new][size]
            self.text = self.current_font.render(self.words,  0,  self.color)
    def change_size(self,  size,  font=1):
        if font != 1 and self.fonts.has_key(font):
            self.fonts[font][size] = Font(font,  size)
            self.current_font = self.fonts[font][size]
            self.text = self.current_font.render(self.words,  0,  self.color)
        elif font == 1:
            self.fonts[self.current_font.get_name()][size] = Font(self.current_font.get_name(),  size)
            self.current_font = self.fonts[self.current_font.get_name()][size]
            self.text = self.current_font.render(self.words,  0,  self.color)
    def change_color(self,  color):
        self.color = color
        self.text = self.current_font.render(self.words,  0,  self.color)
    def add_font(self,  font,  size):
        self.fonts[font][size] = Font(font,  size)
    def render(self):
        return self.text
    def get_width(self):
        return self.text.get_width()
    def get_height(self):
        return self.text.get_height()
    def get_size(self):
        return self.text.get_size()

Pong.py

from __future__ import division
import random
import os
from Text import Text 
import pygame
import pygame.gfxdraw as Drawing
from imputwrapper import Input
from pygame.locals import *
pygame.init()
pygame.mixer.init()
os.environ['SDL_VIDEO_CENTERED'] = '1'

### End imports ###

### System kernal info ###

__Name__ = 'Pong'
__Created__ = 'August 25, 2010'
__Version__ = 0.95 + .1
__Updated__ = 'August 31, 2010'
__ToDo__ = 'Fix bug when ball hits ball of screen'

### End System kernal ###

### Sound check ###

sound = raw_input('Sound?   ') # Ask for sound
if sound.lower() not in 'yes yeah y yup' or not pygame.mixer.get_init():
    print 'Sound is disabled.'
    sound = False
else:
    sound = True

### End sound check ###

### Class definitions ###

class MyException(Exception):
    '''Exception to handle small problems'''
    def __init__(self, message = None):
        self.message = message
    def __str__(self):
        return repr(self.message)

class Music(object):
    def __init__(self, list_of_tracks):
        self.list_of_tracks = {}
        for i in list_of_tracks:
            self.list_of_tracks[i] = pygame.mixer.Sound(i)
        self.current = None
    def play(self, song):
        if song in self.list_of_tracks:
            self.list_of_tracks[song].play()
            self.current = song
        else:
            raise MyException, 'No such music avaible'
    def stop(self):
        if self.current:
            self.list_of_tracks[self.current].stop()
            self.current = None
    def set_nick(self, name, nick):
        self.list_of_tracks[nick] = self.list_of_tracks[name]
        del self.list_of_tracks[name]

class Pobject(object):
    def revert(self):
        '''Changes the image back to the original size'''
        # Get the x and y value
        coor = (self.position[0],  self.position[1])
        # Return the image to normal
        self.image = pygame.transform.smoothscale(self.image,  self.size)
        # Get the new rect
        self.rect = self.image.get_rect()
        # Set the rect to same co-ordinates
        self.position[0] = coor[0]
        self.position[1] = coor[1]
    def scale(self,  scale):
        '''Changes the image another size'''
        # Get the x and y value
        coor = (self.position[0],  self.position[1])
        # Change the size of the image
        self.image = pygame.transform.smoothscale(self.image,  scale)
        # Get the new rect
        self.rect = self.image.get_rect()
        # Set the rect to same co-ordinates
        self.position[0] = coor[0]
        self.position[1] = coor[1]
    def draw(self,  screen):
        '''Draws the object onto the screen'''
        screen.blit(self.image,  self.rect)

class Paddle(Pobject):
    '''A class for the both the player and the opponent.'''
    def __init__(self, size, place, image=None,  color=(255, 255, 255)):
        '''The construtor. Sets boundries, images converted, rects set.'''
        if image:
            # Loads the image
            ima = pygame.image.load(image).convert_alpha()
            self.image = pygame.transform.smoothscale(ima,  size)
        else:
            # Creates a surface if there isn't an image
            self.image = pygame.surface.Surface(size).convert()
            self.image.fill(color)
        # Sets the original size
        self.size = size
        # Set the position and the rect
        self.rect = self.image.get_rect()
        self.rect.topleft = place
        # Set the speed
        self.speed = 0
    def update(self,  move,  disp, bottomrect):
        '''Updates the paddles y value'''
        # Moves the rect
        self.rect.y += move
        # Change speed
        if move > 0 and self.speed < 1:
            self.speed += move / 10
        elif not move:
            self.speed = 0
        # Checks if movement is with-in bounds
        if self.rect.colliderect(disp.rect):
            self.rect.y = disp.rect.bottom
        elif self.rect.colliderect(bottomrect):
            self.rect.bottom = bottomrect.top

class Ball(Pobject):
    '''Creates a new ball'''
    def __init__(self, size, place, image=None, radius=None, color=(255, 255, 255),
                screencolor=(0, 0, 0)):
        '''Constructor. Sets the boundries, the rect, and the image'''
        if image:
            # Loads the image
            ima = pygame.image.load(image).convert_alpha()
            self.image = pygame.transform.smoothscale(ima,  size)
        else:
            # Creates a surface
            if not radius:
                radius = (size[0]/6)*2
            self.image = pygame.surface.Surface(size)
            self.image.fill(screencolor)
            Drawing.filled_circle(self.image,  int(size[0]/3), int(size[1]/3), int(radius), color)
        # Set the size
        self.size = size
        # Get the rect and set the place
        self.rect = self.image.get_rect()
        self.rect.topleft = place
        # Set the angle
        self.random_place()
        # Set up touch
        self.touch = False
        # Set up speed
        self.speed = 1.0
        self.xspeed = 1.0
        # Make table for angling
        self.table = {
            0:[5, 0],
            5:[5, -.5],
            10:[5, -1],
            15:[5, -1.5],
            20:[5, -2],
            25:[5, -2.5],
            30:[5, -3],
            35:[5, -3.5],
            40:[5, -4],
            45:[4.5, -4.5],
            50:[4, -5],
            55:[3.5, -5],
            60:[3, -5],
            65:[2.5, -5],
            70:[2, -5],
            75:[1.5, -5],
            80:[1, -5],
            85:[.5, -5],
            90:[0, -5],
            360:[5, 0],
            355:[5, .5],
            350:[5, 1],
            345:[5, 1.5],
            340:[5, 2],
            335:[5, 2.5],
            330:[5, 3],
            325:[5, 3.5],
            320:[5, 4],
            315:[4.5, 4.5],
            310:[4, 5],
            305:[3.5, 5],
            300:[3, 5],
            295:[2.5, 5],
            290:[2, 5],
            285:[1.5, 5],
            280:[1, 5],
            275:[.5, 5],
            270:[0, 5],
            180:[-5, 0],
            185:[-5, .5],
            190:[-5, 1],
            195:[-5, 1.5],
            200:[-5, 2],
            205:[-5, 2.5],
            210:[-5, 3],
            215:[-5, 3.5],
            220:[-5, 4],
            225:[-4.5, 4.5],
            230:[-4, 5],
            235:[-3.5, 5],
            240:[-3, 5],
            245:[-2.5, 5],
            250:[-2, 5],
            255:[-1.5, 5],
            260:[-1, 5],
            265:[-.5, 5],
            175:[-5, -.5],
            170:[-5, -1],
            165:[-5, -1.5],
            160:[-5, -2],
            155:[-5, -2.5],
            150:[-5, -3],
            145:[-5, -3.5],
            140:[-5, -4],
            135:[-4.5, -4.5],
            130:[-4, -5],
            125:[-3.5, -5],
            120:[-3, -5],
            115:[-2.5, -5],
            110:[-2, -5],
            105:[-1.5, -5],
            100:[-1, -5],
            95:[-.5, -5],
            }
    def random_place(self):
        '''Place the ball in a random angle'''
        self.angle = random.randint(1, 359)
    def aup(self):
        '''Checks the angle'''
        if self.angle in [90, 180, 270, 360, 0]:
            self.angle += random.choice([1, -1])
    def tup(self, p1, p2):
        '''Checks if ball isnt touching paddles'''
        if self.touch and not (self.rect.colliderect(p1) or self.rect.colliderect(p2)):
            self.touch = False
    def speed_check(self):
        '''Checks the speed of the ball and sets reduction values'''
        if self.speed > 1.0:
            self.speed -= .05
            if self.speed < 1.0:
                self.speed = 1.0
        elif self.speed < 1.0:
            self.speed = 1.05
        if self.xspeed > 1.0:
            self.xspeed -= .05
            if self.xspeed < 1.0:
                self.xspeed = 1.0
        elif self.xspeed < 1.0:
            self.xspeed = 1.05
    def table_return(self):
        '''Get positioning from table'''
        if self.table.has_key(self.angle):
            return self.table[self.angle]
        else:
            for i in range(5):
                if self.table.has_key(self.angle+i):
                    return self.table[self.angle+i]
    def update(self,  speed,  player1,  player2,  disp, bottomrect):
        '''Updates the balls position'''
        # Check the angles
        self.aup()
        # Check for touch
        self.tup(player1, player2)
        t = self.table_return()
        # Moves the x value according to the direction
        if self.angle <= 90 or self.angle >= 270:
            self.rect.x += self.xspeed * speed #+ (t[0]/5)
        else:
            self.rect.x -= self.xspeed * speed# + (t[0]/5)
        # Moves the y value according to the speed
        if self.angle < 180:
            self.rect.y -= self.speed + (t[1]/5)
        else:
            self.rect.y += self.speed + (t[1]/5)
        # Check speed
        self.speed_check()
        # Check the angles
        self.aup()
        # Checks for collisions
        return self.check(player1,  player2,  disp, bottomrect)
    def check(self,  p1,  p2,  disp, bottomrect):
        '''Checks for collisions'''
        collide = False
        # If the ball is moving right
        if (self.angle <= 90 or self.angle >= 270) and self.rect.colliderect(p2.rect):
            # If it isn't already touching the paddle
            if not self.touch:
                collide = True
                self.touch = True
                self.angle += 180 if self.angle <= 180 else -180
                # Change the speed
                if self.around(p2):
                    self.speed += .6
                    self.xspeed += self.xspeed * p2.speed
                elif self.around(p2, 'bottomright'):
                    self.speed += .6
                    self.xspeed += self.xspeed * p2.speed
                elif self.around(p2,  (p2.rect.center[0]+(p2.rect.width/2),  p2.rect.center[1]), 10, True):
                    self.speed = 1
                    self.xspeed = 1
                else:
                    self.speed += .1
                    self.xspeed += p2.speed
        # If ball is moving left
        elif (self.angle <= 270 and self.angle >= 90) and self.rect.colliderect(p1.rect):
            # If it isn't already touching the paddle
            if not self.touch:
                collide = True
                self.angle += 180 if self.angle <= 180 else -180
                self.touch = True
                # Change the speed
                if self.around(p1):
                    self.speed += .6
                    self.xspeed += self.xspeed * p1.speed
                elif self.around(p1, 'bottomright'):
                    self.speed += .6
                    self.xspeed += self.xspeed * p1.speed
                elif self.around(p1,  (p1.rect.center[0]+(p1.rect.width/2),  p1.rect.center[1]), 10, True):
                    self.speed = 1
                    self.xspeed = 1
                else:
                    self.speed += .1
                    self.xspeed += p1.speed
        # If it is touching the top
        if self.rect.colliderect(disp.rect):
            if self.rect.y <= 90 and self.rect.y > 0:
                self.angle = 360 - self.angle
            elif self.rect.y >= 90 and self.rect.y <= 180:
                self.angle += 90
            self.speed += .05
        # If it is touching the bottom
        if self.rect.colliderect(bottomrect):
            if self.angle <= 360 and self.angle >= 270:
                self.angle = 360 - self.angle
            elif self.angle >= 180 and self.angle <= 270:
                self.angle -= 90
            self.speed += .05
        return collide
    def around(self, pad, point='topright',  divide=5,  p=False):
        '''Checks if ball is around a certain point'''
        if not p:
            po = eval('pad.rect.%s'%point)
        else:
            po = point
        x = po[1] / divide
        for i in range(int(po[1]-x), int(po[1]+x)):
            if self.rect.collidepoint((po[0], i)):
                return True
        return False

class Power(Pobject):
    def __init__(self, size, upperbound, lowerbound, left, right, image, target={'1.5 scale':['player']},
                power=['1.5 scale'], ptime=200,  stime=200):
        '''The construtor. Sets boundries, images converted, rects set.'''
        # Loads the image
        ima = pygame.image.load(image).convert_alpha()
        self.image = pygame.transform.smoothscale(ima,  size)
        # Sets the original size
        self.size = size
        # Get the rect
        self.rect = self.image.get_rect()
        # Set the bounds
        self.upper = upperbound
        self.lower = lowerbound
        self.left = left
        self.right = right
        # Set the times
        self.stime = stime
        self.ptime = ptime
        self.screen = True
        # Set powers and targets
        self.powers = power
        self.targets = target
    def update(self, player, opponent, ball):
        if self.screen:
            self.stime -= 1
            self.check_ball(player, opponent, ball)
            if not self.stime:
                return 'delete'
        else:
            self.ptime -= 1
            if not self.ptime:
                self.stop(player, opponent, ball)
                return 'delete'
        return 'stay'
    def draw(self,  screen):
        '''Draw the power up to the screen'''
        if self.screen:
            screen.blit(self.image,  self.rect)
    def place(self,  screen):
        '''Place the power up on the screen'''
        self.rect.x = random.randint(self.upper,  self.lower)
        self.rect.y = random.randint(self.left, self.right)
        self.draw(screen)
    def check_ball(self, p1, p2, ball):
        if ball.rect.colliderect(self.rect):
            self.run(p1, p2, ball)
    def run(self, p1, p2, ball):
        for pow in self.powers:
            pow1 = pow.split()
            for t in self.targets[pow]:
                if 'scale' == pow1[1]:
                    if t == 'player':
                        p1.scale(int(pow1[0]))
                    elif t == 'opponent':
                        p2.scale(int(pow1[0]))
                    elif t == 'ball':
                        ball.scale(int(pow1[0]))
    def stop(self,  p1,  p2,  ball):
        p1.revert()
        p2.revert()
        ball.revert()

class Display(Pobject):
    '''Class for display of points and such'''
    def __init__(self, size, ssize, place, name1, name2, color1, color2, image=None, bcolor=(0, 0, 0)):
        '''Constructor. Sets the names and background and scores up.'''
        if image:
            # Loads the image
            ima = pygame.image.load(image)
            self.image = pygame.transform.smoothscale(ima,  size)
        else:
            # Create a surface for the background
            self.image = pygame.surface.Surface(size)
            self.image.fill(bcolor)
        # Set the size
        self.size = size
        # Get the rect
        self.rect = self.image.get_rect()
        self.rect.x = place[0]
        self.rect.y = place[1]
        # Set name and scores
        self.name1 = Text(name1,  color=color1)
        self.name2 = Text(name2,  color=color2)
        self.score = [0, 0]
        self.score1 = Text('0',  color=color1)
        self.score2 = Text('0',  color=color2)
        # Set up the draw positions
        self.places = {}
        self.places['name1'] = place
        self.places['name2'] = (ssize[0]-self.name2.get_width()-10, place[1])
        self.places['score1'] = (ssize[0]/2-20,  place[1])
        self.places['score2'] = (ssize[0]/2+20,  place[1])
    def update(self,  score1,  score2):
        '''Update the scores'''
        self.score[0] += score1
        self.score[1] += score2
        self.score1.change_text(str(self.score[0]))
        self.score2.change_text(str(self.score[1]))
    def change_name(self,  n1,  n2):
        '''Change the names of the players'''
        self.name1.change_text(n1)
        self.name2.change_text(n2)
    def draw(self,  screen):
        '''Draw the Display'''
        # Draw the background
        screen.blit(self.image,  self.rect)
        # Draw the names
        screen.blit(self.name1.render(),  self.places['name1'])
        screen.blit(self.name2.render(),  self.places['name2'])
        # Draw the scores
        screen.blit(self.score1.render(),  self.places['score1'])
        screen.blit(self.score2.render(),  self.places['score2'])

class AI(object):
    '''Class that decides where AI paddle will move'''
    def __init__(self, main='Normal', levels={'Easy':[3, 4, 5, 4, 3],  'Normal':[2, 3, 4, 3, 2],  'Hard':[3, 2, 1, 2, 3, 2, 3]}):
        '''Constructor. Sets the level'''
        self.levels = levels
        self.main = main
        self.level = levels[main]
    def update(self, frame, ball,  p):
        '''Updates the paddle'''
        if random.choice(self.level) <= 100:#frame:
            if ball.angle >= 180 and ball.angle <= 360 or p.rect.y <= ball.rect.y:
                # If ball is moving downward
                return 1
            elif ball.angle <= 180 and ball.angle >= 0 or p.rect.y >= ball.rect.y:
                # If ball is moving upward
                return -1
        return 0

### End class definitions ###

### Global definitions ###

def draw_all(screen, background, player, ball, opp, disp, power):
    '''Draws all the items onto the screen'''
    screen.blit(background,  (0, 0))
    disp.draw(screen)
    player.draw(screen)
    ball.draw(screen)
    opp.draw(screen)
    if power:
        power.draw(screen)

def main(size,  limit,  name, chance=10, pows=True,  image=(20, 20, 50), sound=True):
    '''Sets up and plays the game'''
    # Creates the screen
    screen = pygame.display.set_mode(size)
    pygame.display.set_caption('Pong %s'%__Version__)
    icon = pygame.surface.Surface((40, 40))
    icon.fill((0, 0, 0))
    icon.set_alpha(255)
    pygame.display.set_icon(icon)
    bottomrect = pygame.rect.Rect(0, size[1], size[0], 1)
    # Create/load background image
    if isinstance(image, tuple):
        background = pygame.surface.Surface(size).convert()
        background.fill(image)
    else:
        background = pygame.image.load(image).convert()
    # Creates the player
    player = Paddle((20, 50), [10, size[1]/2])
    # Creates the opponent and the AI
    opp = Paddle((20, 50),  [size[0]-30, size[1]/2])
    ai = AI('Hard')
    # Creates the ball
    ball = Ball((30, 30), [300, 250], screencolor=image)
    # Create the display
    disp = Display((size[0], 20), size, (0, 0), name,  '%s Opponent'%ai.main, (0, 0, 200), (200, 0, 0))
    # Create power ups
    if pows:
        powers = [((40, 40),  size[1]-10, disp.image.get_height(), 40, size[0]-50,  'pow1.png')]
    else:
        powers = ''
    power = ''
    pow = 'Stay'
    # Create the clock for frame rate control
    clock = pygame.time.Clock()
    # Set up player variables
    move = 0
    # Set up opponent variables
    omove = 0
    # Set up AI variables
    frame = 0
    # Set up frame rate check
    low = 1000
    high = 0
    # Check for the game to be done
    run = 1
    # Create the sound effects
    if sound:
        music = Music(['score.wav', 'collide.wav'])
        music.set_nick('score.wav', 'score')
        music.set_nick('collide.wav', 'collide')
    # Start the loop
    while run:
        # Tick the clock
        clock.tick(limit)
        # Check the frame rate
        current_fps = int(clock.get_fps())
        if  current_fps < low and current_fps > 10:
            low = current_fps
        if current_fps > high:
            high = current_fps
        # Update AI variable
        frame += 1
        # Get keys
        Input.add_events(pygame.event.get())
        # Check for exit
        if Input.isset(pygame.QUIT) or Input.down(pygame.K_ESCAPE):
            run = 0
        # Check for player movement
        # If up
        if Input.down(pygame.K_UP):
            move += -1
        # If down
        elif Input.down(pygame.K_DOWN):
            move += 1
        # Create a new power up:
        if not power and powers and random.randint(0, 100) >= chance:
            #p = random.choice(powers)
            #power = Power(p[0], p[1],  p[2], p[3], p[4], p[5])
            #power.place(screen)
            #del p
            pass
        if pow == 'Delete':
            power = ''
            pow = 'Stay'
        # Update everything
        player.update(move,  disp, bottomrect)
        if power:
            pow = power.update(player,  opp,  ball)
        if 30:
            m = ball.update(1, player, opp, disp, bottomrect)
            if sound and m:
                music.play('collide')
        omove = ai.update(frame, ball, opp)
        if omove == 1 or omove == -1:
            frame = 0
        opp.update(omove, disp, bottomrect)
        # Check for score
        if ball.rect.x <= 0 or ball.rect.x >= size[0]:
            if ball.rect.x >= size[0]:
                disp.update(1, 0)
            else:
                disp.update(0, 1)
            if sound:
                music.play('score')
            ball.rect.topleft = [size[0]/2,  size[1]/2]
            pygame.time.wait(limit*3)
            ball.touch = False
            ball.random_place()
        # Draw everything
        draw_all(screen,background, player, ball, opp, disp, power)
        # Clean up
        pygame.display.update()
        move = 0
    print 'The lowest frame rate was %s and the highest was %s.' %(low,  high)
    pygame.quit()

### End global definitions ###

### Start ###

if __name__ == '__main__':
    n = 'Kyle'#raw_input('Name?   ')
    main((600, 500), 200,  n, 0, sound=False)

Again, thanks for any help given