0

On my mini-mage project, whenever a unit on the chessboard is either wounded or killed, the square on which the unit is gets outlined of respectively a yellow or red colour.

Once this happens, I have to wait for the next Player click in order to make the outline to disappear (which means obviously to redraw the chessboard and all the units in the current position).

Want I am looking for is a mean to redraw everything before the next player's click (at the moment just for the yellow outline/wounded unit).

The easiest thing I came up with, is to make the game wait with time.sleep() and then redraw everything (in the same chunk of code), so I just insert time.sleep(3) right after the highlight_yellow(square_on) function, and before the statement which changes the game state.

enter image description here

Well, I don't know why but for some reason it works (waits 3 seconds and redraws everything) except for displaying the yellow outline.

Can anyone tell me what am I doing wrong?

My main loop is the following:

# main loop
while 1:

    # event loop
    for event in pygame.event.get():
        if event.type is pygame.QUIT:
            sys.exit()

        # mouse click handling
        if event.type == pygame.MOUSEBUTTONDOWN:
            new_position = pygame.mouse.get_pos()

            # unit not selected
            if game_state is 'no unit selected':
                if cancel_yellow_square:
                    draw_chessboard()
                    for white_unit in white_army:
                        white_unit.draw_unit()
                    for black_unit in black_army:
                        black_unit.draw_unit()
                    cancel_yellow_square = False
                if cancel_red_square:
                    selected_unit.set_unit_position(selected_unit.new_position[0], selected_unit.new_position[1])
                    selected_unit = None
                    draw_chessboard()
                    for white_unit in white_army:
                        white_unit.draw_unit()
                    for black_unit in black_army:
                        black_unit.draw_unit()
                    cancel_red_square = False

                if turn is 'white army':
                    for white_unit in white_army:
                        if white_unit.square_on.collidepoint(new_position[0], new_position[1]):
                            selected_unit = white_unit
                            game_state = 'unit selected'
                            print(str(game_state) + ', this unit is a white ' + str(selected_unit.get_condition()) +
                                  ' ' + str(selected_unit.kind))

                elif turn is 'black army':
                    for black_unit in black_army:
                        if black_unit.square_on.collidepoint(new_position[0], new_position[1]):
                            selected_unit = black_unit
                            game_state = 'unit selected'
                            print(str(game_state) + ', this unit is a black ' + str(selected_unit.get_condition()) +
                                  ' ' + str(selected_unit.kind))

            elif game_state == 'unit selected':
                if turn is 'white army':
                    current_position = selected_unit.square_on
                    if not current_position.collidepoint(new_position[0], new_position[1]):
                        if is_legal_move(selected_unit) and white_unit_collision():
                            print('this square is occupied by a friendly white unit, therefore the move is not allowed.'
                                  ' choose another square')
                        elif is_legal_move(selected_unit) and black_unit_collision():
                            for black_unit in black_army:
                                if black_unit.get_unit_position() == selected_unit.new_position:
                                    if black_unit.get_condition() == 'fresh':
                                        game_state = 'enemy unit wounded'
                                        print('black unit wounded')
                                    elif black_unit.get_condition() == 'wounded':
                                        game_state = 'enemy unit killed'
                                        print('black unit killed')
                        elif not is_legal_move(selected_unit):
                            print('move not allowed for this unit')
                        elif is_legal_move(selected_unit):
                            game_state = 'unit movement allowed'
                            turn = 'black army'
                    else:
                        print('this unit has been deselected, select a unit')
                        game_state = 'no unit selected'
                        current_position = selected_unit.get_unit_position()
                        new_position = selected_unit.get_unit_position()
                        selected_unit.set_unit_position(new_position[0], new_position[1])

                elif turn is 'black army':
                    current_position = selected_unit.square_on
                    if not current_position.collidepoint(new_position[0], new_position[1]):
                        if is_legal_move(selected_unit) and black_unit_collision():
                            print('this square is occupied by a friendly black unit, therefore the move is not allowed.'
                                  ' choose another square')
                        elif is_legal_move(selected_unit) and white_unit_collision():
                            for white_unit in white_army:
                                if white_unit.get_unit_position() == selected_unit.new_position:
                                    if white_unit.get_condition() == 'fresh':
                                        game_state = 'enemy unit wounded'
                                        print('black unit wounded')
                                    elif white_unit.get_condition() == 'wounded':
                                        game_state = 'enemy unit killed'
                                        print('white unit killed')
                        elif not is_legal_move(selected_unit):
                            print('move not allowed for this unit')
                        elif is_legal_move(selected_unit):
                            game_state = 'unit movement allowed'
                            turn = 'white army'

                    else:
                        print('this unit has been deselected, select a unit')
                        game_state = 'no unit selected'
                        current_position = selected_unit.get_unit_position()
                        new_position = selected_unit.get_unit_position()
                        selected_unit.set_unit_position(new_position[0], new_position[1])

    # application loop

    # highlight square
    if game_state == 'unit selected':
        highlight_green(selected_unit.square_on)
        highlight_possible_moves()

    # move unit
    if game_state == 'unit movement allowed':
        selected_unit.set_unit_position(selected_unit.new_position[0], selected_unit.new_position[1])
        game_state = 'no unit selected'
        print('---' + str(turn).upper() + ', IS YOUR TURN---')
        selected_unit = None

    # enemy wounded
    if game_state == 'enemy unit wounded':
        print(selected_unit.new_position)
        if turn == 'white army':
            for black_unit in black_army:
                if black_unit.get_unit_position() == selected_unit.new_position:
                    black_unit.set_condition('wounded')
                    print('this unit has been ' + str(black_unit.get_condition()))
        elif turn == 'black army':
            for white_unit in white_army:
                if white_unit.get_unit_position() == selected_unit.new_position:
                    white_unit.set_condition('wounded')
                    print('this unit has been ' + str(white_unit.get_condition()))
        square_on = selected_unit.new_position[0], selected_unit.new_position[1], 100, 100
        highlight_yellow(square_on)
        time.sleep(3)
        draw_chessboard()
        for white_unit in white_army:
            white_unit.draw_unit()
        for black_unit in black_army:
            black_unit.draw_unit()
        if turn == 'white army':
            turn = 'black army'
        elif turn == 'black army':
            turn = 'white army'
        game_state = 'no unit selected'
        cancel_yellow_square = True
        print('---' + str(turn).upper() + ', IS YOUR TURN---')
        selected_unit = None

    # enemy killed
    if game_state == 'enemy unit killed':
        print(selected_unit.new_position)
        if turn == 'white army':
            for black_unit in black_army:
                if black_unit.get_unit_position() == selected_unit.new_position:
                    black_unit.set_condition('killed')
                    black_army.remove(black_unit)
                    print('this unit has been ' + str(black_unit.get_condition()))
        elif turn == 'black army':
            for white_unit in white_army:
                if white_unit.get_unit_position() == selected_unit.new_position:
                    white_unit.set_condition('killed')
                    white_army.remove(white_unit)
                    print('this unit has been ' + str(white_unit.get_condition()))
        square_on = selected_unit.new_position[0], selected_unit.new_position[1], 100, 100
        highlight_red(square_on)
        if turn == 'white army':
            turn = 'black army'
        elif turn == 'black army':
            turn = 'white army'
        game_state = 'no unit selected'
        cancel_red_square = True
        print('---' + str(turn).upper() + ', IS YOUR TURN---')

    pygame.display.update()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Techoplite
  • 605
  • 9
  • 23
  • *"How to make a chunk of code to wait for a few seconds"* - Not at all. Use the main loop to draw the "same" for a few seconds. – Rabbid76 Nov 01 '19 at 11:25
  • Does that involve the use of the time.sleep() function or should I look for something else? Because at the moment I am in the dark... – Techoplite Nov 01 '19 at 11:36
  • No, just draw the same for some frames. If you want to use `sleep`, then you've to update the display before and to handle the events before `sleep`. But recommend to set a new `game_state` `'paused'`. Decrement a counter when this state is set and return to a different state when the counter is 0. – Rabbid76 Nov 01 '19 at 11:39
  • Could I please have a simple example of a counter? Does it involve the use of perf_counter()? – Techoplite Nov 01 '19 at 12:10

1 Answers1

0

If you just wait for some time, you can use pygame.time.wait or pygame.time.delay. However, if you want to display a message and then wait some time, you need to update the display beforehand. The display is updated only if either pygame.display.update() or pygame.display.flip() is called. Further you've to handles the events by pygame.event.pump(), before the update of the display becomes visible in the window:

highlight_yellow(square_on)
pygame.display.flip()
pygame.event.pump()
pygame.time.delay(3000) # 3 second == 3000 milliseconds

In any case, this is not the way to wait or delay something in a typical application. The game does not respond while you wait. Use pygame.time.get_ticks() to measure the time.
For further information see the answers to the questions:

Rabbid76
  • 202,892
  • 27
  • 131
  • 174