Skip to content

Instantly share code, notes, and snippets.

@EncodeTheCode
Created January 5, 2025 18:23
Show Gist options
  • Select an option

  • Save EncodeTheCode/58293beaec31ba9281746809cfb65235 to your computer and use it in GitHub Desktop.

Select an option

Save EncodeTheCode/58293beaec31ba9281746809cfb65235 to your computer and use it in GitHub Desktop.
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