Creating a 3D Game with PyOpenGL
Step 1: Install Required Libraries
Before starting, make sure you have PyGame
and PyOpenGL
installed. These libraries will assist with window management and rendering 3D objects.
Run the following command in your terminal or command prompt to install the required libraries:
pip install pygame PyOpenGL
Step 2: Folder Structure
Here is the folder structure for your game project:
3d_game/
│
├── assets/ # For storing textures, models, sounds
│
├── src/ # Source code for the game
│ ├── main.py # Main game loop
│ ├── engine.py # Contains camera and movement logic
│ ├── player.py # Handles user input (WASD, mouse)
│ └── physics.py # Handles physics (e.g., preventing falling)
│
└── README.md # Game info (optional)
Step 3: engine.py
- Setting Up OpenGL and Camera
In this file, we’ll set up OpenGL, initialize the camera, and handle basic camera movements.
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
import math
# Window settings
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT), DOUBLEBUF | OPENGL)
# Camera settings
camera_pos = [0, 0, -5] # Camera's position in 3D space (x, y, z)
camera_angle = [0, 0] # Camera's angle (yaw, pitch)
# Initialize OpenGL and set up the camera
def init_camera():
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(45, (WIDTH / HEIGHT), 0.1, 50.0) # Perspective projection
glTranslatef(camera_pos[0], camera_pos[1], camera_pos[2]) # Position the camera
def update_camera():
glRotatef(camera_angle[0], 1, 0, 0) # Rotate around X-axis (pitch)
glRotatef(camera_angle[1], 0, 1, 0) # Rotate around Y-axis (yaw)
# Handle keyboard input for movement (WASD keys)
def handle_keys():
global camera_pos
keys = pygame.key.get_pressed()
# Move forward, backward, left, right
if keys[pygame.K_w]:
camera_pos[2] += 0.1 # Move forward
if keys[pygame.K_s]:
camera_pos[2] -= 0.1 # Move backward
if keys[pygame.K_a]:
camera_pos[0] += 0.1 # Move left
if keys[pygame.K_d]:
camera_pos[0] -= 0.1 # Move right
Step 4: player.py
- Handling Mouse Look
This file handles mouse movement for looking around.
import pygame
from engine import camera_pos, camera_angle
# Mouse sensitivity for camera rotation
MOUSE_SENSITIVITY = 0.1
def handle_mouse():
global camera_angle
mouse_x, mouse_y = pygame.mouse.get_pos()
# Calculate the movement of the mouse from the center
delta_x = mouse_x - (WIDTH // 2)
delta_y = mouse_y - (HEIGHT // 2)
# Update camera angles (yaw and pitch)
camera_angle[1] += delta_x * MOUSE_SENSITIVITY # Rotate left/right (yaw)
camera_angle[0] -= delta_y * MOUSE_SENSITIVITY # Rotate up/down (pitch)
# Restrict pitch angle (up/down) to prevent flipping
if camera_angle[0] > 90:
camera_angle[0] = 90
if camera_angle[0] < -90:
camera_angle[0] = -90
# Center the mouse in the window
pygame.mouse.set_pos(WIDTH // 2, HEIGHT // 2)
def update():
handle_mouse() # Control camera with mouse
handle_keys() # Control movement with WASD
Step 5: physics.py
- Basic Physics (Collision)
This file ensures the player doesn’t fall through the ground.
# Simple collision check for the ground
def check_collision(player_pos, ground_level=0):
if player_pos[1] < ground_level:
player_pos[1] = ground_level # Prevent player from falling below ground
Step 6: main.py
- The Main Game Loop
This is where everything comes together: initializing the game, running the game loop, and rendering objects.
import pygame
from engine import init_camera, update_camera
from player import update
from physics import check_collision
# Window settings
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT), DOUBLEBUF | OPENGL)
# Game loop
def game_loop():
clock = pygame.time.Clock()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Clear the screen before drawing
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
# Initialize the camera
init_camera()
# Update the player input (movement, mouse look)
update()
# Basic collision (prevent falling through the ground)
check_collision(camera_pos)
# Draw a rotating cube (just an example)
draw_cube()
# Update the display
pygame.display.flip()
# Control the frame rate
clock.tick(60)
pygame.quit()
# Function to draw a simple cube
def draw_cube():
vertices = [
(1, -1, -1), (1, 1, -1), (-1, 1, -1), (-1, -1, -1),
(1, -1, 1), (1, 1, 1), (-1, -1, 1), (-1, 1, 1)
]
edges = [
(0, 1), (1, 2), (2, 3), (3, 0),
(4, 5), (5, 6), (6, 7), (7, 4),
(0, 4), (1, 5), (2, 6), (3, 7)
]
glBegin(GL_LINES)
for edge in edges:
for vertex in edge:
glVertex3fv(vertices[vertex])
glEnd()
# Run the game
if __name__ == "__main__":
pygame.mouse.set_visible(False) # Hide the mouse cursor
pygame.mouse.set_pos(WIDTH // 2, HEIGHT // 2) # Center the mouse
game_loop()
engine.py
: Initializes OpenGL, sets up the camera, and handles basic movement (WASD).
player.py
: Uses the mouse to look around (pitch and yaw).
physics.py
: Ensures the player doesn’t fall below the ground (basic physics).
main.py
: Contains the main game loop and rendering logic (including drawing a rotating cube).
- Add 3D models: Use
glBindTexture()
to add textures to objects or load external models like.obj
files. - Advanced Physics: Integrate more realistic physics using libraries like
PyBullet
orPymunk
. - Lighting: Use
glEnable(GL_LIGHTING)
andglLightfv()
to add lighting effects to your scene.