1

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.(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

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

Community
  • 1
  • 1
  • possible duplicate of [Pygame level/menu states](http://stackoverflow.com/questions/14700889/pygame-level-menu-states) – sloth Jul 02 '14 at 09:53
  • Why do you have two seperated programs with own `screen` and own resolution ? – furas Jul 02 '14 at 12:17
  • When I click `Start` I see `Hello World` in console - but I don't see any method (made by you) in code to run `bounceball` – furas Jul 02 '14 at 12:25
  • @furas yeah thats why i say am stuck ...am a beginner in pygame so i dont know how to link bounceball.py file to the start button ..i have tried copying the codes of bounceball.py to def hello_world() function in menu.py .but it didnt worked ..if you know how to link this both ..please tell me how or post as an answer.. – user3792941 Jul 02 '14 at 13:31
  • It is more work to reorganize that mess. :) – furas Jul 02 '14 at 13:36
  • @furas if you know how to do it then please put an answer as the code ..it would be really helpful and i will appreciate it ..thanx – user3792941 Jul 02 '14 at 13:45
  • @furas any suggestions or puttting code as the answer would be really appreciated ..:) – user3792941 Jul 02 '14 at 13:50

1 Answers1

0

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)
furas
  • 134,197
  • 12
  • 106
  • 148