app.hypergames.hypersdk 1.3.4 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/Editor/{HyperSDK.Editor.asmdef → Hyper.Editor.asmdef} +1 -1
- package/Editor/Resources/ControlBarPreviews/Dark/Default.png +0 -0
- package/Editor/Resources/ControlBarPreviews/Dark/Default.png.meta +143 -0
- package/Editor/Resources/ControlBarPreviews/Dark/HealthBarLeft.png +0 -0
- package/Editor/Resources/ControlBarPreviews/Dark/HealthBarLeft.png.meta +143 -0
- package/Editor/Resources/ControlBarPreviews/Dark/HeartsLeft.png +0 -0
- package/Editor/Resources/ControlBarPreviews/Dark/HeartsLeft.png.meta +169 -0
- package/Editor/Resources/ControlBarPreviews/Dark.meta +8 -0
- package/Editor/Resources/ControlBarPreviews/Light/Default.png +0 -0
- package/Editor/Resources/ControlBarPreviews/Light/Default.png.meta +143 -0
- package/Editor/Resources/ControlBarPreviews/Light/HealthBarLeft.png +0 -0
- package/Editor/Resources/ControlBarPreviews/Light/HealthBarLeft.png.meta +143 -0
- package/Editor/Resources/ControlBarPreviews/Light/HeartsLeft.png +0 -0
- package/Editor/Resources/ControlBarPreviews/Light/HeartsLeft.png.meta +143 -0
- package/Editor/Resources/ControlBarPreviews/Light.meta +8 -0
- package/Editor/Resources/ControlBarPreviews.meta +8 -0
- package/Editor/Scripts/Inspectors/HyperSDKSettingsEditor.cs +206 -0
- package/Editor/Scripts/Inspectors/HyperSDKSettingsEditor.cs.meta +2 -0
- package/Editor/Scripts/Inspectors.meta +8 -0
- package/Editor/Scripts/Windows/HyperCoreSettingsWindow.cs +0 -8
- package/Editor/Scripts/Windows/HyperGameContentWindow.cs +0 -8
- package/Editor/Scripts/Windows/HyperSettingsWindow.cs +3 -3
- package/HyperLoader.unity +4 -49
- package/Runtime/Internal/AssemblyInfo.cs +1 -1
- package/Runtime/Internal/Managers/EventManager.cs +4 -0
- package/Runtime/Internal/Managers/GameManager.cs +135 -2
- package/Runtime/Internal/ScriptableObjects/HyperSDKSettings.cs +16 -10
- package/Runtime/Internal/UI/Animation/BlinkingText.cs +1 -1
- package/Runtime/Internal/UI/Animation/HyperTween.cs +88 -0
- package/Runtime/Internal/UI/Components/ControlBar.cs +220 -40
- package/Runtime/Internal/UI/Components/HealthBarDisplay.cs +269 -0
- package/Runtime/Internal/UI/Components/HealthBarDisplay.cs.meta +2 -0
- package/Runtime/Internal/UI/Components/LivesDisplay.cs +327 -0
- package/Runtime/Internal/UI/Components/LivesDisplay.cs.meta +2 -0
- package/Runtime/Internal/UI/Modals/StartingInstructionModal.cs +202 -3
- package/Runtime/Internal/Utils/HyperConstants.cs +27 -0
- package/Runtime/Public/Core/HyperSDK.cs +68 -0
- package/Runtime/Resources/Fonts/Wonder Boys/Wonder Boys + Hyper BIG.mat +1 -1
- package/Runtime/Resources/HyperSDKSettings.asset +3 -2
- package/Runtime/Resources/Sprites/Control Bar/Ellipse 3.png +0 -0
- package/Runtime/Resources/Sprites/Control Bar/Ellipse 3.png.meta +169 -0
- package/Runtime/Resources/Sprites/Control Bar/Health Bar - Green Fill.png +0 -0
- package/Runtime/Resources/Sprites/Control Bar/Health Bar - Green Fill.png.meta +169 -0
- package/Runtime/Resources/Sprites/Control Bar/Health Bar - Underlay.png +0 -0
- package/Runtime/Resources/Sprites/Control Bar/Health Bar - Underlay.png.meta +169 -0
- package/Runtime/Resources/Sprites/Control Bar/Health Bar.png +0 -0
- package/Runtime/Resources/Sprites/Control Bar/Health Bar.png.meta +169 -0
- package/Runtime/Resources/Sprites/Control Bar/heart.empty.png +0 -0
- package/Runtime/Resources/Sprites/Control Bar/heart.empty.png.meta +169 -0
- package/Runtime/Resources/Sprites/Control Bar/heart.fill.png +0 -0
- package/Runtime/Resources/Sprites/Control Bar/heart.fill.png.meta +169 -0
- package/Runtime/Resources/Sprites/Frames/{Game Over P.png.meta → Game Over.png.meta } +4 -4
- package/Runtime/Resources/Sprites/HYPERGAMES_Logo.png.meta +3 -3
- package/Runtime/Resources/Sprites/Hyper Atlas.spriteatlasv2 +6 -0
- package/Runtime/Resources/Sprites/Start CTAs/Hand.PNG +0 -0
- package/Runtime/Resources/Sprites/Start CTAs/Hand.PNG.meta +169 -0
- package/Runtime/Resources/Sprites/Start CTAs/Line .PNG +0 -0
- package/Runtime/Resources/Sprites/Start CTAs/Line .PNG.meta +169 -0
- package/Runtime/Resources/Sprites/Start CTAs/Swipe Gesture GIF.controller +130 -0
- package/Runtime/Resources/Sprites/Start CTAs/Swipe Gesture GIF.controller.meta +8 -0
- package/Runtime/Resources/Sprites/Start CTAs/Swipe Gesture.anim +158 -0
- package/Runtime/Resources/Sprites/Start CTAs/Swipe Gesture.anim.meta +8 -0
- package/Runtime/Resources/Sprites/Start CTAs.meta +8 -0
- package/Runtime/Resources/UIPrefabs/Control Bar Objects/Health Bar Display.prefab +361 -0
- package/Runtime/Resources/UIPrefabs/Control Bar Objects/Health Bar Display.prefab.meta +7 -0
- package/Runtime/Resources/UIPrefabs/Control Bar Objects/Lives Display .prefab +246 -0
- package/Runtime/Resources/UIPrefabs/Control Bar Objects/Lives Display .prefab.meta +7 -0
- package/Runtime/Resources/UIPrefabs/Control Bar Objects.meta +8 -0
- package/Runtime/Resources/UIPrefabs/ControlBar.prefab +131 -17
- package/Runtime/Resources/UIPrefabs/StartingInstructionModal.prefab +271 -57
- package/Runtime/Resources/UIPrefabs/TutorialLandscapeModal.prefab +1 -1
- package/Runtime/Resources/UIPrefabs/TutorialPortraitModal.prefab +1 -1
- package/Runtime/Shared/DTOs/Enums.cs +22 -6
- package/package.json +1 -1
- /package/Editor/{HyperSDK.Editor.asmdef.meta → Hyper.Editor.asmdef.meta} +0 -0
- /package/Runtime/Resources/Sprites/Frames/{Game Over P.png → Game Over.png} +0 -0
|
@@ -42,6 +42,47 @@ namespace Hyper.Internal.Managers
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
_isPortrait = Screen.height > Screen.width;
|
|
45
|
+
SubscribeToLivesEvents();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private void SubscribeToLivesEvents()
|
|
49
|
+
{
|
|
50
|
+
// Default behavior: automatically end game when lives are exhausted
|
|
51
|
+
// Developers can still subscribe to OnLivesExhausted for custom behavior
|
|
52
|
+
_eventManager.OnLivesExhausted += HandleLivesExhausted;
|
|
53
|
+
_eventManager.OnHealthExhausted += HandleHealthExhausted;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
private void HandleLivesExhausted()
|
|
57
|
+
{
|
|
58
|
+
if (!IsInGameScene || _hasGameEnded || !_hasGameStarted) return;
|
|
59
|
+
|
|
60
|
+
// Automatically end the game when lives are exhausted
|
|
61
|
+
// Use appropriate method based on game mode
|
|
62
|
+
if (IsBattleMode)
|
|
63
|
+
{
|
|
64
|
+
EndBattleGame();
|
|
65
|
+
}
|
|
66
|
+
else
|
|
67
|
+
{
|
|
68
|
+
EndPracticeGame();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
private void HandleHealthExhausted()
|
|
73
|
+
{
|
|
74
|
+
if (!IsInGameScene || _hasGameEnded || !_hasGameStarted) return;
|
|
75
|
+
|
|
76
|
+
// Automatically end the game when health is exhausted
|
|
77
|
+
// Use appropriate method based on game mode
|
|
78
|
+
if (IsBattleMode)
|
|
79
|
+
{
|
|
80
|
+
EndBattleGame();
|
|
81
|
+
}
|
|
82
|
+
else
|
|
83
|
+
{
|
|
84
|
+
EndPracticeGame();
|
|
85
|
+
}
|
|
45
86
|
}
|
|
46
87
|
|
|
47
88
|
internal void Cleanup()
|
|
@@ -107,6 +148,7 @@ namespace Hyper.Internal.Managers
|
|
|
107
148
|
|
|
108
149
|
internal ControlBarTheme ControlBarTheme { get; private set; }
|
|
109
150
|
internal ControlBarLayout ControlBarLayout { get; private set; }
|
|
151
|
+
internal StartCTA StartCTA { get; private set; }
|
|
110
152
|
|
|
111
153
|
internal void PauseGame()
|
|
112
154
|
{
|
|
@@ -144,6 +186,90 @@ namespace Hyper.Internal.Managers
|
|
|
144
186
|
_controlBarModal?.UpdateScoreLabel();
|
|
145
187
|
}
|
|
146
188
|
|
|
189
|
+
internal void InitializeLives(int maxLives, int initialLives = -1)
|
|
190
|
+
{
|
|
191
|
+
var livesDisplay = _controlBarModal?.GetLivesDisplay();
|
|
192
|
+
livesDisplay?.Initialize(maxLives, initialLives);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
internal void SetLives(int lives)
|
|
196
|
+
{
|
|
197
|
+
var livesDisplay = _controlBarModal?.GetLivesDisplay();
|
|
198
|
+
livesDisplay?.SetLives(lives);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
internal void AddLife()
|
|
202
|
+
{
|
|
203
|
+
var livesDisplay = _controlBarModal?.GetLivesDisplay();
|
|
204
|
+
livesDisplay?.AddLife();
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
internal void RemoveLife()
|
|
208
|
+
{
|
|
209
|
+
var livesDisplay = _controlBarModal?.GetLivesDisplay();
|
|
210
|
+
livesDisplay?.RemoveLife();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
internal int GetCurrentLives()
|
|
214
|
+
{
|
|
215
|
+
var livesDisplay = _controlBarModal?.GetLivesDisplay();
|
|
216
|
+
return livesDisplay?.GetCurrentLives() ?? 0;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
internal int GetMaxLives()
|
|
220
|
+
{
|
|
221
|
+
var livesDisplay = _controlBarModal?.GetLivesDisplay();
|
|
222
|
+
return livesDisplay?.GetMaxLives() ?? 0;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
internal void InitializeHealth(float maxHealth, float initialHealth = -1f, bool isNormalized = false)
|
|
226
|
+
{
|
|
227
|
+
var healthBarDisplay = _controlBarModal?.GetHealthBarDisplay();
|
|
228
|
+
healthBarDisplay?.Initialize(maxHealth, initialHealth, isNormalized);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
internal void SetHealth(float health)
|
|
232
|
+
{
|
|
233
|
+
var healthBarDisplay = _controlBarModal?.GetHealthBarDisplay();
|
|
234
|
+
healthBarDisplay?.SetHealth(health);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
internal void SetHealthNormalized(float normalizedHealth)
|
|
238
|
+
{
|
|
239
|
+
var healthBarDisplay = _controlBarModal?.GetHealthBarDisplay();
|
|
240
|
+
healthBarDisplay?.SetHealthNormalized(normalizedHealth);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
internal void AddHealth(float amount)
|
|
244
|
+
{
|
|
245
|
+
var healthBarDisplay = _controlBarModal?.GetHealthBarDisplay();
|
|
246
|
+
healthBarDisplay?.AddHealth(amount);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
internal void RemoveHealth(float amount)
|
|
250
|
+
{
|
|
251
|
+
var healthBarDisplay = _controlBarModal?.GetHealthBarDisplay();
|
|
252
|
+
healthBarDisplay?.RemoveHealth(amount);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
internal float GetCurrentHealth()
|
|
256
|
+
{
|
|
257
|
+
var healthBarDisplay = _controlBarModal?.GetHealthBarDisplay();
|
|
258
|
+
return healthBarDisplay?.GetCurrentHealth() ?? 0f;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
internal float GetMaxHealth()
|
|
262
|
+
{
|
|
263
|
+
var healthBarDisplay = _controlBarModal?.GetHealthBarDisplay();
|
|
264
|
+
return healthBarDisplay?.GetMaxHealth() ?? 0f;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
internal float GetHealthNormalized()
|
|
268
|
+
{
|
|
269
|
+
var healthBarDisplay = _controlBarModal?.GetHealthBarDisplay();
|
|
270
|
+
return healthBarDisplay?.GetHealthNormalized() ?? 0f;
|
|
271
|
+
}
|
|
272
|
+
|
|
147
273
|
internal void ShowConnectionLost()
|
|
148
274
|
{
|
|
149
275
|
if (!IsInGameScene) return;
|
|
@@ -389,8 +515,9 @@ namespace Hyper.Internal.Managers
|
|
|
389
515
|
|
|
390
516
|
private void LoadConfiguration()
|
|
391
517
|
{
|
|
392
|
-
ControlBarLayout = HyperRuntime.Settings.
|
|
393
|
-
ControlBarTheme = HyperRuntime.Settings.
|
|
518
|
+
ControlBarLayout = HyperRuntime.Settings.controlBarLayout;
|
|
519
|
+
ControlBarTheme = HyperRuntime.Settings.controlBarTheme;
|
|
520
|
+
StartCTA = HyperRuntime.Settings.startCTA;
|
|
394
521
|
}
|
|
395
522
|
|
|
396
523
|
#if UNITY_WEBGL && !UNITY_EDITOR
|
|
@@ -1268,6 +1395,12 @@ namespace Hyper.Internal.Managers
|
|
|
1268
1395
|
|
|
1269
1396
|
_startingInstructionModal = instance;
|
|
1270
1397
|
_startingInstructionModalComponent = instance.GetComponent<StartingInstructionModal>();
|
|
1398
|
+
|
|
1399
|
+
// Configure the CTA text based on settings
|
|
1400
|
+
if (_startingInstructionModalComponent != null)
|
|
1401
|
+
{
|
|
1402
|
+
_startingInstructionModalComponent.Configure(StartCTA);
|
|
1403
|
+
}
|
|
1271
1404
|
}
|
|
1272
1405
|
|
|
1273
1406
|
private void HideStartingInstructionModal()
|
|
@@ -31,24 +31,30 @@ namespace Hyper.Internal
|
|
|
31
31
|
|
|
32
32
|
#endregion
|
|
33
33
|
|
|
34
|
-
#region
|
|
34
|
+
#region Start CTA
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
[Space(20)]
|
|
37
|
+
[Header("Start CTA Overlay")]
|
|
38
|
+
[Tooltip("Choose the start CTA overlay shown before gameplay begins. Hyper requires one of these overlays - do not add your own start buttons.")]
|
|
39
|
+
public StartCTA startCTA = StartCTA.TapToPlay;
|
|
40
|
+
|
|
41
|
+
#endregion
|
|
42
|
+
|
|
43
|
+
#region Control Bar Settings
|
|
44
|
+
|
|
45
|
+
[Space(20)]
|
|
46
|
+
[Header("Control Bar Settings")]
|
|
47
|
+
[Tooltip("Select the layout type for the in-game control bar.")]
|
|
48
|
+
public ControlBarLayout controlBarLayout = ControlBarLayout.Default;
|
|
41
49
|
|
|
42
50
|
// [Space(5)]
|
|
43
|
-
// [Tooltip("Select the
|
|
51
|
+
// [Tooltip("Select the color theme (light or dark) for the control bar.")]
|
|
44
52
|
[HideInInspector]
|
|
45
|
-
public
|
|
53
|
+
public ControlBarTheme controlBarTheme = ControlBarTheme.Dark;
|
|
46
54
|
|
|
47
55
|
#endregion
|
|
48
56
|
|
|
49
57
|
#region Editor Testing
|
|
50
|
-
|
|
51
|
-
[Space(10)]
|
|
52
58
|
[Header("Editor Simulation")]
|
|
53
59
|
[Tooltip("Configuration settings for testing within the Unity Editor.")]
|
|
54
60
|
public URLData _settings;
|
|
@@ -162,6 +162,34 @@ namespace Hyper.Internal.Animation
|
|
|
162
162
|
return handle;
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
+
/// <summary>
|
|
166
|
+
/// Animates an Image's fillAmount (0-1).
|
|
167
|
+
/// </summary>
|
|
168
|
+
public static TweenHandle DoFillAmount(Image target, float endValue, float duration)
|
|
169
|
+
{
|
|
170
|
+
EnsureCoroutineRunner();
|
|
171
|
+
var handle = new TweenHandle();
|
|
172
|
+
var coroutine = coroutineRunner.StartCoroutine(AnimateFillAmount(target, endValue, duration, handle));
|
|
173
|
+
TrackCoroutine(target, coroutine);
|
|
174
|
+
handle.coroutine = coroutine;
|
|
175
|
+
handle.target = target;
|
|
176
|
+
return handle;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/// <summary>
|
|
180
|
+
/// Animates a Transform's local scale.
|
|
181
|
+
/// </summary>
|
|
182
|
+
public static TweenHandle DoScale(Transform target, Vector3 endValue, float duration)
|
|
183
|
+
{
|
|
184
|
+
EnsureCoroutineRunner();
|
|
185
|
+
var handle = new TweenHandle();
|
|
186
|
+
var coroutine = coroutineRunner.StartCoroutine(AnimateScale(target, endValue, duration, handle));
|
|
187
|
+
TrackCoroutine(target, coroutine);
|
|
188
|
+
handle.coroutine = coroutine;
|
|
189
|
+
handle.target = target;
|
|
190
|
+
return handle;
|
|
191
|
+
}
|
|
192
|
+
|
|
165
193
|
/// <summary>
|
|
166
194
|
/// Executes a callback after a delay.
|
|
167
195
|
/// </summary>
|
|
@@ -345,6 +373,56 @@ namespace Hyper.Internal.Animation
|
|
|
345
373
|
handle.InvokeComplete();
|
|
346
374
|
}
|
|
347
375
|
|
|
376
|
+
private static IEnumerator AnimateFillAmount(Image target, float endValue, float duration, TweenHandle handle)
|
|
377
|
+
{
|
|
378
|
+
float startValue = target.fillAmount;
|
|
379
|
+
float elapsed = 0f;
|
|
380
|
+
|
|
381
|
+
while (elapsed < duration)
|
|
382
|
+
{
|
|
383
|
+
if (target == null)
|
|
384
|
+
{
|
|
385
|
+
UntrackCoroutine(target, handle.coroutine);
|
|
386
|
+
yield break;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
elapsed += handle.useUnscaledTime ? Time.unscaledDeltaTime : Time.deltaTime;
|
|
390
|
+
float t = Mathf.Clamp01(elapsed / duration);
|
|
391
|
+
float easedT = ApplyEasing(t, handle.ease);
|
|
392
|
+
target.fillAmount = Mathf.Lerp(startValue, endValue, easedT);
|
|
393
|
+
yield return null;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
target.fillAmount = endValue;
|
|
397
|
+
UntrackCoroutine(target, handle.coroutine);
|
|
398
|
+
handle.InvokeComplete();
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
private static IEnumerator AnimateScale(Transform target, Vector3 endValue, float duration, TweenHandle handle)
|
|
402
|
+
{
|
|
403
|
+
Vector3 startValue = target.localScale;
|
|
404
|
+
float elapsed = 0f;
|
|
405
|
+
|
|
406
|
+
while (elapsed < duration)
|
|
407
|
+
{
|
|
408
|
+
if (target == null)
|
|
409
|
+
{
|
|
410
|
+
UntrackCoroutine(target, handle.coroutine);
|
|
411
|
+
yield break;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
elapsed += handle.useUnscaledTime ? Time.unscaledDeltaTime : Time.deltaTime;
|
|
415
|
+
float t = Mathf.Clamp01(elapsed / duration);
|
|
416
|
+
float easedT = ApplyEasing(t, handle.ease);
|
|
417
|
+
target.localScale = Vector3.Lerp(startValue, endValue, easedT);
|
|
418
|
+
yield return null;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
target.localScale = endValue;
|
|
422
|
+
UntrackCoroutine(target, handle.coroutine);
|
|
423
|
+
handle.InvokeComplete();
|
|
424
|
+
}
|
|
425
|
+
|
|
348
426
|
private static IEnumerator DelayedCallCoroutine(float delay, Action callback, TweenHandle handle)
|
|
349
427
|
{
|
|
350
428
|
float elapsed = 0f;
|
|
@@ -467,6 +545,16 @@ namespace Hyper.Internal.Animation
|
|
|
467
545
|
return HyperTween.DoColor(target, endValue, duration);
|
|
468
546
|
}
|
|
469
547
|
|
|
548
|
+
public static HyperTween.TweenHandle DOFillAmount(this Image target, float endValue, float duration)
|
|
549
|
+
{
|
|
550
|
+
return HyperTween.DoFillAmount(target, endValue, duration);
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
public static HyperTween.TweenHandle DOScale(this Transform target, Vector3 endValue, float duration)
|
|
554
|
+
{
|
|
555
|
+
return HyperTween.DoScale(target, endValue, duration);
|
|
556
|
+
}
|
|
557
|
+
|
|
470
558
|
public static void DOKill(this Component target)
|
|
471
559
|
{
|
|
472
560
|
HyperTween.Kill(target);
|
|
@@ -4,32 +4,82 @@ using TMPro;
|
|
|
4
4
|
using UnityEngine;
|
|
5
5
|
using UnityEngine.UI;
|
|
6
6
|
|
|
7
|
-
|
|
8
7
|
namespace Hyper.Internal
|
|
9
8
|
{
|
|
10
9
|
internal class ControlBar : MonoBehaviour
|
|
11
10
|
{
|
|
11
|
+
[Header("UI Components")]
|
|
12
|
+
public Image roundedBG;
|
|
12
13
|
[SerializeField] TextMeshProUGUI scoreText;
|
|
13
14
|
[SerializeField] private RectTransform scoreTextRect;
|
|
14
15
|
[SerializeField] private RectTransform timerText;
|
|
15
16
|
[SerializeField] private Image safeAreaFillerBG;
|
|
16
|
-
public Image roundedBG;
|
|
17
17
|
[SerializeField] private Image pauseButtonImage;
|
|
18
18
|
[SerializeField] private Image pauseBarsImage;
|
|
19
|
+
[SerializeField] private Button connectionStatusIcon;
|
|
20
|
+
|
|
21
|
+
[Header("Sprites")]
|
|
19
22
|
[SerializeField] Sprite portraitBG;
|
|
20
23
|
[SerializeField] Sprite landscapeBG;
|
|
21
24
|
[SerializeField] Sprite pauseBarsLight;
|
|
22
25
|
[SerializeField] Sprite pauseBarsDark;
|
|
23
26
|
|
|
27
|
+
[Header("Lives Display")]
|
|
28
|
+
[SerializeField] private GameObject livesDisplayPrefab;
|
|
29
|
+
|
|
30
|
+
[Header("Health Bar Display")]
|
|
31
|
+
[SerializeField] private GameObject healthBarDisplayPrefab;
|
|
32
|
+
|
|
24
33
|
private GameManager _gameManager;
|
|
34
|
+
private TextMeshProUGUI _scoreTextComponent;
|
|
35
|
+
private TextMeshProUGUI _timerTextComponent;
|
|
36
|
+
private LivesDisplay _livesDisplay;
|
|
37
|
+
private HealthBarDisplay _healthBarDisplay;
|
|
38
|
+
|
|
39
|
+
// Layout constants
|
|
40
|
+
private const float CENTERED_LAYOUT_SCORE_Y = 31f;
|
|
41
|
+
private const float CENTERED_LAYOUT_TIMER_Y = -13f;
|
|
42
|
+
private const float CENTERED_LAYOUT_SCORE_FONT_SIZE = 100f;
|
|
43
|
+
private const float CENTERED_LAYOUT_TIMER_FONT_SIZE = 50f;
|
|
44
|
+
|
|
45
|
+
private const float DEFAULT_LAYOUT_SCORE_Y = 10f;
|
|
46
|
+
private const float DEFAULT_LAYOUT_TIMER_X = 35f;
|
|
47
|
+
private const float DEFAULT_LAYOUT_TIMER_Y = 10f;
|
|
48
|
+
private const float DEFAULT_LAYOUT_SCORE_FONT_SIZE = 100f;
|
|
49
|
+
private const float DEFAULT_LAYOUT_TIMER_FONT_SIZE = 60f;
|
|
50
|
+
|
|
51
|
+
// Theme constants
|
|
52
|
+
private const string LIGHT_THEME_BG_COLOR = "#F5F5F5";
|
|
53
|
+
private const string LIGHT_THEME_TEXT_COLOR = "#434343";
|
|
54
|
+
private const float DARK_THEME_PAUSE_BUTTON_ALPHA = 0.25f;
|
|
55
|
+
private const float LIGHT_THEME_PAUSE_BUTTON_ALPHA = 1f;
|
|
25
56
|
|
|
26
57
|
void Awake()
|
|
27
58
|
{
|
|
28
59
|
_gameManager = HyperRuntime.GameManager;
|
|
60
|
+
CacheTextComponents();
|
|
29
61
|
|
|
30
62
|
RectTransform rect = transform.GetComponent<RectTransform>();
|
|
63
|
+
ConfigureOrientation(rect);
|
|
64
|
+
ConfigureLayout();
|
|
65
|
+
ConfigureTheme();
|
|
66
|
+
|
|
67
|
+
connectionStatusIcon.onClick.AddListener(ShowConnectionLostStatus);
|
|
68
|
+
}
|
|
31
69
|
|
|
32
|
-
|
|
70
|
+
private void OnDestroy()
|
|
71
|
+
{
|
|
72
|
+
connectionStatusIcon.onClick.RemoveListener(ShowConnectionLostStatus);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private void CacheTextComponents()
|
|
76
|
+
{
|
|
77
|
+
_scoreTextComponent = scoreTextRect.GetComponent<TextMeshProUGUI>();
|
|
78
|
+
_timerTextComponent = timerText.GetComponent<TextMeshProUGUI>();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private void ConfigureOrientation(RectTransform rect)
|
|
82
|
+
{
|
|
33
83
|
if (_gameManager.IsPortrait())
|
|
34
84
|
{
|
|
35
85
|
roundedBG.sprite = portraitBG;
|
|
@@ -40,62 +90,174 @@ namespace Hyper.Internal
|
|
|
40
90
|
roundedBG.sprite = landscapeBG;
|
|
41
91
|
rect.sizeDelta = new Vector2(rect.sizeDelta.x, 180);
|
|
42
92
|
}
|
|
93
|
+
}
|
|
43
94
|
|
|
95
|
+
private void ConfigureLayout()
|
|
96
|
+
{
|
|
97
|
+
switch (_gameManager.ControlBarLayout)
|
|
98
|
+
{
|
|
99
|
+
case ControlBarLayout.HeartsLeft:
|
|
100
|
+
ApplyCenteredLayout();
|
|
101
|
+
SetupLivesDisplay();
|
|
102
|
+
break;
|
|
103
|
+
case ControlBarLayout.HealthBarLeft:
|
|
104
|
+
ApplyCenteredLayout();
|
|
105
|
+
HideLivesDisplay();
|
|
106
|
+
SetupHealthBarDisplay();
|
|
107
|
+
break;
|
|
108
|
+
case ControlBarLayout.Default:
|
|
109
|
+
ApplyDefaultLayout();
|
|
110
|
+
HideLivesDisplay();
|
|
111
|
+
HideHealthBarDisplay();
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
44
115
|
|
|
45
|
-
|
|
46
|
-
|
|
116
|
+
private void SetupLivesDisplay()
|
|
117
|
+
{
|
|
118
|
+
if (_livesDisplay == null && livesDisplayPrefab != null)
|
|
47
119
|
{
|
|
48
|
-
|
|
49
|
-
|
|
120
|
+
GameObject livesInstance = Instantiate(livesDisplayPrefab, roundedBG.transform);
|
|
121
|
+
_livesDisplay = livesInstance.GetComponent<LivesDisplay>();
|
|
50
122
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
123
|
+
if (_livesDisplay == null)
|
|
124
|
+
{
|
|
125
|
+
Debug.LogError("[ControlBar] LivesDisplay prefab does not have LivesDisplay component!");
|
|
126
|
+
Destroy(livesInstance);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Position on the left side where timer would be in default layout
|
|
131
|
+
RectTransform livesRect = livesInstance.GetComponent<RectTransform>();
|
|
132
|
+
if (livesRect != null)
|
|
133
|
+
{
|
|
134
|
+
livesRect.anchoredPosition = new Vector2(DEFAULT_LAYOUT_TIMER_X, DEFAULT_LAYOUT_TIMER_Y);
|
|
135
|
+
livesRect.anchorMin = new Vector2(0f, 0.5f);
|
|
136
|
+
livesRect.anchorMax = new Vector2(0f, 0.5f);
|
|
137
|
+
livesRect.pivot = new Vector2(0, 0.5f);
|
|
138
|
+
}
|
|
56
139
|
}
|
|
57
|
-
|
|
140
|
+
|
|
141
|
+
if (_livesDisplay != null)
|
|
58
142
|
{
|
|
59
|
-
|
|
60
|
-
|
|
143
|
+
_livesDisplay.gameObject.SetActive(true);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
61
146
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
timerText.GetComponent<TextMeshProUGUI>().alignment = TextAlignmentOptions.MidlineLeft;
|
|
147
|
+
private void HideLivesDisplay()
|
|
148
|
+
{
|
|
149
|
+
if (_livesDisplay != null)
|
|
150
|
+
{
|
|
151
|
+
_livesDisplay.gameObject.SetActive(false);
|
|
68
152
|
}
|
|
153
|
+
}
|
|
69
154
|
|
|
70
|
-
|
|
71
|
-
|
|
155
|
+
private void SetupHealthBarDisplay()
|
|
156
|
+
{
|
|
157
|
+
if (_healthBarDisplay == null && healthBarDisplayPrefab != null)
|
|
72
158
|
{
|
|
73
|
-
|
|
74
|
-
|
|
159
|
+
GameObject healthBarInstance = Instantiate(healthBarDisplayPrefab, roundedBG.transform);
|
|
160
|
+
_healthBarDisplay = healthBarInstance.GetComponent<HealthBarDisplay>();
|
|
75
161
|
|
|
76
|
-
|
|
77
|
-
|
|
162
|
+
if (_healthBarDisplay == null)
|
|
163
|
+
{
|
|
164
|
+
Debug.LogError("[ControlBar] HealthBarDisplay prefab does not have HealthBarDisplay component!");
|
|
165
|
+
Destroy(healthBarInstance);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
78
168
|
|
|
79
|
-
//
|
|
80
|
-
|
|
81
|
-
|
|
169
|
+
// Position on the left side where timer would be in default layout
|
|
170
|
+
RectTransform healthBarRect = healthBarInstance.GetComponent<RectTransform>();
|
|
171
|
+
if (healthBarRect != null)
|
|
172
|
+
{
|
|
173
|
+
healthBarRect.anchoredPosition = new Vector2(DEFAULT_LAYOUT_TIMER_X, DEFAULT_LAYOUT_TIMER_Y);
|
|
174
|
+
healthBarRect.anchorMin = new Vector2(0f, 0.5f);
|
|
175
|
+
healthBarRect.anchorMax = new Vector2(0f, 0.5f);
|
|
176
|
+
healthBarRect.pivot = new Vector2(0, 0.5f);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (_healthBarDisplay != null)
|
|
181
|
+
{
|
|
182
|
+
_healthBarDisplay.gameObject.SetActive(true);
|
|
82
183
|
}
|
|
83
|
-
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
private void HideHealthBarDisplay()
|
|
187
|
+
{
|
|
188
|
+
if (_healthBarDisplay != null)
|
|
84
189
|
{
|
|
85
|
-
|
|
86
|
-
|
|
190
|
+
_healthBarDisplay.gameObject.SetActive(false);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
private void ApplyCenteredLayout()
|
|
195
|
+
{
|
|
196
|
+
scoreTextRect.anchoredPosition = new Vector2(0, CENTERED_LAYOUT_SCORE_Y);
|
|
197
|
+
_scoreTextComponent.fontSize = CENTERED_LAYOUT_SCORE_FONT_SIZE;
|
|
87
198
|
|
|
88
|
-
|
|
89
|
-
|
|
199
|
+
timerText.anchoredPosition = new Vector2(0, CENTERED_LAYOUT_TIMER_Y);
|
|
200
|
+
timerText.anchorMin = new Vector2(0.5f, 0.5f);
|
|
201
|
+
timerText.anchorMax = new Vector2(0.5f, 0.5f);
|
|
202
|
+
timerText.pivot = new Vector2(0.5f, 0.5f);
|
|
203
|
+
_timerTextComponent.fontSize = CENTERED_LAYOUT_TIMER_FONT_SIZE;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
private void ApplyDefaultLayout()
|
|
207
|
+
{
|
|
208
|
+
scoreTextRect.anchoredPosition = new Vector2(0, DEFAULT_LAYOUT_SCORE_Y);
|
|
209
|
+
_scoreTextComponent.fontSize = DEFAULT_LAYOUT_SCORE_FONT_SIZE;
|
|
90
210
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
211
|
+
timerText.anchoredPosition = new Vector2(DEFAULT_LAYOUT_TIMER_X, DEFAULT_LAYOUT_TIMER_Y);
|
|
212
|
+
timerText.anchorMin = new Vector2(0f, 0.5f);
|
|
213
|
+
timerText.anchorMax = new Vector2(0f, 0.5f);
|
|
214
|
+
timerText.pivot = new Vector2(0, 0.5f);
|
|
215
|
+
_timerTextComponent.fontSize = DEFAULT_LAYOUT_TIMER_FONT_SIZE;
|
|
216
|
+
_timerTextComponent.alignment = TextAlignmentOptions.MidlineLeft;
|
|
95
217
|
}
|
|
96
218
|
|
|
97
|
-
|
|
219
|
+
private void ConfigureTheme()
|
|
98
220
|
{
|
|
221
|
+
switch (_gameManager.ControlBarTheme)
|
|
222
|
+
{
|
|
223
|
+
case ControlBarTheme.Dark:
|
|
224
|
+
ApplyDarkTheme();
|
|
225
|
+
break;
|
|
226
|
+
case ControlBarTheme.Light:
|
|
227
|
+
ApplyLightTheme();
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
private void ApplyDarkTheme()
|
|
233
|
+
{
|
|
234
|
+
roundedBG.color = Color.black;
|
|
235
|
+
safeAreaFillerBG.color = Color.black;
|
|
236
|
+
|
|
237
|
+
_scoreTextComponent.color = Color.white;
|
|
238
|
+
_timerTextComponent.color = Color.white;
|
|
239
|
+
|
|
240
|
+
pauseButtonImage.color = new Color(1, 1, 1, DARK_THEME_PAUSE_BUTTON_ALPHA);
|
|
241
|
+
pauseBarsImage.sprite = pauseBarsDark;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
private void ApplyLightTheme()
|
|
245
|
+
{
|
|
246
|
+
Color bgColor = HexToColor(LIGHT_THEME_BG_COLOR);
|
|
247
|
+
Color textColor = HexToColor(LIGHT_THEME_TEXT_COLOR);
|
|
248
|
+
|
|
249
|
+
roundedBG.color = bgColor;
|
|
250
|
+
safeAreaFillerBG.color = bgColor;
|
|
251
|
+
|
|
252
|
+
_scoreTextComponent.color = textColor;
|
|
253
|
+
_timerTextComponent.color = textColor;
|
|
254
|
+
|
|
255
|
+
pauseButtonImage.color = new Color(1, 1, 1, LIGHT_THEME_PAUSE_BUTTON_ALPHA);
|
|
256
|
+
pauseBarsImage.sprite = pauseBarsLight;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
private void ShowConnectionLostStatus()
|
|
260
|
+
{
|
|
99
261
|
// Show the connection lost status
|
|
100
262
|
_gameManager.ShowConnectionLost();
|
|
101
263
|
}
|
|
@@ -105,6 +267,24 @@ namespace Hyper.Internal
|
|
|
105
267
|
scoreText.SetText(HyperRuntime.DataManager.CurrentScore.ToString("N0"));
|
|
106
268
|
}
|
|
107
269
|
|
|
270
|
+
/// <summary>
|
|
271
|
+
/// Gets the LivesDisplay component if available.
|
|
272
|
+
/// Only available when ControlBarLayout is set to HeartsLeft.
|
|
273
|
+
/// </summary>
|
|
274
|
+
public LivesDisplay GetLivesDisplay()
|
|
275
|
+
{
|
|
276
|
+
return _livesDisplay;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/// <summary>
|
|
280
|
+
/// Gets the HealthBarDisplay component if available.
|
|
281
|
+
/// Only available when ControlBarLayout is set to HealthBarGreenLeft.
|
|
282
|
+
/// </summary>
|
|
283
|
+
public HealthBarDisplay GetHealthBarDisplay()
|
|
284
|
+
{
|
|
285
|
+
return _healthBarDisplay;
|
|
286
|
+
}
|
|
287
|
+
|
|
108
288
|
Color HexToColor(string hex)
|
|
109
289
|
{
|
|
110
290
|
if (ColorUtility.TryParseHtmlString(hex, out Color color))
|