Skip to content

Instantly share code, notes, and snippets.

@KVinS
Created October 14, 2024 21:41
Show Gist options
  • Save KVinS/d1581844d56efa193f3141fc28b35e4b to your computer and use it in GitHub Desktop.
Save KVinS/d1581844d56efa193f3141fc28b35e4b to your computer and use it in GitHub Desktop.
Connect dots - Unity3D minigame
using System;
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
using Unity.VisualScripting;
public class LineConnector : MonoBehaviour
{
[SerializeField] private List<LineRenderer> _linesCash = new List<LineRenderer>();
[SerializeField] private float _minDrawDistance = 0.05f;
[SerializeField] private float _radius = 5f; // Радиус игрового поля
[SerializeField] private LineLevel _level;
private bool isDrawingLine = false;
private Vector2 _lastDrawnPoint;
private LinePoint _startPoint;
private LineRenderer _currentLine;
private Dictionary<Color, LineRenderer> _lineRenderers = new Dictionary<Color, LineRenderer>();
private void Start()
{
}
private void TryStartDrawLine(Vector2 pos)
{
foreach (var point in _level.Points)
{
if (Vector2.Distance(pos, point.transform.position) < _minDrawDistance)
{
if (_lineRenderers.ContainsKey(point.Color))
{
return;
}
_startPoint = point;
isDrawingLine = true;
_lastDrawnPoint = pos;
_currentLine = _linesCash[0];
_linesCash.Remove(_currentLine);
_currentLine.positionCount = 1;
_currentLine.SetPosition(0, _startPoint.transform.position);
_currentLine.startColor = point.Color;
_currentLine.endColor = point.Color;
}
}
}
private void TryAddPoint(Vector2 pos)
{
if (Vector2.Distance(pos, _lastDrawnPoint) >= _minDrawDistance)
{
if (CheckLineIntersection(_lastDrawnPoint, pos))
{
StopDrawLine();
return;
}
foreach (var point in _level.Points)
{
if (Vector2.Distance(pos, point.transform.position) < _minDrawDistance && point.Color != _startPoint.Color)
{
StopDrawLine();
return;
}
}
_lastDrawnPoint = pos;
_currentLine.positionCount++;
_currentLine.SetPosition(_currentLine.positionCount - 1, _lastDrawnPoint);
}
}
private void StopDrawLine()
{
if (isDrawingLine)
{
_currentLine.positionCount = 0;
_linesCash.Add(_currentLine);
_lineRenderers.Remove(_startPoint.Color);
}
_currentLine = null;
isDrawingLine = false;
_startPoint = null;
}
private void Update()
{
Vector3 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
if (Input.GetMouseButton(0))
{
if (!IsPointWithinCircle(mousePosition))
{
StopDrawLine();
return;
}
// Начало рисования линии
if (isDrawingLine)
{
TryAddPoint(mousePosition);
}
else
{
TryStartDrawLine(mousePosition);
}
} else if (isDrawingLine)
{
CheckLineCompletion(mousePosition);
}
}
private void CheckLineCompletion(Vector2 pos)
{
bool checkWin = false;
foreach (var point in _level.Points)
{
if (point != _startPoint && point.Color == _startPoint.Color && Vector2.Distance(pos, point.transform.position) < _minDrawDistance * 2)
{
isDrawingLine = false;
_currentLine.SetPosition(_currentLine.positionCount - 1, point.transform.position);
_lineRenderers.Add(_startPoint.Color, _currentLine);
checkWin = true;
}
}
StopDrawLine();
if (checkWin)
{
if (_level.Points.Count / 2 == _lineRenderers.Count)
{
Debug.Log("WIN");
}
}
}
private bool IsPointWithinCircle(Vector2 point)
{
return Vector3.Distance(point, Vector3.zero) <= _radius;
}
private bool CheckLineIntersection(Vector3 start, Vector3 end)
{
foreach (LineRenderer line in _lineRenderers.Values)
{
for (int i = 0; i < line.positionCount - 1; i++)
{
Vector3 lineStart = line.GetPosition(i);
Vector3 lineEnd = line.GetPosition(i+1);
if (LineLineIntersection(start, end, lineStart, lineEnd))
{
return true;
}
}
}
for (int i = 0; i < _level.Borders.positionCount - 1; i++)
{
Vector3 lineStart = _level.Borders.GetPosition(i);
Vector3 lineEnd = _level.Borders.GetPosition(i+1);
if (LineLineIntersection(start, end, lineStart, lineEnd))
{
return true;
}
}
return false;
}
private bool LineLineIntersection(Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4)
{
// Алгоритм проверки пересечения отрезков (прямая - отрезок)
float denominator = (p4.y - p3.y) * (p2.x - p1.x) - (p4.x - p3.x) * (p2.y - p1.y);
if (denominator == 0)
{
return false; // Линии параллельны или совпадают
}
float uA = ((p4.x - p3.x) * (p1.y - p3.y) - (p4.y - p3.y) * (p1.x - p3.x)) / denominator;
float uB = ((p2.x - p1.x) * (p1.y - p3.y) - (p2.y - p1.y) * (p1.x - p3.x)) / denominator;
return (uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1);
}
// Метод для рестарта текущего уровня
public void RestartLevel()
{
// Удаление всех линий
isDrawingLine = false;
}
// Метод для перехода к следующему уровню
public void NextLevel()
{
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LineLevel : MonoBehaviour
{
[SerializeField] private List<LinePoint> _points;
[SerializeField] private LineRenderer _borders;
public List<LinePoint> Points
{
get { return _points; }
}
public LineRenderer Borders
{
get { return _borders; }
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LinePoint : MonoBehaviour
{
[SerializeField] private Color _color;
public Color Color => _color;
[SerializeField] private SpriteRenderer _renderer;
private void Awake()
{
_renderer.color = _color;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment