""" Sample Python/Pygame Programs Simpson College Computer Science http://programarcadegames.com/ http://simpson.edu/computer-science/ Main module for platform scroller example. From: http://programarcadegames.com/python_examples/sprite_sheets/ Explanation video: http://youtu.be/czBDKWJqOao Part of a series: http://programarcadegames.com/python_examples/f.php?file=move_with_walls_example.py http://programarcadegames.com/python_examples/f.php?file=maze_runner.py http://programarcadegames.com/python_examples/f.php?file=platform_jumper.py http://programarcadegames.com/python_examples/f.php?file=platform_scroller.py http://programarcadegames.com/python_examples/f.php?file=platform_moving.py http://programarcadegames.com/python_examples/sprite_sheets/ Game art from Kenney.nl: http://opengameart.org/content/platformer-art-deluxe """ import pygame from pygame.locals import * import constants import levels from player import Player print(FULLSCREEN) def main(): """ Main Program """ pygame.init() # Set the height and width of the screen size = [constants.SCREEN_WIDTH, constants.SCREEN_HEIGHT] screen = pygame.display.set_mode(size) pygame.display.set_caption("Platformer with sprite sheets") # Create the player player = Player() # Create all the levels level_list = [] level_list.append(levels.Level_01(player)) level_list.append(levels.Level_02(player)) # Set the current level current_level_no = 0 current_level = level_list[current_level_no] active_sprite_list = pygame.sprite.Group() player.level = current_level player.rect.x = 340 player.rect.y = constants.SCREEN_HEIGHT - player.rect.height active_sprite_list.add(player) #Loop until the user clicks the close button. done = False # Used to manage how fast the screen updates clock = pygame.time.Clock() # -------- Main Program Loop ----------- while not done: for event in pygame.event.get(): # User did something if event.type == pygame.QUIT: # If user clicked close done = True # Flag that we are done so we exit this loop if event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: player.go_left() if event.key == pygame.K_RIGHT: player.go_right() if event.key == pygame.K_UP: player.jump() if event.type == pygame.KEYUP: if event.key == pygame.K_LEFT and player.change_x < 0: player.stop() if event.key == pygame.K_RIGHT and player.change_x > 0: player.stop() # Update the player. active_sprite_list.update() # Update items in the level current_level.update() # If the player gets near the right side, shift the world left (-x) if player.rect.right >= 500: diff = player.rect.right - 500 player.rect.right = 500 current_level.shift_world(-diff) # If the player gets near the left side, shift the world right (+x) if player.rect.left <= 120: diff = 120 - player.rect.left player.rect.left = 120 current_level.shift_world(diff) # If the player gets to the end of the level, go to the next level current_position = player.rect.x + current_level.world_shift if current_position < current_level.level_limit: player.rect.x = 120 if current_level_no < len(level_list)-1: current_level_no += 1 current_level = level_list[current_level_no] player.level = current_level # ALL CODE TO DRAW SHOULD GO BELOW THIS COMMENT current_level.draw(screen) active_sprite_list.draw(screen) # ALL CODE TO DRAW SHOULD GO ABOVE THIS COMMENT # Limit to 60 frames per second clock.tick(60) # Go ahead and update the screen with what we've drawn. pygame.display.flip() # Be IDLE friendly. If you forget this line, the program will 'hang' # on exit. pygame.quit() if __name__ == "__main__": main()
""" Global constants """ # Colors BLACK = ( 0, 0, 0) WHITE = ( 255, 255, 255) BLUE = ( 0, 0, 255) # Screen dimensions SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600
import pygame import constants import platforms class Level(): """ This is a generic super-class used to define a level. Create a child class for each level with level-specific info. """ def __init__(self, player): """ Constructor. Pass in a handle to player. Needed for when moving platforms collide with the player. """ # Lists of sprites used in all levels. Add or remove # lists as needed for your game. self.platform_list = None self.enemy_list = None # Background image self.background = None # How far this world has been scrolled left/right self.world_shift = 0 self.level_limit = -1000 self.platform_list = pygame.sprite.Group() self.enemy_list = pygame.sprite.Group() self.player = player # Update everythign on this level def update(self): """ Update everything in this level.""" self.platform_list.update() self.enemy_list.update() def draw(self, screen): """ Draw everything on this level. """ # Draw the background # We don't shift the background as much as the sprites are shifted # to give a feeling of depth. screen.fill(constants.BLUE) screen.blit(self.background,(self.world_shift // 3,0)) # Draw all the sprite lists that we have self.platform_list.draw(screen) self.enemy_list.draw(screen) def shift_world(self, shift_x): """ When the user moves left/right and we need to scroll everything: """ # Keep track of the shift amount self.world_shift += shift_x # Go through all the sprite lists and shift for platform in self.platform_list: platform.rect.x += shift_x for enemy in self.enemy_list: enemy.rect.x += shift_x # Create platforms for the level class Level_01(Level): """ Definition for level 1. """ def __init__(self, player): """ Create level 1. """ # Call the parent constructor Level.__init__(self, player) self.background = pygame.image.load("background_01.png").convert() self.background.set_colorkey(constants.WHITE) self.level_limit = -2500 # Array with type of platform, and x, y location of the platform. level = [ [platforms.GRASS_LEFT, 500, 500], [platforms.GRASS_MIDDLE, 570, 500], [platforms.GRASS_RIGHT, 640, 500], [platforms.GRASS_LEFT, 800, 400], [platforms.GRASS_MIDDLE, 870, 400], [platforms.GRASS_RIGHT, 940, 400], [platforms.GRASS_LEFT, 1000, 500], [platforms.GRASS_MIDDLE, 1070, 500], [platforms.GRASS_RIGHT, 1140, 500], [platforms.STONE_PLATFORM_LEFT, 1120, 280], [platforms.STONE_PLATFORM_MIDDLE, 1190, 280], [platforms.STONE_PLATFORM_RIGHT, 1260, 280], ] # Go through the array above and add platforms for platform in level: block = platforms.Platform(platform[0]) block.rect.x = platform[1] block.rect.y = platform[2] block.player = self.player self.platform_list.add(block) # Add a custom moving platform block = platforms.MovingPlatform(platforms.STONE_PLATFORM_MIDDLE) block.rect.x = 1350 block.rect.y = 280 block.boundary_left = 1350 block.boundary_right = 1600 block.change_x = 1 block.player = self.player block.level = self self.platform_list.add(block) # Create platforms for the level class Level_02(Level): """ Definition for level 2. """ def __init__(self, player): """ Create level 1. """ # Call the parent constructor Level.__init__(self, player) self.background = pygame.image.load("background_02.png").convert() self.background.set_colorkey(constants.WHITE) self.level_limit = -1000 # Array with type of platform, and x, y location of the platform. level = [ [platforms.STONE_PLATFORM_LEFT, 500, 550], [platforms.STONE_PLATFORM_MIDDLE, 570, 550], [platforms.STONE_PLATFORM_RIGHT, 640, 550], [platforms.GRASS_LEFT, 800, 400], [platforms.GRASS_MIDDLE, 870, 400], [platforms.GRASS_RIGHT, 940, 400], [platforms.GRASS_LEFT, 1000, 500], [platforms.GRASS_MIDDLE, 1070, 500], [platforms.GRASS_RIGHT, 1140, 500], [platforms.STONE_PLATFORM_LEFT, 1120, 280], [platforms.STONE_PLATFORM_MIDDLE, 1190, 280], [platforms.STONE_PLATFORM_RIGHT, 1260, 280], ] # Go through the array above and add platforms for platform in level: block = platforms.Platform(platform[0]) block.rect.x = platform[1] block.rect.y = platform[2] block.player = self.player self.platform_list.add(block) # Add a custom moving platform block = platforms.MovingPlatform(platforms.STONE_PLATFORM_MIDDLE) block.rect.x = 1500 block.rect.y = 300 block.boundary_top = 100 block.boundary_bottom = 550 block.change_y = -1 block.player = self.player block.level = self self.platform_list.add(block)
""" Module for managing platforms. """ import pygame from spritesheet_functions import SpriteSheet # These constants define our platform types: # Name of file # X location of sprite # Y location of sprite # Width of sprite # Height of sprite GRASS_LEFT = (576, 720, 70, 70) GRASS_RIGHT = (576, 576, 70, 70) GRASS_MIDDLE = (504, 576, 70, 70) STONE_PLATFORM_LEFT = (432, 720, 70, 40) STONE_PLATFORM_MIDDLE = (648, 648, 70, 40) STONE_PLATFORM_RIGHT = (792, 648, 70, 40) class Platform(pygame.sprite.Sprite): """ Platform the user can jump on """ def __init__(self, sprite_sheet_data): """ Platform constructor. Assumes constructed with user passing in an array of 5 numbers like what's defined at the top of this code. """ super().__init__() sprite_sheet = SpriteSheet("tiles_spritesheet.png") # Grab the image for this platform self.image = sprite_sheet.get_image(sprite_sheet_data[0], sprite_sheet_data[1], sprite_sheet_data[2], sprite_sheet_data[3]) self.rect = self.image.get_rect() class MovingPlatform(Platform): """ This is a fancier platform that can actually move. """ def __init__(self, sprite_sheet_data): super().__init__(sprite_sheet_data) self.change_x = 0 self.change_y = 0 self.boundary_top = 0 self.boundary_bottom = 0 self.boundary_left = 0 self.boundary_right = 0 self.level = None self.player = None def update(self): """ Move the platform. If the player is in the way, it will shove the player out of the way. This does NOT handle what happens if a platform shoves a player into another object. Make sure moving platforms have clearance to push the player around or add code to handle what happens if they don't. """ # Move left/right self.rect.x += self.change_x # See if we hit the player hit = pygame.sprite.collide_rect(self, self.player) if hit: # We did hit the player. Shove the player around and # assume he/she won't hit anything else. # If we are moving right, set our right side # to the left side of the item we hit if self.change_x < 0: self.player.rect.right = self.rect.left else: # Otherwise if we are moving left, do the opposite. self.player.rect.left = self.rect.right # Move up/down self.rect.y += self.change_y # Check and see if we the player hit = pygame.sprite.collide_rect(self, self.player) if hit: # We did hit the player. Shove the player around and # assume he/she won't hit anything else. # Reset our position based on the top/bottom of the object. if self.change_y < 0: self.player.rect.bottom = self.rect.top else: self.player.rect.top = self.rect.bottom # Check the boundaries and see if we need to reverse # direction. if self.rect.bottom > self.boundary_bottom or self.rect.top < self.boundary_top: self.change_y *= -1 cur_pos = self.rect.x - self.level.world_shift if cur_pos < self.boundary_left or cur_pos > self.boundary_right: self.change_x *= -1
""" This module is used to hold the Player class. The Player represents the user- controlled sprite on the screen. """ import pygame import constants from platforms import MovingPlatform from spritesheet_functions import SpriteSheet class Player(pygame.sprite.Sprite): """ This class represents the bar at the bottom that the player controls. """ # -- Methods def __init__(self): """ Constructor function """ # Call the parent's constructor super().__init__() # -- Attributes # Set speed vector of player self.change_x = 0 self.change_y = 0 # This holds all the images for the animated walk left/right # of our player self.walking_frames_l = [] self.walking_frames_r = [] # What direction is the player facing? self.direction = "R" # List of sprites we can bump against self.level = None sprite_sheet = SpriteSheet("p1_walk.png") # Load all the right facing images into a list image = sprite_sheet.get_image(0, 0, 66, 90) self.walking_frames_r.append(image) image = sprite_sheet.get_image(66, 0, 66, 90) self.walking_frames_r.append(image) image = sprite_sheet.get_image(132, 0, 67, 90) self.walking_frames_r.append(image) image = sprite_sheet.get_image(0, 93, 66, 90) self.walking_frames_r.append(image) image = sprite_sheet.get_image(66, 93, 66, 90) self.walking_frames_r.append(image) image = sprite_sheet.get_image(132, 93, 72, 90) self.walking_frames_r.append(image) image = sprite_sheet.get_image(0, 186, 70, 90) self.walking_frames_r.append(image) # Load all the right facing images, then flip them # to face left. image = sprite_sheet.get_image(0, 0, 66, 90) image = pygame.transform.flip(image, True, False) self.walking_frames_l.append(image) image = sprite_sheet.get_image(66, 0, 66, 90) image = pygame.transform.flip(image, True, False) self.walking_frames_l.append(image) image = sprite_sheet.get_image(132, 0, 67, 90) image = pygame.transform.flip(image, True, False) self.walking_frames_l.append(image) image = sprite_sheet.get_image(0, 93, 66, 90) image = pygame.transform.flip(image, True, False) self.walking_frames_l.append(image) image = sprite_sheet.get_image(66, 93, 66, 90) image = pygame.transform.flip(image, True, False) self.walking_frames_l.append(image) image = sprite_sheet.get_image(132, 93, 72, 90) image = pygame.transform.flip(image, True, False) self.walking_frames_l.append(image) image = sprite_sheet.get_image(0, 186, 70, 90) image = pygame.transform.flip(image, True, False) self.walking_frames_l.append(image) # Set the image the player starts with self.image = self.walking_frames_r[0] # Set a reference to the image rect. self.rect = self.image.get_rect() def update(self): """ Move the player. """ # Gravity self.calc_grav() # Move left/right self.rect.x += self.change_x pos = self.rect.x + self.level.world_shift if self.direction == "R": frame = (pos // 30) % len(self.walking_frames_r) self.image = self.walking_frames_r[frame] else: frame = (pos // 30) % len(self.walking_frames_l) self.image = self.walking_frames_l[frame] # See if we hit anything block_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False) for block in block_hit_list: # If we are moving right, # set our right side to the left side of the item we hit if self.change_x > 0: self.rect.right = block.rect.left elif self.change_x < 0: # Otherwise if we are moving left, do the opposite. self.rect.left = block.rect.right # Move up/down self.rect.y += self.change_y # Check and see if we hit anything block_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False) for block in block_hit_list: # Reset our position based on the top/bottom of the object. if self.change_y > 0: self.rect.bottom = block.rect.top elif self.change_y < 0: self.rect.top = block.rect.bottom # Stop our vertical movement self.change_y = 0 if isinstance(block, MovingPlatform): self.rect.x += block.change_x def calc_grav(self): """ Calculate effect of gravity. """ if self.change_y == 0: self.change_y = 1 else: self.change_y += .35 # See if we are on the ground. if self.rect.y >= constants.SCREEN_HEIGHT - self.rect.height and self.change_y >= 0: self.change_y = 0 self.rect.y = constants.SCREEN_HEIGHT - self.rect.height def jump(self): """ Called when user hits 'jump' button. """ # move down a bit and see if there is a platform below us. # Move down 2 pixels because it doesn't work well if we only move down 1 # when working with a platform moving down. self.rect.y += 2 platform_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False) self.rect.y -= 2 # If it is ok to jump, set our speed upwards if len(platform_hit_list) > 0 or self.rect.bottom >= constants.SCREEN_HEIGHT: self.change_y = -10 # Player-controlled movement: def go_left(self): """ Called when the user hits the left arrow. """ self.change_x = -6 self.direction = "L" def go_right(self): """ Called when the user hits the right arrow. """ self.change_x = 6 self.direction = "R" def stop(self): """ Called when the user lets off the keyboard. """ self.change_x = 0
""" This module is used to pull individual sprites from sprite sheets. """ import pygame import constants class SpriteSheet(object): """ Class used to grab images out of a sprite sheet. """ def __init__(self, file_name): """ Constructor. Pass in the file name of the sprite sheet. """ # Load the sprite sheet. self.sprite_sheet = pygame.image.load(file_name).convert() def get_image(self, x, y, width, height): """ Grab a single image out of a larger spritesheet Pass in the x, y location of the sprite and the width and height of the sprite. """ # Create a new blank image image = pygame.Surface([width, height]).convert() # Copy the sprite from the large sheet onto the smaller image image.blit(self.sprite_sheet, (0, 0), (x, y, width, height)) # Assuming black works as the transparent color image.set_colorkey(constants.BLACK) # Return the image return image
settings
unfold_less visibility play_arrow