В честь 9 мая мы решили устроить мини-ивент: на карте появился один уникальный участок, на котором спрятана «звезда Победы». Кто первым найдёт и встанет на неё — получает приз.
Сделали это без новых моделей, миграций или «ивентового движка». Просто добавили одну строку в базу и использовали то, что уже работало — систему собственности тайлов и отрисовку кастомных текстур.
Карта игровой локации для игроков с подсказками. Игроки всегда видят только небольшой кусочек, поэтому потребуется логически догадаться, где именно ты находишься и куда держать курс, чтобы найти звезду. Плюс запасы энергии ограничены. Нужно будет отдыхать)
🧱 Что у нас уже было
Каждый участок карты может принадлежать игроку. Собственность хранится в таблице properties, с координатами x, y, ID владельца и (опционально) кастомным изображением.
Вот как мы это обрабатываем в Python (условный пример с использованием SQLAlchemy + Pillow):
tile = db.query(Property).filter_by(x=x, y=y).first() if tile: if tile.user_id == current_user.id: draw_border(img, dx, dy, color='green') else: draw_border(img, dx, dy, color='red') if tile.picture: texture_path = f"./pictures/adv/{tile.picture}" overlay_texture(img, dx, dy, texture_path)
🔹 draw_border() — функция, которая рисует обводку на изображении.
🔹 overlay_texture() — поверх накладывает PNG-текстуру на указанный тайл.
⭐ Что мы добавили для конкурса
1. Загрузили изображение
Файл star.png размером 64×64 положили туда же, где лежат остальные кастомные текстуры.
2. Добавили участок в базу
Просто внесли вручную запись в таблицу properties, где user_id равен 0 (свободный тайл), и picture = 'star.png'.
INSERT INTO properties (x, y, user_id, picture) VALUES (234, -112, 0, 'star.png');
3. Никакой дополнительной логики отрисовки не потребовалось — всё уже умело показывать кастомную текстуру на карте, если такая есть.
🏆 Как определяется победитель
На каждом шаге игрока мы проверяем: не оказался ли он на «звёздном» тайле? Если да — проверяем, не занят ли приз. Если свободен — фиксируем победу:
STAR_COORDS = (234, -112) if (player.x, player.y) == STAR_COORDS: tile = db.query(Property).filter_by(x=234, y=-112).first() if tile and tile.user_id == 0: tile.user_id = player.id db.commit() notify_winner(player)
🟢 Всё. Победитель найден, деньги уходят, лог сохраняется, сообщение в канал готовится.
⚙️ Почему это было просто
У нас уже были гибкие свойства у тайлов, включая кастомные текстуры.
Уже существовала система проверки координат и принадлежности.
Мы сделали только одну вставку в базу, и один блок условий в обработчике движения.
Сам конкурс получился таким: https://t.me/terry_game_official
💡 Вывод
Это отличный пример, когда достаточно гибкая внутренняя архитектура позволяет внедрять геймплейные фишки буквально за пару минут — без костылей и трудоемкости.
Один PNG, одна строка в базе, один if. Ивент — готов.
P.s. игроки до сих пор ищут клад :) Энергия не позволяет разом пройти большое расстояние на карте, требуются остановки для подзарядки ровера.