ro-webgl/Assets/Src/UI/UICore/Components/MyDanmuPlayer.cs

247 lines
8.9 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.Serialization;
public class DanmuItemData
{
public bool isMe;
public string head;
public string content;
}
public class MyDanmuPlayer : MonoBehaviour
{
[SerializeField] private float _speed = 2.0f;
[SerializeField] private float _danmuSpacing = 100.0f;
[SerializeField] private float _trackSpacing = 30.0f;
[SerializeField] private float _wordWidth = 40.0f;
private GameObject _danmuItemTpl;
private Transform _danmuScreen;
private Transform _danmuPool;
private Queue<DanmuItemData> _contentQueue = new Queue<DanmuItemData>();
private Queue<DanmuItemData> _myselfContentQueue = new Queue<DanmuItemData>();
private Action _onPlayFinished;
private Action _onPlayNtf;
private List<Transform> _danmuPoolItems = new List<Transform>();
private List<List<RectTransform>> _trackDanmuItemsList = new List<List<RectTransform>>();
private int _lastPlayFinishCount = 0;
private void Awake()
{
}
// Start is called before the first frame update
void Start()
{
_danmuItemTpl = transform.Find("DanmuItemTpl").gameObject;
_danmuScreen = transform.Find("DanmuScreen");
_danmuPool = transform.Find("DanmuPool");
var danmuHeight = _danmuItemTpl.GetComponent<RectTransform>().rect.height;
var screenHeight = _danmuScreen.GetComponent<RectTransform>().rect.height;
var screenRectTransform = _danmuScreen.GetComponent<RectTransform>();
Debug.Log("screenHeight: " + screenHeight);
int trackCount = (int)(screenHeight/(danmuHeight+_trackSpacing));
for (int i = 0; i < trackCount*5; i++)
{
var danmuItem = Instantiate(_danmuItemTpl, _danmuPool);
danmuItem.SetActive(false);
_danmuPoolItems.Add(danmuItem.transform);
}
}
IEnumerator StartTrack(List<RectTransform> currDanmuItems, Vector2 startPos, Vector2 endPos)
{
while (true)
{
float maxX = 0;
for (int i = 0; i < currDanmuItems.Count; i++)
{
currDanmuItems[i].anchoredPosition -= new Vector2(_speed, 0);
var x = currDanmuItems[i].anchoredPosition.x + currDanmuItems[i].rect.width/2;
if (x > maxX)
{
maxX = x;
}
}
if (currDanmuItems.Count > 0)
{
if (currDanmuItems[0].anchoredPosition.x + currDanmuItems[0].rect.width < endPos.x-20)
{
_FreeDanmuItem(currDanmuItems[0]);
currDanmuItems.RemoveAt(0);
if (_CheckPlayFinish() && _onPlayFinished != null)
{
Debug.Log("[MyDanmuPlayer] _onPlayFinished");
_onPlayFinished?.Invoke();
_onPlayFinished = null;
}
if (_contentQueue.Count < _lastPlayFinishCount && _onPlayNtf != null)
{
Debug.Log("[MyDanmuPlayer] _onPlayNtf");
_onPlayNtf?.Invoke();
_onPlayNtf = null;
}
}
}
if (startPos.x - maxX > (_danmuSpacing + UnityEngine.Random.Range(0, 200)))
{
DanmuItemData danmuItemData = null;
if (_myselfContentQueue.Count > 0)
{
danmuItemData = _myselfContentQueue.Dequeue();
}
else if (_contentQueue.Count > 0)
{
danmuItemData = _contentQueue.Dequeue();
}
if (danmuItemData != null)
{
var danmuItem = _AllocDanmuItem();
var danmuItemRect = danmuItem.GetComponent<RectTransform>();
danmuItem.SetParent(_danmuScreen);
danmuItemRect.anchoredPosition = startPos;
danmuItemRect.sizeDelta = new Vector2(danmuItemData.content.Length*_wordWidth, danmuItemRect.sizeDelta.y);
danmuItem.Find("Text").gameObject.SetActive(!danmuItemData.isMe);
danmuItem.Find("Text").GetComponent<TextMeshProUGUI>().text = danmuItemData.content;
danmuItem.Find("MeText").gameObject.SetActive(danmuItemData.isMe);
danmuItem.Find("MeText").GetComponent<TextMeshProUGUI>().text = danmuItemData.content;
currDanmuItems.Add(danmuItemRect);
}
}
yield return null;
}
}
bool _CheckPlayFinish()
{
bool isAllPlayFinished = true;
if (_contentQueue.Count == 0 && _myselfContentQueue.Count == 0)
{
for (int i = 0; i < _trackDanmuItemsList.Count; i++)
{
if (_trackDanmuItemsList[i].Count > 0)
{
isAllPlayFinished = false;
break;
}
}
}
else
{
isAllPlayFinished = false;
}
return isAllPlayFinished;
}
public void ResetPlayer()
{
Debug.Log("[MyDanmuPlayer] _ResetPlayer");
_contentQueue.Clear();
_myselfContentQueue.Clear();
for (int i = 0; i < _trackDanmuItemsList.Count; i++)
{
var trackDanmuItems = _trackDanmuItemsList[i];
for (int j = 0; j < trackDanmuItems.Count; j++)
{
_FreeDanmuItem(trackDanmuItems[j]);
}
trackDanmuItems.Clear();
}
_trackDanmuItemsList.Clear();
StopAllCoroutines();
StartCoroutine(_DelayReset());
}
IEnumerator _DelayReset()
{
yield return null;
_danmuItemTpl = transform.Find("DanmuItemTpl").gameObject;
_danmuScreen = transform.Find("DanmuScreen");
var danmuHeight = _danmuItemTpl.GetComponent<RectTransform>().rect.height;
var screenHeight = _danmuScreen.GetComponent<RectTransform>().rect.height;
var screenRectTransform = _danmuScreen.GetComponent<RectTransform>();
int trackCount = (int)(screenHeight/(danmuHeight+_trackSpacing));
int offset = (int)screenHeight % (int)(danmuHeight+_trackSpacing);
for (int i = trackCount-1; i >= 0; i--)
{
var danmuPosY = -offset/2 + (i+1) * (danmuHeight + _trackSpacing) - screenRectTransform.rect.height/2;
var startPos = new Vector2(screenRectTransform.rect.width, danmuPosY);
var endPos = new Vector2(0, danmuPosY);
Debug.Log("[MyDanmuPlayer] Start Track " + startPos.ToString());
List<RectTransform> currDanmuItems = new List<RectTransform>();
_trackDanmuItemsList.Add(currDanmuItems);
StartCoroutine(StartTrack(currDanmuItems, startPos, endPos));
}
}
public void Play(string[] contents, int lastPlayFinishCount, Action onPlayNtf, Action onPlayFinished)
{
StartCoroutine(_DelayPlay(contents, lastPlayFinishCount, onPlayNtf, onPlayFinished));
}
IEnumerator _DelayPlay(string[] contents, int lastPlayFinishCount, Action onPlayNtf, Action onPlayFinished)
{
yield return null;
yield return null;
for (int i = 0; i < contents.Length; i++)
{
_contentQueue.Enqueue(new DanmuItemData(){isMe = false, head = "", content = contents[i]});
}
_lastPlayFinishCount = lastPlayFinishCount;
_onPlayNtf = onPlayNtf;
_onPlayFinished = onPlayFinished;
}
public void PlayMySelf(string content)
{
_myselfContentQueue.Enqueue(new DanmuItemData(){isMe = true, head = "", content = content});
}
// [ContextMenu("TestPlayMySelf")]
// void TestPlayMySelf()
// {
// PlayMySelf("这是我的弹幕,哈哈哈哈哈!!!");
// }
//
// [ContextMenu("TestPlay")]
// void TestPlay()
// {
// var contents = new[] {"AAAAA", "BBBBB", "CCCCC", "DDDDD", "EEEEEE", "FFFFFF", "AAAAA", "BBBBB", "CCCCC", "DDDDD", "EEEEEE", "FFFFFF"};
// Play(contents, 0, () =>
// {
// Debug.Log("TestPlay Over");
// });
// }
Transform _AllocDanmuItem()
{
if (_danmuPoolItems.Count > 0)
{
var danmuItem = _danmuPoolItems[_danmuPoolItems.Count-1];
_danmuPoolItems.RemoveAt(_danmuPoolItems.Count-1);
danmuItem.gameObject.SetActive(true);
return danmuItem;
}
else
{
var danmuItemGo = Instantiate(_danmuItemTpl, _danmuPool);
danmuItemGo.SetActive(true);
return danmuItemGo.transform;
}
}
void _FreeDanmuItem(Transform danmuItem)
{
danmuItem.SetParent(_danmuPool);
danmuItem.gameObject.SetActive(false);
_danmuPoolItems.Add(danmuItem);
}
}