import pygame import csv import os.path as path # initializing pygame pygame.init() # set fps and screen dimensions as constant values fps = 60 SCREEN_WIDTH = 800 SCREEN_HEIGHT = 640 # create a clock that controls the framerate of the game clock = pygame.time.Clock() # set up display screen screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) pygame.display.set_caption('Scrolling Platformer Game') # main game variables level = 0 ROWS = 16 TILE_SIZE = SCREEN_HEIGHT // ROWS GRAVITY = 0.6 JUMP_POWER = -10 # negative value so player moves upwards # load in and scale background image bg_img = pygame.image.load('img/bg.png') bg_img = pygame.transform.scale(bg_img, (SCREEN_WIDTH, SCREEN_HEIGHT)) # create spike and doublespike groups spike_group = pygame.sprite.Group() doublespike_group = pygame.sprite.Group() # world class (handles all data for the "world") class World(): def __init__(self, data): self.tile_list = [] # load in ground tile image ground_img = pygame.image.load('img/tile/0.png') # load tiles from world data row_count = 0 for row in data: col_count = 0 for tile in row: if tile == 0: img = pygame.transform.scale(ground_img, (TILE_SIZE, TILE_SIZE)) img_rect = img.get_rect() img_rect.x = col_count * TILE_SIZE img_rect.y = row_count * TILE_SIZE tile = (img, img_rect) self.tile_list.append(tile) if tile == 7: spike = Spike(col_count * TILE_SIZE, row_count * TILE_SIZE + 15) spike_group.add(spike) if tile == 10: doublespike = DoubleSpike(col_count * TILE_SIZE, row_count * TILE_SIZE + 15) doublespike_group.add(doublespike) col_count += 1 row_count += 1 # draw function to display tiles onto screen def draw(self): for tile in self.tile_list: screen.blit(tile[0], tile[1].topleft) # cube class (handles everything for the player aka jumping, collisions etc) class Cube(pygame.sprite.Sprite): def __init__(self, x, y): pygame.sprite.Sprite.__init__(self) self.image1 = pygame.image.load('img/cube/1.png') self.image2 = pygame.image.load('img/cube/2.png') self.image_dead = pygame.image.load('img/cube/dead.png') self.image1 = pygame.transform.scale(self.image1, (TILE_SIZE, TILE_SIZE)) self.image2 = pygame.transform.scale(self.image2, (TILE_SIZE, TILE_SIZE)) self.image_dead = pygame.transform.scale(self.image_dead, (TILE_SIZE, TILE_SIZE)) self.image = self.image1 self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y self.y_velocity = 0 self.x_velocity = 0 self.on_ground = False self.dead = 0 # update function for the cube (handles the cube's position and state) def update(self): if self.dead == 0: # gravity physics implementation self.y_velocity += GRAVITY self.rect.y += self.y_velocity self.rect.x += self.x_velocity # checks for ground collision self.on_ground = False for tile in world.tile_list: if self.rect.colliderect(tile[1]): # Check vertical collisions if self.y_velocity > 0: self.rect.bottom = tile[1].top self.y_velocity = 0 self.on_ground = True self.image = self.image1 # changes back to the original image once landed elif self.y_velocity < 0: self.rect.top = tile[1].bottom self.y_velocity = 0 # Check horizontal collisions if self.x_velocity > 0: self.rect.right = tile[1].left elif self.x_velocity < 0: self.rect.left = tile[1].right # Prevent the player from moving off the left side of the screen if self.rect.left < 0: self.rect.left = 0 # check for spike collision if pygame.sprite.spritecollide(self, spike_group, False) or pygame.sprite.spritecollide(self, doublespike_group, False): self.dead = 1 # set player as "dead" self.image = self.image_dead # jumping function for cube def jump(self): if self.on_ground and self.dead == 0: self.y_velocity = JUMP_POWER self.image = self.image2 # Change to the jumping image # class to handle spikes class Spike(pygame.sprite.Sprite): def __init__(self, x, y): pygame.sprite.Sprite.__init__(self) img = pygame.image.load('img/spikes/1.png') self.image = pygame.transform.scale(img, (TILE_SIZE, TILE_SIZE // 2)) self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y # class to handle double spikes class DoubleSpike(pygame.sprite.Sprite): def __init__(self, x, y): pygame.sprite.Sprite.__init__(self) img = pygame.image.load('img/spikes/4.png') self.image = pygame.transform.scale(img, (TILE_SIZE, TILE_SIZE // 2)) self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y # load level data from the csv file def load_level_data(level): if path.exists(f'level_data{level}.csv'): world_data = [] with open(f'level_data{level}.csv', mode='r') as file: reader = csv.reader(file) for row in reader: # convert the CSV row back to the appropriate data types world_data.append([int(item) for item in row]) else: world_data = [[]] # Create an empty list if no world data is found return world_data world_data = load_level_data(level) world = World(world_data) # create the player as an instance of the cube class player = Cube(100, 400) # main game loop run = True while run: # frame rate clock.tick(fps) # event handler keys = pygame.key.get_pressed() if keys[pygame.K_a]: player.x_velocity = -5 elif keys[pygame.K_d]: player.x_velocity = 5 else: player.x_velocity = 0 for event in pygame.event.get(): if event.type == pygame.QUIT: run = False if event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE: # space to jump player.jump() # draw background images screen.blit(bg_img, (0, 0)) # update + draw player and world player.update() world.draw() screen.blit(player.image, player.rect.topleft) # draw spikes spike_group.draw(screen) doublespike_group.draw(screen) # update the display pygame.display.update() # quit pygame pygame.quit()