Simple examples for beginners in PySDL3 #18
Replies: 21 comments 1 reply
-
Change a background color by timer Click this to collapse/fold
main.py import ctypes
import os
import time
os.environ["SDL_MAIN_USE_CALLBACKS"] = "1"
os.environ["SDL_RENDER_DRIVER"] = "opengl"
import sdl3
renderer = ctypes.POINTER(sdl3.SDL_Renderer)()
window = ctypes.POINTER(sdl3.SDL_Window)()
@sdl3.SDL_AppInit_func
def SDL_AppInit(appstate, argc, argv):
if not sdl3.SDL_Init(sdl3.SDL_INIT_VIDEO):
sdl3.SDL_Log("Couldn't initialize SDL: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
if not sdl3.SDL_CreateWindowAndRenderer("Background color using PySDL3".encode(), 350, 350, 0, window, renderer):
sdl3.SDL_Log("Couldn't create window/renderer: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
sdl3.SDL_SetRenderVSync(renderer, 1) # Turn on vertical sync
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppEvent_func
def SDL_AppEvent(appstate, event):
if sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_QUIT:
return sdl3.SDL_APP_SUCCESS
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppIterate_func
def SDL_AppIterate(appstate):
r = 0
g = int(time.time() * 255 / 2) % 256
b = 0
sdl3.SDL_SetRenderDrawColor(renderer, r, g, b, sdl3.SDL_ALPHA_OPAQUE)
sdl3.SDL_RenderClear(renderer)
sdl3.SDL_RenderPresent(renderer)
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppQuit_func
def SDL_AppQuit(appstate, result):
... # SDL will clean up the window/renderer for us |
Beta Was this translation helpful? Give feedback.
-
Filled rectangle Click this to collapse/fold
main.py import ctypes
import os
os.environ["SDL_MAIN_USE_CALLBACKS"] = "1"
os.environ["SDL_RENDER_DRIVER"] = "opengl"
import sdl3
renderer = ctypes.POINTER(sdl3.SDL_Renderer)()
window = ctypes.POINTER(sdl3.SDL_Window)()
@sdl3.SDL_AppInit_func
def SDL_AppInit(appstate, argc, argv):
if not sdl3.SDL_Init(sdl3.SDL_INIT_VIDEO):
sdl3.SDL_Log("Couldn't initialize SDL: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
if not sdl3.SDL_CreateWindowAndRenderer("Rectangle".encode(), 380, 380, 0, window, renderer):
sdl3.SDL_Log("Couldn't create window/renderer: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
sdl3.SDL_SetRenderVSync(renderer, 1) # Turn on vertical sync
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppEvent_func
def SDL_AppEvent(appstate, event):
if sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_QUIT:
return sdl3.SDL_APP_SUCCESS
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppIterate_func
def SDL_AppIterate(appstate):
# As you can see from this, rendering draws over whatever was drawn before it
sdl3.SDL_SetRenderDrawColor(renderer, 33, 33, 33, sdl3.SDL_ALPHA_OPAQUE)
sdl3.SDL_RenderClear(renderer) # Start with a blank canvas
# Draw a filled rectangle in the middle of the canvas
sdl3.SDL_SetRenderDrawColor(renderer, 100, 255, 100, sdl3.SDL_ALPHA_OPAQUE)
rect = sdl3.SDL_FRect()
rect.x = 50
rect.y = 200
rect.w = 280
rect.h = 30
sdl3.SDL_RenderFillRect(renderer, rect)
sdl3.SDL_RenderPresent(renderer)
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppQuit_func
def SDL_AppQuit(appstate, result):
... # SDL will clean up the window/renderer for us |
Beta Was this translation helpful? Give feedback.
-
Keyboard handler A keyboard handler for W, A, S, D key and arrow keys. It prints Click this to collapse/fold
main.py import ctypes
import os
os.environ["SDL_MAIN_USE_CALLBACKS"] = "1"
os.environ["SDL_RENDER_DRIVER"] = "opengl"
import sdl3
renderer = ctypes.POINTER(sdl3.SDL_Renderer)()
window = ctypes.POINTER(sdl3.SDL_Window)()
keys = { "left": False, "right": False, "up": False, "down": False }
@sdl3.SDL_AppInit_func
def SDL_AppInit(appstate, argc, argv):
if not sdl3.SDL_Init(sdl3.SDL_INIT_VIDEO):
sdl3.SDL_Log("Couldn't initialize SDL: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
windowTitle = "Keyboard handler using PySDL3".encode()
if not sdl3.SDL_CreateWindowAndRenderer(windowTitle, 350, 350, 0, window, renderer):
sdl3.SDL_Log("Couldn't create window/renderer: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
sdl3.SDL_SetRenderVSync(renderer, 1) # Turn on vertical sync
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppEvent_func
def SDL_AppEvent(appstate, event):
if sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_QUIT:
return sdl3.SDL_APP_SUCCESS
elif sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_KEY_DOWN:
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_W or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_UP
):
keys["up"] = True
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_S or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_DOWN
):
keys["down"] = True
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_A or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_LEFT
):
keys["left"] = True
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_D or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_RIGHT
):
keys["right"] = True
elif sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_KEY_UP:
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_W or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_UP
):
keys["up"] = False
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_S or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_DOWN
):
keys["down"] = False
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_A or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_LEFT
):
keys["left"] = False
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_D or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_RIGHT
):
keys["right"] = False
return sdl3.SDL_APP_CONTINUE
def keyboard():
if keys["up"]:
print("up")
if keys["down"]:
print("down")
if keys["left"]:
print("left")
if keys["right"]:
print("right")
@sdl3.SDL_AppIterate_func
def SDL_AppIterate(appstate):
sdl3.SDL_SetRenderDrawColor(renderer, 200, 200, 220, sdl3.SDL_ALPHA_OPAQUE)
sdl3.SDL_RenderClear(renderer)
keyboard()
sdl3.SDL_RenderPresent(renderer)
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppQuit_func
def SDL_AppQuit(appstate, result):
... # SDL will clean up the window/renderer for us |
Beta Was this translation helpful? Give feedback.
-
NoobTuts Snake game The Snake game from the NoobTuts OpenGL/Python tutorial in PySDL3 Click this to collapse/fold
main.py import ctypes
import os
from random import randint
os.environ["SDL_MAIN_USE_CALLBACKS"] = "1"
os.environ["SDL_RENDER_DRIVER"] = "opengl"
import sdl3
renderer = ctypes.POINTER(sdl3.SDL_Renderer)()
window = ctypes.POINTER(sdl3.SDL_Window)()
windowWidth = 400
windowHeight = 400
snake = [(20, 20)] # Snake list of (x, y) positions
snakeDir = (10, 0) # Snake movement direction
interval = 0.2 # update interval in milliseconds
keyFrameTime = 0
lastTime = 0
keys = { "left": False, "right": False, "up": False, "down": False }
food = [] # Food list of type (x, y)
def vecAdd(v1, v2):
return (v1[0] + v2[0], v1[1] + v2[1])
@sdl3.SDL_AppInit_func
def SDL_AppInit(appstate, argc, argv):
global windowWidth
global windowHeight
if not sdl3.SDL_Init(sdl3.SDL_INIT_VIDEO):
sdl3.SDL_Log("Couldn't initialize SDL: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
if not sdl3.SDL_CreateWindowAndRenderer("Snake NoobTuts".encode(), windowWidth, windowHeight, 0, window, renderer):
sdl3.SDL_Log("Couldn't create window/renderer: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
sdl3.SDL_SetRenderVSync(renderer, 1) # Turn on vertical sync
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppEvent_func
def SDL_AppEvent(appstate, event):
if sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_QUIT:
return sdl3.SDL_APP_SUCCESS
elif sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_KEY_DOWN:
if sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_W or sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_UP:
keys["up"] = True
if sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_S or sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_DOWN:
keys["down"] = True
if sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_A or sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_LEFT:
keys["left"] = True
if sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_D or sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_RIGHT:
keys["right"] = True
elif sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_KEY_UP:
if sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_W or sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_UP:
keys["up"] = False
if sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_S or sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_DOWN:
keys["down"] = False
if sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_A or sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_LEFT:
keys["left"] = False
if sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_D or sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_RIGHT:
keys["right"] = False
return sdl3.SDL_APP_CONTINUE
def keyboard():
global snakeDir # important if we want to set it to a new value
if keys["up"]:
snakeDir = (0, -10)
if keys["down"]:
snakeDir = (0, 10)
if keys["left"]:
snakeDir = (-10, 0)
if keys["right"]:
snakeDir = (10, 0)
@sdl3.SDL_AppIterate_func
def SDL_AppIterate(appstate):
global interval
global lastTime
global keyFrameTime
global snake
global snakeDir
# As you can see from this, rendering draws over whatever was drawn before it
sdl3.SDL_SetRenderDrawColor(renderer, 33, 33, 33, sdl3.SDL_ALPHA_OPAQUE)
sdl3.SDL_RenderClear(renderer) # Start with a blank canvas
keyboard();
currentTime = sdl3.SDL_GetTicks()
deltaTime = (currentTime - lastTime) / 1000
lastTime = currentTime
# Game tick
keyFrameTime += deltaTime
if keyFrameTime > interval:
# Insert new position in the beginning of the snake list
snake.insert(0, vecAdd(snake[0], snakeDir))
# Remove the last element
snake.pop()
# Spawn food
r = randint(0, 20) # Spawn food with 5% chance
if r == 0:
# Random spawn position
x = randint(0, int(windowWidth / 10)) * 10
y = randint(0, int(windowHeight / 10)) * 10
food.append((x, y))
print("spawn food:", x, y)
# Let the snake eat the food
(hx, hy) = snake[0] # Get the snake's head x and y position
for x, y in food: # Go through the food list
if hx == x and hy == y: # Is the head where the food is?
snake.append((x, y)) # Make the snake longer
food.remove((x, y)) # Remove the food
# Start a new frame
keyFrameTime = 0
rect = sdl3.SDL_FRect()
rect.w = 10
rect.h = 10
# Draw a food
sdl3.SDL_SetRenderDrawColor(renderer, 128, 128, 255, sdl3.SDL_ALPHA_OPAQUE)
for x, y in food:
rect.x = x
rect.y = y
sdl3.SDL_RenderFillRect(renderer, rect)
# Draw a snake
sdl3.SDL_SetRenderDrawColor(renderer, 255, 255, 255, sdl3.SDL_ALPHA_OPAQUE)
for x, y in snake:
rect.x = x
rect.y = y
sdl3.SDL_RenderFillRect(renderer, rect)
sdl3.SDL_RenderPresent(renderer)
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppQuit_func
def SDL_AppQuit(appstate, result):
... # SDL will clean up the window/renderer for us snake-noobtuts-pysdl3.mp4 |
Beta Was this translation helpful? Give feedback.
-
Text drawing Click this to collapse/fold
main.py import ctypes
import os
os.environ["SDL_MAIN_USE_CALLBACKS"] = "1"
os.environ["SDL_RENDER_DRIVER"] = "opengl"
import sdl3
renderer = ctypes.POINTER(sdl3.SDL_Renderer)()
window = ctypes.POINTER(sdl3.SDL_Window)()
textTexture = None
@sdl3.SDL_AppInit_func
def SDL_AppInit(appstate, argc, argv):
global textTexture
if not sdl3.SDL_Init(sdl3.SDL_INIT_VIDEO):
sdl3.SDL_Log("Couldn't initialize SDL: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
# Initialize the TTF library
if not sdl3.TTF_Init():
sdl3.SDL_Log("Couldn't initialize TTF: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
if not sdl3.SDL_CreateWindowAndRenderer("Draw a text using PySDL3".encode(), 320, 320, 0, window, renderer):
sdl3.SDL_Log("Couldn't create window/renderer: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
sdl3.SDL_SetRenderVSync(renderer, 1) # Turn on vertical sync
font = sdl3.TTF_OpenFont("C:/Windows/Fonts/arial.ttf".encode(), 28)
if not font:
sdl3.SDL_Log("Error: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
textColor = sdl3.SDL_Color(10, 10, 10)
surface = sdl3.TTF_RenderText_Blended(font, "Hello World!".encode(), 12, textColor)
textTexture = sdl3.SDL_CreateTextureFromSurface(renderer, surface)
sdl3.SDL_DestroySurface(surface)
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppEvent_func
def SDL_AppEvent(appstate, event):
if sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_QUIT:
return sdl3.SDL_APP_SUCCESS
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppIterate_func
def SDL_AppIterate(appstate):
sdl3.SDL_SetRenderDrawColor(renderer, 150, 200, 170, sdl3.SDL_ALPHA_OPAQUE)
sdl3.SDL_RenderClear(renderer)
width, height = ctypes.c_float(), ctypes.c_float()
sdl3.SDL_GetTextureSize(textTexture, ctypes.byref(width), ctypes.byref(height))
rect = sdl3.SDL_FRect(20.0, 20.0, width.value, height.value)
sdl3.SDL_RenderTexture(renderer, textTexture, None, rect)
sdl3.SDL_RenderPresent(renderer)
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppQuit_func
def SDL_AppQuit(appstate, result):
global textTexture
# SDL will clean up the window/renderer for us
sdl3.SDL_DestroyTexture(textTexture) |
Beta Was this translation helpful? Give feedback.
-
Mouse handler Click this to collapse/fold
main.py import ctypes
import os
os.environ["SDL_MAIN_USE_CALLBACKS"] = "1"
os.environ["SDL_RENDER_DRIVER"] = "opengl"
import sdl3
renderer = ctypes.POINTER(sdl3.SDL_Renderer)()
window = ctypes.POINTER(sdl3.SDL_Window)()
# This function runs once at startup
@sdl3.SDL_AppInit_func
def SDL_AppInit(appstate, argc, argv):
if not sdl3.SDL_Init(sdl3.SDL_INIT_VIDEO):
sdl3.SDL_Log("Couldn't initialize SDL: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
title = "Mouse handler, PySDL3".encode()
if not sdl3.SDL_CreateWindowAndRenderer(title, 350, 350, 0, window, renderer):
sdl3.SDL_Log("Couldn't create window/renderer: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
sdl3.SDL_SetRenderVSync(renderer, 1) # Turn on vertical sync
return sdl3.SDL_APP_CONTINUE
# This function runs when a new event (mouse input, keypresses, etc) occurs
@sdl3.SDL_AppEvent_func
def SDL_AppEvent(appstate, event):
if sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_QUIT:
return sdl3.SDL_APP_SUCCESS
elif sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_MOUSE_BUTTON_DOWN:
if sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_BUTTON_LEFT:
print("Left button click down")
elif sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_BUTTON_RIGHT:
print("Right button click down")
elif sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_BUTTON_MIDDLE:
print("middle button click down")
elif sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_MOUSE_MOTION:
if sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_BUTTON_LEFT:
print("Motion with left button holding")
elif sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_BUTTON_RIGHT:
print("Motion with right button holding")
elif sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_BUTTON_MIDDLE:
print("Motion with middle button holding")
elif sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_MOUSE_BUTTON_UP:
if sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_BUTTON_LEFT:
print("Left button click up")
elif sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_BUTTON_RIGHT:
print("Right button click up")
elif sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_BUTTON_MIDDLE:
print("middle button click up")
return sdl3.SDL_APP_CONTINUE
# This function runs once per frame, and it is the heart of the program
@sdl3.SDL_AppIterate_func
def SDL_AppIterate(appstate):
sdl3.SDL_SetRenderDrawColor(renderer, 50, 50, 50, sdl3.SDL_ALPHA_OPAQUE)
sdl3.SDL_RenderClear(renderer)
sdl3.SDL_RenderPresent(renderer)
return sdl3.SDL_APP_CONTINUE
# This function runs once at shutdown
@sdl3.SDL_AppQuit_func
def SDL_AppQuit(appstate, result):
... # SDL will clean up the window/renderer for us |
Beta Was this translation helpful? Give feedback.
-
Click counter It shows the Click this to collapse/foldmain.py import ctypes
import os
os.environ["SDL_MAIN_USE_CALLBACKS"] = "1"
os.environ["SDL_RENDER_DRIVER"] = "opengl"
import sdl3
renderer = ctypes.POINTER(sdl3.SDL_Renderer)()
window = ctypes.POINTER(sdl3.SDL_Window)()
font = None
textColor = sdl3.SDL_Color(255, 255, 255)
counter = 0
@sdl3.SDL_AppInit_func
def SDL_AppInit(appstate, argc, argv):
global font
if not sdl3.SDL_Init(sdl3.SDL_INIT_VIDEO):
sdl3.SDL_Log("Couldn't initialize SDL: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
# Initialize the TTF library
if not sdl3.TTF_Init():
sdl3.SDL_Log("Couldn't initialize TTF: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
if not sdl3.SDL_CreateWindowAndRenderer("Click counter using PySDL3".encode(), 320, 320, 0, window, renderer):
sdl3.SDL_Log("Couldn't create window/renderer: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
sdl3.SDL_SetRenderVSync(renderer, 1) # Turn on vertical sync
font = sdl3.TTF_OpenFont("C:/Windows/Fonts/arial.ttf".encode(), 28)
if not font:
sdl3.SDL_Log("Error: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppEvent_func
def SDL_AppEvent(appstate, event):
global counter
if sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_QUIT:
return sdl3.SDL_APP_SUCCESS
elif sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_MOUSE_BUTTON_DOWN:
counter += 1
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppIterate_func
def SDL_AppIterate(appstate):
global counter
global font
sdl3.SDL_SetRenderDrawColor(renderer, 55, 55, 55, sdl3.SDL_ALPHA_OPAQUE)
sdl3.SDL_RenderClear(renderer)
text = "Click counter = %d".encode() % counter
surface = sdl3.TTF_RenderText_Blended(font, text, len(text), textColor)
textTexture = sdl3.SDL_CreateTextureFromSurface(renderer, surface)
sdl3.SDL_DestroySurface(surface)
width, height = ctypes.c_float(), ctypes.c_float()
sdl3.SDL_GetTextureSize(textTexture, ctypes.byref(width), ctypes.byref(height))
rect = sdl3.SDL_FRect(20.0, 20.0, width.value, height.value)
sdl3.SDL_RenderTexture(renderer, textTexture, None, rect)
sdl3.SDL_RenderPresent(renderer)
sdl3.SDL_DestroyTexture(textTexture)
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppQuit_func
def SDL_AppQuit(appstate, result):
... # SDL will clean up the window/renderer for us
|
Beta Was this translation helpful? Give feedback.
-
Play a sound by click This example load this free WAV-file using SDL3_mixer: https://opengameart.org/content/picked-coin-echo-2 and play the sound by mouse click in the window. play-sound-by-click-pysdl3.zip Click this to collapse/fold
main.py import ctypes
import os
os.environ["SDL_MAIN_USE_CALLBACKS"] = "1"
os.environ["SDL_RENDER_DRIVER"] = "opengl"
import sdl3
renderer = ctypes.POINTER(sdl3.SDL_Renderer)()
window = ctypes.POINTER(sdl3.SDL_Window)()
wave = ctypes.POINTER(sdl3.Mix_Chunk)()
@sdl3.SDL_AppInit_func
def SDL_AppInit(appstate, argc, argv):
global wave
if not sdl3.SDL_Init(sdl3.SDL_INIT_VIDEO | sdl3.SDL_INIT_AUDIO):
sdl3.SDL_Log("Couldn't initialize SDL: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
if not sdl3.SDL_CreateWindowAndRenderer("Play a sound by click using PySDL3".encode(), 380, 380, 0, window, renderer):
sdl3.SDL_Log("Couldn't create window/renderer: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
sdl3.SDL_SetRenderVSync(renderer, 1) # Turn on vertical sync
spec = sdl3.SDL_AudioSpec()
spec.freq = sdl3.MIX_DEFAULT_FREQUENCY
spec.format = sdl3.MIX_DEFAULT_FORMAT
spec.channels = sdl3.MIX_DEFAULT_CHANNELS
# Open the audio device
if not sdl3.Mix_OpenAudio(0, spec):
sdl3.SDL_Log("Couldn't open an audio device: %s".encode() % SDL_GetError())
return sdl3.SDL_APP_FAILURE
# Load the WAV file
soundFilePath = "./assets/audio/picked-coin-echo-2.wav".encode();
wave = sdl3.Mix_LoadWAV(soundFilePath);
if not wave:
sdl3.SDL_Log("Couldn't open the file: %s".encode() % soundFilePath)
sdl3.SDL_Log("Error: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE;
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppEvent_func
def SDL_AppEvent(appstate, event):
if sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_QUIT:
return sdl3.SDL_APP_SUCCESS
elif sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_MOUSE_BUTTON_DOWN:
# Play the sound effect
sdl3.Mix_PlayChannel(-1, wave, 0);
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppIterate_func
def SDL_AppIterate(appstate):
sdl3.SDL_SetRenderDrawColor(renderer, 210, 220, 210, sdl3.SDL_ALPHA_OPAQUE)
sdl3.SDL_RenderClear(renderer)
sdl3.SDL_RenderPresent(renderer)
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppQuit_func
def SDL_AppQuit(appstate, result):
global wave
# SDL will clean up the window/renderer for us
if wave:
sdl3.Mix_FreeChunk(wave)
wave = None |
Beta Was this translation helpful? Give feedback.
-
NoobTuts Pong game The Pong game from the NoobTuts OpenGL/C++ tutorial in PySDL3 Click this to collapse/fold
main.py import ctypes
import os
os.environ["SDL_MAIN_USE_CALLBACKS"] = "1"
os.environ["SDL_RENDER_DRIVER"] = "opengl"
import sdl3
renderer = ctypes.POINTER(sdl3.SDL_Renderer)()
window = ctypes.POINTER(sdl3.SDL_Window)()
leftRacketKeys = { "up": False, "down": False }
rightRacketKeys = { "up": False, "down": False }
font = None
textColor = sdl3.SDL_Color(255, 255, 255)
scoreLeft = 0
scoreRight = 0
canvasWidth = 500
canvasHeight = 200
# Rackets in general
racketWidth = 10
racketHeight = 80
racketSpeed = 190
# Left racket position
racketLeftX = 10
racketLeftY = 50
# Right racket position
racketRightX = canvasWidth - racketWidth - 10
racketRightY = 50
lastTime = 0
ballPosX = canvasWidth / 2
ballPosY = canvasHeight / 2
ballDirX = -1
ballDirY = 0
ballSize = 8
ballSpeed = 125
@sdl3.SDL_AppInit_func
def SDL_AppInit(appstate, argc, argv):
global font
global canvasWidth
global canvasHeight
if not sdl3.SDL_Init(sdl3.SDL_INIT_VIDEO):
sdl3.SDL_Log("Couldn't initialize SDL: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
# Initialize the TTF library
if not sdl3.TTF_Init():
sdl3.SDL_Log("Couldn't initialize TTF: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
if not sdl3.SDL_CreateWindowAndRenderer("Pong NoobTuts using PySDL3".encode(), canvasWidth, canvasHeight, 0, window, renderer):
sdl3.SDL_Log("Couldn't create window/renderer: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
sdl3.SDL_SetRenderVSync(renderer, 1) # Turn on vertical sync
font = sdl3.TTF_OpenFont("C:/Windows/Fonts/arial.ttf".encode(), 26)
if not font:
sdl3.SDL_Log("Error: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppEvent_func
def SDL_AppEvent(appstate, event):
if sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_QUIT:
return sdl3.SDL_APP_SUCCESS
elif sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_KEY_DOWN:
if sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_W:
leftRacketKeys["up"] = True
if sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_S:
leftRacketKeys["down"] = True
if sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_UP:
rightRacketKeys["up"] = True
if sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_DOWN:
rightRacketKeys["down"] = True
elif sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_KEY_UP:
if sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_W:
leftRacketKeys["up"] = False
if sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_S:
leftRacketKeys["down"] = False
if sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_UP:
rightRacketKeys["up"] = False
if sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_DOWN:
rightRacketKeys["down"] = False
return sdl3.SDL_APP_CONTINUE
def keyboard(deltaTime):
global racketLeftY
global racketRightY
# Left racket
if leftRacketKeys["up"]:
racketLeftY -= racketSpeed * deltaTime
if leftRacketKeys["down"]:
racketLeftY += racketSpeed * deltaTime
# Right racket
if rightRacketKeys["up"]:
racketRightY -= racketSpeed * deltaTime
if rightRacketKeys["down"]:
racketRightY += racketSpeed * deltaTime
def updateBall(deltaTime):
global ballDirX
global ballDirY
global ballPosX
global ballPosY
global scoreRight
global scoreLeft
# Fly the ball a bit
ballPosX += ballDirX * ballSpeed * deltaTime
ballPosY += ballDirY * ballSpeed * deltaTime
# Hit by left racket?
if (
ballPosX < racketLeftX + racketWidth and ballPosX > racketLeftX and
ballPosY < racketLeftY + racketHeight and ballPosY > racketLeftY
):
# Set the fly direction depending on where it hit the racket
# t is 0.5 if hit at top, 0 at center, -0.5 at bottom
t = ((ballPosY - racketLeftY) / racketHeight) - 0.5
ballDirX = abs(ballDirX) # Force it to be positive
ballDirY = t
print(t)
# Hit by right racket?
if (
ballPosX < racketRightX + racketWidth and ballPosX > racketRightX and
ballPosY < racketRightY + racketHeight and ballPosY > racketRightY
):
# Set the fly direction depending on where it hit the racket
# t is 0.5 if hit at top, 0 at center, -0.5 at bottom
t = ((ballPosY - racketRightY) / racketHeight) - 0.5
ballDirX = -abs(ballDirX) # Force it to be negative
ballDirY = t
print(t)
# Hit left wall?
if ballPosX < 0:
scoreRight += 1
ballPosX = canvasWidth / 2
ballPosY = canvasHeight / 2
ballDirX = abs(ballDirX) # Force it to be positive
ballDirY = 0
# Hit right wall?
if ballPosX > canvasWidth:
scoreLeft += 1
ballPosX = canvasWidth / 2
ballPosY = canvasHeight / 2
ballDirX = -abs(ballDirX) # Force it to be negative
ballDirY = 0
# Hit top wall?
if ballPosY < 0:
ballDirY = abs(ballDirY) # Force to be positive
# Hit bottom wall?
if ballPosY > canvasHeight:
ballDirY = -abs(ballDirY) # Force bot negativef
@sdl3.SDL_AppIterate_func
def SDL_AppIterate(appstate):
global lastTime
# Delta time
currentTime = sdl3.SDL_GetTicks()
deltaTime = (currentTime - lastTime) / 1000
lastTime = currentTime
# Input handling
keyboard(deltaTime)
# Update the ball
updateBall(deltaTime)
sdl3.SDL_SetRenderDrawColor(renderer, 0, 0, 0, sdl3.SDL_ALPHA_OPAQUE)
sdl3.SDL_RenderClear(renderer)
# Draw the left racket
sdl3.SDL_SetRenderDrawColor(renderer, 255, 255, 255, sdl3.SDL_ALPHA_OPAQUE)
rect = sdl3.SDL_FRect(racketLeftX, racketLeftY, racketWidth, racketHeight)
sdl3.SDL_RenderFillRect(renderer, rect)
# Draw the right racket
sdl3.SDL_SetRenderDrawColor(renderer, 255, 255, 255, sdl3.SDL_ALPHA_OPAQUE)
rect = sdl3.SDL_FRect(racketRightX, racketRightY, racketWidth, racketHeight)
sdl3.SDL_RenderFillRect(renderer, rect)
# Draw the ball
sdl3.SDL_SetRenderDrawColor(renderer, 255, 255, 255, sdl3.SDL_ALPHA_OPAQUE)
rect = sdl3.SDL_FRect(ballPosX - ballSize / 2, ballPosY - ballSize / 2, ballSize, ballSize)
sdl3.SDL_RenderFillRect(renderer, rect)
scoreText = "%d:%d".encode() % (scoreLeft, scoreRight)
surface = sdl3.TTF_RenderText_Blended(font, scoreText, len(scoreText), textColor)
textTexture = sdl3.SDL_CreateTextureFromSurface(renderer, surface)
sdl3.SDL_DestroySurface(surface)
width, height = ctypes.c_float(), ctypes.c_float()
sdl3.SDL_GetTextureSize(textTexture, ctypes.byref(width), ctypes.byref(height))
rect = sdl3.SDL_FRect(canvasWidth / 2 - 18, 5, width.value, height.value)
sdl3.SDL_RenderTexture(renderer, textTexture, None, rect)
sdl3.SDL_RenderPresent(renderer)
sdl3.SDL_DestroyTexture(textTexture)
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppQuit_func
def SDL_AppQuit(appstate, result):
... # SDL will clean up the window/renderer for us |
Beta Was this translation helpful? Give feedback.
-
Draw an image It draws an image from the asset pack: https://opengameart.org/content/crate-5
Click this to collapse/foldmain.py import ctypes
import os
os.environ["SDL_MAIN_USE_CALLBACKS"] = "1"
os.environ["SDL_RENDER_DRIVER"] = "opengl"
import sdl3
renderer = ctypes.POINTER(sdl3.SDL_Renderer)()
window = ctypes.POINTER(sdl3.SDL_Window)()
spriteTexture = None
@sdl3.SDL_AppInit_func
def SDL_AppInit(appstate, argc, argv):
global spriteTexture
if not sdl3.SDL_Init(sdl3.SDL_INIT_VIDEO):
sdl3.SDL_Log("Couldn't initialize SDL: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
if not sdl3.SDL_CreateWindowAndRenderer("Draw an image using PySDL3".encode(),
350, 350, 0, window, renderer):
sdl3.SDL_Log("Couldn't create window/renderer: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
sdl3.SDL_SetRenderVSync(renderer, 1) # Turn on vertical sync
texturePath = "./assets/images/crate.png".encode()
spriteTexture = sdl3.IMG_LoadTexture(renderer, texturePath)
if not spriteTexture:
sdl3.SDL_Log("Error: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppEvent_func
def SDL_AppEvent(appstate, event):
if sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_QUIT:
return sdl3.SDL_APP_SUCCESS
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppIterate_func
def SDL_AppIterate(appstate):
sdl3.SDL_SetRenderDrawColor(renderer, 200, 220, 200, sdl3.SDL_ALPHA_OPAQUE)
sdl3.SDL_RenderClear(renderer) # Start with a blank canvas
# Render a texture
srcRect = sdl3.SDL_FRect(0, 0, 256, 256)
destRect = sdl3.SDL_FRect(50, 50, 256, 256)
sdl3.SDL_RenderTexture(renderer, spriteTexture, srcRect, destRect)
sdl3.SDL_RenderPresent(renderer)
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppQuit_func
def SDL_AppQuit(appstate, result):
global spriteTexture
# SDL will clean up the window/renderer for us
sdl3.SDL_DestroyTexture(spriteTexture) |
Beta Was this translation helpful? Give feedback.
-
Sprite animation It plays a sprite animation from the asset pack: https://pixelfrog-assets.itch.io/tiny-swords
Click this to collapse/foldmain.py # pip install PySDL3
# py main.py
import ctypes
import os
import time
os.environ["SDL_MAIN_USE_CALLBACKS"] = "1"
os.environ["SDL_RENDER_DRIVER"] = "opengl"
import sdl3
renderer = ctypes.POINTER(sdl3.SDL_Renderer)()
window = ctypes.POINTER(sdl3.SDL_Window)()
spriteTexture = None
frameIndex = 0
lastTime = 0
animationTime = 0
animationInterval = 0.1
# Define animation frame
frames = []
frames.append(sdl3.SDL_FRect(0, 0, 96, 96)) # Frame 0
frames.append(sdl3.SDL_FRect(96, 0, 96, 96)) # Frame 1
frames.append(sdl3.SDL_FRect(192, 0, 96, 96)) # Frame 2
frames.append(sdl3.SDL_FRect(0, 96, 96, 96)) # Frame 3
frames.append(sdl3.SDL_FRect(96, 96, 96, 96)) # Frame 4
frames.append(sdl3.SDL_FRect(192, 96, 96, 96)) # Frame 5
@sdl3.SDL_AppInit_func
def SDL_AppInit(appstate, argc, argv):
global spriteTexture
if not sdl3.SDL_Init(sdl3.SDL_INIT_VIDEO):
sdl3.SDL_Log("Couldn't initialize SDL: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
if not sdl3.SDL_CreateWindowAndRenderer("Sprite animation using PySDL3".encode(),
350, 200, 0, window, renderer):
sdl3.SDL_Log("Couldn't create window/renderer: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
sdl3.SDL_SetRenderVSync(renderer, 1) # Turn on vertical sync
texturePath = "./assets/sprites/warrior/idle.png".encode()
spriteTexture = sdl3.IMG_LoadTexture(renderer, texturePath)
if not spriteTexture:
sdl3.SDL_Log("Error: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppEvent_func
def SDL_AppEvent(appstate, event):
if sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_QUIT:
return sdl3.SDL_APP_SUCCESS
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppIterate_func
def SDL_AppIterate(appstate):
global animationTime
global lastTime
global frameIndex
# As you can see from this, rendering draws over whatever was drawn before it
sdl3.SDL_SetRenderDrawColor(renderer, 153, 207, 145, sdl3.SDL_ALPHA_OPAQUE)
sdl3.SDL_RenderClear(renderer) # Start with a blank canvas
# Update animation
srcRect = frames[frameIndex]
# Render the current frame
destRect = sdl3.SDL_FRect(50, 50, 96, 96)
sdl3.SDL_RenderTexture(renderer, spriteTexture, srcRect, destRect)
sdl3.SDL_RenderPresent(renderer)
currentTime = sdl3.SDL_GetTicks()
deltaTime = (currentTime - lastTime) / 1000
lastTime = currentTime
animationTime += deltaTime
if animationTime > animationInterval:
frameIndex = (frameIndex + 1) % 6
animationTime = 0
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppQuit_func
def SDL_AppQuit(appstate, result):
# SDL will clean up the window/renderer for us
sdl3.SDL_DestroyTexture(spriteTexture) |
Beta Was this translation helpful? Give feedback.
-
Draw line segments It draws line segments using the SDL_RenderLine() function. Click this to collapse/fold
main.py import ctypes
import os
os.environ["SDL_MAIN_USE_CALLBACKS"] = "1"
os.environ["SDL_RENDER_DRIVER"] = "opengl"
import sdl3
renderer = ctypes.POINTER(sdl3.SDL_Renderer)()
window = ctypes.POINTER(sdl3.SDL_Window)()
@sdl3.SDL_AppInit_func
def SDL_AppInit(appstate, argc, argv):
if not sdl3.SDL_Init(sdl3.SDL_INIT_VIDEO):
sdl3.SDL_Log("Couldn't initialize SDL: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
if not sdl3.SDL_CreateWindowAndRenderer("Draw line segments using PySDL3".encode(),
380, 380, 0, window, renderer):
sdl3.SDL_Log("Couldn't create window/renderer: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
sdl3.SDL_SetRenderVSync(renderer, 1) # Turn on vertical sync
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppEvent_func
def SDL_AppEvent(appstate, event):
if sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_QUIT:
return sdl3.SDL_APP_SUCCESS
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppIterate_func
def SDL_AppIterate(appstate):
# As you can see from this, rendering draws over whatever was drawn before it
sdl3.SDL_SetRenderDrawColor(renderer, 33, 33, 33, sdl3.SDL_ALPHA_OPAQUE)
sdl3.SDL_RenderClear(renderer) # Start with a blank canvas
# First line segment
sdl3.SDL_SetRenderDrawColor(renderer, 255, 0, 0, sdl3.SDL_ALPHA_OPAQUE)
sdl3.SDL_RenderLine(renderer, 90, 105, 285, 50)
# Second line segment
sdl3.SDL_SetRenderDrawColor(renderer, 0, 255, 0, sdl3.SDL_ALPHA_OPAQUE)
sdl3.SDL_RenderLine(renderer, 50, 170, 260, 225)
# Third line segment
sdl3.SDL_SetRenderDrawColor(renderer, 0, 0, 255, sdl3.SDL_ALPHA_OPAQUE)
sdl3.SDL_RenderLine(renderer, 65, 335, 320, 280)
sdl3.SDL_RenderPresent(renderer)
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppQuit_func
def SDL_AppQuit(appstate, result):
... # SDL will clean up the window/renderer for us |
Beta Was this translation helpful? Give feedback.
-
Draw outline rectangles It draws line segments using the SDL_RenderRect() function. Click this to collapse/fold
main.py import ctypes
import os
os.environ["SDL_MAIN_USE_CALLBACKS"] = "1"
os.environ["SDL_RENDER_DRIVER"] = "opengl"
import sdl3
renderer = ctypes.POINTER(sdl3.SDL_Renderer)()
window = ctypes.POINTER(sdl3.SDL_Window)()
@sdl3.SDL_AppInit_func
def SDL_AppInit(appstate, argc, argv):
if not sdl3.SDL_Init(sdl3.SDL_INIT_VIDEO):
sdl3.SDL_Log("Couldn't initialize SDL: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
if not sdl3.SDL_CreateWindowAndRenderer("Draw outline rectangles using PySDL3".encode(),
380, 380, 0, window, renderer):
sdl3.SDL_Log("Couldn't create window/renderer: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
sdl3.SDL_SetRenderVSync(renderer, 1) # Turn on vertical sync
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppEvent_func
def SDL_AppEvent(appstate, event):
if sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_QUIT:
return sdl3.SDL_APP_SUCCESS
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppIterate_func
def SDL_AppIterate(appstate):
# As you can see from this, rendering draws over whatever was drawn before it
sdl3.SDL_SetRenderDrawColor(renderer, 33, 33, 33, sdl3.SDL_ALPHA_OPAQUE)
sdl3.SDL_RenderClear(renderer) # Start with a blank canvas
# First rectangle
sdl3.SDL_SetRenderDrawColor(renderer, 255, 0, 0, sdl3.SDL_ALPHA_OPAQUE)
sdl3.SDL_RenderRect(renderer, sdl3.SDL_FRect(160, 70, 160, 20))
# Second rectangle
sdl3.SDL_SetRenderDrawColor(renderer, 0, 255, 0, sdl3.SDL_ALPHA_OPAQUE)
sdl3.SDL_RenderRect(renderer, sdl3.SDL_FRect(20, 180, 160, 20))
# Third rectangle
sdl3.SDL_SetRenderDrawColor(renderer, 0, 0, 255, sdl3.SDL_ALPHA_OPAQUE)
sdl3.SDL_RenderRect(renderer, sdl3.SDL_FRect(135, 290, 200, 20))
sdl3.SDL_RenderPresent(renderer)
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppQuit_func
def SDL_AppQuit(appstate, result):
... # SDL will clean up the window/renderer for us |
Beta Was this translation helpful? Give feedback.
-
Draw rings using line segments It draws rings using the SDL_RenderLine() function. Click this to collapse/fold
main.py import math
import ctypes
import os
os.environ["SDL_MAIN_USE_CALLBACKS"] = "1"
os.environ["SDL_RENDER_DRIVER"] = "opengl"
import sdl3
renderer = ctypes.POINTER(sdl3.SDL_Renderer)()
window = ctypes.POINTER(sdl3.SDL_Window)()
@sdl3.SDL_AppInit_func
def SDL_AppInit(appstate, argc, argv):
if not sdl3.SDL_Init(sdl3.SDL_INIT_VIDEO):
sdl3.SDL_Log("Couldn't initialize SDL: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
windowTitle = "Draw rings using line segments, PySDL3".encode()
if not sdl3.SDL_CreateWindowAndRenderer(windowTitle,
380, 380, 0, window, renderer):
sdl3.SDL_Log("Couldn't create window/renderer: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
sdl3.SDL_SetRenderVSync(renderer, 1) # Turn on vertical sync
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppEvent_func
def SDL_AppEvent(appstate, event):
if sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_QUIT:
return sdl3.SDL_APP_SUCCESS
return sdl3.SDL_APP_CONTINUE
def drawRing(centerX, centerY, radius, numberOfSegments=100):
angle = 0
angleStep = 360 / numberOfSegments
x = radius * math.cos(math.radians(angle))
y = radius * math.sin(math.radians(angle))
fromX = centerX + x
fromY = centerY + y
for i in range(numberOfSegments + 1):
x = radius * math.cos(math.radians(angle))
y = radius * math.sin(math.radians(angle))
toX = centerX + x
toY = centerY + y
sdl3.SDL_RenderLine(renderer, fromX, fromY, toX, toY)
angle += angleStep
fromX = toX
fromY = toY
@sdl3.SDL_AppIterate_func
def SDL_AppIterate(appstate):
# As you can see from this, rendering draws over whatever was drawn before it
sdl3.SDL_SetRenderDrawColor(renderer, 33, 33, 33, sdl3.SDL_ALPHA_OPAQUE)
sdl3.SDL_RenderClear(renderer) # Start with a blank canvas
# First ring
sdl3.SDL_SetRenderDrawColor(renderer, 255, 0, 0, sdl3.SDL_ALPHA_OPAQUE)
drawRing(95, 70, 20)
# Second ring
sdl3.SDL_SetRenderDrawColor(renderer, 0, 255, 0, sdl3.SDL_ALPHA_OPAQUE)
drawRing(190, 70, 35)
# Third ring
sdl3.SDL_SetRenderDrawColor(renderer, 0, 0, 255, sdl3.SDL_ALPHA_OPAQUE)
drawRing(285, 70, 50)
sdl3.SDL_RenderPresent(renderer)
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppQuit_func
def SDL_AppQuit(appstate, result):
... # SDL will clean up the window/renderer for us |
Beta Was this translation helpful? Give feedback.
-
Draw Box2D colliders using line segments It draws Box2D using the SDL_RenderLine() function. draw-box2d-colliders-pysdl3.zip
Click this to collapse/foldmain.py import ctypes
import math
import os
from Box2D import (b2_dynamicBody, b2BodyDef, b2CircleShape, b2FixtureDef,
b2PolygonShape, b2Vec2, b2World)
os.environ["SDL_MAIN_USE_CALLBACKS"] = "1"
os.environ["SDL_RENDER_DRIVER"] = "opengl"
import sdl3
from debug_drawer import DebugDrawer
renderer = ctypes.POINTER(sdl3.SDL_Renderer)()
window = ctypes.POINTER(sdl3.SDL_Window)()
world = b2World(gravity=b2Vec2(0, 9.8))
ppm = 30 # pixels per meter
@sdl3.SDL_AppInit_func
def SDL_AppInit(appstate, argc, argv):
if not sdl3.SDL_Init(sdl3.SDL_INIT_VIDEO):
sdl3.SDL_Log("Couldn't initialize SDL: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
windowTitle = "Draw Box2D colliders using line segments, PySDL3".encode()
if not sdl3.SDL_CreateWindowAndRenderer(windowTitle, 500, 300, 0, window, renderer):
sdl3.SDL_Log("Couldn't create window/renderer: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
sdl3.SDL_SetRenderVSync(renderer, 1) # Turn on vertical sync
debugDrawer = DebugDrawer(renderer, ppm)
debugDrawer.flags = { "drawShapes": True }
world.renderer = debugDrawer
# Create a ground body
groundBodyDef = b2BodyDef()
groundBodyDef.position = b2Vec2(250 / ppm, 270 / ppm)
groundBody = world.CreateBody(groundBodyDef)
groundShape = b2PolygonShape()
groundShape.SetAsBox(400 / 2 / ppm, 40 / 2 / ppm)
groundFixtureDef = b2FixtureDef()
groundFixtureDef.shape = groundShape
groundFixtureDef.density = 0
groundBody.CreateFixture(groundFixtureDef)
# Create a box body
boxBodyDef = b2BodyDef()
boxBodyDef.position = b2Vec2(200 / ppm, 30 / ppm)
boxBodyDef.angle = 30 * math.pi / 180
boxBodyDef.type = b2_dynamicBody
boxBody = world.CreateBody(boxBodyDef)
boxShape = b2PolygonShape()
boxShape.SetAsBox(60 / 2 / ppm, 60 / 2 / ppm)
boxFixtureDef = b2FixtureDef()
boxFixtureDef.shape = boxShape
boxFixtureDef.density = 1
boxBody.CreateFixture(boxFixtureDef)
# Create a circle body
circleBodyDef = b2BodyDef()
circleBodyDef.position = b2Vec2(300 / ppm, 50 / ppm)
circleBodyDef.type = b2_dynamicBody
circleBody = world.CreateBody(circleBodyDef)
circleShape = b2CircleShape()
circleShape.radius = 20 / ppm
circleFixtureDef = b2FixtureDef()
circleFixtureDef.shape = circleShape
circleFixtureDef.density = 1
circleFixtureDef.restitution = 0.5
circleBody.CreateFixture(circleFixtureDef)
# Create a platform body
platformBodyDef = b2BodyDef()
platformBodyDef.position = b2Vec2(320 / ppm, 200 / ppm)
platformBodyDef.angle = -20 * math.pi / 180
platformBody = world.CreateBody(platformBodyDef)
platformShape = b2PolygonShape()
platformShape.SetAsBox(100 / 2 / ppm, 10 / 2 / ppm)
platformFixtureDef = b2FixtureDef()
platformFixtureDef.shape = platformShape
platformFixtureDef.density = 0
platformBody.CreateFixture(platformFixtureDef)
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppEvent_func
def SDL_AppEvent(appstate, event):
if sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_QUIT:
return sdl3.SDL_APP_SUCCESS
elif sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_MOUSE_BUTTON_DOWN:
print("click")
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppIterate_func
def SDL_AppIterate(appstate):
# Set the color and clear the canvas with color
sdl3.SDL_SetRenderDrawColor(renderer, 50, 50, 50, sdl3.SDL_ALPHA_OPAQUE)
sdl3.SDL_RenderClear(renderer)
world.Step(0.016, 3, 2)
world.DrawDebugData()
sdl3.SDL_RenderPresent(renderer)
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppQuit_func
def SDL_AppQuit(appstate, result):
... # SDL will clean up the window/renderer for us debug_drawer.py import math
import sdl3
from Box2D import b2Draw
class DebugDrawer(b2Draw):
def __init__(self, renderer, pixelsPerMeter, thickness=3):
super().__init__()
self.renderer = renderer
self.ppm = pixelsPerMeter
self.thickness = thickness
def DrawSolidPolygon(self, vertices, color):
r = int(color.r * 255)
g = int(color.g * 255)
b = int(color.b * 255)
sdl3.SDL_SetRenderDrawColor(self.renderer, r, g, b, sdl3.SDL_ALPHA_OPAQUE)
x0 = vertices[0][0] * self.ppm
y0 = vertices[0][1] * self.ppm
x1 = vertices[1][0] * self.ppm
y1 = vertices[1][1] * self.ppm
sdl3.SDL_RenderLine(self.renderer, x0, y0, x1, y1)
x1 = vertices[1][0] * self.ppm
y1 = vertices[1][1] * self.ppm
x2 = vertices[2][0] * self.ppm
y2 = vertices[2][1] * self.ppm
sdl3.SDL_RenderLine(self.renderer, x1, y1, x2, y2)
x2 = vertices[2][0] * self.ppm
y2 = vertices[2][1] * self.ppm
x3 = vertices[3][0] * self.ppm
y3 = vertices[3][1] * self.ppm
sdl3.SDL_RenderLine(self.renderer, x2, y2, x3, y3)
x3 = vertices[3][0] * self.ppm
y3 = vertices[3][1] * self.ppm
x0 = vertices[0][0] * self.ppm
y0 = vertices[0][1] * self.ppm
sdl3.SDL_RenderLine(self.renderer, x3, y3, x0, y0)
def DrawSolidCircle(self, center, radius, axis, color):
numberOfSegments = 100
angle = 0
angleStep = 360 / numberOfSegments
r = int(color.r * 255)
g = int(color.g * 255)
b = int(color.b * 255)
sdl3.SDL_SetRenderDrawColor(self.renderer, r, g, b, sdl3.SDL_ALPHA_OPAQUE)
centerX = center[0] * self.ppm
centerY = center[1] * self.ppm
radius *= self.ppm
x = radius * math.cos(math.radians(angle))
y = radius * math.sin(math.radians(angle))
fromX = centerX + x
fromY = centerY + y
for i in range(numberOfSegments + 1):
x = radius * math.cos(math.radians(angle))
y = radius * math.sin(math.radians(angle))
toX = centerX + x
toY = centerY + y
sdl3.SDL_RenderLine(self.renderer, fromX, fromY, toX, toY)
angle += angleStep
fromX = toX
fromY = toY
def DrawPolygon(self, vertices, color):
pass
def DrawSegment(self, p1, p2, color):
pass
def DrawPoint(self, p, size, color):
pass
def DrawCircle(self, center, radius, color, drawwidth=1):
pass
def DrawTransform(self, xf):
pass |
Beta Was this translation helpful? Give feedback.
-
Draw a rotated and scaled images It draws a rotated and scaled images using the SDL_RenderTextureRotated() function. Asset: https://opengameart.org/content/crate-5 draw-rotated-scaled-image-pysdl3.zip
Click this to collapse/foldmain.py import ctypes
import os
os.environ["SDL_MAIN_USE_CALLBACKS"] = "1"
os.environ["SDL_RENDER_DRIVER"] = "opengl"
import sdl3
renderer = ctypes.POINTER(sdl3.SDL_Renderer)()
window = ctypes.POINTER(sdl3.SDL_Window)()
spriteTexture = None
@sdl3.SDL_AppInit_func
def SDL_AppInit(appstate, argc, argv):
global spriteTexture
if not sdl3.SDL_Init(sdl3.SDL_INIT_VIDEO):
sdl3.SDL_Log("Couldn't initialize SDL: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
windowTitle = "Draw a rotated image using PySDL3".encode()
if not sdl3.SDL_CreateWindowAndRenderer(windowTitle, 380, 380, 0, window, renderer):
sdl3.SDL_Log("Couldn't create window/renderer: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
sdl3.SDL_SetRenderVSync(renderer, 1) # Turn on vertical sync
texturePath = "./assets/images/crate.png".encode()
spriteTexture = sdl3.IMG_LoadTexture(renderer, texturePath)
if not spriteTexture:
sdl3.SDL_Log("Error: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppEvent_func
def SDL_AppEvent(appstate, event):
if sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_QUIT:
return sdl3.SDL_APP_SUCCESS
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppIterate_func
def SDL_AppIterate(appstate):
sdl3.SDL_SetRenderDrawColor(renderer, 200, 220, 200, sdl3.SDL_ALPHA_OPAQUE)
sdl3.SDL_RenderClear(renderer) # Start with a blank canvas
# Render a box
srcRect = sdl3.SDL_FRect(0, 0, 256, 256)
destRect = sdl3.SDL_FRect(50, 50, 128, 128)
# Rotation center (center of the rectangle)
center = sdl3.SDL_FPoint(destRect.w / 2, destRect.h / 2)
sdl3.SDL_RenderTextureRotated(renderer, spriteTexture, None,
destRect, 20, center, sdl3.SDL_FLIP_NONE)
# Render a box
srcRect = sdl3.SDL_FRect(0, 0, 256, 256)
destRect = sdl3.SDL_FRect(200, 200, 100, 100)
# Rotation center (center of the rectangle)
center = sdl3.SDL_FPoint(destRect.w / 2, destRect.h / 2)
sdl3.SDL_RenderTextureRotated(renderer, spriteTexture, None,
destRect, -20, center, sdl3.SDL_FLIP_NONE)
sdl3.SDL_RenderPresent(renderer)
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppQuit_func
def SDL_AppQuit(appstate, result):
global spriteTexture
# SDL will clean up the window/renderer for us
sdl3.SDL_DestroyTexture(spriteTexture) |
Beta Was this translation helpful? Give feedback.
-
Spawn textured boxes and circles by click It spawns a box by left mouse click and a circle by right mouse click. You can disable the drawing of colliders by commenting out this line of code: # world.DrawDebugData() spawn-angry-birds-objects-by-click-box2d-pysdl3.zip
Assets:
Click this to collapse/foldmain.py import ctypes
import math
import os
from Box2D import (b2_dynamicBody, b2BodyDef, b2CircleShape, b2FixtureDef,
b2PolygonShape, b2Vec2, b2World)
os.environ["SDL_MAIN_USE_CALLBACKS"] = "1"
os.environ["SDL_RENDER_DRIVER"] = "opengl"
import sdl3
from debug_drawer import DebugDrawer
renderer = ctypes.POINTER(sdl3.SDL_Renderer)()
window = ctypes.POINTER(sdl3.SDL_Window)()
groundTexture = None
pigTexture = None
blockTexture = None
world = b2World(gravity=b2Vec2(0, 9.8))
ppm = 30 # pixels per meter
groundPosX = 240
groundPosY = 400
groundHalfWidth = 128
groundHalfHeight = 70
boxes = []
boxHalfWidth = 32 / 2 / ppm
boxHalfHeight = 32 / 2 / ppm
circles = []
circleRadius = 27
@sdl3.SDL_AppInit_func
def SDL_AppInit(appstate, argc, argv):
global groundTexture;
global pigTexture;
global blockTexture;
if not sdl3.SDL_Init(sdl3.SDL_INIT_VIDEO):
sdl3.SDL_Log("Couldn't initialize SDL: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
windowTitle = "Spawn boxes and circles using PySDL3 and Box2D".encode()
if not sdl3.SDL_CreateWindowAndRenderer(windowTitle, 480, 480, 0, window, renderer):
sdl3.SDL_Log("Couldn't create window/renderer: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
sdl3.SDL_SetRenderVSync(renderer, 1) # Turn on vertical sync
texturePath = "./assets/sprites/ground.png".encode()
groundTexture = sdl3.IMG_LoadTexture(renderer, texturePath)
if not groundTexture:
sdl3.SDL_Log("Error: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
texturePath = "./assets/sprites/pig.png".encode()
pigTexture = sdl3.IMG_LoadTexture(renderer, texturePath)
if not pigTexture:
sdl3.SDL_Log("Error: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
texturePath = "./assets/sprites/block.png".encode()
blockTexture = sdl3.IMG_LoadTexture(renderer, texturePath)
if not blockTexture:
sdl3.SDL_Log("Error: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
debugDrawer = DebugDrawer(renderer, ppm)
debugDrawer.flags = { "drawShapes": True }
world.renderer = debugDrawer
# Create a ground body
groundBodyDef = b2BodyDef()
groundBodyDef.position = b2Vec2(groundPosX / ppm, groundPosY / ppm)
groundBody = world.CreateBody(groundBodyDef)
groundShape = b2PolygonShape()
groundShape.SetAsBox(groundHalfWidth / ppm, (groundHalfHeight - 12) / ppm)
groundFixtureDef = b2FixtureDef()
groundFixtureDef.shape = groundShape
groundFixtureDef.density = 0
groundBody.CreateFixture(groundFixtureDef)
return sdl3.SDL_APP_CONTINUE
def createBox(x, y):
boxBodyDef = b2BodyDef()
boxBodyDef.position = b2Vec2(x / ppm, y / ppm)
boxBodyDef.type = b2_dynamicBody
boxBody = world.CreateBody(boxBodyDef)
boxShape = b2PolygonShape()
boxShape.SetAsBox(boxHalfWidth, boxHalfHeight)
boxFixtureDef = b2FixtureDef()
boxFixtureDef.shape = boxShape
boxFixtureDef.density = 2
boxFixtureDef.restitution = 0.2
boxBody.CreateFixture(boxFixtureDef)
boxes.append(boxBody)
def createCircle(x, y):
circleBodyDef = b2BodyDef()
circleBodyDef.position = b2Vec2(x / ppm, y / ppm)
circleBodyDef.type = b2_dynamicBody
circleBody = world.CreateBody(circleBodyDef)
circleShape = b2CircleShape()
circleShape.radius = circleRadius / ppm
circleFixtureDef = b2FixtureDef()
circleFixtureDef.shape = circleShape
circleFixtureDef.density = 1
circleFixtureDef.restitution = 0.5
circleBody.CreateFixture(circleFixtureDef)
circles.append(circleBody)
@sdl3.SDL_AppEvent_func
def SDL_AppEvent(appstate, event):
if sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_QUIT:
return sdl3.SDL_APP_SUCCESS
elif sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_MOUSE_BUTTON_DOWN:
if sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_BUTTON_LEFT:
x = sdl3.SDL_DEREFERENCE(event).button.x
y = sdl3.SDL_DEREFERENCE(event).button.y
createBox(x, y)
elif sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_BUTTON_RIGHT:
x = sdl3.SDL_DEREFERENCE(event).button.x
y = sdl3.SDL_DEREFERENCE(event).button.y
createCircle(x, y)
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppIterate_func
def SDL_AppIterate(appstate):
# Set the color and clear the canvas with color
sdl3.SDL_SetRenderDrawColor(renderer, 50, 50, 50, sdl3.SDL_ALPHA_OPAQUE)
sdl3.SDL_RenderClear(renderer)
# Draw boxes
for body in boxes:
boxPosX = body.position[0] * ppm
boxPosY = body.position[1] * ppm
srcRect = sdl3.SDL_FRect(0, 0, 32, 32)
destRect = sdl3.SDL_FRect(boxPosX - 16,
boxPosY - 16, 32, 32)
# Rotation center (center of the rectangle)
center = sdl3.SDL_FPoint(destRect.w / 2, destRect.h / 2)
sdl3.SDL_RenderTextureRotated(renderer, blockTexture, None,
destRect, math.degrees(body.angle), center, sdl3.SDL_FLIP_NONE)
# Draw circles
for body in circles:
circlePosX = body.position[0] * ppm
circlePosY = body.position[1] * ppm
srcRect = sdl3.SDL_FRect(0, 0, 64, 64)
destRect = sdl3.SDL_FRect(circlePosX - 32,
circlePosY - 32, 64, 64)
center = sdl3.SDL_FPoint(destRect.w / 2, destRect.h / 2)
sdl3.SDL_RenderTextureRotated(renderer, pigTexture, None,
destRect, math.degrees(body.angle), center, sdl3.SDL_FLIP_NONE)
# Render a ground
srcRect = sdl3.SDL_FRect(0, 0, 256, 140)
destRect = sdl3.SDL_FRect(groundPosX - groundHalfWidth,
groundPosY - groundHalfHeight, 256, 140)
sdl3.SDL_RenderTexture(renderer, groundTexture, srcRect, destRect)
world.Step(0.016, 3, 2)
world.DrawDebugData()
sdl3.SDL_RenderPresent(renderer)
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppQuit_func
def SDL_AppQuit(appstate, result):
... # SDL will clean up the window/renderer for us
sdl3.SDL_DestroyTexture(groundTexture)
sdl3.SDL_DestroyTexture(pigTexture)
sdl3.SDL_DestroyTexture(blockTexture) debug_drawer.py import math
import sdl3
from Box2D import b2Draw
class DebugDrawer(b2Draw):
def __init__(self, renderer, pixelsPerMeter, thickness=3):
super().__init__()
self.renderer = renderer
self.ppm = pixelsPerMeter
self.thickness = thickness
def DrawSolidPolygon(self, vertices, color):
r = int(color.r * 255)
g = int(color.g * 255)
b = int(color.b * 255)
sdl3.SDL_SetRenderDrawColor(self.renderer, r, g, b, sdl3.SDL_ALPHA_OPAQUE)
x0 = vertices[0][0] * self.ppm
y0 = vertices[0][1] * self.ppm
x1 = vertices[1][0] * self.ppm
y1 = vertices[1][1] * self.ppm
sdl3.SDL_RenderLine(self.renderer, x0, y0, x1, y1)
x1 = vertices[1][0] * self.ppm
y1 = vertices[1][1] * self.ppm
x2 = vertices[2][0] * self.ppm
y2 = vertices[2][1] * self.ppm
sdl3.SDL_RenderLine(self.renderer, x1, y1, x2, y2)
x2 = vertices[2][0] * self.ppm
y2 = vertices[2][1] * self.ppm
x3 = vertices[3][0] * self.ppm
y3 = vertices[3][1] * self.ppm
sdl3.SDL_RenderLine(self.renderer, x2, y2, x3, y3)
x3 = vertices[3][0] * self.ppm
y3 = vertices[3][1] * self.ppm
x0 = vertices[0][0] * self.ppm
y0 = vertices[0][1] * self.ppm
sdl3.SDL_RenderLine(self.renderer, x3, y3, x0, y0)
def DrawSolidCircle(self, center, radius, axis, color):
numberOfSegments = 100
angle = 0
angleStep = 360 / numberOfSegments
r = int(color.r * 255)
g = int(color.g * 255)
b = int(color.b * 255)
sdl3.SDL_SetRenderDrawColor(self.renderer, r, g, b, sdl3.SDL_ALPHA_OPAQUE)
centerX = center[0] * self.ppm
centerY = center[1] * self.ppm
radius *= self.ppm
x = radius * math.cos(math.radians(angle))
y = radius * math.sin(math.radians(angle))
fromX = centerX + x
fromY = centerY + y
for i in range(numberOfSegments + 1):
x = radius * math.cos(math.radians(angle))
y = radius * math.sin(math.radians(angle))
toX = centerX + x
toY = centerY + y
sdl3.SDL_RenderLine(self.renderer, fromX, fromY, toX, toY)
angle += angleStep
fromX = toX
fromY = toY
def DrawPolygon(self, vertices, color):
pass
def DrawSegment(self, p1, p2, color):
pass
def DrawPoint(self, p, size, color):
pass
def DrawCircle(self, center, radius, color, drawwidth=1):
pass
def DrawTransform(self, xf):
pass |
Beta Was this translation helpful? Give feedback.
-
Move Box2D circle by keys It moves a circle by WASD or arrow keys. move-box2d-circle-by-keys-pysdl3.zip
Click this to collapse/foldmain.py import ctypes
import math
import os
from Box2D import (b2_dynamicBody, b2BodyDef, b2CircleShape, b2FixtureDef,
b2PolygonShape, b2Vec2, b2World)
os.environ["SDL_MAIN_USE_CALLBACKS"] = "1"
os.environ["SDL_RENDER_DRIVER"] = "opengl"
import sdl3
from debug_drawer import DebugDrawer
renderer = ctypes.POINTER(sdl3.SDL_Renderer)()
window = ctypes.POINTER(sdl3.SDL_Window)()
keys = { "left": False, "right": False, "up": False, "down": False }
world = b2World(gravity=b2Vec2(0, 0))
ppm = 30 # pixels per meter
playerBody = None
playerSpeed = 5
@sdl3.SDL_AppInit_func
def SDL_AppInit(appstate, argc, argv):
global playerBody
if not sdl3.SDL_Init(sdl3.SDL_INIT_VIDEO):
sdl3.SDL_Log("Couldn't initialize SDL: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
windowTitle = "Move Box2D circle by keys using PySDL3".encode()
if not sdl3.SDL_CreateWindowAndRenderer(windowTitle, 390, 390, 0, window, renderer):
sdl3.SDL_Log("Couldn't create window/renderer: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
sdl3.SDL_SetRenderVSync(renderer, 1) # Turn on vertical sync
debugDrawer = DebugDrawer(renderer, ppm)
debugDrawer.flags = { "drawShapes": True }
world.renderer = debugDrawer
# Friction
friction = 0.1
# Create a wall body
wallBodyDef = b2BodyDef()
wallBodyDef.position = b2Vec2(200 / ppm, 150 / ppm)
wallBodyDef.angle = math.radians(45)
wallBody = world.CreateBody(wallBodyDef)
wallShape = b2PolygonShape()
wallShape.SetAsBox(200 / 2 / ppm, 20 / 2 / ppm)
wallFixtureDef = b2FixtureDef()
wallFixtureDef.shape = wallShape
wallFixtureDef.density = 0
wallFixtureDef.friction = friction
wallBody.CreateFixture(wallFixtureDef)
# Create a player body
playerBodyDef = b2BodyDef()
playerBodyDef.allowSleep = False
playerBodyDef.position = b2Vec2(200 / ppm, 250 / ppm)
playerBodyDef.fixedRotation = True
playerBodyDef.type = b2_dynamicBody
playerBody = world.CreateBody(playerBodyDef)
playerShape = b2CircleShape()
playerShape.radius = 20 / ppm
playerFixtureDef = b2FixtureDef()
playerFixtureDef.shape = playerShape
playerFixtureDef.density = 1
playerFixtureDef.friction = friction
playerBody.CreateFixture(playerFixtureDef)
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppEvent_func
def SDL_AppEvent(appstate, event):
if sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_QUIT:
return sdl3.SDL_APP_SUCCESS
elif sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_KEY_DOWN:
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_W or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_UP
):
keys["up"] = True
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_S or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_DOWN
):
keys["down"] = True
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_A or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_LEFT
):
keys["left"] = True
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_D or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_RIGHT
):
keys["right"] = True
elif sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_KEY_UP:
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_W or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_UP
):
keys["up"] = False
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_S or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_DOWN
):
keys["down"] = False
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_A or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_LEFT
):
keys["left"] = False
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_D or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_RIGHT
):
keys["right"] = False
return sdl3.SDL_APP_CONTINUE
def keyboard():
if keys["up"]:
playerBody.linearVelocity.x = 0
playerBody.linearVelocity.y = -playerSpeed
if keys["down"]:
playerBody.linearVelocity.x = 0
playerBody.linearVelocity.y = playerSpeed
if keys["left"]:
playerBody.linearVelocity.x = -playerSpeed
playerBody.linearVelocity.y = 0
if keys["right"]:
playerBody.linearVelocity.x = playerSpeed
playerBody.linearVelocity.y = 0
if (
not keys["up"] and not keys["down"] and
not keys["left"] and not keys["right"]
):
playerBody.linearVelocity = b2Vec2(0, 0)
@sdl3.SDL_AppIterate_func
def SDL_AppIterate(appstate):
sdl3.SDL_SetRenderDrawColor(renderer, 55, 55, 55, sdl3.SDL_ALPHA_OPAQUE)
sdl3.SDL_RenderClear(renderer)
keyboard()
world.Step(0.016, 3, 2)
world.DrawDebugData()
sdl3.SDL_RenderPresent(renderer)
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppQuit_func
def SDL_AppQuit(appstate, result):
... # SDL will clean up the window/renderer for us debug_drawer.py import math
import sdl3
from Box2D import b2Draw
class DebugDrawer(b2Draw):
def __init__(self, renderer, pixelsPerMeter, thickness=3):
super().__init__()
self.renderer = renderer
self.ppm = pixelsPerMeter
self.thickness = thickness
def DrawSolidPolygon(self, vertices, color):
r = int(color.r * 255)
g = int(color.g * 255)
b = int(color.b * 255)
sdl3.SDL_SetRenderDrawColor(self.renderer, r, g, b, sdl3.SDL_ALPHA_OPAQUE)
x0 = vertices[0][0] * self.ppm
y0 = vertices[0][1] * self.ppm
x1 = vertices[1][0] * self.ppm
y1 = vertices[1][1] * self.ppm
sdl3.SDL_RenderLine(self.renderer, x0, y0, x1, y1)
x1 = vertices[1][0] * self.ppm
y1 = vertices[1][1] * self.ppm
x2 = vertices[2][0] * self.ppm
y2 = vertices[2][1] * self.ppm
sdl3.SDL_RenderLine(self.renderer, x1, y1, x2, y2)
x2 = vertices[2][0] * self.ppm
y2 = vertices[2][1] * self.ppm
x3 = vertices[3][0] * self.ppm
y3 = vertices[3][1] * self.ppm
sdl3.SDL_RenderLine(self.renderer, x2, y2, x3, y3)
x3 = vertices[3][0] * self.ppm
y3 = vertices[3][1] * self.ppm
x0 = vertices[0][0] * self.ppm
y0 = vertices[0][1] * self.ppm
sdl3.SDL_RenderLine(self.renderer, x3, y3, x0, y0)
def DrawSolidCircle(self, center, radius, axis, color):
numberOfSegments = 100
angle = 0
angleStep = 360 / numberOfSegments
r = int(color.r * 255)
g = int(color.g * 255)
b = int(color.b * 255)
sdl3.SDL_SetRenderDrawColor(self.renderer, r, g, b, sdl3.SDL_ALPHA_OPAQUE)
centerX = center[0] * self.ppm
centerY = center[1] * self.ppm
radius *= self.ppm
x = radius * math.cos(math.radians(angle))
y = radius * math.sin(math.radians(angle))
fromX = centerX + x
fromY = centerY + y
for i in range(numberOfSegments + 1):
x = radius * math.cos(math.radians(angle))
y = radius * math.sin(math.radians(angle))
toX = centerX + x
toY = centerY + y
sdl3.SDL_RenderLine(self.renderer, fromX, fromY, toX, toY)
angle += angleStep
fromX = toX
fromY = toY
def DrawPolygon(self, vertices, color):
pass
def DrawSegment(self, p1, p2, color):
pass
def DrawPoint(self, p, size, color):
pass
def DrawCircle(self, center, radius, color, drawwidth=1):
pass
def DrawTransform(self, xf):
pass |
Beta Was this translation helpful? Give feedback.
-
Detect the begin and end contact using Box2D and PySDL3 It shows how to use the b2ContactListener class to detect contacts. begin-and-end-contact-box2d-pysdl3.zip Click this to collapse/foldmain.py import ctypes
import math
import os
from Box2D import (b2_dynamicBody, b2BodyDef, b2CircleShape, b2FixtureDef,
b2PolygonShape, b2Vec2, b2World)
os.environ["SDL_MAIN_USE_CALLBACKS"] = "1"
os.environ["SDL_RENDER_DRIVER"] = "opengl"
import sdl3
from contact_listener import ContactListener
from debug_drawer import DebugDrawer
renderer = ctypes.POINTER(sdl3.SDL_Renderer)()
window = ctypes.POINTER(sdl3.SDL_Window)()
keys = { "left": False, "right": False, "up": False, "down": False }
world = b2World(gravity=b2Vec2(0, 0))
ppm = 30 # pixels per meter
contactListener = None
font = None
playerBody = None
playerSpeed = 5
@sdl3.SDL_AppInit_func
def SDL_AppInit(appstate, argc, argv):
global contactListener
global font
global playerBody
if not sdl3.SDL_Init(sdl3.SDL_INIT_VIDEO):
sdl3.SDL_Log("Couldn't initialize SDL: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
# Initialize the TTF library
if not sdl3.TTF_Init():
sdl3.SDL_Log("Couldn't initialize TTF: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
windowTitle = "Begin and end contact using Box2D and PySDL3".encode()
if not sdl3.SDL_CreateWindowAndRenderer(windowTitle, 430, 430, 0, window, renderer):
sdl3.SDL_Log("Couldn't create window/renderer: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
sdl3.SDL_SetRenderVSync(renderer, 1) # Turn on vertical sync
font = sdl3.TTF_OpenFont("C:/Windows/Fonts/arial.ttf".encode(), 28)
if not font:
sdl3.SDL_Log("Error: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
# Create DebugDrawer and configure it
debugDrawer = DebugDrawer(renderer, ppm)
debugDrawer.flags = { "drawShapes": True }
world.renderer = debugDrawer
# Create a ContactListener
contactListener = ContactListener(font)
world.contactListener = contactListener
# Friction
friction = 0.1
# Create a top wall body
topWallBodyDef = b2BodyDef()
topWallBodyDef.position = b2Vec2(200 / ppm, 150 / ppm)
topWallBodyDef.angle = math.radians(20)
topWallBody = world.CreateBody(topWallBodyDef)
topWallShape = b2PolygonShape()
topWallShape.SetAsBox(200 / 2 / ppm, 20 / 2 / ppm)
topWallFixtureDef = b2FixtureDef()
topWallFixtureDef.shape = topWallShape
topWallFixtureDef.density = 0
topWallFixtureDef.friction = friction
topWallFixture = topWallBody.CreateFixture(topWallFixtureDef)
topWallFixture.userData = { "name": "topWall" }
# Create a left wall body
leftWallBodyDef = b2BodyDef()
leftWallBodyDef.position = b2Vec2(120 / ppm, 230 / ppm)
leftWallBodyDef.angle = math.radians(90)
leftWallBody = world.CreateBody(leftWallBodyDef)
leftWallShape = b2PolygonShape()
leftWallShape.SetAsBox(200 / 2 / ppm, 20 / 2 / ppm)
leftWallFixtureDef = b2FixtureDef()
leftWallFixtureDef.shape = leftWallShape
leftWallFixtureDef.density = 0
leftWallFixtureDef.friction = friction
leftWallFixture = leftWallBody.CreateFixture(leftWallFixtureDef)
leftWallFixture.userData = { "name": "leftWall" }
# Create a right wall body
rightWallBodyDef = b2BodyDef()
rightWallBodyDef.position = b2Vec2(280 / ppm, 285 / ppm)
rightWallBodyDef.angle = math.radians(90)
rightWallBody = world.CreateBody(rightWallBodyDef)
rightWallShape = b2PolygonShape()
rightWallShape.SetAsBox(200 / 2 / ppm, 20 / 2 / ppm)
rightWallFixtureDef = b2FixtureDef()
rightWallFixtureDef.shape = rightWallShape
rightWallFixtureDef.density = 0
rightWallFixtureDef.friction = friction
rightWallFixture = rightWallBody.CreateFixture(rightWallFixtureDef)
rightWallFixture.userData = { "name": "rightWall" }
# Create a player body
playerBodyDef = b2BodyDef()
playerBodyDef.allowSleep = False
playerBodyDef.position = b2Vec2(200 / ppm, 250 / ppm)
playerBodyDef.fixedRotation = True
playerBodyDef.type = b2_dynamicBody
playerBody = world.CreateBody(playerBodyDef)
playerShape = b2CircleShape()
playerShape.radius = 20 / ppm
playerFixtureDef = b2FixtureDef()
playerFixtureDef.shape = playerShape
playerFixtureDef.density = 1
playerFixtureDef.friction = friction
playerFixture = playerBody.CreateFixture(playerFixtureDef)
playerFixture.userData = { "name": "player" }
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppEvent_func
def SDL_AppEvent(appstate, event):
if sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_QUIT:
return sdl3.SDL_APP_SUCCESS
elif sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_KEY_DOWN:
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_W or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_UP
):
keys["up"] = True
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_S or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_DOWN
):
keys["down"] = True
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_A or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_LEFT
):
keys["left"] = True
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_D or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_RIGHT
):
keys["right"] = True
elif sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_KEY_UP:
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_W or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_UP
):
keys["up"] = False
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_S or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_DOWN
):
keys["down"] = False
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_A or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_LEFT
):
keys["left"] = False
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_D or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_RIGHT
):
keys["right"] = False
return sdl3.SDL_APP_CONTINUE
def keyboard():
if keys["up"]:
playerBody.linearVelocity.x = 0
playerBody.linearVelocity.y = -playerSpeed
if keys["down"]:
playerBody.linearVelocity.x = 0
playerBody.linearVelocity.y = playerSpeed
if keys["left"]:
playerBody.linearVelocity.x = -playerSpeed
playerBody.linearVelocity.y = 0
if keys["right"]:
playerBody.linearVelocity.x = playerSpeed
playerBody.linearVelocity.y = 0
if (
not keys["up"] and not keys["down"] and
not keys["left"] and not keys["right"]
):
playerBody.linearVelocity = b2Vec2(0, 0)
def showText(text, x, y, textColor):
# text = "Click counter = %d".encode() % counter
# text = "Begin contact".encode()
pass
@sdl3.SDL_AppIterate_func
def SDL_AppIterate(appstate):
sdl3.SDL_SetRenderDrawColor(renderer, 55, 55, 55, sdl3.SDL_ALPHA_OPAQUE)
sdl3.SDL_RenderClear(renderer)
keyboard()
world.Step(0.016, 3, 2)
world.DrawDebugData()
text = contactListener.text.encode()
textColor = sdl3.SDL_Color(255, 255, 255)
surface = sdl3.TTF_RenderText_Blended(font, text, len(text), textColor)
textTexture = sdl3.SDL_CreateTextureFromSurface(renderer, surface)
sdl3.SDL_DestroySurface(surface)
width, height = ctypes.c_float(), ctypes.c_float()
sdl3.SDL_GetTextureSize(textTexture, ctypes.byref(width), ctypes.byref(height))
rect = sdl3.SDL_FRect(50.0, 50.0, width.value, height.value)
sdl3.SDL_RenderTexture(renderer, textTexture, None, rect)
sdl3.SDL_RenderPresent(renderer)
sdl3.SDL_DestroyTexture(textTexture)
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppQuit_func
def SDL_AppQuit(appstate, result):
... # SDL will clean up the window/renderer for us contact_listener.py from Box2D import b2ContactListener
class ContactListener(b2ContactListener):
def __init__(self, font):
super().__init__()
self.text = "Make a contact with a wall"
def BeginContact(self, contact):
userDataA = contact.fixtureA.userData
userDataB = contact.fixtureB.userData
# print("Begin contact:", userDataA["name"], "<--->", userDataB["name"])
wallName = None
if userDataA["name"] == "player":
wallName = userDataB["name"]
else:
wallName = userDataA["name"]
self.text = "Begin contact with %s" % wallName
def EndContact(self, contact):
userDataA = contact.fixtureA.userData
userDataB = contact.fixtureB.userData
# print("End contact:", userDataA["name"], "<--->", userDataB["name"])
wallName = None
if userDataA["name"] == "player":
wallName = userDataB["name"]
else:
wallName = userDataA["name"]
self.text = "End contact with %s" % wallName debug_drawer.py import math
import sdl3
from Box2D import b2Draw
class DebugDrawer(b2Draw):
def __init__(self, renderer, pixelsPerMeter, thickness=3):
super().__init__()
self.renderer = renderer
self.ppm = pixelsPerMeter
self.thickness = thickness
def DrawSolidPolygon(self, vertices, color):
r = int(color.r * 255)
g = int(color.g * 255)
b = int(color.b * 255)
sdl3.SDL_SetRenderDrawColor(self.renderer, r, g, b, sdl3.SDL_ALPHA_OPAQUE)
x0 = vertices[0][0] * self.ppm
y0 = vertices[0][1] * self.ppm
x1 = vertices[1][0] * self.ppm
y1 = vertices[1][1] * self.ppm
sdl3.SDL_RenderLine(self.renderer, x0, y0, x1, y1)
x1 = vertices[1][0] * self.ppm
y1 = vertices[1][1] * self.ppm
x2 = vertices[2][0] * self.ppm
y2 = vertices[2][1] * self.ppm
sdl3.SDL_RenderLine(self.renderer, x1, y1, x2, y2)
x2 = vertices[2][0] * self.ppm
y2 = vertices[2][1] * self.ppm
x3 = vertices[3][0] * self.ppm
y3 = vertices[3][1] * self.ppm
sdl3.SDL_RenderLine(self.renderer, x2, y2, x3, y3)
x3 = vertices[3][0] * self.ppm
y3 = vertices[3][1] * self.ppm
x0 = vertices[0][0] * self.ppm
y0 = vertices[0][1] * self.ppm
sdl3.SDL_RenderLine(self.renderer, x3, y3, x0, y0)
def DrawSolidCircle(self, center, radius, axis, color):
numberOfSegments = 100
angle = 0
angleStep = 360 / numberOfSegments
r = int(color.r * 255)
g = int(color.g * 255)
b = int(color.b * 255)
sdl3.SDL_SetRenderDrawColor(self.renderer, r, g, b, sdl3.SDL_ALPHA_OPAQUE)
centerX = center[0] * self.ppm
centerY = center[1] * self.ppm
radius *= self.ppm
x = radius * math.cos(math.radians(angle))
y = radius * math.sin(math.radians(angle))
fromX = centerX + x
fromY = centerY + y
for i in range(numberOfSegments + 1):
x = radius * math.cos(math.radians(angle))
y = radius * math.sin(math.radians(angle))
toX = centerX + x
toY = centerY + y
sdl3.SDL_RenderLine(self.renderer, fromX, fromY, toX, toY)
angle += angleStep
fromX = toX
fromY = toY
def DrawPolygon(self, vertices, color):
pass
def DrawSegment(self, p1, p2, color):
pass
def DrawPoint(self, p, size, color):
pass
def DrawCircle(self, center, radius, color, drawwidth=1):
pass
def DrawTransform(self, xf):
pass
|
Beta Was this translation helpful? Give feedback.
-
FamTrinli's Snake in PySDL3 It is a port from the FamTrinli's video tutorial to PySDL3. Play in the browser: https://famtrinli-snake-in-sdl3-cpp.netlify.app/ Download sources: famtrinli's-snake-in-pysdl3.zip Click this to collapse/foldmain.py import ctypes
import os
import random
os.environ["SDL_MAIN_USE_CALLBACKS"] = "1"
os.environ["SDL_RENDER_DRIVER"] = "opengl"
import sdl3
renderer = ctypes.POINTER(sdl3.SDL_Renderer)()
window = ctypes.POINTER(sdl3.SDL_Window)()
greenSpriteTexture = None
redSpriteTexture = None
whiteSpriteTexture = None
N = 30
M = 20
size = 16
w = size * N
h = size * M
keys = { "left": False, "right": False, "up": False, "down": False }
delay = 0.1
timer = 0
lastTime = 0
snakeLength = 4
snakeMaxLength = 100
snakeDir = 0
# Snake list
s = [{ "x": 0, "y": 0 } for _ in range(snakeMaxLength)]
# Fruit list
fruit = { "x": 7, "y": 5 }
@sdl3.SDL_AppInit_func
def SDL_AppInit(appstate, argc, argv):
global greenSpriteTexture
global redSpriteTexture
global whiteSpriteTexture
if not sdl3.SDL_Init(sdl3.SDL_INIT_VIDEO):
sdl3.SDL_Log("Couldn't initialize SDL: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
title = "FamTrinli's Snake in PySDL3".encode()
if not sdl3.SDL_CreateWindowAndRenderer(title, w, h, 0, window, renderer):
sdl3.SDL_Log("Couldn't create window/renderer: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
sdl3.SDL_SetRenderVSync(renderer, 1) # Turn on vertical sync
# Green texture
texturePath = "./assets/images/green.png".encode()
greenSpriteTexture = sdl3.IMG_LoadTexture(renderer, texturePath)
if not greenSpriteTexture:
sdl3.SDL_Log("Error: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
sdl3.SDL_SetTextureScaleMode(greenSpriteTexture, sdl3.SDL_SCALEMODE_NEAREST)
# Red texture
texturePath = "./assets/images/red.png".encode()
redSpriteTexture = sdl3.IMG_LoadTexture(renderer, texturePath)
if not redSpriteTexture:
sdl3.SDL_Log("Error: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
sdl3.SDL_SetTextureScaleMode(redSpriteTexture, sdl3.SDL_SCALEMODE_NEAREST)
# White texture
texturePath = "./assets/images/white.png".encode()
whiteSpriteTexture = sdl3.IMG_LoadTexture(renderer, texturePath)
if not whiteSpriteTexture:
sdl3.SDL_Log("Error: %s".encode() % sdl3.SDL_GetError())
return sdl3.SDL_APP_FAILURE
sdl3.SDL_SetTextureScaleMode(whiteSpriteTexture, sdl3.SDL_SCALEMODE_NEAREST)
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppEvent_func
def SDL_AppEvent(appstate, event):
if sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_QUIT:
return sdl3.SDL_APP_SUCCESS
elif sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_KEY_DOWN:
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_W or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_UP
):
keys["up"] = True
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_S or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_DOWN
):
keys["down"] = True
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_A or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_LEFT
):
keys["left"] = True
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_D or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_RIGHT
):
keys["right"] = True
elif sdl3.SDL_DEREFERENCE(event).type == sdl3.SDL_EVENT_KEY_UP:
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_W or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_UP
):
keys["up"] = False
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_S or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_DOWN
):
keys["down"] = False
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_A or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_LEFT
):
keys["left"] = False
if (
sdl3.SDL_DEREFERENCE(event).key.scancode == sdl3.SDL_SCANCODE_D or
sdl3.SDL_DEREFERENCE(event).button.button == sdl3.SDL_SCANCODE_RIGHT
):
keys["right"] = False
return sdl3.SDL_APP_CONTINUE
def keyboard():
global snakeDir
if snakeDir != 2 and keys["left"]:
snakeDir = 1
if snakeDir != 1 and keys["right"]:
snakeDir = 2
if snakeDir != 0 and keys["up"]:
snakeDir = 3
if snakeDir != 3 and keys["down"]:
snakeDir = 0
def tick():
global snakeLength
for i in range(snakeLength, 0, -1):
s[i]["x"] = s[i - 1]["x"]
s[i]["y"] = s[i - 1]["y"]
if snakeDir == 0:
s[0]["y"] += 1 # down
if snakeDir == 1:
s[0]["x"] -= 1 # left
if snakeDir == 2:
s[0]["x"] += 1 # right
if snakeDir == 3:
s[0]["y"] -= 1 # up
if s[0]["x"] >= N:
s[0]["x"] = 0
if s[0]["x"] < 0:
s[0]["x"] = N - 1
if s[0]["y"] >= M:
s[0]["y"] = 0
if s[0]["y"] < 0:
s[0]["y"] = M - 1
if s[0]["x"] == fruit["x"] and s[0]["y"] == fruit["y"]:
snakeLength += 1
if snakeLength != snakeMaxLength:
fruit["x"] = random.randint(0, N - 1)
fruit["y"] = random.randint(0, M - 1)
else:
print("You won the game!")
fruit["x"] = -1
fruit["y"] = -1
snakeLength -= 1
for i in range(1, snakeLength):
if s[0]["x"] == s[i]["x"] and s[0]["y"] == s[i]["y"]:
snakeLength = i
@sdl3.SDL_AppIterate_func
def SDL_AppIterate(appstate):
global lastTime
global timer
global snakeLength
# Calc delta time
currentTime = sdl3.SDL_GetTicks()
deltaTime = (currentTime - lastTime) / 1000
lastTime = currentTime
timer += deltaTime
if timer > delay:
timer = 0
tick()
keyboard()
# Clear the canvas with a specific color
sdl3.SDL_SetRenderDrawColor(renderer, 168, 185, 168, sdl3.SDL_ALPHA_OPAQUE)
sdl3.SDL_RenderClear(renderer) # Start with a blank canvas
# Draw a background
for i in range(N):
for j in range(M):
srcRect = sdl3.SDL_FRect(0, 0, size, size)
destRect = sdl3.SDL_FRect(i * size, j * size, size, size)
sdl3.SDL_RenderTexture(renderer, whiteSpriteTexture, srcRect, destRect)
# Draw a snake
for i in range(snakeLength):
srcRect = sdl3.SDL_FRect(0, 0, size, size)
destRect = sdl3.SDL_FRect(s[i]["x"] * size, s[i]["y"] * size, size, size)
sdl3.SDL_RenderTexture(renderer, greenSpriteTexture, srcRect, destRect)
# Draw a fruit
srcRect = sdl3.SDL_FRect(0, 0, size, size)
destRect = sdl3.SDL_FRect(fruit["x"] * size, fruit["y"] * size, size, size)
sdl3.SDL_RenderTexture(renderer, redSpriteTexture, srcRect, destRect)
sdl3.SDL_RenderPresent(renderer)
return sdl3.SDL_APP_CONTINUE
@sdl3.SDL_AppQuit_func
def SDL_AppQuit(appstate, result):
global greenSpriteTexture
global redSpriteTexture
global whiteSpriteTexture
sdl3.SDL_DestroyTexture(greenSpriteTexture)
sdl3.SDL_DestroyTexture(redSpriteTexture)
sdl3.SDL_DestroyTexture(whiteSpriteTexture)
# SDL will clean up the window/renderer for us
|
Beta Was this translation helpful? Give feedback.
-
Great work! |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Hello. There are some simple examples (without ChatGPT). There are more examples in the Need examples topic.
These examples use the PySDL3 0.9.8b1 and Box2D 2.3.10. You can install the specific versions of these packages like this:
Table of contents:
Beta Was this translation helpful? Give feedback.
All reactions