The main class of the PyneCraft engine. It is responsible for
creating the window, setting up the OpenGL context, and running the
main loop of the engine. The main loop of the engine is responsible
for updating the game state, rendering, and handling events.
Parameters:
Name |
Type |
Description |
Default |
engine_parameters |
EngineParameters
|
The parameters of the PyneCraft.
|
required
|
Source code in pynecraft/engine.py
| class PyneCraftEngine:
"""The main class of the PyneCraft engine. It is responsible for
creating the window, setting up the OpenGL context, and running the
main loop of the engine. The main loop of the engine is responsible
for updating the game state, rendering, and handling events.
Args:
engine_parameters (EngineParameters): The parameters of the PyneCraft.
"""
def __init__(self, engine_parameters: EngineParameters) -> None:
self.window_resolution = glm.vec2(engine_parameters.window_resolution)
self.depth_buffer_size = engine_parameters.depth_buffer_size
self.background_color = engine_parameters.background_color
pygame.init()
self.set_opengl_attributes()
# Create the display surface
pygame.display.set_mode(
self.window_resolution, flags=pygame.DOUBLEBUF | pygame.OPENGL
)
# Create the opengl context
self.opengl_context = moderngl.create_context()
# Enable specific OpenGL capabilities for the rendering context.
# `moderngl.DEPTH_TEST` enables depth testing which ensures that pixels
# closer to the camera obscure those further away, maintaining the
# proper visual order of objects.
# `moderngl.CULL_FACE` enables face culling which is a technique for
# improving rendering performance by not drawing faces of polygons that
# are not visible to the camera. Typically, this involves not rendering
# the back faces of objects, assuming the front faces are sufficient to
# represent the visible geometry.
# `moderngl.BLEND` enables blending which is the process of combining the
# color of a source pixel with the color of a destination pixel based on
# their alpha values. It is essential for rendering transparent and
# semi-transparent objects correctly.
self.opengl_context.enable(
moderngl.DEPTH_TEST | moderngl.CULL_FACE | moderngl.BLEND
)
# Set the garbage collection mode of the OpenGL context to "auto".
# This enables the OpenGL context to automatically manages the deletion of
# OpenGL objects (like buffers, textures, and shaders) that are no longer
# in use. This helps prevent memory leaks and ensures that resources are
# freed up when they are no longer needed.
self.opengl_context.gc_mode = "auto"
self.clock = pygame.time.Clock()
self.delta_time = 0 # The time elapsed since the last frame.
self.time = 0
self.is_engine_running = True
self.player = FirstPersonPlayer(
window_resolution=engine_parameters.window_resolution,
player_parameters=engine_parameters.player_parameters,
)
self.shader_program = ShaderProgram(
opengl_context=self.opengl_context, player=self.player, shader_dir="shaders"
)
self.scene = Scene(
opengl_context=self.opengl_context, program=self.shader_program.program
)
def set_opengl_attributes(self) -> None:
"""Set the values of several attributes for the OpenGL context before
creating the display surface.
"""
# Set the version of the OpenGL context to 3.3
pygame.display.gl_set_attribute(pygame.GL_CONTEXT_MAJOR_VERSION, 3)
pygame.display.gl_set_attribute(pygame.GL_CONTEXT_MINOR_VERSION, 3)
# Set the subset of the OpenGL API to be used is the core profile.
# The core profile includes only the modern, streamlined parts of
# OpenGL, removing deprecated functions and features.
pygame.display.gl_set_attribute(
pygame.GL_CONTEXT_PROFILE_MASK, pygame.GL_CONTEXT_PROFILE_CORE
)
# Set the size of the depth buffer in bits. The depth buffer is used
# to handle depth information to determine which objects are in front
# of others in a 3D scene by keeping track of the depth of each pixel.
pygame.display.gl_set_attribute(pygame.GL_DEPTH_SIZE, self.depth_buffer_size)
def update(self) -> None:
"""Update the game state using the core game logic."""
self.player.update(self.delta_time)
self.shader_program.update()
self.scene.update()
self.delta_time = self.clock.tick()
self.time = pygame.time.get_ticks() * 1e-3
pygame.display.set_caption(f"PyneCraft | FPS: {self.clock.get_fps()}")
def render(self) -> None:
"""Render the game state to the screen."""
self.opengl_context.clear(*self.background_color)
self.scene.render()
pygame.display.flip()
def handle_events(self) -> None:
"""Handle events such as user input and window events."""
for event in pygame.event.get():
if event.type == pygame.QUIT or (
event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE
):
self.is_engine_running = False
def run(self) -> None:
"""Run the main loop of the engine, which updates the game state, renders the
game, and handles events.
"""
while self.is_engine_running:
self.update()
self.render()
self.handle_events()
pygame.quit()
sys.exit()
|
handle_events()
Handle events such as user input and window events.
Source code in pynecraft/engine.py
| def handle_events(self) -> None:
"""Handle events such as user input and window events."""
for event in pygame.event.get():
if event.type == pygame.QUIT or (
event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE
):
self.is_engine_running = False
|
render()
Render the game state to the screen.
Source code in pynecraft/engine.py
| def render(self) -> None:
"""Render the game state to the screen."""
self.opengl_context.clear(*self.background_color)
self.scene.render()
pygame.display.flip()
|
run()
Run the main loop of the engine, which updates the game state, renders the
game, and handles events.
Source code in pynecraft/engine.py
| def run(self) -> None:
"""Run the main loop of the engine, which updates the game state, renders the
game, and handles events.
"""
while self.is_engine_running:
self.update()
self.render()
self.handle_events()
pygame.quit()
sys.exit()
|
set_opengl_attributes()
Set the values of several attributes for the OpenGL context before
creating the display surface.
Source code in pynecraft/engine.py
| def set_opengl_attributes(self) -> None:
"""Set the values of several attributes for the OpenGL context before
creating the display surface.
"""
# Set the version of the OpenGL context to 3.3
pygame.display.gl_set_attribute(pygame.GL_CONTEXT_MAJOR_VERSION, 3)
pygame.display.gl_set_attribute(pygame.GL_CONTEXT_MINOR_VERSION, 3)
# Set the subset of the OpenGL API to be used is the core profile.
# The core profile includes only the modern, streamlined parts of
# OpenGL, removing deprecated functions and features.
pygame.display.gl_set_attribute(
pygame.GL_CONTEXT_PROFILE_MASK, pygame.GL_CONTEXT_PROFILE_CORE
)
# Set the size of the depth buffer in bits. The depth buffer is used
# to handle depth information to determine which objects are in front
# of others in a 3D scene by keeping track of the depth of each pixel.
pygame.display.gl_set_attribute(pygame.GL_DEPTH_SIZE, self.depth_buffer_size)
|
update()
Update the game state using the core game logic.
Source code in pynecraft/engine.py
| def update(self) -> None:
"""Update the game state using the core game logic."""
self.player.update(self.delta_time)
self.shader_program.update()
self.scene.update()
self.delta_time = self.clock.tick()
self.time = pygame.time.get_ticks() * 1e-3
pygame.display.set_caption(f"PyneCraft | FPS: {self.clock.get_fps()}")
|