ステージ生成方法変更, 難易度切り替えとステージ生成を独立

This commit is contained in:
kimura 2022-08-01 15:55:58 +09:00
parent 8be964e884
commit 144c4a2eb0
5 changed files with 118 additions and 116 deletions

View File

@ -1886,6 +1886,7 @@ MonoBehaviour:
footerManager: {fileID: 4559813503860727170}
stageManager: {fileID: 1870432536}
bgManager: {fileID: 1471947212}
difficultyChanger: {fileID: 1870432537}
resultManager: {fileID: 5034752974072861423}
readyObject: {fileID: 978217474}
tutorialPopupObject: {fileID: 7325523898178317160}
@ -1941,6 +1942,7 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
stageTarget: {fileID: 1450368326}
elapsedTimeOffset: 3
stageGenerateDistance: 15
generateStageCount: 1
beginStageOffset: 0.5

View File

@ -29,6 +29,7 @@ namespace MyGame.Scenes.MiniGame.Scripts
[SerializeField] private FooterManager footerManager;
[SerializeField] private StageManager stageManager;
[SerializeField] private BGManager bgManager;
[SerializeField] private DifficultyChanger difficultyChanger;
[SerializeField] private ResultManager resultManager;
[SerializeField] private GameObject readyObject;
[SerializeField] private GameObject tutorialPopupObject;
@ -44,8 +45,10 @@ namespace MyGame.Scenes.MiniGame.Scripts
private readonly ReactiveProperty<MenuState> menuState = new ReactiveProperty<MenuState>();
private readonly ReactiveProperty<GameState> state = new ReactiveProperty<GameState>();
private readonly ReactiveProperty<int> scoreCount = new ReactiveProperty<int>();
private readonly CompositeDisposable gameCompositeDisposable = new CompositeDisposable();
private readonly ReactiveProperty<float> elapsedTime = new ReactiveProperty<float>();
private readonly CompositeDisposable stageCompositeDisposable = new CompositeDisposable();
private Vector3 characterBeginPos;
private IDisposable timerDisposable;
// Start is called before the first frame update
private void Start()
@ -53,7 +56,8 @@ namespace MyGame.Scenes.MiniGame.Scripts
menuState.AddTo(this);
state.AddTo(this);
scoreCount.AddTo(this);
gameCompositeDisposable.AddTo(this);
elapsedTime.AddTo(this);
stageCompositeDisposable.AddTo(this);
menuState.Value = MenuState.StageSelect;
state.Value = GameState.Ready;
@ -74,11 +78,27 @@ namespace MyGame.Scenes.MiniGame.Scripts
var placeList = SpreadsheetDataManager.Instance.GetBaseDataList<ScrollGamePlaceData>(Const.ScrollGamePlaceDataSheet);
var stageList = SpreadsheetDataManager.Instance.GetBaseDataList<ScrollGameStageData>(Const.ScrollGameStageDataSheet);
// var difficultyList = SpreadsheetDataManager.Instance.GetBaseDataList<ScrollGameStageDifficultyData>(Const.ScrollGameStageDifficultyDataSheet);
//ステージ読み込み
var placeId = 1;
var levelPlaceList = placeList.Where(data => data.placeId == placeId).ToArray();
var levelStageList = stageList.Where(data => data.placeId == placeId).ToArray();
// var levelDifficulty = difficultyList.First(data => data.placeId == placeId);
// 仮データ
for (var i = 0; i < levelStageList.Length; i++)
{
levelStageList[i].time = i * 30;
}
var levelDifficulty = new ScrollGameStageDifficultyData
{
id = 1,
placeId = 1,
normalTime = 30,
hardTime = 60,
extraTime = 90
};
// スコア保存に1つ目のstageDataIdを使用
var stageData = levelStageList[0];
@ -95,17 +115,28 @@ namespace MyGame.Scenes.MiniGame.Scripts
}).AddTo(this);
stageSelectView.OnClick.ThrottleFirst(TimeSpan.FromSeconds(.3f)).Subscribe(_ =>
{
// ステージ設定読み込み
difficultyChanger.SetData(levelDifficulty);
stageManager.SetStageList(levelStageList);
stageCompositeDisposable.Clear();
state.SkipLatestValueOnSubscribe()
.Where(x => x == GameState.Success)
.SelectMany(Observable.Timer(TimeSpan.FromSeconds(resultWaitTime)))
.Subscribe(_ =>
{
resultManager.ShowResult(scoreCount.Value, levelPlaceList, stageData);
SoundManager.Instance.ChangePitchBGM(1f);
}).AddTo(stageCompositeDisposable);
if (gameData.ScrollGameTodayPlayCount == 0)
{
ResetGameWithCount(levelPlaceList, levelStageList);
ResetGameWithCount();
return;
}
// ポップアップ ビデオ視聴表示
ScrollGameWatchVideoDialog.ShowDialog(() =>
{
ResetGameWithCount(levelPlaceList, levelStageList);
});
ScrollGameWatchVideoDialog.ShowDialog(ResetGameWithCount);
}).AddTo(this);
scoreUpdate.OnNext(Unit.Default);
@ -133,6 +164,11 @@ namespace MyGame.Scenes.MiniGame.Scripts
{
headerView.ChangeItemCount(x);
}).AddTo(this);
resultManager.OnRetry.ThrottleFirst(TimeSpan.FromSeconds(.2f)).Subscribe(_ =>
{
ScrollGameWatchVideoDialog.ShowDialog(ResetGameWithCount);
}).AddTo(this);
resultManager.OnClose.ThrottleFirst(TimeSpan.FromMilliseconds(.2f)).Subscribe(_ =>
{
@ -161,6 +197,7 @@ namespace MyGame.Scenes.MiniGame.Scripts
break;
case GameState.Play:
SoundManager.Instance.PlaySE("se_minigame_Start");
StartTimer();
break;
case GameState.Success:
SoundManager.Instance.PlaySE("se_minigame_End", () =>
@ -207,13 +244,19 @@ namespace MyGame.Scenes.MiniGame.Scripts
}
}).AddTo(this);
elapsedTime.SkipLatestValueOnSubscribe().Subscribe(x =>
{
stageManager.UpdateTime(x);
difficultyChanger.UpdateTime(x);
}).AddTo(this);
stageManager.OnFence.Subscribe(x =>
{
bgManager.SetFenceXPos(x);
}).AddTo(this);
// コース難易度変更
stageManager.Difficulty.SkipLatestValueOnSubscribe().Subscribe(x =>
difficultyChanger.Difficulty.SkipLatestValueOnSubscribe().Subscribe(x =>
{
bgManager.SetSky(x);
player.SetSpeed(x);
@ -284,6 +327,7 @@ namespace MyGame.Scenes.MiniGame.Scripts
switch (item.ItemType)
{
case StageItem.Type.Obstacle:
StopTimer();
player.Hit(closestPoint);
SoundManager.Instance.ChangePitchBGM(0f);
break;
@ -301,42 +345,24 @@ namespace MyGame.Scenes.MiniGame.Scripts
}).AddTo(this);
}
private void ResetGameWithCount (ScrollGamePlaceData[] levelPlaceList, ScrollGameStageData[] levelStageList)
private void ResetGameWithCount ()
{
GameDataManager.GameData.ScrollGameLastPlayTime = DateTime.UtcNow.ToBinary();
GameDataManager.GameData.ScrollGameTodayPlayCount++;
stageManager.SetStageList(levelStageList);
ResetGame(levelPlaceList, levelStageList);
ResetGame();
menuState.Value = MenuState.Game;
}
private void ResetGame(ScrollGamePlaceData[] placeList, ScrollGameStageData[] stageDataList)
private void ResetGame()
{
SoundManager.Instance.ChangeVolumeUniqueBGM(1f);
ResetTimer();
// ステージ読み込み
stageManager.SetBeginStages();
player.transform.position = characterBeginPos;
player.ResetPlayer();
scoreCount.Value = 0;
resultManager.Reset();
gameCompositeDisposable.Clear();
state.SkipLatestValueOnSubscribe()
.FirstOrDefault(x => x == GameState.Success)
.SelectMany(Observable.Timer(TimeSpan.FromSeconds(resultWaitTime)))
.Subscribe(x =>
{
resultManager.ShowResult(scoreCount.Value, placeList, stageDataList[0]);
SoundManager.Instance.ChangePitchBGM(1f);
}).AddTo(gameCompositeDisposable);
resultManager.OnRetry.ThrottleFirst(TimeSpan.FromSeconds(.2f)).Subscribe(_ =>
{
ScrollGameWatchVideoDialog.ShowDialog(() =>
{
ResetGameWithCount(placeList, stageDataList);
});
}).AddTo(gameCompositeDisposable);
state.Value = GameState.Ready;
}
@ -348,5 +374,26 @@ namespace MyGame.Scenes.MiniGame.Scripts
GameDataManager.GameData.ScrollGameTodayPlayCount = 0;
}
}
private void ResetTimer()
{
timerDisposable?.Dispose();
elapsedTime.SetValueAndForceNotify(0f);
}
private void StartTimer()
{
timerDisposable?.Dispose();
timerDisposable = Observable.Interval(TimeSpan.FromSeconds(1f))
.Subscribe(x =>
{
elapsedTime.Value = x;
}).AddTo(this);
}
private void StopTimer()
{
timerDisposable?.Dispose();
}
}
}

View File

@ -9,32 +9,27 @@ namespace MyGame.Scenes.MiniGame.Scripts
public class StageManager : MonoBehaviour
{
[SerializeField] private Transform stageTarget;
[SerializeField] private float elapsedTimeOffset;
[SerializeField] private float stageGenerateDistance;
[SerializeField] private int generateStageCount;
[SerializeField] private float beginStageOffset;
[SerializeField] private float partsToPartsOffset;
private float normalTime;
private float hardTime;
private float extraTime;
private Transform[] stageBeginPrefabList;
private Transform[] stageRandomPrefabList;
private int beginIndex;
private int lengthIndex;
private float stageEndXPos;
private float cacheTargetXPos;
private float cacheElapsedTime;
private ScrollGameStageData currentStageData;
private ScrollGameStageData nextStageData;
public IObservable<float> OnFence => fenceSubject.DelayFrame(1); // 1フレーム送らせて通知
private readonly Subject<float> fenceSubject = new();
public IReadOnlyReactiveProperty<ScrollGameDifficulty> Difficulty => difficulty;
private readonly ReactiveProperty<ScrollGameDifficulty> difficulty = new();
private ScrollGameDifficulty generateStageDifficulty;
private readonly CompositeDisposable changeDifficultyDisposable = new();
private readonly Dictionary<ScrollGameDifficulty, ScrollGameStageData> stageDataDict = new();
private readonly CompositeDisposable stageDisposable = new();
private readonly Dictionary<int, ScrollGameStageData> stageDataDict = new();
private void Start()
{
fenceSubject.AddTo(this);
difficulty.AddTo(this);
changeDifficultyDisposable.AddTo(this);
}
@ -42,50 +37,47 @@ namespace MyGame.Scenes.MiniGame.Scripts
{
// ステージリストを取り込み
stageDataDict.Clear();
foreach (var stageData in stageDataList)
foreach (var stageData in stageDataList.OrderBy(data => data.time))
{
if (stageDataDict.ContainsKey(stageData.Difficulty))
if (stageDataDict.ContainsKey(stageData.time))
{
continue;
}
stageDataDict.Add(stageData.Difficulty, stageData);
stageDataDict.Add(stageData.time, stageData);
}
}
public void SetBeginStages()
{
difficulty.SetValueAndForceNotify(ScrollGameDifficulty.Easy);
stageTarget.DestroyAllChildrens();
stageEndXPos = stageTarget.position.x + beginStageOffset;
cacheTargetXPos = stageEndXPos;
lengthIndex = 0;
beginIndex = 0;
generateStageDifficulty = difficulty.Value;
changeDifficultyDisposable.Clear();
cacheElapsedTime = 0f;
currentStageData = GetCurrentStage(cacheElapsedTime);
nextStageData = GetNextStage(cacheElapsedTime);
stageDisposable.Clear();
GenerateStage();
}
private void GenerateStage()
{
/*
* Length基準でまず
* LenghtIndexをつくって更に小さい単位GenerateCountに対応できるようにする
*
* prefabもつづつ読み込んだほうがいいっぽい
*
*
*/
// リソース読み込み
stageBeginPrefabList = stageDataDict[generateStageDifficulty].GetBeginStagePrefabs();
stageRandomPrefabList = stageDataDict[generateStageDifficulty].GetRandomStagePrefabs();
var stagePrefabs = Array.Empty<Transform>();
var stageCount = stageDataDict[generateStageDifficulty].length;
if (stageCount == 0)
// ステージデータ更新確認
var time = cacheElapsedTime + elapsedTimeOffset;
if (nextStageData != null && nextStageData.time <= time)
{
stageCount = generateStageCount;
beginIndex = 0;
currentStageData = GetCurrentStage(time);
nextStageData = GetNextStage(time);
}
// リソース読み込み
stageBeginPrefabList = currentStageData.GetBeginStagePrefabs();
stageRandomPrefabList = currentStageData.GetRandomStagePrefabs();
var stagePrefabs = Array.Empty<Transform>();
var stageCount = generateStageCount;
// beginPrefabsの使用が終わったらrandomに切り替え
if (stageBeginPrefabList.Length > beginIndex)
{
@ -94,7 +86,6 @@ namespace MyGame.Scenes.MiniGame.Scripts
beginIndex += stagePrefabs.Length;
}
Debug.Log($"stage {generateStageDifficulty} use begin {stagePrefabs.Length}");
var randomStageCount = stageCount - stagePrefabs.Length;
if (randomStageCount > 0)
{
@ -106,9 +97,6 @@ namespace MyGame.Scenes.MiniGame.Scripts
randomStageCount -= count;
}
}
Debug.Log($"stage {generateStageDifficulty} use begin + random {stagePrefabs.Length}");
lengthIndex += stagePrefabs.Length;
foreach (var stagePrefab in stagePrefabs)
{
@ -136,24 +124,11 @@ namespace MyGame.Scenes.MiniGame.Scripts
fenceSubject.OnNext(x.transform.position.x);
});
}
// 指定の長さ生成を終えた場合
if (lengthIndex >= stageDataDict[generateStageDifficulty].length)
{
// 次回ステージ生成の難易度を変更
generateStageDifficulty = NextDifficulty(generateStageDifficulty);
lengthIndex = 0;
beginIndex = 0;
// ステージを完走すると難易度変更
var cacheStageEndPos = stageEndXPos;
Observable.Interval(TimeSpan.FromSeconds(.5f))
.First(_ => cacheStageEndPos < cacheTargetXPos)
.Subscribe(_ => { }, () =>
{
difficulty.Value = NextDifficulty(difficulty.Value);
}).AddTo(changeDifficultyDisposable);
}
}
public void UpdateTime(float elapsed)
{
cacheElapsedTime = elapsed;
}
public void UpdatePos(float targetXPos)
@ -165,16 +140,14 @@ namespace MyGame.Scenes.MiniGame.Scripts
}
}
private static ScrollGameDifficulty NextDifficulty(ScrollGameDifficulty value)
private ScrollGameStageData GetCurrentStage(float time)
{
return value switch
{
ScrollGameDifficulty.Easy => ScrollGameDifficulty.Normal,
ScrollGameDifficulty.Normal => ScrollGameDifficulty.Hard,
ScrollGameDifficulty.Hard => ScrollGameDifficulty.Extra,
ScrollGameDifficulty.Extra => ScrollGameDifficulty.Extra,
_ => throw new ArgumentOutOfRangeException(nameof(value), value, null)
};
return stageDataDict.Last(pair => pair.Key <= time).Value;
}
private ScrollGameStageData GetNextStage(float time)
{
return stageDataDict.FirstOrDefault(pair => pair.Key > time).Value;
}
}
}

View File

@ -28,24 +28,6 @@ namespace MyGame.Scenes.MiniGame.Scripts
public IObservable<Unit> OnClick => button.OnClickAsObservable().TakeUntilDestroy(this);
public void SetPrevStageData(ScrollGameStageData stageData)
{
switch (stageData.Difficulty)
{
case ScrollGameDifficulty.Easy:
// lockText.text = string.Format(LocalizationManager.GetTranslation("UI/ScrollGameStageLockNormal"), stageData.needScore);
break;
case ScrollGameDifficulty.Normal:
// lockText.text = string.Format(LocalizationManager.GetTranslation("UI/ScrollGameStageLockHard"), stageData.needScore);
break;
case ScrollGameDifficulty.Hard:
lockText.text = string.Empty;
break;
default:
throw new ArgumentOutOfRangeException();
}
}
public void SetData(ScrollGameStageData stageData)
{
// stageName.text = stageData.id.ToString();

View File

@ -556,11 +556,9 @@ public sealed class ScrollGameStageData
{
public int id;
public int placeId;
public int difficulty;
public int time;
public string beginPrefabName;
public string randomPrefabName;
public int length;
public ScrollGameDifficulty Difficulty => (ScrollGameDifficulty)difficulty;
private string[] BeginPrefabName => beginPrefabName?.Split(',') ?? Array.Empty<string>();
private string[] RandomPrefabName => randomPrefabName?.Split(',') ?? Array.Empty<string>();