Combine effects to menu in pygame
Question: Hey guys am developing a game with pygame. The idea of the game is that when a
user click on `start` button on the menu(which appear on the first before
starting a game) he must see the two balls bouncing on the pygame window.

For this i have two python files.

# bounceball.py

This python file makes the two ball bounce on the pygame window which is made
by me.The code of bounceball.py is [here](http://pastebin.com/M4VA6dH9).(Sorry
for pasting it on pastebin since its a long code)

# menu.py

This python file creates a menu which i have found from the internet and this
also works fine.The code of menu.py is [here](http://pastebin.com/UuTYjFpN)

But the Problem is that when a user clicks on the `Start` button from the menu
it didnt do anything .The thing i want is when a user clicks on `start` button
from menu he must see the ball boucing which i have coded in `bounceball.py`
on the pygame window.How can i link my `bounceball.py` to the menu.

I have tried to acheive this by many methods but it didnt helped me ..

Hope you guys can help me in acheieving this ..Any help would be appreciated
..Thanks in advance


Answer: It could be done better but at least it works.

**menu.py**

    
    
    #!/usr/bin/python
    
    import sys
    import pygame
    
    import bounceball 
    
    #----------------------------------------------------------------------
    
    WHITE = (255, 255, 255)
    RED   = (255,   0,   0)
    BLACK = (  0,   0,   0)
    
    #----------------------------------------------------------------------
    
    class MenuItem(pygame.font.Font):
    
        def __init__(self, text, font=None, font_size=30,
                     font_color=WHITE, (pos_x, pos_y)=(0, 0)):
    
            pygame.font.Font.__init__(self, font, font_size)
            self.text = text
            self.font_size = font_size
            self.font_color = font_color
            self.label = self.render(self.text, 1, self.font_color)
            self.width = self.label.get_rect().width
            self.height = self.label.get_rect().height
            self.dimensions = (self.width, self.height)
            self.pos_x = pos_x
            self.pos_y = pos_y
            self.position = pos_x, pos_y
    
        def is_mouse_selection(self, (posx, posy)):
            if (posx >= self.pos_x and posx <= self.pos_x + self.width) and \
                (posy >= self.pos_y and posy <= self.pos_y + self.height):
                    return True
            return False
    
        def set_position(self, x, y):
            self.position = (x, y)
            self.pos_x = x
            self.pos_y = y
    
        def set_font_color(self, rgb_tuple):
            self.font_color = rgb_tuple
            self.label = self.render(self.text, 1, self.font_color)
    
    #----------------------------------------------------------------------
    
    class GameMenu():
    
        def __init__(self, screen, items, funcs, bg_color=BLACK, font=None, font_size=30,
                     font_color=WHITE):
            self.screen = screen
            self.scr_width = self.screen.get_rect().width
            self.scr_height = self.screen.get_rect().height
    
            self.bg_color = bg_color
            self.clock = pygame.time.Clock()
    
            self.funcs = funcs
            self.items = []
            for index, item in enumerate(items):
                menu_item = MenuItem(item, font, font_size, font_color)
    
                # t_h: total height of text block
                t_h = len(items) * menu_item.height
                pos_x = (self.scr_width / 2) - (menu_item.width / 2)
                pos_y = (self.scr_height / 2) - (t_h / 2) + (index * menu_item.height)
    
                menu_item.set_position(pos_x, pos_y)
                self.items.append(menu_item)
    
            self.mouse_is_visible = True
            self.cur_item = None
    
        def set_mouse_visibility(self):
            if self.mouse_is_visible:
                pygame.mouse.set_visible(True)
            else:
                pygame.mouse.set_visible(False)
    
        def set_keyboard_selection(self, key):
            """
            Marks the MenuItem chosen via up and down keys.
            """
            for item in self.items:
                # Return all to neutral
                item.set_italic(False)
                item.set_font_color(WHITE)
    
            if self.cur_item is None:
                self.cur_item = 0
            else:
                # Find the chosen item
                if key == pygame.K_UP and \
                        self.cur_item > 0:
                    self.cur_item -= 1
                elif key == pygame.K_UP and \
                        self.cur_item == 0:
                    self.cur_item = len(self.items) - 1
                elif key == pygame.K_DOWN and \
                        self.cur_item < len(self.items) - 1:
                    self.cur_item += 1
                elif key == pygame.K_DOWN and \
                        self.cur_item == len(self.items) - 1:
                    self.cur_item = 0
    
            self.items[self.cur_item].set_italic(True)
            self.items[self.cur_item].set_font_color(RED)
    
            # Finally check if Enter or Space is pressed
            if key == pygame.K_SPACE or key == pygame.K_RETURN:
                text = self.items[self.cur_item].text
                self.funcs[text]()
    
        def set_mouse_selection(self, item, mpos):
            """Marks the MenuItem the mouse cursor hovers on."""
            if item.is_mouse_selection(mpos):
                item.set_font_color(RED)
                item.set_italic(True)
            else:
                item.set_font_color(WHITE)
                item.set_italic(False)
    
        def run(self):
            mainloop = True
            while mainloop:
                # Limit frame speed to 50 FPS
                self.clock.tick(50)
    
                mpos = pygame.mouse.get_pos()
    
                for event in pygame.event.get():
                    if event.type == pygame.QUIT:
                        mainloop = False
                    if event.type == pygame.KEYDOWN:
                        self.mouse_is_visible = False
                        self.set_keyboard_selection(event.key)
                    if event.type == pygame.MOUSEBUTTONDOWN:
                        for item in self.items:
                            if item.is_mouse_selection(mpos):
                                self.funcs[item.text]()
    
                if pygame.mouse.get_rel() != (0, 0):
                    self.mouse_is_visible = True
                    self.cur_item = None
    
                self.set_mouse_visibility()
    
                # Redraw the background
                self.screen.fill(self.bg_color)
    
                for item in self.items:
                    if self.mouse_is_visible:
                        self.set_mouse_selection(item, mpos)
                    self.screen.blit(item.label, item.position)
    
                pygame.display.flip()
    
    #----------------------------------------------------------------------
    
    def run_bounceball():
        print "run bounceball"
        bounceball.run(screen)
    
    #----------------------------------------------------------------------
    
    if __name__ == "__main__":
    
        pygame.init()
    
        # Creating the screen
        screen = pygame.display.set_mode((300, 300), 0, 32)
    
        menu_items = ('Start', 'Quit')
        funcs = {'Start': run_bounceball,
                 'Quit': sys.exit}
    
        pygame.display.set_caption('Game Menu')
    
        gm = GameMenu(screen, funcs.keys(), funcs)
        gm.run()
    

**bounceball.py**

    
    
    import pygame
    import math
    from itertools import cycle
    
    #----------------------------------------------------------------------
    
    # some simple vector helper functions, stolen from http://stackoverflow.com/a/4114962/142637
    def magnitude(v):
        return math.sqrt(sum(v[i]*v[i] for i in range(len(v))))
    
    def add(u, v):
        return [ u[i]+v[i] for i in range(len(u)) ]
    
    def sub(u, v):
        return [ u[i]-v[i] for i in range(len(u)) ]    
    
    def dot(u, v):
        return sum(u[i]*v[i] for i in range(len(u)))
    
    def normalize(v):
        vmag = magnitude(v)
        return [ v[i]/vmag  for i in range(len(v)) ]
    
    #----------------------------------------------------------------------
    
    class Ball(object):
    
        def __init__(self, path, screen):
            self.x, self.y = (0, 0)
            self.speed = 2.5
            self.color = (200, 200, 200)
            self.path = cycle(path)
            self.set_target(next(self.path))
    
            self.screen = screen
    
        @property
        def pos(self):
            return self.x, self.y
    
        # for drawing, we need the position as tuple of ints
        # so lets create a helper property
        @property
        def int_pos(self):
            return map(int, self.pos)
    
        @property
        def target(self):
            return self.t_x, self.t_y
    
        @property
        def int_target(self):
            return map(int, self.target)   
    
        def next_target(self):
            self.set_target(self.pos)
            self.set_target(next(self.path))
    
        def set_target(self, pos):
            self.t_x, self.t_y = pos
    
        def update(self):
            # if we won't move, don't calculate new vectors
            if self.int_pos == self.int_target:
                return self.next_target()
    
            target_vector = sub(self.target, self.pos) 
    
            # a threshold to stop moving if the distance is to small.
            # it prevents a 'flickering' between two points
            if magnitude(target_vector) < 2: 
                return self.next_target()
    
            # apply the balls's speed to the vector
            move_vector = [c * self.speed for c in normalize(target_vector)]
    
            # update position
            self.x, self.y = add(self.pos, move_vector)
    
        def draw(self):
            pygame.draw.circle(self.screen, self.color, self.int_pos, 4)
    
    #----------------------------------------------------------------------
    
    def run(screen): 
    
        #pygame.init() # no need it - inited in menu.py
        #screen = pygame.display.set_mode((300, 300))  # no need it - created in menu.py
    
        clock = pygame.time.Clock()    
    
        quit = False
    
        path = [(26, 43),
                (105, 110),
                (45, 225),
                (145, 295),
                (266, 211),
                (178, 134),
                (250, 56),
                (147, 12)]
    
        path2 = [(26, 43),
                 (105, 10),
                 (45, 125),
                 (150, 134),
                 (150, 26),
                 (107, 12)]
    
        ball = Ball(path, screen)
        ball.speed = 1.9
    
        ball2 = Ball(path2, screen)
        ball2.color = (200, 200, 0)
    
        balls = [ball, ball2]
    
        while not quit:
            quit = pygame.event.get(pygame.QUIT)
            pygame.event.poll()
    
            map(Ball.update, balls)
    
            screen.fill((0, 0, 0))
    
            map(Ball.draw, balls)
    
            pygame.display.flip()
            clock.tick(60)
    

