How to create a box pusher game with Python and Pygame Source Code (2020)
This game needs two files, first is the box_pusher.py file, second is the box_pusher_game_level.py file. I have added just 31 levels, there are another 200 levels. I wll add those levels later.
Those two files need to be placed inside the same folder as the pictures below.
Three pictures are all 20x20 pixels and need to be placed in the same folder as the source code.
# box_pusher.py import pygame, sys from pygame.locals import * from box_pusher_game_level import game_level SCREEN_WIDTH = 640 SCREEN_HEIGHT = 480 BOARD_WIDTH = 20 BOARD_HEIGHT = 16 CELL_SIZE = 20 FPS = 30 START_POS = (119, 79) # color preset WHITE = (255,255,255) BLACK = (0,0,0) RED = (255,0,0) GREEN = (0,255,0) BLUE = (0,0,155) # game level dictionary # 'B' represent bricks # 'M' represent marks # 'O' represent boxes # 'P' represent player ##game_level = { ## 1: ( ## '....................', ## '....................', ## '....................', ## '....................', ## '........BBB.........', ## '........BMB.........', ## '........B.BBBB......', ## '......BBBO.OMB......', ## '......BM.OPBBB......', ## '......BBBBOB........', ## '.........BMB........', ## '.........BBB........', ## '....................', ## '....................', ## '....................', ## '....................', ## ), ## 2: ( ## '....................', ## '....................', ## '....................', ## '....................', ## '......BBBBB.........', ## '......BP..B.........', ## '......B.OOB.BBB.....', ## '......B.O.B.BMB.....', ## '......BBB.BBBMB.....', ## '.......BB....MB.....', ## '.......B...B..B.....', ## '.......B...BBBB.....', ## '.......BBBBB........', ## '....................', ## '....................', ## '....................', ## ) ## } # create a board data structure # it is a list of list or 2D list, 20 cells wide, 16 cells high # get the board from the game_level data structure def get_board(level): global game_level player_pos = (None, None) box_pos = [] mark_pos = [] level_data = game_level[level] board = [] for i in range(BOARD_WIDTH): board.append([]) for j in range(BOARD_HEIGHT): if level_data[j][i] == 'P': player_pos = (i,j) elif level_data[j][i] == 'O': box_pos.append((i,j)) elif level_data[j][i] == 'M': mark_pos.append((i,j)) elif level_data[j][i] == 'X': mark_pos.append((i,j)) player_pos.append((i,j)) elif level_data[j][i] == 'Y': box_pos.append((i,j)) mark_pos.append((i,j)) board[i].append(level_data[j][i]) #print(board[i][j]) if board[i][j] == 'X': board[i][j] = 'P' if board[i][j] == 'Y': board[i][j] = 'O' return board, player_pos, box_pos, mark_pos def draw_board(board): global screen, brick_surf, box_surf, player_surf level_board = game_level[level] for i in range(BOARD_WIDTH): for j in range(BOARD_HEIGHT): if board[i][j] == 'B': pos = (START_POS[0]+i*CELL_SIZE, START_POS[1]+j*CELL_SIZE) screen.blit(brick_surf, pos) elif board[i][j] == 'M': pos = (START_POS[0]+i*CELL_SIZE, START_POS[1]+j*CELL_SIZE) circle_center = (pos[0]+int(CELL_SIZE/2), pos[1]+int(CELL_SIZE/2)) pygame.draw.circle(screen, RED, circle_center, 5) elif board[i][j] == 'O' or board[i][j] == 'Y': pos = (START_POS[0]+i*CELL_SIZE, START_POS[1]+j*CELL_SIZE) screen.blit(box_surf, pos) elif board[i][j] == 'P' or board[i][j] == 'X': pos = (START_POS[0]+i*CELL_SIZE, START_POS[1]+j*CELL_SIZE) screen.blit(player_surf, pos) def move_box(box_dir, pos): global box_pos, board, mark_pos # print(box_dir) if box_dir == 'L': left_pos = (pos[0]-1, pos[1]) # box's left position if board[left_pos[0]][left_pos[1]] == '.': board[left_pos[0]][left_pos[1]], board[pos[0]][pos[1]] = \ board[pos[0]][pos[1]], board[left_pos[0]][left_pos[1]] box_pos[box_pos.index(pos)] = left_pos elif board[left_pos[0]][left_pos[1]] == 'M': board[left_pos[0]][left_pos[1]] = 'O' board[pos[0]][pos[1]] = '.' box_pos[box_pos.index(pos)] = left_pos elif box_dir == 'R': right_pos = (pos[0]+1, pos[1]) # box's left position if board[right_pos[0]][right_pos[1]] == '.': board[right_pos[0]][right_pos[1]], board[pos[0]][pos[1]] = \ board[pos[0]][pos[1]], board[right_pos[0]][right_pos[1]] box_pos[box_pos.index(pos)] = right_pos elif board[right_pos[0]][right_pos[1]] == 'M': board[right_pos[0]][right_pos[1]] = 'O' board[pos[0]][pos[1]] = '.' box_pos[box_pos.index(pos)] = right_pos elif box_dir == 'U': up_pos = (pos[0], pos[1]-1) # box's left position if board[up_pos[0]][up_pos[1]] == '.': board[up_pos[0]][up_pos[1]], board[pos[0]][pos[1]] = \ board[pos[0]][pos[1]], board[up_pos[0]][up_pos[1]] box_pos[box_pos.index(pos)] = up_pos elif board[up_pos[0]][up_pos[1]] == 'M': board[up_pos[0]][up_pos[1]] = 'O' board[pos[0]][pos[1]] = '.' box_pos[box_pos.index(pos)] = up_pos elif box_dir == 'D': down_pos = (pos[0], pos[1]+1) # box's left position if board[down_pos[0]][down_pos[1]] == '.': board[down_pos[0]][down_pos[1]], board[pos[0]][pos[1]] = \ board[pos[0]][pos[1]], board[down_pos[0]][down_pos[1]] box_pos[box_pos.index(pos)] = down_pos elif board[down_pos[0]][down_pos[1]] == 'M': board[down_pos[0]][down_pos[1]] = 'O' board[pos[0]][pos[1]] = '.' box_pos[box_pos.index(pos)] = down_pos def move(moving_dir): global player_pos, board if moving_dir == 'L': left_pos = (player_pos[0]-1, player_pos[1]) # player's left position left_left_pos = (left_pos[0]-1, left_pos[1]) if board[left_pos[0]][left_pos[1]] == '.': # if its left position is empty, move to left board[left_pos[0]][left_pos[1]], board[player_pos[0]][player_pos[1]] = \ board[player_pos[0]][player_pos[1]], board[left_pos[0]][left_pos[1]] player_pos = left_pos elif board[left_pos[0]][left_pos[1]] == 'O' and board[left_left_pos[0]][left_left_pos[1]] not in 'BO': # if its left position is a box move_box(moving_dir, left_pos) move(moving_dir) elif board[left_pos[0]][left_pos[1]] == 'M': board[player_pos[0]][player_pos[1]] = '.' board[left_pos[0]][left_pos[1]] = 'P' player_pos = left_pos elif moving_dir == 'R': right_pos = (player_pos[0]+1, player_pos[1]) # player's right position right_right_pos = (right_pos[0]+1, right_pos[1]) if board[right_pos[0]][right_pos[1]] == '.': board[right_pos[0]][right_pos[1]], board[player_pos[0]][player_pos[1]] = \ board[player_pos[0]][player_pos[1]], board[right_pos[0]][right_pos[1]] player_pos = right_pos elif board[right_pos[0]][right_pos[1]] == 'O' and board[right_right_pos[0]][right_right_pos[1]] not in 'BO': # if its right position is a box move_box(moving_dir, right_pos) move(moving_dir) elif board[right_pos[0]][right_pos[1]] == 'M': board[player_pos[0]][player_pos[1]] = '.' board[right_pos[0]][right_pos[1]] = 'P' player_pos = right_pos elif moving_dir == 'U': up_pos = (player_pos[0], player_pos[1]-1) # player's up position up_up_pos = (up_pos[0], up_pos[1]-1) if board[up_pos[0]][up_pos[1]] == '.': board[up_pos[0]][up_pos[1]], board[player_pos[0]][player_pos[1]] = \ board[player_pos[0]][player_pos[1]], board[up_pos[0]][up_pos[1]] player_pos = up_pos elif board[up_pos[0]][up_pos[1]] == 'O' and board[up_up_pos[0]][up_up_pos[1]] not in 'BO': # if its up position is a box move_box(moving_dir, up_pos) move(moving_dir) elif board[up_pos[0]][up_pos[1]] == 'M': board[player_pos[0]][player_pos[1]] = '.' board[up_pos[0]][up_pos[1]] = 'P' player_pos = up_pos elif moving_dir == 'D': down_pos = (player_pos[0], player_pos[1]+1) # player's down position down_down_pos = (down_pos[0], down_pos[1]+1) if board[down_pos[0]][down_pos[1]] == '.': board[down_pos[0]][down_pos[1]], board[player_pos[0]][player_pos[1]] = \ board[player_pos[0]][player_pos[1]], board[down_pos[0]][down_pos[1]] player_pos = down_pos elif board[down_pos[0]][down_pos[1]] == 'O' and board[down_down_pos[0]][down_down_pos[1]] not in 'BO': # if its down position is a box move_box(moving_dir, down_pos) move(moving_dir) elif board[down_pos[0]][down_pos[1]] == 'M': board[player_pos[0]][player_pos[1]] = '.' board[down_pos[0]][down_pos[1]] = 'P' player_pos = down_pos def update_mark(): global board, mark_pos for pos in mark_pos: if board[pos[0]][pos[1]] == '.': board[pos[0]][pos[1]] = 'M' def level_passed(): global board, mark_pos, level for pos in mark_pos: if board[pos[0]][pos[1]] != 'O': return False return True def restart_game_level(level): global board, player_pos, box_pos, mark_pos board, player_pos, box_pos, mark_pos = get_board(level) def game_info(): global text_font, screen, restart_surf, restart_rect, level_surf level_surf = text_font.render(f'Level:{level}', True, BLACK) pygame.draw.rect(screen, BLUE, restart_rect) screen.blit(restart_surf, restart_rect) screen.blit(level_surf, (100,80)) # print board for debugging only def print_board(board): for i in range(BOARD_HEIGHT): for j in range(BOARD_WIDTH): print(board[j][i], end='') print() # initialize the pygame module pygame.init() screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) pygame.display.set_caption('Box Pusher') # game clock game_clock = pygame.time.Clock() # load the brick image, boxe image and player image brick_surf = pygame.image.load('brick.png').convert_alpha() box_surf = pygame.image.load('box.png').convert_alpha() player_surf = pygame.image.load('player.png').convert_alpha() # level starts at 1 level = 1 # restart level text font text_font = pygame.font.SysFont('arial', 20) restart_surf = text_font.render('Restart Level', True, WHITE) # restart rect restart_rect = pygame.Rect(500, 80, 120, 25) board, player_pos, box_pos, mark_pos = get_board(level) moving_dir = '' while True: # print_board(board) for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() elif event.type == KEYDOWN: if event.key == K_LEFT: moving_dir = 'L' move(moving_dir) update_mark() elif event.key == K_RIGHT: moving_dir = 'R' move(moving_dir) update_mark() elif event.key == K_UP: moving_dir = 'U' move(moving_dir) update_mark() elif event.key == K_DOWN: moving_dir = 'D' move(moving_dir) update_mark() elif event.type == MOUSEBUTTONUP: # if restart level button is clicked, level restart click_pos = event.pos if restart_rect.collidepoint(click_pos): restart_game_level(level) #print_board(board) screen.fill(WHITE) draw_board(board) game_info() if level_passed(): level += 1 board, player_pos, box_pos, mark_pos = get_board(level) moving_dir = '' pygame.display.update() game_clock.tick(FPS)
# box_pusher_game_level.py # B for brick # M for mark # O for box # P for player # X for MP (mark and player) # Y for MO (mark and box) game_level = { 1: ( '....................', '....................', '....................', '....................', '........BBB.........', '........BMB.........', '........B.BBBB......', '......BBBO.OMB......', '......BM.OPBBB......', '......BBBBOB........', '.........BMB........', '.........BBB........', '....................', '....................', '....................', '....................', ), 2: ( '....................', '....................', '....................', '....................', '......BBBBB.........', '......BP..B.........', '......B.OOB.BBB.....', '......B.O.B.BMB.....', '......BBB.BBBMB.....', '.......BB....MB.....', '.......B...B..B.....', '.......B...BBBB.....', '.......BBBBB........', '....................', '....................', '....................', ), 3: ( '....................', '....................', '....................', '....................', '......BBBBBBB.......', '......B.....BBB.....', '.....BBOBBB...B.....', '.....B.P.O..O.B.....', '.....B.MMB.O.BB.....', '.....BBMMB...B......', '......BBBBBBBB......', '....................', '....................', '....................', '....................', '....................', ), 4: ( '....................', '....................', '....................', '....................', '.......BBBB.........', '......BB..B.........', '......BPO.B.........', '......BBO.BB........', '......BB.O.B........', '......BMO..B........', '......BMMYMB........', '......BBBBBB........', '....................', '....................', '....................', '....................', ), 5: ( '....................', '....................', '....................', '....................', '......BBBBB.........', '......B..BBB........', '......BPO..B........', '.....BBB.B.BB.......', '.....BMB.B..B.......', '.....BMO..B.B.......', '.....BM...O.B.......', '.....BBBBBBBB.......', '....................', '....................', '....................', '....................', ), 6: ( '....................', '....................', '......BBBBBBB.......', '...BBBB.....B.......', '...B...MBBB.B.......', '...B.B.B....BB......', '...B.B.O.OBM.B......', '...B.B..Y..B.B......', '...B.MBO.O.B.B......', '...BB....B.B.BBB....', '....B.BBBM....PB....', '....B.....BB...B....', '....BBBBBBBBBBBB....', '....................', '....................', '....................', ), 7: ( '....................', '....................', '....................', '....................', '.........BBBBBB.....', '.......BBB....B.....', '......BBM.OBB.BB....', '......BMMO.O..PB....', '......BMM.O.O.BB....', '......BBBBBB..B.....', '...........BBBB.....', '....................', '....................', '....................', '....................', '....................', ), 8: ( '....................', '....................', '....................', '..........BBBBBBB...', '.........BB..B.PB...', '.........B...B..B...', '.........BO.O.O.B...', '.........B.OBB..B...', '.......BBB.O.B.BB...', '.......BMMMMM..B....', '.......BBBBBBBBB....', '....................', '....................', '....................', '....................', '....................', ), 9: ( '....................', '....................', '....................', '....................', '.....BBBBBBBBB......', '.....B..BB...B......', '.....B...O...B......', '.....BO.BBB.OB......', '.....B.BMMMB.B......', '....BB.BMMMB.BB.....', '....B.O..O..O.B.....', '....B.....B.P.B.....', '....BBBBBBBBBBB......', '....................', '....................', '....................', ), 10: ( '....................', '....................', '....................', '....................', '....................', '.........BBBBBB.....', '.........B....B.....', '.......BBBOOO.B.....', '.......BP.OMM.B.....', '.......B.OMMMBB.....', '.......BBBB..B......', '..........BBBB......', '....................', '....................', '....................', '....................', ), 11: ( '....................', '....................', '....................', '....................', '....................', '....BBBB..BBBBB.....', '...BB..B..B...B.....', '...B.O.BBBBO..B.....', '...B..OMMMM.O.B.....', '...BB....B..PBB.....', '....BBBBBBBBBB......', '....................', '....................', '....................', '....................', '....................', ), 12: ( '....................', '....................', '....................', '....................', '........BBBBB.......', '......BBB..PB.......', '......B..OM.BB......', '......B..MOM.B......', '......BBB.YO.B......', '........B...BB......', '........BBBBB.......', '....................', '....................', '....................', '....................', '....................', ), 13: ( '....................', '....................', '....................', '....................', '........BBBB........', '........BMMB........', '.......BB.MBB.......', '.......B..OMB.......', '......BB.O..BB......', '......B..BOO.B......', '......B.P....B......', '......BBBBBBBB......', '....................', '....................', '....................', '....................', ), 14: ( '....................', '....................', '....................', '....................', '....................', '.....BBBBBBBB.......', '.....B..B...B.......', '.....B.OMMO.B.......', '.....BPOMY..B.......', '.....B.OMMO.B.......', '.....B..B...B.......', '.....BBBBBBBB.......', '....................', '....................', '....................', '....................', ), 15: ( '....................', '....................', '....................', '....................', '....................', '........BBBBBB......', '.......BB....BB.....', '.......B.O.OO.B.....', '.......BMMMMMMB.....', '.......B.OO.O.B.....', '.......BBB.PBBB.....', '.........BBBB.......', '....................', '....................', '....................', '....................', ), 16: ( '....................', '....................', '....................', '....................', '.......BBBBBB.......', '.......B....BBB.....', '.......B.O....B.....', '.....BBB.O.BB.B.....', '.....BMMM.O...B.....', '.....BMMMOBO.BB.....', '.....BBBB.B.O.B.....', '........B..P..B.....', '........BBBBBBB.....', '....................', '....................', '....................', ), 17: ( '....................', '....................', '....................', '....................', '....................', '.....BBBBBB.........', '.....B....B.........', '.....B.OOOBB........', '.....B..BMMBBB......', '.....BB..MMO.B......', '......B.P....B......', '......BBBBBBBB......', '....................', '....................', '....................', '....................', ), 18: ( '....................', '....................', '....................', '....................', '........BBBBBBBB....', '........B...BM.B....', '.......BB..OMMMB....', '.......B..O.BYMB....', '......BB.BBOB.BB....', '......B...O..O.B....', '......B...B....B....', '......BBBBBBB..B....', '............BBBB....', '....................', '....................', '....................', ), 19: ( '....................', '....................', '....................', '....................', '......BBBBBBB.......', '......BMMMM.B.......', '.....BBBMMMOBBB.....', '.....B..OBO.O.B.....', '.....B.OO..BO.B.....', '.....B....B...B.....', '.....BBBB.P.BBB.....', '........BBBBB.......', '....................', '....................', '....................', '....................', ), 20: ( '....................', '....................', '....................', '.......BBBBBBB......', '.......BMMOMMB......', '.......BMMBMMB......', '.......B.OOO.B......', '.......B..O..B......', '.......B.OOO.B......', '.......B..BP.B......', '.......BBBBBBB......', '....................', '....................', '....................', '....................', '....................', ), 21: ( '....................', '....................', '....................', '.........BBBBBB.....', '.........B.MMMB.....', '......BBBBMMMMBBB...', '......B..BBBO...B...', '......B.O.O..OO.B...', '......B..O.O....B...', '......BP..BBB...B...', '......BBBBB.BBBBB...', '....................', '....................', '....................', '....................', '....................', ), 22: ( '....................', '....................', '....................', '....................', '......BBBBBBBB......', '......B......B......', '......B.BOO..B......', '......B.MMMB.B......', '......BBMMMO.BB.....', '.......B.BB.O.B.....', '.......BO..O..B.....', '.......B..B..PB.....', '.......BBBBBBBB.....', '....................', '....................', '....................', ), 23: ( '....................', '....................', '....................', '........BBBBBB......', '......BBB...BBBB....', '......B...O.O..B....', '......B.O...O.PB....', '......BBBOOBBBBB....', '........B..MMB......', '........BMMMMB......', '........BBBBBB......', '....................', '....................', '....................', '....................', '....................', ), 24: ( '....................', '....................', '....................', '...BBBBBB...BBBBB...', '...B....BBB.B..MB...', '...B..O.O.B.BMMMB...', '...B.B..O.BBB..MB...', '...B..OOO...O.PMB...', '...BBB..O..OB..MB...', '.....B..OBO.BMMMB...', '.....BB.....B..MB...', '......BBBBBBBBBBB...', '....................', '....................', '....................', '....................', ), 25: ( '....................', '....................', '....................', '.........BBBBBB.....', '.....BBBBBM...B.....', '.....B..BMM...B.....', '.....B..OMM...B.....', '.....B..B.MB.BB.....', '....BBB.BBOB..B.....', '....B.O....OO.B.....', '....B.BOB..B..B.....', '....BP..BBBBBBB.....', '....BBBBB...........', '....................', '....................', '....................', ), 26: ( '....................', '....................', '...BBBBBBBBB........', '...B...BB..BBBB.....', '...B.O........B.....', '...BBOBBB.BB..B.....', '...B..BB.Y.B.BB.....', '...B.OMMMMMM.B......', '..BB.BBB.M.B.B......', '..B.....OBBBOB......', '..B...B....OPB......', '..BBBBBOB.BBBB......', '......B...B.........', '......BBBBB.........', '....................', '....................', ), 27: ( '....................', '....................', '.........BBBBBBBBB..', '.........B.......B..', '.........B.B.B.B.B..', '.........B..O.OB.B..', '...BBBBBBB...O...B..', '...BMMB..BB.O.OB.B..', '...BMM...BB.O.O..B..', '...BMMB..BB.BBBBBB..', '...BMMB.B.O.O.B.....', '...BMM.....O..B.....', '...B..BBB.P.BBB.....', '...BBBB.BBBBB.......', '....................', '....................', ), 28: ( '....................', '......BBBB..........', '..BBBBB..B..........', '..B..O.O.B.BBBBBBB..', '..B...O..B.BYMYMYB..', '..BB.O.O.BBBMYMYMB..', '...BO.O..B..YMYMYB..', '...BP.OO....MYMYBB..', '...BO.O..B..YMYMYB..', '..BB.O.O.BBBMYMYMB..', '..B...O..B.BYMYMYB..', '..B..O.O.B.BBBBBBB..', '..BBBBB..B..........', '......BBBB..........', '....................', '....................', ), 29: ( '....................', '....................', '....................', '....................', '.....BBBBBBBB.......', '.....BMMMMMMB.......', '.....B..O.B.BB......', '.....B.O.B.O.B......', '.....BBO.O.O.B......', '......B..P...B......', '......BBBBBBBB......', '....................', '....................', '....................', '....................', '....................', ), 30: ( '....................', '....................', '....................', '....................', '....................', '.......BBBBBBBBBB...', '.....BBB...M....B...', '.....B...BBOBB..B...', '.....BP.OM.M.MOBB...', '.....BB.OBBOBB.B....', '......B....M...B....', '......BBBBBBBBBB....', '....................', '....................', '....................', '....................', ), 31: ( '....................', '....................', '....................', '....................', '.........BBBBBB.....', '......BBBBM..PB.....', '......B..OOO..B.....', '......BMBBMBBMB.....', '......B...O...B.....', '......B..OMB.BB.....', '......BBBB...B......', '.........BBBBB......', '....................', '....................', '....................', '....................', ), }
Comments
Post a Comment