diff --git a/geom.py b/geom.py index 11d5213..1664d35 100755 --- a/geom.py +++ b/geom.py @@ -11,10 +11,6 @@ def main(): elapsed = 0 while geom.loop(): clock.tick(60) - #elapsed += clock.get_time() - #if elapsed >= 1000: - # print(f"FPS: {clock.get_fps()}") - # elapsed = 0 pygame.quit() sys.exit() diff --git a/geom/__init__.py b/geom/__init__.py index bd3a4d9..1237be0 100644 --- a/geom/__init__.py +++ b/geom/__init__.py @@ -1,6 +1,5 @@ import pygame -from pygame.locals import * -from . import text +from .math import sub WIDTH = 1280 HEIGHT = 720 @@ -12,18 +11,21 @@ screen = None def init(): pygame.display.set_caption("Geom Demo") pygame.mouse.set_visible(False) + pygame.key.set_repeat(500, 60) global surface global screen surface = pygame.display.set_mode((WIDTH, HEIGHT)) - text.init() + + from . import draw + draw.init() from .screen import Screen screen = Screen() def loop(): - for event in pygame.event.get(QUIT): + for event in pygame.event.get(pygame.QUIT): return False surface.fill((0, 0, 0)) @@ -32,3 +34,6 @@ def loop(): pygame.display.update() return True + +def get_cursor_pos(): + return sub(*pygame.mouse.get_pos(), WIDTH / 2, HEIGHT / 2) diff --git a/geom/demos/aabb.py b/geom/demos/aabb.py index 223d547..a836637 100644 --- a/geom/demos/aabb.py +++ b/geom/demos/aabb.py @@ -1,9 +1,9 @@ -from pygame import draw, mouse -from .. import text -from ..geom.rect import Rect -from .. import WIDTH, HEIGHT, text +from pygame import draw +from ..geom import Rect +from .. import WIDTH, HEIGHT, get_cursor_pos from ..colors import * from ..math import * +from ..draw import * class AABBDistance: @@ -11,13 +11,13 @@ class AABBDistance: def render(self, surface): rect_a = Rect( - WIDTH / 2 - (WIDTH / 8), - HEIGHT / 2 - (HEIGHT / 8), + -(WIDTH / 8), + -(HEIGHT / 8), WIDTH / 4, HEIGHT / 4, ) rect_b = Rect( - *mouse.get_pos(), + *get_cursor_pos(), WIDTH / 5, HEIGHT / 5 ) @@ -41,10 +41,10 @@ class AABBDistance: else: distance = length(gap_x, gap_y) - text.draw(surface, (10, HEIGHT - 20), WHITE, f"Distance: {distance}") + text_screen(surface, WHITE, (10, HEIGHT - 20), f"Distance: {distance}") rect_a.draw(surface, YELLOW, 4) rect_b.draw(surface, WHITE, 4) - draw.line(surface, RED if distance < 0 else GREEN, + line(surface, RED if distance < 0 else GREEN, rect_a.get_center(), rect_b.get_center(), 2) class PointAABBDistance: @@ -53,12 +53,12 @@ class PointAABBDistance: def render(self, surface): rect_a = Rect( - WIDTH / 2 - (WIDTH / 8), - HEIGHT / 2 - (HEIGHT / 8), + -(WIDTH / 8), + -(HEIGHT / 8), WIDTH / 4, HEIGHT / 4, ) - cx, cy = mouse.get_pos() + cx, cy = get_cursor_pos() # cx, cy = point dist_x = abs(cx - rect_a.cx) @@ -79,7 +79,7 @@ class PointAABBDistance: else: distance = length(gap_x, gap_y) - text.draw(surface, (10, HEIGHT - 20), WHITE, f"Distance: {distance}") + text_screen(surface, WHITE, (10, HEIGHT - 20), f"Distance: {distance}") rect_a.draw(surface, YELLOW, 4) - draw.line(surface, RED if distance < 0 else GREEN, + line(surface, RED if distance < 0 else GREEN, rect_a.get_center(), (cx, cy), 2) diff --git a/geom/demos/vec_proj.py b/geom/demos/vec_proj.py index f4eadeb..e266092 100644 --- a/geom/demos/vec_proj.py +++ b/geom/demos/vec_proj.py @@ -1,19 +1,19 @@ -from pygame import draw, mouse -from .. import HEIGHT, WIDTH +from .. import HEIGHT, WIDTH, get_cursor_pos from ..colors import * from ..math import * +from ..draw import * class VecProj: title = "Vector Projection" def render(self, surface): - x1 = WIDTH / 4 - y1 = HEIGHT / 2 + 100 - x2 = 0.75 * WIDTH - y2 = HEIGHT / 2 + x1 = -(WIDTH / 4) + y1 = 100 + x2 = WIDTH / 4 + y2 = 0 - cx, cy = mouse.get_pos() + cx, cy = get_cursor_pos() lx, ly = x2 - x1, y2 - y1 # line vector llen = length(lx, ly) @@ -21,9 +21,9 @@ class VecProj: lcx, lcy = cx - x1, cy - y1 # line start - cursor vector proj = dot(lcx, lcy, lx, ly) / llen + nearest_point = add(x1, y1, *scale(lnx, lny, proj)) - draw.line( - surface, GREEN, (cx, cy), add(x1, y1, *scale(lnx, lny, proj)), 5 - ) - draw.line(surface, WHITE, (cx, cy), (x1, y1), 5) - draw.line(surface, YELLOW, (x1, y1), (x2, y2), 5) + line(surface, GREEN, (cx, cy), nearest_point, 5) + line(surface, WHITE, (cx, cy), (x1, y1), 5) + line(surface, YELLOW, (x1, y1), (x2, y2), 5) + line(surface, RED, (x1, y1), nearest_point, 5) diff --git a/geom/draw.py b/geom/draw.py new file mode 100644 index 0000000..dd0de70 --- /dev/null +++ b/geom/draw.py @@ -0,0 +1,41 @@ +import pygame +from pygame import gfxdraw +from pygame import freetype +from . import HEIGHT, WIDTH +from .math import add + +OFFSET = (WIDTH/2, HEIGHT/2) +FONT = None + +def init(): + global FONT + freetype.init() + FONT = freetype.SysFont('Arial', 16) + +def line(surface, color, start, end, width=0): + pygame.draw.line(surface, color, + add(*OFFSET, *start), add(*OFFSET, *end), width) + + +def polygon(surface, color, vertices, width): + translated = [add(*OFFSET, *vertex) for vertex in vertices] + pygame.draw.polygon(surface, color, translated, width) + + +def rect(surface, color, x, y, height, width, stroke_width): + pygame.draw.rect(surface, color, + pygame.Rect(OFFSET[0] + x, OFFSET[1] + y, height, width), + stroke_width) + + +def pixel(surface, color, x, y): + gfxdraw.pixel(surface, + int(OFFSET[0] + x), + int(OFFSET[1] + y), + color) + +def text(surface, color, position, text): + FONT.render_to(surface, add(*OFFSET, *position), text, color) + +def text_screen(surface, color, position, text): + FONT.render_to(surface, position, text, color) diff --git a/geom/geom/rect.py b/geom/geom.py similarity index 50% rename from geom/geom/rect.py rename to geom/geom.py index a392f6f..4ecea74 100644 --- a/geom/geom/rect.py +++ b/geom/geom.py @@ -1,5 +1,5 @@ -from pygame import draw, gfxdraw -from pygame.rect import Rect as pRect +from .math import * +from .draw import * class Rect: @@ -49,7 +49,50 @@ class Rect: and y >= self.min_y and y <= self.max_y) def draw(self, surface, colour, width): - #gfxdraw.pixel(surface, *self.get_center_px(), colour) - draw.rect(surface, colour, - pRect(self.x, self.y, self.width, self.height), - width) + pixel(surface, colour, *self.get_center()) + rect(surface, colour, self.x, self.y, self.width, self.height, width) + +class Polygon: + + def __init__(self, x, y, vertices, origin_x=0, origin_y=0): + self.x = x + self.y = y + self.vertices = vertices + self.origin_x = origin_x + self.origin_y = origin_y + self.update() + + def update(self): + self.translated_vertices = [ + (self.x + self.origin_x + x, + self.y + self.origin_y + y) + for x, y in self.vertices + ] + + def set_position(self, x, y): + self.x = x + self.y = y + self.update() + + def get_normals(self): + return [ + normalize(*lnormal(*sub(*v2, *v1))) + for v1, v2 in self.get_segments() + ] + + def get_translated_vertices(self): + return self.translated_vertices + + def get_segments(self): + cnt = len(self.vertices) + return [ + ( + self.translated_vertices[i], + self.translated_vertices[i + 1 if i + 1 < cnt else 0], + ) + for i in range(cnt) + ] + + def draw(self, surface, colour, width): + polygon(surface, colour, self.translated_vertices, width) + pixel(surface, colour, self.x, self.y) diff --git a/geom/screen.py b/geom/screen.py index d56c299..4b2a1bd 100644 --- a/geom/screen.py +++ b/geom/screen.py @@ -1,7 +1,8 @@ import pygame from .demos import aabb, vec_proj -from . import text, HEIGHT +from . import HEIGHT from .colors import * +from .draw import text_screen class Screen: @@ -27,9 +28,9 @@ class Screen: def draw_demo_list(self, surface): y_offset = 10 for i in range(len(self.demos)): - text.draw(surface, - (10, y_offset + i * 20), + text_screen(surface, CYAN if self.demo == i else WHITE, + (10, y_offset + i * 20), self.demos[i].title) def render(self, surface): diff --git a/geom/text.py b/geom/text.py deleted file mode 100644 index 735bb35..0000000 --- a/geom/text.py +++ /dev/null @@ -1,10 +0,0 @@ -from pygame import freetype - -FONT = None - -def init(): - global FONT - FONT = freetype.SysFont('Arial', 16) - -def draw(surface, position, color, text): - FONT.render_to(surface, position, text, color)