Created
April 13, 2017 06:13
-
-
Save kiwwisk/ecf8d370a6690c15ff0cc4c6b201fda1 to your computer and use it in GitHub Desktop.
Skeleton for SDL2/OpenGL application in Python 3. Game loop has fixed time step, rendering is going at full speed.
This file contains 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
# | |
# Skeleton for SDL2/OpenGL application in Python | |
# with fixed logic time step, rendering is going still at full speed. | |
# | |
# To turn debug logging messages on, run with -v parameter: | |
# python <script_name.py> -v | |
# | |
import argparse | |
import logging | |
import ctypes | |
import time | |
import sdl2 | |
from OpenGL import GL | |
WIDTH = 450 | |
HEIGHT = 600 | |
LOGIC_FPS = 1.0 / 25.0 # 25 logic frames per second, fixed step | |
def logic(delta_time): | |
""" | |
Game logic goes here. Delta time is fixed to LOGIC_FPS | |
""" | |
pass | |
def render(delta_time): | |
""" | |
Render code goes here. | |
""" | |
GL.glClearColor(0.3, 0.3, 0.3, 1) | |
GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) | |
def init_args_and_logging(): | |
parser = argparse.ArgumentParser( | |
description='OpenGL skeleton app.') | |
parser.add_argument("-v", "--verbose", help="increase output verbosity", | |
action="store_true") | |
format_str = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' | |
args = parser.parse_args() | |
if args.verbose: | |
logging.basicConfig(format=format_str, level=logging.DEBUG) | |
else: | |
logging.basicConfig(format=format_str, level=logging.INFO) | |
def throw_runtime_sdl_error(): | |
err = sdl2.SDL_GetError() | |
logging.error(err) | |
raise RuntimeError(err) | |
def create_opengl_context(window): | |
sdl2.video.SDL_GL_SetAttribute( | |
sdl2.video.SDL_GL_CONTEXT_MAJOR_VERSION, | |
3) | |
sdl2.video.SDL_GL_SetAttribute( | |
sdl2.video.SDL_GL_CONTEXT_MINOR_VERSION, | |
3) | |
sdl2.video.SDL_GL_SetAttribute( | |
sdl2.video.SDL_GL_CONTEXT_PROFILE_MASK, | |
sdl2.video.SDL_GL_CONTEXT_PROFILE_CORE) | |
context = sdl2.SDL_GL_CreateContext(window) | |
GL.glEnable(GL.GL_BLEND) | |
GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA) | |
GL.glEnable(GL.GL_DEPTH_TEST) | |
GL.glDepthFunc(GL.GL_LESS) | |
return context | |
def window_title(frames=None): | |
if not frames: | |
return 'OpenGL Torch demo'.encode('utf-8') | |
return 'OpenGL Torch demo FPS:{}'.format(frames).encode('utf-8') | |
def main(): | |
init_args_and_logging() | |
logging.debug('Application starting...') | |
if sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO) != 0: | |
throw_runtime_sdl_error() | |
logging.debug('SDL Initialized...') | |
try: | |
window = None | |
window = sdl2.SDL_CreateWindow(window_title(), | |
sdl2.SDL_WINDOWPOS_UNDEFINED, | |
sdl2.SDL_WINDOWPOS_UNDEFINED, | |
WIDTH, HEIGHT, | |
sdl2.SDL_WINDOW_OPENGL) | |
if not window: | |
throw_runtime_sdl_error() | |
logging.debug('SDL Window initialized...') | |
context = None | |
context = create_opengl_context(window) | |
if not context: | |
throw_runtime_sdl_error() | |
logging.debug('OpenGL context initialized...') | |
logging.debug('Entering main loop...') | |
accumulator = 0.0 | |
window_title_timer = 0.0 | |
frames = 0 | |
current_time = time.monotonic() | |
running = True | |
while running: | |
event = sdl2.SDL_Event() | |
while sdl2.SDL_PollEvent(ctypes.byref(event)) != 0: | |
if event.type == sdl2.SDL_QUIT: | |
logging.debug('SDL_QUIT event received, bailing out.') | |
running = False | |
elif (event.type == sdl2.SDL_KEYDOWN and | |
event.key.keysym.sym == sdl2.SDLK_ESCAPE): | |
logging.debug('ESC key pressed, bailing out.') | |
running = False | |
new_time = time.monotonic() | |
delta_time = new_time - current_time | |
accumulator += delta_time | |
while accumulator >= LOGIC_FPS: | |
logic(LOGIC_FPS) | |
accumulator -= LOGIC_FPS | |
render(delta_time) | |
sdl2.SDL_GL_SwapWindow(window) | |
sdl2.SDL_Delay(1) | |
frames += 1 | |
window_title_timer += delta_time | |
if window_title_timer >= 1.0: | |
sdl2.SDL_SetWindowTitle(window, window_title(frames)) | |
frames = 0 | |
window_title_timer -= 1.0 | |
current_time = new_time | |
finally: | |
logging.debug('Quitting, doing cleanup...') | |
if context: | |
sdl2.SDL_GL_DeleteContext(context) | |
if window: | |
sdl2.SDL_DestroyWindow(window) | |
sdl2.SDL_Quit() | |
logging.debug('Done. Bye.') | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment