Подробные изменения: - Добавлены сцены Bootstrap, MainMenu и Game с текущей вертикальной 9:16 структурой проекта. - Добавлены runtime-скрипты gameplay-архитектуры: DI через Extenject, спавнер платформ, прогрессия этапов, one-way платформы, игрок, камера и оборудование JumpPad. - Добавлены ScriptableObject-этапы сложности, weighted-настройки платформ, оборудования, противников и collectibles. - Добавлены UI Toolkit ресурсы главного меню, preview-материалы, шрифты, спрайты, анимации и игровые prefab-ассеты. - Перенесена и оформлена новая COM-система для работы с аппаратными портами и StreamingAssets. - Обновлены проектные гайды, AGENTS.md, правила Git/Git LFS, .gitignore, Unity Packages и ProjectSettings. - Удалён локальный skill start-required-mcp-servers из репозитория.
146 lines
4.5 KiB
C#
146 lines
4.5 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using Zenject;
|
|
|
|
namespace DanroJump.Gameplay
|
|
{
|
|
public sealed class GameplayDifficultyProgression : MonoBehaviour, IGameplayDifficultyProgression
|
|
{
|
|
[SerializeField] private JumpPlayerController player;
|
|
[SerializeField] private bool progressionEnabled = true;
|
|
[SerializeField] private List<GameplayDifficultyStage> stages = new();
|
|
|
|
public bool HasStages => stages != null && stages.Exists(stage => stage != null);
|
|
public float InitialSpawnY => GetInitialSpawnY();
|
|
public float CurrentProgress => CalculateProgress(player != null ? player.HighestY : 0f);
|
|
public string CurrentStageName => GetStage(player != null ? player.HighestY : 0f)?.StageName ?? string.Empty;
|
|
|
|
[Inject]
|
|
public void Construct(JumpPlayerController injectedPlayer)
|
|
{
|
|
player = injectedPlayer;
|
|
}
|
|
|
|
public GameObject GetPlatformPrefab(float worldY, System.Random random)
|
|
{
|
|
var stage = GetStage(worldY);
|
|
return stage != null ? stage.GetPlatformPrefab(random) : null;
|
|
}
|
|
|
|
public float GetVerticalSpacing(float worldY)
|
|
{
|
|
var stage = GetStage(worldY);
|
|
if (stage == null)
|
|
{
|
|
return 0f;
|
|
}
|
|
|
|
return stage.GetVerticalSpacing(worldY);
|
|
}
|
|
|
|
public float GetHorizontalDistribution(float worldY)
|
|
{
|
|
var stage = GetStage(worldY);
|
|
return stage != null ? stage.GetHorizontalDistribution() : 0f;
|
|
}
|
|
|
|
public IPlatformContentSource CreateContentSource(float worldY)
|
|
{
|
|
var stage = GetStage(worldY);
|
|
if (stage == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return stage.CreateContentSource(worldY);
|
|
}
|
|
|
|
public string GetStageName(float worldY)
|
|
{
|
|
return GetStage(worldY)?.StageName ?? string.Empty;
|
|
}
|
|
|
|
public float GetStageProgress(float worldY)
|
|
{
|
|
var stage = GetStage(worldY);
|
|
return stage != null ? stage.CalculateProgress(worldY) : 0f;
|
|
}
|
|
|
|
private float CalculateProgress(float worldY)
|
|
{
|
|
var stage = GetStage(worldY);
|
|
return stage != null ? stage.CalculateProgress(worldY) : 0f;
|
|
}
|
|
|
|
private float GetInitialSpawnY()
|
|
{
|
|
var firstStage = GetFirstStage();
|
|
return firstStage != null ? firstStage.StartY : 0f;
|
|
}
|
|
|
|
private GameplayDifficultyStage GetFirstStage()
|
|
{
|
|
if (stages == null || stages.Count == 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
GameplayDifficultyStage firstStage = null;
|
|
foreach (var stage in stages)
|
|
{
|
|
if (stage == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (firstStage == null || stage.StartY < firstStage.StartY)
|
|
{
|
|
firstStage = stage;
|
|
}
|
|
}
|
|
|
|
return firstStage;
|
|
}
|
|
|
|
private GameplayDifficultyStage GetStage(float worldY)
|
|
{
|
|
if (!progressionEnabled || stages == null || stages.Count == 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
GameplayDifficultyStage currentStage = null;
|
|
foreach (var stage in stages)
|
|
{
|
|
if (stage == null || worldY < stage.StartY)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (currentStage == null || stage.StartY >= currentStage.StartY)
|
|
{
|
|
currentStage = stage;
|
|
}
|
|
}
|
|
|
|
// The last reached stage intentionally keeps running forever after its length ends.
|
|
// verticalLength controls curve progress only; it does not disable the stage.
|
|
return currentStage;
|
|
}
|
|
}
|
|
|
|
public interface IGameplayDifficultyProgression
|
|
{
|
|
float CurrentProgress { get; }
|
|
string CurrentStageName { get; }
|
|
bool HasStages { get; }
|
|
float InitialSpawnY { get; }
|
|
GameObject GetPlatformPrefab(float worldY, System.Random random);
|
|
float GetVerticalSpacing(float worldY);
|
|
float GetHorizontalDistribution(float worldY);
|
|
IPlatformContentSource CreateContentSource(float worldY);
|
|
string GetStageName(float worldY);
|
|
float GetStageProgress(float worldY);
|
|
}
|
|
}
|