Initial commit: Plants turn-based battle game
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
import pygame
|
||||
|
||||
from engine.plants import RARITY_COLORS
|
||||
from engine.relics import RELIC_POOL
|
||||
from ui.relics_overview import RelicsOverview
|
||||
from ui.scaling import make_window, request_quit, to_logical
|
||||
|
||||
WIN_W, WIN_H = 1040, 720
|
||||
BG = (24, 30, 24)
|
||||
TEXT = (230, 235, 230)
|
||||
MUTED = (150, 155, 150)
|
||||
HINT = (255, 220, 120)
|
||||
CARD = (36, 44, 36)
|
||||
BORDER = (90, 120, 90)
|
||||
SKIP = (60, 60, 60)
|
||||
|
||||
|
||||
class RelicChoiceScreen:
|
||||
"""Pick one of the offered roguelike blessings (or skip)."""
|
||||
|
||||
def __init__(self, relics, stage, owned=()):
|
||||
pygame.init()
|
||||
self.window, self.scale = make_window(WIN_W, WIN_H)
|
||||
self.screen = pygame.Surface((WIN_W, WIN_H))
|
||||
pygame.display.set_caption("Plants — Blessing")
|
||||
self.clock = pygame.time.Clock()
|
||||
self.font = pygame.font.SysFont("segoeui", 36)
|
||||
self.bold = pygame.font.SysFont("segoeui", 20, bold=True)
|
||||
self.small = pygame.font.SysFont("segoeui", 16)
|
||||
self.tiny = pygame.font.SysFont("segoeui", 13)
|
||||
self.relics = relics
|
||||
self.stage = stage
|
||||
self.owned = list(owned)
|
||||
self.overview = None
|
||||
self.cards = []
|
||||
cw, ch = 250, 300
|
||||
gap = 26
|
||||
total = len(relics) * cw + (len(relics) - 1) * gap
|
||||
x0 = (WIN_W - total) // 2
|
||||
y = 190
|
||||
for i, r in enumerate(relics):
|
||||
self.cards.append((r, pygame.Rect(x0 + i * (cw + gap), y, cw, ch)))
|
||||
self.skip_rect = pygame.Rect(WIN_W // 2 - 80, WIN_H - 70, 160, 40)
|
||||
self.all_btn = pygame.Rect(24, WIN_H - 70, 160, 40)
|
||||
|
||||
def run(self):
|
||||
running = True
|
||||
result = None
|
||||
while running:
|
||||
self.clock.tick(60)
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
request_quit()
|
||||
running = False
|
||||
elif event.type == pygame.MOUSEWHEEL:
|
||||
if self.overview is not None:
|
||||
self.overview.handle_wheel(event.y)
|
||||
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
|
||||
pos = to_logical(event.pos, self.scale)
|
||||
if self.overview is not None:
|
||||
if self.overview.handle_click(pos) == "close":
|
||||
self.overview = None
|
||||
continue
|
||||
for r, rect in self.cards:
|
||||
if rect.collidepoint(pos):
|
||||
result = r
|
||||
running = False
|
||||
break
|
||||
else:
|
||||
if self.skip_rect.collidepoint(pos):
|
||||
result = None
|
||||
running = False
|
||||
elif self.all_btn.collidepoint(pos):
|
||||
self.overview = RelicsOverview(
|
||||
self.screen, self.bold, self.small, self.tiny,
|
||||
RELIC_POOL, self.owned)
|
||||
self._draw()
|
||||
pygame.transform.smoothscale(self.screen, self.window.get_size(), self.window)
|
||||
pygame.display.flip()
|
||||
return result
|
||||
|
||||
def _wrap(self, text, font, width):
|
||||
words = text.split()
|
||||
lines = []
|
||||
cur = ""
|
||||
for w in words:
|
||||
if font.size(cur + " " + w)[0] > width and cur:
|
||||
lines.append(cur)
|
||||
cur = w
|
||||
else:
|
||||
cur = (cur + " " + w).strip()
|
||||
if cur:
|
||||
lines.append(cur)
|
||||
return lines
|
||||
|
||||
def _draw(self):
|
||||
self.screen.fill(BG)
|
||||
if self.overview is not None:
|
||||
self.overview.draw(pygame.mouse.get_pos())
|
||||
return
|
||||
t = self.font.render("Choose a blessing", True, HINT)
|
||||
self.screen.blit(t, t.get_rect(center=(WIN_W // 2, 60)))
|
||||
st = self.small.render(
|
||||
f"Stage {self.stage} defeated — pick a relic for the rest of the tower.",
|
||||
True, MUTED)
|
||||
self.screen.blit(st, st.get_rect(center=(WIN_W // 2, 110)))
|
||||
mouse = pygame.mouse.get_pos()
|
||||
for r, rect in self.cards:
|
||||
hover = rect.collidepoint(mouse)
|
||||
pygame.draw.rect(self.screen, CARD, rect, border_radius=10)
|
||||
pygame.draw.rect(self.screen, HINT if hover else BORDER, rect, 2, border_radius=10)
|
||||
name = self.bold.render(r.name, True, HINT)
|
||||
self.screen.blit(name, name.get_rect(midtop=(rect.centerx, rect.y + 16)))
|
||||
rar = self.small.render(r.rarity.capitalize(), True, RARITY_COLORS.get(r.rarity, MUTED))
|
||||
self.screen.blit(rar, rar.get_rect(midtop=(rect.centerx, rect.y + 50)))
|
||||
y = rect.y + 92
|
||||
for ln in self._wrap(r.desc, self.small, rect.w - 24)[:7]:
|
||||
lr = self.small.render(ln, True, TEXT)
|
||||
self.screen.blit(lr, lr.get_rect(midtop=(rect.centerx, y)))
|
||||
y += 24
|
||||
pygame.draw.rect(self.screen, SKIP, self.skip_rect, border_radius=8)
|
||||
pygame.draw.rect(self.screen, (150, 150, 150), self.skip_rect, 2, border_radius=8)
|
||||
sk = self.small.render("Skip", True, TEXT)
|
||||
self.screen.blit(sk, sk.get_rect(center=self.skip_rect.center))
|
||||
pygame.draw.rect(self.screen, (70, 90, 70), self.all_btn, border_radius=8)
|
||||
pygame.draw.rect(self.screen, BORDER, self.all_btn, 2, border_radius=8)
|
||||
ab = self.small.render("All blessings", True, TEXT)
|
||||
self.screen.blit(ab, ab.get_rect(center=self.all_btn.center))
|
||||
hint = self.tiny.render("Blessings persist for the rest of this tower run", True, MUTED)
|
||||
self.screen.blit(hint, hint.get_rect(center=(WIN_W // 2, WIN_H - 20)))
|
||||
Reference in New Issue
Block a user