Files
MiniGame_Unity_GP/Assets/Resources/flower/scripts/CreatFlower.cs
T
2026-07-06 16:27:14 +08:00

1344 lines
49 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Serialization;
using DG.Tweening;
using Newtonsoft.Json;
using Spine.Unity;
using TowerClimberChronicles;
using Unity.VisualScripting;
using UnityEngine;
public class CreatFlower : MonoBehaviour
{
// Start is called before the first frame update
public Camera orthoCamera;
public static CreatFlower instance;
public List<GameObject> temp_slot_gameobject_list;//固定的暂存位置点位信息
public List<GameObject> flower_slot_gameobject_list_0;
public List<GameObject> flower_slot_gameobject_list_1;
public List<GameObject> flower_slot_gameobject_list_2;
public List<GameObject> flower_slot_gameobject_list_3;
public List<GameObject> pot_object_list;
public List<SpriteRenderer> pot_object_type_image;
public List<SkeletonAnimation> pot_animation_list;
public SkeletonAnimation clean_animation;
public SkeletonAnimation refresh_animation;
public List<GameObject> branch_list;
public GameObject clean_pos_object;
public List<GameObject> gray_pot_list;
public List<GameObject> normal_branch_list;
private List<GameObject> temp_slot_item_list = new List<GameObject>()
{
null,null,null,null,null
};//暂存区的实例化的花
public List<GameObject> clean_item_list = new List<GameObject>();//使用道具后的item
private List<GameObject> flower_slot_list0 = new List<GameObject>();
private List<GameObject> flower_slot_list1 = new List<GameObject>();
private List<GameObject> flower_slot_list2 = new List<GameObject>();
private List<GameObject> flower_slot_list3 = new List<GameObject>();
// private List<GameObject> all_flower_list = new List<GameObject>();//所有还没被销毁的花
public List<int> slot_type_list = new List<int>() { -1, -1, -1, -1 };
private List<GameObject> bubble_prefab_list = new List<GameObject>();
private List<Sprite> flower_image_list = new List<Sprite>();
private List<Sprite> pot_image_list = new List<Sprite>();
private List<GameObject> all_flower_in_pool_list = new List<GameObject>();//所有没被点击过的花;
public bool CanClick = true;
private GameObject top_area;
// public bool slot_0_open = false;
// public bool slot_1_open = false;
private void Awake()
{
instance = this;
// for (int i = 0; i < 16; i++)
// {
// img_list.Add(Resources.Load<Sprite>("card/card_sprite/" + i));
// }
orthoCamera = GameObject.Find("GameCamera").GetComponent<Camera>();
float size = (float)System.Math.Round(28.125f / ((float)Screen.width / Screen.height), 4);
string type = SystemInfo.deviceModel.ToLower().Trim();
// //////Debug.Log($"type==========={type}");
if (type.Substring(0, 3) == "ipa")
{//iPad机型
size = 49.9f;
}
orthoCamera.orthographicSize = size;
GameObject target = GameObject.Find("qiang");
top_area = GameObject.Find("top_area");
FitObjectToScreenWidth(target, orthoCamera);
AlignObjectBottom(target, orthoCamera);
AlignObjectTop(top_area, orthoCamera);
for (int i = 1; i < 6; i++)
{
bubble_prefab_list.Add(Resources.Load<GameObject>("flower/item/item_" + i));
}
for (int i = 1; i < 13; i++)
{
flower_image_list.Add(Resources.Load<Sprite>("flower/image/" + i + "_b"));
pot_image_list.Add(Resources.Load<Sprite>("flower/image/" + i + "_a"));
}
for (int i = 0; i < pot_animation_list.Count; i++)
{
pot_animation_list[i].gameObject.SetActive(false);
}
clean_animation.gameObject.SetActive(false);
refresh_animation.gameObject.SetActive(false);
// GameDispatcher.Instance.AddListener(GameMsg.FlowerEnd, ResetGame);
GameDispatcher.Instance.AddListener(GameMsg.FlowerReset, ResetGame);
}
private GameObject Popup;
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
if (!CanClick) return;
if (Popup == null) Popup = GameObject.Find("Popup");
if (Popup.transform.childCount != 0) return;
int layerMask = 1 << 7;
// 如果射线与layerMask指定层的碰撞器发生碰撞
Ray ray = orthoCamera.ScreenPointToRay(Input.mousePosition);
RaycastHit2D hit = Physics2D.Raycast(ray.origin, ray.direction, Mathf.Infinity, layerMask);
if (hit.collider != null)
{
if (hit.collider.CompareTag("flower_mask"))
{
// 命中遮罩,不响应
return;
}
ChildItem child = hit.collider.GetComponent<ChildItem>();
if (child != null) child.OnChildClicked();
}
else
{
// //////Debug.Log("No hit");
}
}
if (show_finger)
{
finger_object.transform.rotation = Quaternion.identity;
}
}
public void ResetGame(object a = null)
{
for (int i = bubble_parent.transform.childCount - 1; i >= 0; i--)
{
Destroy(bubble_parent.transform.GetChild(i).gameObject);
}
all_flower_in_pool_list.Clear();
for (int i = 0; i < temp_slot_item_list.Count; i++)
{
if (temp_slot_item_list[i] != null) Destroy(temp_slot_item_list[i]);
}
for (int i = 0; i < clean_item_list.Count; i++)
{
Destroy(clean_item_list[i]);
}
clean_item_list.Clear();
for (int i = 0; i < flower_slot_list0.Count; i++)
{
Destroy(flower_slot_list0[i]);
}
flower_slot_list0.Clear();
for (int i = 0; i < flower_slot_list1.Count; i++)
{
Destroy(flower_slot_list1[i]);
}
flower_slot_list1.Clear();
for (int i = 0; i < flower_slot_list2.Count; i++)
{
Destroy(flower_slot_list2[i]);
}
flower_slot_list2.Clear();
for (int i = 0; i < flower_slot_list3.Count; i++)
{
Destroy(flower_slot_list3[i]);
}
flower_slot_list3.Clear();
for (int i = 0; i < pot_object_list.Count; i++)
{
pot_object_list[i].SetActive(true);
}
for (int i = 0; i < pot_animation_list.Count; i++)
{
pot_animation_list[i].gameObject.SetActive(false);
}
GameDispatcher.Instance.Dispatch(GameMsg.RefreshFlowerCleanBtn);
clean_item_list.Clear();
all_flower_in_pool_list.Clear();
slot_type_list = new List<int>() { -1, -1, -1, -1 };
CanClick = true;
DataMgr.FlowerLevelState.Value = 3;
for (int i = 0; i < pot_object_list.Count; i++)
{
pot_object_list[i].transform.localScale = Vector3.one;
}
for (int i = 0; i < branch_list.Count; i++)
{
SpriteRenderer sr = branch_list[i].GetComponent<SpriteRenderer>();
Color c = sr.color;
c.a = 1f; // 设置透明度为 1(完全不透明)
sr.color = c;
}
CreatFlowerItem();
}
public Transform AddFlowerInTemp(GameObject obj, int type)
{
FlowerUI.start_update = true;
if (FlowerUI.Stop_time >= 5)
{
GameDispatcher.Instance.Dispatch(GameMsg.FlowerHideclickAni);
}
FlowerUI.Stop_time = 0;
all_flower_in_pool_list.Remove(obj);
List<int> indices = new List<int>();
for (int i = 0; i < slot_type_list.Count; i++)
{
if (slot_type_list[i] == type)
{
indices.Add(i);
}
}
int index = -1;
int in_slot_numbers = -1;
if (indices.Count == 1)
{
index = indices[0];
}
else if (indices.Count > 1)
{
for (int i = 0; i < indices.Count; i++)
{
int index_numbres = 0;
if (indices[i] == 0)
{
index_numbres = flower_slot_list0.Count;
}
else if (indices[i] == 1)
{
index_numbres = flower_slot_list1.Count;
}
else if (indices[i] == 2)
{
index_numbres = flower_slot_list2.Count;
}
else if (indices[i] == 3)
{
index_numbres = flower_slot_list3.Count;
}
if (index_numbres > in_slot_numbers)
{
in_slot_numbers = index_numbres;
index = indices[i];
}
}
}
if (index >= 0)
{
if (index == 0 && flower_slot_list0.Count < 3)
{
flower_slot_list0.Add(obj);
obj.GetComponent<SpriteRenderer>().sortingOrder = flower_slot_list0.Count;
return flower_slot_gameobject_list_0[flower_slot_list0.Count - 1].transform;
}
else if (index == 1 && flower_slot_list1.Count < 3)
{
flower_slot_list1.Add(obj);
obj.GetComponent<SpriteRenderer>().sortingOrder = flower_slot_list1.Count;
return flower_slot_gameobject_list_1[flower_slot_list1.Count - 1].transform;
}
else if (index == 2 && flower_slot_list2.Count < 3)
{
flower_slot_list2.Add(obj);
obj.GetComponent<SpriteRenderer>().sortingOrder = flower_slot_list2.Count;
return flower_slot_gameobject_list_2[flower_slot_list2.Count - 1].transform;
}
else if (index == 3 && flower_slot_list3.Count < 3)
{
flower_slot_list3.Add(obj);
obj.GetComponent<SpriteRenderer>().sortingOrder = flower_slot_list3.Count;
return flower_slot_gameobject_list_3[flower_slot_list3.Count - 1].transform;
}
}
int temp_numbers = 0;
Transform transform_ = null;
for (int i = 0; i < 5; i++)
{
if (temp_slot_item_list[i] == null)
{
transform_ = temp_slot_gameobject_list[i].transform;
temp_slot_item_list[i] = obj;
break;
}
}
for (int i = 0; i < 5; i++)
{
if (temp_slot_item_list[i] != null)
{
temp_numbers++;
}
}
if (temp_numbers >= 4)
{
bool next_have = false;
for (int i = 0; i < temp_slot_item_list.Count; i++)
{
if (temp_slot_item_list[i] != null)
{
//if ((index >= 0) && ((temp_slot_item_list[i].GetComponent<ChildItem>().type == next_type_list[index])))
if (next_type_list.Contains(temp_slot_item_list[i].GetComponent<ChildItem>().type) || slot_type_list.Contains(temp_slot_item_list[i].GetComponent<ChildItem>().type))
{
next_have = true;
break;
}
}
}
if (temp_numbers >= 5)
{
CanClick = false;
if (!next_have)
{
if (DataMgr.FlowerLevelState.Value != 0)
{
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.FlowerRemakeUI_Open);
FlowerUI.start_update = false;
}
else
{
float[] ch_array = GameHelper.GetRewardValue(2);
var temp = new SuccessData();
temp.IsWin = false;
temp.ch_number = ch_array[0];
temp.IsLevelSuccess = true;
temp.IsH5Reward = false;
temp.boost_array = GameHelper.GetRewardBoost(2);
temp.level = DataMgr.FlowerLevel.Value;
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.FlowerEndUI_Open, temp);
}
}
}
if (temp_numbers == 4)
{
if (!next_have)
{
GameDispatcher.Instance.Dispatch(GameMsg.FlowerFullTips);
}
}
//////Debug.Log("满了");
}
if (transform_ != null) return transform_;
return null;
}
private int clear_pot_num;
private int all_pot_num;
private List<int> next_type_list = new List<int>()
{
-1,-1,-1,-1
};
public void CheckPot()
{
for (int i = 0; i < 4; i++)
{
int index = i;
List<GameObject> slot_list = null;
if (index == 0) slot_list = flower_slot_list0;
else if (index == 1) slot_list = flower_slot_list1;
else if (index == 2) slot_list = flower_slot_list2;
else if (index == 3) slot_list = flower_slot_list3;
if (slot_list.Count >= 3)
{
int old_type = slot_type_list[index];
slot_type_list[index] = -1;
next_type_list[index] = CreatPotType();
// CanClick = false;
DOVirtual.DelayedCall(0.5f, () =>
{
for (int j = 0; j < 3; j++)
{
slot_list[j].GetComponent<SpriteRenderer>().DOFade(0f, 0.3f);
}
branch_list[index].GetComponent<SpriteRenderer>().DOFade(0f, 0.3f);
});
DOVirtual.DelayedCall(0.9f, () =>
{
int ani_type = old_type + 1;
string ani_name;
if (ani_type < 10) ani_name = "0" + ani_type;
else ani_name = ani_type.ToString();
pot_animation_list[index].gameObject.SetActive(true);
pot_animation_list[index].state.SetAnimation(0, "hua_" + ani_name, false);
pot_animation_list[index].state.Complete += (trackEntry) =>
{
pot_object_list[index].transform.DOScale(new Vector3(0f, 0f, 0f), 0.3f).OnComplete(() =>
{
//////Debug.Log("缩放完成!");
pot_animation_list[index].gameObject.SetActive(false);
if (next_type_list[index] >= 0) branch_list[index].GetComponent<SpriteRenderer>().sprite = pot_image_list[next_type_list[index]];
});
};
});
DOVirtual.DelayedCall(1, () =>
{
for (int j = 0; j < 3; j++)
{
// all_flower_list.Remove(slot_list[j]);
GameObject.Destroy(slot_list[j]);
}
slot_list.Clear();
clear_pot_num += 3;
// CanClick = true;
// //////Debug.Log("新创建的类型是:" + ne);
// pot_object_list[index].SetActive(false);
DOVirtual.DelayedCall(1.3f, () =>
{
//////Debug.Log($"slot_type_list[{index}] = {next_type_list[index]}");
slot_type_list[index] = next_type_list[index];
CheckNewPot(index);
});
});
}
}
if (all_flower_in_pool_list.Count == 0)
{
// bool temp_null = true;
// for (int j = 0; j < temp_slot_item_list.Count; j++)
// {
// if (temp_slot_item_list[j] != null)
// {
// temp_null = false;
// break;
// }
// }
// if (temp_null)
// {
//////Debug.Log("游戏结束");
GameDispatcher.Instance.Dispatch(GameMsg.FlowelSuccess);
// }
}
}
// private int next_type = -1;
void CheckNewPot(int index)
{
if (slot_type_list[index] >= 0)
{
List<GameObject> slot_list = null;
if (index == 0) slot_list = flower_slot_list0;
else if (index == 1) slot_list = flower_slot_list1;
else if (index == 2) slot_list = flower_slot_list2;
else if (index == 3) slot_list = flower_slot_list3;
// pot_object_list[index].SetActive(true);
if (slot_type_list[index] >= 0)
{
pot_object_type_image[index].sprite = flower_image_list[slot_type_list[index]];
}
branch_list[index].GetComponent<SpriteRenderer>().DOFade(1f, 0.1f);
pot_object_list[index].transform.DOScale(new Vector3(1f, 1f, 1f), 0.3f).OnComplete(() =>
{
//////Debug.Log("放大完成!");
});
bool have_temp_ = false;
for (int k = 0; k < temp_slot_item_list.Count; k++)
{
if (temp_slot_item_list[k] != null)
{
ChildItem ChildItem_ = temp_slot_item_list[k].GetComponent<ChildItem>();
if (slot_type_list[index] == ChildItem_.type)
{
if (slot_list.Count < 3)
{
slot_list.Add(temp_slot_item_list[k]);
List<GameObject> target_list = null;
if (index == 0) target_list = flower_slot_gameobject_list_0;
else if (index == 1) target_list = flower_slot_gameobject_list_1;
else if (index == 2) target_list = flower_slot_gameobject_list_2;
else if (index == 3) target_list = flower_slot_gameobject_list_3;
ChildItem_.SetParentAndFly(top_area.transform, target_list[slot_list.Count - 1].transform, 0.5f);
temp_slot_item_list[k].GetComponent<SpriteRenderer>().sortingOrder = slot_list.Count;
temp_slot_item_list[k] = null;
have_temp_ = true;
CanClick = true;
//////Debug.Log("有相同的!!!!!!!!!!!!!");
}
}
}
}
if (slot_list.Count < 3)
{
for (int n = 0; n < clean_item_list.Count; n++)
{
ChildItem ChildItem_ = clean_item_list[n].GetComponent<ChildItem>();
if (ChildItem_.type == slot_type_list[index])
{
if (slot_list.Count >= 3) break;
slot_list.Add(clean_item_list[n]);
List<GameObject> target_list = null;
if (index == 0) target_list = flower_slot_gameobject_list_0;
else if (index == 1) target_list = flower_slot_gameobject_list_1;
else if (index == 2) target_list = flower_slot_gameobject_list_2;
else if (index == 3) target_list = flower_slot_gameobject_list_3;
ChildItem_.SetParentAndFly(top_area.transform, target_list[slot_list.Count - 1].transform, 0.5f);
clean_item_list[n].GetComponent<SpriteRenderer>().sortingOrder = slot_list.Count;
SpriteRenderer render = clean_item_list[n].GetComponent<SpriteRenderer>();
Color c = render.color;
c.a = 1f;
render.color = c;
render.sortingOrder = slot_list.Count;
clean_item_list[n] = null;
have_temp_ = true;
}
}
clean_item_list.RemoveAll(item => item == null);
GameDispatcher.Instance.Dispatch(GameMsg.RefreshFlowerCleanBtn);
}
//////Debug.Log("再次调用检测方法");
if (have_temp_)
{
DOVirtual.DelayedCall(0.3f, () =>
{
CheckPot();
});
}
}
}
public GameObject bubble_parent;
private FlowerMatch flowerMatch;
float creatPotAccuracy;//生成的花盆可以直接被消除的概率
public void AddSlost(int index)
{
//////Debug.Log("解锁。。。。。。。。。。" + index);
if (index == 0)
{
gray_pot_list[0].SetActive(false);
normal_branch_list[0].SetActive(true);
slot_type_list[2] = CreatPotType();
if (slot_type_list[2] >= 0)
{
pot_object_type_image[2].sprite = flower_image_list[slot_type_list[2]];
CheckNewPot(2);
}
else
{
pot_object_list[2].transform.DOScale(new Vector3(0f, 0f, 0f), 0.3f);
}
}
else if (index == 1)
{
gray_pot_list[1].SetActive(false);
normal_branch_list[1].SetActive(true);
slot_type_list[3] = CreatPotType();
if (slot_type_list[3] >= 0)
{
pot_object_type_image[3].sprite = flower_image_list[slot_type_list[3]];
CheckNewPot(3);
}
else
{
pot_object_list[3].transform.DOScale(new Vector3(0f, 0f, 0f), 0.3f);
}
}
// CheckPot();
}
public void UseTipsItem()
{
List<int> canremove_numbers = new List<int>() { 0, 0, 0, 0 };
List<GameObject> canremove_obj = new List<GameObject>();
CanClick = false;
for (int i = 0; i < all_flower_in_pool_list.Count; i++)
{
if (all_flower_in_pool_list[i].transform.position.y < (temp_slot_gameobject_list[0].transform.position.y))//视为可以点击的
{
int item_type = all_flower_in_pool_list[i].GetComponent<ChildItem>().type;
for (int j = 0; j < 4; j++)
{
if (slot_type_list[j] == item_type)
{
canremove_obj.Add(all_flower_in_pool_list[i]);
canremove_numbers[j]++;
break;
}
}
}
}
canremove_obj.Sort((a, b) => a.transform.position.y.CompareTo(b.transform.position.y));
List<int> can_remove_index_array = new List<int>();
for (int i = 0; i < canremove_numbers.Count; i++)
{
if (canremove_numbers[i] >= 3)
{
can_remove_index_array.Add(i);//0123
}
}
int random_index = -1;
if (can_remove_index_array.Count > 0)
{
random_index = can_remove_index_array[UnityEngine.Random.Range(0, can_remove_index_array.Count)];
}
if (random_index >= 0)
{
int tips_type = slot_type_list[random_index];
List<GameObject> slot_list = null;
if (random_index == 0) slot_list = flower_slot_list0;
else if (random_index == 1) slot_list = flower_slot_list1;
else if (random_index == 2) slot_list = flower_slot_list2;
else if (random_index == 3) slot_list = flower_slot_list3;
int slot_count = slot_list.Count;
for (int i = 0; i < canremove_obj.Count; i++)
{
int item_type = canremove_obj[i].GetComponent<ChildItem>().type;
if (item_type == tips_type)
{
if (slot_count >= 3) break;
canremove_obj[i].GetComponent<ChildItem>().OnChildClicked();
slot_count++;
}
}
CheckPot();
DataMgr.FlowerItem0.Value = DataMgr.FlowerItem0.Value - 1;
GameHelper.ShowTips("Randomly clear a target flower");
}
else
{
GameHelper.ShowTips("There are no flowers to remove");
}
DOVirtual.DelayedCall(0.5f, () =>
{
CanClick = true;
});
//////Debug.Log(JsonConvert.SerializeObject(canremove_numbers));
}
public void UseCleanItem()
{
bool is_null = true;
CanClick = false;
for (int i = 0; i < temp_slot_item_list.Count; i++)
{
if (temp_slot_item_list[i] != null)
{
is_null = false;
break;
}
}
if (is_null)
{
GameHelper.ShowTips("There are no flowers to clean");
CanClick = true;
return;
}
clean_animation.gameObject.SetActive(true);
clean_animation.state.SetAnimation(0, "animation", false);
clean_animation.state.Complete += (trackEntry) =>
{
clean_animation.gameObject.SetActive(false);
};
for (int i = 0; i < temp_slot_item_list.Count; i++)
{
if (temp_slot_item_list[i] != null)
{
clean_item_list.Add(temp_slot_item_list[i]);
GameObject temp = temp_slot_item_list[i];
DOVirtual.DelayedCall(1 - 0.1f * i, () =>
{
temp.GetComponent<SpriteRenderer>().DOFade(0f, 0.1f);
});
}
temp_slot_item_list[i] = null;
}
DOVirtual.DelayedCall(1, () =>
{
for (int i = 0; i < clean_item_list.Count; i++)
{
clean_item_list[i].transform.position = clean_pos_object.transform.position;
}
CanClick = true;
});
GameDispatcher.Instance.Dispatch(GameMsg.RefreshFlowerCleanBtn);
DataMgr.FlowerItem1.Value = DataMgr.FlowerItem1.Value - 1;
}
public void UseRefreshItem()
{
CanClick = false;
refresh_animation.gameObject.SetActive(true);
refresh_animation.state.SetAnimation(0, "animation", false);
refresh_animation.state.Complete += (trackEntry) =>
{
refresh_animation.gameObject.SetActive(false);
};
FlyIntoCircle(all_flower_in_pool_list, refresh_animation.gameObject.transform.position, 4, 0.3f);
}
public void FlyIntoCircle(List<GameObject> objs, Vector3 center, float radius, float duration)
{
if (objs == null || objs.Count == 0) return;
int count = objs.Count;
for (int i = 0; i < count; i++)
{
GameObject obj = objs[i];
if (obj == null) continue;
// 记录初始 localPosition
Vector3 startLocalPos = obj.transform.localPosition;
// 找到父物体上的 Rigidbody2D
Rigidbody2D rb2d = obj.transform.parent != null ? obj.transform.parent.GetComponent<Rigidbody2D>() : null;
if (rb2d != null && rb2d.simulated)
{
rb2d.simulated = false;
}
// 随机角度
float angle = UnityEngine.Random.Range(0f, Mathf.PI * 2f);
// 半径用 sqrt(Random.value),保证均匀分布在圆内
float r = radius * Mathf.Sqrt(UnityEngine.Random.value);
// 目标位置:圆心 + 半径 * (cos, sin)
Vector3 targetPos = center + new Vector3(Mathf.Cos(angle), Mathf.Sin(angle), 0) * r;
// DOTween 移动到目标点位
obj.transform.DOMove(targetPos, duration).SetEase(Ease.OutQuad)
.OnComplete(() =>
{
// 停留 0.1 秒后再返回
DOVirtual.DelayedCall(0.3f, () =>
{
// 在返回之前打乱 type 和 sprite
ShuffleItems(objs);
CanClick = true;
obj.transform.DOLocalMove(startLocalPos, duration).SetEase(Ease.InQuad)
.OnComplete(() =>
{
if (rb2d != null && !rb2d.simulated)
{
rb2d.simulated = true;
}
});
});
});
}
}
void ShuffleItems(List<GameObject> objs)
{
// 收集所有 (type, sprite) 对
List<(int type, Sprite sprite)> pairs = new List<(int, Sprite)>();
foreach (var obj in objs)
{
if (obj == null) continue;
ChildItem item = obj.GetComponent<ChildItem>();
SpriteRenderer sr = obj.GetComponent<SpriteRenderer>();
if (item != null && sr != null)
{
pairs.Add((item.type, sr.sprite));
}
}
// 打乱 pairs 列表
System.Random rand = new System.Random();
pairs = pairs.OrderBy(x => rand.Next()).ToList();
// 重新分配,保持对应关系
int index = 0;
foreach (var obj in objs)
{
if (obj == null) continue;
ChildItem item = obj.GetComponent<ChildItem>();
SpriteRenderer sr = obj.GetComponent<SpriteRenderer>();
if (item != null && sr != null)
{
item.type = pairs[index].type;
sr.sprite = pairs[index].sprite;
index++;
}
}
}
public int CreatPotType()
{
float[] Difficulty_array = flowerMatch.Difficulty;
if (((float)clear_pot_num) / all_pot_num > Difficulty_array[1])
{
creatPotAccuracy = flowerMatch.Accuracy[2];
}
else if (((float)clear_pot_num) / all_pot_num > Difficulty_array[0])
{
creatPotAccuracy = flowerMatch.Accuracy[1];
}
else
{
creatPotAccuracy = flowerMatch.Accuracy[0];
}
Debug.Log("flower---------当前完成进度:" + (float)clear_pot_num / all_pot_num);
Debug.Log("flower---------当前击中率:" + creatPotAccuracy);
List<int> canremove_numbers = new List<int>();
List<int> all_numbers = new List<int>();
for (int i = 0; i < all_flower_in_pool_list.Count; i++)
{
if (all_flower_in_pool_list[i].transform.position.y < (temp_slot_gameobject_list[0].transform.position.y))//视为可以点击的
{
canremove_numbers.Add(all_flower_in_pool_list[i].GetComponent<ChildItem>().type);
}
all_numbers.Add(all_flower_in_pool_list[i].GetComponent<ChildItem>().type);
}
for (int i = 0; i < temp_slot_item_list.Count; i++)
{
if (temp_slot_item_list[i] != null)
{
canremove_numbers.Add(temp_slot_item_list[i].GetComponent<ChildItem>().type);
all_numbers.Add(temp_slot_item_list[i].GetComponent<ChildItem>().type);
}
}
for (int i = 0; i < clean_item_list.Count; i++)
{
canremove_numbers.Add(clean_item_list[i].GetComponent<ChildItem>().type);
all_numbers.Add(clean_item_list[i].GetComponent<ChildItem>().type);
}
IEnumerable<IGrouping<int, int>> grouped_all_number = all_numbers.GroupBy(x => x);
List<int> result_pot = new List<int>();
foreach (IGrouping<int, int> g in grouped_all_number)
{
int newCount = g.Count() / 3; // 出现次数除以3
for (int i = 0; i < newCount; i++)
{
result_pot.Add(g.Key);
}
}
for (int i = 0; i < slot_type_list.Count; i++)
{
result_pot.Remove(slot_type_list[i]);
}
for (int i = 0; i < next_type_list.Count; i++)
{
result_pot.Remove(next_type_list[i]);
}
IEnumerable<IGrouping<int, int>> grouped = canremove_numbers.GroupBy(x => x);
System.Random rand = new System.Random();
int randomMore = -1;
IEnumerable<IGrouping<int, int>> moreThanThreeGroups = grouped.Where(g => g.Count() >= 3);
List<int> moreThanThreeKeys = moreThanThreeGroups.Select(g => g.Key).ToList();
if (moreThanThreeKeys.Count > 0)
{
int index = rand.Next(moreThanThreeKeys.Count);
randomMore = moreThanThreeKeys[index];
}
int randomLess = -1;
IEnumerable<IGrouping<int, int>> lessThanThreeGroups = grouped.Where(g => g.Count() < 3);
List<int> lessThanThreeKeys = lessThanThreeGroups.Select(g => g.Key).ToList();
if (lessThanThreeKeys.Count > 0)
{
int index = rand.Next(lessThanThreeKeys.Count);
randomLess = lessThanThreeKeys[index];
}
// Console.WriteLine("随机选取的 ≥3 元素: " + randomMore);
// Console.WriteLine("随机选取的 <3 元素: " + randomLess);
System.Random randdom_ = new System.Random();
double value = randdom_.NextDouble();
if (value < creatPotAccuracy)//生成可以消除的
{
if (result_pot.Count <= 0) return -1;
Debug.Log("flower---------当前击中了");
if (creatPotAccuracy < 0)//目前显示出的没有可以消除的了,随机一个出来
{
Debug.Log("flower---------当前没有可以消除的元素,随机一个");
return result_pot[UnityEngine.Random.Range(0, result_pot.Count)];
}
if (result_pot.Contains(randomMore))
{
Debug.Log("flower---------当前有可以消除的元素,生成一个");
return randomMore;
}
else
{
Debug.Log("flower---------当前没有可以消除的元素,随机一个");
return result_pot[UnityEngine.Random.Range(0, result_pot.Count)];
}
}
else
{
if (result_pot.Count <= 0) return -1;
Debug.Log("flower---------当前没有击中");
if (randomLess < 0)
{
Debug.Log("flower---------当前没有不能消除的元素,随机一个");
return result_pot[UnityEngine.Random.Range(0, result_pot.Count)];
}
if (result_pot.Contains(randomLess))
{
Debug.Log("flower---------生成不能消除的元素");
return randomLess;
}
else
{
Debug.Log("flower---------当前没有不能消除的元素,随机一个");
return result_pot[UnityEngine.Random.Range(0, result_pot.Count)];
}
}
}
private bool show_finger = false;
private GameObject finger_object;
public void DestoryFinger()
{
show_finger = false;
Destroy(finger_object);
}
public void CreatFlowerItem()
{
int level = DataMgr.FlowerLevel.Value;
//////Debug.Log(ConfigSystem.GetConfig<FlowerMatch>()[level]);
flowerMatch = ConfigSystem.GetConfig<FlowerMatch>()[level];
#if UNITY_EDITOR
// flowerMatch.ElementCount = 21;
#endif
List<int> elements = Allocate(flowerMatch.ElementCount, 12, flowerMatch.ElementTypes);
//////Debug.Log(JsonConvert.SerializeObject(elements));
// 输出示例: [3, 7, 7, 5, 2, 2, 9, 9, 9, ...] 共 30 个
// 每个数字代表种类编号,数量分布是两个 6、两个 9
all_pot_num = flowerMatch.ElementCount;
int[] counts = Allocate(flowerMatch.ElementCount, (float)flowerMatch.TypeDistribution / 100);
//////Debug.Log(JsonConvert.SerializeObject(counts));
// 1. 收集所有要生成的对象
List<GameObject> toSpawn = new List<GameObject>();
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < counts[i]; j++)
{
toSpawn.Add(bubble_prefab_list[i]);
}
}
// 2. 打乱顺序
toSpawn = toSpawn.OrderBy(x => UnityEngine.Random.value).ToList();
//////Debug.Log(JsonConvert.SerializeObject(slot_type_list) + "??????????????8");
// 3. 按顺序生成并摆放
Vector3 basePos = bubble_parent.transform.position;
float xSpacing = 20f;
float ySpacing = 20f;
int maxPerRow = 3;
int image_index = 0;
for (int counter = 0; counter < toSpawn.Count; counter++)
{
int row = counter / maxPerRow;
int col = counter % maxPerRow;
Vector3 pos = basePos + new Vector3(col * xSpacing, row * ySpacing, 0);
GameObject piece = Instantiate(toSpawn[counter], pos, Quaternion.identity, bubble_parent.transform);
// 获取所有子物体的 SpriteRenderer(排除自己)
SpriteRenderer[] childRenderers = piece.transform.Cast<Transform>() // 遍历直接子物体
.Select(t => t.GetComponent<SpriteRenderer>()) // 获取子物体上的 SpriteRenderer
.Where(r => r != null) // 过滤掉没有 SpriteRenderer 的
.ToArray();
// 遍历使用
for (int i = 0; i < childRenderers.Length; i++)
{
childRenderers[i].sprite = flower_image_list[elements[image_index]];
all_flower_in_pool_list.Add(childRenderers[i].gameObject);
// 获取对应子物体上的脚本
ChildItem script = childRenderers[i].gameObject.GetComponent<ChildItem>();
script.type = elements[image_index]; // 举例调用
image_index++;
}
if (DataMgr.FlowerLevel.Value == 0 && counter == 0)
{
GameObject spinePrefab = Resources.Load<GameObject>("flower/effect/guide/guide");
//////Debug.Log(piece.transform.Find("child_0"));
finger_object = Instantiate(spinePrefab, piece.transform.Find("child_0").transform);
finger_object.transform.rotation = Quaternion.identity;
SkeletonAnimation skeletonAnimation = finger_object.transform.Find("ani_parent").GetComponent<SkeletonAnimation>();
skeletonAnimation.state.SetAnimation(0, "animation", true);
show_finger = true;
}
Rigidbody2D rb = piece.GetComponent<Rigidbody2D>();
if (rb != null)
{
rb.angularVelocity = UnityEngine.Random.Range(-200f, 200f);
}
}
slot_type_list[0] = CreatPotType();
branch_list[0].GetComponent<SpriteRenderer>().sprite = pot_image_list[slot_type_list[0]];
pot_object_type_image[0].sprite = flower_image_list[slot_type_list[0]];
slot_type_list[1] = CreatPotType();
if (slot_type_list[1] >= 0)
{
pot_object_type_image[1].sprite = flower_image_list[slot_type_list[1]];
branch_list[1].GetComponent<SpriteRenderer>().sprite = pot_image_list[slot_type_list[1]];
}
gray_pot_list[0].SetActive(true);
gray_pot_list[1].SetActive(true);
normal_branch_list[0].SetActive(false);
normal_branch_list[1].SetActive(false);
}
public static List<int> Allocate(int total, int kinds, int choose)
{
if (total % 3 != 0)
throw new ArgumentException("总数必须是3的倍数");
System.Random rand = new System.Random();
// 随机选出指定数量的种类(范围 0..kinds-1)
var chosen = Enumerable.Range(0, kinds) // 改成从 0 开始
.OrderBy(_ => rand.Next())
.Take(choose)
.ToArray();
//////Debug.Log("当前随机出的花的种类" + JsonConvert.SerializeObject(chosen));
// 以3为单位来分配
int units = total / 3; // 总共多少个“单位”
int basePerKind = units / choose; // 每种基础单位数
int remainderUnits = units % choose; // 余下的单位数
// 分配数量
int[] counts = new int[choose];
for (int i = 0; i < choose; i++) counts[i] = basePerKind * 3;
for (int i = 0; i < remainderUnits; i++) counts[i] += 3;
// 打乱分配顺序
counts = counts.OrderBy(_ => rand.Next()).ToArray();
// 展开成元素列表
var result = new List<int>(total);
for (int i = 0; i < choose; i++)
{
for (int j = 0; j < counts[i]; j++)
{
result.Add(chosen[i]);
}
}
// 打乱元素顺序
result = result.OrderBy(_ => rand.Next()).ToList();
return result;
}
////////////////////计算方法
///
// 返回各类型道具数量:[type1, type2, type3, type4, type5]
// N:总元素数量(必须精确满足)
// rBig:大道具占比目标(按“道具数量”定义)
// ratioTolerance:容错范围(例如 0.05 表示 ±5%)
public static int[] Allocate(int N, float rBig, float ratioTolerance = 0.05f, int maxIters = 10000)
{
if (N < 0) throw new ArgumentOutOfRangeException(nameof(N));
if (rBig < 0f || rBig > 1f) throw new ArgumentOutOfRangeException(nameof(rBig));
if (ratioTolerance < 0f || ratioTolerance > 1f) throw new ArgumentOutOfRangeException(nameof(ratioTolerance));
// 容量: 1..5
int[] caps = { 1, 2, 3, 4, 5 };
// 小/大索引集合
int[] smallIdx = { 0, 1, 2 };
int[] bigIdx = { 3, 4 };
// 1) 基于目标占比估算平均容量,估算总道具数 M
float avgSmall = (1 + 2 + 3) / 3f; // 2.0
float avgBig = (4 + 5) / 2f; // 4.5
float avgCap = (1f - rBig) * avgSmall + rBig * avgBig;
int M = Math.Max(1, (int)Math.Round(N / avgCap));
// 2) 先按占比分道具数量,再组内平均
int bigCount = (int)Math.Round(M * rBig);
int smallCount = M - bigCount;
int[] counts = new int[5];
EvenSplitInto(counts, smallIdx, smallCount);
EvenSplitInto(counts, bigIdx, bigCount);
// 3) 容量校正:保证 sum(caps[i]*counts[i]) == N
int S = TotalCapacity(counts, caps);
// 贪心迭代:每次增加/减少一个道具,选择对“容量差”和“占比偏差”综合更优的类型
for (int iter = 0; iter < maxIters && S != N; iter++)
{
int sumProps = counts.Sum();
float currentBigRatio = sumProps > 0 ? (counts[3] + counts[4]) / (float)sumProps : 0f;
float ratioError = Math.Abs(currentBigRatio - rBig);
// 我们构造一个候选集合:当 S < N 需要增加一个道具;当 S > N 需要减少一个道具(数量必须 >0)
bool needAdd = S < N;
int diff = Math.Abs(N - S);
// 评分函数:优先弥补容量差,同时尽量减小占比偏差
// score 越小越好
double bestScore = double.PositiveInfinity;
int bestType = -1;
for (int i = 0; i < 5; i++)
{
if (!needAdd && counts[i] == 0) continue; // 不能减到负数
// 试探性变更
int dProps = needAdd ? +1 : -1;
int newSumProps = sumProps + dProps;
if (newSumProps <= 0) continue;
int newS = S + (needAdd ? +caps[i] : -caps[i]);
// 新的大道具比例
int newBigCount = counts[3] + counts[4];
if (i == 3 || i == 4) newBigCount += needAdd ? 1 : -1;
float newBigRatio = newBigCount / (float)newSumProps;
// 容量误差与占比误差
int newDiff = Math.Abs(N - newS);
float newRatioError = Math.Abs(newBigRatio - rBig);
// 打分:容量误差权重高,细微平衡占比误差
// 你可以根据需要调整权重 wRatio 以强化/弱化占比优先级。
const double wRatio = 0.5; // 越大越重视靠近占比
double score = newDiff + wRatio * Math.Max(0f, newRatioError - ratioError);
// 为了平滑地贴近 diff,也考虑容量步长的合适性(越接近 diff 越好)
score += 0.01 * Math.Abs(caps[i] - diff);
if (score < bestScore)
{
bestScore = score;
bestType = i;
}
}
if (bestType < 0)
break; // 没有可行动作(理论上不应该发生),保护性退出
// 应用最佳动作
if (needAdd)
{
counts[bestType]++;
S += caps[bestType];
}
else
{
counts[bestType]--;
S -= caps[bestType];
}
}
// 4) 若仍未达成精确容量(极少数边缘案例),回退到纯容量贪心补齐
if (S != N)
{
// 简单补齐:优先用 5/4 增加或用 1/2 减少
if (S < N)
{
S += GreedyCapacityFix(counts, caps, N - S, add: true);
}
else
{
S -= GreedyCapacityFix(counts, caps, S - N, add: false);
}
}
// 5) 可选:如果你希望严格将大道具比例限制在 [rBig ± ratioTolerance] 范围,
// 可以在此做一次微调,但必须保持 S == N(通过“等容量替换”实现)。
// 示例策略:在小/大组内等容量交换(比如用一个3替代一个1+2),保证容量不变只改比例。
// 为简洁,这里先不给出额外等容量替换;若需要,我可以加一个安全的交换器。
return counts;
}
private static void EvenSplitInto(int[] counts, int[] indices, int total)
{
if (indices.Length == 0 || total <= 0) return;
int q = total / indices.Length;
int r = total % indices.Length;
for (int i = 0; i < indices.Length; i++) counts[indices[i]] += q;
for (int i = 0; i < r; i++) counts[indices[i]] += 1; // 轮询余数
}
private static int TotalCapacity(int[] counts, int[] caps)
{
int sum = 0;
for (int i = 0; i < counts.Length; i++) sum += counts[i] * caps[i];
return sum;
}
// 只考虑容量差的贪心修正(作为兜底)
private static int GreedyCapacityFix(int[] counts, int[] caps, int diff, bool add)
{
int changed = 0;
if (add)
{
// 优先用高容量填补
for (int i = caps.Length - 1; i >= 0 && changed < diff; i--)
{
int step = caps[i];
int canDo = (diff - changed) / step;
if (canDo <= 0) continue;
counts[i] += canDo;
changed += canDo * step;
}
// 若仍有剩余,用最小步长补到位
for (int i = caps.Length - 1; i >= 0 && changed < diff; i--)
{
counts[i] += 1;
changed += caps[i];
}
}
else
{
// 优先从低容量减
for (int i = 0; i < caps.Length && changed < diff; i++)
{
int step = caps[i];
int canDo = Math.Min(counts[i], (diff - changed) / step);
if (canDo <= 0) continue;
counts[i] -= canDo;
changed += canDo * step;
}
// 若仍有剩余,从最低容量逐个减
for (int i = 0; i < caps.Length && changed < diff; i++)
{
if (counts[i] <= 0) continue;
counts[i] -= 1;
changed += caps[i];
i--; // 继续在同一类型尝试
}
}
return changed;
}
void AlignObjectTop(GameObject obj, Camera cam)
{
// 相机顶部的世界坐标
float topY = cam.transform.position.y + cam.orthographicSize;
// 物体一半高度
float objHalfHeight = 50f;
Vector3 pos = obj.transform.position;
pos.y = topY - objHalfHeight;
obj.transform.position = pos;
}
void FitObjectToScreenWidth(GameObject obj, Camera cam)
{
float worldWidth = 2f * cam.orthographicSize * cam.aspect;
float objWidth = obj.GetComponent<SpriteRenderer>().bounds.size.x;
float scale = worldWidth / objWidth;
obj.transform.localScale = new Vector3(scale, scale, 1f);
}
void AlignObjectBottom(GameObject obj, Camera cam)
{
float bottomY = cam.transform.position.y - cam.orthographicSize;
float objHalfHeight = obj.GetComponent<SpriteRenderer>().bounds.extents.y;
Vector3 pos = obj.transform.position;
pos.y = bottomY + objHalfHeight + 12;
obj.transform.position = pos;
}
}