Files
rudder-unity-sdk/Assets/LiveOpsExamples/Scripts/GameWorld.cs
T
2026-08-12 14:03:44 +03:00

150 lines
4.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using UnityEngine;
namespace LiveOpsExamples
{
/// <summary>
/// Gameplay world for the Cozy Collector demo — the Unity port of the Phaser
/// GameScene.ts. Renders only the game world: player movement (WASD/arrows),
/// round timer, spawn cadence and pickups. All chrome lives in the UI panels,
/// all SDK calls in <see cref="CozyCollectorController"/>.
///
/// The Phaser field is 1280×720 px at 100 PPU, i.e. 12.8×7.2 world units
/// centered on the origin; tuning speeds/intervals stay in Phaser units
/// (px/s, ms) and are converted here.
/// </summary>
public class GameWorld : MonoBehaviour
{
private const float PixelsPerUnit = 100f;
[SerializeField] private SpriteRenderer player;
[SerializeField] private SnackSpawner spawner;
[SerializeField] private CozyCollectorController controller;
[SerializeField] private ScorePopupView scorePopupPrefab;
[SerializeField] private ParticleSystem collectBurstPrefab;
[SerializeField] private Vector2 moveMin = new Vector2(-6.0f, -3.2f);
[SerializeField] private Vector2 moveMax = new Vector2(6.0f, 3.2f);
private bool _paused;
private float _spawnElapsedMs;
private int _lastSecond = -1;
private bool _finishRaised;
public int Score { get; private set; }
public int Collected { get; private set; }
public float TimeLeftSeconds { get; private set; }
public bool RoundActive { get; private set; }
public event Action StateChanged;
public event Action<int, int> RoundFinished;
private void Awake()
{
spawner.Player = player;
spawner.Collected += OnSnackCollected;
}
private void OnDestroy()
{
spawner.Collected -= OnSnackCollected;
}
private void Update()
{
MovePlayer(_paused || !RoundActive);
if (!RoundActive || _paused)
return;
TimeLeftSeconds = Mathf.Max(0f, TimeLeftSeconds - Time.deltaTime);
_spawnElapsedMs += Time.deltaTime * 1000f;
if (_spawnElapsedMs >= controller.Tuning.SpawnIntervalMs)
{
_spawnElapsedMs = 0f;
spawner.Spawn();
}
var second = Mathf.CeilToInt(TimeLeftSeconds);
if (second != _lastSecond)
{
_lastSecond = second;
StateChanged?.Invoke();
}
if (TimeLeftSeconds <= 0f)
FinishRound();
}
public void SetPaused(bool paused)
{
_paused = paused;
}
public void RestartRound()
{
Score = 0;
Collected = 0;
TimeLeftSeconds = controller.Tuning.RoundSeconds;
_spawnElapsedMs = 0f;
_lastSecond = -1;
_finishRaised = false;
spawner.Clear();
RoundActive = true;
spawner.Spawn();
StateChanged?.Invoke();
}
private void MovePlayer(bool frozen)
{
if (frozen)
return;
var vx = (Input.GetKey(KeyCode.LeftArrow) || Input.GetKey(KeyCode.A) ? -1 : 0) +
(Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.D) ? 1 : 0);
var vy = (Input.GetKey(KeyCode.DownArrow) || Input.GetKey(KeyCode.S) ? -1 : 0) +
(Input.GetKey(KeyCode.UpArrow) || Input.GetKey(KeyCode.W) ? 1 : 0);
if (vx == 0 && vy == 0)
return;
var direction = new Vector2(vx, vy).normalized;
var speed = controller.Tuning.PlayerSpeed / PixelsPerUnit;
var position = player.transform.position;
position += (Vector3)(direction * speed * Time.deltaTime);
position.x = Mathf.Clamp(position.x, moveMin.x, moveMax.x);
position.y = Mathf.Clamp(position.y, moveMin.y, moveMax.y);
player.transform.position = position;
if (vx != 0)
player.flipX = vx < 0;
}
private void OnSnackCollected(Snack snack)
{
var position = snack.transform.position;
var gain = Mathf.RoundToInt(controller.Tuning.CollectibleScore);
Score += gain;
Collected += 1;
var popup = Instantiate(scorePopupPrefab, position, Quaternion.identity);
popup.Set(gain);
Instantiate(collectBurstPrefab, position, Quaternion.identity);
StateChanged?.Invoke();
}
private void FinishRound()
{
if (_finishRaised)
return;
_finishRaised = true;
RoundActive = false;
spawner.Clear();
StateChanged?.Invoke();
RoundFinished?.Invoke(Score, Collected);
}
}
}