From d5030c557d78a3a9b9f6477619ad87e03e6496b2 Mon Sep 17 00:00:00 2001 From: Laurent Bernabé Date: Thu, 26 Sep 2013 16:50:39 +0000 Subject: I've started to implement the main menu. --- diff --git a/activity.py b/activity.py index f888b8d..792abed 100644 --- a/activity.py +++ b/activity.py @@ -11,7 +11,8 @@ from sugar3.activity.widgets import ActivityToolbarButton from sugar3.graphics.toolbutton import ToolButton from sugar3.activity.widgets import StopButton -import main +import main_game + class Activity(activity.Activity): @@ -20,11 +21,11 @@ class Activity(activity.Activity): self.max_participants = 1 self.build_toolbar() - self._act = main.Game() + self._act = main_game.Game() self._pygamecanvas = sugargame.canvas.PygameCanvas(self) self.set_canvas(self._pygamecanvas) self._pygamecanvas.grab_focus() - self._pygamecanvas.run_pygame(self._act.run) + self._pygamecanvas.run_pygame(self._act.show_menu) def build_toolbar(self): toolbar_box = ToolbarBox() @@ -48,6 +49,6 @@ class Activity(activity.Activity): def read_file(self, file_path): pass - + def write_file(self, file_path): pass diff --git a/main.py b/main.py index 24f1f45..d68e216 100644 --- a/main.py +++ b/main.py @@ -5,38 +5,8 @@ Created on Sat Sep 14 10:57:17 2013 @author: laurent-bernabe """ - -from operation import OPER_ADD, OPER_SUB, OPER_MUL, OPER_DIV -from balls_generator import OperationConfig -from main_game import play_game - - -class Game(): - - def __init__(self): - pass - - def run(self): - levels = [ - # level 1 - [OperationConfig(OPER_ADD, 9, 9), - OperationConfig(OPER_MUL, 9, 9), - OperationConfig(OPER_SUB, 18, 9), - OperationConfig(OPER_DIV, 81, 9, 9)], - # level 2 - [OperationConfig(OPER_ADD, 99, 99, 100), - OperationConfig(OPER_MUL, 99, 9), - OperationConfig(OPER_SUB, 100, 98), - OperationConfig(OPER_DIV, 891, 9, 99)], - # level 3 - [OperationConfig(OPER_ADD, 999, 999, 1000), - OperationConfig(OPER_MUL, 99, 99, 1000), - OperationConfig(OPER_SUB, 1000, 998), - OperationConfig(OPER_DIV, 1000, 99, 99)] - ] - - play_game(30, levels[2]) +from main_game import Game if __name__ == "__main__": g = Game() - g.run() + g.show_menu() diff --git a/main_game.py b/main_game.py index c0a4752..7ea2b1e 100644 --- a/main_game.py +++ b/main_game.py @@ -17,144 +17,227 @@ from result_bar import ResultBar from game_state import GameState from balls_generator import BallsGenerator import balls_collision +from operation import OPER_ADD, OPER_SUB, OPER_MUL, OPER_DIV +from balls_generator import OperationConfig -def get_result_at_pos(point, balls_list): - """ - Returns the result of the ball located at point (from the balls_list) - and its index in the balls_list, - if any, else returns None. - point : point to test => tuple of 2 integers - balls_list : list of balls to test => list of Ball - => dictionnary with "result" key => value : integer - "index" key => value : integer - """ - for ball_index in range(len(balls_list)): - ball = balls_list[ball_index] - if ball.contains(point): - return {"result": ball.get_operation().get_result(), - "index": ball_index} - return None - +class Game: -def all_target_balls_destroyed(target_result, balls_list): """ - Says whether all target ball, those with the expected result, have been - removed from the given list. - target_result : expected result => integer - balls_list : list of balls => list of Ball - => Boolean + Manages the game. """ - for ball in balls_list: - if ball.is_visible() \ - and ball.get_operation().get_result() == target_result: - return False - return True - - -def play_game(time_seconds, operations_config): - """ The main game routine - time_seconds : time limit in seconds => integer - operations_config : configurations for the wanted operations => list of - OperationConfig. - """ - pygame.init() - LEFT_BUTTON = 1 - FPS = 40 - BACKGROUND = (255, 255, 255) - TIME_BAR_HEIGHT = 20 - BLACK = (0, 0, 0) - BLUE = (0, 0, 255) - YELLOW = (255, 255, 0) - RED = (255, 0, 0) - DARK_GREEN = (0, 100, 0) - GRAY = (200, 200, 200) - - screen = pygame.display.get_surface() - if not(screen): - size = (600, 400) - screen = pygame.display.set_mode(size) - pygame.display.set_caption("Hit the balls") - else: - size = screen.get_size() - - clock = pygame.time.Clock() - font = pygame.font.Font(None, 40) - end_font = pygame.font.Font(None, 90) - END_TXT_POS = (int(size[0] / 4)), int(size[1] / 2.6) - - game_state = GameState.NORMAL - - result_bar = ResultBar(font, txt_color=YELLOW, bg_color=RED, - header="Hit the ball(s) with result : ", - width=size[0]) - RESULT_BAR_HEIGHT = result_bar.get_height() - - time_bar = TimeBar(size[0], TIME_BAR_HEIGHT, DARK_GREEN, GRAY, - lftp_edge=(0, RESULT_BAR_HEIGHT)) - # Don't forget that it will take time argument * 10 milliseconds - time_bar.start(time_seconds * 100, 1) - - balls_area = (0, TIME_BAR_HEIGHT + RESULT_BAR_HEIGHT, size[0], size[1]) - - the_balls = BallsGenerator().generate_list(5, operations_config, - balls_area, font, BLACK) - - result_index = randint(1, len(the_balls)) - 1 - target_result = the_balls[result_index].get_operation().get_result() - result_bar.set_result(target_result) - - balls_collision.place_balls(the_balls, balls_area) - show_status = True - pygame.time.set_timer(USEREVENT + 2, 800) - - while True: - pygame.display.update() - screen.fill(BACKGROUND) - paint_result_bar(result_bar, screen) - paint_time_bar(time_bar, screen) - if game_state == GameState.NORMAL: - for ball in the_balls: - paint_ball(ball, screen) - - while Gtk.events_pending(): - Gtk.main_iteration() - for event in pygame.event.get(): - if event.type == QUIT: - pygame.quit() - exit() - elif event.type == USEREVENT + 1: - time_bar.decrease() - if time_bar.is_empty(): - game_state = GameState.LOST - elif event.type == MOUSEBUTTONUP: - if event.button == LEFT_BUTTON: - event_pos = event.pos - clicked_ball = get_result_at_pos(event_pos, the_balls) - if clicked_ball is not None: - if clicked_ball["result"] == target_result: - the_balls[clicked_ball["index"]].hide() - if all_target_balls_destroyed( - target_result, the_balls): - game_state = GameState.WON - else: - game_state = GameState.LOST - clock.tick(FPS) - for ball in the_balls: - ball.move() - balls_collision.manage_colliding_balls(the_balls) + def __init__(self): + """ + Constructor. + """ + pygame.init() + self._LEFT_BUTTON = 1 + self._FPS = 40 + self._MENU_LEVELS_RECTS_Y_GAP = 30 + self._MENU_LEVELS_RECTS_WIDTH = 345 + self._MENU_LEVELS_RECTS_HEIGHT = 60 + self._MENU_LEVELS_RECTS_TXT_OFFSET = (10, 10) + self._MENU_LEVELS_RECTS_BG_COLOR = (255, 0, 0) + self._MENU_LEVELS_RECTS_TXT_COLOR = (255, 255, 0) + self._MENU_BACKGROUND = (255, 255, 255) + self._GAME_BACKGROUND = (255, 255, 255) + self._TIME_BAR_HEIGHT = 20 + self._BLACK = (0, 0, 0) + self._BLUE = (0, 0, 255) + self._YELLOW = (255, 255, 0) + self._RED = (255, 0, 0) + self._DARK_GREEN = (0, 100, 0) + self._GRAY = (200, 200, 200) + + self._screen = pygame.display.get_surface() + if not(self._screen): + self._size = (600, 400) + self._screen = pygame.display.set_mode(self._size) + pygame.display.set_caption("Hit the balls") else: - paint_results(balls_area, the_balls, screen) - # Blinks the status text. - if show_status: - if game_state == GameState.WON: - end_txt = "Success !" - else: - end_txt = "Failure !" - end_txt_surface = end_font.render(end_txt, 1, BLUE, RED) - screen.blit(end_txt_surface, END_TXT_POS) - + self._size = self._screen.get_size() + + self._game_font = pygame.font.Font(None, 40) + self._menu_font = pygame.font.Font(None, 90) + self._end_font = pygame.font.Font(None, 90) + self._END_TXT_POS = (int(self._size[0] / 4)), int(self._size[1] / 2.6) + + self._clock = pygame.time.Clock() + self._levels = [ + # level 1 + [OperationConfig(OPER_ADD, 9, 9), + OperationConfig(OPER_MUL, 9, 9), + OperationConfig(OPER_SUB, 18, 9), + OperationConfig(OPER_DIV, 81, 9, 9)], + # level 2 + [OperationConfig(OPER_ADD, 99, 99, 100), + OperationConfig(OPER_MUL, 99, 9), + OperationConfig(OPER_SUB, 100, 98), + OperationConfig(OPER_DIV, 891, 9, 99)], + # level 3 + [OperationConfig(OPER_ADD, 999, 999, 1000), + OperationConfig(OPER_MUL, 99, 99, 1000), + OperationConfig(OPER_SUB, 1000, 998), + OperationConfig(OPER_DIV, 1000, 99, 99)] + ] + self._MENU_LEVELS_RECT_X = (self._size[0] - self._MENU_LEVELS_RECTS_WIDTH)\ + / 2 + self._MENU_LEVEL_1_RECT_Y = (self._size[1] - + (self._MENU_LEVELS_RECTS_HEIGHT + + self._MENU_LEVELS_RECTS_Y_GAP) * len(self._levels) + + self._MENU_LEVELS_RECTS_Y_GAP) / 2 + + self._levels_rect = [(self._MENU_LEVELS_RECT_X, + self._MENU_LEVEL_1_RECT_Y + + y * (self._MENU_LEVELS_RECTS_HEIGHT + + self._MENU_LEVELS_RECTS_Y_GAP), + self._MENU_LEVELS_RECTS_WIDTH, + self._MENU_LEVELS_RECTS_HEIGHT) + for y in range(len(self._levels))] + + def _get_result_at_pos(self, point, balls_list): + """ + Returns the result of the ball located at point (from the balls_list) + and its index in the balls_list, + if any, else returns None. + point : point to test => tuple of 2 integers + balls_list : list of balls to test => list of Ball + => dictionnary with "result" key => value : integer + "index" key => value : integer + """ + for ball_index in range(len(balls_list)): + ball = balls_list[ball_index] + if ball.contains(point): + return {"result": ball.get_operation().get_result(), + "index": ball_index} + return None + + def _all_target_balls_destroyed(self, target_result, balls_list): + """ + Says whether all target ball, those with the expected result, have been + removed from the given list. + target_result : expected result => integer + balls_list : list of balls => list of Ball + => Boolean + """ + for ball in balls_list: + if ball.is_visible() \ + and ball.get_operation().get_result() == target_result: + return False + return True + + def _play_game(self, time_seconds, operations_config): + """ The main game routine + time_seconds : time limit in seconds => integer + operations_config : configurations for the wanted operations => list of + OperationConfig. + """ + game_state = GameState.NORMAL + + result_bar = ResultBar(self._game_font, txt_color=self._YELLOW, + bg_color=self._RED, + header="Hit the ball(s) with result : ", + width=self._size[0]) + RESULT_BAR_HEIGHT = result_bar.get_height() + + time_bar = TimeBar(self._size[0], self._TIME_BAR_HEIGHT, + self._DARK_GREEN, + self._GRAY, lftp_edge=(0, RESULT_BAR_HEIGHT)) + # Don't forget that it will take time argument * 10 milliseconds + time_bar.start(time_seconds * 100, 1) + + balls_area = (0, self._TIME_BAR_HEIGHT + RESULT_BAR_HEIGHT, + self._size[0], self._size[1]) + + the_balls = BallsGenerator().generate_list(5, operations_config, + balls_area, self._game_font, + self._BLACK) + + result_index = randint(1, len(the_balls)) - 1 + target_result = the_balls[result_index].get_operation().get_result() + result_bar.set_result(target_result) + + balls_collision.place_balls(the_balls, balls_area) + show_status = True + pygame.time.set_timer(USEREVENT + 2, 800) + + while True: + pygame.display.update() + self._screen.fill(self._GAME_BACKGROUND) + paint_result_bar(result_bar, self._screen) + paint_time_bar(time_bar, self._screen) + if game_state == GameState.NORMAL: + for ball in the_balls: + paint_ball(ball, self._screen) + + while Gtk.events_pending(): + Gtk.main_iteration() + + for event in pygame.event.get(): + if event.type == QUIT: + pygame.quit() + exit() + elif event.type == USEREVENT + 1: + time_bar.decrease() + if time_bar.is_empty(): + game_state = GameState.LOST + elif event.type == MOUSEBUTTONUP: + if event.button == self._LEFT_BUTTON: + event_pos = event.pos + clicked_ball = self.\ + _get_result_at_pos(event_pos, the_balls) + if clicked_ball is not None: + if clicked_ball["result"] == target_result: + the_balls[clicked_ball["index"]].hide() + if self.\ + _all_target_balls_destroyed( + target_result, the_balls): + game_state = GameState.WON + else: + game_state = GameState.LOST + self._clock.tick(self._FPS) + for ball in the_balls: + ball.move() + balls_collision.manage_colliding_balls(the_balls) + else: + paint_results(balls_area, the_balls, self._screen) + # Blinks the status text. + if show_status: + if game_state == GameState.WON: + end_txt = "Success !" + else: + end_txt = "Failure !" + end_txt_surface = self._end_font.render(end_txt, 1, + self._BLUE, + self._RED) + self._screen.blit(end_txt_surface, self._END_TXT_POS) + + while Gtk.events_pending(): + Gtk.main_iteration() + + for event in pygame.event.get(): + if event.type == QUIT: + pygame.quit() + exit() + elif event.type == USEREVENT + 2: + show_status = not show_status + elif event.type == MOUSEBUTTONUP: + if event.button == self._LEFT_BUTTON: + return + + def show_menu(self): + """ + Manages the main menu. + """ + while True: + self._screen.fill(self._MENU_BACKGROUND) + for box_index in range(len(self._levels)): + box_value = self._levels_rect[box_index] + pygame.draw.rect( + self._screen, self._MENU_LEVELS_RECTS_BG_COLOR, + box_value) + pygame.display.update() while Gtk.events_pending(): Gtk.main_iteration() @@ -162,5 +245,4 @@ def play_game(time_seconds, operations_config): if event.type == QUIT: pygame.quit() exit() - elif event.type == USEREVENT + 2: - show_status = not show_status + #self._play_game(30, self._levels[2]) -- cgit v0.9.1