I have tried to use WASD movement and it worked quite well, but let’s say I was facing East in game, when I click/hold W, I move towards North, instead of where I’m facing it takes me to where the set orientation is (North). That’s just one problem, in my code, I had a jumping function, but it wouldn’t work because the game thinks that I am not standing on any solid surface. My last issue was that I added gravity, and it didn’t work very well, but it was still functional.
import os
os.environ[‘PYGAME_HIDE_SUPPORT_PROMPT’] = “hide”
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
import math
Constants
GRID_SIZE = 3
PLANET_RADIUS = 1500.0 # Planet radius in meters
PLAYER_SIZE = 1.75 # Player size in meters (average human height)
RENDER_DISTANCE = 10000.0 # 10 km render distance
GRAVITY = 6.0 # Gravity force
JUMP_VELOCITY = 5.0 # Initial velocity for jumping
FRICTION = 0.9 # Friction coefficient for movement
REAL_SECONDS_PER_INGAME_DAY = 24 * 60 # 24 minutes for a full in-game day
FONT_SIZE = 24 # Adjust font size for better visibility
Function to initialize Pygame and OpenGL
def init():
pygame.init()
display = (1300, 800)
pygame.display.set_mode(display, DOUBLEBUF | OPENGL)
gluPerspective(75, (display[0] / display[1]), 0.1, RENDER_DISTANCE)
glEnable(GL_DEPTH_TEST)
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glEnable(GL_COLOR_MATERIAL)
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE)
glShadeModel(GL_SMOOTH)
glLightfv(GL_LIGHT0, GL_POSITION, (0, 10000, 10000, 1))
# Adding specular highlight
glMaterialfv(GL_FRONT, GL_SPECULAR, (1, 1, 1, 1))
glMateriali(GL_FRONT, GL_SHININESS, 50)
# Initialize font
pygame.font.init()
global font
font = pygame.font.Font(None, FONT_SIZE)
Function to draw a sphere (planet) with texture
def draw_sphere(radius):
quad = gluNewQuadric()
gluQuadricNormals(quad, GLU_SMOOTH)
gluQuadricTexture(quad, GL_TRUE)
gluSphere(quad, radius, 64, 64) # Increased slices and stacks for smoother sphere
gluDeleteQuadric(quad)
Function to draw the grid of planets
def draw_grid(position):
cell_size = PLANET_RADIUS * 10 # Adjust to spread the planets appropriately
half_grid_size = (GRID_SIZE * cell_size) / 2
for i in range(GRID_SIZE):
for j in range(GRID_SIZE):
x = (i * cell_size) - half_grid_size
y = 0 # Planets on the same horizontal plane for simplicity
z = (j * cell_size) - half_grid_size
distance = math.sqrt((position[0] - x)**2 + (position[1] - y)**2 + (position[2] - z)**2)
if distance <= RENDER_DISTANCE:
glPushMatrix()
glTranslatef(x, y, z)
draw_sphere(PLANET_RADIUS)
glPopMatrix()
Function to handle movement and look around
def handle_keys(position, velocity, orientation, is_jumping, on_ground):
keys = pygame.key.get_pressed()
mouse_mov = pygame.mouse.get_rel()
sensitivity = 0.1 # Adjusted sensitivity for smoother mouse movement
camera_speed = 0.1 # Adjusted camera speed for smaller player size
# Mouse movement to control the orientation
orientation[0] += mouse_mov[0] * sensitivity
orientation[1] -= mouse_mov[1] * sensitivity
# Prevent pitch from going too far up or down
orientation[1] = max(-90, min(90, orientation[1]))
# Calculate forward, right, and up vectors based on orientation
yaw, pitch = orientation
forward = [
math.cos(math.radians(pitch)) * math.sin(math.radians(yaw)),
math.sin(math.radians(pitch)),
math.cos(math.radians(pitch)) * math.cos(math.radians(yaw))
]
right = [
math.sin(math.radians(yaw) - math.pi / 2),
0,
math.cos(math.radians(yaw) - math.pi / 2)
]
# Move based on keys pressed
if keys[K_w]:
position[0] += forward[0] * camera_speed
position[2] += forward[2] * camera_speed
if keys[K_s]:
position[0] -= forward[0] * camera_speed
position[2] -= forward[2] * camera_speed
if keys[K_a]:
position[0] -= right[0] * camera_speed
position[2] -= right[2] * camera_speed
if keys[K_d]:
position[0] += right[0] * camera_speed
position[2] += right[2] * camera_speed
if keys[K_SPACE] and on_ground:
velocity[1] = JUMP_VELOCITY
is_jumping = True
on_ground = False
# Apply gravity if not on the ground
if not on_ground:
velocity[1] -= GRAVITY
# Apply friction to horizontal movement
velocity[0] *= FRICTION
velocity[2] *= FRICTION
# Update position based on velocity
position[0] += velocity[0]
position[1] += velocity[1]
position[2] += velocity[2]
return position, velocity, orientation, is_jumping, on_ground
Function to check for collisions with planets
def check_collisions(position, velocity):
cell_size = PLANET_RADIUS * 10
half_grid_size = (GRID_SIZE * cell_size) / 2
on_ground = False
for i in range(GRID_SIZE):
for j in range(GRID_SIZE):
planet_x = (i * cell_size) - half_grid_size
planet_y = 0
planet_z = (j * cell_size) - half_grid_size
distance = math.sqrt((position[0] - planet_x)**2 + (position[1] - planet_y)**2 + (position[2] - planet_z)**2)
if distance < PLANET_RADIUS + PLAYER_SIZE:
# Adjust position to stay on the planet surface
direction = [position[0] - planet_x, position[1] - planet_y, position[2] - planet_z]
direction_magnitude = math.sqrt(direction[0]**2 + direction[1]**2 + direction[2]**2)
direction = [d / direction_magnitude for d in direction] # Normalize the direction vector
position = [
planet_x + direction[0] * (PLANET_RADIUS + PLAYER_SIZE),
planet_y + direction[1] * (PLANET_RADIUS + PLAYER_SIZE),
planet_z + direction[2] * (PLANET_RADIUS + PLAYER_SIZE)
]
# Stop downward velocity when colliding with the ground
if velocity[1] < 0:
velocity[1] = 0
on_ground = True
return position, velocity, on_ground
def render_clock(screen, font, elapsed_time):
# Calculate in-game time
in_game_seconds = (elapsed_time / 1000.0) * (24 * 60 * 60) / REAL_SECONDS_PER_INGAME_DAY
in_game_hours = int(in_game_seconds // 3600) % 24
in_game_minutes = int((in_game_seconds % 3600) // 60)
in_game_seconds = int(in_game_seconds % 60)
time_str = f"{in_game_hours:02}:{in_game_minutes:02}:{in_game_seconds:02}"
text_surface = font.render(time_str, True, (255, 255, 255)) # White color
screen.blit(text_surface, (10, 10))
pygame.display.update() # Ensure the display is updated
def main():
init()
clock = pygame.time.Clock() # Initialize the clock object
pygame.event.set_grab(True)
pygame.mouse.set_visible(False)
# Starting on the surface of the center planet
center_planet_index = GRID_SIZE // 2
cell_size = PLANET_RADIUS * 10
center_planet_position = [
(center_planet_index * cell_size) - ((GRID_SIZE * cell_size) / 2),
0,
(center_planet_index * cell_size) - ((GRID_SIZE * cell_size) / 2)
]
player_spawn_position = [
center_planet_position[0],
PLANET_RADIUS + PLAYER_SIZE, # Set the y-coordinate to the sum of the planet's radius and player size
center_planet_position[2]
]
position = player_spawn_position # Use the spawn position calculated above
velocity = [0.0, 0.0, 0.0]
orientation = [0.0, 0.0] # yaw, pitch
is_jumping = False
on_ground = True
start_time = pygame.time.get_ticks()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
position, velocity, orientation, is_jumping, on_ground = handle_keys(position, velocity, orientation, is_jumping, on_ground)
position, velocity, on_ground = check_collisions(position, velocity) # Check for collisions and adjust position if necessary
glPushMatrix()
glRotatef(-orientation[1], 1, 0, 0)
glRotatef(-orientation[0], 0, 1, 0)
glTranslatef(-position[0], -position[1], -position[2])
draw_grid(position)
glPopMatrix()
# Calculate elapsed time
elapsed_time = pygame.time.get_ticks() - start_time
# Render the clock on the screen
screen = pygame.display.get_surface()
render_clock(screen, font, elapsed_time)
pygame.display.flip()
clock.tick(60) # Cap the frame rate at 60 FPS
if name == “main“:
main()
Astrox9966 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.