# 17. Фон игрового поля и меню
Table of Contents
17. Фон игрового поля и меню
Цель
Уйти от плоского одноцветного меню и сделать фон партии и главного экрана единым космическим стилем: глубина за счёт градиента, живость за счёт мерцания звёзд и мягкой «туманности», не перегружая мобильный GPU.
Описание выполненной работы
Структура нового starfield_bg.gdshader
Шейдер типа canvas_item работает в пространстве UV всего экрана (0…1 по обеим осям). Вместо одного параметра sky_dark введены:
sky_bottomиsky_top— цвета нижней и верхней части экрана; смешивание идёт поpow(uv.y, …), чтобы низ был чуть темнее и «тяжелее», верх — слегка прохладнее (типичный night sky для портретной ориентации).
Дальше добавлены процедурные слои:
-
Туманность — значения
vnoiseна двух-трёх масштабахUV, смещаемых медленно черезTIME(скорости порядка0.01…0.02по разным осям). Это даёт мягкое движение без резких артефактов. Две палитрыnebula_aиnebula_bсмешиваются по второму шумовому каналу и суммируются с градиентом с ограничениемclampдля контроля насыщенности. -
Звёзды первого слоя — прежняя логика
hashпо ячейкам сеткиfloor(uv * vec2(420, 740)), но результат смешивается с общей «дышащей» синусоидальной модуляцией по времени. -
Звёды второго слоя — более мелкая сетка (
900 × 1580), более высокий порогsmoothstepдляhash, чтобы получить много мелких точек без пересвета. -
Гало по центру — множитель
haloот расстояния до точки(0.5, 0.42)слегка прижимает яркость звёзд к краям экрана — зона HUD и центрального заголовка менее зашумлена светящимися точками. -
Виньетка — финальный множитель по
length(uv - 0.5)затемняет углы и помогает сфокусировать внимание на доске или блоке кнопок.
Функции hash и vnoise продублированы в этом файле намеренно, чтобы не тянуть preload других скриптов — canvas_item шейдеры компилируются автономно.
Совместное использование на поле и в меню
И game_board.tscn, и title_screen.tscn используют ShaderMaterial с одним и тем же ресурсом шейдера. Это означает:
- любое улучшение неба автоматически проявится везде;
- при необходимости можно добавить
uniform bool menu_dimили второйShaderMaterialс другимиshader_parameterчерез инспектор, не дублируя файл шейдера.
На титульном ColorRect установлен color = Color(1,1,1,1), чтобы TEXTURE/COLOR умножение не приглушало результат шейдера. mouse_filter = ignore отключает перехват событий фоном — клики идут в VBox как раньше.
Производительность на Android
Шейдер выполняется один раз на полноэкранный ColorRect; сложность — несколько hash/**vnoise** на пиксель плюс тригонометрия для мерцания. На типичном телефоне при 720×1280 это обычно дешевле, чем большой статический текстура-тайл высокого разрешения с прокруткой.
Если профилировщик покажет узкое место:
- уберите второй слой звёзд или замените
sin(TIME …)на редко обновляемыйuniformизGDScript; - уменьшите число вызовов
vnoiseв туманности; - понизьте
precisionдирективой компилятора (редко нужно).
Контент против процедурности
В плане упомянуто «фоновое изображение» — для казуальной игры процедурный фон даёт малый размер apk и отсутствие артефактов сжатия JPEG/PNG на градиентах. Если позже понадобится художественная иллюстрация:
- Замените
ColorRectнаTextureRectсexpand_modeи поверх добавьте полупрозрачныйColorRectсо смягчённым шейдером звёзд. - Или смешайте текстуру в шейдере:
uniform sampler2D bg_artиmix(tex.rgb, procedural, factor).
Текущая реализация намеренно не добавляет новые файлы png — только код.
Проверка на устройстве
Посмотрите партию при ярком солнечном свете и в темноте: если звёзды «сыпятся» слишком ярко, уменьшите коэффициенты tw1/tw2 или усильте halo/виньетку. Если верх экрана кажется пустым — слегка поднимите sky_top к более светлому голубому.
Связь с соседними шагами плана
Шаг 16 обеспечил читаемость кнопок и панелей на сложном фоне; шаг 17 добавляет атмосферу без конфликта с HUD. Шаг 18 (splash) реализован статическим кадром в той же палитре — см. posts/18-splash-screen.md; шейдер starfield_bg по-прежнему изолирован в res://shaders/.
Экспорт, mip-mapping и будущие uniform-параметры
При добавлении uniform для тонкой настройки (например star_density или nebula_strength) помните: ShaderMaterial на title_screen и game_board — это два экземпляра. Если хотите менять параметры одним местом, повесьте скрипт на корень сцены или используйте Resource ShaderMaterial с .duplicate(false) только когда нужно различие между меню и партией.
Для GLES3/мобильных драйверов** избегайте экстремальных экспонентов в **pow(uv.y, …)** без **clamp** входа — мы уже ограничиваем **uv.y** через **clamp(uv.y, 0.0, 1.0)** в смешении градиента. Если когда‑нибудь понадобится **HDR** bloom поверх неба, проще добавить отдельный **CanvasLayer** с **ColorRect** и **additive`** материалом, не меняя базовый шейдер звёзд.
UX и доступность на ярком солнце
Яркие звёзды на OLED могут утомлять; uniform-параметры sky_bottom и sky_top можно связать с опцией «контраст фона» в GameSettings в будущем: параметры шейдера доступны из material.set_shader_parameter. На первом этапе достаточно консервативных коэффициентов tw1/tw2 и усиленной виньетки — они уже делают центр экрана спокойнее для текста заголовка и счёта.
Контрольный список после правок шейдера
Просмотрите на эмуляторе и реальном устройстве: нет ли цветового бэнда на градиенте (если есть — добавьте шум dither либо повысите битность буфера через настройки рендера проекта); нет ли «шахматных» узоров при медленном движении туманности (увеличьте период TIME или сгладите vnoise дополнительным smoothstep); сохранилась ли стабильность FPS при паузе приложения (NOTIFICATION_APPLICATION_PAUSED не останавливает шейдерное время автоматически — это нормально для фона, но можно заморозить TIME через shader_parameter из GameAudio или корня дерева при желании экономить батарею).
Ссылка на проект: Third Planet
Ссылка на игру: Google Play Rustore