Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent 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)
commite2ad90b939627353419a7cf3b77ca70d82dc27e8 (patch)
tree00211420805b2af4bd550c5e49f9466c24627c4a
parent41064152d503bea830bf931477b3e5ebf0b2eccc (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.py145
-rw-r--r--main.py36
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
diff --git a/main.py b/main.py
index 6d19fce..a98c74f 100644
--- a/main.py
+++ b/main.py
@@ -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