Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- """
- This program is a nice game of checkers.
- """
- import pygame as py
- import settings as s
- py.init()
- # create the screen and set the caption
- screen = py.display.set_mode((s.WIDTH, s.HEIGHT))
- py.display.set_caption("Checkers")
- # groups of sprites so the program can update and display the sprites more easily
- squares = py.sprite.Group()
- checkers = py.sprite.Group()
- # Sets up the board logic.
- board = []
- for x in range(int(s.SQUARE_SIZE//2), s.WIDTH, int(s.SQUARE_SIZE)):
- col = []
- for y in range(int(s.SQUARE_SIZE//2), s.HEIGHT, int(s.SQUARE_SIZE)):
- col.append((x, y))
- board.append(col)
- class Checker(py.sprite.Sprite):
- def __init__(self, coords, color):
- super(Checker, self).__init__()
- self.surf = py.Surface((s.CIRCLE_SIZE,s.CIRCLE_SIZE))
- self.surf.fill(s.BLACK)
- self.surf.set_colorkey(s.BLACK)
- py.draw.circle(self.surf, color, [s.CIRCLE_SIZE//2,s.CIRCLE_SIZE//2], s.CIRCLE_SIZE//2)
- self.set_pos(coords)
- self.isCrown = False
- self.coords = coords
- self.color = color
- def set_pos(self, coords):
- self.rect = self.surf.get_rect(center=(board[coords[0]][coords[1]]))
- # When selected, this function is called and the checker is anchored on the mouse
- def update(self, mouse):
- self.rect = self.surf.get_rect(center=mouse)
- def set_crown(self):
- self.isCrown = True
- py.draw.circle(self.surf, s.NEAR_BLACK, [s.CIRCLE_SIZE//2, s.CIRCLE_SIZE//2], s.CROWN_SIZE)
- class Square(py.sprite.Sprite):
- def __init__(self, location, color):
- super(Square, self).__init__()
- self.surf = py.Surface((s.SQUARE_SIZE, s.SQUARE_SIZE))
- self.surf.fill(color)
- self.rect = self.surf.get_rect(topleft=location)
- # Point used to determine what checker the user clicks.
- class Point(py.sprite.Sprite):
- def __init__(self, location):
- super(Point, self).__init__()
- x = location[0]
- y = location[1]
- self.rect = py.Rect(x, y, 1, 1)
- # Check to see if a specific coordinate has a checker in it.
- def has_checker(coords):
- collision = py.sprite.spritecollide(Point(board[coords[0]][coords[1]]), checkers, False)
- return collision
- # Check if the coordinate is a valid move (if it is in range and it doesnt have a checker in it)
- # for the given checker.
- def is_valid_move(coords, checker):
- if not coords[0] in range(8) or not coords[1] in range(8):
- return False
- square_has_checker = has_checker(coords)
- if checker in square_has_checker:
- square_has_checker.remove(checker)
- if square_has_checker:
- return False
- return True
- # Check to see if the given checker can jump from the given coordinates in the
- # given direction with the distance given by the move variable.
- def calculate_jump(checker, start_coords, move, direction):
- jumped_coords = []
- forwards = (start_coords[0]+(move[0]*direction), start_coords[1]+(move[1]*direction))
- backwards = (start_coords[0]+(move[0]*-direction), start_coords[1]+(move[1]*-direction))
- if is_valid_move(forwards, checker):
- checker_to_jump = has_checker([start_coords[0]+(move[0]//2*direction), start_coords[1]+(move[1]//2*direction)])
- if checker_to_jump and checker_to_jump[0].color != checker.color:
- jumped_coords.append((start_coords[0]+(move[0]//2*direction), start_coords[1]+(move[1]//2*direction)))
- return jumped_coords, forwards
- if checker.isCrown:
- if is_valid_move(backwards, checker):
- checker_to_jump = has_checker([start_coords[0]+(move[0]//2*direction), start_coords[1]+(move[1]//2*-direction)])
- if checker_to_jump and checker_to_jump[0].color != checker.color:
- jumped_coords.append((start_coords[0]+(move[0]//2*direction), start_coords[1]+(move[1]//2*-direction)))
- return jumped_coords, backwards
- return None, None
- # Function to get all the possible positions the given checker can
- # move to.
- def get_valid_positions(checker):
- valid_positions = []
- valid_capture_positions = []
- coords_jumped = []
- normal_moves = [[1, -1], [-1, -1]]
- capture_moves = [[2, -2], [-2, -2]]
- if checker.color == s.WHITE:
- direction = 1
- else:
- direction = -1
- # Get all possible normal moves
- for move in normal_moves:
- forwards = (checker.coords[0]+(move[0]*direction), checker.coords[1]+(move[1]*direction))
- backwards = (checker.coords[0]+(move[0]*-direction), checker.coords[1]+(move[1]*-direction))
- if is_valid_move(forwards, checker):
- valid_positions.append(forwards)
- if checker.isCrown:
- if is_valid_move(backwards, checker):
- valid_positions.append(backwards)
- # Get all possible jump moves
- for move in capture_moves:
- jumped_coords, new_coords = calculate_jump(checker, checker.coords, move, direction)
- if new_coords:
- # Check to see if a double jump is possible
- valid_capture_positions.append(new_coords)
- coords_jumped.append(jumped_coords)
- for move in capture_moves:
- second_jumped_coords, second_coords = calculate_jump(checker, new_coords, move, direction)
- if second_coords:
- valid_capture_positions.append(second_coords)
- coords_jumped.append([jumped_coords + second_jumped_coords])
- # If the settings require that the player to jump, then the normal moves are
- # not returned.
- if valid_capture_positions and s.REQUIRE_JUMP:
- return [[], valid_capture_positions, coords_jumped]
- else:
- return [valid_positions, valid_capture_positions, coords_jumped]
- def text_objects(text, font):
- textSurface = font.render(text, True, s.WHITE)
- return textSurface, textSurface.get_rect()
- def turn_display(turn):
- font = py.font.SysFont(None, 25)
- text = font.render(turn, True, s.NEAR_BLACK)
- return text
- def set_up():
- for i in range(s.BOARD_SIZE):
- for j in range(s.BOARD_SIZE):
- # location of where the new squares need to be
- location = [i*s.SQUARE_SIZE, j*s.SQUARE_SIZE]
- # Calculate the color of the squares
- if (i+j) % 2 == 0:
- color = s.BROWN
- # If the current row is in the range of the number of rows
- # given in the settings, it will add a checker with the correct color
- if j > s.BOARD_SIZE-(s.ROWS_OF_CHECKERS+1):
- new_checker = Checker((i, j), s.WHITE)
- checkers.add(new_checker)
- elif j < s.ROWS_OF_CHECKERS:
- new_checker = Checker((i, j), s.DARK_GRAY)
- checkers.add(new_checker)
- else:
- color = s.BEIGE
- new_square = Square(location, color)
- squares.add(new_square)
- # Testing purposes only.
- def test_set_up():
- for i in range(s.BOARD_SIZE):
- for j in range(s.BOARD_SIZE):
- # location of where the new squares need to be
- location = [i*s.SQUARE_SIZE, j*s.SQUARE_SIZE]
- # Calculate the color of the squares
- if (i+j) % 2 == 0:
- color = s.BROWN
- else:
- color = s.BEIGE
- new_square = Square(location, color)
- squares.add(new_square)
- new_checker_1 = Checker((4, 6), s.DARK_GRAY)
- checkers.add(new_checker_1)
- new_checker_2 = Checker((3, 1), s.WHITE)
- checkers.add(new_checker_2)
- # Render all the squares, checkers, and text to the screen.
- def render(turn):
- screen.fill(s.REDWOOD)
- # Display all the squares first
- for entity in squares:
- screen.blit(entity.surf, entity.rect)
- # Then display all the checkers so they are on top of them.
- for entity in checkers:
- screen.blit(entity.surf, entity.rect)
- # Display what turn it is.
- if turn == s.WHITE:
- turn_text = turn_display("Turn: White")
- else:
- turn_text = turn_display("Turn: Gray")
- screen.blit(turn_text,(15,s.WIDTH+17))
- py.display.update()
- def main():
- #set_up()
- test_set_up()
- selected_checker = None
- turn = s.WHITE
- while True:
- mouse = py.mouse.get_pos()
- snapped_mouse = (int(mouse[0] // s.SQUARE_SIZE), int(mouse[1] // s.SQUARE_SIZE))
- for event in py.event.get():
- if event.type == py.QUIT:
- py.quit()
- return
- elif event.type == py.MOUSEBUTTONDOWN:
- # Select a checker, if it exists
- if not selected_checker:
- clicked_checker = py.sprite.spritecollideany(Point(mouse), checkers)
- if clicked_checker and clicked_checker.color == turn:
- selected_checker = clicked_checker
- elif event.type == py.MOUSEBUTTONUP:
- # If a checker is currently selected, check if the move the player attempted to make is
- # valid, if so then move the checker to the new position and kill any
- # checkers it jumped over if neccesary
- if selected_checker:
- valid_positions = get_valid_positions(selected_checker)
- if snapped_mouse in valid_positions[0] or snapped_mouse in valid_positions[1]:
- if snapped_mouse in valid_positions[1]:
- index = valid_positions[1].index(snapped_mouse)
- for i in range(len(valid_positions[2][index])):
- for checker in checkers:
- if checker.coords == valid_positions[2][index][i] or checker.coords in valid_positions[2][index][i]:
- checker.kill()
- selected_checker.set_pos(snapped_mouse)
- # Change the turn
- if turn == s.WHITE:
- turn = s.DARK_GRAY
- else:
- turn = s.WHITE
- selected_checker.coords = snapped_mouse
- else:
- # If the position is not valid, move the checker back to the original position
- # and don't change the turn
- selected_checker.rect = selected_checker.surf.get_rect(center=(board[selected_checker.coords[0]][selected_checker.coords[1]]))
- # Check to see if the checker is in a position to be crowned, if it is in a position
- # to be crowned and the setting for crowning is enabled, then crown the checker.
- if ((selected_checker.color == s.WHITE and selected_checker.coords[1] == 0) \
- or (selected_checker.color == s.DARK_GRAY and selected_checker.coords[1] == 7)) \
- and s.CAN_CROWN:
- selected_checker.set_crown()
- # Let go of the checker
- selected_checker = None
- # If there is a selected checker, move it to the position of the mouse.
- if selected_checker:
- selected_checker.update(mouse)
- render(turn)
- s.CLOCK.tick(s.FPS)
- if __name__ == "__main__":
- main()
Advertisement
Add Comment
Please, Sign In to add comment