룰렛 MVP 패턴으로 수정
This commit is contained in:
@@ -2,7 +2,7 @@ using UnityEngine;
|
|||||||
using UnityEngine.Events;
|
using UnityEngine.Events;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using UniRx;
|
using UniRx;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace TON
|
namespace TON
|
||||||
{
|
{
|
||||||
@@ -27,6 +27,9 @@ namespace TON
|
|||||||
private bool isSpinning = false; // 현재 회전중인지
|
private bool isSpinning = false; // 현재 회전중인지
|
||||||
private int selectedIndex = 0; // 룰렛에서 선택된 아이템
|
private int selectedIndex = 0; // 룰렛에서 선택된 아이템
|
||||||
|
|
||||||
|
private RoulettePresenter presenter;
|
||||||
|
private List<RoulettePiece> pieceUIs = new();
|
||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
pieceAngle = 360 / roulettePieceData.Length;
|
pieceAngle = 360 / roulettePieceData.Length;
|
||||||
@@ -39,16 +42,15 @@ namespace TON
|
|||||||
|
|
||||||
private void SpawnPiecesAndLines()
|
private void SpawnPiecesAndLines()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < roulettePieceData.Length; ++i)
|
for (int i = 0; i < presenter.RoulettePieces.Count; ++i)
|
||||||
{
|
{
|
||||||
Transform piece = Instantiate(piecePrefab, pieceParent.position, Quaternion.identity, pieceParent);
|
Transform piece = Instantiate(piecePrefab, pieceParent.position, Quaternion.identity, pieceParent);
|
||||||
// 생성한 룰렛 조각의 정보 설정(아이콘, 설명)
|
var pieceUI = piece.GetComponent<RoulettePiece>();
|
||||||
piece.GetComponent<RoulettePiece>().Setup(roulettePieceData[i]);
|
pieceUI.Setup(presenter.RoulettePieces[i].Model);
|
||||||
// 생성한 룰렛 조각 회전
|
|
||||||
piece.RotateAround(pieceParent.position, Vector3.back, (pieceAngle * i));
|
piece.RotateAround(pieceParent.position, Vector3.back, (pieceAngle * i));
|
||||||
|
pieceUIs.Add(pieceUI);
|
||||||
|
|
||||||
Transform line = Instantiate(linePrefab, lineParent.position, Quaternion.identity, lineParent);
|
Transform line = Instantiate(linePrefab, lineParent.position, Quaternion.identity, lineParent);
|
||||||
// 생성한 선 회전 (룰렛 조각 사이를 구분하는 용도
|
|
||||||
line.RotateAround(lineParent.position, Vector3.back, (pieceAngle * i) + halfPieceAngle);
|
line.RotateAround(lineParent.position, Vector3.back, (pieceAngle * i) + halfPieceAngle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,50 +89,48 @@ namespace TON
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Spin(UnityAction<RoulettePieceData> action = null)
|
public void Bind(RoulettePresenter presenter)
|
||||||
{
|
{
|
||||||
if(isSpinning == true) return;
|
this.presenter = presenter;
|
||||||
|
pieceAngle = 360f / roulettePieceData.Length;
|
||||||
// 룰렛의 결과 값 선택
|
halfPieceAngle = pieceAngle * 0.5f;
|
||||||
selectedIndex = GetRandomIndex();
|
halfPieceAngleWithPaddings = halfPieceAngle - (halfPieceAngle * 0.25f);
|
||||||
// 선택된 결과의 중심 각도
|
SpawnPiecesAndLines();
|
||||||
float angle = pieceAngle * selectedIndex;
|
|
||||||
// 정확히 중심이 아닌 결과 값 범위 안의 임의의 각도 선택
|
|
||||||
float leftOffset = (angle - halfPieceAngleWithPaddings) % 360;
|
|
||||||
float rightOffset = (angle + halfPieceAngleWithPaddings) % 360;
|
|
||||||
float randomAngle = Random.Range(leftOffset, rightOffset);
|
|
||||||
|
|
||||||
// 목표 각도(targetAngle) = 결과 각도 + 360 * 회전 시간 * 회전 속도
|
|
||||||
int rotateSpeed = 2;
|
|
||||||
float targetangle = (randomAngle + 360 * spinDuration * rotateSpeed);
|
|
||||||
|
|
||||||
Debug.Log($"SelectedIndex:{selectedIndex}, angle:{angle}");
|
|
||||||
Debug.Log($"left/right/random:{leftOffset}/{rightOffset}/{randomAngle}");
|
|
||||||
Debug.Log($"targetAngle:{targetangle}");
|
|
||||||
|
|
||||||
isSpinning = true;
|
|
||||||
StartCoroutine(OnSpin(targetangle, action));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerator OnSpin(float end, UnityAction<RoulettePieceData> action)
|
public void Spin(System.Action<RoulettePiecePresenter> onEnd)
|
||||||
|
{
|
||||||
|
if (presenter.IsSpinning.Value) return;
|
||||||
|
presenter.Spin(selectedPresenter =>
|
||||||
|
{
|
||||||
|
int selectedIndex = selectedPresenter.Index.Value;
|
||||||
|
float angle = pieceAngle * selectedIndex;
|
||||||
|
float leftOffset = (angle - halfPieceAngleWithPaddings) % 360;
|
||||||
|
float rightOffset = (angle + halfPieceAngleWithPaddings) % 360;
|
||||||
|
float randomAngle = Random.Range(leftOffset, rightOffset);
|
||||||
|
int rotateSpeed = 2;
|
||||||
|
float targetangle = (randomAngle + 360 * spinDuration * rotateSpeed);
|
||||||
|
StartCoroutine(OnSpin(targetangle, () =>
|
||||||
|
{
|
||||||
|
presenter.IsSpinning.Value = false;
|
||||||
|
onEnd?.Invoke(selectedPresenter);
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private System.Collections.IEnumerator OnSpin(float end, System.Action onEnd)
|
||||||
{
|
{
|
||||||
float current = 0;
|
float current = 0;
|
||||||
float percent = 0;
|
float percent = 0;
|
||||||
|
|
||||||
while (percent < 1)
|
while (percent < 1)
|
||||||
{
|
{
|
||||||
current = Time.deltaTime;
|
current = Time.deltaTime;
|
||||||
percent += current / spinDuration;
|
percent += current / spinDuration;
|
||||||
|
|
||||||
float z = Mathf.Lerp(0, end, spinningCurve.Evaluate(percent));
|
float z = Mathf.Lerp(0, end, spinningCurve.Evaluate(percent));
|
||||||
spinningRoulette.rotation = Quaternion.Euler(0, 0, z);
|
spinningRoulette.rotation = Quaternion.Euler(0, 0, z);
|
||||||
|
|
||||||
yield return null;
|
yield return null;
|
||||||
}
|
}
|
||||||
|
onEnd?.Invoke();
|
||||||
isSpinning = false;
|
|
||||||
|
|
||||||
if(action != null) action.Invoke(roulettePieceData[selectedIndex]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using UniRx;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace TON
|
||||||
|
{
|
||||||
|
public class RoulettePiecePresenter
|
||||||
|
{
|
||||||
|
public ReactiveProperty<Sprite> Icon { get; }
|
||||||
|
public ReactiveProperty<string> Description { get; }
|
||||||
|
public ReactiveProperty<int> Chance { get; }
|
||||||
|
public ReactiveProperty<int> Index { get; }
|
||||||
|
public ReactiveProperty<int> Weight { get; }
|
||||||
|
|
||||||
|
public RoulettePieceData Model { get; }
|
||||||
|
|
||||||
|
public RoulettePiecePresenter(RoulettePieceData model)
|
||||||
|
{
|
||||||
|
Model = model;
|
||||||
|
Icon = new ReactiveProperty<Sprite>(model.icon);
|
||||||
|
Description = new ReactiveProperty<string>(model.description);
|
||||||
|
Chance = new ReactiveProperty<int>(model.chance);
|
||||||
|
Index = new ReactiveProperty<int>(model.index);
|
||||||
|
Weight = new ReactiveProperty<int>(model.weight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 322f049f974a11c4d8b04937b20b2180
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Collections;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UniRx;
|
using UniRx;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
@@ -9,42 +9,64 @@ namespace TON
|
|||||||
{
|
{
|
||||||
private PlayerDataManager playerDataManager;
|
private PlayerDataManager playerDataManager;
|
||||||
private List<RoulettePieceData> roulettePieceModels = new();
|
private List<RoulettePieceData> roulettePieceModels = new();
|
||||||
public ReactiveCollection<RoulettePresenter> RoulettePieces { get; } = new();
|
public ReactiveCollection<RoulettePiecePresenter> RoulettePieces { get; } = new();
|
||||||
|
public ReactiveProperty<bool> IsSpinning { get; } = new(false);
|
||||||
public RoulettePresenter()
|
public ReactiveProperty<RoulettePiecePresenter> SelectedPiece { get; } = new();
|
||||||
{
|
private int accumulatedWeight;
|
||||||
// 싱글톤으로 PlayerDataManager 접근
|
|
||||||
playerDataManager = PlayerDataManager.Singleton;
|
|
||||||
|
|
||||||
|
public RoulettePresenter(RoulettePieceData[] pieceDataArray)
|
||||||
|
{
|
||||||
|
playerDataManager = PlayerDataManager.Singleton;
|
||||||
if (playerDataManager == null)
|
if (playerDataManager == null)
|
||||||
{
|
{
|
||||||
Debug.LogError("PlayerDataManager가 초기화되지 않았습니다.");
|
Debug.LogError("PlayerDataManager가 초기화되지 않았습니다.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Todo : UI 바인딩
|
|
||||||
|
|
||||||
roulettePieceModels.Add(new RoulettePieceData("10", 1));
|
|
||||||
roulettePieceModels.Add(new RoulettePieceData("2", 14));
|
|
||||||
roulettePieceModels.Add(new RoulettePieceData("25", 1));
|
|
||||||
roulettePieceModels.Add(new RoulettePieceData("400", 72));
|
|
||||||
roulettePieceModels.Add(new RoulettePieceData("50", 1));
|
|
||||||
roulettePieceModels.Add(new RoulettePieceData("1000", 11));
|
|
||||||
|
|
||||||
foreach (var item in roulettePieceModels)
|
accumulatedWeight = 0;
|
||||||
|
for (int i = 0; i < pieceDataArray.Length; ++i)
|
||||||
{
|
{
|
||||||
RoulettePieces.Add(new RoulettePresenter(this, item));
|
var data = pieceDataArray[i];
|
||||||
|
data.index = i;
|
||||||
|
if (data.chance <= 0) data.chance = 1;
|
||||||
|
accumulatedWeight += data.chance;
|
||||||
|
data.weight = accumulatedWeight;
|
||||||
|
roulettePieceModels.Add(data);
|
||||||
|
RoulettePieces.Add(new RoulettePiecePresenter(data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 재화 획득 메서드
|
public int GetRandomIndex()
|
||||||
public void InsertRouletteResult(RoulettePieceData selectedData)
|
|
||||||
{
|
{
|
||||||
// 재화 획득 코드 추가
|
int weight = UnityEngine.Random.Range(0, accumulatedWeight);
|
||||||
playerDataManager.AddGold(int.Parse(selectedData.description));
|
for (int i = 0; i < roulettePieceModels.Count; ++i)
|
||||||
|
{
|
||||||
// UI 갱신 코드 추가
|
if (roulettePieceModels[i].weight > weight)
|
||||||
UIManager.Singleton.UpdateCashData();
|
{
|
||||||
Debug.Log($"{selectedData.index}:{selectedData.description}");
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Spin(Action<RoulettePiecePresenter> onResult = null)
|
||||||
|
{
|
||||||
|
if (IsSpinning.Value) return;
|
||||||
|
IsSpinning.Value = true;
|
||||||
|
int selectedIndex = GetRandomIndex();
|
||||||
|
var selected = RoulettePieces[selectedIndex];
|
||||||
|
SelectedPiece.Value = selected;
|
||||||
|
onResult?.Invoke(selected);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 결과 처리(예: 골드 지급 등)
|
||||||
|
public void InsertRouletteResult(RoulettePiecePresenter selectedPresenter)
|
||||||
|
{
|
||||||
|
if (playerDataManager != null && int.TryParse(selectedPresenter.Description.Value, out int gold))
|
||||||
|
{
|
||||||
|
playerDataManager.AddGold(gold);
|
||||||
|
UIManager.Singleton.UpdateCashData();
|
||||||
|
Debug.Log($"{selectedPresenter.Index.Value}:{selectedPresenter.Description.Value}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,65 +1,33 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UniRx;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
using UniRx;
|
||||||
|
|
||||||
namespace TON
|
namespace TON
|
||||||
{
|
{
|
||||||
// View <> Presenter <> Model
|
// View
|
||||||
public class RouletteSpin : MonoBehaviour
|
public class RouletteSpin : MonoBehaviour
|
||||||
{
|
{
|
||||||
[SerializeField] private Roulette roulette;
|
[SerializeField] private Roulette roulette;
|
||||||
[SerializeField] private Button buttonSpin;
|
[SerializeField] private Button buttonSpin;
|
||||||
|
|
||||||
// TODO : Roulette 변수 선언
|
|
||||||
|
|
||||||
private RoulettePresenter roulettePresenter;
|
private RoulettePresenter roulettePresenter;
|
||||||
|
|
||||||
private void Start()
|
|
||||||
{
|
|
||||||
// Presenter 초기화
|
|
||||||
roulettePresenter = new RoulettePresenter();
|
|
||||||
// TODO : UI와 Presenter 바인딩
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
buttonSpin.onClick.AddListener(()=>
|
roulettePresenter = new RoulettePresenter(roulette.roulettePieceData);
|
||||||
|
roulette.Bind(roulettePresenter);
|
||||||
|
buttonSpin.onClick.AddListener(() =>
|
||||||
{
|
{
|
||||||
buttonSpin.interactable = false;
|
buttonSpin.interactable = false;
|
||||||
roulette.Spin(EndOfSpin);
|
roulette.Spin(selectedPresenter =>
|
||||||
|
{
|
||||||
|
buttonSpin.interactable = true;
|
||||||
|
roulettePresenter.InsertRouletteResult(selectedPresenter);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EndOfSpin(RoulettePieceData selectedData)
|
|
||||||
{
|
|
||||||
buttonSpin.interactable = true;
|
|
||||||
|
|
||||||
roulettePresenter.InsertRouletteResult(selectedData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Presenter
|
|
||||||
public class RouletteItemPresenter
|
|
||||||
{
|
|
||||||
public ReactiveProperty<string> Description { get; set; }
|
|
||||||
public ReactiveProperty<int> Chance { get; set; }
|
|
||||||
|
|
||||||
public ReactiveCommand BuyCommand { get; set; }
|
|
||||||
|
|
||||||
private RoulettePieceData _model;
|
|
||||||
|
|
||||||
public RouletteItemPresenter(RoulettePresenter roulettePresenter, RoulettePieceData model)
|
|
||||||
{
|
|
||||||
_model = model;
|
|
||||||
|
|
||||||
Description = new ReactiveProperty<string>(model.description);
|
|
||||||
Chance = new ReactiveProperty<int>(model.chance);
|
|
||||||
|
|
||||||
BuyCommand = new ReactiveCommand();
|
|
||||||
BuyCommand.Subscribe(_ => roulettePresenter.InsertRouletteResult(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user