示例#1
0
def opening():
    black_cover = GRect(w.width, w.height, x=0, y=0)
    black_cover.filled = True
    black_cover.fill_color = "black"
    w.add(black_cover)
    far = GLabel("A long time ago in a galaxy far, \nfar away...")
    far.color = "blue"
    far.font = "-20"
    w.add(far, x=w.width / 2 - far.width / 2 + 60, y=w.height / 2)
    pause(1200)
    w.remove(far)
    main_title = GLabel("STAR\nWARS")
    main_title.color = "yellow"
    for i in range(20):
        size = (160 // (int(i) + 1))
        size = -size
        main_title.font = str(size)
        w.add(main_title, x=w.width / 2 - main_title.width / 4, y=w.height / 2)
        pause(FRAME_RATE * 6)
        w.remove(main_title)
    opening_crawl = GLabel("It   is   a   period  of   civil   war\n"
                           "Princess Leia races home abroad\n"
                           "her   spaceship   but   was   later\n"
                           "captured   by   Empires's  agents\n"
                           "Use  your  lightsaber  to destroy\n"
                           "the   force   field   to   save  the\n"
                           "princess")
    opening_crawl.color = "yellow"
    opening_crawl.font = "-15"
    w.add(opening_crawl, x=w.width / 2 - 130, y=w.height + 1)
    for i in range(50):
        opening_crawl.move(0, -10)
        pause(FRAME_RATE * 6)
    w.remove(black_cover)
    w.remove(opening_crawl)
示例#2
0
def main():
    graphics = BreakoutGraphics()

    dx = graphics.get_x_speed()
    dy = graphics.get_y_speed()

    lives = NUM_LIVES

    # Add animation loop here!
    while True:
        pause(FRAME_RATE)

        if graphics.start and lives > 0 and graphics.count > 0:
            graphics.ball.move(dx, dy)

            if graphics.ball.y >= graphics.window.height:
                lives -= 1
                graphics.reset_ball()
            else:
                # ball touches paddle or bricks
                if graphics.get_obj():
                    if graphics.ball.y < graphics.window.height / 2:  # bricks
                        dy = -dy
                    else:  # paddle
                        if dy > 0:  # ensure won’t stick on the paddle
                            dy = -dy
                # ball touches the window
                if graphics.ball.x <= 0 or graphics.ball.x + graphics.ball.width >= graphics.window.width:
                    dx = -dx
                if graphics.ball.y <= 0:
                    dy = -dy

            # update ball velocity
            if graphics.score > 0 and graphics.score % 200 == 0:
                dy += 0.1
                graphics.update_dy(dy)

        elif lives <= 0:
            # game over
            label = GLabel('Game Over', x=0, y=graphics.window.height / 2)
            label.font = '-48-bold'
            label.color = 'red'
            graphics.window.add(label)
            graphics.window.remove(graphics.ball)
            break

        elif graphics.count <= 0:
            # you win
            label = GLabel('You Win!!!', x=0, y=graphics.window.height / 2)
            label.font = '-48-bold'
            label.color = 'forestgreen'
            graphics.window.add(label)
            graphics.window.remove(graphics.ball)
            break

    # label animation
    label_dx = 1
    while label.x <= graphics.window.width / 2 - 120:
        label.move(label_dx, 0)
        pause(10)
示例#3
0
def main():
    graphics = BreakoutGraphics()

    dx = graphics.get_x_speed()
    dy = graphics.get_y_speed()

    lives = NUM_LIVES

    # Add animation loop here!
    while True:
        pause(FRAME_RATE)
        if graphics.start and lives > 0 and graphics.count > 0:
            graphics.ball.move(dx, dy)

            if graphics.ball.y + graphics.ball.height >= graphics.window.height:
                lives -= 1
                graphics.reset_ball()
            else:
                if graphics.get_obj():
                    dy = -dy
                if graphics.ball.x <= 0 or graphics.ball.x + graphics.ball.width >= graphics.window.width:
                    dx = -dx
                if graphics.ball.y <= 0:
                    dy = -dy

        elif lives <= 0:
            # game over
            label = GLabel('Game Over', x=0, y=graphics.window.height / 2)
            label.font = '-48-bold'
            label.color = 'red'
            graphics.window.add(label)
            graphics.window.remove(graphics.ball)
            break
        elif graphics.count <= 0:
            # you win
            label = GLabel('You Win!!!', x=0, y=graphics.window.height / 2)
            label.font = '-48-bold'
            label.color = 'forestgreen'
            graphics.window.add(label)
            graphics.window.remove(graphics.ball)
            break

    # move the label
    dx = 1
    while label.x <= graphics.window.width / 2 - 120:
        label.move(dx, 0)
        pause(10)
示例#4
0
 def the_end(self):
     num = 0
     vx = 1
     vy = 0
     if self.score <= 4:
         gameover = GLabel('Game Over')
         gameover.color = 'goldenrod'
         gameover.font = 'Courier-35-bold'
         self.window.add(gameover, x=80, y=400)
         while True:
             pause(1000 / 120)
             if num == 10:
                 break
             else:
                 gameover.move(vx, vy)
                 if gameover.x + gameover.width >= self.window.width or gameover.x == 0:
                     vx = -vx
                     num += 1
     elif self.score >= 5:
         goodgame = GLabel('Congratulation!')
         goodgame.color = 'red'
         goodgame.font = 'Courier-30-bold'
         self.window.add(goodgame, x=30, y=400)
         while True:
             pause(1000 / 120)
             if num == 100:
                 break
             else:
                 goodgame.move(vx, vy)
                 if 0 <= goodgame.x <= 20:
                     goodgame.color = 'red'
                 elif 20 <= goodgame.x <= 40:
                     goodgame.color = 'orange'
                 elif 40 <= goodgame.x <= 60:
                     goodgame.color = 'yellow'
                 elif 60 <= goodgame.x <= 80:
                     goodgame.color = 'green'
                 elif 80 <= goodgame.x <= 100:
                     goodgame.color = 'blue'
                 elif 100 <= goodgame.x <= 109:
                     goodgame.color = 'purple'
                 if goodgame.x + goodgame.width >= self.window.width or goodgame.x == 0:
                     vx = -vx
                     num += 1
                     print(goodgame.x)
示例#5
0
 def pilot(self):
     # Instructions
     line_1 = GLabel('Welcome to my Breakout Game!')
     line_1.font = 'Courier-12-bold'
     line_2 = GLabel('Your mission is to get the highest score.')
     line_2.font = 'Courier-12-bold'
     line_3 = GLabel('No matter how you get it >.^')
     line_3.font = 'Courier-12-bold'
     self.window.add(line_1,
                     x=(self.window.width - line_1.width) / 2,
                     y=self.window.height - 40)
     self.window.add(line_2,
                     x=(self.window.width - line_2.width) / 2,
                     y=self.window.height - 20)
     self.window.add(line_3,
                     x=(self.window.width - line_3.width) / 2,
                     y=self.window.height)
     # Animation
     while True:
         # Update
         line_1.move(0, -5)
         line_2.move(0, -5)
         line_3.move(0, -5)
         # Check
         if line_1.y <= self.window.height / 2:
             break
         # Pause
         pause(100)
     pause(1000)
     self.window.remove(line_1)
     self.window.remove(line_2)
     self.window.remove(line_3)
     pause(1000)
示例#6
0
def main():
    """
    it shows the animation of a guinea pig with zentangle pattern, and a label will show on the top of window
    """
    #background

    background = GRect(600, 600)
    background.filled = True
    window.add(background)


    #zentangle

    for i in range(0,600,30):
        line = GLine(i,0,600,600)
        window.add(line)
        line.color = 'white'
        pause(10)

    for j in range(0,600,30):
        line = GLine(600,j,0,600)
        window.add(line)
        line.color = 'wheat'
        pause(10)

    for k in range(0, 600, 30):
        line = GLine(600-k, 600, 0, 0)
        window.add(line)
        line.color = 'whitesmoke'
        pause(10)

    for l in range(0, 600, 30):
        line = GLine(0, 600-l, 600, 0)
        window.add(line)
        line.color = 'grey'
        pause(10)



    for m in range(0,300, 10):
        circle = GOval(m, m, x=random.randrange(0, window.width), y=random.randrange(0, window.width))
        window.add(circle)
        circle.color = 'red'
        pause(10)

    for n in range(0, 200, 40):
        circle = GOval(n, n, x=random.randrange(0, window.width), y=random.randrange(0, window.width))
        window.add(circle)
        circle.color = 'orange'
        pause(10)

    for o in range(100,300, 35):
        circle = GOval(o, o, x=random.randrange(0, window.width), y=random.randrange(0, window.width))
        window.add(circle)
        circle.color = 'yellow'
        pause(10)

    for p in range(50,200, 25):
        circle = GOval(p, p, x=random.randrange(0, window.width), y=random.randrange(0, window.width))
        window.add(circle)
        circle.color = 'lime'
        pause(10)

    for q in range(0,100, 15):
        circle = GOval(q, q, x=random.randrange(0, window.width), y=random.randrange(0, window.width))
        window.add(circle)
        circle.color = 'lightblue'
        pause(10)

    for r in range(300, 500, 30):
        circle = GOval(r, r, x=random.randrange(0, window.width), y=random.randrange(0, window.width))
        window.add(circle)
        circle.color = 'navy'
        pause(10)

    for s in range(0, 400, 50):
        circle = GOval(s, s, x=random.randrange(0, window.width), y=random.randrange(0, window.width))
        window.add(circle)
        circle.color = 'purple'
        pause(10)


    #face
    face = GPolygon()
    face.add_vertex((255, 250))
    face.add_vertex((345, 250))
    face.add_vertex((355, 340))
    face.add_vertex((245, 340))

    forehead = GPolygon()
    forehead.add_vertex((270, 255))
    forehead.add_vertex((330, 255))
    forehead.add_vertex((335, 275))
    forehead.add_vertex((265, 275))

    l_chin = GPolygon()
    l_chin = GPolygon()
    l_chin.add_vertex((250, 310))
    l_chin.add_vertex((300, 305))
    l_chin.add_vertex((300, 340))
    l_chin.add_vertex((247, 340))

    r_chin = GPolygon()
    r_chin = GPolygon()
    r_chin.add_vertex((300, 305))
    r_chin.add_vertex((350, 310))
    r_chin.add_vertex((353, 340))
    r_chin.add_vertex((300, 340))

    nose = GOval(18, 35, x=292, y=290)

    l_eye = GOval(15, 17, x=280, y=285)
    r_eye = GOval(15, 17, x=310, y=285)

    l_foot = GOval(20, 30, x=233, y=315)
    r_foot = GOval(20, 30, x=348, y=315)

    l_ear = GOval(25, 15, x=230, y=265)
    r_ear = GOval(25, 15, x=345, y=265)

    mouse1 = GLine(300, 340, 300, 333)
    mouse2 = GLine(300, 333, 293, 323)
    mouse3 = GLine(300, 333, 307, 323)

    window.add(l_foot)
    l_foot.filled = True
    l_foot.fill_color = 'lightsalmon'
    l_foot.color = 'lightsalmon'

    window.add(r_foot)
    r_foot.filled = True
    r_foot.fill_color = 'lightsalmon'
    r_foot.color = 'lightsalmon'

    window.add(face)
    face.filled = True
    face.fill_color = 'goldenrod'
    face.color = 'goldenrod'

    window.add(forehead)
    forehead.filled = True
    forehead.fill_color = 'lightyellow'
    forehead.color = 'peachpuff'

    window.add(l_chin)
    l_chin.filled = True
    l_chin.fill_color = 'wheat'
    l_chin.color = 'wheat'

    window.add(r_chin)
    r_chin.filled = True
    r_chin.fill_color = 'wheat'
    r_chin.color = 'wheat'

    window.add(nose)
    nose.filled = True
    nose.fill_color = 'wheat'
    nose.color = 'wheat'

    window.add(mouse1)
    mouse1.color = 'brown'
    window.add(mouse2)
    mouse2.color = 'brown'
    window.add(mouse3)
    mouse3.color = 'brown'

    window.add(l_eye)
    l_eye.filled = True
    window.add(r_eye)
    r_eye.filled = True

    window.add(l_ear)
    l_ear.filled = True
    l_ear.fill_color = 'brown'
    l_ear.color = 'brown'
    window.add(r_ear)
    r_ear.filled = True
    r_ear.fill_color = 'brown'
    r_ear.color = 'brown'


    # words
    label = GLabel('Python is just like Zentangle - impossible to have the same works')
    label.font = 'Courier-10-italic'
    words_frame = GRect(530, 40, x=(window.width - label.width - 10) / 2, y=18)
    label.color = 'navy'

    window.add(words_frame)
    words_frame.filled = True
    words_frame.fill_color = 'lemonchiffon'
    words_frame.color = 'gold'
    window.add(label, x=(window.width - label.width) / 2, y=50)

    vx = 1
    while True:
        label.move(vx, 0)
        words_frame.move(vx, 0)
        if words_frame.x <= 0 or words_frame.x + words_frame.width >= window.width:
            vx = -vx
        pause(DELAY)
示例#7
0
class BreakoutGraphics:

    def __init__(self, ball_radius=BALL_RADIUS, paddle_width=PADDLE_WIDTH,
                 paddle_height=PADDLE_HEIGHT, paddle_offset=PADDLE_OFFSET,
                 brick_rows=BRICK_ROWS, brick_cols=BRICK_COLS,
                 brick_width=BRICK_WIDTH, brick_height=BRICK_HEIGHT,
                 brick_offset=BRICK_OFFSET, brick_spacing=BRICK_SPACING,
                 title='Breakout'):

        self.brick_rows = brick_rows
        self.brick_cols = brick_cols

        # Create a graphical window, with some extra space
        self.window_width = brick_cols * (brick_width + brick_spacing) - brick_spacing
        self.window_height = brick_offset + 3 * (brick_rows * (brick_height + brick_spacing) - brick_spacing)
        self.window = GWindow(width=self.window_width, height=self.window_height, title=title)

        self.ball_radius = BALL_RADIUS
        self.ball = GOval(ball_radius * 2, ball_radius * 2)
        self.ball.filled = 'True'

        # Center a filled ball in the graphical window
        self.window.add(self.ball, x=(self.window.width - self.ball.width) / 2,
                        y=(self.window.height - self.ball.height) / 2)

        # Create a paddle
        self.paddle = GRect(width=paddle_width, height=paddle_height)
        self.paddle.filled = True
        self.paddle_offset = PADDLE_OFFSET
        self.paddle.fill_color = 'black'
        self.window.add(self.paddle, x=(self.window.width - self.paddle.width) / 2,
                        y=self.window.height - paddle_offset)

        # Draw bricks
        for i in range(brick_rows):
            for j in range(brick_cols):
                self.brick = GRect(width=brick_width, height=brick_height)
                self.brick.filled = 'True'
                self.brick.color = 'black'

                self.window.add(self.brick, x=(brick_width * j + brick_spacing * j),
                                y=brick_offset + brick_height * i + brick_spacing * i)

                if (i+j)% 2 == 0:
                    self.brick.fill_color = 'ivory'
                else:
                    self.brick.fill_color = 'black'

        # Create label when user hits 10 balls
        self.half = GLabel("WOW! TEN BRICKS ALREADY! KEEP GOING!")
        self.half.font = '-15'

        # Score cnt
        self.score_cnt = 0
        self.score = GLabel('SCORE:' + str(self.score_cnt))
        self.score.font = 'Helvetica-30-bold'
        self.score.color = 'silver'
        self.vx = 0
        self.vy = 0

        # Life 
        self.life = GLabel('LIVES:')
        self.life.font = 'Helvetica-30'
        self.life.color = 'plum'
        self.life1 = GOval(20, 20)
        self.life1.filled = True
        self.life1.fill_color = 'plum'
        self.life1.color = 'plum'
        self.life2 = GOval(20, 20)
        self.life2.filled = True
        self.life2.fill_color = 'plum'
        self.life2.color = 'plum'
        self.life3 = GOval(20, 20)
        self.life3.filled = True
        self.life3.fill_color = 'plum'
        self.life3.color = 'plum'

        # Default initial velocity for the ball
        self.__dx = 0
        self.__dy = 0
        self.lives = 3
        onmouseclicked(self.start_ball)
        onmousemoved(self.track_paddle)

    def start_ball(self, event):
        if (self.__dx == 0) and (self.__dy == 0) and (not self.lives == 0):
            self.window.add(self.ball, x=(self.window.width - self.ball.width) / 2,
                            y=(self.window.height - self.ball.height) / 2)
            self.ball.fill_color = 'black'
            self.__dx = random.randint(1, MAX_X_SPEED)
            self.__dy = INITIAL_Y_SPEED
            if random.random() > 0.5:
                self.__dx = -self.__dx
            if random.random() > 0.5:
                self.__dy = -self.__dy
        return True

    def track_paddle(self, e):
        self.paddle.x = e.x - self.paddle.width / 2
        # make sure the paddle will always be in the window
        if e.x <= 0:
            self.paddle.x = 0
        elif e.x > self.window.width - self.paddle.width / 2:
            self.paddle.x = self.window.width - self.paddle.width

    def check_wall(self):
        if self.ball.x <= 0 or self.ball.x + self.ball.width > self.window.width:
            self.__dx = -self.__dx

        if self.ball.y <= 0:
            self.__dy = -self.__dy

    def check_pts(self):

        p1 = self.window.get_object_at(self.ball.x, self.ball.y)
        p2 = self.window.get_object_at(self.ball.x, self.ball.y + self.ball_radius * 2)
        p3 = self.window.get_object_at(self.ball.x + self.ball_radius * 2, self.ball.y)
        p4 = self.window.get_object_at(self.ball.x + self.ball_radius * 2,
                                           self.ball.y + self.ball_radius * 2)

        if p2 is not None:
            # determine which item the ball hits
            if self.ball.y > self.window.height/2:
                if self.__dy > 0:
                    self.__dy = -self.__dy
                self.ball.fill_color = 'red'
            else:
                if p2 != self.half and p2 != self.score \
                        and p2 != self.life and p2!=self.life1 and p2!= self.life2 and p2!= self.life3 :
                    self.window.remove(p2)
                    self.score_cnt += 1
                    self.score.text = ("SCORE: " + str(self.score_cnt))
                    self.__dy = -self.__dy
                self.ball.fill_color = 'gold'

        elif p4 is not None:
            if self.ball.y > self.window.height/2:
                if self.__dy > 0:
                    self.__dy = -self.__dy
                self.ball.fill_color = 'red'
            else:
                if p4 != self.half and p4 != self.score \
                        and p4 != self.life and p4!=self.life1 and p4 != self.life2 and p4 != self.life3:
                    self.window.remove(p4)
                    self.score_cnt += 1
                    self.score.text = ("SCORE: " + str(self.score_cnt))
                    self.__dy = -self.__dy
                self.ball.fill_color = 'gold'

        elif p1 is not None:
            if self.ball.y > self.window.height/2:
                if self.__dy > 0:
                    self.__dy = -self.__dy
                self.ball.fill_color = 'red'
            else:
                if p1 != self.half and p1 != self.score \
                        and p1 != self.life and p1 != self.life1 and p1 != self.life2 and p1 != self.life3:
                    self.window.remove(p1)
                    self.score_cnt += 1
                    self.score.text = ("SCORE: " + str(self.score_cnt))
                    self.__dy = -self.__dy
                self.ball.fill_color = 'gold'

        elif p3 is not None:
            if self.ball.y > self.window.height/2:
                if self.__dy > 0:
                    self.__dy = -self.__dy
                self.ball.fill_color = 'red'
            else:
                if p3 != self.half and p3 != self.score \
                        and p3 != self.life and p3 !=self.life1 and p3 != self.life2 and p3 != self.life3:
                    self.window.remove(p3)
                    self.score_cnt += 1
                    self.score.text = ("SCORE: " + str(self.score_cnt))
                    self.__dy = -self.__dy
                self.ball.fill_color = 'gold'

    def score_run(self):
        if self.vx == 0 and self.vy == 0:
            self.vx = 5
            self.vy = 3

        elif (self.score.x <= 0) or (self.score.x + self.score.width >= self.window.width):
            self.vx = -self.vx
            self.score.color = 'salmon'

        elif (self.score.y - self.score.height <= 0) or (self.score.y >= self.window.height)and self.vy > 0:
            self.vy = -self.vy
            self.score.color = 'powderblue'

        self.score.move(self.vx, self.vy)

    def cheer(self):
        # Cheering words
        obj = self.window.get_object_at(x=(self.window.width - self.half.width) / 2,
                                            y=(self.window.height - self.half.height) / 2)
        if obj is None and self.score_cnt == 10:
            self.window.add(self.half, x=(self.window.width - self.half.width) / 2,
                                y=(self.window.height - self.half.height) / 2)

        if self.score_cnt == 15:
            self.window.remove(self.half)





    def get_dx(self):
        return self.__dx

    def get_dy(self):
        return self.__dy

    def set_dx(self, new_speed):
        self.__dx = -self.__dx

    def set_dy(self, new_speed):
        self.__dy = -self.__dy

    def set2_dx(self, new_speed2):
        self.__dx = 0

    def set2_dy(self, new_speed2):
        self.__dy = 0
class BreakoutGraphics:
    def __init__(self,
                 ball_radius=BALL_RADIUS,
                 paddle_width=PADDLE_WIDTH,
                 paddle_height=PADDLE_HEIGHT,
                 paddle_offset=PADDLE_OFFSET,
                 brick_rows=BRICK_ROWS,
                 brick_cols=BRICK_COLS,
                 brick_width=BRICK_WIDTH,
                 brick_height=BRICK_HEIGHT,
                 brick_offset=BRICK_OFFSET,
                 brick_spacing=BRICK_SPACING,
                 title='Breakout'):

        # Create a graphical window, with some extra space.
        self.window_width = brick_cols * (brick_width +
                                          brick_spacing) - brick_spacing
        self.window_height = brick_offset + 3 * (
            brick_rows * (brick_height + brick_spacing) - brick_spacing)
        self.window = GWindow(width=self.window_width,
                              height=self.window_height,
                              title=title)

        # set up the paddle.
        self.paddle_width = paddle_width
        self.paddle_height = paddle_height
        self.paddle = GRect(paddle_width,
                            paddle_height,
                            x=(self.window_width - PADDLE_WIDTH) / 2,
                            y=self.window_height - paddle_offset -
                            paddle_height)
        self.paddle.filled = True
        self.paddle.color = 'slategrey'
        self.paddle.fill_color = 'slategrey'

        # set up a the ball.
        self.ball_radius = ball_radius
        self.ball = GOval(self.ball_radius * 2,
                          self.ball_radius * 2,
                          x=(self.window_width - self.ball_radius * 2) / 2,
                          y=(self.window_height - self.ball_radius * 2) / 2)
        self.ball.filled = True
        self.ball.color = 'crimson'
        self.ball.fill_color = 'crimson'

        # Default initial velocity for the ball.
        self.__dx = random.randint(MIN_X_SPEED, MAX_X_SPEED)
        if random.random() > 0.5:
            self.__dx = -self.__dx
        self.__dy = INITIAL_Y_SPEED

        # Initialize our mouse listeners.
        onmousemoved(self.move_paddle)
        onmouseclicked(self.switch)

        # Control whether the user can start the game
        self.__start = False

        # Determine the lives the user gets
        self.__num_lives = 0

        # Attributes relate to the score
        self.__score = 0
        self.__win_score = BRICK_COLS * BRICK_ROWS * 10
        self.score_sign = GLabel(f'SCORE : {self.__score}')
        self.can_move = False
        self.can_drop = True
        self.reward = 0

        # Attribute relate to live sign
        self.live_2 = GOval(self.ball_radius * 2,
                            self.ball_radius * 2,
                            x=self.window_width - (self.ball_radius * 2 + 8),
                            y=self.window_height - (self.ball_radius * 2 + 8))
        self.live_1 = GOval(self.ball_radius * 2,
                            self.ball_radius * 2,
                            x=self.window_width -
                            (self.ball_radius * 2 + 8) * 2,
                            y=self.window_height - (self.ball_radius * 2 + 8))

        # Attributes relate to extension opening
        self.o_ball = GOval(30, 30, x=(self.window.width - 30) / 2, y=240)
        self.start_button = GLabel('S T A R T')
        self.__enter_game = False

        # Attributes relate to extension 'game over' scene
        self.game_over_w = GLabel('G A M E   O V E R')

        # Attributes relate to rewards
        self.hint_sign = 0
        self.reverse_paddle = False
        self.paddle_adding = False
        self.adding_count = 0

        # To store the mouse event
        self.paddle_x = 0

    def set_game(self):
        """
        This method set up the starting interface for the game.
        Including materials such as: paddle, window, score sign and bricks.
        """
        # Create a paddle.
        self.window.add(self.paddle)

        # Center a filled ball in the graphical window.
        self.window.add(self.ball)

        # Build the score sign
        self.score_sign = GLabel(f'SCORE : {self.__score}')
        self.score_sign.color = 'crimson'
        self.score_sign.font = 'Mamelon-20'
        self.window.add(self.score_sign, x=8, y=self.window.height - 8)

        # Build lives sign
        self.live_2.filled = True
        self.live_2.color = 'crimson'
        self.live_2.fill_color = 'crimson'
        self.window.add(self.live_2)

        self.live_1.filled = True
        self.live_1.color = 'crimson'
        self.live_1.fill_color = 'crimson'
        self.window.add(self.live_1)

        # Draw bricks.
        for i in range(BRICK_ROWS):
            for j in range(BRICK_COLS):
                brick = GRect(BRICK_WIDTH,
                              BRICK_HEIGHT,
                              x=i * (BRICK_WIDTH + BRICK_SPACING),
                              y=BRICK_OFFSET + j *
                              (BRICK_HEIGHT + BRICK_SPACING))
                brick.filled = True
                if j == 0 or j == 1:
                    brick.color = 'darkslategrey'
                    brick.fill_color = 'darkslategrey'
                elif j == 2 or j == 3:
                    brick.color = 'teal'
                    brick.fill_color = 'teal'
                elif j == 4 or j == 5:
                    brick.color = 'cadetblue'
                    brick.fill_color = 'cadetblue'
                elif j == 6 or j == 7:
                    brick.color = 'lightseagreen'
                    brick.fill_color = 'lightseagreen'
                else:
                    brick.color = 'mediumturquoise'
                    brick.fill_color = 'mediumturquoise'
                self.window.add(brick)

    def move_paddle(self, event):
        """
        This method keep mouse event regarding reverse and not reverse situation of the paddle.
        Also, it keeps the paddle within the window .
        :param event: mouse event
        """
        if self.reverse_paddle:
            # reverse paddle movement
            event_x = self.window_width - event.x
        else:
            # Normal paddle movement
            event_x = event.x

        # Keeping the paddle within the window
        if event_x - self.paddle_width / 2 < 0:
            self.paddle.x = 0
        elif event_x + self.paddle_width / 2 > self.window.width:
            self.paddle.x = self.window.width - self.paddle_width

        # Control the paddle when the mouse is in the window
        else:
            self.paddle.x = event_x - self.paddle_width / 2

        # To store the mouse event
        self.paddle_x = self.paddle.x

    def reset_ball(self):
        """
        This method resets the ball at the starting position,
        and will not drop unless the the user clicks.
        """
        self.ball = GOval(self.ball_radius * 2,
                          self.ball_radius * 2,
                          x=(self.window_width - self.ball_radius * 2) / 2,
                          y=(self.window_height - self.ball_radius * 2) / 2)
        self.ball.filled = True
        self.ball.color = 'crimson'
        self.ball.fill_color = 'crimson'
        self.window.add(self.ball)
        self.__start = False

    # getter for the ball's moving speed.
    def get_dx(self):
        return self.__dx

    # getter for the ball's moving speed.
    def get_dy(self):
        return self.__dy

    # getter, see if the ball is ready to be click and fall
    def start(self):
        return self.__start

    # getter, see if the start button in the opening scene is clicked
    def get_enter_game(self):
        return self.__enter_game

    # setter, the user can set up the initial lives.
    def set_num_lives(self, num_lives):
        self.__num_lives = num_lives

    def switch(self, e):
        """
        This method is the switch for 2 purpose.

        1. whether the user can start the game.
        In the start of each round, if user's lives > 0, the switch will set to open,
        the ball will move after the user click the window.

        2. whether the start button in the opening scene is clicked.
        If clicked, set up the game.
        If not, wait for the click.
        """
        if self.__num_lives > 0:
            self.__start = True

        if self.window.get_object_at(e.x, e.y) is self.o_ball or \
                self.window.get_object_at(e.x, e.y) is self.start_button:
            self.__enter_game = True

    # To get the position of the 4 corners of the ball
    def corner_hits(self):
        """
        This method check from corner_1 to corner_4,
        to see if any corner of the ball has encounter obstacles.

        If so, return the method to remove object encountered.
        If not, move on to the next corner.

        :return: method, remove the object on the encountered corner.
        """
        # To get position of each corner of the ball
        corner_1 = self.window.get_object_at(self.ball.x, self.ball.y)
        corner_2 = self.window.get_object_at(
            self.ball.x + 2 * self.ball_radius, self.ball.y)
        corner_3 = self.window.get_object_at(
            self.ball.x, self.ball.y + 2 * self.ball_radius)
        corner_4 = self.window.get_object_at(
            self.ball.x + 2 * self.ball_radius,
            self.ball.y + 2 * self.ball_radius)

        # To check which corner hits things
        if corner_1 is not None:
            return corner_1
        elif corner_2 is not None:
            return corner_2
        elif corner_3 is not None:
            return corner_3
        elif corner_4 is not None:
            return corner_4
        else:
            pass

    # To check whether the ball hits the wall
    def if_hits_walls(self):
        """
        This method checks whether the ball hits the side walls and the the top wall.
        If so, the ball will bounce back.
        """
        # The ball hits the side walls and the the top wall
        if self.ball.x <= 0 or self.ball.x + 2 * self.ball_radius >= self.window.width:
            self.__dx *= -1
        # The ball hits the the top wall
        if self.ball.y <= 0:
            self.__dy *= -1

    # To check what the ball hits
    def if_hits_things(self):
        """
        This method determines what kind of object the ball hits,
        and run the actions after hitting certain objects.
        """
        # The ball hits the paddle
        if self.corner_hits() is self.paddle:
            # bounce back
            if self.__dy >= 0:
                self.__dy *= -1
            else:
                # debug: keep the ball from sticking on the paddle
                pass
            # Clean up the hint sign
            self.window.remove(self.hint_sign)

        # the ball hits other item, pass
        elif self.corner_hits() is self.score_sign or self.corner_hits() is self.hint_sign or self.corner_hits() is self.reward \
                or self.corner_hits() is self.live_2 or self.corner_hits() is self.live_1:
            pass

        # The ball hits the paddle
        elif self.corner_hits() is not None:

            # The thing hit by the ball need to be removed
            self.window.remove(self.corner_hits())

            # Speed up and bounce
            self.__dy *= -1.005
            self.__score += 10

            # Show score
            self.show_score()

            # The reward will dropped everytime the user get 70 more score.
            if self.__score % 70 == 0 and self.can_drop:

                # Choose the dropping x position randomly
                t_x = random.choice(range(1, 10))

                # Set up the reward object
                self.reward = GRect(10,
                                    10,
                                    x=self.window.width * t_x // 10,
                                    y=self.window.height / 3)
                self.reward.filled = True
                self.reward.fill_color = 'darkslateblue'
                self.reward.color = 'darkslateblue'
                self.window.add(self.reward)
                self.can_move = True
        else:
            pass

    def show_score(self):
        """
        This method remove the previous score sign and create a new one.
        """
        self.window.remove(self.score_sign)
        self.score_sign = GLabel(f'SCORE : {self.__score}')
        self.score_sign.color = 'crimson'
        self.score_sign.font = 'Mamelon-20'
        self.window.add(self.score_sign, x=8, y=self.window.height - 8)

    # To check: if the reward is allowed to drop / if it was obtained or missed.
    def test_move(self):
        if self.can_move:
            self.can_drop = False
            self.reward.move(0, 5)

            # The user got the reward
            if self.window.get_object_at(self.reward.x + 7,
                                         self.reward.y + 15) is self.paddle:
                self.window.remove(self.reward)
                self.run_reward()
                self.can_move = False
                self.can_drop = True

            # The user miss the reward -- clean up
            if self.reward.y + 15 >= self.window.height:
                self.window.remove(self.reward)
                self.can_move = False
                self.can_drop = True

    def run_reward(self):
        """
        This method uses random to choose a reward to run randomly.
        Also, it shows a sign for the running reward.

        Possible situation are listed below:
        1. Make the paddle longer
        2. Make the paddle shorter
        3. Reverse the paddle's movement
        4. Speed up the ball
        5. Slow down the ball
        """
        # Choose a reward randomly
        choice = random.choice(range(6))
        self.window.remove(self.hint_sign)

        # paddle width ++
        if choice == 0:
            self.window.remove(self.paddle)
            self.paddle_width += 20
            self.paddle = GRect(self.paddle_width,
                                self.paddle_height,
                                x=self.paddle_x - self.paddle_width / 2,
                                y=self.window_height - PADDLE_OFFSET -
                                self.paddle_height)
            self.build_paddle()
            self.hint_sign = GLabel('ADD UP')
            self.show_hint()

        # paddle width --
        elif choice == 1:
            self.paddle_adding = False
            if self.paddle_width <= 30:
                pass
            else:
                self.window.remove(self.paddle)
                self.paddle_width -= 30
                self.paddle = GRect(self.paddle_width,
                                    self.paddle_height,
                                    x=self.paddle_x - self.paddle_width / 2,
                                    y=self.window_height - PADDLE_OFFSET -
                                    self.paddle_height)
                self.build_paddle()
                self.hint_sign = GLabel('WATCH OUT')
                self.show_hint()

        # Set reverse paddle movement
        elif choice == 2 or choice == 3:
            if self.reverse_paddle:
                self.reverse_paddle = False
                self.hint_sign = GLabel('REVERSE AGAIN')
                self.show_hint()
            else:
                self.reverse_paddle = True
                self.hint_sign = GLabel('REVERSE')
                self.show_hint()

        # Speed up the ball
        elif choice == 4:
            self.__dy *= 1.1
            self.hint_sign = GLabel('SPEED UP')
            self.show_hint()

        # Slow down the ball
        else:
            self.__dy *= 0.9
            self.hint_sign = GLabel('SLOW DOWN')
            self.show_hint()

    def build_paddle(self):
        """
        This methods build up paddle for each reward.
        """
        self.window.add(self.paddle)
        self.paddle.filled = True
        self.paddle.color = 'slategrey'
        self.paddle.fill_color = 'slategrey'

    def show_hint(self):
        """
        This method shows a sign to tell user that clicking can earn rewards
        """
        self.hint_sign.color = 'crimson'
        self.hint_sign.font = 'Mamelon-20'
        self.window.add(self.hint_sign,
                        x=(self.window.width - self.hint_sign.width) / 2,
                        y=self.window_height - PADDLE_OFFSET - PADDLE_HEIGHT -
                        30)

    def if_lose_life(self):
        """
        This method check if the user lost life.
        If so, will reset the ball if there's still lives remain.
        """
        if self.ball.y >= self.window.height:
            self.window.remove(self.ball)
            self.window.remove(self.hint_sign)
            self.__num_lives -= 1

            if self.__num_lives == 2:
                # Build 1 point
                self.window.remove(self.live_1)

            elif self.__num_lives == 1:
                # empty
                self.window.remove(self.live_2)

            # Avoid being too hard for players to get ball with reverse paddle
            self.reverse_paddle = False
            self.__dy = INITIAL_Y_SPEED

            if self.__num_lives > 0:
                # User still has chances
                self.reset_ball()

    # Getter, to check if it's the end of the game (either win or lose)
    def end_game(self):
        if self.__num_lives <= 0 or self.__score >= self.__win_score:
            return True

    # To check if the game is over
    def game_over(self):
        if self.__num_lives <= 0:
            self.__enter_game = False
            return True

    def build_game_over(self):
        """
        This method builds the 'Game Over' scene
        """

        # delete the score
        line = GLine(4, self.window.height - 18, 12 + self.score_sign.width,
                     self.window.height - 18)
        line.color = 'crimson'
        self.window.add(line)

        # Clean up
        self.window.remove(self.reward)
        self.window.remove(self.hint_sign)

        # Build up the 'Game Over' sign
        self.game_over_w.font = "Mamelon-35"
        self.game_over_w.color = 'midnightblue'
        self.window.add(self.game_over_w,
                        x=(self.window.width - self.game_over_w.width) / 2,
                        y=self.window.height / 2)

        # Create the movement of the 'Game Over' sign
        speed = self.__dy
        while True:
            self.game_over_w.move(0, speed)
            speed += 0.5
            if self.game_over_w.y >= self.window.height * 2 // 3:
                speed *= -0.7
            pause(10)
        # The sign will end with a shaking animation.

    # To check if the user won the game
    def win_game(self):
        if self.__score >= self.__win_score:
            return True

    def build_win(self):
        """
        This method builds the 'Winning' scene
        """
        win_sign_1 = GLabel('S A V A G E')
        win_sign_1.font = 'Mamelon-40'
        win_sign_1.color = 'mediumturquoise'
        win_sign_2 = GLabel('S A V A G E')
        win_sign_2.font = 'Mamelon-40'
        win_sign_2.color = 'mediumturquoise'
        win_sign_3 = GLabel('S A V A G E')
        win_sign_3.font = 'Mamelon-40'
        win_sign_3.color = 'mediumturquoise'

        # To create the flashing animation
        for i in range(12):
            if i % 2 != 0:
                self.window.add(win_sign_1,
                                x=(self.window.width - win_sign_1.width) / 2,
                                y=(self.window.height - win_sign_1.height) / 2)
                self.window.add(
                    win_sign_2,
                    x=(self.window.width - win_sign_2.width) / 2,
                    y=(self.window.height - win_sign_2.height) / 2 + 50)
                self.window.add(
                    win_sign_3,
                    x=(self.window.width - win_sign_3.width) / 2,
                    y=(self.window.height - win_sign_3.height) / 2 + 100)
            else:
                self.window.remove(win_sign_1)
                self.window.remove(win_sign_2)
                self.window.remove(win_sign_3)

            pause(100)

        self.fire_work()

    def fire_work(self):
        """
        This method creates a firework animation.
        """

        # Numbers of the firework
        for i in range(10):
            f_x = random.randint(self.window.width // 8,
                                 self.window.width * 7 // 8)
            f_y = random.randint(self.window.height // 10,
                                 self.window.height * 9 // 10)
            size = random.randint(4, 7)

            # The size of the firework
            for j in range(size):
                fire = GOval(10 + 20 * j,
                             10 + 20 * j,
                             x=f_x - 10 * j,
                             y=f_y - 10 * j)

                # Choose color randomly
                fire.color = self.choose_color()
                self.window.add(fire)
                pause(100)

                self.window.remove(fire)

            pause(500)

    @staticmethod
    def choose_color():
        """
        This method help choose the color for each circle of the firework randomly
        """
        num = random.choice(range(6))
        if num == 0:
            return "crimson"
        elif num == 1:
            return "midnightblue"
        elif num == 2:
            return "limegreen"
        elif num == 3:
            return "cyan"
        elif num == 4:
            return 'darkviolet'
        else:
            return "gold"

    def window_clear(self):
        """
        This method clean up the whole window after the opening scene is over.
        """
        self.window.clear()

    def set_opening(self):
        """
        This method set up the whole opening scene.
        """

        # To create the tube
        start_button_1 = GRect(60, 211, x=(self.window.width - 60) / 2, y=-1)
        start_button_1.color = 'slategrey'
        start_button_1.filled = True
        start_button_1.fill_color = 'slategrey'
        start_button_2 = GRect(50, 206, x=(self.window.width - 50) / 2)
        start_button_2.color = 'gainsboro'
        start_button_2.filled = True
        start_button_2.fill_color = 'gainsboro'
        self.window.add(start_button_1)
        self.window.add(start_button_2)
        head = GPolygon()
        head.add_vertex(((self.window.width - 60) / 2, 210))
        head.add_vertex(((self.window.width - 60) / 2 + 60, 210))
        head.add_vertex(((self.window.width - 60) / 2 + 60 + 20, 240))
        head.add_vertex(((self.window.width - 60) / 2 - 20, 240))
        head.color = 'slategrey'
        head.filled = True
        head.fill_color = 'slategrey'
        self.window.add(head)

        # Loading animation
        for i in range(10):
            load = GRect(40,
                         15,
                         x=(self.window.width - 60) / 2 + 10,
                         y=5 + 20 * i)
            load.filled = 'True'
            load.color = 'slategrey'
            load.fill_color = 'slategrey'
            self.window.add(load)
            pause(100)

        # Bouncing ball
        self.o_ball.filled = 'True'
        self.o_ball.color = 'crimson'
        self.o_ball.fill_color = 'crimson'
        self.window.add(self.o_ball)
        ball_vy = 5
        count = 0
        while True:
            self.o_ball.move(0, ball_vy)
            ball_vy += 1
            if self.o_ball.y + 30 >= self.window.height:
                ball_vy *= -0.9
                count += 1
            if count == 5 and ball_vy >= 0:
                break
            pause(10)
        self.window.remove(self.o_ball)

        # Blowing balloon animation
        for i in range(55):
            self.o_ball = GOval(30 + i,
                                30 + i,
                                x=(self.window.width - 30 + i) / 2 - i,
                                y=415 - i)
            self.o_ball.filled = 'True'
            self.o_ball.color = 'crimson'
            self.o_ball.fill_color = 'crimson'
            self.window.add(self.o_ball)
            pause(7)

        # Flashing start sign animation
        for i in range(10):
            self.start_button.font = 'Mamelon-20'
            if i % 2 == 0:
                self.start_button.color = 'crimson'
            else:
                self.start_button.color = 'snow'
            self.window.add(self.o_ball)
            self.window.add(self.start_button,
                            x=(self.window.width - 64) / 2,
                            y=413)
            pause(100)

        # Show the rules
        rule_1 = GLabel('3 LIVES.')
        rule_1.color = 'darkslategrey'
        rule_1.font = 'Mamelon-20'
        rule_2 = GLabel("CATCH '    ' FOR RANDOM EFFECTS.")
        rule_2.color = 'darkslategrey'
        rule_2.font = 'Mamelon-20'
        rule_3 = GLabel('SCORE 1000 ---> FIREWORKS.')
        rule_3.color = 'crimson'
        rule_3.font = 'Mamelon-20'
        square = GRect(10,
                       10,
                       x=self.window.width / 10 + 63,
                       y=self.window.height * 4 // 5 + 10)
        square.filled = True
        square.fill_color = 'darkslateblue'
        square.color = 'darkslateblue'
        self.window.add(square)
        self.window.add(rule_1,
                        x=self.window.width / 10,
                        y=self.window.height * 4 // 5)
        self.window.add(rule_2,
                        x=self.window.width / 10,
                        y=self.window.height * 4 // 5 + 25)
        self.window.add(rule_3,
                        x=self.window.width / 10,
                        y=self.window.height * 4 // 5 + 50)