Created
November 18, 2022 04:01
-
-
Save kdougan/d80266833318fb3d6a7f610f87f598fe to your computer and use it in GitHub Desktop.
pygame._sdl2 + pymunk
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
from __future__ import annotations | |
import random | |
from dataclasses import dataclass | |
import pygame | |
import pymunk | |
from pygame import Vector2 as vec2 | |
from pygame import _sdl2 as sdl2 | |
from pygame._sdl2.video import Texture | |
@dataclass | |
class Entity: | |
pos: vec2 | |
size: vec2 | |
texture: Texture | |
@dataclass | |
class Camera: | |
pos: vec2 | |
scale: float | |
class Game: | |
def __init__(self): | |
self.win_size = vec2(1440, 900) | |
self.screen = pygame.display.set_mode(self.win_size) | |
self.clock = pygame.time.Clock() | |
self.running = False | |
self.sdl_window = sdl2.Window.from_display_module() | |
self.renderer = sdl2.Renderer.from_window(self.sdl_window) | |
self.space = pymunk.Space() | |
self.space.gravity = (0.0, 0.0) | |
self.space.iterations = 4 | |
self.camera = Camera(vec2(), 1.0) | |
self.entities = [] | |
self.mpos = vec2() | |
self.prev_mpos = vec2() | |
@property | |
def screen_size(self): | |
return self.win_size / self.camera.scale | |
def run(self): | |
self.running = True | |
while self.running: | |
self.events() | |
self.update() | |
self.draw() | |
def events(self): | |
for event in pygame.event.get(): | |
if (event.type == pygame.QUIT or | |
(event.type == pygame.KEYDOWN and | |
event.key == pygame.K_ESCAPE)): | |
self.running = False | |
elif event.type == pygame.KEYDOWN: | |
if event.key == pygame.K_SPACE: | |
pass | |
elif event.type == pygame.MOUSEWHEEL: | |
# zoom in/out | |
self.camera.scale += event.y * 0.1 | |
self.camera.scale = max(0.1, self.camera.scale) | |
# offset zoom to mouse position | |
self.camera.pos -= (self.mpos - self.camera.pos) * \ | |
(self.camera.scale - 1) | |
self.prev_mpos = self.mpos | |
self.mpos = vec2(pygame.mouse.get_pos()) | |
# if left mouse is pressed | |
if pygame.mouse.get_pressed()[0]: | |
for _ in range(10): | |
size = vec2((random.randint(12, 32) // 4) * 4) | |
surf = pygame.Surface(size, pygame.SRCALPHA) | |
pygame.draw.rect(surf, pygame.Color( | |
0, 200, 0, 255), pygame.Rect((0, 0), size), 1) | |
ent = Entity( | |
(self.mpos + self.camera.pos), | |
size, | |
sdl2.Texture.from_surface(self.renderer, surf) | |
) | |
self.entities.append(ent) | |
body = pymunk.Body() | |
body.position = tuple( | |
self.mpos + self.camera.pos) | |
shape = pymunk.Poly( | |
body=body, | |
vertices=[ | |
(0, 0), | |
(size.x, 0), | |
(size.x, size.y), | |
(0, size.y) | |
], | |
radius=0.1) | |
shape.mass = 1.0 | |
self.space.add(body, shape) | |
if pygame.mouse.get_pressed()[2]: | |
# pan the camera | |
self.camera.pos += (self.prev_mpos - self.mpos) | |
def update(self): | |
dt = self.clock.tick(60) * 0.001 | |
fps = self.clock.get_fps() | |
self.sdl_window.title = f'fps: {fps:.2f} entities: {len(self.entities)}' | |
# update the space | |
self.space.step(dt) | |
# update the entities | |
for i, entity in enumerate(self.entities): | |
entity.pos = vec2(self.space.bodies[i].position) | |
def draw(self): | |
self.renderer.draw_color = pygame.Color(30, 20, 30, 255) | |
self.renderer.clear() | |
self.renderer.scale = vec2(self.camera.scale) | |
# draw the entities | |
for entity in self.entities: | |
self.renderer.blit( | |
entity.texture, | |
pygame.Rect(entity.pos - self.camera.pos, entity.size) | |
) | |
self.renderer.present() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment