1344 lines
49 KiB
C#
1344 lines
49 KiB
C#
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);//0,1,2,3
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
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;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
}
|