Debug view improvements, warp animation
* Add a visible frame one tile beyond the normal screen in debug mode. * Fix the display of motion paths for mounted traps in debug mode. * Add an animation for the warp trap.
This commit is contained in:
@@ -49,6 +49,12 @@ class Level:
|
||||
self.width = self.cols * self.tile
|
||||
self.height = self.grid_rows * self.tile
|
||||
|
||||
# Draw-time translation (pixels): everything visible is shifted by this
|
||||
# when blitted. Physics stays in true level coordinates — this is purely
|
||||
# so the debug view can reveal a margin of overscan around the level (set
|
||||
# by the Game). (0, 0) in normal play, so nothing moves.
|
||||
self.render_offset = (0, 0)
|
||||
|
||||
self.solids = [] # list[pygame.Rect] — full blocking
|
||||
self.oneways = [] # list[pygame.Rect] — blocking only from above
|
||||
self.spawn = (self.tile, self.tile)
|
||||
@@ -123,9 +129,10 @@ class Level:
|
||||
|
||||
def draw(self, surface, assets):
|
||||
t = self.tile
|
||||
ox, oy = self.render_offset
|
||||
block = assets.get("block", t, t)
|
||||
for rect in self.solids:
|
||||
surface.blit(block, rect)
|
||||
surface.blit(block, rect.move(ox, oy))
|
||||
|
||||
# One-way platforms look identical to solid blocks — you only discover
|
||||
# them by falling through. `debug` fades them so a level designer can
|
||||
@@ -135,10 +142,10 @@ class Level:
|
||||
oneway_img = block.copy()
|
||||
oneway_img.fill((255, 255, 255, 110), special_flags=pygame.BLEND_RGBA_MULT)
|
||||
for rect in self.oneways:
|
||||
surface.blit(oneway_img, rect)
|
||||
surface.blit(oneway_img, rect.move(ox, oy))
|
||||
|
||||
surface.blit(assets.get("goal", self.goal_rect.w, self.goal_rect.h),
|
||||
self.goal_rect)
|
||||
self.goal_rect.move(ox, oy))
|
||||
for tr in self.traps:
|
||||
tr.render(surface, assets)
|
||||
|
||||
@@ -149,22 +156,48 @@ class Level:
|
||||
|
||||
def _draw_grid(self, surface):
|
||||
"""A faint tile grid with col/row labels, so `at: [col,row]` placement
|
||||
is eyeballable while designing."""
|
||||
is eyeballable while designing.
|
||||
|
||||
In the debug view the drawing surface is larger than the level (a margin
|
||||
of overscan; see ``render_offset``). The grid extends across the whole
|
||||
surface — labels go negative / past the map in the margin — the off-map
|
||||
region is shaded, and the true play area is outlined so it's clear what's
|
||||
actually on screen at runtime."""
|
||||
if Level._grid_font is None:
|
||||
Level._grid_font = pygame.font.SysFont("consolas,menlo,monospace", 10)
|
||||
overlay = pygame.Surface((self.width, self.height), pygame.SRCALPHA)
|
||||
t = self.tile
|
||||
ox, oy = self.render_offset
|
||||
sw, sh = surface.get_size()
|
||||
overlay = pygame.Surface((sw, sh), pygame.SRCALPHA)
|
||||
|
||||
# Shade the off-screen overscan so the real play area reads clearly.
|
||||
view = pygame.Rect(ox, oy, self.width, self.height)
|
||||
shade = (10, 12, 20, 130)
|
||||
for band in (pygame.Rect(0, 0, sw, oy), # above
|
||||
pygame.Rect(0, view.bottom, sw, sh - view.bottom), # below
|
||||
pygame.Rect(0, oy, ox, self.height), # left
|
||||
pygame.Rect(view.right, oy, sw - view.right, self.height)): # right
|
||||
if band.w > 0 and band.h > 0:
|
||||
overlay.fill(shade, band)
|
||||
|
||||
# Tile grid across the whole surface; offsets are whole tiles so lines
|
||||
# stay aligned to the level grid. mx/my = margin width in tiles.
|
||||
mx, my = ox // t, oy // t
|
||||
line = (255, 255, 255, 26)
|
||||
for c in range(self.cols + 1):
|
||||
x = c * self.tile
|
||||
pygame.draw.line(overlay, line, (x, 0), (x, self.height))
|
||||
for r in range(self.grid_rows + 1):
|
||||
y = r * self.tile
|
||||
pygame.draw.line(overlay, line, (0, y), (self.width, y))
|
||||
for k in range(sw // t + 1):
|
||||
pygame.draw.line(overlay, line, (k * t, 0), (k * t, sh))
|
||||
for k in range(sh // t + 1):
|
||||
pygame.draw.line(overlay, line, (0, k * t), (sw, k * t))
|
||||
label = (150, 162, 190)
|
||||
for c in range(self.cols):
|
||||
overlay.blit(Level._grid_font.render(str(c), True, label),
|
||||
(c * self.tile + 2, 1))
|
||||
for r in range(self.grid_rows):
|
||||
overlay.blit(Level._grid_font.render(str(r), True, label),
|
||||
(1, r * self.tile + 1))
|
||||
for k in range(sw // t):
|
||||
overlay.blit(Level._grid_font.render(str(k - mx), True, label),
|
||||
(k * t + 2, 1))
|
||||
for k in range(sh // t):
|
||||
overlay.blit(Level._grid_font.render(str(k - my), True, label),
|
||||
(1, k * t + 1))
|
||||
|
||||
# Outline the actual runtime viewport (the level's true bounds).
|
||||
if (mx or my):
|
||||
pygame.draw.rect(overlay, (95, 210, 235, 200), view, 2)
|
||||
|
||||
surface.blit(overlay, (0, 0))
|
||||
|
||||
Reference in New Issue
Block a user