1114 lines
27 KiB
C#
1114 lines
27 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
public class BeadDrawer : MonoBehaviour
|
|
{
|
|
private enum ExitSide
|
|
{
|
|
None = 0,
|
|
Left = 1,
|
|
Right = 2,
|
|
Top = 3,
|
|
Bottom = 4
|
|
}
|
|
|
|
public static BeadDrawer instance;
|
|
|
|
public GameObject beadPrefab;
|
|
|
|
public Collider2D drawArea;
|
|
|
|
public AudioClip beadSound;
|
|
|
|
public AudioSource myAudioSource;
|
|
|
|
public float minPitch = 0.5f;
|
|
|
|
public float maxPitch = 2f;
|
|
|
|
[SerializeField]
|
|
private float constantDistance = 0.01f;
|
|
|
|
[SerializeField]
|
|
private float beadSizeMultiplier = 5.5f;
|
|
|
|
[SerializeField]
|
|
private float movingPlatformTimeLimit = 5f;
|
|
|
|
private Vector3 previousPoint;
|
|
|
|
private GameObject parentObject;
|
|
|
|
private bool isDrawing;
|
|
|
|
private int beadsSpawned;
|
|
|
|
public bool cantHitBorder;
|
|
|
|
private Camera mainCamera;
|
|
|
|
private bool IsGameStarted;
|
|
|
|
private bool IsLineDrawn;
|
|
|
|
private PhysicsMaterial2D linePhysicsMat;
|
|
|
|
private bool hasMoved;
|
|
|
|
private bool _drawingBlocked;
|
|
|
|
private bool _externalDragStart;
|
|
|
|
private float lastVibrateTime;
|
|
|
|
private const float vibrateInterval = 0.1f;
|
|
|
|
private Vector2 touchDownScreenPos;
|
|
|
|
private bool touchDownRecorded;
|
|
|
|
private const float minMovePixels = 12f;
|
|
|
|
private ExitSide currentExitSide;
|
|
|
|
private float exitLockValue;
|
|
|
|
private float lastBeadTime = -1f;
|
|
|
|
private const float soundPauseDelay = 0.05f;
|
|
|
|
private int _arrayCapacity = 3000;
|
|
|
|
private Mesh drawMesh;
|
|
|
|
private MeshFilter meshFilter;
|
|
|
|
private MeshRenderer meshRenderer;
|
|
|
|
private Material beadMaterial;
|
|
|
|
private Vector3[] _verts;
|
|
|
|
private Vector2[] _uvs;
|
|
|
|
private int[] _tris;
|
|
|
|
private int _quadCount;
|
|
|
|
private Vector2 uvBL;
|
|
|
|
private Vector2 uvBR;
|
|
|
|
private Vector2 uvTR;
|
|
|
|
private Vector2 uvTL;
|
|
|
|
private float beadHalfSize;
|
|
|
|
private Vector3[] _allBeadPosArr;
|
|
|
|
private int _beadPosCount;
|
|
|
|
private float _constantDistanceSq;
|
|
|
|
private float _invConstantDistance;
|
|
|
|
private Vector3 _boundsMin;
|
|
|
|
private Vector3 _boundsMax;
|
|
|
|
[SerializeField]
|
|
[Header("Draw Blocking")]
|
|
private LayerMask drawBlockingLayers;
|
|
|
|
[Header("Tool Level")]
|
|
public bool isToolLevel;
|
|
|
|
public Rigidbody2D[] toolRigidbodies;
|
|
|
|
public bool testMode;
|
|
|
|
private const int COLLIDER_CHUNK_SIZE = 60;
|
|
|
|
private const int MAX_COLLIDER_POINTS = 120;
|
|
|
|
private readonly List<EdgeCollider2D> _colliderPool = new List<EdgeCollider2D>();
|
|
|
|
private int _activeChunks;
|
|
|
|
public float LinemovedThreshold = 0.1f;
|
|
|
|
public int DrawnBeadCount => _beadPosCount;
|
|
|
|
public Rigidbody2D LineRigidbody => (parentObject != null) ? parentObject.GetComponent<Rigidbody2D>() : null;
|
|
|
|
private void Awake()
|
|
{
|
|
instance = this;
|
|
EyeBallTracker.LookTarget = null;
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
parentObject = UnityEngine.Object.Instantiate(GameManager.Instance.lineParentTr);
|
|
if (parentObject != null)
|
|
{
|
|
EdgeCollider2D component = parentObject.GetComponent<EdgeCollider2D>();
|
|
if (component != null)
|
|
{
|
|
component.enabled = false;
|
|
_colliderPool.Add(component);
|
|
}
|
|
}
|
|
mainCamera = Camera.main;
|
|
beadHalfSize = constantDistance * beadSizeMultiplier * 0.5f;
|
|
GameObject gameObject = new GameObject("BeadMesh");
|
|
gameObject.transform.SetParent(parentObject.transform, false);
|
|
meshFilter = gameObject.AddComponent<MeshFilter>();
|
|
meshRenderer = gameObject.AddComponent<MeshRenderer>();
|
|
_verts = new Vector3[_arrayCapacity * 4];
|
|
_uvs = new Vector2[_arrayCapacity * 4];
|
|
_tris = new int[_arrayCapacity * 6];
|
|
_allBeadPosArr = new Vector3[_arrayCapacity];
|
|
for (int i = 0; i < _arrayCapacity; i++)
|
|
{
|
|
_tris[i * 6] = i * 4;
|
|
_tris[i * 6 + 1] = i * 4 + 2;
|
|
_tris[i * 6 + 2] = i * 4 + 1;
|
|
_tris[i * 6 + 3] = i * 4;
|
|
_tris[i * 6 + 4] = i * 4 + 3;
|
|
_tris[i * 6 + 5] = i * 4 + 2;
|
|
}
|
|
_constantDistanceSq = constantDistance * constantDistance;
|
|
_invConstantDistance = 1f / constantDistance;
|
|
drawMesh = new Mesh();
|
|
drawMesh.MarkDynamic();
|
|
meshFilter.mesh = drawMesh;
|
|
if (beadPrefab != null)
|
|
{
|
|
SpriteRenderer component2 = beadPrefab.GetComponent<SpriteRenderer>();
|
|
if (component2 != null)
|
|
{
|
|
meshRenderer.sortingLayerID = component2.sortingLayerID;
|
|
meshRenderer.sortingOrder = component2.sortingOrder;
|
|
}
|
|
}
|
|
SetupBeadMaterial(PersistableData.Instance.shopItemSprite[PersistableData.Instance.itemsData.currentShopItemId]);
|
|
}
|
|
|
|
private void SetupBeadMaterial(Sprite sprite)
|
|
{
|
|
if (sprite == null)
|
|
{
|
|
return;
|
|
}
|
|
if (beadMaterial == null)
|
|
{
|
|
beadMaterial = new Material(Shader.Find("Sprites/Default"));
|
|
}
|
|
beadMaterial.mainTexture = sprite.texture;
|
|
beadMaterial.color = new Color(0f, 0f, 0f, 1f);
|
|
meshRenderer.material = beadMaterial;
|
|
Rect textureRect = sprite.textureRect;
|
|
Texture2D texture = sprite.texture;
|
|
uvBL = new Vector2(textureRect.x / (float)texture.width, textureRect.y / (float)texture.height);
|
|
uvTR = new Vector2((textureRect.x + textureRect.width) / (float)texture.width, (textureRect.y + textureRect.height) / (float)texture.height);
|
|
uvBR = new Vector2((textureRect.x + textureRect.width) / (float)texture.width, textureRect.y / (float)texture.height);
|
|
uvTL = new Vector2(textureRect.x / (float)texture.width, (textureRect.y + textureRect.height) / (float)texture.height);
|
|
if (_verts != null)
|
|
{
|
|
RefillUVArray();
|
|
}
|
|
}
|
|
|
|
private void RefillUVArray()
|
|
{
|
|
for (int i = 0; i < _arrayCapacity; i++)
|
|
{
|
|
_uvs[i * 4] = uvBL;
|
|
_uvs[i * 4 + 1] = uvBR;
|
|
_uvs[i * 4 + 2] = uvTR;
|
|
_uvs[i * 4 + 3] = uvTL;
|
|
}
|
|
}
|
|
|
|
public void UpdatePooledBeadSprite(Sprite newSprite)
|
|
{
|
|
SetupBeadMaterial(newSprite);
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
GameManager.OnGameStarts += OnGameStarts;
|
|
GameManager.OnLineDrawingComplete += IsLineDrawingComplete;
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
GameManager.OnGameStarts -= OnGameStarts;
|
|
GameManager.OnLineDrawingComplete -= IsLineDrawingComplete;
|
|
}
|
|
|
|
private void OnGameStarts()
|
|
{
|
|
linePhysicsMat = GameManager.Instance.lineDrawPhysics2dMat;
|
|
IsGameStarted = true;
|
|
}
|
|
|
|
private void IsLineDrawingComplete()
|
|
{
|
|
IsLineDrawn = true;
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (!IsGameStarted)
|
|
{
|
|
return;
|
|
}
|
|
if (AppConstants.IsDialogueOpened)
|
|
{
|
|
return;
|
|
}
|
|
if (AppConstants.IsAnyPanelOpen)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (Input.touchCount > 0)
|
|
{
|
|
HandleTouchInput();
|
|
}
|
|
else
|
|
{
|
|
HandleMouseInput();
|
|
}
|
|
if (!hasMoved)
|
|
{
|
|
return;
|
|
}
|
|
if (myAudioSource == null)
|
|
{
|
|
return;
|
|
}
|
|
if (!AppConstants.isSound)
|
|
{
|
|
return;
|
|
}
|
|
if (isDrawing && Time.time - lastBeadTime < soundPauseDelay)
|
|
{
|
|
if (!myAudioSource.isPlaying)
|
|
{
|
|
myAudioSource.UnPause();
|
|
}
|
|
}
|
|
else if (myAudioSource.isPlaying)
|
|
{
|
|
myAudioSource.Pause();
|
|
}
|
|
}
|
|
|
|
private void HandleMouseInput()
|
|
{
|
|
if (Input.GetMouseButtonDown(0))
|
|
{
|
|
touchDownScreenPos = Input.mousePosition;
|
|
touchDownRecorded = true;
|
|
return;
|
|
}
|
|
if (Input.GetMouseButton(0))
|
|
{
|
|
if (IsLineDrawn)
|
|
{
|
|
return;
|
|
}
|
|
bool flag = IsMouseInsideDrawArea();
|
|
bool flag2 = isDrawing;
|
|
if (flag)
|
|
{
|
|
if (!flag2)
|
|
{
|
|
Vector3 mousePosition = Input.mousePosition;
|
|
float num = mousePosition.x - touchDownScreenPos.x;
|
|
float num2 = mousePosition.y - touchDownScreenPos.y;
|
|
if (Mathf.Sqrt(num * num + num2 * num2) < minMovePixels)
|
|
{
|
|
return;
|
|
}
|
|
StartDrawing();
|
|
}
|
|
if (currentExitSide != ExitSide.None)
|
|
{
|
|
currentExitSide = ExitSide.None;
|
|
}
|
|
ContinueDrawing();
|
|
return;
|
|
}
|
|
if (!flag2)
|
|
{
|
|
return;
|
|
}
|
|
if (cantHitBorder)
|
|
{
|
|
StopDrawing();
|
|
return;
|
|
}
|
|
DetectExitSide(Input.mousePosition);
|
|
ContinueDrawing();
|
|
return;
|
|
}
|
|
if (Input.GetMouseButtonUp(0))
|
|
{
|
|
bool isLineDrawn = IsLineDrawn;
|
|
touchDownRecorded = false;
|
|
currentExitSide = ExitSide.None;
|
|
if (isLineDrawn)
|
|
{
|
|
return;
|
|
}
|
|
if (!isDrawing)
|
|
{
|
|
return;
|
|
}
|
|
if (beadsSpawned >= 1)
|
|
{
|
|
if (GameManager.OnLineDrawingComplete != null)
|
|
{
|
|
GameManager.OnLineDrawingComplete();
|
|
}
|
|
changeAction();
|
|
}
|
|
StopDrawing();
|
|
}
|
|
}
|
|
|
|
private void HandleTouchInput()
|
|
{
|
|
if (Input.touchCount == 0)
|
|
{
|
|
return;
|
|
}
|
|
Touch touch = Input.GetTouch(0);
|
|
TouchPhase phase = touch.phase;
|
|
if (phase != TouchPhase.Ended && phase != TouchPhase.Canceled)
|
|
{
|
|
if (phase == TouchPhase.Moved)
|
|
{
|
|
if (IsLineDrawn)
|
|
{
|
|
return;
|
|
}
|
|
Vector2 position = touch.position;
|
|
bool flag = IsTouchInsideDrawArea(position);
|
|
bool flag2 = isDrawing;
|
|
if (flag)
|
|
{
|
|
if (!flag2)
|
|
{
|
|
Vector2 vector = touch.position;
|
|
float num = vector.x - touchDownScreenPos.x;
|
|
float num2 = vector.y - touchDownScreenPos.y;
|
|
if (Mathf.Sqrt(num * num + num2 * num2) < minMovePixels)
|
|
{
|
|
return;
|
|
}
|
|
StartDrawing();
|
|
}
|
|
if (currentExitSide != ExitSide.None)
|
|
{
|
|
currentExitSide = ExitSide.None;
|
|
}
|
|
ContinueDrawing();
|
|
return;
|
|
}
|
|
if (!flag2)
|
|
{
|
|
return;
|
|
}
|
|
if (cantHitBorder)
|
|
{
|
|
StopDrawing();
|
|
return;
|
|
}
|
|
DetectExitSide(touch.position);
|
|
ContinueDrawing();
|
|
return;
|
|
}
|
|
if (phase != TouchPhase.Began)
|
|
{
|
|
return;
|
|
}
|
|
touchDownScreenPos = touch.position;
|
|
touchDownRecorded = true;
|
|
return;
|
|
}
|
|
bool isLineDrawn = IsLineDrawn;
|
|
touchDownRecorded = false;
|
|
currentExitSide = ExitSide.None;
|
|
if (isLineDrawn)
|
|
{
|
|
return;
|
|
}
|
|
if (!isDrawing)
|
|
{
|
|
return;
|
|
}
|
|
if (beadsSpawned >= 1)
|
|
{
|
|
if (GameManager.OnLineDrawingComplete != null)
|
|
{
|
|
GameManager.OnLineDrawingComplete();
|
|
}
|
|
changeAction();
|
|
}
|
|
StopDrawing();
|
|
}
|
|
|
|
private bool IsMouseInsideDrawArea()
|
|
{
|
|
Vector3 mousePosition = Input.mousePosition;
|
|
return drawArea.OverlapPoint(mainCamera.ScreenToWorldPoint(new Vector3(mousePosition.x, mousePosition.y, 10f)));
|
|
}
|
|
|
|
private bool IsTouchInsideDrawArea(Vector2 touchPosition)
|
|
{
|
|
return drawArea.OverlapPoint(mainCamera.ScreenToWorldPoint(new Vector3(touchPosition.x, touchPosition.y, 10f)));
|
|
}
|
|
|
|
private void StartDrawing()
|
|
{
|
|
previousPoint = GetInputWorldPoint();
|
|
_boundsMin = new Vector3(float.MaxValue, float.MaxValue, -1f);
|
|
_boundsMax = new Vector3(-3.4028235E+38f, -3.4028235E+38f, 1f);
|
|
_beadPosCount = 0;
|
|
_quadCount = 0;
|
|
drawMesh.Clear();
|
|
beadsSpawned = 0;
|
|
hasMoved = false;
|
|
_drawingBlocked = false;
|
|
EyeBallTracker.IsDrawBlocked = false;
|
|
if (drawBlockingLayers != 0)
|
|
{
|
|
Vector3 vector = mainCamera.ScreenToWorldPoint(new Vector3(touchDownScreenPos.x, touchDownScreenPos.y, 10f));
|
|
_externalDragStart = Physics2D.OverlapPoint(vector, drawBlockingLayers) != null;
|
|
}
|
|
else
|
|
{
|
|
_externalDragStart = false;
|
|
}
|
|
isDrawing = true;
|
|
if (GameManager.OnLineDrawingStarts != null)
|
|
{
|
|
GameManager.OnLineDrawingStarts();
|
|
}
|
|
if (GameManager.OnHintHideCalled != null)
|
|
{
|
|
GameManager.OnHintHideCalled(LevelScript.Instance.isWheelLevel);
|
|
}
|
|
if (CharacterAction.EnemyAction != null)
|
|
{
|
|
CharacterAction.EnemyAction(1);
|
|
}
|
|
EyeBallTracker.LookTarget = null;
|
|
}
|
|
|
|
private void changeAction()
|
|
{
|
|
if (CharacterAction.EnemyAction != null)
|
|
{
|
|
CharacterAction.EnemyAction(2);
|
|
}
|
|
if (isToolLevel && toolRigidbodies != null && toolRigidbodies.Length > 0 && toolRigidbodies[0] != null)
|
|
{
|
|
EyeBallTracker.LookTarget = toolRigidbodies[0].transform;
|
|
}
|
|
else
|
|
{
|
|
EyeBallTracker.LookTarget = null;
|
|
}
|
|
}
|
|
|
|
private void ContinueDrawing()
|
|
{
|
|
Vector3 vector = GetEffectiveDrawPosition();
|
|
if (_externalDragStart)
|
|
{
|
|
bool flag = drawBlockingLayers != 0 && Physics2D.OverlapPoint(vector, drawBlockingLayers) != null;
|
|
previousPoint = vector;
|
|
if (flag)
|
|
{
|
|
return;
|
|
}
|
|
_externalDragStart = false;
|
|
}
|
|
if (drawBlockingLayers != 0 && (Physics2D.OverlapPoint(vector, drawBlockingLayers) != null || Physics2D.Linecast(previousPoint, vector, drawBlockingLayers).collider != null))
|
|
{
|
|
_drawingBlocked = true;
|
|
EyeBallTracker.IsDrawBlocked = true;
|
|
EyeBallTracker.DrawBlockedLookPoint = previousPoint;
|
|
return;
|
|
}
|
|
if (_drawingBlocked)
|
|
{
|
|
float num = vector.x - previousPoint.x;
|
|
float num2 = vector.y - previousPoint.y;
|
|
if (Mathf.Sqrt(num * num + num2 * num2) > constantDistance * 512f)
|
|
{
|
|
return;
|
|
}
|
|
if (Physics2D.Linecast(previousPoint, vector, drawBlockingLayers).collider != null)
|
|
{
|
|
return;
|
|
}
|
|
_drawingBlocked = false;
|
|
EyeBallTracker.IsDrawBlocked = false;
|
|
vector = previousPoint + (vector - previousPoint) * 0.25f;
|
|
}
|
|
Vector3 vector2 = vector - previousPoint;
|
|
float num3 = vector2.x * vector2.x + vector2.y * vector2.y + vector2.z * vector2.z;
|
|
if (num3 < _constantDistanceSq)
|
|
{
|
|
return;
|
|
}
|
|
int num4 = (int)(Mathf.Sqrt(num3) * _invConstantDistance) + 2;
|
|
float num5 = ((num4 >= 2) ? (1f / (float)(num4 - 1)) : 0f);
|
|
if (!hasMoved)
|
|
{
|
|
if (AppConstants.isSound)
|
|
{
|
|
myAudioSource.clip = SoundManager.instance.Drawing;
|
|
myAudioSource.loop = true;
|
|
myAudioSource.Play();
|
|
}
|
|
hasMoved = true;
|
|
}
|
|
Vector3 p = previousPoint + vector2 * 0.1f;
|
|
Vector3 p2 = vector - vector2 * 0.1f;
|
|
for (int i = 0; i < num4; i++)
|
|
{
|
|
AddBeadToMesh(CubicBezierLerp(previousPoint, p, p2, vector, (float)i * num5));
|
|
beadsSpawned++;
|
|
}
|
|
ApplyMesh();
|
|
if (Time.time - lastVibrateTime >= vibrateInterval)
|
|
{
|
|
AppConstants.AndroidVibrate(10L);
|
|
lastVibrateTime = Time.time;
|
|
}
|
|
previousPoint = vector;
|
|
}
|
|
|
|
private void GrowArrays()
|
|
{
|
|
int arrayCapacity = _arrayCapacity;
|
|
int num = arrayCapacity * 2;
|
|
Array.Resize(ref _verts, num * 4);
|
|
Array.Resize(ref _uvs, num * 4);
|
|
Array.Resize(ref _tris, num * 6);
|
|
Array.Resize(ref _allBeadPosArr, num);
|
|
for (int i = arrayCapacity; i < num; i++)
|
|
{
|
|
_tris[i * 6] = i * 4;
|
|
_tris[i * 6 + 1] = i * 4 + 2;
|
|
_tris[i * 6 + 2] = i * 4 + 1;
|
|
_tris[i * 6 + 3] = i * 4;
|
|
_tris[i * 6 + 4] = i * 4 + 3;
|
|
_tris[i * 6 + 5] = i * 4 + 2;
|
|
}
|
|
for (int j = arrayCapacity * 4; j < num * 4; j += 4)
|
|
{
|
|
_uvs[j] = uvBL;
|
|
_uvs[j + 1] = uvBR;
|
|
_uvs[j + 2] = uvTR;
|
|
_uvs[j + 3] = uvTL;
|
|
}
|
|
_arrayCapacity = num;
|
|
}
|
|
|
|
private void AddBeadToMesh(Vector3 pos)
|
|
{
|
|
if (_quadCount >= _arrayCapacity)
|
|
{
|
|
GrowArrays();
|
|
}
|
|
_allBeadPosArr[_beadPosCount++] = pos;
|
|
int num = _quadCount * 4;
|
|
float x = pos.x;
|
|
float y = pos.y;
|
|
_verts[num] = new Vector3(x - beadHalfSize, y - beadHalfSize, pos.z);
|
|
_verts[num + 1] = new Vector3(x + beadHalfSize, y - beadHalfSize, pos.z);
|
|
_verts[num + 2] = new Vector3(x + beadHalfSize, y + beadHalfSize, pos.z);
|
|
_verts[num + 3] = new Vector3(x - beadHalfSize, y + beadHalfSize, pos.z);
|
|
if (x - beadHalfSize < _boundsMin.x)
|
|
{
|
|
_boundsMin.x = x - beadHalfSize;
|
|
}
|
|
if (y - beadHalfSize < _boundsMin.y)
|
|
{
|
|
_boundsMin.y = y - beadHalfSize;
|
|
}
|
|
if (x + beadHalfSize > _boundsMax.x)
|
|
{
|
|
_boundsMax.x = x + beadHalfSize;
|
|
}
|
|
if (y + beadHalfSize > _boundsMax.y)
|
|
{
|
|
_boundsMax.y = y + beadHalfSize;
|
|
}
|
|
_quadCount++;
|
|
}
|
|
|
|
private void ApplyMesh()
|
|
{
|
|
if (_quadCount == 0)
|
|
{
|
|
return;
|
|
}
|
|
drawMesh.Clear();
|
|
int num = _quadCount * 4;
|
|
drawMesh.SetVertices(_verts, 0, num);
|
|
drawMesh.SetUVs(0, _uvs, 0, num);
|
|
drawMesh.SetTriangles(_tris, 0, _quadCount * 6, 0);
|
|
drawMesh.bounds = new Bounds((_boundsMax + _boundsMin) * 0.5f, (_boundsMax - _boundsMin) * 0.5f);
|
|
}
|
|
|
|
public void SetLineStatic()
|
|
{
|
|
if (parentObject == null)
|
|
{
|
|
return;
|
|
}
|
|
Rigidbody2D component = parentObject.GetComponent<Rigidbody2D>();
|
|
if (component != null)
|
|
{
|
|
component.bodyType = RigidbodyType2D.Static;
|
|
}
|
|
if (toolRigidbodies == null)
|
|
{
|
|
return;
|
|
}
|
|
for (int i = 0; i < toolRigidbodies.Length; i++)
|
|
{
|
|
Rigidbody2D rigidbody2D = toolRigidbodies[i];
|
|
if (rigidbody2D != null)
|
|
{
|
|
rigidbody2D.bodyType = RigidbodyType2D.Static;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void StopDrawing()
|
|
{
|
|
isDrawing = false;
|
|
hasMoved = false;
|
|
_drawingBlocked = false;
|
|
_externalDragStart = false;
|
|
EyeBallTracker.IsDrawBlocked = false;
|
|
if (myAudioSource != null)
|
|
{
|
|
myAudioSource.loop = false;
|
|
myAudioSource.Stop();
|
|
}
|
|
if (_beadPosCount == 0)
|
|
{
|
|
return;
|
|
}
|
|
Vector2[] array = new Vector2[_beadPosCount];
|
|
Vector2 vector = Vector2.zero;
|
|
for (int i = 0; i < _beadPosCount; i++)
|
|
{
|
|
array[i] = _allBeadPosArr[i];
|
|
vector += array[i];
|
|
}
|
|
Vector3 position = parentObject.transform.position;
|
|
Vector2 vector2 = array[0] - array[array.Length - 1];
|
|
float num = Mathf.Sqrt(vector2.x * vector2.x + vector2.y * vector2.y);
|
|
bool flag = num < 0.6f;
|
|
bool flag2 = LevelScript.Instance != null && LevelScript.Instance.isMovingPlatformLevel;
|
|
bool flag3 = LevelScript.Instance != null && LevelScript.Instance.isWheelLevel;
|
|
float num2 = (flag ? 0.08f : 0.15f);
|
|
int num3 = ((flag3 || flag2) ? MAX_COLLIDER_POINTS : 30);
|
|
Vector2[] array2 = SimplifyPoints(array, num2);
|
|
while (num2 < 2f && num3 < array2.Length)
|
|
{
|
|
num2 *= 2f;
|
|
array2 = SimplifyPoints(array, num2);
|
|
}
|
|
if (flag)
|
|
{
|
|
Vector2[] array3 = new Vector2[array2.Length + 1];
|
|
Array.Copy(array2, array3, array2.Length);
|
|
array3[array3.Length - 1] = array2[0];
|
|
array2 = array3;
|
|
}
|
|
Debug.Log(string.Format("Original: {0} | Simplified: {1} | Closed: {2} | Tol: {3:F4} | MovingPlatform: {4}", _beadPosCount, array2.Length, flag, num2, flag2));
|
|
SetupChunkedColliders(array2);
|
|
if (testMode)
|
|
{
|
|
return;
|
|
}
|
|
Rigidbody2D rigidbody2D = parentObject.GetComponent<Rigidbody2D>();
|
|
if (rigidbody2D != null)
|
|
{
|
|
rigidbody2D.interpolation = RigidbodyInterpolation2D.None;
|
|
rigidbody2D.centerOfMass = new Vector2(vector.x / (float)_beadPosCount - position.x, vector.y / (float)_beadPosCount - position.y);
|
|
rigidbody2D.collisionDetectionMode = CollisionDetectionMode2D.Continuous;
|
|
rigidbody2D.bodyType = RigidbodyType2D.Dynamic;
|
|
rigidbody2D.velocity = Vector2.zero;
|
|
rigidbody2D.angularVelocity = 0f;
|
|
StartCoroutine(RestoreInterpolation(rigidbody2D));
|
|
StartCoroutine(CheckLineStuck(rigidbody2D));
|
|
}
|
|
}
|
|
|
|
private IEnumerator RestoreInterpolation(Rigidbody2D rb)
|
|
{
|
|
yield return new WaitForFixedUpdate();
|
|
if (rb != null)
|
|
{
|
|
rb.interpolation = RigidbodyInterpolation2D.Interpolate;
|
|
}
|
|
}
|
|
|
|
private IEnumerator CheckLineStuck(Rigidbody2D rb)
|
|
{
|
|
yield return new WaitForSeconds(1f);
|
|
bool flag = LevelScript.Instance != null && LevelScript.Instance.isMovingPlatformLevel;
|
|
float num = 0f;
|
|
bool flag2 = isToolLevel && toolRigidbodies != null && toolRigidbodies.Length > 0;
|
|
int num2 = (flag2 ? toolRigidbodies.Length : 0);
|
|
float num3 = 0f;
|
|
Vector2 vector = rb.position;
|
|
Camera cam = Camera.main;
|
|
float[] array = new float[num2];
|
|
Vector2[] array2 = new Vector2[num2];
|
|
float[] array3 = new float[num2];
|
|
for (int i = 0; i < num2; i++)
|
|
{
|
|
Rigidbody2D rigidbody2D = toolRigidbodies[i];
|
|
array2[i] = ((rigidbody2D != null) ? rigidbody2D.position : Vector2.zero);
|
|
array3[i] = ((rigidbody2D != null) ? rigidbody2D.rotation : 0f);
|
|
}
|
|
float num4 = 0f;
|
|
while (GameManager.Instance != null && !GameManager.Instance.IsGameEnded && rb != null)
|
|
{
|
|
num += 0.25f;
|
|
if (flag && num >= movingPlatformTimeLimit)
|
|
{
|
|
goto LineStuckFail;
|
|
}
|
|
Vector2 position = rb.position;
|
|
bool flag3 = false;
|
|
if (cam != null)
|
|
{
|
|
Vector3 vector2 = cam.WorldToViewportPoint(position);
|
|
flag3 = vector2.y > 1.5f || vector2.y < -0.5f || vector2.x < -0.5f || vector2.x > 1.5f;
|
|
}
|
|
if (flag3)
|
|
{
|
|
num4 += 0.25f;
|
|
}
|
|
else
|
|
{
|
|
num4 = 0f;
|
|
}
|
|
if (cam != null && !flag3 && flag2)
|
|
{
|
|
for (int j = 0; j < num2; j++)
|
|
{
|
|
Rigidbody2D rigidbody2D2 = toolRigidbodies[j];
|
|
if (rigidbody2D2 == null)
|
|
{
|
|
continue;
|
|
}
|
|
Vector3 vector3 = cam.WorldToViewportPoint(rigidbody2D2.position);
|
|
if (vector3.y > 1.5f || vector3.y < -0.5f || vector3.x < -0.5f || vector3.x > 1.5f)
|
|
{
|
|
array[j] += 0.25f;
|
|
}
|
|
else
|
|
{
|
|
array[j] = 0f;
|
|
}
|
|
if (array[j] >= 0.5f && (num4 >= 0.5f || (position - vector).magnitude < LinemovedThreshold))
|
|
{
|
|
goto LineStuckFail;
|
|
}
|
|
}
|
|
}
|
|
if (flag3 && !flag2 && num4 >= 0.5f)
|
|
{
|
|
goto LineStuckFail;
|
|
}
|
|
if (num4 >= 0.5f && num2 > 0)
|
|
{
|
|
for (int k = 0; k < num2; k++)
|
|
{
|
|
Rigidbody2D rigidbody2D3 = toolRigidbodies[k];
|
|
if (rigidbody2D3 == null)
|
|
{
|
|
continue;
|
|
}
|
|
Vector2 position2 = rigidbody2D3.position;
|
|
float rotation = rigidbody2D3.rotation;
|
|
float num5 = Mathf.DeltaAngle(rotation, array3[k]);
|
|
if ((position2 - array2[k]).magnitude < LinemovedThreshold && Mathf.Abs(num5) < 0.2f)
|
|
{
|
|
goto LineStuckFail;
|
|
}
|
|
}
|
|
}
|
|
Vector2 vector4 = vector;
|
|
vector = position;
|
|
float linemovedThreshold = LinemovedThreshold;
|
|
bool flag4 = true;
|
|
if (flag2 && num2 > 0)
|
|
{
|
|
for (int l = 0; l < num2; l++)
|
|
{
|
|
Rigidbody2D rigidbody2D4 = toolRigidbodies[l];
|
|
if (rigidbody2D4 == null)
|
|
{
|
|
continue;
|
|
}
|
|
Vector2 vector5 = rigidbody2D4.position;
|
|
Vector2 vector6 = array2[l];
|
|
float rotation2 = rigidbody2D4.rotation;
|
|
float num6 = Mathf.DeltaAngle(rotation2, array3[l]);
|
|
array2[l] = vector5;
|
|
array3[l] = rotation2;
|
|
if (Mathf.Abs(num6) >= 0.2f || (vector5 - vector6).magnitude >= linemovedThreshold)
|
|
{
|
|
flag4 = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (flag4 && (position - vector4).magnitude < linemovedThreshold)
|
|
{
|
|
num3 += 0.25f;
|
|
if (!flag && num3 >= 0.5f)
|
|
{
|
|
goto LineStuckFail;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
num3 = 0f;
|
|
}
|
|
yield return new WaitForSeconds(0.25f);
|
|
}
|
|
yield break;
|
|
LineStuckFail:
|
|
if (!GameManager.Instance.IsGameEnded && GameManager.EnemyList.Count >= 1)
|
|
{
|
|
GameManager.Instance.CheckLevelFailed();
|
|
}
|
|
yield break;
|
|
}
|
|
|
|
private Vector3 CubicBezierLerp(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
|
|
{
|
|
float num = 1f - t;
|
|
float num2 = num * num;
|
|
float num3 = num2 * num;
|
|
float num4 = t * t;
|
|
float num5 = num4 * t;
|
|
return num3 * p0 + 3f * num2 * t * p1 + 3f * num * num4 * p2 + num5 * p3;
|
|
}
|
|
|
|
private Vector2[] SimplifyPoints(Vector2[] points, float tolerance)
|
|
{
|
|
if (points.Length < 3)
|
|
{
|
|
return points;
|
|
}
|
|
List<Vector2> list = new List<Vector2>();
|
|
RDP(points, 0, points.Length - 1, tolerance * tolerance, list);
|
|
list.Add(points[points.Length - 1]);
|
|
return list.ToArray();
|
|
}
|
|
|
|
private void RDP(Vector2[] pts, int s, int e, float tolSq, List<Vector2> result)
|
|
{
|
|
if (s + 1 < e)
|
|
{
|
|
float num = 0f;
|
|
int num2 = s;
|
|
for (int i = s + 1; i < e; i++)
|
|
{
|
|
float num3 = PerpendicularDistanceSq(pts[i], pts[s], pts[e]);
|
|
if (num3 > num)
|
|
{
|
|
num2 = i;
|
|
num = num3;
|
|
}
|
|
}
|
|
if (num > tolSq)
|
|
{
|
|
RDP(pts, s, num2, tolSq, result);
|
|
RDP(pts, num2, e, tolSq, result);
|
|
return;
|
|
}
|
|
}
|
|
result.Add(pts[s]);
|
|
}
|
|
|
|
private void SetupChunkedColliders(Vector2[] points)
|
|
{
|
|
int num = points.Length;
|
|
int num2 = Mathf.CeilToInt((float)(num - 1) / 60f);
|
|
while (_colliderPool.Count < num2)
|
|
{
|
|
EdgeCollider2D edgeCollider2D = parentObject.AddComponent<EdgeCollider2D>();
|
|
edgeCollider2D.enabled = false;
|
|
_colliderPool.Add(edgeCollider2D);
|
|
}
|
|
if (num2 < _activeChunks)
|
|
{
|
|
for (int i = num2; i < _activeChunks; i++)
|
|
{
|
|
_colliderPool[i].enabled = false;
|
|
}
|
|
}
|
|
_activeChunks = num2;
|
|
for (int j = 0; j < num2; j++)
|
|
{
|
|
int num3 = j * 59;
|
|
int num4 = Mathf.Min(num3 + 60, points.Length) - num3;
|
|
Vector2[] array = new Vector2[num4];
|
|
Array.Copy(points, num3, array, 0, num4);
|
|
EdgeCollider2D edgeCollider2D2 = _colliderPool[j];
|
|
edgeCollider2D2.sharedMaterial = linePhysicsMat;
|
|
edgeCollider2D2.points = array;
|
|
edgeCollider2D2.enabled = true;
|
|
}
|
|
}
|
|
|
|
private float PerpendicularDistanceSq(Vector2 point, Vector2 lineStart, Vector2 lineEnd)
|
|
{
|
|
Vector2 vector = lineEnd - lineStart;
|
|
float num = vector.x * vector.x + vector.y * vector.y;
|
|
float num2 = point.x - lineStart.x;
|
|
float num3 = point.y - lineStart.y;
|
|
if (num == 0f)
|
|
{
|
|
return num2 * num2 + num3 * num3;
|
|
}
|
|
float num4 = Mathf.Clamp01((num2 * vector.x + num3 * vector.y) / num);
|
|
Vector2 vector2 = lineStart + vector * num4;
|
|
float num5 = point.x - vector2.x;
|
|
float num6 = point.y - vector2.y;
|
|
return num5 * num5 + num6 * num6;
|
|
}
|
|
|
|
private Vector3 GetEffectiveDrawPosition()
|
|
{
|
|
Vector3 result = GetInputWorldPoint();
|
|
if (currentExitSide != ExitSide.None)
|
|
{
|
|
Bounds bounds = drawArea.bounds;
|
|
Vector3 center = bounds.center;
|
|
Vector3 extents = bounds.extents;
|
|
float num = center.x + extents.x;
|
|
float num2 = center.x - extents.x;
|
|
float num3 = center.y + extents.y;
|
|
float num4 = center.y - extents.y;
|
|
if (currentExitSide == ExitSide.Left || currentExitSide == ExitSide.Right)
|
|
{
|
|
result.x = exitLockValue;
|
|
result.y = Mathf.Clamp(result.y, num4, num3);
|
|
}
|
|
else if (currentExitSide == ExitSide.Top || currentExitSide == ExitSide.Bottom)
|
|
{
|
|
result.x = Mathf.Clamp(result.x, num2, num);
|
|
result.y = exitLockValue;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private void DetectExitSide(Vector2 screenPos)
|
|
{
|
|
Vector3 vector = mainCamera.ScreenToWorldPoint(new Vector3(screenPos.x, screenPos.y, 10f));
|
|
Bounds bounds = drawArea.bounds;
|
|
Vector3 center = bounds.center;
|
|
Vector3 extents = bounds.extents;
|
|
float num = center.x + extents.x;
|
|
float num2 = center.x - extents.x;
|
|
float num3 = center.y + extents.y;
|
|
float num4 = center.y - extents.y;
|
|
float x = vector.x;
|
|
float y = vector.y;
|
|
ExitSide exitSide;
|
|
float num5;
|
|
if (x <= num && x >= num2 && y < num4)
|
|
{
|
|
exitSide = ExitSide.Bottom;
|
|
num5 = num4;
|
|
}
|
|
else if (x <= num && x >= num2 && y > num3)
|
|
{
|
|
exitSide = ExitSide.Top;
|
|
num5 = num3;
|
|
}
|
|
else if (y <= num3 && y >= num4 && x < num2)
|
|
{
|
|
exitSide = ExitSide.Left;
|
|
num5 = num2;
|
|
}
|
|
else if (y <= num3 && y >= num4 && x > num)
|
|
{
|
|
exitSide = ExitSide.Right;
|
|
num5 = num;
|
|
}
|
|
else
|
|
{
|
|
float num6 = num2 - x;
|
|
float num7 = x - num;
|
|
float num8 = num4 - y;
|
|
float num9 = y - num3;
|
|
float[] array = new float[4];
|
|
array[0] = ((x < num2) ? num6 : float.MaxValue);
|
|
array[1] = ((x > num) ? num7 : float.MaxValue);
|
|
array[2] = ((y < num4) ? num8 : float.MaxValue);
|
|
array[3] = ((y > num3) ? num9 : float.MaxValue);
|
|
float num10 = Mathf.Min(array);
|
|
if (y < num4 && Mathf.Approximately(num10, num8))
|
|
{
|
|
exitSide = ExitSide.Bottom;
|
|
num5 = num4;
|
|
}
|
|
else if (y > num3 && Mathf.Approximately(num10, num9))
|
|
{
|
|
exitSide = ExitSide.Top;
|
|
num5 = num3;
|
|
}
|
|
else if (x < num2 && Mathf.Approximately(num10, num6))
|
|
{
|
|
exitSide = ExitSide.Left;
|
|
num5 = num2;
|
|
}
|
|
else
|
|
{
|
|
exitSide = ExitSide.Right;
|
|
num5 = num;
|
|
}
|
|
}
|
|
if (currentExitSide != exitSide)
|
|
{
|
|
currentExitSide = exitSide;
|
|
exitLockValue = num5;
|
|
}
|
|
}
|
|
|
|
private Vector3 GetInputWorldPoint()
|
|
{
|
|
|
|
Vector2 screenPos = Input.touchCount > 0 ? Input.GetTouch(0).position : new Vector2(Input.mousePosition.x, Input.mousePosition.y);
|
|
return mainCamera.ScreenToWorldPoint(new Vector3(screenPos.x, screenPos.y, 10f));
|
|
}
|
|
}
|