Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import arcade
- import os
- # Constants
- SCREEN_WIDTH = 800
- SCREEN_HEIGHT = 800
- SCREEN_TITLE = "Platformer"
- # Constants used to scale our sprites from their original size
- CHARACTER_SCALING = 1
- TILE_SCALING = 1
- COIN_SCALING = 0.5
- SPRITE_PIXEL_SIZE = 128
- GRID_PIXEL_SIZE = (SPRITE_PIXEL_SIZE * TILE_SCALING)
- ENEMY_SCALING = 1
- SPRITE_SIZE = 32
- SPRITE_SCALING = 0.1
- # Movement speed of player, in pixels per frame
- PLAYER_MOVEMENT_SPEED = 2
- GRAVITY = 0.1
- PLAYER_JUMP_SPEED = 5
- GRAVITY_CONSTANT = 1
- # How many pixels to keep as a minimum margin between the character
- # and the edge of the screen.
- LEFT_VIEWPORT_MARGIN = 25
- RIGHT_VIEWPORT_MARGIN = 500
- BOTTOM_VIEWPORT_MARGIN = 0
- TOP_VIEWPORT_MARGIN = 200
- PLAYER_START_X = 32
- PLAYER_START_Y = 25
- # Constants used to track if the player is facing left or right
- RIGHT_FACING = 0
- LEFT_FACING = 1
- def load_texture_pair(filename):
- """
- Load a texture pair, with the second being a mirror image.
- """
- return [
- arcade.load_texture(filename, scale=CHARACTER_SCALING),
- arcade.load_texture(filename, scale=CHARACTER_SCALING, mirrored=True)
- ]
- class PlayerCharacter(arcade.Sprite):
- def __init__(self):
- # Set up parent class
- super().__init__()
- # Default to face-right
- self.character_face_direction = RIGHT_FACING
- # Used for flipping between image sequences
- self.cur_texture = 0
- # Track our state
- self.jumping = False
- self.climbing = False
- self.is_on_ladder = False
- self.game_over = False
- # Adjust the collision box. Default includes too much empty space
- # side-to-side. Box is centered at sprite center, (0, 0)
- self.points = [[-5.5, -16], [5.5, -16], [5.5, 7], [-5.5, 7]]
- # --- Load Textures ---
- # main_path = "images/Female adventurer/PNG/Poses/character_femaleAdventurer"
- # main_path = "images/Female person/PNG/Poses/character_femalePerson"
- # main_path = "images/Male person/PNG/Poses/character_malePerson"
- # main_path = "images/Male adventurer/PNG/Poses/character_maleAdventurer"
- # main_path = "images/Zombie/PNG/Poses/character_zombie"
- # main_path = "images/Robot/PNG/Poses/character_robot"
- main_path = "images/player_1/"
- # Load textures for idle standing
- self.idle_texture_pair = load_texture_pair(f"{main_path}idle.png")
- self.jump_texture_pair = load_texture_pair(f"{main_path}jump.png")
- self.fall_texture_pair = load_texture_pair(f"{main_path}fall.png")
- # Load textures for walking
- self.walk_textures = []
- for i in range(4):
- texture = load_texture_pair(f"{main_path}walk{i}.png")
- self.walk_textures.append(texture)
- # Load textures for climbing
- self.climbing_textures = []
- texture = arcade.load_texture(f"{main_path}climb2.png", scale=CHARACTER_SCALING)
- self.climbing_textures.append(texture)
- texture = arcade.load_texture(f"{main_path}climb1.png", scale=CHARACTER_SCALING)
- self.climbing_textures.append(texture)
- def update_animation(self, delta_time: float = 1/60):
- # Figure out if we need to flip face left or right
- if self.change_x < 0 and self.character_face_direction == RIGHT_FACING:
- self.character_face_direction = LEFT_FACING
- elif self.change_x > 0 and self.character_face_direction == LEFT_FACING:
- self.character_face_direction = RIGHT_FACING
- if self.center_x > 960:
- self.center_x = 950
- #Die if Y is below 0
- if self.center_y < -0:
- self.center_y = PLAYER_START_Y
- self.center_x = PLAYER_START_X
- #Next level
- if self.center_x > 900 and self.center_y < 90:
- arcade.finish_render()
- arcade.close_window()
- from subprocess import call
- call(["python", "level2.py"])
- # Climbing animation
- if self.is_on_ladder:
- self.climbing = True
- if not self.is_on_ladder and self.climbing:
- self.climbing = False
- if self.climbing and abs(self.change_y) > 1:
- self.cur_texture += 1
- if self.cur_texture > 7:
- self.cur_texture = 0
- if self.climbing:
- self.texture = self.climbing_textures[self.cur_texture // 4]
- return
- # Jumping animation
- if self.jumping and not self.is_on_ladder:
- if self.change_y >= 0:
- self.texture = self.jump_texture_pair[self.character_face_direction]
- else:
- self.texture = self.fall_texture_pair[self.character_face_direction]
- return
- # Idle animation
- if self.change_x == 0:
- self.texture = self.idle_texture_pair[self.character_face_direction]
- return
- # Walking animation
- self.cur_texture += 1
- if self.cur_texture > 3:
- self.cur_texture = 0
- self.texture = self.walk_textures[self.cur_texture][self.character_face_direction]
- #boundary
- if self.left < 0:
- self.left = 0
- elif self.right > SCREEN_WIDTH * 3:
- self.right = SCREEN_WIDTH - 1
- if self.bottom < 0:
- self.bottom = 0
- elif self.top > SCREEN_HEIGHT * 3:
- self.top = SCREEN_HEIGHT - 1
- class MyGame(arcade.Window):
- """
- Main application class.
- """
- def __init__(self):
- """
- Initializer for the game
- """
- # Call the parent class and set up the window
- super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
- # Set the path to start with this program
- file_path = os.path.dirname(os.path.abspath(__file__))
- os.chdir(file_path)
- # Track the current state of what key is pressed
- self.left_pressed = False
- self.right_pressed = False
- self.up_pressed = False
- self.down_pressed = False
- self.jump_needs_reset = False
- # These are 'lists' that keep track of our sprites. Each sprite should
- # go into a list.
- self.coin_list = None
- self.wall_list = None
- self.background_list = None
- self.ladder_list = None
- self.player_list = None
- self.enemy_list = None
- self.moving_wall_list = None
- # Separate variable that holds the player sprite
- self.player_sprite = None
- # Our 'physics' engine
- self.physics_engine = None
- # Used to keep track of our scrolling
- self.view_bottom = 0
- self.view_left = 0
- self.end_of_map = 0
- # Keep track of the score
- self.score = 0
- # Load sounds
- self.collect_coin_sound = arcade.load_sound("sounds/coin1.wav")
- self.jump_sound = arcade.load_sound("sounds/jump1.wav")
- self.game_over = arcade.load_sound("sounds/gameover1.wav")
- def setup(self):
- """ Set up the game here. Call this function to restart the game. """
- # Used to keep track of our scrolling
- self.view_bottom = 0
- self.view_left = 0
- # Keep track of the score
- self.score = 0
- # Create the Sprite lists
- self.player_list = arcade.SpriteList()
- self.background_list = arcade.SpriteList()
- self.wall_list = arcade.SpriteList()
- self.coin_list = arcade.SpriteList()
- self.enemy_list = arcade.SpriteList()
- self.movingplatforms_list = arcade.SpriteList()
- # Set up the player, specifically placing it at these coordinates.
- # self.player_sprite = arcade.Sprite("images/player_1/player_stand.png", CHARACTER_SCALING)
- self.player_sprite = PlayerCharacter()
- self.player_sprite.center_x = PLAYER_START_X
- self.player_sprite.center_y = PLAYER_START_Y
- self.player_list.append(self.player_sprite)
- # --- Load in a map from the tiled editor ---
- # Name of the layer in the file that has our platforms/walls
- platforms_layer_name = 'Platforms'
- moving_platforms_layer_name = 'Moving Platforms'
- # Name of the layer that has items for pick-up
- coins_layer_name = 'Coins'
- # Map name
- map_name = f"LEVEL_1.tmx"
- # Read in the tiled map
- my_map = arcade.tilemap.read_tmx(map_name)
- # Calculate the right edge of the my_map in pixels
- self.end_of_map = my_map.map_size.width * GRID_PIXEL_SIZE
- # -- Platforms
- self.wall_list = arcade.tilemap.process_layer(my_map, platforms_layer_name, TILE_SCALING)
- # -- Moving Platforms
- moving_platforms_list = arcade.tilemap.process_layer(my_map, moving_platforms_layer_name, TILE_SCALING)
- for sprite in moving_platforms_list:
- sprite.boundary_top = sprite.center_y + 300
- sprite.boundary_bottom = sprite.center_y - 75
- sprite.change_y = 2
- self.movingplatforms_list.append(sprite)
- self.wall_list.append(sprite)
- # -- Spike #1
- enemy = arcade.Sprite("images/enemies/spike.png", ENEMY_SCALING)
- enemy.bottom = 48
- enemy.left = 112
- #Spike #2
- enemy2 = arcade.Sprite("images/enemies/spike.png", ENEMY_SCALING)
- enemy2.bottom = 48
- enemy2.left = 128
- #Spike #3
- enemy3 = arcade.Sprite("images/enemies/spike.png", ENEMY_SCALING)
- enemy3.bottom = 48
- enemy3.left = 144
- #Spike #4
- enemy4 = arcade.Sprite("images/enemies/spike.png", ENEMY_SCALING)
- enemy4.bottom = 48
- enemy4.left = 160
- #Spike #5
- enemy5 = arcade.Sprite("images/enemies/spike.png", ENEMY_SCALING)
- enemy5.bottom = 48
- enemy5.left = 176
- #Spike #6
- enemy6 = arcade.Sprite("images/enemies/spike.png", ENEMY_SCALING)
- enemy6.bottom = 80
- enemy6.left = 720
- #Spike #7
- enemy7 = arcade.Sprite("images/enemies/spike.png", ENEMY_SCALING)
- enemy7.bottom = 160
- enemy7.left = 21*16
- #Spike #8
- enemy8 = arcade.Sprite("images/enemies/spike.png", ENEMY_SCALING)
- enemy8.bottom = 160
- enemy8.left = 22*16
- # Set enemy initial speed
- enemy.change_x = 0
- self.enemy_list.append(enemy)
- self.enemy_list.append(enemy2)
- self.enemy_list.append(enemy3)
- self.enemy_list.append(enemy4)
- self.enemy_list.append(enemy5)
- self.enemy_list.append(enemy6)
- self.enemy_list.append(enemy7)
- self.enemy_list.append(enemy8)
- # -- Background objects
- self.background_list = arcade.tilemap.process_layer(my_map, "Background", TILE_SCALING)
- # -- End Flagpole
- self.end_list = arcade.tilemap.process_layer(my_map, "End", TILE_SCALING)
- # -- Background objects
- self.ladder_list = arcade.tilemap.process_layer(my_map, "Ladders", TILE_SCALING)
- # -- Coins
- self.coin_list = arcade.tilemap.process_layer(my_map, coins_layer_name, TILE_SCALING)
- # --- Other stuff
- # Set the background color
- if my_map.background_color:
- arcade.set_background_color(my_map.background_color)
- # Create the 'physics engine'
- self.physics_engine = arcade.PhysicsEnginePlatformer(self.player_sprite,
- self.wall_list,
- gravity_constant=GRAVITY,
- ladders=self.ladder_list)
- def on_draw(self):
- """ Render the screen. """
- # Clear the screen to the background color
- arcade.start_render()
- # Draw our sprites
- self.background_list.draw()
- self.wall_list.draw()
- self.ladder_list.draw()
- self.coin_list.draw()
- self.player_list.draw()
- self.end_list.draw()
- self.enemy_list.draw()
- self.movingplatforms_list.draw()
- # Draw our score on the screen, scrolling it with the viewport
- def process_keychange(self):
- """
- Called when we change a key up/down or we move on/off a ladder.
- """
- # Process up/down
- if self.up_pressed and not self.down_pressed:
- if self.physics_engine.is_on_ladder():
- self.player_sprite.change_y = PLAYER_MOVEMENT_SPEED
- elif self.physics_engine.can_jump() and not self.jump_needs_reset:
- self.player_sprite.change_y = PLAYER_JUMP_SPEED
- self.jump_needs_reset = True
- arcade.play_sound(self.jump_sound)
- elif self.down_pressed and not self.up_pressed:
- if self.physics_engine.is_on_ladder():
- self.player_sprite.change_y = -PLAYER_MOVEMENT_SPEED
- # Process up/down when on a ladder and no movement
- if self.physics_engine.is_on_ladder():
- if not self.up_pressed and not self.down_pressed:
- self.player_sprite.change_y = 0
- elif self.up_pressed and self.down_pressed:
- self.player_sprite.change_y = 0
- # Process left/right
- if self.right_pressed and not self.left_pressed:
- self.player_sprite.change_x = PLAYER_MOVEMENT_SPEED
- elif self.left_pressed and not self.right_pressed:
- self.player_sprite.change_x = -PLAYER_MOVEMENT_SPEED
- else:
- self.player_sprite.change_x = 0
- def on_key_press(self, key, modifiers):
- """Called whenever a key is pressed. """
- if key == arcade.key.UP or key == arcade.key.W:
- self.up_pressed = True
- elif key == arcade.key.DOWN or key == arcade.key.S:
- self.down_pressed = True
- elif key == arcade.key.LEFT or key == arcade.key.A:
- self.left_pressed = True
- elif key == arcade.key.RIGHT or key == arcade.key.D:
- self.right_pressed = True
- self.process_keychange()
- def on_key_release(self, key, modifiers):
- """Called when the user releases a key. """
- if key == arcade.key.UP or key == arcade.key.W:
- self.up_pressed = False
- self.jump_needs_reset = False
- elif key == arcade.key.DOWN or key == arcade.key.S:
- self.down_pressed = False
- elif key == arcade.key.LEFT or key == arcade.key.A:
- self.left_pressed = False
- elif key == arcade.key.RIGHT or key == arcade.key.D:
- self.right_pressed = False
- self.process_keychange()
- def on_update(self, delta_time):
- """ Movement and game logic """
- # Call update on all sprites (The sprites don't do much in this
- # example though.)
- self.physics_engine.update()
- # Update animations
- if self.physics_engine.can_jump():
- self.player_sprite.can_jump = False
- else:
- self.player_sprite.can_jump = True
- if self.physics_engine.is_on_ladder() and not self.physics_engine.can_jump():
- self.player_sprite.is_on_ladder = True
- self.process_keychange()
- else:
- self.player_sprite.is_on_ladder = False
- self.process_keychange()
- self.coin_list.update_animation(delta_time)
- self.background_list.update_animation(delta_time)
- self.player_list.update_animation(delta_time)
- #die if self.game_over is true
- if self.game_over:
- self.player_sprite.center_x = PLAYER_START_X
- self.player_sprite.center_y = PLAYER_START_Y
- self.game_over = False
- # Update walls, used with moving platforms
- self.wall_list.update()
- # Update the player based on the physics engine
- if not self.game_over:
- # Move the enemies
- self.enemy_list.update()
- # Check each enemy
- for enemy in self.enemy_list:
- # If the enemy hit a wall, reverse
- if len(arcade.check_for_collision_with_list(enemy, self.wall_list)) > 0:
- enemy.change_x *= 0
- # If the enemy hit the left boundary, reverse
- elif enemy.boundary_left is not None and enemy.left < enemy.boundary_left:
- enemy.change_x *= 0
- # If the enemy hit the right boundary, reverse
- elif enemy.boundary_right is not None and enemy.right > enemy.boundary_right:
- enemy.change_x = 0
- # Update the player using the physics engine
- self.physics_engine.update()
- # See if the player hit a worm. If so, game over.
- if len(arcade.check_for_collision_with_list(self.player_sprite, self.enemy_list)) > 0:
- self.game_over = True
- # See if we hit any coins
- coin_hit_list = arcade.check_for_collision_with_list(self.player_sprite,
- self.coin_list)
- # Loop through each coin we hit (if any) and remove it
- for coin in coin_hit_list:
- # Figure out how many points this coin is worth
- if 'Points' not in coin.properties:
- print("Warning, collected a coin without a Points property.")
- else:
- points = int(coin.properties['Points'])
- self.score += points
- # Remove the coin
- coin.remove_from_sprite_lists()
- arcade.play_sound(self.collect_coin_sound)
- # Track if we need to change the viewport
- changed_viewport = True
- # --- Manage Scrolling ---
- # Scroll left
- left_boundary = self.view_left + LEFT_VIEWPORT_MARGIN
- if self.player_sprite.left < left_boundary:
- self.view_left -= left_boundary - self.player_sprite.left
- changed_viewport = True
- # Scroll right
- right_boundary = self.view_left + SCREEN_WIDTH - RIGHT_VIEWPORT_MARGIN
- if self.player_sprite.right > right_boundary:
- self.view_left += self.player_sprite.right - right_boundary
- changed_viewport = True
- # Scroll up
- # top_boundary = self.view_bottom + SCREEN_HEIGHT - TOP_VIEWPORT_MARGIN
- # if self.player_sprite.top > top_boundary:
- # self.view_bottom += self.player_sprite.top - top_boundary
- # changed_viewport = True
- # Scroll down
- bottom_boundary = self.view_bottom + BOTTOM_VIEWPORT_MARGIN
- if self.player_sprite.bottom < bottom_boundary:
- self.view_bottom -= bottom_boundary - self.player_sprite.bottom
- changed_viewport = True
- if changed_viewport:
- # Only scroll to integers. Otherwise we end up with pixels that
- # don't line up on the screen
- self.view_bottom = int(self.view_bottom)
- self.view_left = int(self.view_left)
- # Do the scrolling
- self.view_right = SCREEN_WIDTH + self.view_left-400
- if self.view_left < 2:
- self.view_left = 2
- if SCREEN_WIDTH + self.view_left-400 > 960:
- self.view_left = 960+400-SCREEN_WIDTH
- if self.view_bottom < 0:
- self.view_bottom = 0
- arcade.set_viewport(self.view_left,
- SCREEN_WIDTH + self.view_left-400,
- self.view_bottom,
- SCREEN_HEIGHT + self.view_bottom-400)
- def main():
- """ Main method """
- window = MyGame()
- window.setup()
- arcade.run()
- class Start_screen(arcade.Window):
- #will class what we are doing is creating a tpye of varible. The tpye of varible is called Game
- def __init__(self):
- '''
- when making a class we always start with the initializer function
- we call this function __init__. Self is what holds all of the information inside the class.
- '''
- super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
- # this one here is kind of weird. We recall the function __init__ from inside the function __init__
- # but we call it as a super so it does some weird stuff and opens the window for the game.
- def setup(self):
- self.background = None
- def on_draw(self):
- #The name is very important. Based on the name the class will run the function at different times
- # here you will draw your character and your background, really anything that you want on the screen
- arcade.start_render()
- self.background = arcade.load_texture("images/start.png")
- arcade.draw_texture_rectangle(SCREEN_WIDTH/2, SCREEN_HEIGHT/2, SCREEN_WIDTH, SCREEN_HEIGHT, self.background)
- def on_key_press(self, key, modifiers):
- if key == arcade.key.ENTER:
- arcade.close_window()
- main()
- if key == arcade.key.ESCAPE:
- arcade.close_window()
- def mainstart():
- #
- start = Start_screen()
- start.setup()
- arcade.run()
- if __name__ == "__main__":
- mainstart()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement