1
0
Fork 0
mirror of https://github.com/EDeev/pixel_gamble.git synced 2026-10-07 23:49:29 +03:00
pixel_gamble/game/pixelgamble/world.py
Egor Deev 4ecb9257c8 Pixel Gamble 2.0: законченная игра на ресурсах Ninja Adventure
- 10 волн, 5 видов врагов со своим поведением и босс в три фазы
- меч, копьё и посох, 11 улучшений между волнами, опыт и уровни
- меню, пауза, настройки, итоги партии и рекорд, русский и английский
- мир 480×270 с масштабированием, интерфейс в 960×540, скорости от dt
- асинхронный цикл: та же игра в браузере через pygbag
- тесты без окна, автоигрок, CI, релизы exe/Linux, GitHub Pages
- README на двух языках; исходная версия — релиз v1.0.0
2026-10-07 12:29:41 +00:00

111 lines
4.7 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Арена: пол, деревья, камни, точки появления врагов."""
import random
import pygame
from . import assets
from .settings import TILE
COLS, ROWS = 52, 34
SEED = 2022 # раскладка камней и кустов одна и та же в каждой партии
GROVES = [(9, 7), (11, 8), (40, 6), (42, 7), (8, 25), (10, 26), (41, 24), (39, 25), (25, 5), (26, 27)]
STUMPS = [(17, 12), (34, 12), (17, 22), (34, 22), (25, 16), (21, 9), (30, 25)]
class Prop(pygame.sprite.Sprite):
"""Дерево или камень: рисуется с сортировкой по глубине и мешает проходу."""
def __init__(self, image, topleft, hitbox, breakable=False):
super().__init__()
self.image = image
self.rect = image.get_rect(topleft=topleft)
self.hitbox = hitbox
self.breakable = breakable
self.sort_y = self.hitbox.bottom
class World:
def __init__(self):
self.width, self.height = COLS * TILE, ROWS * TILE
self.rect = pygame.Rect(0, 0, self.width, self.height)
self.props = pygame.sprite.Group()
edge = 2 * TILE # толщина кольца деревьев
self.walls = [pygame.Rect(0, 0, self.width, edge), pygame.Rect(0, self.height - edge, self.width, edge),
pygame.Rect(0, 0, edge, self.height), pygame.Rect(self.width - edge, 0, edge, self.height)]
self.inner = pygame.Rect(2 * TILE, 2 * TILE, self.width - 4 * TILE, self.height - 4 * TILE)
self.center = pygame.Vector2(self.width / 2, self.height / 2 + TILE)
self.floor = pygame.Surface((self.width, self.height)).convert()
self._build()
def _build(self):
rnd = random.Random(SEED)
grass = assets.tile("floor.png", 0, 12)
decor = [assets.tile("floor.png", c, r) for c, r in ((1, 12), (2, 12), (3, 12), (4, 12), (3, 11))]
bushes = [assets.tile("nature.png", c, 10) for c in range(4)]
trees = [assets.tile("nature.png", 0, 0, 2, 2), assets.tile("nature.png", 16, 0, 2, 2),
assets.tile("nature.png", 18, 0, 2, 2)]
rock = assets.tile("nature.png", 7, 12)
stump = assets.tile("nature.png", 15, 9)
for y in range(ROWS):
for x in range(COLS):
self.floor.blit(grass, (x * TILE, y * TILE))
if rnd.random() < 0.13:
self.floor.blit(rnd.choice(decor), (x * TILE, y * TILE))
taken = set()
def tree(cx, cy):
for dx in (0, 1):
for dy in (0, 1):
taken.add((cx + dx, cy + dy))
px, py = cx * TILE, cy * TILE
self.props.add(Prop(rnd.choice(trees), (px, py), pygame.Rect(px + 8, py + 20, 16, 10)))
# Кольцо деревьев по краю: стена — отдельные прямоугольники self.walls.
for x in range(0, COLS, 2):
tree(x, 0)
tree(x, ROWS - 2)
for y in range(2, ROWS - 2, 2):
tree(0, y)
tree(COLS - 2, y)
for cx, cy in GROVES:
tree(cx, cy)
def free(x, y):
near_center = abs(x - COLS / 2) < 6 and abs(y - ROWS / 2) < 5
return (x, y) not in taken and not near_center and 3 <= x < COLS - 3 and 3 <= y < ROWS - 3
for x, y in STUMPS:
taken.add((x, y))
px, py = x * TILE, y * TILE
self.props.add(Prop(stump, (px, py), pygame.Rect(px + 2, py + 5, 12, 10)))
placed = 0
while placed < 26:
x, y = rnd.randrange(3, COLS - 3), rnd.randrange(3, ROWS - 3)
if free(x, y):
taken.add((x, y))
px, py = x * TILE, y * TILE
self.props.add(Prop(rock, (px, py), pygame.Rect(px + 2, py + 4, 12, 11), breakable=True))
placed += 1
for _ in range(40):
x, y = rnd.randrange(2, COLS - 2), rnd.randrange(2, ROWS - 2)
if (x, y) not in taken:
self.floor.blit(rnd.choice(bushes), (x * TILE, y * TILE))
self.spawns = []
for x in range(4, COLS - 4, 5):
self.spawns += [pygame.Vector2(x * TILE + 8, 3 * TILE), pygame.Vector2(x * TILE + 8, (ROWS - 3) * TILE)]
for y in range(6, ROWS - 5, 5):
self.spawns += [pygame.Vector2(3 * TILE, y * TILE + 8), pygame.Vector2((COLS - 3) * TILE, y * TILE + 8)]
self.spawns = [p for p in self.spawns if not self.blocked(pygame.Rect(p.x - 8, p.y - 6, 16, 12))]
def obstacles(self):
return self.walls + [p.hitbox for p in self.props]
def blocked(self, rect):
return rect.collidelist(self.walls) != -1 or any(rect.colliderect(p.hitbox) for p in self.props)