pymunk_demo_platformer_07.py Diff

pymunk_demo_platformer_07.py
--- /home/docs/checkouts/readthedocs.org/user_builds/arcade-library/checkouts/stable/doc/tutorials/pymunk_platformer/pymunk_demo_platformer_06.py
+++ /home/docs/checkouts/readthedocs.org/user_builds/arcade-library/checkouts/stable/doc/tutorials/pymunk_platformer/pymunk_demo_platformer_07.py
@@ -1,7 +1,7 @@
 """
 Example of Pymunk Physics Engine Platformer
 """
-
+from typing import Optional
 import arcade
 
 SCREEN_TITLE = "PyMunk Platformer"
@@ -48,24 +48,30 @@
 # Force applied while on the ground
 PLAYER_MOVE_FORCE_ON_GROUND = 8000
 
+# Force applied when moving left/right in the air
+PLAYER_MOVE_FORCE_IN_AIR = 900
+
+# Strength of a jump
+PLAYER_JUMP_IMPULSE = 1800
+
 
 class GameWindow(arcade.Window):
-    """Main Window"""
+    """ Main Window """
 
     def __init__(self, width, height, title):
-        """Create the variables"""
+        """ Create the variables """
 
         # Init the parent class
         super().__init__(width, height, title)
 
         # Player sprite
-        self.player_sprite: arcade.Sprite | None = None
+        self.player_sprite: arcade.Sprite|None = None
 
         # Sprite lists we need
-        self.player_list: arcade.SpriteList | None = None
-        self.wall_list: arcade.SpriteList | None = None
-        self.bullet_list: arcade.SpriteList | None = None
-        self.item_list: arcade.SpriteList | None = None
+        self.player_list: arcade.SpriteList|None = None
+        self.wall_list: arcade.SpriteList|None = None
+        self.bullet_list: arcade.SpriteList|None = None
+        self.item_list: arcade.SpriteList|None = None
 
         # Track the current state of what key is pressed
         self.left_pressed: bool = False
@@ -78,7 +84,7 @@
         self.background_color = arcade.color.AMAZON
 
     def setup(self):
-        """Set up everything with the game"""
+        """ Set up everything with the game """
 
         # Create the sprite lists
         self.player_list = arcade.SpriteList()
@@ -95,10 +101,8 @@
         self.item_list = tile_map.sprite_lists["Dynamic Items"]
 
         # Create player sprite
-        self.player_sprite = arcade.Sprite(
-            ":resources:images/animated_characters/female_person/femalePerson_idle.png",
-            SPRITE_SCALING_PLAYER,
-        )
+        self.player_sprite = arcade.Sprite(":resources:images/animated_characters/female_person/femalePerson_idle.png",
+                                           SPRITE_SCALING_PLAYER)
         # Set player location
         grid_x = 1
         grid_y = 1
@@ -121,7 +125,8 @@
         gravity = (0, -GRAVITY)
 
         # Create the physics engine
-        self.physics_engine = arcade.PymunkPhysicsEngine(damping=damping, gravity=gravity)
+        self.physics_engine = arcade.PymunkPhysicsEngine(damping=damping,
+                                                         gravity=gravity)
 
         # Add the player.
         # For the player, we set the damping to a lower value, which increases
@@ -133,15 +138,13 @@
         # Friction is between two objects in contact. It is important to remember
         # in top-down games that friction moving along the 'floor' is controlled
         # by damping.
-        self.physics_engine.add_sprite(
-            self.player_sprite,
-            friction=PLAYER_FRICTION,
-            mass=PLAYER_MASS,
-            moment_of_inertia=arcade.PymunkPhysicsEngine.MOMENT_INF,
-            collision_type="player",
-            max_horizontal_velocity=PLAYER_MAX_HORIZONTAL_SPEED,
-            max_vertical_velocity=PLAYER_MAX_VERTICAL_SPEED,
-        )
+        self.physics_engine.add_sprite(self.player_sprite,
+                                       friction=PLAYER_FRICTION,
+                                       mass=PLAYER_MASS,
+                                       moment_of_inertia=arcade.PymunkPhysicsEngine.MOMENT_INF,
+                                       collision_type="player",
+                                       max_horizontal_velocity=PLAYER_MAX_HORIZONTAL_SPEED,
+                                       max_vertical_velocity=PLAYER_MAX_VERTICAL_SPEED)
 
         # Create the walls.
         # By setting the body type to PymunkPhysicsEngine.STATIC the walls can't
@@ -150,28 +153,32 @@
         # PymunkPhysicsEngine.KINEMATIC objects will move, but are assumed to be
         # repositioned by code and don't respond to physics forces.
         # Dynamic is default.
-        self.physics_engine.add_sprite_list(
-            self.wall_list,
-            friction=WALL_FRICTION,
-            collision_type="wall",
-            body_type=arcade.PymunkPhysicsEngine.STATIC,
-        )
+        self.physics_engine.add_sprite_list(self.wall_list,
+                                            friction=WALL_FRICTION,
+                                            collision_type="wall",
+                                            body_type=arcade.PymunkPhysicsEngine.STATIC)
 
         # Create the items
-        self.physics_engine.add_sprite_list(
-            self.item_list, friction=DYNAMIC_ITEM_FRICTION, collision_type="item"
-        )
+        self.physics_engine.add_sprite_list(self.item_list,
+                                            friction=DYNAMIC_ITEM_FRICTION,
+                                            collision_type="item")
 
     def on_key_press(self, key, modifiers):
-        """Called whenever a key is pressed."""
+        """Called whenever a key is pressed. """
 
         if key == arcade.key.LEFT:
             self.left_pressed = True
         elif key == arcade.key.RIGHT:
             self.right_pressed = True
+        elif key == arcade.key.UP:
+            # find out if player is standing on ground
+            if self.physics_engine.is_on_ground(self.player_sprite):
+                # She is! Go ahead and jump
+                impulse = (0, PLAYER_JUMP_IMPULSE)
+                self.physics_engine.apply_impulse(self.player_sprite, impulse)
 
     def on_key_release(self, key, modifiers):
-        """Called when the user releases a key."""
+        """Called when the user releases a key. """
 
         if key == arcade.key.LEFT:
             self.left_pressed = False
@@ -179,18 +186,25 @@
             self.right_pressed = False
 
     def on_update(self, delta_time):
-        """Movement and game logic"""
-
+        """ Movement and game logic """
+
+        is_on_ground = self.physics_engine.is_on_ground(self.player_sprite)
         # Update player forces based on keys pressed
         if self.left_pressed and not self.right_pressed:
             # Create a force to the left. Apply it.
-            force = (-PLAYER_MOVE_FORCE_ON_GROUND, 0)
+            if is_on_ground:
+                force = (-PLAYER_MOVE_FORCE_ON_GROUND, 0)
+            else:
+                force = (-PLAYER_MOVE_FORCE_IN_AIR, 0)
             self.physics_engine.apply_force(self.player_sprite, force)
             # Set friction to zero for the player while moving
             self.physics_engine.set_friction(self.player_sprite, 0)
         elif self.right_pressed and not self.left_pressed:
             # Create a force to the right. Apply it.
-            force = (PLAYER_MOVE_FORCE_ON_GROUND, 0)
+            if is_on_ground:
+                force = (PLAYER_MOVE_FORCE_ON_GROUND, 0)
+            else:
+                force = (PLAYER_MOVE_FORCE_IN_AIR, 0)
             self.physics_engine.apply_force(self.player_sprite, force)
             # Set friction to zero for the player while moving
             self.physics_engine.set_friction(self.player_sprite, 0)
@@ -202,16 +216,15 @@
         self.physics_engine.step()
 
     def on_draw(self):
-        """Draw everything"""
+        """ Draw everything """
         self.clear()
         self.wall_list.draw()
         self.bullet_list.draw()
         self.item_list.draw()
         self.player_list.draw()
 
-
 def main():
-    """Main function"""
+    """ Main function """
     window = GameWindow(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
     window.setup()
     arcade.run()