Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/main_game.py
blob: c0a4752ea320d1bb9ef0a9744eccf1f0a12e6f20 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# -*- coding: utf-8 -*-
"""
Manages the main game.
Created on Tue Sep 24 13:54:20 2013

@author: laurent-bernabe
"""
from gi.repository import Gtk
import pygame
from random import randint
from sys import exit
from pygame.locals import QUIT, USEREVENT, MOUSEBUTTONUP
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
import balls_collision


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


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
    """
    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)
        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)

            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