Files

1344 lines
49 KiB
C#
Raw Permalink Normal View History

2026-07-06 16:27:14 +08:00
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;
}
}