Merge branch 'develop' of bitbucket.org:usaya/popcorn into develop

This commit is contained in:
koya_15 2021-09-03 14:53:11 +09:00
commit 3fbb294d94
3 changed files with 215 additions and 125 deletions

View File

@ -21,7 +21,6 @@ public enum CustomerMovingType
public enum CustomerState public enum CustomerState
{ {
Walk, Walk,
Want,
Wait, Wait,
Order, Order,
Leave, Leave,
@ -76,12 +75,12 @@ public class CustomerController : MonoBehaviour
private float walkSideDirection; private float walkSideDirection;
public IReadOnlyReactiveProperty<CustomerMovingType> MoveEndObservable => moveEndSubject; public IReadOnlyReactiveProperty<CustomerMovingType> MoveEndObservable => moveEndSubject;
private readonly ReactiveProperty<CustomerMovingType> moveEndSubject = new ReactiveProperty<CustomerMovingType>(); private readonly ReactiveProperty<CustomerMovingType> moveEndSubject = new ReactiveProperty<CustomerMovingType>();
public IReadOnlyReactiveProperty<CustomerState> CustomerState => customerState; public IReadOnlyReactiveProperty<CustomerState> State => state;
private readonly ReactiveProperty<CustomerState> customerState = new ReactiveProperty<CustomerState>(); private readonly ReactiveProperty<CustomerState> state = new ReactiveProperty<CustomerState>();
private void Start() private void Start()
{ {
customerState.AddTo(this); state.AddTo(this);
durationDelta = 0f; durationDelta = 0f;
this.UpdateAsObservable().Subscribe(_ => this.UpdateAsObservable().Subscribe(_ =>
{ {
@ -118,43 +117,42 @@ public class CustomerController : MonoBehaviour
public void ChangeCustomerState(CustomerState state) public void ChangeCustomerState(CustomerState state)
{ {
customerState.Value = state; this.state.Value = state;
Debug.Log(state); Debug.Log(state);
switch (state) switch (state)
{ {
case global::CustomerState.Walk: case CustomerState.Walk:
SetMove(CustomerMovingType.WalkCenter); SetMove(CustomerMovingType.WalkCenter);
// 数秒立ち止まる // 数秒立ち止まる
AddMove(CustomerMovingType.StayBackLook, 2f); AddMove(CustomerMovingType.StayBackLook, 2f);
AddMove(CustomerMovingType.WalkSide); AddMove(CustomerMovingType.WalkSide);
break; break;
case global::CustomerState.Want: case CustomerState.Wait:
// 店に向かう // 店に向かう&順番待ち
// 近くの場合その場に待機
// まだ遠い場合待機場所に移動
moves.Clear(); moves.Clear();
if (currentMovingType == CustomerMovingType.StayBackLook) if (currentMovingType == CustomerMovingType.StayBackLook)
{ {
SetMove(CustomerMovingType.WalkBackHalf); SetMove(CustomerMovingType.WalkBackHalf);
break;
} }
else
{
SetMove(CustomerMovingType.WalkCenter); SetMove(CustomerMovingType.WalkCenter);
break;
case global::CustomerState.Wait:
// 順番待ち
// 近くの場合その場に待機
// まだ遠い場合待機場所に移動
AddMove(CustomerMovingType.WalkBackHalf); AddMove(CustomerMovingType.WalkBackHalf);
}
AddMove(CustomerMovingType.StayBackLook); AddMove(CustomerMovingType.StayBackLook);
break; break;
case global::CustomerState.Order: case CustomerState.Order:
// 受付まで行く // 受付まで行く
AddMove(CustomerMovingType.WalkBack); AddMove(CustomerMovingType.WalkBack);
AddMove(CustomerMovingType.StayBack); AddMove(CustomerMovingType.StayBack);
break; break;
case global::CustomerState.Leave: case CustomerState.Leave:
moves.Clear(); moves.Clear();
SetMove(CustomerMovingType.WalkSide); SetMove(CustomerMovingType.WalkSide);
break; break;
case global::CustomerState.EatingLeave: case CustomerState.EatingLeave:
AddMove(CustomerMovingType.WalkFrontEat); AddMove(CustomerMovingType.WalkFrontEat);
AddMove(CustomerMovingType.WalkSideEat); AddMove(CustomerMovingType.WalkSideEat);
break; break;

View File

@ -29,6 +29,7 @@ public class Market : MonoBehaviour
private ReactiveProperty<ShopState> shopState = new ReactiveProperty<ShopState>(); private ReactiveProperty<ShopState> shopState = new ReactiveProperty<ShopState>();
private ReactiveCollection<CustomerController> waitCustomerList = new ReactiveCollection<CustomerController>(); private ReactiveCollection<CustomerController> waitCustomerList = new ReactiveCollection<CustomerController>();
private Subject<CustomerController> requestSubject = new Subject<CustomerController>(); private Subject<CustomerController> requestSubject = new Subject<CustomerController>();
private Subject<Unit> orderSubject = new Subject<Unit>();
// Start is called before the first frame update // Start is called before the first frame update
void Start() void Start()
@ -36,6 +37,7 @@ public class Market : MonoBehaviour
shopState.AddTo(this); shopState.AddTo(this);
waitCustomerList.AddTo(this); waitCustomerList.AddTo(this);
requestSubject.AddTo(this); requestSubject.AddTo(this);
orderSubject.AddTo(this);
var gameData = GameDataManager.GameData; var gameData = GameDataManager.GameData;
CoinManager.Instance.ChangeCoin(gameData.coin); CoinManager.Instance.ChangeCoin(gameData.coin);
@ -65,7 +67,8 @@ public class Market : MonoBehaviour
}; };
HeartMeter.Instance.Initialize(shopLevelList.Select(x => x.heart).ToList()); HeartMeter.Instance.Initialize(shopLevelList.Select(x => x.heart).ToList());
HeartMeter.Instance.SetHeart(15); HeartMeter.Instance.SetHeart(gameData.Heart);
HeartMeter.Instance.SetHeart(99999);
// 在庫数表示 // 在庫数表示
stockView.SetStock(gameData.StorageTanks); stockView.SetStock(gameData.StorageTanks);
@ -83,54 +86,63 @@ public class Market : MonoBehaviour
// お店の状態設定 // お店の状態設定
shopState.Value = gameData.ShopStock.Count == 0 ? ShopState.Close : ShopState.Open; shopState.Value = gameData.ShopStock.Count == 0 ? ShopState.Close : ShopState.Open;
// 購入リクエスト
shopState
.Where(x => x == ShopState.Open)
.Where(_ => waitCustomerList.Count > 0)
.Select(_ => waitCustomerList[0])
.Merge(waitCustomerList.ObserveAdd().Select(x => x.Value))
.BatchFrame()
.Select(x => x.RandomChoose()) // 同時にリクエストが有った場合1人選ぶ
.Where(_ => shopState.Value == ShopState.Open) // 他に購入中の客がいないことを確認
.Subscribe(x =>
{
Debug.Log($"RequestComfirmed");
waitCustomerList.Remove(x);
// 購入へ
x.ChangeCustomerState(CustomerState.Order);
shopState.Value = ShopState.Busy;
}).AddTo(this);
// お客さん一覧 // お客さん一覧
var customerList = new ReactiveCollection<CustomerController>(); var customerList = new ReactiveCollection<CustomerController>();
customerList.AddTo(this); customerList.AddTo(this);
// 購入リクエスト
orderSubject
.Merge(waitCustomerList.ObserveAdd().AsUnitObservable())
.Merge(shopState.Where(x => x == ShopState.Open).AsUnitObservable())
.Where(_ => shopState.Value == ShopState.Open)
.BatchFrame()
.Where(_ => waitCustomerList.Count > 0)
.SelectMany(_ => waitCustomerList.ToList().GetRange(0, Mathf.Min(3, waitCustomerList.Count)))
.Subscribe(customer =>
{
Debug.Log($"aa order:{customerList.Count(x => x.State.Value == CustomerState.Order)} Request {Time.time} {customer.GetHashCode()}");
if (customerList.Count(x => x.State.Value == CustomerState.Order) >= 3)
{
shopState.Value = ShopState.Busy;
return;
}
waitCustomerList.Remove(customer);
// 購入へ
customer.ChangeCustomerState(CustomerState.Order);
}).AddTo(this);
// 購入客 // 購入客
customerList.ObserveAdd() customerList.ObserveAdd()
.Select(x => x.Value) .Select(x => x.Value)
.Subscribe(customerController => .Subscribe(customerController =>
{ {
customerController.State.Subscribe(c =>
{
if (c == CustomerState.EatingLeave)
{
Debug.Log($"aa order:{customerList.Count(x => x.State.Value == CustomerState.Order)} EatingLeave");
orderSubject.OnNext(default);
}
}).AddTo(customerController);
// 店に向かう // 店に向かう
customerController.ChangeCustomerState(CustomerState.Want); customerController.ChangeCustomerState(CustomerState.Wait);
waitCustomerList.Add(customerController);
shopState.Subscribe(x => shopState.Subscribe(x =>
{ {
switch (x) switch (x)
{ {
case ShopState.Open: case ShopState.Open:
break;
case ShopState.Busy: case ShopState.Busy:
// 自分が購入中
if (customerController.CustomerState.Value == CustomerState.Order)
{
return;
}
// 待機
customerController.ChangeCustomerState(CustomerState.Wait);
break; break;
case ShopState.Close: case ShopState.Close:
// 売り切れの場合帰る // 売り切れの場合帰る
if (customerController.State.Value == CustomerState.Order)
{
return;
}
this.CallWaitForSeconds(Random.Range(0f, .4f), () =>
{
customerController.ChangeCustomerState(CustomerState.Leave); customerController.ChangeCustomerState(CustomerState.Leave);
});
break; break;
default: default:
throw new ArgumentOutOfRangeException(nameof(x), x, null); throw new ArgumentOutOfRangeException(nameof(x), x, null);
@ -138,34 +150,66 @@ public class Market : MonoBehaviour
}).AddTo(customerController); }).AddTo(customerController);
}).AddTo(this); }).AddTo(this);
requestSubject.Subscribe(customerController => requestSubject.BatchFrame(30, FrameCountType.Update).Subscribe(customers =>
{ {
// 売り切れ
if (gameData.ShopStock.Count == 0) if (gameData.ShopStock.Count == 0)
{ {
shopState.Value = ShopState.Close; shopState.Value = ShopState.Close;
}
var coin = 0;
var orders = new List<int>();
var dontBuyCustomerList = new List<CustomerController>();
foreach (var controller in customers)
{
Debug.Log(shuffledOrder.Aggregate("", (s, i) => $"{s},{i}"));
// 売り切れ
if (shuffledOrder.Count == 0)
{
controller.ChangeCustomerState(CustomerState.Leave);
dontBuyCustomerList.Add(controller);
break;
}
// オーダー数
var orderCount = Random.Range(1,5);
// 在庫取得
var tmpOrderCount = Mathf.Min(orderCount, shuffledOrder.Count);
// shuffledOrder順に販売
orders.AddRange(shuffledOrder.GetRange(0, tmpOrderCount));
shuffledOrder.RemoveRange(0, tmpOrderCount);
// コーンの味吹き出しを設定(レア度優先など
controller.ChangeWantFlavor(displayFlavors[orders.RandomChoose()]);
}
foreach (var customerController in dontBuyCustomerList)
{
customers.Remove(customerController);
}
if (orders.Count == 0)
{
return; return;
} }
// shuffledOrder順に販売
Debug.Log(shuffledOrder.Aggregate("", (s, i) => s + i));
var orderNum = shuffledOrder[0];
shuffledOrder.RemoveAt(0);
// コーンの味吹き出しを設定
customerController.ChangeWantFlavor(displayFlavors[orderNum]);
this.CallWaitForSeconds(1.5f, () =>
{
// 購入 // 購入
SellPopcorn(orderNum); var flavors = orders.Select(x => (displayFlavors[x], 0)).ToList();
blueView.SellAction(); coin += SellPopcorn(flavors);
var remainStockCount = gameData.ShopStock.Count;
// 自動補充 refill // 自動補充 refill
RefillOneProduct(); RefillProduct();
StockFlavorLog(); StockFlavorLog();
var setStockFlag = false;
// 補充された場合フレーバー再設定 // 補充された場合フレーバー再設定
var setStockFlag = false;
if (gameData.ShopStock.Count == ShopStockCount) if (gameData.ShopStock.Count == ShopStockCount)
{ {
shuffledOrder.Add(orderNum); shuffledOrder.AddRange(orders);
displayFlavors[orderNum] = gameData.ShopStock.Last(); Debug.Log($"remain {remainStockCount}, order {orders.Count}");
var stock = gameData.ShopStock.GetRange(remainStockCount, orders.Count).ToArray();
for (int i = 0; i < orders.Count; i++)
{
displayFlavors[orders[i]] = stock[i];
}
} }
else if (gameData.ShopStock.Count <= 13 && shuffledOrder.Exists(x => x > 13)) else if (gameData.ShopStock.Count <= 13 && shuffledOrder.Exists(x => x > 13))
{ {
@ -180,28 +224,46 @@ public class Market : MonoBehaviour
setStockFlag = true; setStockFlag = true;
} }
// 表示更新 this.CallWaitForSeconds(1.5f, () =>
{
foreach (var order in orders)
{
cartView.SellStock(order);
}
blueView.SellAction();
// コイン獲得
CoinManager.Instance.AddCoinWithEffect(coin, () => { });
gameData.coin = CoinManager.Instance.OwnCoin;
gameData.Heart += customers.Count;
GameDataManager.SaveGameData();
shopState.Value = gameData.ShopStock.Count == 0 ? ShopState.Close : ShopState.Open;
// 表示更新(陳列13=650ms,7=350ms)
this.CallWaitForSeconds(1f, () => this.CallWaitForSeconds(1f, () =>
{
foreach (var customerController in customers)
{ {
var heartAnimation = customerController.GetComponent<HeartAnimation>(); var heartAnimation = customerController.GetComponent<HeartAnimation>();
heartAnimation.GetHeart(() => heartAnimation.GetHeart(() =>
{ {
HeartMeter.Instance.AddHeart(3); HeartMeter.Instance.AddHeart(1);
}); });
customerController.ChangeCustomerState(CustomerState.EatingLeave); customerController.ChangeCustomerState(CustomerState.EatingLeave);
}
stockView.SetStock(gameData.StorageTanks); stockView.SetStock(gameData.StorageTanks);
if (gameData.ShopStock.Count == ShopStockCount) if (gameData.ShopStock.Count == ShopStockCount)
{ {
// 補充したフレーバーのスキンを設定 // 補充したフレーバーのスキンを設定
cartView.Refill(orderNum, displayFlavors[orderNum]); foreach (var order in orders)
{
cartView.Refill(order, displayFlavors[order]);
}
} }
else if (setStockFlag) else if (setStockFlag)
{ {
cartView.SetStock(displayFlavors); cartView.SetStock(displayFlavors);
} }
}); });
shopState.Value = gameData.ShopStock.Count == 0 ? ShopState.Close : ShopState.Open;
}); });
}).AddTo(this); }).AddTo(this);
@ -254,7 +316,10 @@ public class Market : MonoBehaviour
var customer = Instantiate(customerPrefab); var customer = Instantiate(customerPrefab);
var customerController = customer.GetComponent<CustomerController>(); var customerController = customer.GetComponent<CustomerController>();
customerController.Setup(); customerController.Setup();
customerController.MoveEndObservable.SkipLatestValueOnSubscribe().DistinctUntilChanged().Subscribe(type => customerController.MoveEndObservable
.SkipLatestValueOnSubscribe()
.DistinctUntilChanged()
.Subscribe(type =>
{ {
// Debug.Log($"move end {type}"); // Debug.Log($"move end {type}");
switch (type) switch (type)
@ -264,6 +329,9 @@ public class Market : MonoBehaviour
customerList.Remove(customerController); customerList.Remove(customerController);
Destroy(customer); Destroy(customer);
break; break;
case CustomerMovingType.WalkBackHalf:
waitCustomerList.Add(customerController);
break;
case CustomerMovingType.StayBack: case CustomerMovingType.StayBack:
requestSubject.OnNext(customerController); requestSubject.OnNext(customerController);
break; break;
@ -290,28 +358,27 @@ public class Market : MonoBehaviour
}).AddTo(this); }).AddTo(this);
} }
private void SellPopcorn(int orderNum) private int SellPopcorn(List<(int flavor, int bonusRate)> flavors)
{ {
var gameData = GameDataManager.GameData; var gameData = GameDataManager.GameData;
// 品切れ // 品切れ
if (gameData.ShopStock.Count == 0) if (gameData.ShopStock.Count == 0)
{ {
return; return 0;
} }
var targetFlavorId = displayFlavors[orderNum]; Debug.Log($"sellCount:{flavors.Count} {shuffledOrder.Count}");
Debug.Log($"sell:{orderNum} flavor:{targetFlavorId} {shuffledOrder.Count}");
var targetIndex = gameData.ShopStock.FindIndex(x => x == targetFlavorId); // フレーバーを売る
var stockData = gameData.ShopStock[targetIndex]; var coin = 0;
foreach (var flavorData in flavors)
{
var targetIndex = gameData.ShopStock.FindIndex(x => x == flavorData.flavor);
var flavorRecipe = allRecipe.First(x => x.RecipeId == gameData.ShopStock[targetIndex]);
gameData.ShopStock.RemoveAt(targetIndex); gameData.ShopStock.RemoveAt(targetIndex);
cartView.SellStock(orderNum);
// コイン獲得
var bonusRate = 0; var bonusRate = 0;
var flavor = allRecipe.First(x => x.RecipeId == stockData); coin += flavorRecipe.Price * (1 + bonusRate / 100);
CoinManager.Instance.AddCoinWithEffect(flavor.Price * (1 + bonusRate / 100), () => { }); }
gameData.coin = CoinManager.Instance.OwnCoin; return coin;
GameDataManager.SaveGameData();
} }
private List<int> ShuffleOrder(int length) private List<int> ShuffleOrder(int length)
@ -338,6 +405,31 @@ public class Market : MonoBehaviour
GameDataManager.SaveGameData(); GameDataManager.SaveGameData();
} }
private void RefillProduct()
{
// 手前のタンクから出し多分stockをへらす
// へらした分を店頭リストに追加する
var gameData = GameDataManager.GameData;
var shopSpace = ShopStockCount - gameData.ShopStock.Count;
var index = 0;
var tankCount = gameData.StorageTanks.Count;
while (shopSpace > 0)
{
if (index > tankCount - 1)
{
break;
}
var tank = gameData.StorageTanks[index];
var stockCount = Mathf.Min(shopSpace, tank.Stock);
gameData.ShopStock.AddRange(Enumerable.Repeat(tank.FlavorId, stockCount));
shopSpace -= stockCount;
tank.Stock -= stockCount;
gameData.StorageTanks[index] = tank;
index++;
}
GameDataManager.SaveGameData();
}
private void CheckAndFixStock() private void CheckAndFixStock()
{ {
if (GameDataManager.GameData.ShopStock.Count > ShopStockCount) if (GameDataManager.GameData.ShopStock.Count > ShopStockCount)

View File

@ -75,8 +75,8 @@ public sealed class GameData {
// タンクポップコーン在庫 // タンクポップコーン在庫
[DataMember(Name = "Data20")] [DataMember(Name = "Data20")]
public List<StorageTank> StorageTanks; public List<StorageTank> StorageTanks;
[DataMember(Name = "Data21")]
public int Heart = 0;
// public void ChangeAvatar(AvatarData avatarData){ // public void ChangeAvatar(AvatarData avatarData){
// newAvatarIdList.Remove(avatarData.id); // newAvatarIdList.Remove(avatarData.id);