flakni krtka

This commit is contained in:
2026-03-28 12:16:35 +01:00
parent 6a7314ff4e
commit 050e58e73c
3 changed files with 185 additions and 0 deletions

View File

@@ -0,0 +1,175 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class WhackTheMoleTask : MonoBehaviour, ITask
{
[Header("Game Settings")]
public float moleAppearTime = 1.5f;
public float spawnInterval = 0.8f;
public int gameDuration = 30;
public int scoreThreshold = 5;
[Header("UI References")]
public List<Button> holes;
public TMP_Text scoreText;
public TMP_Text timerText;
public string TaskID { get; set; }
public TaskType TaskType { get; set; }
public string TaskName { get; set; }
public (double, double) TaskLocation { get; set; }
public bool IsCompleted { get; private set; }
private Action<ITask> _onCompleted;
private Action<ITask> _onExit;
private int _score;
private float _timer;
private bool _gameRunning;
private Button _activeMole;
private int _lastHoleIndex = -1;
private Coroutine _hideMoleCoroutine;
private Coroutine _gameLoopCoroutine;
private void Start()
{
Initialize(null);
_gameLoopCoroutine = StartCoroutine(GameLoop());
}
private void OnDisable()
{
ExitTask(_onExit);
}
public void Initialize(Action<ITask> onCompleted)
{
_onCompleted = onCompleted;
IsCompleted = false;
_score = 0;
_gameRunning = false;
}
public void Complete()
{
if (IsCompleted) return;
IsCompleted = true;
_onCompleted?.Invoke(this);
Debug.Log("[WhackTheMole] Task completed!");
}
public void ExitTask(Action<ITask> onExit)
{
_onExit = onExit;
_gameRunning = false;
StopGameCoroutines();
SetAllHolesInactive();
_onExit?.Invoke(this);
}
private IEnumerator GameLoop()
{
_timer = gameDuration;
_score = 0;
_gameRunning = true;
RefreshScore();
RefreshTimer();
float nextSpawn = 0f;
while (_timer > 0f && _gameRunning)
{
_timer -= Time.deltaTime;
nextSpawn -= Time.deltaTime;
RefreshTimer();
if (nextSpawn <= 0f)
{
SpawnMole();
nextSpawn = spawnInterval;
}
yield return null;
}
_gameRunning = false;
EndGame();
}
private void SpawnMole()
{
if (_hideMoleCoroutine != null) StopCoroutine(_hideMoleCoroutine);
if (_activeMole != null) _activeMole.gameObject.SetActive(false);
int index = PickHoleIndex();
_lastHoleIndex = index;
_activeMole = holes[index];
_activeMole.gameObject.SetActive(true);
Button thisHole = _activeMole;
_activeMole.onClick.RemoveAllListeners();
_activeMole.onClick.AddListener(() => OnMoleHit(thisHole));
_hideMoleCoroutine = StartCoroutine(AutoHideMole(thisHole, moleAppearTime));
}
private int PickHoleIndex()
{
if (holes.Count == 1) return 0;
int index;
int attempts = 0;
const int maxAttempts = 10;
do
{
index = UnityEngine.Random.Range(0, holes.Count);
attempts++;
} while (index == _lastHoleIndex && attempts < maxAttempts);
return index;
}
private IEnumerator AutoHideMole(Button mole, float delay)
{
yield return new WaitForSeconds(delay);
if (mole == _activeMole) mole.gameObject.SetActive(false);
_activeMole = null;
_hideMoleCoroutine = null;
}
private void OnMoleHit(Button mole)
{
if (!_gameRunning) return;
if (_hideMoleCoroutine != null) StopCoroutine(_hideMoleCoroutine);
mole.gameObject.SetActive(false);
if (mole == _activeMole) _activeMole = null;
_score++;
RefreshScore();
}
private void EndGame()
{
SetAllHolesInactive();
Debug.Log($"[WhackTheMole] Game ended. Score: {_score} / Threshold: {scoreThreshold}");
if (_score >= scoreThreshold) Complete();
}
private void StopGameCoroutines()
{
if (_hideMoleCoroutine != null) { StopCoroutine(_hideMoleCoroutine); _hideMoleCoroutine = null; }
if (_gameLoopCoroutine != null) { StopCoroutine(_gameLoopCoroutine); _gameLoopCoroutine = null; }
}
private void SetAllHolesInactive()
{
if (holes == null) return;
foreach (var hole in holes)
if (hole != null) hole.gameObject.SetActive(false);
_activeMole = null;
}
private void RefreshScore() { if (scoreText != null) scoreText.text = $"Score: {_score}"; }
private void RefreshTimer() { if (timerText != null) timerText.text = $"Time: {Mathf.CeilToInt(_timer)}"; }
}