diff options
author | Laurent Bernabé <laurent.bernabe@gmail.com> | 2013-09-23 19:08:39 (GMT) |
---|---|---|
committer | Laurent Bernabé <laurent.bernabe@gmail.com> | 2013-09-23 19:08:39 (GMT) |
commit | e2ad90b939627353419a7cf3b77ca70d82dc27e8 (patch) | |
tree | 00211420805b2af4bd550c5e49f9466c24627c4a | |
parent | 41064152d503bea830bf931477b3e5ebf0b2eccc (diff) |
The game balls and target result are not hard coded any more, but they are generated for each session.
-rw-r--r-- | balls_generator.py | 145 | ||||
-rw-r--r-- | main.py | 36 |
2 files changed, 159 insertions, 22 deletions
diff --git a/balls_generator.py b/balls_generator.py new file mode 100644 index 0000000..9ae0119 --- /dev/null +++ b/balls_generator.py @@ -0,0 +1,145 @@ +# -*- coding: utf-8 -*- +""" +Generates balls. +Created on Mon Sep 23 18:44:00 2013 + +@author: laurent-bernabe +""" + +from random import randint +from ball import Ball +from operation import Operation, OPER_ADD, OPER_SUB, OPER_MUL, OPER_DIV + + +class OperationConfig(object): + + """ + Stores configuration about a type of operation (OPER_ADD for example) : + what is the limit for its operands ? + """ + + def __init__(self, op_type, fst_op, snd_op): + """ + Constructor: + op_type : operation type => either OPER_ADD, OPER_SUB, OPER_MUL or OPER_DIV + fst_op : limit, in digit numbers, for first operand => integer + snd_op : limit, in digit numbers, for second operand => integer + """ + if op_type == OPER_SUB or op_type == OPER_DIV: + # First operand can't have less digits than second operand in such + # cases. + if fst_op < snd_op: + raise ValueError("fst_op(%d) can't be less than snd_op(%d)" % + (fst_op, snd_op)) + if fst_op <= 0 or snd_op <= 0: + raise ValueError( + "fst_op(%d) and snd_op(%d) must be greater than O." % + (fst_op, snd_op)) + self._op_type = op_type + self._fst_op = fst_op + self._snd_op = snd_op + + def get_operation_type(self): + """ + Accessor to the operation type. + => either OPER_ADD, OPER_SUB, OPER_MUL or OPER_DIV + """ + return self._op_type + + def get_first_operand_limit(self): + """ + Accessor to the limit, in digits, of the first operand + => integer + """ + return self._fst_op + + def get_second_operand_limit(self): + """ + Accessor to the limit, in digits, of the second operand + => integer + """ + return self._snd_op + + +class BallsGenerator(object): + + """ + Generates a list of balls + """ + + def generate_list(self, balls_number, oper_configs, move_area, + txt_font, txt_color): + """ + Generates a list of Ball instances. + Firstly, notice that it is not necessary to pass all four operations. + In such cases only configured operations type will be used for generation. + Secondly, notice that if you pass several configurations for a same + operation, only the first configuration matching this operation will be + used. + balls_number : number of balls to build => integer + oper_configs : configurations for the wanted operations => list of + OperationConfig. + move_area : space where balls are allowed to be => Tuple of 4 integers ( + left side x, top side y, right side x, bottom side y) + txt_font : font common to all balls => olpcgames.pangofont + txt_color : color common to all balls text => tuple of 3 integers between + [0,255] + """ + # We take only one configuration for a given kind of operation. + filtered_oper_configs = [] + registered_operations = set() + for config in oper_configs: + if not config.get_operation_type()["txt"] in registered_operations: + filtered_oper_configs.append(config) + registered_operations.add(config.get_operation_type()["txt"]) + # Then we generates balls + balls = [] + op_type, fst_operand, snd_operand = None, None, None + for counter in range(balls_number): + while True: + op_type_index = randint(1, len(filtered_oper_configs)) - 1 + operation_config = filtered_oper_configs[op_type_index] + op_type = operation_config.get_operation_type() + lim_1 = operation_config.get_first_operand_limit() + lim_2 = operation_config.get_second_operand_limit() + fst_operand = randint(2, 10 ** lim_1 - 1) + snd_operand = randint(2, 10 ** lim_2 - 1) + if op_type == OPER_ADD or op_type == OPER_MUL: + break + elif op_type == OPER_SUB: + if fst_operand > snd_operand: + break + elif op_type == OPER_DIV: + if fst_operand % snd_operand == 0: + break + else: + raise Exception("Unkown operation type") + ball_bg_color = self._generate_color() + ball_velocity = self._generate_velocity() + balls.append(Ball(txt_font, txt_color, ball_bg_color, + Operation(fst_operand, snd_operand, op_type), + move_area, ball_velocity)) + return balls + + def _generate_color(self): + """ + Generates a color + => Tuple of 3 integers between [10, 245[ + """ + red = randint(10, 245) + green = randint(10, 245) + blue = randint(10, 245) + return (red, green, blue) + + def _generate_velocity(self): + """ + Generates ball velocity + => Tuple of 2 integers. + """ + while True: + x = (200 - randint(0, 400)) / 100 # between -2.0 and 2.0 + y = (200 - randint(0, 400)) / 100 # between -2.0 and 2.0 + velocity = (x, y) + if abs(velocity[0]) >= 0.5 and abs(velocity[1]) >= 0.5: + break + return velocity @@ -7,16 +7,17 @@ Created on Sat Sep 14 10:57:17 2013 import olpcgames import pygame +from random import randint from sys import exit from olpcgames.pangofont import PangoFont from pygame.locals import QUIT, USEREVENT, MOUSEBUTTONUP -from ball import Ball -from operation import Operation, OPER_ADD, OPER_SUB, OPER_MUL, OPER_DIV +from operation import OPER_ADD, OPER_SUB, OPER_MUL, OPER_DIV from elements_painter import paint_ball, paint_time_bar, paint_result_bar,\ paint_results from time_bar import TimeBar from result_bar import ResultBar from game_state import GameState +from balls_generator import BallsGenerator, OperationConfig import balls_collision @@ -64,10 +65,8 @@ def main(): BLUE = (0, 0, 255) YELLOW = (255, 255, 0) RED = (255, 0, 0) - GREEN = (0, 255, 0) DARK_GREEN = (0, 100, 0) GRAY = (200, 200, 200) - BROWN = (160, 100, 0) if olpcgames.ACTIVITY: size = olpcgames.ACTIVITY.game_size @@ -82,35 +81,28 @@ def main(): END_TXT_POS = (int(size[0] / 4)), int(size[1] / 2.6) game_state = GameState.NORMAL - target_result = 360 result_bar = ResultBar(font, txt_color=YELLOW, bg_color=RED, header="Hit the balls with result : ", width=size[0]) RESULT_BAR_HEIGHT = result_bar.get_height() - result_bar.set_result(target_result) time_bar = TimeBar(size[0], TIME_BAR_HEIGHT, DARK_GREEN, GRAY, lftp_edge=(0, RESULT_BAR_HEIGHT)) - time_bar.start(1000, 1) + time_bar.start(6000, 1) balls_area = (0, TIME_BAR_HEIGHT + RESULT_BAR_HEIGHT, size[0], size[1]) - the_balls = [Ball(font, txt_color=BLACK, bg_color=BLUE, - operation=Operation(1000, 3000, OPER_MUL), - move_area=balls_area, velocity=(2, 1.2)), - Ball(font, txt_color = BLACK, bg_color = YELLOW, - operation = Operation(120, 45, OPER_SUB), - move_area = balls_area, velocity = (1.6, -0.4)), - Ball(font, txt_color = BLACK, bg_color = BROWN, - operation = Operation(3, 120, OPER_MUL), - move_area = balls_area, velocity = (0.7, -1.8)), - Ball(font, txt_color = BLACK, bg_color = RED, - operation = Operation(9, 3, OPER_DIV), - move_area = balls_area, velocity = (-0.8, 1.6)), - Ball(font, txt_color = BLACK, bg_color = GREEN, - operation = Operation(120, 240, OPER_ADD), - move_area = balls_area, velocity = (1.7, -1.2))] + operations_config = [OperationConfig(OPER_ADD, 2, 2), + OperationConfig(OPER_MUL, 2, 1), + OperationConfig(OPER_SUB, 2, 2), + OperationConfig(OPER_DIV, 2, 2)] + 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 |