コード例 #1
0
def main():
    """
    This program simulates a bouncing ball at (START_X, START_Y)
    that has VX as x velocity and 0 as y velocity. Each bounce reduces
    y velocity to REDUCE of itself.
    """
    global times,switch,VY
    ball=GOval(SIZE,SIZE,x=START_X,y=START_Y)
    ball.filled= True
    ball.fill_color='black'
    window.add(ball)
    switch = False
    onmouseclicked(turn_on)
    while True:
        pause(DELAY)
        if switch==True:
            VY+=GRAVITY
            ball.move(VX,VY)
            pause(DELAY)
            if ball.y>window.height:
                VY=-REDUCE*VY
            if ball.x>window.width:
                ball.x=START_X
                ball.y=START_Y
                times +=1
            if times>=3:
                break
        else:
            pass
コード例 #2
0
def bouncing(m):
    global START_X, START_Y, VX, GRAVITY, DELAY, click, Time
    if Time > 0:
        # remove the ball at START_X and START_Y
        window.remove(ball)
        while click is True:  # The ball will not be influenced by click as moving
            # creating the ball at the next moving place
            ball2 = GOval(SIZE, SIZE, x=START_X + VX, y=START_Y + GRAVITY)
            ball2.filled = True
            window.add(ball2)
            # the primary down speed
            gravity = 0
            while True:  # the process of moving
                click = False
                gravity = gravity + GRAVITY
                ball2.move(VX, gravity)
                if ball2.y >= window.height:
                    gravity = -gravity
                    gravity = gravity * REDUCE
                    ball2.move(VX, gravity)
                pause(DELAY)
                if ball2.x > window.width:
                    break
            # back to the primary place
            window.add(ball)
            # count the time
            Time -= 1
        click = True
コード例 #3
0
def move_function(m):
    global life, switch  # use the variables on the upper side of def main()
    while life > 0 and switch == 1:  # the condition to determine whether the ball can move or not
        original_ball = window.get_object_at(
            x=START_X + SIZE / 2,
            y=START_Y + SIZE / 2)  # select the ball at the original position
        window.remove(
            original_ball)  # remove the ball at the original position
        life -= 1  # life number minus one
        switch *= -1  # switch turns off, which let user not operate during the ball moving
        ball = GOval(SIZE, SIZE, x=START_X,
                     y=START_Y)  # create the ball that will move later
        ball.filled = True  # fill the ball with black color
        window.add(ball)  # put the ball that will move later on the window
        x_speed = VX  # control the speed of the ball at x direction
        y_speed = 0  # control the speed of the ball at y direction
        height = window.height - START_Y  # the height of the ball at the original position
        while True:
            y_speed += GRAVITY  # speed at y direction will be changed due to the gravity
            height *= REDUCE  # reflecting height will decrease when the ball touches to the ground
            ball.move(x_speed,
                      y_speed)  # give the ball the speeds at x and y direction
            pause(
                DELAY
            )  # give a delay time that human can see the moving of the ball
            if ball.y >= (
                    window.height - SIZE
            ) or ball.y <= height:  # the condition that ball will reflect
                y_speed = -1 * y_speed  # the speed of y direction will be changed at every reflection
            if ball.x >= window.width:  # if the ball moves out of the window.width, it will stop
                window.add(
                    ball, x=START_X, y=START_Y
                )  # put a ball on the original position that will move next time
                switch *= -1  # turn on the switch that user can operate
                break
        if switch == 1:  # break the while loop and ready for the next move (next mouse click)
            break
コード例 #4
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.
        window_width = brick_cols * (brick_width +
                                     brick_spacing) - brick_spacing
        window_height = brick_offset + 2.7 * (brick_rows *
                                              (brick_height + brick_spacing) -
                                              brick_spacing)
        self.window = GWindow(width=window_width,
                              height=window_height,
                              title=title)

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

        # Center a filled ball in the graphical window.
        self.ball = GOval(ball_radius * 2, ball_radius * 2)
        self.ball.color = 'navy'
        self.ball.filled = True
        self.ball.fill_color = 'navy'
        self.window.add(self.ball, (self.window.width - self.ball.width) / 2,
                        (self.window.height - self.ball.height) / 2 + 50)

        # a list dynamically stores four detecting points of the ball
        self.ball_boundary = []

        # Default initial velocity for the ball.
        self.__dx = random.randint(3, MAX_X_SPEED)
        self.__dy = INITIAL_Y_SPEED

        # Initialize our mouse listeners.
        self.mouse_click = False
        onmouseclicked(self.start_game)

        # check accessibility
        self.is_game_over = False

        # total numbers of bricks
        self.total_bricks = brick_rows * brick_cols

        # bricks storing box
        self.bricks_box = []

        # create a list to store random number, if the same number of brick be removed, a magic accessories will appear.
        self.accessories_number = []

        # create a list to store accessories.
        self.accessories_box = {}

        # generate accessories
        self.blue_acc = GRect(0, 0)

        # set a score board
        self.score = 0
        self.score_board_label = GLabel(f'scores:{self.score}')

        # create a heart icon and a list to store these icons.
        # self.heart_point = [(7.5, 15), (0, 5), (3.75, 0), (7.5, 3), (11.25, 0), (15, 5), (7.5, 15)]
        self.heart_icon_box = []

        # give result label to present end of game
        self.result_label = GLabel('Game Over or You Win')

    def dx_getter(self):
        print(f'this is dx value: {self.__dx}.')

    def dy_getter(self):
        print(f'this is dy value: {self.__dy}.')

    def set_velocity(self):
        self.__dx = random.randint(1, MAX_X_SPEED)
        self.__dy = INITIAL_Y_SPEED
        if random.random() > 0.5:
            self.__dx = -self.__dx

    def start_game(self, m):
        """
        The game will triggered by this method once player click the mouse.
        :param m: mouse position in (x,y) expression.
        """
        if not self.is_game_over:
            if self.mouse_click:
                print('Game already start.')
            else:
                self.mouse_click = True
                print('Game started')
                onmousemoved(self.__paddle_move)
        else:
            print('There\'s no chance left')

    def __paddle_move(self, m):
        """
        This method will listen to mouse click, making paddle's position always align to mouse position.
        :param m: mouse position in (x,y) expression.
        """
        if self.mouse_click:
            self.paddle.x = m.x - self.paddle.width / 2
            if self.paddle.x < 0:
                self.paddle.x = 0
            elif self.paddle.x > self.window.width - self.paddle.width:
                self.paddle.x = self.window.width - self.paddle.width

    def ball_move(self, ball_radius=BALL_RADIUS):
        self.ball.move(self.__dx, self.__dy)

        if self.ball.x < 0:  # right and left boundary of window
            self.ball.x = 0
            self.__dx = -self.__dx
        elif self.ball.x > self.window.width - ball_radius * 2:  # left boundary of window
            self.ball.x = self.window.width - ball_radius * 2
            self.__dx = -self.__dx

        elif self.ball.y < 0:  # top boundary of window
            self.ball.y = 0
            self.__dy = -self.__dy

        self.__ball_detect_obj()

    def __ball_detect_obj(
        self,
        ball_radius=BALL_RADIUS,
        brick_width=BRICK_WIDTH,
        brick_offset=BRICK_OFFSET,
        brick_spacing=BRICK_SPACING,
    ):
        """
       The method will detects object around the ball, once it detects a brick, the brick will be removed.
       Also, depending on the color of brick removed, different accelerate velocity will be adding to the ball.
        """

        self.ball_boundary = [(self.ball.x, self.ball.y),
                              (self.ball.x + ball_radius * 2, self.ball.y),
                              (self.ball.x, self.ball.y + ball_radius * 2),
                              (self.ball.x + ball_radius * 2,
                               self.ball.y + ball_radius * 2)]

        for i in range(len(self.ball_boundary)):

            my_obj = self.window.get_object_at(self.ball_boundary[i][0],
                                               self.ball_boundary[i][1])

            if my_obj in self.bricks_box:  # has detected bricks

                if self.bricks_box.index(
                        my_obj
                ) in self.accessories_number:  # the index of the brick equals accessories number, blue or red blocks will be generated.

                    if self.accessories_number.index(
                            self.bricks_box.index(
                                my_obj)) % 2 == 0:  # create blue accessories
                        self.blue_acc = GRect(15, 15)
                        self.blue_acc.filled = True
                        self.blue_acc.fill_color = 'navy'
                        self.accessories_box[self.blue_acc] = 'navy'
                        self.window.add(self.blue_acc,
                                        (my_obj.x + my_obj.width / 2),
                                        (my_obj.y + my_obj.height / 2))

                    else:  # create blue accessories
                        self.red_acc = GRect(15, 15)
                        self.red_acc.filled = True
                        self.red_acc.fill_color = 'red'
                        self.accessories_box[self.red_acc] = 'red'
                        self.window.add(self.red_acc,
                                        (my_obj.x + my_obj.width / 2),
                                        (my_obj.y + my_obj.height / 2))

                self.__dy = -self.__dy
                self.window.remove(my_obj)
                self.total_bricks -= 1

                if 80 <= self.bricks_box.index(my_obj):
                    self.__dy *= random.uniform(1.006, 1.02)
                    self.__dx *= random.uniform(1.006, 1.02)
                    self.score += 1
                elif 50 <= self.bricks_box.index(my_obj) < 80:
                    self.__dy *= random.uniform(1.004, 1.01)
                    self.__dx *= random.uniform(1.004, 1.01)
                    self.score += 3
                elif 20 <= self.bricks_box.index(my_obj) < 50:
                    self.__dy *= random.uniform(1.001, 1.006)
                    self.__dx *= random.uniform(1.001, 1.006)
                    self.score += 5
                elif 0 <= self.bricks_box.index(my_obj) < 20:
                    self.__dy *= random.uniform(1.001, 1.003)
                    self.__dx *= random.uniform(1.001, 1.003)
                    self.score += 10

                self.score_board_label.text = f'scores:{self.score}'
                self.window.add(self.score_board_label,
                                brick_width + brick_spacing, brick_offset - 15)
                return

            elif my_obj is self.paddle:  # has detected the paddle
                self.__dy = -self.__dy
                self.ball.y = my_obj.y - ball_radius * 2  # To avoid ball sticking on paddle by reset y-position of the ball.
                return

    def accessory_move(self):
        for key, value in list(self.accessories_box.items()):

            key.move(2 * self.__dx / abs(self.__dx),
                     random.randint(3, 8))  # accessory blocks move down.

            obj = self.window.get_object_at((key.x + key.width / 2),
                                            (key.y + key.height + 1))

            if obj is self.paddle:

                if value == 'navy':  # when paddle get blue block, paddle width increased.
                    self.paddle.width *= 1.4
                    if self.paddle.width > self.window.width * 0.8:
                        self.paddle.width = self.window.width * 0.8

                else:  # when paddle get red block, paddle width cut back.
                    self.paddle.width *= 0.5
                    if self.paddle.width < 50:
                        self.paddle.width = 50

                self.window.remove(key)
                del self.accessories_box[
                    key]  # delete key value pair after the block reaches paddle.
                self.window.remove(self.paddle)
                self.window.add(self.paddle, self.paddle.x,
                                self.paddle.y)  # renew paddle width to screen.

            if key.y > self.window.height:  # It should be removed if accessory block didn't caught by paddle.
                self.window.remove(key)
                del self.accessories_box[key]

    def reset_ball_paddle(self, paddle_offset=PADDLE_OFFSET):
        """
        When ball is out of button range, the method will reset ball and paddle's position and clear accessories.
        :param paddle_offset:
        """
        if self.ball.y > self.window.height:
            print('reset ball and paddle.')
            self.mouse_click = False  # reset mouse state.

            self.ball.x = (self.window.width - self.ball.width
                           ) / 2  # reset the x-position of ball.
            self.ball.y = (self.window.height - self.ball.height
                           ) / 2  # reset the y-position of ball.

            self.paddle.x = (self.window.width - self.paddle.width
                             ) / 2  # reset the x-position of paddle.
            self.paddle.y = self.window.height - paddle_offset  # reset the y-position of paddle.

            for i in self.accessories_box:  # clear all accessories on the window.
                self.window.remove(i)
            self.accessories_box.clear()

    def draw_bricks(self,
                    brick_width=BRICK_WIDTH,
                    brick_height=BRICK_HEIGHT,
                    brick_offset=BRICK_OFFSET,
                    brick_spacing=BRICK_SPACING):
        """
        When player enter game page, this method called by main function, it will displays bricks from left top corner until
        all bricks displayed. It also give bricks different colors depends on which row the brick exactly occupy. Moreover,
        at the moment brick generated, it will be store in list in order to be used later.
        """
        for i in range(12):
            for j in range(10):
                brick = GRect(brick_width,
                              brick_height,
                              x=(brick_width + brick_spacing) * j,
                              y=brick_offset +
                              (brick_height + brick_spacing) * i)
                brick.filled = True
                if i < 2:
                    brick.fill_color = '#204051'
                    self.bricks_box.append(brick)
                    self.window.add(brick)
                elif 2 <= i < 5:
                    brick.fill_color = '#3b6978'
                    self.bricks_box.append(brick)
                    self.window.add(brick)
                elif 5 <= i < 8:
                    brick.fill_color = '#84a9ac'
                    self.bricks_box.append(brick)
                    self.window.add(brick)
                elif 8 <= i < 12:
                    brick.fill_color = '#e4e3e3'
                    self.bricks_box.append(brick)
                    self.window.add(brick)

    def add_score_board(
        self,
        brick_width=BRICK_WIDTH,
        brick_offset=BRICK_OFFSET,
        brick_spacing=BRICK_SPACING,
    ):
        """
        Setting a score board on to left-top screen and align to second column.
        """
        self.score_board_label.font = '-15'
        self.window.add(self.score_board_label, brick_width + brick_spacing,
                        brick_offset - 15)

    def add_accessories(self, num):
        """
        This method randomly chose numbers between 0 to numbers of total bricks, and each numbers will not be repeated.
        :param num: total number of accessories.
        :return: return self until number of list - self.accessories_number - equals to num.
        """
        if len(self.accessories_number) < num <= len(self.bricks_box):
            for i in range(num - len(self.accessories_number)):
                random_number = random.randint(0, len(self.bricks_box))
                if not random_number in self.accessories_number:
                    self.accessories_number.append(random_number)

            return self.add_accessories(num)
        else:
            return

    def show_result_label(self):
        """
        This method shows game result when game finished, it depends on if the player clears all bricks in three game times.
        """
        if self.is_game_over:
            self.result_label.text = 'Game Over'
            self.result_label.font = '-40'
            self.window.add(self.result_label,
                            (self.window.width - self.result_label.width) / 2,
                            (self.window.height - self.result_label.height) *
                            3 / 4)
        else:
            self.result_label.text = 'You Win'
            self.result_label.color = 'red'
            self.result_label.font = '-40'
            self.window.add(self.result_label,
                            (self.window.width - self.result_label.width) / 2,
                            (self.window.height - self.result_label.height) /
                            2)

    def draw_heart_icon(self):
        """
        To represent how many NUM_LIVES left onto screen.
        P.S: I am trying to use GPolygon to create heart shape but it seems to conflict to windows.get_obj_at method.
        """
        self.heart_shape = GOval(15, 15)
        self.heart_shape.color = 'lightgray'
        self.heart_shape.filled = True
        self.heart_shape.fill_color = 'pink'
        self.heart_icon_box.append(self.heart_shape)
        return self.heart_shape
コード例 #5
0
ファイル: breakoutgraphics.py プロジェクト: egsui/sc-projects
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.
        window_width = brick_cols * (brick_width +
                                     brick_spacing) - brick_spacing
        window_height = brick_offset + 3 * (brick_rows *
                                            (brick_height + brick_spacing) -
                                            brick_spacing)
        self.__window = GWindow(width=window_width,
                                height=window_height,
                                title=title)

        # Switch controls whether the game starts. If True, start the game.
        self.switch = False

        # Greeting Page involves: bg as background / wd1 as welcome words / wd2 as start bottom
        #                       / button as the background of the start button.
        self.__grt_bg = GRect(self.__window.width, self.__window.height)
        self.__grt_bg.filled = True
        self.__grt_bg.fill_color = 'white'
        self.__grt_bg.color = 'white'

        # grt_wd: Welcome to BREAKOUT GAME.
        self.__grt = GLabel('WELCOME\nTO\nBREAKOUT\nGAME')
        self.__grt_wd1 = GLabel('WELCOME\nTO\nBREAKOUT\nGAME',
                                self.__window.width / 3 - self.__grt.width / 2,
                                self.__window.height / 3)
        font_size = 18 * self.__window.width / 445
        self.__grt_wd1.font = 'Courier-18'

        # grt_bottom: black rectangle
        self.__grt_button = GRect(
            100,
            40,
            x=self.__window.width / 3 - self.__grt.width / 2,
            y=self.__window.height * 2 / 3 - self.__grt.height * 2.5)
        self.__grt_button.filled = True

        # grt_wd: START!
        self.__grt_wd2 = GLabel('START!',
                                self.__window.width / 3 - self.__grt.width / 2,
                                self.__window.height * 2 / 3)
        self.__grt_wd2.font = 'Courier-28'
        self.__grt_wd2.color = 'white'

        # Create a paddle to catch the ball and make it bounce.
        self.__paddle = GRect(paddle_width,
                              paddle_height,
                              y=window_height - paddle_offset)
        self.__paddle_offset = paddle_offset
        self.__paddle.filled = True

        # Center a filled ball in the graphical window.
        self.__ball = GOval(ball_radius * 2,
                            ball_radius * 2,
                            x=window_width / 2 - ball_radius,
                            y=window_height / 2 - ball_radius)
        self.__ball.filled = True
        self.__ball_radius = ball_radius

        # Default initial velocity for the ball.
        self.__dx = random.randint(1, MAX_X_SPEED)
        self.__dy = INITIAL_Y_SPEED

        # Initialize our mouse listeners.
        onmousemoved(self.__handle_move)

        # Draw bricks in rows and columns.
        self.__brick_width = brick_width
        self.__brick_height = brick_height
        self.__brick_spacing = brick_spacing
        self.__brick_offset = brick_offset
        self.__brick_rows = brick_rows
        self.__brick_cols = brick_cols
        self.__left_bricks = self.__brick_rows * self.__brick_cols

        # Add the elements(bg / wd1 / button / wd2) to start screen.
        self.__window.add(self.__grt_bg)
        self.__window.add(self.__grt_wd1)
        self.__window.add(self.__grt_button)
        self.__window.add(self.__grt_wd2)

        # Scoreboard records the score.
        self.__scores = 0
        self.__scoreboard = GLabel('Score: ' + str(self.__scores),
                                   x=0,
                                   y=window_height)
        self.__scoreboard.font = 'Courier-18'

        # Click on mouse and start game.
        onmouseclicked(self.start_game)

    # Set up the start screen of the game in this function.
    def start_game(self, event):
        click = self.__window.get_object_at(event.x, event.y)
        b = self.__grt_button
        grt = self.__grt_wd2

        # While the mouse click on the button, start the game.
        if click == b or click == grt and b.x <= event.x <= b.x + b.width and b.y <= event.y <= b.y + b.height:
            self.__window.remove(self.__grt_wd1)  # Remove the greeting words.
            self.__window.remove(self.__grt_wd2)  # Remove the greeting words.
            self.__window.remove(self.__grt_button)  # Remove the start button.
            self.__window.remove(
                self.__grt_bg)  # Remove the greeting background.
            self.switch = True  # Turn on the switch.

            # Set the ball on the start position, in the middle of the window.
            self.__window.add(
                self.__ball,
                x=self.__window.width / 2 - self.__ball.width / 2,
                y=self.__window.height / 2 - self.__ball.height / 2)
            self.__window.add(self.__paddle)  # Add the paddle to the window.
            self.__draw_bricks()  # Add the bricks to the window.
            self.__window.add(
                self.__scoreboard)  # Add the scoreboard to the window.

            pause(300)  # Delay time serving a ball.

    # Set ball at a random position in certain area, below bricks and above paddle.
    def set_ball_position(self):
        self.__ball.x = random.randint(0,
                                       self.__window.width - self.__ball.width)
        self.__ball.y = random.randint(
            self.__brick_offset + self.__brick_rows *
            (self.__brick_height + self.__brick_spacing) -
            self.__brick_spacing, self.__window.height - self.__paddle_offset -
            self.__paddle.height - self.__ball_radius * 2)
        pause(500)  # Delay serving a ball

    # Set the ball in random velocity.
    def set_ball_velocity(self):
        if random.random() > 0.5:
            self.__dx = -self.__dx

    # Determine whether the ball is out of the window.
    # Leave the window from the bottom edge / return boolean (True)
    def ball_out(self):
        if self.__ball.y >= self.__window.height:
            return True

    # If the ball is out of bounds, reset 'position' and 'velocity' of ball, and add it to screen.
    def reset_ball(self):
        self.set_ball_position()
        self.set_ball_velocity()
        self.__window.add(self.__ball)

    # Move ball as animation in velocity of dx and dy.
    def move_ball(self):
        if self.switch:
            self.__ball.move(self.__dx, self.__dy)

    # Check whether the ball collides with walls, then bounce back.
    def wall_collisions(self):
        # Ball collides with up right edge and left edge.
        if self.__ball.x <= 0 or self.__ball.x >= self.__window.width - self.__ball.width:
            self.__dx = -self.__dx

        # Ball collides with upper edge.
        if self.__ball.y <= 0:
            self.__dy = -self.__dy

    # Check whether the ball collides with paddle or bricks, then bounce back.
    def check_for_collisions(self):
        if self.switch:  # if the game starts:
            # Set b1, b2, b3, b4 as four corners of ball.
            b1 = self.__window.get_object_at(self.__ball.x, self.__ball.y)
            b2 = self.__window.get_object_at(
                self.__ball.x + self.__ball_radius * 2, self.__ball.y)
            b3 = self.__window.get_object_at(
                self.__ball.x, self.__ball.y + self.__ball_radius * 2)
            b4 = self.__window.get_object_at(
                self.__ball.x + self.__ball_radius * 2,
                self.__ball.y + self.__ball_radius * 2)

            # Detecting whether four corners of ball collides with:
            if b1 is not None or b2 is not None or b3 is not None or b4 is not None:
                # Collides with paddle.
                if b1 is self.__paddle or b2 is self.__paddle or b3 is self.__paddle or b4 is self.__paddle:
                    # Avoid ball stick to paddle.
                    if self.__ball.y + self.__ball_radius * 2 >= self.__paddle.y:
                        self.__ball.y = self.__paddle.y - self.__ball_radius * 2
                        self.set_ball_velocity()
                        if self.__dy > 0:
                            self.__dy = -self.__dy

                # Collides with scoreboard, then pass.
                elif b1 is self.__scoreboard or b2 is self.__scoreboard or \
                        b3 is self.__scoreboard or b4 is self.__scoreboard:
                    pass

                # Collides with brick / remove the brick / bounce back.
                else:
                    if b1 is not None and b1 is not self.__scoreboard:
                        self.__window.remove(
                            b1)  # Remove a brick while colliding with a brick.
                        self.__left_bricks -= 1  # Minus 1 while colliding with a brick.
                        self.__scores += 10  # Add 10 scores while colliding with a brick.

                    elif b2 is not None and b2 is not self.__scoreboard:
                        self.__window.remove(
                            b2)  # Remove a brick while colliding with a brick.
                        self.__left_bricks -= 1  # Minus 1 while colliding with a brick.
                        self.__scores += 10  # Add 10 scores while colliding with a brick.

                    elif b3 is not None and b3 is not self.__scoreboard:
                        self.__window.remove(
                            b3)  # Remove a brick while colliding with a brick.
                        self.__left_bricks -= 1  # Minus 1 while colliding with a brick.
                        self.__scores += 10  # Add 10 scores while colliding with a brick.

                    elif b4 is not None and b4 is not self.__scoreboard:
                        self.__window.remove(
                            b4)  # Remove a brick while colliding with a brick.
                        self.__left_bricks -= 1  # Minus 1 while colliding with a brick.
                        self.__scores += 10  # Add 10 scores while colliding with a brick.

                    self.__scoreboard.text = 'Score: ' + str(
                        self.__scores)  # Refresh score to scoreboard
                    self.set_ball_velocity()  # Reset x velocity of ball.
                    self.__dy = -self.__dy  # Reset y velocity of ball.

    # Draw bricks.
    def __draw_bricks(self):
        for i in range(self.__brick_rows):
            for j in range(self.__brick_cols):
                br1 = GRect(self.__brick_width, self.__brick_height)
                br1.filled = True

                br1.x = (self.__brick_width + self.__brick_spacing) * j
                br1.y = self.__brick_offset + (self.__brick_height +
                                               self.__brick_spacing) * i

                rows_in_sec = self.__brick_rows / BRICK_SECTION

                if i <= rows_in_sec - 1:  # Section 1
                    br1.fill_color = 'red'
                    br1.color = 'red'
                elif rows_in_sec - 1 < i <= rows_in_sec * 2 - 1:  # Section 2
                    br1.fill_color = 'orange'
                    br1.color = 'orange'
                elif rows_in_sec * 2 - 1 < i <= rows_in_sec * 3 - 1:  # Section 3
                    br1.fill_color = 'yellow'
                    br1.color = 'yellow'
                elif rows_in_sec * 3 - 1 < i <= rows_in_sec * 4 - 1:  # Section 4
                    br1.fill_color = 'green'
                    br1.color = 'green'
                else:  # Section 5 and so on.
                    br1.fill_color = 'lightseagreen'
                    br1.color = 'lightseagreen'

                self.__window.add(br1)

    # Handle the movement of paddle with mouse move.
    def __handle_move(self, event):
        if event.x < self.__paddle.width / 2:
            self.__paddle.x = 0
        elif event.x > self.__window.width - self.__paddle.width / 2:
            self.__paddle.x = self.__window.width - self.__paddle.width
        else:
            self.__paddle.x = event.x - self.__paddle.width / 2

    # If lives <= 0, then game over.
    def game_over(self):
        g_over = GLabel('GAME OVER!')
        g_over.font = 'Courier-25'
        g_over = GLabel('GAME OVER!',
                        self.__window.width / 2 - g_over.width / 2,
                        self.__window.height / 2)
        g_over.font = 'Courier-25'
        self.__window.add(g_over)

    # If the bricks are all removed, you win the game.
    def win_game(self):
        if self.__left_bricks <= 0:
            you_win = GLabel('YOU WIN!')
            you_win.font = 'Courier-25'
            you_win = GLabel('YOU WIN!',
                             self.__window.width / 2 - you_win.width / 2,
                             self.__window.height / 2)
            you_win.font = 'Courier-25'
            self.__window.add(you_win)
            return True
コード例 #6
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)

        # Create a paddle.
        self.pw = paddle_width
        self.ph = paddle_height
        self.paddle = GRect(self.pw,
                            self.ph,
                            x=(self.window_width - self.pw) / 2,
                            y=self.window_height - paddle_offset)
        self.paddle.filled = True
        self.window.add(self.paddle)

        # Center a filled ball in the graphical window.
        self.bra = ball_radius * 2
        self.ball = GOval(self.bra, self.bra)
        self.ball.filled = True
        self.window.add(self.ball, (self.window_width - self.bra) / 2,
                        (self.window_height - self.bra) / 2)

        # Default initial velocity for the ball.
        self.__dx = 0
        self.__dy = 0

        # Initialize our mouse listeners.
        onmousemoved(self.paddle_move)
        onmouseclicked(self.ball_move)

        # Draw bricks.
        self.build_bricks()

        self.score = 0
        self.score_text = GLabel('Score: ' + str(self.score))
        self.score_text.font = '-15-bold'
        self.window.add(self.score_text, 0, self.window_height)

        self.lives_text = GLabel('Lives: ' + str(3))
        self.lives_text.font = '-15-bold'
        self.window.add(self.lives_text, self.window_width - 80,
                        self.window_height)

    def build_bricks(self):
        """

        :return: Build bricks
        """
        self.br = BRICK_ROWS
        self.bc = BRICK_COLS
        for i in range(self.br):
            for j in range(self.bc):
                self.bricks = GRect(BRICK_WIDTH,
                                    BRICK_HEIGHT,
                                    x=i * (BRICK_WIDTH + BRICK_SPACING),
                                    y=j * (BRICK_HEIGHT + BRICK_SPACING))
                self.bricks.filled = True
                if j < 5:
                    self.bricks.fill_color = 'red'
                else:
                    self.bricks.fill_color = 'blue'

                self.window.add(self.bricks)

    def paddle_move(self, e):
        """

        :param e: Mouse position
        :return: Only change the X-axis position of the mouse
        """
        if self.pw / 2 < e.x < self.window_width - self.pw / 2:
            self.paddle.x = e.x - self.paddle.width / 2

    def ball_move(self, e):
        """

        :return: Give the ball x and y speed
        """
        self.__dx = random.randint(1, MAX_X_SPEED)
        self.__dy = INITIAL_Y_SPEED
        if (random.random() > 0.5):
            self.__dx = -(self.__dx)

    def check(self):
        """

        :return: Determine the state of the ball and other objects
        """

        # Avoid the ball beyond the window
        if self.ball.x < 0 or self.ball.x > (self.window_width - self.bra):
            self.__dx *= -1
        if self.ball.y < 0 or self.ball.y > (self.window_height - self.bra):
            self.__dy *= -1

        # Record old scores
        self.old_score = self.score

        # Set four points as the judgment state
        maybe_object1 = self.window.get_object_at(self.ball.x, self.ball.y)
        maybe_object2 = self.window.get_object_at(self.ball.x + self.bra,
                                                  self.ball.y)
        maybe_object3 = self.window.get_object_at(self.ball.x,
                                                  self.ball.y + self.bra)
        maybe_object4 = self.window.get_object_at(self.ball.x + self.bra,
                                                  self.ball.y + self.bra)

        # Judgment points and the status of bricks
        if maybe_object1 is not self.paddle and maybe_object2 is not self.paddle and \
                maybe_object3 is not self.paddle and maybe_object4 is not self.paddle \
                and maybe_object1 is not self.lives_text and maybe_object2 is not self.lives_text \
                and maybe_object3 is not self.lives_text and maybe_object4 is not self.lives_text \
                and maybe_object1 is not self.score_text and maybe_object2 is not self.score_text \
                and maybe_object3 is not self.score_text and maybe_object4 is not self.score_text:

            while True:
                if maybe_object1 is not None or maybe_object2 is not None:
                    if maybe_object1 is not None and maybe_object2 is not None:
                        self.window.remove(maybe_object1)
                        self.window.remove(maybe_object2)
                        self.__dy *= -1
                        if maybe_object1 is maybe_object2:
                            self.score += 1
                        else:
                            self.score += 2
                    else:
                        if maybe_object1 is not None:
                            self.window.remove(maybe_object1)
                            self.__dy *= -1
                            self.score += 1
                        else:
                            self.window.remove(maybe_object2)
                            self.__dy *= -1
                            self.score += 1

                if maybe_object2 is not None or maybe_object4 is not None:
                    if maybe_object2 is not None and maybe_object4 is not None:
                        self.window.remove(maybe_object2)
                        self.window.remove(maybe_object4)
                        self.__dx *= -1
                        if maybe_object2 is maybe_object4:
                            self.score += 1
                        else:
                            self.score += 2
                    else:
                        if maybe_object4 is not None:
                            self.window.remove(maybe_object4)
                            self.__dx *= -1
                            self.score += 1

                if maybe_object1 is not None or maybe_object3 is not None:
                    if maybe_object1 is not None and maybe_object3 is not None:
                        self.window.remove(maybe_object1)
                        self.window.remove(maybe_object3)
                        self.__dx *= -1
                        if maybe_object1 is maybe_object3:
                            self.score += 1
                        else:
                            self.score += 2
                    else:
                        if maybe_object3 is not None:
                            self.window.remove(maybe_object3)
                            self.__dx *= -1
                            self.score += 1
                break

        # Judgment point and paddle state
        if maybe_object3 is self.paddle or maybe_object4 is self.paddle:
            self.__dy *= -1
            self.ball.move(0, -10)

        # If the score changes, change the score on the window
        if self.old_score != self.score:
            self.score_text.text = 'Score: ' + str(self.score)
            self.window.add(self.score_text, 0, self.window_height)

        # After the inspection, the ball moves
        self.ball.move(self.__dx, self.__dy)

    def reset(self):
        """
        Reset the position and speed of the ball
        """
        self.ball.x = (self.window_width - self.bra) / 2
        self.ball.y = (self.window_height - self.bra) / 2
        self.__dx = 0
        self.__dy = 0

    def lose(self):
        """

        :return:(bool)  Check if the ball is under the paddle
        """
        ball_lose = self.ball.y > self.paddle.y + 15

        return ball_lose

    def lives_time(self, lives):
        """

        :param lives: (int) The number of times you can play
        :return: (int) Remaining times
        """
        lives -= 1
        self.lives = lives

        return lives

    def print_lives(self):

        self.lives_text.font = '-15-bold'
        self.lives_text.text = 'Lives: ' + str(self.lives)
        self.window.add(self.lives_text, self.window_width - 80,
                        self.window_height)

    def faster(self, rate):
        '''

        :param rate: (int) Game speed
        :return: (int) Speed of the game after acceleration
        '''
        rate += self.score * 0.01
        return rate

    def end(self):
        """

        :return: End screen
        """
        pic = GRect(self.window_width, self.window_height)
        pic.filled = True
        pic.fill_color = 'gold'
        end_word = GLabel('Your score: ' + str(self.score))
        end_word.font = '-20-bold'
        self.window.add(pic)
        self.window.add(end_word, self.window_width / 4 + 30,
                        self.window_height / 2)
コード例 #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'):
        """
        Parameter settings.
        :param ball_radius: Controls the radius of the ball.
        :param paddle_width: Controls the width of the paddle.
        :param paddle_height: Controls the height of the paddle.
        :param paddle_offset: Controls the y-position of the paddle.
        :param brick_rows: Controls the number of rows of bricks.
        :param brick_cols: Controls the number of columns of bricks.
        :param brick_width: Controls the width of a single brick.
        :param brick_height: Controls the height of a single brick.
        :param brick_offset: Controls the y-position of the highest row of bricks.
        :param brick_spacing: Controls the interval between any two bricks.
        :param title: Set the title of the canvas.
        """
        self.ball_radius = ball_radius
        self.paddle_width = paddle_width
        self.paddle_height = paddle_height
        self.paddle_offset = paddle_offset
        self.brick_cols = brick_cols
        self.brick_rows = brick_rows
        self.brick_width = brick_width
        self.brick_height = brick_height
        self.brick_offset = brick_offset
        self.brick_spacing = brick_spacing

        # Create a label for usernames before create a window.
        self.name = GLabel('Player: ' + input('Nickname: '))
        self.name.font = '-15-bold'

        # Create a graphical window, with some extra space.
        self.window_width = self.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)

        # Initial settings before the game starts.
        self.score = 0
        self.score_label = GLabel('Score: ' + str(self.score))
        self.score_label.font = '-15-bold'
        self.lives = 3
        self.lives_label = GLabel('Lives: ' + str(self.lives))
        self.lives_label.font = '-15-bold'
        self.click2start = GLabel('Click to Start !')
        self.click2start.font = '-20-bold'
        self.window.add(self.name, 5, self.brick_offset - 25)
        self.window.add(self.click2start, 130, self.window.height-150)
        self.window.add(self.score_label, 5, self.window.height)
        self.window.add(self.lives_label, self.window_width-100, self.window_height-5)

        # Create a paddle.
        self.count = 1  # For paddle width resetting after losing one live.
        self.paddle = GRect(self.paddle_width, self.paddle_height)
        self.paddle.filled = True
        self.window.add(self.paddle, x=(self.window_width-self.paddle_width)/2, y=self.window_height-paddle_offset)

        # Center a filled ball in the graphical window.
        self.ball = GOval(ball_radius*2, ball_radius*2)
        self.ball.filled = True
        self.window.add(self.ball, (self.window_width-self.ball.width)/2, (self.window_height-brick_height)/2)

        # Default initial velocity for the ball.
        self.__dx = 0
        self.__dy = INITIAL_Y_SPEED
        self.set_x_velocity()

        # Initialize our mouse listeners.
        self.is_game_started = False
        onmouseclicked(self.handle_click)

        # Draw bricks.
        self.brick_left = self.brick_cols * self.brick_rows
        for i in range(self.brick_rows):
            for j in range(self.brick_cols):
                # Different colors for every two rows.
                self.brick = GRect(self.brick_width, self.brick_height)
                self.brick.filled = True
                if i < 2:
                    self.brick.fill_color = 'lightcoral'
                elif 2 <= i < 4:
                    self.brick.fill_color = 'peachpuff'
                elif 4 <= i < 6:
                    self.brick.fill_color = 'lightyellow'
                elif 6 <= i < 8:
                    self.brick.fill_color = 'palegreen'
                elif 8 <= i < 10:
                    self.brick.fill_color = 'aqua'
                self.window.add(self.brick, x=j*(self.brick_width+self.brick_spacing),
                                y=self.brick_offset+i*(self.brick_height+self.brick_spacing))

    def paddle_move(self, event):
        """
        This function will execute if the the game is started. If the game is started,
        it will detect the position of the mouse so that players can control the paddle
        with their mouse.
        :param event: Detects position of the mouse.
        """
        if self.is_game_started:
            # If the mouse is out of the range of the width of the window, the paddle will still remain in the window.
            if event.x <= self.paddle.width/2:
                self.paddle.x = 0
            elif event.x >= self.window_width - self.paddle_width/2:
                self.paddle.x = self.window_width - self.paddle_width
            else:
                self.paddle.x = event.x - self.paddle_width/2

    def get_x_velocity(self):
        """
        Since self.__dx is private instance variable, we need to create a getter for the user-end.
        :return: The value of self.__dx (the x-velocity)
        """
        return self.__dx

    def get_y_velocity(self):
        """
        Since self.__dy is private instance variable, we need to create a getter for the user-end.
        :return: The value of self.__dy (the y-velocity)
        """
        return self.__dy

    def set_x_velocity(self):
        """
        Setting a random x-velocity and y-velocity for the ball. The y-velocity is a constant, and
        the x-velocity is set between 1 and MAX_X_SPEED, There is a 50% chance that the ball will have
        opposite direction in x dimension.
        """
        self.__dx = random.randint(2, MAX_X_SPEED)
        if random.random() < 0.5:
            self.__dx = -self.__dx

    def handle_click(self, _):
        """
        This function will execute if a click on the mouse. After a single click,
        the game will start, and any clicks can no longer affect the game.
        :param _: Detects a click on the mouse.
        :return: self.count
        """
        self.window.remove(self.click2start)
        self.is_game_started = True
        onmousemoved(self.paddle_move)

    def probe_obj(self):
        """
        This function will detect any collision between the ball with other objects.
        :return: True, if the ball bump into the paddle or the bricks.
        """
        # The variable 'obj' will change to the next corner if the checked None.
        obj1 = self.window.get_object_at(self.ball.x, self.ball.y)
        obj2 = self.window.get_object_at(self.ball.x + self.ball.width, self.ball.y)
        obj3 = self.window.get_object_at(self.ball.x, self.ball.y + self.ball.height)
        obj4 = self.window.get_object_at(self.ball.x + self.ball.width, self.ball.y + self.ball.height)
        point = obj1
        if point is None or point is self.name and point is self.score_label and point is self.lives_label:
            point = obj2
        if point is None or point is self.name and point is self.score_label and point is self.lives_label:
            point = obj3
        if point is None or point is self.name and point is self.score_label and point is self.lives_label:
            point = obj4
        if point is None or point is self.name and point is self.score_label and point is self.lives_label:
            pass
        if point is self.paddle:
            # To avoid the ball from sticking on the paddle, I move the ball above the paddle.
            self.ball.move(0, -self.paddle_height - self.ball.height)
            # When the ball touches the paddle, the paddle will change its color to the ball's color.
            self.paddle.color = self.ball.color
            self.paddle.fill_color = self.ball.fill_color
            return True
        if point is not self.paddle and point is not None and point is not self.name\
                and point is not self.score_label and point is not self.lives_label:
            # Every time when the ball bump into a brick, the score will reset.
            self.window.remove(point)
            self.brick_left -= 1
            # The formula of score counting.
            self.score = int((self.brick_rows * self.brick_cols - self.brick_left) ** 1.5)
            if self.brick_left == (self.brick_rows * self.brick_cols) * 1/2:
                self.lives += 1
                self.window.remove(self.lives_label)
                self.lives_label = GLabel('Lives: ' + str(self.lives))
                self.lives_label.font = '-15-bold'
                self.window.add(self.lives_label, self.window_width-100, self.window_height-5)
            self.window.remove(self.score_label)
            self.score_label = GLabel('Score: ' + str(self.score))
            self.score_label.font = '-15-bold'
            self.window.add(self.score_label, 5, self.window.height)
            # The color of the ball depends on how many bricks are left.
            if self.brick_rows * self.brick_cols * 3/5 < self.brick_left <= self.brick_rows * self.brick_cols * 4/5:
                self.ball.color = 'palegreen'
                self.ball.fill_color = 'palegreen'
            elif self.brick_rows * self.brick_cols * 2/5 < self.brick_left <= self.brick_rows * self.brick_cols * 3/5:
                self.ball.color = 'lightyellow'
                self.ball.fill_color = 'lightyellow'
            elif self.brick_rows * self.brick_cols * 1/5 < self.brick_left <= self.brick_rows * self.brick_cols * 2/5:
                self.ball.color = 'peachpuff'
                self.ball.fill_color = 'peachpuff'
            # More difficult to see the ball.
            elif self.brick_left <= self.brick_rows * self.brick_cols * 1/5:
                self.ball.color = 'black'
                self.ball.fill_color = 'black'
            return True
        # Lives will reset when the ball fall out of the lower margin of the window.

    def fall_out(self):
        self.is_game_started = False
        # Every chance loses, the variable 'count', which affects the length of the paddle, will add 0.15.
        self.count += 0.15
        self.lives -= 1
        self.window.remove(self.lives_label)
        self.lives_label = GLabel('Lives: ' + str(self.lives))
        self.lives_label.font = '-15-bold'
        self.window.add(self.lives_label, self.window_width - 100, self.window_height - 5)
        self.set_x_velocity()
        return self.count, self.lives, self.__dx

    def build_ball(self):
        """
        This function will first remove the original ball and create a new ball. The color of the ball depends
        on the number of remaining bricks.
        """
        self.window.remove(self.ball)
        self.ball = GOval(self.ball_radius*2, self.ball_radius*2)
        self.ball.filled = True
        # The color of the ball depends on how many bricks are left.
        if self.brick_rows * self.brick_cols * 3 / 5 < self.brick_left <= self.brick_rows * self.brick_cols * 4 / 5:
            self.ball.color = 'palegreen'
            self.ball.fill_color = 'palegreen'
        elif self.brick_rows * self.brick_cols * 2 / 5 < self.brick_left <= self.brick_rows * self.brick_cols * 3 / 5:
            self.ball.color = 'lightyellow'
            self.ball.fill_color = 'lightyellow'
        elif self.brick_rows * self.brick_cols * 1 / 5 < self.brick_left <= self.brick_rows * self.brick_cols * 2 / 5:
            self.ball.color = 'peachpuff'
            self.ball.fill_color = 'peachpuff'
        # More difficult to see the ball.
        elif self.brick_left <= self.brick_rows * self.brick_cols * 1 / 5:
            self.ball.color = 'black'
            self.ball.fill_color = 'black'
        self.window.add(self.ball, (self.window_width-self.ball.width)/2, (self.window_height-self.brick_height)/2)

    def build_paddle(self):
        """
        This function will first remove the original paddle and create a new one. The width of the new paddle
        depends on the variable of count.
        """
        self.window.remove(self.paddle)
        self.paddle = GRect(self.paddle_width/self.count, self.paddle_height, x=(self.window_width-self.paddle_width)/2,
                            y=self.window_height-self.paddle_offset)
        self.paddle.filled = True
        self.paddle.color = self.ball.color
        self.paddle.fill_color = self.ball.fill_color
        self.window.add(self.paddle)

    def game_over(self):
        """
        This function execute when no lives are remaining. The window will show the game is over
        and the final score. The score depends on the number of remaining bricks and the variable
        count.
        """
        self.is_game_started = False
        self.window.clear()
        game_over = GLabel('Game Over')
        game_over.font = '-60-bold'
        lose = GLabel('You Lose...')
        lose.font = '-30-bold'
        score_label = GLabel('Your Score:' + str(self.score))
        score_label.font = 'courier-25-bold'
        background = GRect(self.window.width, self.window.height)
        background.filled = True
        background.color = 'red'
        background.fill_color = 'red'
        self.window.add(background)
        self.window.add(game_over, 2, (self.window.height/2)+30)
        self.window.add(lose, 120, (self.window.height/2+120))
        self.window.add(score_label, 100, self.window.height)

    def winner(self):
        """
        This function will execute if and only if a player successfully eliminates
        all the bricks. After all bricks are eliminated, the window will show
        'You win!!!!' and the final score. The score depends on the number of remaining
        bricks and the variable count.
        """
        self.window.clear()
        you_win = GLabel('Love Cindy!!!!')
        you_win.font = '-60-bold'
        # One live remaining worth 100 points.
        self.score += self.lives * 100
        score_label = GLabel('Your Score is:' + str(self.score), 0, 20)
        score_label.font = 'courier-25-bold'
        background = GRect(self.window.width, self.window.height)
        background.filled = True
        background.color = 'pink'
        background.fill_color = 'pink'
        self.window.add(background)
        self.window.add(you_win, 5, (self.window.height/2)+30)
        self.window.add(score_label, 50, self.window.height)
コード例 #8
0
class ZoneGraphics:
    def __init__(self,
                 window_width=WINDOW_WIDTH,
                 window_height=WINDOW_HEIGHT,
                 zone_width=ZONE_WIDTH,
                 zone_height=ZONE_HEIGHT,
                 ball_radius=BALL_RADIUS):
        # Create window
        self.window = GWindow(window_width, window_height, title='Zone Game')

        # Create zone
        self.zone = GRect(zone_width,
                          zone_height,
                          x=(window_width - zone_width) / 2,
                          y=(window_height - zone_height) / 2)
        self.zone.color = 'blue'
        self.window.add(self.zone)

        # Create ball and initialize velocity/position
        self.ball = GOval(2 * ball_radius, 2 * ball_radius)
        self.ball.filled = True
        self.ball.fill_color = 'salmon'

        self.dx = 0
        self.dy = 0

        self.reset_ball()

        # Initialize mouse listeners
        onmouseclicked(self.handle_click)

        # Set ball position at random inside the window

    def set_ball_position(self):
        self.ball.x = random.randint(0, self.window.width - self.ball.width)
        self.ball.y = random.randint(0, self.window.height - self.ball.height)

    def set_ball_velocity(self):
        self.dx = random.randint(0, MAX_SPEED)
        if random.random() > 0.5:
            self.dx = -self.dx
        self.dy = random.randint(MIN_Y_SPEED, MAX_SPEED)
        if random.random() > 0.5:
            self.dy = -self.dy

    def reset_ball(self):
        self.set_ball_position()
        while self.ball_in_zone():
            self.set_ball_position()
        self.set_ball_velocity()
        self.window.add(self.ball)

    def move_ball(self):
        self.ball.move(self.dx, self.dy)

    def handle_wall_collisions(self):
        if self.ball.x + self.ball.width >= self.window.width or self.ball.x <= 0:
            self.dx = -self.dx
        if self.ball.y + self.ball.height >= self.window.height or self.ball.y <= 0:
            self.dy = -self.dy

    def ball_in_zone(self):
        zone_left_side = self.zone.x
        zone_right_side = self.zone.x + self.zone.width
        ball_x_in_zone = zone_left_side <= self.ball.x <= zone_right_side - self.ball.width

        zone_top_side = self.zone.y
        zone_bottom_side = self.zone.y + self.zone.height
        ball_y_in_zone = zone_top_side <= self.ball.y <= zone_bottom_side - self.ball.height

        return ball_x_in_zone and ball_y_in_zone

    def handle_click(self, event):
        obj = self.window.get_object_at(event.x, event.y)
        if self.ball == obj:
            self.reset_ball()
コード例 #9
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
        window_width = brick_cols * (brick_width +
                                     brick_spacing) - brick_spacing
        window_height = brick_offset + 3 * (brick_rows *
                                            (brick_height + brick_spacing) -
                                            brick_spacing)
        self.window = GWindow(width=window_width,
                              height=window_height,
                              title='Breakout')

        # Element score label
        self.score = 0
        self.score_label = GLabel('Score: ' + str(self.score))

        # Element for game winning
        self.win_show = GLabel('Create by Mike Lin', x=100, y=100)
        self.win_show2 = GLabel('March 20 stanCode SC101', x=135, y=115)

        # Create a paddle
        self.paddle = GRect(paddle_width,
                            paddle_height,
                            x=(window_width - paddle_width) / 2,
                            y=window_height - paddle_offset)
        self.window.add(self.paddle)
        self.paddle.filled = True

        # Center a filled ball in the graphical window
        self.ball = GOval(2 * ball_radius,
                          2 * ball_radius,
                          x=window_width / 2 - ball_radius,
                          y=window_height / 2 - ball_radius)
        self.ball_x = window_width / 2 - ball_radius
        self.ball_y = window_height / 2 - ball_radius

        # Default initial velocity for the ball
        self.__dx = 0
        self.__dy = 0

        # Other variables
        self.total_bricks = 0

        # Initialize our mouse listeners
        onmousemoved(
            self.paddle_move)  # using own method must add 'self.' in the front
        onmouseclicked(self.clicked)
        self.draw_bricks_and_ball()

    def draw_bricks_and_ball(self):
        """
        set the bricks and balls
        """
        self.window.add(self.score_label, x=0, y=15)
        self.window.add(self.ball)
        self.ball.filled = True
        color_num = BRICK_COLS / 5
        for i in range(BRICK_ROWS):
            for j in range(BRICK_COLS):
                if j // color_num == 0:
                    color = 'red'
                elif j // color_num == 1:
                    color = 'orange'
                elif j // color_num == 2:
                    color = 'yellow'
                elif j // color_num == 3:
                    color = 'green'
                else:
                    color = 'blue'
                bricks = GRect(BRICK_WIDTH, BRICK_HEIGHT)
                self.window.add(bricks,
                                x=0 + i * (BRICK_WIDTH + BRICK_SPACING),
                                y=BRICK_OFFSET + j *
                                (BRICK_HEIGHT + BRICK_SPACING))
                bricks.filled = True
                bricks.fill_color = color
                self.total_bricks += 1

    def paddle_move(self, m):
        """
        :param m: mouse you move
        this function controls the moving of the paddle and prevents it from disappearing
        """
        if self.paddle.width / 2 <= m.x <= self.window.width - self.paddle.width / 2:
            self.paddle.x = m.x - self.paddle.width / 2
        elif m.x >= self.window.width:
            self.paddle.x = self.window.width - self.paddle.width
        elif m.x < 0:
            self.paddle.x = 0

    def clicked(self, m):
        """
        the boolean that controls the start of the game once you clicked the mouse
        """
        if (self.ball.x, self.ball.y) == (self.ball_x, self.ball_y):
            self.__dx = random.randint(1, MAX_X_SPEED)
            if random.random() > 0.5:
                self.__dx = -self.__dx
            self.__dy = INITIAL_Y_SPEED

    def set_ball_direct(self):
        """
        to set the ball's direction and the action the ball takes when hitting the walls, bricks, paddle
        """
        self.ball.move(self.__dx, self.__dy)
        self.meet_the_wall()
        if self.meet_object() is self.paddle:
            self.__dy = -abs(self.__dy)
        elif self.meet_object() is self.ball:
            pass
        elif self.meet_object() is self.score_label:
            pass
        elif self.meet_object() is not None:
            self.window.remove(self.meet_object())
            self.__dy *= -1
            self.total_bricks -= 1
            self.score += 1
            self.score_label.text = 'Score: ' + str(self.score)
            if self.total_bricks == 0:
                self.ball.x = self.ball_x
                self.ball.y = self.ball_y
                self.window.add(self.win_show)
                self.window.add(self.win_show2)
                self.win_show.font = '-30'

    def meet_the_wall(self):
        """
        the function that determines the ball's vy
        """
        if self.ball.x <= 0:
            self.__dx *= -1
        elif self.ball.x + self.ball.width >= self.window.width:
            self.__dx *= -1
        elif self.ball.y <= 0:
            self.__dy *= -1
        elif self.ball.y + self.ball.height >= self.window.height:
            self.__dx = 0
            self.__dy = 0

    def dead(self):
        """
        to set the ball to start point when falling under the bottom window
        """
        if self.ball.y + self.ball.height >= self.window.height:
            self.ball.x = self.ball_x
            self.ball.y = self.ball_y
            return True

    def meet_object(self):
        """
        the detector for checking what the ball hits
        :return: the obstacle that ball hits
        """
        obstacle1 = self.window.get_object_at(self.ball.x, self.ball.y)
        obstacle2 = self.window.get_object_at(self.ball.x + self.ball.width,
                                              self.ball.y)
        obstacle3 = self.window.get_object_at(self.ball.x + self.ball.width,
                                              self.ball.y + self.ball.height)
        obstacle4 = self.window.get_object_at(self.ball.x,
                                              self.ball.y + self.ball.height)
        if obstacle1 is not None and not self.ball:
            return obstacle1
        elif obstacle2 is not None:
            return obstacle2
        elif obstacle3 is not None:
            return obstacle3
        elif obstacle4 is not None:
            return obstacle4
        else:
            return None

    def get_dx(self):
        """
        to get dx speed
        :return: dx speed
        """
        return self.__dx

    def get_dy(self):
        """
        to get dy speed
        :return: dy speed
        """
        return self.__dy
コード例 #10
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.
        window_width = brick_cols * (brick_width +
                                     brick_spacing) - brick_spacing
        window_height = brick_offset + 3 * (brick_rows *
                                            (brick_height + brick_spacing) -
                                            brick_spacing)
        self.window = GWindow(width=window_width,
                              height=window_height,
                              title=title)

        # Create a paddle.
        self.paddle = GRect(paddle_width, paddle_height)
        self.paddle.filled = True
        self.window.add(self.paddle, (window_width - paddle_width) / 2,
                        window_height - paddle_offset)

        # Center a filled ball in the graphical window.
        self.ball = GOval(ball_radius * 2,
                          ball_radius * 2,
                          x=window_width / 2 - ball_radius,
                          y=window_height / 2 - ball_radius)
        self.ball.filled = True
        self.window.add(self.ball)

        # Create a scoreboard.
        self.__score = 0
        self.__board = GLabel('Score: ' + str(self.__score))
        self.__board.font = '-30'
        self.window.add(self.__board, 0, self.__board.height + 5)

        # Default initial velocity for the ball.
        self.__dx = 0
        self.__dy = 0
        self.reverse_dy = -INITIAL_Y_SPEED

        # Initialize our mouse listeners.
        onmousemoved(self.move_paddle)
        onmouseclicked(self.click_to_start)
        self.__start = False

        # Draw bricks.
        self.__count = 0
        for i in range(brick_rows):
            for j in range(brick_cols):
                self.__brick = GRect(brick_width, brick_height)
                self.__brick.filled = True

                if i // 2 == 0:
                    self.__brick.fill_color = 'red'
                    self.__brick.color = 'red'
                if i // 2 == 1:
                    self.__brick.fill_color = 'orange'
                    self.__brick.color = 'orange'
                if i // 2 == 2:
                    self.__brick.fill_color = 'yellow'
                    self.__brick.color = 'yellow'
                if i // 2 == 3:
                    self.__brick.fill_color = 'green'
                    self.__brick.color = 'green'
                if i // 2 == 4:
                    self.__brick.fill_color = 'blue'
                    self.__brick.color = 'blue'

                brick_y = brick_offset + (brick_height + brick_spacing) * i
                brick_x = (brick_width + brick_spacing) * j

                self.window.add(self.__brick, brick_x, brick_y)
                self.__count += 1

    def move_paddle(self, mouse):
        """
        Set the paddle to move horizontally with mouse moved and is contained in window.

        Input:
            event (GMouseEvent): mouse moved event
        """
        self.paddle.x = mouse.x - self.paddle.width / 2
        if self.paddle.x <= 0:
            self.paddle.x = 0
        if self.paddle.x + self.paddle.width >= self.window.width:
            self.paddle.x = self.window.width - self.paddle.width

    def click_to_start(self, event):
        """
        Start the game if the mouse is clicked and detect whether the game is started.

        Input:
            event (GMouseEvents): mouse clicked event
        """
        if not self.__start:
            self.set_ball_direction()
            self.__start = True

    def set_ball_direction(self):
        """
        Give ball x, y velocity which will determine its initial direction.
        """
        self.__dx = random.randint(1, MAX_X_SPEED)
        self.__dy = INITIAL_Y_SPEED
        if random.random() > 0.5:
            self.__dx = -self.__dx

    def get_x_velocity(self):
        """
        Return ball x velocity.
        """
        return self.__dx

    def get_y_velocity(self):
        """
        Return ball y velocity.
        """
        return self.__dy

    def move_ball(self):
        """
        Move ball by the change in x and the change in y stored in class BreakoutGraphics.
        """
        self.ball.move(self.__dx, self.__dy)

    def wall_collisions(self):
        """
        Update dx and dy depending on whether the ball has hit walls.
        """
        if 0 >= self.ball.x or self.ball.x + self.ball.width >= self.window.width:
            self.__dx = -self.__dx
        if 0 >= self.ball.y:
            self.__dy = -self.__dy

    def ball_collisions(self):
        """
        Remove bricks and change ball's direction when the ball hit bricks.
        Rebound the ball by changing its y velocity when the ball hit the paddle.
        The score will add one when each time brick was removed.
        """
        up_l_corner = self.window.get_object_at(self.ball.x, self.ball.y)
        up_r_corner = self.window.get_object_at(self.ball.x + self.ball.width,
                                                self.ball.y)
        down_l_corner = self.window.get_object_at(
            self.ball.x, self.ball.y + self.ball.height)
        down_r_corner = self.window.get_object_at(
            self.ball.x + self.ball.width, self.ball.y + self.ball.height)

        # The situation that the ball hits the paddle.
        if down_l_corner == self.paddle:
            self.__dy = self.reverse_dy
        elif down_r_corner == self.paddle:
            self.__dy = self.reverse_dy

        # The situation that the ball hits bricks and remove them.
        if up_l_corner is not None and up_l_corner is not self.paddle and up_l_corner is not self.__board:
            self.__dy = -self.__dy
            self.window.remove(up_l_corner)
            self.__count -= 1
            self.__score += 1
            self.__board.text = 'Score: ' + str(self.__score)
        elif up_r_corner is not None and up_r_corner is not self.paddle and up_r_corner is not self.__board:
            self.__dy = -self.__dy
            self.window.remove(up_r_corner)
            self.__count -= 1
            self.__score += 1
            self.__board.text = 'Score: ' + str(self.__score)
        elif down_l_corner is not None and down_l_corner is not self.paddle and down_l_corner is not self.__board:
            self.__dy = -self.__dy
            self.window.remove(down_l_corner)
            self.__count -= 1
            self.__score += 1
            self.__board.text = 'Score: ' + str(self.__score)
        elif down_r_corner is not None and down_r_corner is not self.paddle and down_r_corner is not self.__board:
            self.__dy = -self.__dy
            self.window.remove(down_r_corner)
            self.__count -= 1
            self.__score += 1
            self.__board.text = 'Score: ' + str(self.__score)

    def outside_window(self):
        """
        Check whether the ball has fallen outside the window bottom.
        :return: Bool
        """
        if self.ball.y >= self.window.height:
            return True

    def reset_ball(self):
        """
        Reset the ball's location and velocity after the ball has fallen outside the window.
        :return: Bool
        """
        self.window.remove(self.ball)
        self.ball.x = (self.window.width - self.ball.width) / 2
        self.ball.y = (self.window.height - self.ball.height) / 2
        self.__dx = 0
        self.__dy = 0
        self.window.add(self.ball)
        self.__start = False

    def game_over(self):
        """
        One of the conditions for game over. When all chances were used out.
        """
        self.reset_ball()
        lose = GLabel('You lose!')
        lose.font = '-70-bold'
        self.window.add(lose, (self.window.width - lose.width) / 2, 500)

    def end_game(self):
        """
        One of the conditions for game over. When all bricks were remove.
        :return: Bool
        """
        if self.__count == 0:
            self.window.remove(self.ball)
            congrats = GLabel('Congratulation!')
            congrats.font = '-70-bold'
            congrats.color = 'red'
            self.window.add(congrats, (self.window.width - congrats.width) / 2,
                            500)
            return True
コード例 #11
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',
                 life=NUM_LIVES):

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

        # Create a paddle.
        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 = '#53414E'
        self.paddle.fill_color = '#53414E'
        self.window.add(self.paddle)

        # Center a filled ball in the graphical window.
        self.ball = GOval(ball_radius * 2,
                          ball_radius * 2,
                          x=self.window_width / 2 - ball_radius,
                          y=self.window_height / 2 - ball_radius)
        self.ball.filled = True
        self.ball.fill_color = '#FF7146'
        self.window.add(self.ball, self.window_width / 2 - ball_radius,
                        self.window_height / 2 - ball_radius)

        # Default initial velocity for the ball.
        self.__dx = 0
        self.__dy = INITIAL_Y_SPEED
        self.__dx = random.randint(1, MAX_X_SPEED)

        # Initialize our mouse listeners.
        self.no_restart = False  # to switch on the game
        self.count = 0
        self.life = NUM_LIVES

        onmousemoved(self.move_paddle)
        onmouseclicked(self.move_ball)

        # Draw bricks.
        for i in range(brick_rows):
            for j in range(brick_cols):
                if j % 2 == 0:
                    self.brick = GRect(brick_width,
                                       brick_height,
                                       x=i * (brick_width + brick_spacing),
                                       y=brick_offset + j *
                                       (brick_height + brick_spacing))
                    self.brick.filled = True
                    self.brick.fill_color = '#B2CFD6'
                    self.window.add(self.brick)
                else:
                    self.brick = GRect(brick_width,
                                       brick_height,
                                       x=i * (brick_width + brick_spacing),
                                       y=brick_offset + j *
                                       (brick_height + brick_spacing))
                    self.brick.filled = True
                    self.brick.fill_color = '#AED690'
                    self.window.add(self.brick)

        #game over label
        self.over_label = GLabel('Game Over',
                                 x=self.window_width / 2,
                                 y=self.window_height / 2)
        self.over_label.color = 'black'

        #finish label
        self.brick_amount = int(brick_rows * brick_cols)
        self.finish_label = GLabel('Congrats',
                                   x=self.window_width / 2,
                                   y=self.window_height / 2)
        self.finish_label.color = 'red'

        #ball touch paddle
        self.ball_touch_paddle_1 = self.window.get_object_at(
            self.ball.x, self.ball.y + self.ball.height)
        self.ball_touch_paddle_2 = self.window.get_object_at(
            self.ball.x + self.ball.width, self.ball.y + self.ball.height)
        self.ball_touch_paddle_check = True

        #bounce
        self.ten_point = GOval(ball_radius * 2, ball_radius * 2)
        self.ten_point.filled = True
        self.ten_point.fill_color = 'black'

    def drop_ten_point(self):
        self.ten_point.move(0, 5)

    def get_ten_point(self):
        if self.ten_point.y + self.ten_point.height >= self.paddle.y and self.paddle.x <= self.ten_point.x <= self.paddle.width - self.ten_point.width:
            self.count += 10

    def move_paddle(self, mouse):
        if 0 <= mouse.x <= self.window.width - self.paddle.width:
            self.paddle.x = mouse.x
            self.paddle.y = self.paddle.y

    def move_ball(self, event):
        if 0 <= event.x <= self.window.width and 0 <= event.y <= self.window.height and not self.no_restart:
            self.no_restart = True

    def get_dx(self):  # getter: let breakout.py to get the dx
        return self.__dx

    def get_dy(self):  # getter: let breakout.py to get the dy
        return self.__dy

    def ball_outside_window(self):
        ball_outside_window = self.ball.y > self.window.height
        return ball_outside_window

    def bouncing_dx(self):
        self.__dx = -self.__dx
        return self.__dx

    def bouncing_dy(self):
        self.__dy = -self.__dy
        return self.__dy

    def ball_touch_wall(self):
        ball_touch_x_left_wall = self.ball.x <= 0
        ball_touch_x_right_wall = self.ball.x + self.ball.width >= self.window.width
        ball_touch_y_top = self.ball.y <= 0
        return ball_touch_x_left_wall or ball_touch_x_right_wall or ball_touch_y_top

    def ball_touch_paddle(self):
        ball_touch_x_paddle = self.paddle.x - self.ball.width <= self.ball.x <= self.paddle.x + self.paddle.width
        ball_touch_y_paddle = self.paddle.y <= self.ball.y + self.ball.height <= self.paddle.y + self.paddle.height
        return ball_touch_x_paddle and ball_touch_y_paddle

    def ball_in_window(self):
        ball_in_window_x = self.ball.x == self.window_width / 2 - self.ball.width
        return ball_in_window_x

    def reset_ball(self):
        self.set_ball_position()
        while self.ball_outside_window():
            self.set_ball_position()
        self.set_ball_velocity()
        self.window.add(self.ball)

    def set_ball_velocity(self):
        self.__dx = random.randint(1, MAX_X_SPEED)
        self.__dy = INITIAL_Y_SPEED

    def set_ball_position(self):
        self.window.add(self.ball, self.window_width / 2 - self.ball.width,
                        self.window_height / 2 - self.ball.height)

    def remove_brick(self, obj):
        self.window.remove(obj)
        self.__dx = random.randint(1, MAX_X_SPEED)
        self.__dy = -self.__dy

    def game_over(self):
        self.window.add(self.over_label,
                        x=self.window_width / 2,
                        y=self.window_height / 2)
        self.window.remove(self.ball)

    def finish_game(self):
        self.window.add(self.finish_label,
                        x=self.window_width / 2,
                        y=self.window_height / 2)

    def remove_ball_paddle(self):
        self.window.remove(self.ball)
        self.window.remove(self.paddle)
コード例 #12
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'):
        num_bricks = 100
        # Create a graphical window, with some extra space.
        window_width = brick_cols * (brick_width +
                                     brick_spacing) - brick_spacing
        window_height = brick_offset + 3 * (brick_rows *
                                            (brick_height + brick_spacing) -
                                            brick_spacing)
        self.window = GWindow(width=window_width,
                              height=window_height,
                              title=title)
        self.paddle = GRect(paddle_width, paddle_height, x=(window_width - paddle_width)/2, y = window_height - \
                            paddle_offset)

        # initializing the paddle
        self.paddle.filled = True
        self.paddle.fill_color = 'black'
        self.window.add(self.paddle)

        # initializing the ball
        self.ball = GOval(width=ball_radius * 2,
                          height=ball_radius * 2,
                          x=window_width / 2 - BALL_RADIUS,
                          y=window_height / 2 - BALL_RADIUS)
        self.ball.filled = True
        self.ball.fill_color = 'black'
        self.window.add(self.ball)

        # initial velocity
        self.vx = 0
        self.vy = INITIAL_Y_SPEED

        # draw bricks
        self.draw_bricks()

        # number of lives left
        self.num_lives = 3

        # running? big question mark
        self.running = False

        # brick count
        self.brick_count = 100

        # mouse listeners
        onmouseclicked(self.start)
        onmousemoved(self.move_paddle)

    def start(self, event):
        """
        Starts game on mouse click.
        """
        self.running = True

    def draw_bricks(self):
        """
        Draws bricks by row and with color changing for each turn.
        """
        x_init = 0
        curr_y = BRICK_OFFSET
        color_index = 0
        for row in range(1, BRICK_ROWS + 1):
            curr_x = x_init
            for col in range(BRICK_COLS):
                self.brick = GRect(BRICK_WIDTH,
                                   BRICK_HEIGHT,
                                   x=curr_x,
                                   y=curr_y)
                self.brick.filled = True
                self.brick.fill_color = COLORS[color_index]
                self.window.add(self.brick)
                curr_x += BRICK_WIDTH + BRICK_SPACING
            curr_y += BRICK_HEIGHT + BRICK_SPACING
            if row % 2 == 0:
                color_index += 1

    def move_paddle(self, event):
        """
        Moves paddle with mouse event.
        """
        self.paddle.x = event.x - PADDLE_WIDTH / 2

    def move_ball(self):
        """
        Moves ball with proper x and y velocities.
        """
        self.ball.move(self.vx, self.vy)

    def handle_collisions(self):
        """
        Handles collisions as necessary per animation loop.
        """
        # changing for wall collisions
        if self.side_wall_hit(
        ):  # checks for side wall hits and changes x-component
            print('oop hit a side wall')
            self.vx = -self.vx
        elif self.top_wall_paddle_hit(
        ):  # checks for top/paddle hits and changes y-component
            print('oop hit the top or a paddle')
            self.vy = -self.vy
        # changing for block collisions
        elif self.brick_paddle_hit(
        ) != -1 and self.ball.y != self.window.height - 2 * BALL_RADIUS - PADDLE_OFFSET - PADDLE_HEIGHT:
            loc_x, loc_y = self.brick_paddle_hit()
            print(loc_x, loc_y)
            self.remove_brick(loc_x, loc_y)
            self.vy = -self.vy
            self.vx = random.uniform(-MAX_X_SPEED, MAX_X_SPEED)
        # changing for bottom collision
        elif self.bottom_hit():
            self.num_lives -= 1
            print('the number of lives is', self.num_lives)
            self.reset()

    def bottom_hit(self):
        """
        Checks if the bottom was hit.
        """
        if self.ball.y + 2 * BALL_RADIUS >= self.window.height:
            return True
        else:
            return False

    def side_wall_hit(self):
        """
        Checks if the left or right walls were hit.
        """
        if self.ball.x <= 0 or self.ball.x >= self.window.width - 2 * BALL_RADIUS:
            return True
        else:
            return False

    def top_wall_paddle_hit(self):
        """
        Checks if the top wall or paddle was hit.
        """
        if self.ball.y <= 0:
            return True
        elif self.brick_paddle_hit(
        ) != -1 and self.ball.y >= self.window.height - 2 * BALL_RADIUS - PADDLE_OFFSET:
            return True
        else:
            return False

    def brick_paddle_hit(self):
        """
        Checks, according to the guidelines in the handout, if a collision has occurred with the ball and a brick or
        the paddle.
        """
        if self.window.get_object_at(self.ball.x, self.ball.y) != None:
            return self.ball.x, self.ball.y
        elif self.window.get_object_at(self.ball.x + 2 * BALL_RADIUS,
                                       self.ball.y) != None:
            return self.ball.x + 2, self.ball.y
        elif self.window.get_object_at(self.ball.x,
                                       self.ball.y + 2 * BALL_RADIUS) != None:
            return self.ball.x, self.ball.y + 2 * BALL_RADIUS
        elif self.window.get_object_at(self.ball.x + 2 * BALL_RADIUS,
                                       self.ball.y + 2 * BALL_RADIUS) != None:
            return self.ball.x + 2 * BALL_RADIUS, self.ball.y + 2 * BALL_RADIUS
        else:
            return -1

    def remove_brick(self, loc_x, loc_y):
        """
        Remove a brick when hit.
        """
        if self.window.get_object_at(loc_x, loc_y) != self.paddle:
            self.window.remove(self.window.get_object_at(loc_x, loc_y))
            self.brick_count -= 1

    def reset(self):
        """
        Resets the game when the bottom is hit.
        """
        self.window.clear()
        self.window.remove(self.ball)

        self.ball = GOval(width=BALL_RADIUS * 2,
                          height=BALL_RADIUS * 2,
                          x=self.window.width / 2 - BALL_RADIUS,
                          y=self.window.height / 2 - BALL_RADIUS)
        self.ball.filled = True
        self.ball.fill_color = 'black'
        self.window.add(self.ball)
        self.draw_bricks()
        self.brick_count = 100
        self.vx = 0
        self.vy = INITIAL_Y_SPEED
        self.paddle.filled = True
        self.paddle.fill_color = 'black'
        self.window.add(self.paddle)
        self.running = False

    def game_over(self):
        game_over_label = GLabel('GAME OVER',
                                 x=self.window.width / 2 - 40,
                                 y=self.window.height / 2)
        self.window.add(game_over_label)
コード例 #13
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'):
        """
        Function: Create initial parameters such as window, ball, paddle,brick etc.
        :param ball_radius: Radius of the ball (in pixels).
        :param paddle_width: Width of the paddle (in pixels).
        :param paddle_height: Height of the paddle (in pixels).
        :param paddle_offset: Vertical offset of the paddle from the window bottom (in pixels).
        :param brick_rows:  Number of rows of bricks.
        :param brick_cols: Number of cols of bricks.
        :param brick_width: Width of a brick (in pixels).
        :param brick_height: Height of a brick (in pixels).
        :param brick_offset: Vertical offset of the topmost brick from the window top (in pixels).
        :param brick_spacing: Space between bricks (in pixels). This space is used for horizontal and vertical spacing.
        :param title: Window title
        """
        # Create a graphical window, with some extra space.
        window_width = brick_cols * (brick_width +
                                     brick_spacing) - brick_spacing
        window_height = brick_offset + 3 * (brick_rows *
                                            (brick_height + brick_spacing) -
                                            brick_spacing)
        self.window = GWindow(width=window_width,
                              height=window_height,
                              title=title)

        # Create a paddle.
        self.paddle = GRect(paddle_width,
                            paddle_height,
                            x=(window_width - paddle_width) / 2,
                            y=window_height - paddle_offset)
        self.paddle.filled = True
        self.window.add(self.paddle)

        # Center a filled ball in the graphical window.
        self.ball = GOval(ball_radius * 2,
                          ball_radius * 2,
                          x=window_width / 2 - ball_radius,
                          y=window_height / 2 - ball_radius)
        self.ball.filled = True
        self.window.add(self.ball)

        # Default initial velocity for the ball.
        self.__dx = 0
        self.__dy = 0
        print('dxdy')

        # Initialize our mouse listeners.
        self.brick_number = brick_rows * brick_cols
        # Draw bricks.
        self.__brick_site(brick_rows, brick_cols, brick_width, brick_height,
                          brick_offset, brick_spacing)
        onmouseclicked(self.star_fire)
        onmousemoved(self.__move_paddle)

        self.star_switch = False
        self.ball_rest()

    def star_fire(self, mouse):
        """
        Function: When you click the mouse, start the bool.
        :param mouse: Mouse parameters
        """
        self.star_switch = True

    def __brick_site(self, b_r, b_c, b_w, b_h, b_offset, b_spacing):
        """
        Function: Establish the position of the brick
        :param b_r: Number of rows of bricks.
        :param b_c: Number of cols of bricks.
        :param b_w: Width of a brick (in pixels).
        :param b_h: Height of a brick (in pixels).
        :param b_offset: Vertical offset of the topmost brick from the window top (in pixels).
        :param b_spacing: Space between bricks (in pixels). This space is used for horizontal and vertical spacing.
        """
        dy = b_offset
        for j in range(b_r):
            dx = 0
            for i in range(b_c):
                self.brick = GRect(b_w, b_h, x=dx, y=dy)
                self.brick.filled = True

                if j == 0 or j == 1:
                    self.brick.fill_color = 'darkgreen'
                elif j == 2 or j == 3:
                    self.brick.fill_color = 'forestgreen'
                elif j == 4 or j == 5:
                    self.brick.fill_color = 'green'
                elif j == 6 or j == 7:
                    self.brick.fill_color = 'limegreen'
                elif j == 8 or j == 9:
                    self.brick.fill_color = 'lime'
                else:
                    self.brick.fill_color = 'lawngreen'

                self.window.add(self.brick)
                dx += b_w + b_spacing
            dy += b_h + b_spacing

    def __move_paddle(self, mouse):
        """
        Function: When moving the mouse, move the position of the paddle.
        :param mouse: Mouse parameters
        """
        if (mouse.x <= self.window.width - self.paddle.width / 2) and (
                mouse.x >= self.paddle.width / 2):
            self.paddle.x = mouse.x - (self.paddle.width / 2)
        elif mouse.x < self.paddle.width / 2:
            self.paddle.x = 0
        elif mouse.x > self.window.width:
            self.paddle.x = self.window.width - self.paddle.width

    def set_ball_velocity(self):
        """
        Function: set initial speed.
        """
        self.__dx = random.randint(1, MAX_X_SPEED)
        if random.random() > 0.5:
            self.__dx = -self.__dx
        self.__dy = INITIAL_Y_SPEED

    def set_ball_site(self):
        """
        Function: set initial site.
        """
        self.ball.x = (self.window.width - self.ball.height) / 2
        self.ball.y = (self.window.height - self.ball.height) / 2

    def ball_move(self):
        """
        Function: the distance the ball moves each time.
        """
        self.ball.move(self.__dx, self.__dy)

    def get_ball_outside(self):
        """
        Function: Report when the ball outside.
        """
        if self.ball.y > self.window.height:
            return True

    def ball_rest(self):
        """
        Function: Set the initialization of the ball
        """
        self.set_ball_site()
        self.set_ball_velocity()
        while True:
            if self.star_switch:
                print(f'ball_rest {self.star_switch}')
                self.star_switch = False
                break
            pause(200)

    def ball_rebound_window(self):
        """
        Function: The ball bounces to the window.
        """
        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 ball_rebound_obj(self):
        """
        Function: The ball bounces to the object.
        """
        obj_u = self.window.get_object_at(self.ball.x + self.ball.width / 2,
                                          self.ball.y - 0.1)
        obj_d = self.window.get_object_at(self.ball.x + self.ball.width / 2,
                                          self.ball.y + self.ball.height + 0.1)
        obj_l = self.window.get_object_at(self.ball.x - 0.1,
                                          self.ball.y + self.ball.height / 2)
        obj_r = self.window.get_object_at(self.ball.x + self.ball.width + 0.1,
                                          self.ball.y + self.ball.height / 2)

        if obj_u is not None:
            self.ball.y = obj_u.y + obj_u.height
            self.__dy = -self.__dy
            if obj_u != self.paddle:
                self.window.remove(obj_u)
                self.brick_number -= 1
        elif obj_d is not None:
            self.ball.y = obj_d.y - self.ball.height
            self.__dy = -self.__dy
            if obj_d != self.paddle:
                self.window.remove(obj_d)
                self.brick_number -= 1
        elif obj_l is not None:
            self.ball.x = obj_l.x + obj_l.width
            self.__dx = -self.__dx
            if obj_l != self.paddle:
                self.window.remove(obj_l)
                self.brick_number -= 1
        elif obj_r is not None:
            self.ball.x = obj_r.x - self.ball.width
            self.__dx = -self.__dx
            if obj_r != self.paddle:
                self.window.remove(obj_r)
                self.brick_number -= 1
コード例 #14
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)
コード例 #15
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.
        window_width = brick_cols * (brick_width +
                                     brick_spacing) - brick_spacing
        window_height = brick_offset + 3 * (brick_rows *
                                            (brick_height + brick_spacing) -
                                            brick_spacing)
        self.window = GWindow(width=window_width,
                              height=window_height,
                              title=title)

        # Create a paddle.
        self.paddle = GRect(paddle_width, paddle_height)
        self.paddle.filled = True
        self.paddle.fill_color = 'black'

        # set paddle's instance variable
        self.pad_width = paddle_width
        self.pad_height = paddle_height
        self.pad_offset = paddle_offset
        """
        go will be a variable set to 0 or 1
        go equal 1 means it's touch paddle already and go to bricks
        go equals 0 means it's touch bricks and can go back to paddle  
        """
        self.go = 0

        # set ball's instance variable
        self.radius = ball_radius

        # Center a filled ball in the graphical window.
        self.ball = GOval(2 * self.radius, 2 * self.radius)
        self.set_ball()  # start set_ball method

        # set brick's instance variable
        self.bri_width = brick_width
        self.bri_height = brick_height
        self.bri_cols = brick_cols
        self.bri_rows = brick_rows
        self.bri_spacing = brick_spacing
        self.bri_offset = brick_offset
        self.brick = GRect(self.bri_width, self.bri_height)
        self.tot_brick = brick_rows * brick_cols
        self.move_brick = 0

        # Default initial velocity for the ball.
        self.__dx = 0  # use to storage the x speed
        self.__dy = 0  # use to storage the y speed
        self.dx = self.get_dx()  # get the x speed
        self.dy = self.get_dy()  # get the y speed

        # Initialize our mouse listeners.
        onmouseclicked(self.mouse_click)
        onmousemoved(self.paddle_move)

        # Draw bricks.
        self.set_brick()

        # set label for the text
        self.dead_label = GLabel('')
        self.cry_label = GLabel('')
        self.win_label = GLabel('')
        self.smile_label = GLabel('')

    def dead(self):
        """
        if the lives equal zero, it mean the player dead. so it will remove the ball and show you are dead
        """
        self.window.remove(self.ball)  # remove the ball
        self.dead_label = GLabel('You are dead')  # add label context
        self.dead_label.font = 'courier-40'  # set text size and type
        self.cry_label = GLabel('(〒︿〒)')  # add label context
        self.cry_label.font = 'courier-30'  # set text size and type
        self.window.add(self.dead_label,
                        x=self.window.width / 2 - 195,
                        y=self.window.height /
                        2)  # add on windows of specific location
        self.window.add(self.cry_label,
                        x=self.window.width / 2 - 80,
                        y=(self.window.height / 2 +
                           80))  # add on windows of specific location

    def win(self):
        """
        if all the bricks are remove, it means you win the game
        """
        self.window.remove(self.ball)  # remove the ball
        self.win_label = GLabel('Congratulation')  # add label context
        self.win_label.font = 'courier-40'  # set text size and type
        self.smile_label = GLabel('(ノ>ω<)ノ')  # add label context
        self.smile_label.font = 'courier-30'  # set text size and type
        self.window.add(self.win_label,
                        x=self.window.width / 2 - 250,
                        y=self.window.height /
                        2)  # add on windows of specific location
        self.window.add(self.smile_label,
                        x=self.window.width / 2 - 85,
                        y=(self.window.height / 2 +
                           80))  # add on windows of specific location

    def set_ball(self):
        """
        let a ball filled with color
        """
        self.ball.filled = True  # True to fill color
        self.ball.fill_color = 'navy'  # choose the color
        self.__dy = 0  # speed of initial position of the ball
        self.__dx = 0  # speed of initial position of the ball
        """
        put the ball on a specific location on window
        """
        self.window.add(self.ball,
                        x=(self.window.width - self.radius) / 2,
                        y=(self.window.height - self.radius) / 2)

    def detect_brick(self):
        """
        use four corner to detect if it touch a brick or not
        maybe_obj1 to maybe_obj4 is use to get if there is object or not
        """
        maybe_obj1 = self.window.get_object_at(self.ball.x, self.ball.y)
        maybe_obj2 = self.window.get_object_at(self.ball.x,
                                               self.ball.y + (2 * self.radius))
        maybe_obj3 = self.window.get_object_at(self.ball.x + (2 * self.radius),
                                               self.ball.y)
        maybe_obj4 = self.window.get_object_at(self.ball.x + (2 * self.radius),
                                               self.ball.y + (2 * self.radius))
        if maybe_obj1 is not self.paddle and maybe_obj1 is not None:  # if it has object and is not paddle - means brick
            self.window.remove(maybe_obj1)  # remove the object
            self.__dy = -self.__dy  # change the direction
            self.go = 0  # ball can touch the paddle now
            self.move_brick += 1  # number of remove brick plus 1
        elif maybe_obj2 is not self.paddle and maybe_obj2 is not None:  # if it has object and is not paddle - means brick
            self.window.remove(maybe_obj2)  # remove the object
            self.__dy = -self.__dy  # change the direction
            self.go = 0  # ball can touch the paddle now
            self.move_brick += 1  # number of remove brick plus 1
        elif maybe_obj3 is not self.paddle and maybe_obj3 is not None:  # if it has object and is not paddle - means brick
            self.window.remove(maybe_obj3)  # remove the object
            self.__dy = -self.__dy  # change the direction
            self.go = 0  # ball can touch the paddle now
            self.move_brick += 1  # number of remove brick plus 1
        elif maybe_obj4 is not self.paddle and maybe_obj4 is not None:  # if it has object and is not paddle - means brick
            self.window.remove(maybe_obj4)  # remove the object
            self.__dy = -self.__dy  # change the direction
            self.go = 0  # ball can touch the paddle now
            self.move_brick += 1  # number of remove brick plus 1

    def detect_paddle(self):
        """
        use four corner to detect if it touch a paddle or not
        maybe_obj1 to maybe_obj4 is use to get if there is object or not
        """
        maybe_obj1 = self.window.get_object_at(self.ball.x, self.ball.y)
        maybe_obj2 = self.window.get_object_at(self.ball.x + (2 * self.radius),
                                               self.ball.y)
        maybe_obj3 = self.window.get_object_at(self.ball.x + (2 * self.radius),
                                               self.ball.y)
        maybe_obj4 = self.window.get_object_at(self.ball.x + (2 * self.radius),
                                               self.ball.y + (2 * self.radius))
        if self.go == 0:  # go is use to let the ball detect the paddle only one times
            if maybe_obj1 is self.paddle:  # if it is paddle
                self.__dy = -self.__dy  # change the direction
                self.go = 1  # go equal 1 means it's touch and go to bricks
            elif maybe_obj2 is self.paddle:  # if it is paddle
                self.__dy = -self.__dy  # change the direction
                self.go = 1  # go equal 1 means it's touch and go to bricks
            elif maybe_obj3 is self.paddle:  # if it is paddle
                self.__dy = -self.__dy  # change the direction
                self.go = 1  # go equal 1 means it's touch and go to bricks
            elif maybe_obj4 is self.paddle:  # if it is paddle
                self.__dy = -self.__dy  # change the direction
                self.go = 1  # go equal 1 means it's touch and go to bricks

    def mouse_click(self, event):
        """
        if the x speed of ball and y speed of the ball is 0, it means it's a new start, and click will let the ball move
        :param event: mouse detect
        """
        if self.__dx == 0 and self.__dy == 0:  # x speed and y speed is both zero
            self.set_ball_velocity()  # decide the velocity of ball
            self.move_ball()  # ball move

    def wall_collision(self):
        """
        1.touch the wall, and it need to change the direction, beside, consider that it may not touch brick to reflect to
        paddle, so when touch the wall, go also need to change into 0
        2. ball can not touch the bottom of window, it will cause dead, using other way to figure iy out
        """
        if self.ball.x <= 0 or self.ball.x + self.ball.width >= self.window.width:  # touch the right and left wall
            self.__dx = -self.__dx  # change the direction
            self.go = 0  # it can touch the paddle now
        if self.ball.y <= 0:  # touch the up wall
            self.__dy = -self.__dy  # change the direction
            self.go = 0  # it can touch the paddle now

    def set_ball_velocity(self):
        """
        let the ball have speed and have different way to move forward
        """
        self.__dx = random.randint(
            0, MAX_X_SPEED)  # choose a speed rate from 0 and MAX_X_SPEED
        self.__dy = random.randint(
            0,
            INITIAL_Y_SPEED)  # choose a speed rate from 0 and INITIAL_Y_SPEED
        if self.__dx == 0:  # let ball not just move up and down
            self.__dx = random.randint(0,
                                       MAX_X_SPEED)  # re-choose a x speed rate
        if self.__dy == 0:  # let the ball not just move left and right
            self.__dy = random.randint(
                0, INITIAL_Y_SPEED)  # re-choose a y speed rate
        if random.random(
        ) > 0.5:  # let the ball have 50-50 chance to move left or right
            self.__dx = -self.__dx  # set to have opposite way
        if random.random(
        ) > 0.5:  # let the ball have 50-50 chance to move up or down
            self.__dy = -self.__dy  # set to have opposite way

    def move_ball(self):
        """
        ball move with the speed __dx and __dy
        """
        self.ball.move(self.__dx, self.__dy)

    def get_dx(self):
        """
        set a getter to get x speed
        :return: the value of x speed
        """
        return self.__dx  # return the x speed

    def get_dy(self):
        """
        getter to get y speed
        :return: the value of y speed
        """
        return self.__dy  # return the y speed

    def paddle_move(self, mouse):
        """
        mouse detect to let paddle follow the mouse
        :param mouse: mouse detect
        """
        paddle_x_position = mouse.x - (self.pad_width / 2
                                       )  # set into middle part of paddle
        if mouse.x + self.pad_width >= self.window.width:  # when the mouse on left side outside of windoe
            paddle_x_position = self.window.width - self.pad_width  # x set into left of window
        if mouse.x - self.pad_width <= 0:  # when the mouse on the right side outside of window
            paddle_x_position = 0  # x position set into right of window
        """
        add paddle into specific location on the window
        """
        self.window.add(self.paddle,
                        x=paddle_x_position,
                        y=self.window.height - self.pad_offset -
                        self.pad_height)

    def set_brick(self):
        """
        set brick into initial position
        """
        brick_width_in_window = 0  # initial position of brick in x
        brick_height_in_window = self.bri_offset  # initial position of brick in y
        for i in range(
                self.bri_rows):  # for loop based on how many rows it has
            for j in range(self.bri_cols
                           ):  # for loop based on how many columns it has
                self.brick = GRect(self.bri_width,
                                   self.bri_height)  # set a brick
                self.brick.filled = True  # True to fill with color
                if j % 4 == 0:  # base on the columns to choose color
                    self.brick.fill_color = 'red'
                    self.brick.color = 'red'
                if j % 4 == 1:  # base on the columns to choose color
                    self.brick.fill_color = 'salmon'
                    self.brick.color = 'salmon'
                if j % 4 == 2:  # base on the columns to choose color
                    self.brick.fill_color = 'orange'
                    self.brick.color = 'orange'
                if j % 4 == 3:  # base on the columns to choose color
                    self.brick.fill_color = 'tomato'
                    self.brick.color = 'tomato'
                self.window.add(
                    self.brick,
                    x=brick_width_in_window,
                    y=brick_height_in_window)  # add brick to windows
                """
                move forward to next columns position, include brick width and spacing 
                """
                brick_width_in_window += self.bri_width
                brick_width_in_window += self.bri_spacing
            brick_width_in_window = 0  # all the row start at x = 0
            """
            move forward to next rows position, include brick height and spacing 
            """
            brick_height_in_window += self.bri_height
            brick_height_in_window += self.bri_spacing
コード例 #16
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.game_started = False
        # Create a graphical window, with some extra space.
        window_width = brick_cols * (brick_width +
                                     brick_spacing) - brick_spacing
        window_height = brick_offset + 3 * (brick_rows *
                                            (brick_height + brick_spacing) -
                                            brick_spacing)
        self.window = GWindow(width=window_width,
                              height=window_height,
                              title=title)
        # Create a  score and a live
        self.sscore = GLabel('{score}: 0')
        self.sscore.font = '-20'
        self.window.add(self.sscore, x=0, y=self.sscore.height + 20)
        self.live = GLabel('3 :{live}')
        self.live.font = '-20'
        self.window.add(self.live,
                        x=window_width - self.live.width,
                        y=self.live.height + 20)
        # Create a paddle.
        self.paddle = GRect(paddle_width,
                            paddle_height,
                            x=window_width // 2 - paddle_width // 2,
                            y=window_height - paddle_offset)
        self.paddle.filled = True
        self.window.add(self.paddle)
        # Center a filled ball in the graphical window.
        self.ball = GOval(ball_radius * 2,
                          ball_radius * 2,
                          x=window_width // 2 - ball_radius,
                          y=window_height // 2 - ball_radius)
        self.ball.filled = True
        self.window.add(self.ball)
        # Default initial velocity for the ball.
        self.__dyr__dxr()
        # Initialize our mouse listeners.
        onmousemoved(self.move_paddle)
        onmouseclicked(self.start)
        # Draw bricks.
        for cols in range(brick_cols):
            for row in range(brick_rows):
                block = GRect(brick_width, brick_height)
                self.block = block
                block.filled = True
                block.color = self.block_color(cols)
                block.fill_color = self.block_color(cols)
                self.window.add(block,
                                x=(block.width + brick_spacing) * row,
                                y=brick_offset +
                                (brick_spacing + block.height) * cols)
        # draw a disturb playing block
        self.brick_width = brick_width
        self.disturb = GRect(brick_width + 20,
                             brick_height,
                             x=self.window.width - brick_width,
                             y=250)
        self.disturb.color = 'magenta'
        self.disturb.filled = True
        self.disturb.fill_color = 'magenta'
        self.window.add(self.disturb)
        self.d = -1
        # set self
        self.brick_c = brick_cols
        self.brick_row = brick_rows

    def __dyr__dxr(self):
        """
        set __dx and __dy
        """
        self.__dy = INITIAL_Y_SPEED
        self.__dx = random.randint(1, MAX_X_SPEED)
        if (random.random() > 0.5):
            self.__dx = -self.__dx

    def block_color(self, c):
        """
        :param c: brick's cols
        :return: the brick's color
        """
        if int(c // 2) == 0:
            return 'red'
        elif int(c // 2) == 1:
            return 'orange'
        elif int(c // 2) == 2:
            return 'yellow'
        elif int(c // 2) == 3:
            return 'green'
        elif int(c // 2) == 4:
            return 'blue'

    def move_paddle(self, event):
        """
        :param event: mouse
        """
        if not event.x < 0 + self.paddle.width // 2 and not event.x + self.paddle.width // 2 > self.window.width:
            self.paddle.x = event.x - self.paddle.width // 2

    def get_dx(self):
        """
        :return __dx: the speed of the ball x
        """
        return self.__dx

    def get_dy(self):
        """
        :return  __dy: the speed of the ball y
        """
        return self.__dy

    def bounce_ball(self, dx, dy, lives, score, delay, score2):
        """
        :param dx: the speed of the ball x
        :param dy: the speed of the ball y
        :param lives: the lives you left
        :param score: the score you have
        :param delay: the pause time
        :return lives, score, delay: the lives , score, pause time
        """
        self.disturb.x += self.d
        self.d -= 1
        if self.disturb.x <= 0:
            self.d = -self.d
        elif self.disturb.x > self.window.width - self.disturb.width:
            self.disturb.x = self.window.width - self.brick_width - 50
            self.d = -1
        # bounce at the edge
        if self.ball.x + self.ball.width > self.window.width or self.ball.x < 0:  # x
            if self.ball.y + self.ball.width > self.window.height or self.ball.y < 0:  # if the ball bounce at the corner
                dx *= -1
                dy *= -1
            else:
                dx *= -1
        elif self.ball.y < 0:  # y
            if self.ball.x + self.ball.width > self.window.width or self.ball.x < 0:  # if the ball bounce at the corner
                dy *= -1
                dx *= -1
            else:
                dy *= -1
        elif self.ball.y + self.ball.width > self.window.height:  # if the ball bounce at the ground
            lives -= 1  # live - 1
            self.game_started = False  # the ball is not bouncing now
            self.ball.x = self.window.width // 2 - self.ball.width // 2
            self.ball.y = self.window.height // 2 - self.ball.width // 2
            self.__dyr__dxr()
            self.sscore.text = '{score}: ' + str(score)
            self.live.text = str(lives) + ' :{live}'
            return lives, score, delay, score2, self.brick_c * self.brick_row
        # bounce at the block
        elif self.window.get_object_at(self.ball.x, self.ball.y):
            maybe_obj = self.window.get_object_at(self.ball.x, self.ball.y)
            if self.ball.y > 50:
                if self.ball.y < 250 and self.ball.y > 49:
                    self.window.remove(maybe_obj)
                    score += self.score(maybe_obj.y)
                    score2 += 1
                    delay -= 0.2
                elif self.ball.y > 350:
                    self.ball.y = self.paddle.y - self.ball.height
                if self.ball.y > 49:
                    dy *= -1
        elif self.window.get_object_at(self.ball.x + BALL_RADIUS * 2,
                                       self.ball.y):
            maybe_obj = self.window.get_object_at(
                self.ball.x + self.ball.width, self.ball.y)
            if self.ball.y > 50:
                if self.ball.y < 250 and self.ball.y > 49:
                    self.window.remove(maybe_obj)
                    score += self.score(maybe_obj.y)
                    score2 += 1
                    delay -= 0.2
                elif self.ball.y > 350:
                    self.ball.y = self.paddle.y - self.ball.height
                if self.ball.y > 49:
                    dy *= -1
        elif self.window.get_object_at(self.ball.x,
                                       self.ball.y + self.ball.width):
            maybe_obj = self.window.get_object_at(
                self.ball.x, self.ball.y + self.ball.width)
            if self.ball.y > 50:
                if self.ball.y + self.ball.width < 250 and self.ball.y + self.ball.width > 49:
                    self.window.remove(maybe_obj)
                    score += self.score(maybe_obj.y)
                    score2 += 1
                    delay -= 0.2
                elif self.ball.y > 350:
                    self.ball.y = self.paddle.y - self.ball.height
                if self.ball.y > 49:
                    dy *= -1
        elif self.window.get_object_at(self.ball.x + self.ball.width,
                                       self.ball.y + self.ball.width):
            maybe_obj = self.window.get_object_at(
                self.ball.x + self.ball.width, self.ball.y + self.ball.width)
            if self.ball.y > 50:
                if self.ball.y + self.ball.width < 250 and self.ball.y + self.ball.width > 49:
                    self.window.remove(maybe_obj)
                    score += self.score(maybe_obj.y)
                    score2 += 1
                    delay -= 0.2
                elif self.ball.y > 350:
                    self.ball.y = self.paddle.y - self.ball.height
                if self.ball.y > 49:
                    dy *= -1
        self.ball.move(dx, dy)
        self.__dx = dx
        self.__dy = dy
        self.sscore.text = '{score}: ' + str(score)
        self.live.text = str(lives) + ' :{live}'
        return lives, score, delay, score2, self.brick_c * self.brick_row

    def start(self, event):
        """
        :param event: mouse
        """
        if not self.game_started:
            self.game_started = True

    def get_game_state(self):
        """
        :return game_start: is the game running?
        """
        return self.game_started

    def score(self, y):
        if y < 80:
            return 5
        elif y < 120:
            return 4
        elif y < 160:
            return 3
        elif y < 200:
            return 2
        elif y < 240:
            return 1

    def remove_all(self, score):
        self.window.remove(self.ball)
        self.window.remove(self.paddle)
        self.window.remove(self.sscore)
        self.window.remove(self.live)
        self.window.remove(self.disturb)
        if score == 300:
            win = GLabel('YOU WIN!!  . .    YA!!!!!!!!!\n                  U',
                         x=50,
                         y=350)
            win.font = '-20'
            self.window.add(win)
        else:
            sscore = GLabel('YOUR SCORE IS:' + str(score) +
                            '\n HA HA HA YOU LOSE!!!',
                            x=50,
                            y=350)
            sscore.font = '-20'
            self.window.add(sscore)
コード例 #17
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)
        # Create a paddle.
        self.paddle = GRect(width=PADDLE_WIDTH, height=PADDLE_HEIGHT, x=(self.window_width-PADDLE_WIDTH)/2,
                            y=self.window_height-PADDLE_OFFSET+paddle_height)
        self.paddle.color = 'Navy'
        self.paddle.filled = True
        self.paddle.fill_color = 'Navy'
        self.window.add(self.paddle)
        # Center a filled ball in the graphical window.
        self.ball = GOval(width=2*ball_radius, height=2*ball_radius, x=self.window_width/2-ball_radius,
                          y=(self.window_height-PADDLE_HEIGHT)/2)
        self.ball.filled = True
        self.ball.color = 'red'
        self.ball.fill_color = 'red'
        self.window.add(self.ball)
        # Default initial velocity for the ball.
        self.__dy = INITIAL_Y_SPEED
        self.__dx = random.randint(1, MAX_X_SPEED)
        if random.random() > 0.5:
            self.__dx = -self.__dx

        self.ball_radius = BALL_RADIUS
        self.switch = False

        # Initialize our mouse listeners.
        onmouseclicked(self.start)
        onmousemoved(self.paddle_move)
        # Draw bricks.
        for i in range(brick_rows):
            for j in range(brick_cols):
                self.brick = GRect(width=brick_width, height=brick_height)
                self.window.add(self.brick, x=(brick_width+brick_spacing)*j,
                                y=BRICK_OFFSET+(brick_height+brick_spacing)*i)
                self.brick.filled = True
                if i <= 1:
                    self.brick.color = 'red'
                    self.brick.fill_color = 'red'
                elif 2 <= i <= 3:
                    self.brick.color = 'orange'
                    self.brick.fill_color = 'orange'
                elif 4 <= i <= 5:
                    self.brick.color = 'yellow'
                    self.brick.fill_color = 'yellow'
                elif 6 <= i <= 7:
                    self.brick.color = 'green'
                    self.brick.fill_color = 'green'
                elif 8 <= i <= 9:
                    self.brick.color = 'blue'
                    self.brick.fill_color = 'blue'
                else:
                    self.brick.color = 'grey'
                    self.brick.fill_color = 'grey'
        self.check_hit_object()
        self.brick_counts = BRICK_ROWS * BRICK_COLS

    def check_hit_object(self):
        a = self.window.get_object_at(self.ball.x, self.ball.y)
        b = self.window.get_object_at(self.ball.x+2*self.ball_radius, self.ball.y)
        c = self.window.get_object_at(self.ball.x, self.ball.y+2*self.ball_radius)
        d = self.window.get_object_at(self.ball.x+2*self.ball_radius, self.ball.y+2*self.ball_radius)
        if c is self.paddle or d is self.paddle:
            self.__dy = -1 * self.__dy
        elif a is not None and a is not self.paddle:
            self.window.remove(a)
            self.__dy = -1 * self.__dy
            self.brick_counts -= 1
        elif b is not None and b is not self.paddle:
            self.window.remove(b)
            self.__dy = -1 * self.__dy
            self.brick_counts -= 1
        elif c is not None and c is not self.paddle:
            self.window.remove(c)
            self.__dy = -1 * self.__dy
            self.brick_counts -= 1
        elif d is not None and d is not self.paddle:
            self.window.remove(d)
            self.__dy = -1 * self.__dy
            self.brick_counts -= 1

    def get_vy(self):
        return self.__dy

    def get_vx(self):
        return self.__dx

    def start(self, event):
        self.switch = True

    def ball_move(self, vx, vy):
        self.ball.move(dx=vx, dy=vy)

    def paddle_move(self, mouse):
        if self.paddle.width/2 < mouse.x <= self.window.width-(self.paddle.width / 2):
            self.paddle.x = mouse.x-self.paddle.width/2
        elif mouse.x <= self.paddle.width/2:
            self.paddle.x = 0
        elif mouse.x >= self.window.width-(self.paddle.width/2):
            self.paddle.x = self.window.width-self.paddle.width

    def set_vx(self, new_speed):
        self.__dx = new_speed

    def set_vy(self, new_speed):
        self.__dy = new_speed

    def reset(self):
        self.switch = False
        self.ball.x = self.window_width/2-self.ball_radius
        self.ball.y = (self.window_height-PADDLE_HEIGHT)/2
コード例 #18
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.ball_radius = ball_radius
        self.over = GLabel('GAME OVER')
        self.over.color = 'red'

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

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

        # Default initial velocity for the ball.
        self.__dx = 0
        self.__dy = 0

        # Initialize our mouse listeners.
        onmousemoved(self.move_pad)
        onmouseclicked(self.start_check)

        # the checker to decide whether the game can start,if 1, start, if 0, pending
        self.chk = 0

        # Draw bricks.
        for y in range(
                brick_offset,
                brick_rows * (brick_height + brick_spacing) + brick_offset,
                brick_height + brick_spacing):
            for x in range(0, self.window_width - brick_width + 1,
                           brick_width + brick_spacing):
                self.brick = GRect(brick_width, brick_height)
                self.brick.filled = True
                self.brick.fill_color = 'yellow'
                self.brick.color = 'green'
                self.window.add(self.brick, x=x, y=y)
        self.num_bricks = brick_cols * brick_rows

        # Center a filled ball in the graphical window.
        self.ball = GOval(ball_radius * 2, ball_radius * 2)
        self.ball.filled = True
        self.ball.fill_color = 'navy'
        self.ball.color = 'blue'
        self.window.add(self.ball,
                        x=self.window_width / 2 - ball_radius,
                        y=self.window_height / 2 - ball_radius)

    def move_pad(self, event):
        """
        To make the paddle moves following the mouse
        :param event: int, the coordinate(x,y) of the mouse
        """
        if event.x < self.pad.width / 2:
            self.pad.x = 0
        elif event.x > self.window.width - self.pad.width / 2:
            self.pad.x = self.window.width - self.pad.width
        else:
            self.pad.x = event.x - self.pad.width / 2

    def get_dx(self):
        """
        To return the hidden object dx
        :return: int, the distance to move on x-coordinate per movement
        """
        return self.__dx

    def get_dy(self):
        """
        To return the hidden object dy
        :return: int, the distance to move on y-coordinate per movement
        """
        return self.__dy

    def reset_ball(self):
        """
        To set the ball at initial position and resetting chk to 0
        """
        self.window.add(self.ball,
                        x=self.window_width / 2 - self.ball_radius,
                        y=self.window_height / 2 - self.ball_radius)
        self.chk = 0

    def start_check(self, m):
        """
        Check if the ball is at the center, if yes, start bouncing; if no, the click is ignored
        """
        if self.ball.x == self.window_width / 2 - self.ball_radius and self.ball.y == self.window_height / 2 - \
                self.ball_radius and self.num_bricks > 0:
            self.__dx = random.randint(1, MAX_X_SPEED)
            self.__dy = INITIAL_Y_SPEED
            if (random.random()) > 0.5:
                self.__dx = -self.__dx
            self.chk = 1

    def get_chk(self):
        """
        To return chk
        :return: int, the checker to detect whether the game should starts
        """
        return self.chk

    def check_collision(self):
        """
        Check if the 4 vertex touch paddle or brick
        :return: str or object, to indicate if the ball touches anything
        """
        for i in range(0, self.ball_radius * 2 + 1, self.ball_radius * 2):
            for j in range(0, self.ball_radius * 2 + 1, self.ball_radius * 2):
                is_obj = self.window.get_object_at(self.ball.x + j,
                                                   self.ball.y + i)
                if is_obj is not None:
                    if is_obj is self.pad:
                        self.ball.move(0, -self.pad.height)
                        print('touch pad')
                        return 'pad'
                    else:
                        self.window.remove(is_obj)
                        self.num_bricks -= 1
                        print('touch brick')
                        return 'brick'
                return 'not collide'
コード例 #19
0
class BreakoutGraphics:
    # Constructor
    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.
        window_width = brick_cols * (brick_width +
                                     brick_spacing) - brick_spacing
        window_height = brick_offset + 3 * (brick_rows *
                                            (brick_height + brick_spacing) -
                                            brick_spacing)
        self.window = GWindow(width=window_width,
                              height=window_height,
                              title=title)

        # Create a paddle.
        self.paddle = GRect(paddle_width, paddle_height)
        self.paddle.filled = True
        self.window.add(self.paddle,
                        x=(window_width - self.paddle.width) / 2,
                        y=window_height - paddle_offset)

        # Center a filled ball in the graphical window.
        self.ball = GOval(ball_radius * 2, ball_radius * 2)
        self.ball.filled = True
        self.window.add(self.ball,
                        x=(window_width - ball_radius) / 2,
                        y=(window_height - ball_radius) / 2)

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

        # Initialize our mouse listeners.
        onmouseclicked(self.game_start)  # Todo: Need fixing!!!
        self.mouse_lock = False
        onmousemoved(self.paddle_move)

        # Draw bricks.
        for i in range(brick_rows):
            self.brick_x = 0
            self.brick_y = brick_offset
            self.brick_y += (brick_height + brick_spacing) * i
            for j in range(brick_cols):
                self.brick = GRect(brick_width, brick_height)
                self.brick.filled = True
                self.brick_color(i)
                self.window.add(self.brick, x=self.brick_x, y=self.brick_y)
                self.brick_x += (brick_width + brick_spacing)
        self.brick_left = brick_rows * brick_cols

        # For detecting whether ball hit objects.
        self.obj = 0

    # Methods
    def game_start(self, event):  # Todo: Need fixing!!
        """
        To detect whether the game has started or not.
                If not, the game will start and turns the mouse lock on (True).
                If yes, further mouse clicks should have no effects.
        """
        self.mouse_lock = True

    def move_ball(self):
        """
        Ball move by the velocity of __dx and __dy as defined in the constructor.
        """
        self.ball.move(self.__dx, self.__dy)

    def reset_ball(self):
        """
        Reset the ball back to its initial position.
        Mouse lock off (False).
        """
        self.ball.x = (self.window.width - self.ball.width) / 2
        self.ball.y = (self.window.height - self.ball.height) / 2
        self.mouse_lock = False

    def handle_collision(self):
        """
        Updates __dx and __dy depending on whether or not ball has hit a wall, the paddle or bricks.
        """
        # Hit left/right wall
        if self.ball.x <= 0 or self.ball.x >= self.window.width - self.ball.width:
            self.__dx = -self.__dx
        # Hit top/bottom wall
        if self.ball.y <= 0 or self.ball.y >= self.window.height - self.ball.height:
            self.__dy = -self.__dy

        # Hit paddles/bricks
        self.detect_obj()
        self.hit_paddle_or_bricks()

    def detect_obj(self):
        """
        Detect if the ball hit any objects.
        """
        self.obj = self.window.get_object_at(self.ball.x, self.ball.y)
        if self.obj is not None:
            return self.obj
        else:
            self.obj = self.window.get_object_at(self.ball.x,
                                                 self.ball.y + self.ball.width)
            if self.obj is not None:
                return self.obj
            else:
                self.obj = self.window.get_object_at(
                    self.ball.x + self.ball.width, self.ball.y)
                if self.obj is not None:
                    return self.obj
                else:
                    self.obj = self.window.get_object_at(
                        self.ball.x + self.ball.width,
                        self.ball.y + +self.ball.width)
                    if self.obj is not None:
                        return self.obj
                    else:
                        return None

    def hit_paddle_or_bricks(self):
        """
        Identify whether the object(s) hit is the paddle or brick.
        """
        if self.obj == self.paddle:
            self.__dy = -self.__dy
        elif self.obj is not None and self.obj is not self.paddle:
            self.__dy = -self.__dy
            self.window.remove(self.obj)
            self.brick_left -= 1

    def ball_out(self):
        """
        Return whether or not the ball has fallen below the paddle/bottom wall.
        """
        is_ball_out = self.ball.y >= self.window.height - self.ball.height
        return is_ball_out

    def paddle_move(self, event):
        """
        Sync the center of the paddle and the location of the mouse while moving.
        """
        if event.x - self.paddle.width / 2 <= 0:
            self.paddle.x = 0
        elif self.window.width - event.x <= self.paddle.width / 2:
            self.paddle.x = self.window.width - self.paddle.width
        else:
            self.paddle.x = event.x - self.paddle.width / 2

    def brick_color(self, i):
        """
        Sets the bricks in color designated in the handout.
        """
        if i <= 1:
            self.brick.fill_color = 'red'
        elif 1 < i <= 3:
            self.brick.fill_color = 'orange'
        elif 3 < i <= 5:
            self.brick.fill_color = 'yellow'
        elif 5 < i <= 7:
            self.brick.fill_color = 'green'
        elif 7 < i <= 9:
            self.brick.fill_color = 'blue'
        else:
            pass
コード例 #20
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'):
        """
        The basic parameters for building these breakout game.

        :param ball_radius: The radius of the ball.
        :param paddle_width: The width of the paddle.
        :param paddle_height: The height of the paddle.
        :param paddle_offset: The distance between paddle and the bottom of the window.
        :param brick_rows: The number of rows in bricks.
        :param brick_cols: The number of column in bricks.
        :param brick_width: The width of each brick.
        :param brick_height: The height of each brick.
        :param brick_offset: The distance between the first row of bricks and the top of the window.
        :param brick_spacing: The spacing between each brick.
        :param title: The name of this program.
        """

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

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

        # Center a filled ball in the graphical window
        self.ball = GOval(ball_radius * 2,
                          ball_radius * 2,
                          x=(self.window_width - ball_radius * 2) / 2,
                          y=(self.window_height - ball_radius * 2) / 2)
        self.ball.filled = True
        self.ball.fill_color = 'black'
        self.window.add(self.ball)
        self.ball_radius = ball_radius

        # Default initial velocity for the ball
        self.__dx = 0  # self.__dx = random.randint(1, MAX_X_SPEED)
        self.__dy = 0  # self.__dy = INITIAL_Y_SPEED
        # if random.random() > 0.5:
        #     self.__dx = -self.__dx
        # The above is the mistake I made during doing this homework.

        # Draw bricks
        for i in range(brick_cols):
            for j in range(brick_rows):
                # Crucial point! This can't be placed at the outside of for loop.
                brick = GRect(brick_width, brick_height)
                brick.x = (brick_width + brick_spacing) * i
                brick.y = brick_offset + (brick_height + brick_spacing) * j
                brick.filled = True
                if j < 2:
                    brick.fill_color = 'red'
                elif j < 4:
                    brick.fill_color = 'orange'
                elif j < 6:
                    brick.fill_color = 'yellow'
                elif j < 8:
                    brick.fill_color = 'green'
                elif j < 10:
                    brick.fill_color = 'blue'
                elif j < 12:
                    brick.fill_color = 'teal'
                elif j < 14:
                    brick.fill_color = 'chocolate'
                self.window.add(brick)

        # Initialize our mouse listeners
        onmouseclicked(self.is_start_game)
        onmousemoved(self.moving_paddle)

        # Total bricks
        self.total_bricks = brick_cols * brick_rows

    def is_start_game(
        self, event
    ):  # Crucial point!!! Stuck here for three days! The initial velocity!
        """
        The check point of the game start.

        :param event: The information of the mouse, including (x,y) of it.
        :return: Set the __dx and __dy of the ball.
        """
        if event.x != -1 and event.y != -1 and self.__dx == 0 and self.__dy == 0:
            self.__dx = random.randint(1, MAX_X_SPEED)
            self.__dy = INITIAL_Y_SPEED
            if random.random() > 0.5:
                self.__dx = -self.__dx

    def check_for_collisions(self):
        """
        Four check points of the ball to check the collision with objects.

        :return: boolean value. Build the information of object that the ball collide with.
        """
        one = self.window.get_object_at(self.ball.x, self.ball.y)
        two = self.window.get_object_at(self.ball.x + 2 * self.ball_radius,
                                        self.ball.y)
        three = self.window.get_object_at(self.ball.x,
                                          self.ball.y + 2 * self.ball_radius)
        four = self.window.get_object_at(self.ball.x + 2 * self.ball_radius,
                                         self.ball.y + 2 * self.ball_radius)
        if one is not None:
            self.obj = self.window.get_object_at(self.ball.x, self.ball.y)
            return True
        elif two is not None:
            self.obj = self.window.get_object_at(
                self.ball.x + 2 * self.ball_radius, self.ball.y)
            return True
        elif three is not None:
            self.obj = self.window.get_object_at(
                self.ball.x, self.ball.y + 2 * self.ball_radius)
            return True
        elif four is not None:
            self.obj = self.window.get_object_at(
                self.ball.x + 2 * self.ball_radius,
                self.ball.y + 2 * self.ball_radius)
            return True

    def check_object_type(self):
        """
        The objects above the half of the window height are bricks and the object below the half of the window height is paddle.

        :return: boolean value. Bricks return True and paddle returns False.
        """
        if self.ball.y > self.window.height / 2:
            return True
        else:
            return False

    def moving_ball(self):
        """
        The method for moving ball.

        :return: The moving result of the ball.
        """
        self.ball.move(self.__dx, self.__dy)

    def moving_paddle(self, event):
        """
        The method for moving paddle.

        :param event: The information of the mouse, including (x,y) of it.
        :return: The moving result of the paddle.
        """
        if event.x - self.paddle_width / 2 >= 0 and event.x - self.paddle_width / 2 <= self.window_width - self.paddle_width:
            self.paddle.x = event.x - self.paddle_width / 2

    def reset_ball(self):
        """
        As the ball falls below the paddle and the game hasn't overed, the ball will be reset to the original position.

        :return: The ball at the original position.
        """
        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.fill_color = 'black'
        self.window.add(self.ball)
        self.ball_radius = self.ball_radius
        self.__dx = 0
        self.__dy = 0

    def set_dx(self, new_dx):
        """
        Set the new __dx.

        :param new_dx: The new dx.
        :return: __dx.
        """
        self.__dx = new_dx

    def set_dy(self, new_dy):
        """
        Set the new __dy.

        :param new_dy: The new dy.
        :return: __dy.
        """
        self.__dy = new_dy

    def get_dx(self):
        """
        Get the information of __dx from class BreakoutGraphics.

        :return: The __dx for the ball.
        """
        return self.__dx

    def get_dy(self):
        """
        Get the information of __dy from class BreakoutGraphics.

        :return: The __dy for the ball.
        """
        return self.__dy

    def set_dx_collision(self, new_dx):
        """
        Set the new __dx for ball after colliding with bricks.

        :param new_dx: The new dx.
        :return: __dx.
        """
        if random.random() > 0.5:
            self.__dx = new_dx
        else:
            self.__dx = -new_dx

    def game_over(self):
        """
        The label for game over.

        :return: The label for game over.
        """
        label = GLabel('Game Over!!!')
        # The condition below is for 10*10 bricks.
        # If coder change the number of rows or columns, the size would probably not fit.
        label.font = '-40'
        self.window.add(label,
                        x=self.window_width / 2 - 100,
                        y=self.window_height / 2 + 100)

    def game_win(self):
        """
        The label for game win.

        :return: The label for game win.
        """
        label = GLabel('You Win!!!')
        # The condition below is for 10*10 bricks.
        # If coder change the number of rows or columns, the size would probably not fit.
        label.font = '-40'
        self.window.add(label,
                        x=self.window_width / 2 - 100,
                        y=self.window_height / 2 + 100)
コード例 #21
0
class NoBreakout(NoGraphics):
    def __init__(self, lives=LIVES, frame_rate=FRAME_RATE):
        super().__init__()
        self.__game_lives = lives
        self.__game_integral = 0
        self.__frame_rate = 1000 / frame_rate

        self.__obj_game_integral = None
        self.__obj_game_lives = None
        self.__obj_game_brick = None

        # Identify code
        self.__menu_code = 9  # 介面碼 0:main 1:game 9:none
        self.__status_code = 0  # 狀態碼 0:wait 1:start 9:reade
        self.__obj_menu_code = None
        self.__obj_status_code = None

        # main menu
        self.__obj_main_txt_1 = None
        self.__obj_main_txt_2 = None
        self.__obj_main_txt_start = None
        self.__obj_main_button = None
        self.__obj_main_zone = None

        # game menu
        self.__obj_game_zone_line_u = None
        self.__obj_game_zone_line_d = None
        self.__obj_game_zone_line_l = None
        self.__obj_game_zone_line_r = None
        self.brick = None

        self.__game_zone_u = 0
        self.__game_zone_d = 0
        self.__game_zone_l = 0
        self.__game_zone_r = 0

        self.__game_zone_w = 0
        self.__game_zone_h = 0

        # game brick
        self.__game_brick_num = 0

        # game ball
        self.__game_ball_size = BALL_SIZE
        self.__obj_game_ball = None

        self.__game_ball_vx = 0
        self.__game_ball_vy = 0

        self.__start_bool = False

        # game paddle
        self.__game_paddle_w = PADDLE_WIDTH
        self.__game_paddle_h = PADDLE_HEIGHT
        self.__game_paddle_offset = PADDLE_OFFSET
        self.__obj_game_paddle = None

        self.main_code_star()
        # self.main_button()  # 首頁返回鈕
        print(f'<<< end >>>')

    def main_code_star(self):
        # self.__obj_menu_code=GLabel(f'menu :{self.__menu_code}',x= self.__boundary_x + 1000, y=self.__boundary_y + 300)
        # self.__obj_menu_code.font = '-50'
        # self.window.add(self.__obj_menu_code)
        #
        # self.__obj_status_code=GLabel(f'status :{self.__status_code}',x= self.__boundary_x + 1000, y=self.__boundary_y + 400)
        # self.__obj_status_code.font = '-50'
        # self.window.add(self.__obj_status_code)

        self.__obj_game_lives = GLabel(f'lives = {self.__game_lives}',
                                       x=self.__boundary_x + 750,
                                       y=self.__boundary_y + 700)
        self.__obj_game_lives.font = '-25'
        self.window.add(self.__obj_game_lives)

        self.__obj_game_integral = GLabel(f'integral = {self.__game_integral}',
                                          x=self.__boundary_x + 0,
                                          y=self.__boundary_y + 700)
        self.__obj_game_integral.font = '-25'
        self.window.add(self.__obj_game_integral)

        # self.__obj_game_brick = GLabel(f'status :{self.__game_brick_num}', x=self.__boundary_x + 1000, y=self.__boundary_y + 200)
        # self.__obj_game_brick.font = '-50'
        # self.window.add(self.__obj_game_brick)

    def main_code_update(self):
        # self.__obj_menu_code.text = f'menu :{self.__menu_code}'
        # self.__obj_status_code.text = f'status :{self.__status_code}'
        self.__obj_game_lives.text = f'lives :{self.__game_lives}'
        self.__obj_game_integral.text = f'integral :{self.__game_integral}'
        # self.__obj_game_brick.text = f'brick :{self.__game_brick_num}'

    def mouse_start(self):
        onmousemoved(self.move_perform)
        onmouseclicked(self.click_perform)

    def main_menu(self, dx=0, dy=0):
        self.__menu_code = 0

        # 建立邊界區
        self.boundary_zone()

        # 大標體
        self.__obj_main_txt_1 = GLabel('Breakout clone',
                                       x=200 + self.__boundary_x + dx,
                                       y=200 + self.__boundary_y + dy)
        self.__obj_main_txt_1.font = f'Times New Roman-100'
        self.window.add(self.__obj_main_txt_1)

        # 中標題
        self.__obj_main_txt_2 = GLabel('Maker : Tsai NoNo',
                                       x=200 + self.__boundary_x + dx,
                                       y=300 + self.__boundary_y + dy)
        self.__obj_main_txt_2.font = f'Times New Roman-50'
        self.__obj_main_txt_2.color = "gray"
        self.window.add(self.__obj_main_txt_2)

        # 開始
        self.__obj_main_txt_start = GLabel('Start',
                                           x=200 + self.__boundary_x + dx,
                                           y=400 + self.__boundary_y + dy)
        self.__obj_main_txt_start.font = f'Times New Roman-50'
        self.__obj_main_txt_start.color = "dimgray"
        self.window.add(self.__obj_main_txt_start)
        self.main_code_update()

    def game_menu(self):
        self.__menu_code = 1
        self.boundary_zone()
        self.main_code_update()

    def menu_exit(self):
        """
        清除所有的物件
        1.地毯式:優點:程式短,無差別清除,缺點:較久,無法針對特定
        2.標記式:優點:快速,針對特定清除,缺點:每一筆都需記憶變數
        """

        for i in range(0, self.window.width - 300, 20):
            for j in range(0, self.window.height, 25):
                get_obj = self.window.get_object_at(i, j)
                self.window.remove(get_obj)
        #
        self.window.remove(self.__obj_main_txt_1)
        self.window.remove(self.__obj_main_txt_2)
        self.window.remove(self.__obj_main_txt_start)
        self.window.remove(self.__obj_main_zone)
        #
        self.window.remove(self.__obj_game_zone_line_u)
        self.window.remove(self.__obj_game_zone_line_d)
        self.window.remove(self.__obj_game_zone_line_l)
        self.window.remove(self.__obj_game_zone_line_r)
        #
        self.window.remove(self.__obj_game_ball)
        self.window.remove(self.__obj_game_paddle)

    def main_button(self, dx=0, dy=0):
        self.__obj_main_button = GOval(50,
                                       50,
                                       x=1100 + self.__boundary_x + dx,
                                       y=600 + self.__boundary_y + dy)
        self.__obj_main_button.color = 'red'
        self.__obj_main_button.filled = True
        self.__obj_main_button.fill_color = 'red'
        self.window.add(self.__obj_main_button)

    def boundary_zone(self, dx=0, dy=0):

        if self.__menu_code == 0:
            # Main Zone
            main_zone_w = self.window.width - 2 * self.__boundary_x
            main_zone_h = self.window.height - 2 * self.__boundary_y

            self.__obj_main_zone = GRect(main_zone_w,
                                         main_zone_h,
                                         x=self.__boundary_x + dx,
                                         y=self.__boundary_y + dy)
            self.window.add(self.__obj_main_zone)

        elif self.__menu_code == 1:
            # Game Zone
            self.__game_zone_w = self.window.width - 2 * self.__boundary_x - 300
            self.__game_zone_h = self.window.height - 2 * self.__boundary_y

            self.__game_zone_u = self.__boundary_y
            self.__game_zone_d = self.__boundary_y + self.__game_zone_h
            self.__game_zone_l = self.__boundary_x
            self.__game_zone_r = self.__boundary_x + self.__game_zone_w

            print(f'{self.__game_zone_w} , {self.__game_zone_h}')

            self.__obj_game_zone_line_u = GLine(self.__game_zone_l,
                                                self.__game_zone_u,
                                                self.__game_zone_r,
                                                self.__game_zone_u)
            self.__obj_game_zone_line_d = GLine(self.__game_zone_l,
                                                self.__game_zone_d,
                                                self.__game_zone_r,
                                                self.__game_zone_d)
            self.__obj_game_zone_line_l = GLine(self.__game_zone_l,
                                                self.__game_zone_u,
                                                self.__game_zone_l,
                                                self.__game_zone_d)
            self.__obj_game_zone_line_r = GLine(self.__game_zone_r,
                                                self.__game_zone_u,
                                                self.__game_zone_r,
                                                self.__game_zone_d)

            self.window.add(self.__obj_game_zone_line_u)
            self.window.add(self.__obj_game_zone_line_d)
            self.window.add(self.__obj_game_zone_line_l)
            self.window.add(self.__obj_game_zone_line_r)

    def click_perform(self, mouse):
        get_obj = self.window.get_object_at(mouse.x, mouse.y)

        # 進入遊戲畫面
        if get_obj == self.__obj_main_txt_start and self.__menu_code != 1 and self.__status_code == 0:
            self.__menu_code = 1  # feedback
            print("<<< up to game >>>")
            self.menu_exit()
            self.game_menu()
            self.game_brick_build(self.game_level_formation(level=1))
            self.game_ball_build()
            self.game_paddle_build()
            self.set_game_ball_rest()
            self.game_star()
        # 進入主畫面
        # elif get_obj == self.__obj_main_button and self.__menu_code != 0:
        #     self.__menu_code = 0    # feedback
        #     # self.__status_code == 0
        #     print(f'get_obj:self.__obj_main_button menu_code:{self.__menu_code} status_code:{self.__status_code}')
        #     print("<<< up to main >>>")
        #     self.menu_exit()
        #     self.main_menu()
        elif get_obj == self.__obj_game_ball and self.__menu_code == 1 and self.__status_code == 0:
            print(
                f'get_obj:self.__obj_game_ball menu_code:{self.__menu_code} status_code:{self.__status_code}'
            )
            print(f'ok star')
            self.__start_bool = True
            self.main_code_update()
        elif get_obj is not None:
            print(f'obj')
            print(
                f'get_obj:??? menu_code:{self.__menu_code} status_code:{self.__status_code}'
            )
        else:
            print(f'None')
        # print(str(get_obj))

    def move_perform(self, mouse):
        get_obj = self.window.get_object_at(mouse.x, mouse.y)

        if self.__menu_code == 0:
            if get_obj == self.__obj_main_txt_start:
                self.__obj_main_txt_start.color = "red"
            else:
                self.__obj_main_txt_start.color = "dimgray"

        # 針對遊戲畫面,做各狀態判斷
        elif self.__menu_code == 1:
            self.__game_paddle_move(mouse)
            if self.__status_code == 0:
                if get_obj == self.__obj_game_ball:
                    self.__obj_game_ball.fill_color = "red"
            else:
                self.__obj_game_ball.fill_color = "black"

        # if get_obj == self.__obj_main_button:
        #     self.__obj_main_button.color = "dimgray"
        #     self.__obj_main_button.fill_color = "dimgray"
        # else:
        #     self.__obj_main_button.color = "red"
        #     self.__obj_main_button.fill_color = "red"

    @staticmethod
    def game_level_formation(self, level=1):
        """
        0 一單位空
        1 一單位磚
        2 二單位磚
        3 三單位磚
        _ NONE

        :param level:
        :return:
        """
        if level == 1:
            formation = "1111111111|" \
                        "1111111111|" \
                        "1111111111|" \
                        "1111111111|" \
                        "1111111111|" \
                        "1111111111|" \
                        "1111111111|" \
                        "1111111111|" \
                        "1111111111|" \
                        "1111111111|" \
                        "1111111111|"

        return formation

    def game_brick_build(self,
                         formation,
                         b_w=85,
                         b_h=20,
                         b_offset_x=5,
                         b_offset_y=30,
                         b_spacing=5,
                         row_max=10,
                         cow_max=10):
        j = 0
        num_cow = 0
        dy = self.__boundary_y + b_offset_y
        while formation.find('|') != -1:

            if num_cow == cow_max:
                break

            # 抓第一段字串
            site = formation[:formation.find('|')]
            # 存放剩下字串
            formation = formation[formation.find('|') + 1:]

            # 將字串轉換成磚塊
            dx = self.__boundary_x + b_offset_x / 2
            num_row = 0
            for i in site:
                if i != '0' and i != '_':
                    num_row += int(i)
                    if num_row <= row_max:
                        self.brick = GRect(b_w * int(i) + b_spacing *
                                           (int(i) - 1),
                                           b_h,
                                           x=dx,
                                           y=dy)
                        dx += (b_w + b_spacing) * int(i)
                        self.__game_brick_num += 1
                elif i == '0':
                    num_row += 1
                    dx += b_w + b_spacing

                self.brick.filled = True
                self.window.add(self.brick)
                self.game_brick_color(j)

            print(f'{site} {j} {num_row} {self.__game_brick_num}')

            dy += b_h + b_spacing
            j += 1
            num_cow += 1

    def game_brick_color(self, j, mode=1):
        if mode == 1:
            if j == 0 or j == 1:
                self.brick.fill_color = 'darkgreen'
            elif j == 2 or j == 3:
                self.brick.fill_color = 'forestgreen'
            elif j == 4 or j == 5:
                self.brick.fill_color = 'green'
            elif j == 6 or j == 7:
                self.brick.fill_color = 'limegreen'
            elif j == 8 or j == 9:
                self.brick.fill_color = 'lime'
            else:
                self.brick.fill_color = 'lawngreen'
        # 亂數給特殊磚-高分
        if random.randint(1, 10) == 1:
            self.brick.fill_color = 'red'

    def game_paddle_build(self):

        paddle_width = 75
        paddle_height = 15
        paddle_offset = 50
        # Create a paddle.
        print(f'paddle {self.__game_zone_w}  {self.__obj_game_ball.width}')
        self.__obj_game_paddle = GRect(
            self.__game_paddle_w,
            self.__game_paddle_h,
            x=(self.__game_zone_w - self.__game_paddle_w) / 2 +
            self.__boundary_x,
            y=self.__game_zone_h - self.__game_paddle_offset +
            self.__boundary_y)
        print(
            f'paddle x={self.__obj_game_paddle.x}, y= {self.__obj_game_paddle.y}'
        )

        self.__obj_game_paddle.filled = True
        self.window.add(self.__obj_game_paddle)

    def __game_paddle_move(self, mouse):
        if (mouse.x <= self.__game_zone_r - self.__game_paddle_w / 2) and (
                mouse.x >= self.__game_zone_l + self.__game_paddle_w / 2):
            self.__obj_game_paddle.x = mouse.x - (self.__game_paddle_w / 2)
            # print(mouse.x)
        elif mouse.x < self.__game_zone_l:
            self.__obj_game_paddle.x = self.__game_zone_l
            # print(mouse.x)
        elif mouse.x > self.__game_zone_r:
            self.__obj_game_paddle.x = self.__game_zone_r - self.__game_paddle_w
            # print(mouse.x)

    def game_star(self):

        num_lives = self.__game_lives
        print(f'game_star : OK')
        while True:
            if self.__menu_code == 0:
                break
            if self.get_ball_outside():
                self.__game_lives -= 1
                self.main_code_update()
                if self.__game_lives > 0:
                    print('1')
                    self.__status_code = 0
                    self.set_game_ball_rest()
                    self.ball_speed_update()
                else:
                    print('1 end')
                    break
            if self.__game_brick_num == 0:
                print('2 end')
                break
            self.game_ball_move()
            self.ball_rebound_window()
            self.ball_rebound_obj()
            pause(self.__frame_rate)
        print('Game over')

    def game_ball_build(self):
        # Center a filled ball in the graphical window.
        self.__obj_game_ball = GOval(
            self.__game_ball_size,
            self.__game_ball_size,
            x=(self.__game_zone_w - self.__game_ball_size) / 2 +
            self.__boundary_x,
            y=(self.__game_zone_h - self.__game_ball_size) / 2 +
            self.__boundary_y)
        print(f'ball x={self.__obj_game_ball.x}, y={self.__obj_game_ball.y}')
        self.__obj_game_ball.filled = True
        self.window.add(self.__obj_game_ball)

        # self.__start_bool = True

    def __set_ball_velocity(self):
        self.__game_ball_vx = random.randint(1, BALL_X_SPEED_MAX)
        if random.random() > 0.5:
            self.__game_ball_vx = -self.__game_ball_vx
        self.__game_ball_vy = BALL_Y_SPEED
        print(
            f'set_ball_velocity {self.__game_ball_vx}, {self.__game_ball_vy}')

    def __set_ball_site(self):
        self.__obj_game_ball.x = (
            self.__game_zone_w - self.__game_ball_size) / 2 + self.__boundary_x
        self.__obj_game_ball.y = (
            self.__game_zone_h - self.__game_ball_size) / 2 + self.__boundary_y

    def game_ball_move(self):
        print(f'ball_move {self.__game_ball_vx}, {self.__game_ball_vy}')
        self.__obj_game_ball.move(self.__game_ball_vx, self.__game_ball_vy)

    def get_ball_outside(self):
        if self.__obj_game_ball.y > self.window.height - self.__boundary_y - self.__game_ball_size:
            return True

    def get_brick_number(self):
        return self.__game_brick_num

    def set_game_ball_rest(self):
        print(f'ball_rest : start')
        self.__set_ball_site()
        self.__set_ball_velocity()
        while True:
            if self.__start_bool:
                print(f'ball_rest {self.__start_bool}')
                self.__start_bool = False
                break
            pause(200)
        print(f'ball_rest : end')
        self.__status_code = 1

    def ball_rebound_window(self):
        if self.__obj_game_ball.x <= self.__game_zone_l or \
                (self.__obj_game_ball.x + self.__obj_game_ball.width) >= self.__game_zone_r:
            print('撞到兩側')
            self.__game_ball_vx = -self.__game_ball_vx

        if self.__obj_game_ball.y <= self.__game_zone_u:
            print('撞到上面')
            self.__game_ball_vy = -self.__game_ball_vy

            #下邊界要拿掉的
        if self.__obj_game_ball.y >= self.__game_zone_d - self.__obj_game_ball.height:
            print('撞到下面')
        #     self.__game_ball_vy = -self.__game_ball_vy

    def ball_rebound_obj(self):
        non_remove_obj = []
        non_remove_obj.append(self.__obj_game_paddle)
        non_remove_obj.append(self.__obj_game_zone_line_u)
        non_remove_obj.append(self.__obj_game_zone_line_d)
        non_remove_obj.append(self.__obj_game_zone_line_l)
        non_remove_obj.append(self.__obj_game_zone_line_r)

        non_rebound_obj = []
        non_rebound_obj.append(self.__obj_game_lives)
        non_rebound_obj.append(self.__obj_game_integral)

        ball_touch_obj = []
        ball_touch_obj.append(
            self.window.get_object_at(
                self.__obj_game_ball.x + self.__obj_game_ball.width / 2,
                self.__obj_game_ball.y - 0.1))
        ball_touch_obj.append(
            self.window.get_object_at(
                self.__obj_game_ball.x + self.__obj_game_ball.width / 2,
                self.__obj_game_ball.y + self.__obj_game_ball.height + 0.1))
        ball_touch_obj.append(
            self.window.get_object_at(
                self.__obj_game_ball.x - 0.1,
                self.__obj_game_ball.y + self.__obj_game_ball.height / 2))
        ball_touch_obj.append(
            self.window.get_object_at(
                self.__obj_game_ball.x + self.__obj_game_ball.width + 0.1,
                self.__obj_game_ball.y + self.__obj_game_ball.height / 2))

        j = 0
        for i in ball_touch_obj:
            if i is not None:
                if i not in non_rebound_obj:
                    if i not in non_remove_obj:
                        if i.fill_color == 'red':
                            self.__game_integral += 50
                        else:
                            self.__game_integral += 10
                        self.window.remove(i)
                        self.__game_brick_num -= 1
                        self.main_code_update()

                    if j == 0:
                        if i == self.__obj_game_paddle:
                            self.__obj_game_ball.y = self.__obj_game_paddle.y + self.__game_paddle_h
                        self.__game_ball_vy = -self.__game_ball_vy
                    elif j == 1:
                        if i == self.__obj_game_paddle:
                            self.__obj_game_ball.y = self.__obj_game_paddle.y - self.__obj_game_ball.height
                        self.__game_ball_vy = -self.__game_ball_vy
                    elif j == 2:
                        if i == self.__obj_game_paddle:
                            self.__obj_game_ball.x = self.__obj_game_paddle.x + self.__game_paddle_w
                        self.__game_ball_vx = -self.__game_ball_vx
                    # print(f'obj_r')
                    elif j == 3:
                        if i == self.__obj_game_paddle:
                            self.__obj_game_ball.x = self.__obj_game_paddle.x - self.__obj_game_ball.width
                        self.__game_ball_vx = -self.__game_ball_vx
            j += 1

    def ball_speed_update(self, threshold=100):
        speed = 10
        if self.__game_integral % threshold == 0 and self.__game_integral != 0:
            self.__frame_rate = 1000 / (FRAME_RATE + speed)