Created
January 5, 2025 18:23
-
-
Save EncodeTheCode/58293beaec31ba9281746809cfb65235 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from ursina import * | |
| import time | |
| app = Ursina() | |
| # Player settings | |
| player_speed = 5 | |
| jump_speed = 10 | |
| run_speed = 10 | |
| rate_of_fire = 0.5 # seconds between shots | |
| reload_time = 2 # seconds for reloading | |
| max_magazine = 30 # max ammo in magazine | |
| spare_ammo = 100 # total spare ammo | |
| current_ammo = max_magazine # current ammo in magazine | |
| # Global variables | |
| last_shot_time = 0 | |
| is_reloading = False | |
| reload_start_time = 0 | |
| projectiles = [] | |
| # Floor height | |
| floor_height = 0 | |
| # Create the player | |
| camera.position = Vec3(0, 5, -10) | |
| camera.rotation = Vec3(10, 0, 0) | |
| camera.fov = 90 | |
| window.fps_counter.enabled = False | |
| window.exit_button.visible = False | |
| # Floor Plane with Collision | |
| floor = Entity(model='plane', scale=(10, 1, 10), color=color.gray, collider='box') | |
| floor.position = Vec3(0, floor_height, 0) | |
| # UI for reload text | |
| reload_text = Text(text='', position=(0.5, -0.4), origin=(0.5, 0.5), scale=2, color=color.red) | |
| # Projectile settings | |
| projectile_speed = 20 | |
| # Function to respawn player if they fall off the map | |
| def respawn_player(): | |
| camera.position = Vec3(0, 5, -10) # Reset to default spawn position | |
| camera.rotation = Vec3(10, 0, 0) # Reset rotation | |
| # Function to create projectiles | |
| def create_projectile(): | |
| global current_ammo | |
| if current_ammo > 0: | |
| projectile = Projectile(position=camera.position + camera.forward * 2, direction=camera.forward) | |
| projectiles.append(projectile) | |
| current_ammo -= 1 | |
| print(f"Ammo left: {current_ammo}/{max_magazine}") | |
| else: | |
| print("Out of ammo!") | |
| # Projectile class that inherits from Entity | |
| class Projectile(Entity): | |
| def __init__(self, position, direction): | |
| super().__init__(model='cube', color=color.red, scale=(0.2, 0.2, 0.2)) | |
| self.position = position | |
| self.direction = direction | |
| self.start_position = position | |
| self.travelled_distance = 0 # Track travelled distance | |
| def update(self): | |
| # Move projectile | |
| self.position += self.direction * projectile_speed * time.dt | |
| # Calculate distance travelled | |
| self.travelled_distance = distance(self.start_position, self.position) | |
| # Check if the projectile has exceeded 50 meters | |
| if self.travelled_distance > 50: | |
| remove_projectile(self) | |
| # Wrapper function to remove projectiles after they exceed 50 meters in distance | |
| def remove_projectile(projectile): | |
| if projectile in projectiles: | |
| projectiles.remove(projectile) | |
| projectile.enabled = False # Disable the projectile entity (no longer renders) | |
| print("Projectile removed after 50 meters") | |
| # Handle shooting, reloading, and movement | |
| def update(): | |
| global last_shot_time, reload_start_time, is_reloading, current_ammo, spare_ammo | |
| # Player movement controls (WASD + Space to jump) | |
| if held_keys['w']: | |
| camera.position += camera.forward * player_speed * time.dt | |
| if held_keys['s']: | |
| camera.position -= camera.forward * player_speed * time.dt | |
| if held_keys['a']: | |
| camera.position -= camera.right * player_speed * time.dt | |
| if held_keys['d']: | |
| camera.position += camera.right * player_speed * time.dt | |
| # Jumping (Spacebar) | |
| if held_keys['space'] and camera.position.y <= floor_height + 1: | |
| camera.y += jump_speed * time.dt | |
| # Running (Shift to run) | |
| if held_keys['shift']: | |
| camera.position += camera.forward * run_speed * time.dt | |
| # Shooting (left mouse button) - prevent shooting while reloading | |
| if mouse.left and time.time() - last_shot_time > rate_of_fire and not is_reloading: | |
| create_projectile() | |
| last_shot_time = time.time() | |
| # Reloading system | |
| if held_keys['r'] and not is_reloading: | |
| reload() | |
| if is_reloading: | |
| # Check if reload time is complete | |
| if time.time() - reload_start_time >= reload_time: | |
| # Perform the reload | |
| ammo_needed = max_magazine - current_ammo | |
| ammo_to_reload = min(spare_ammo, ammo_needed) | |
| current_ammo += ammo_to_reload | |
| spare_ammo -= ammo_to_reload | |
| is_reloading = False | |
| reload_text.text = "" # Hide the reloading text after completion | |
| # Update projectiles | |
| for projectile in projectiles: | |
| projectile.update() | |
| # Handle player falling into the abyss (below the floor) | |
| if camera.position.y < floor_height - 5: # Check if player is below the floor by more than 5 meters (i.e., into the abyss) | |
| respawn_player() | |
| # Update camera orientation based on mouse movement without any clicks | |
| camera.rotation_y -= mouse.delta[0] * 0.1 # Rotate the camera horizontally (left-right) | |
| camera.rotation_x -= mouse.delta[1] * 0.1 # Rotate the camera vertically (up-down) | |
| camera.rotation_x = clamp(camera.rotation_x, -80, 80) # Limit vertical camera rotation | |
| # Reload function | |
| def reload(): | |
| global is_reloading, reload_start_time | |
| is_reloading = True | |
| reload_start_time = time.time() | |
| reload_text.text = "Reloading..." | |
| # Start the game loop | |
| app.run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment