app.hypergames.hypersdk 1.3.4 → 1.4.1

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.
Files changed (86) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/Editor/{HyperSDK.Editor.asmdef → Hyper.Editor.asmdef} +1 -1
  3. package/Editor/Resources/ControlBarPreviews/Dark/Default.png +0 -0
  4. package/Editor/Resources/ControlBarPreviews/Dark/Default.png.meta +143 -0
  5. package/Editor/Resources/ControlBarPreviews/Dark/HealthBarLeft.png +0 -0
  6. package/Editor/Resources/ControlBarPreviews/Dark/HealthBarLeft.png.meta +143 -0
  7. package/Editor/Resources/ControlBarPreviews/Dark/HeartsLeft.png +0 -0
  8. package/Editor/Resources/ControlBarPreviews/Dark/HeartsLeft.png.meta +169 -0
  9. package/Editor/Resources/ControlBarPreviews/Dark.meta +8 -0
  10. package/Editor/Resources/ControlBarPreviews/Light/Default.png +0 -0
  11. package/Editor/Resources/ControlBarPreviews/Light/Default.png.meta +143 -0
  12. package/Editor/Resources/ControlBarPreviews/Light/HealthBarLeft.png +0 -0
  13. package/Editor/Resources/ControlBarPreviews/Light/HealthBarLeft.png.meta +143 -0
  14. package/Editor/Resources/ControlBarPreviews/Light/HeartsLeft.png +0 -0
  15. package/Editor/Resources/ControlBarPreviews/Light/HeartsLeft.png.meta +143 -0
  16. package/Editor/Resources/ControlBarPreviews/Light.meta +8 -0
  17. package/Editor/Resources/ControlBarPreviews.meta +8 -0
  18. package/Editor/Scripts/Inspectors/HyperSDKSettingsEditor.cs +206 -0
  19. package/Editor/Scripts/Inspectors/HyperSDKSettingsEditor.cs.meta +2 -0
  20. package/Editor/Scripts/Inspectors.meta +8 -0
  21. package/Editor/Scripts/Tools/HyperBuildAssistant.cs +53 -3
  22. package/Editor/Scripts/Windows/HyperCoreSettingsWindow.cs +0 -8
  23. package/Editor/Scripts/Windows/HyperGameContentWindow.cs +0 -8
  24. package/Editor/Scripts/Windows/HyperSettingsWindow.cs +3 -3
  25. package/HyperLoader.unity +4 -49
  26. package/Runtime/Internal/AssemblyInfo.cs +1 -1
  27. package/Runtime/Internal/Managers/EventManager.cs +4 -0
  28. package/Runtime/Internal/Managers/GameManager.cs +173 -5
  29. package/Runtime/Internal/ScriptableObjects/HyperSDKSettings.cs +16 -10
  30. package/Runtime/Internal/UI/Animation/BlinkingText.cs +1 -1
  31. package/Runtime/Internal/UI/Animation/HyperTween.cs +88 -0
  32. package/Runtime/Internal/UI/Components/ControlBar.cs +220 -40
  33. package/Runtime/Internal/UI/Components/HealthBarDisplay.cs +269 -0
  34. package/Runtime/Internal/UI/Components/HealthBarDisplay.cs.meta +2 -0
  35. package/Runtime/Internal/UI/Components/LivesDisplay.cs +327 -0
  36. package/Runtime/Internal/UI/Components/LivesDisplay.cs.meta +2 -0
  37. package/Runtime/Internal/UI/Modals/ExitGameMenuModal.cs +46 -0
  38. package/Runtime/Internal/UI/Modals/ExitGameMenuModal.cs.meta +11 -0
  39. package/Runtime/Internal/UI/Modals/StartingInstructionModal.cs +202 -3
  40. package/Runtime/Internal/Utils/HyperConstants.cs +27 -0
  41. package/Runtime/Public/Core/HyperSDK.cs +68 -0
  42. package/Runtime/Resources/Fonts/Wonder Boys/Wonder Boys + Hyper BIG.mat +1 -1
  43. package/Runtime/Resources/Fonts/Wonder Boys/Wonder Boys + Shadows.mat +1 -1
  44. package/Runtime/Resources/HyperSDKSettings.asset +3 -2
  45. package/Runtime/Resources/Sprites/Big Icons/Exit.png +0 -0
  46. package/Runtime/Resources/Sprites/Big Icons/Exit.png.meta +195 -0
  47. package/Runtime/Resources/Sprites/Control Bar/Ellipse 3.png +0 -0
  48. package/Runtime/Resources/Sprites/Control Bar/Ellipse 3.png.meta +169 -0
  49. package/Runtime/Resources/Sprites/Control Bar/Health Bar - Green Fill.png +0 -0
  50. package/Runtime/Resources/Sprites/Control Bar/Health Bar - Green Fill.png.meta +169 -0
  51. package/Runtime/Resources/Sprites/Control Bar/Health Bar - Underlay.png +0 -0
  52. package/Runtime/Resources/Sprites/Control Bar/Health Bar - Underlay.png.meta +169 -0
  53. package/Runtime/Resources/Sprites/Control Bar/Health Bar.png +0 -0
  54. package/Runtime/Resources/Sprites/Control Bar/Health Bar.png.meta +169 -0
  55. package/Runtime/Resources/Sprites/Control Bar/heart.empty.png +0 -0
  56. package/Runtime/Resources/Sprites/Control Bar/heart.empty.png.meta +169 -0
  57. package/Runtime/Resources/Sprites/Control Bar/heart.fill.png +0 -0
  58. package/Runtime/Resources/Sprites/Control Bar/heart.fill.png.meta +169 -0
  59. package/Runtime/Resources/Sprites/Frames/{Game Over P.png.meta → Game Over.png.meta } +4 -4
  60. package/Runtime/Resources/Sprites/HYPERGAMES_Logo.png.meta +3 -3
  61. package/Runtime/Resources/Sprites/Hyper Atlas.spriteatlasv2 +6 -0
  62. package/Runtime/Resources/Sprites/Start CTAs/Hand.PNG +0 -0
  63. package/Runtime/Resources/Sprites/Start CTAs/Hand.PNG.meta +169 -0
  64. package/Runtime/Resources/Sprites/Start CTAs/Line .PNG +0 -0
  65. package/Runtime/Resources/Sprites/Start CTAs/Line .PNG.meta +169 -0
  66. package/Runtime/Resources/Sprites/Start CTAs/Swipe Gesture GIF.controller +130 -0
  67. package/Runtime/Resources/Sprites/Start CTAs/Swipe Gesture GIF.controller.meta +8 -0
  68. package/Runtime/Resources/Sprites/Start CTAs/Swipe Gesture.anim +158 -0
  69. package/Runtime/Resources/Sprites/Start CTAs/Swipe Gesture.anim.meta +8 -0
  70. package/Runtime/Resources/Sprites/Start CTAs.meta +8 -0
  71. package/Runtime/Resources/UIPrefabs/Control Bar Objects/Health Bar Display.prefab +361 -0
  72. package/Runtime/Resources/UIPrefabs/Control Bar Objects/Health Bar Display.prefab.meta +7 -0
  73. package/Runtime/Resources/UIPrefabs/Control Bar Objects/Lives Display .prefab +246 -0
  74. package/Runtime/Resources/UIPrefabs/Control Bar Objects/Lives Display .prefab.meta +7 -0
  75. package/Runtime/Resources/UIPrefabs/Control Bar Objects.meta +8 -0
  76. package/Runtime/Resources/UIPrefabs/ControlBar.prefab +131 -17
  77. package/Runtime/Resources/UIPrefabs/ExitGameMenuModal.prefab +1043 -0
  78. package/Runtime/Resources/UIPrefabs/ExitGameMenuModal.prefab.meta +7 -0
  79. package/Runtime/Resources/UIPrefabs/GamePausedModal_Battle.prefab +1 -1
  80. package/Runtime/Resources/UIPrefabs/StartingInstructionModal.prefab +271 -57
  81. package/Runtime/Resources/UIPrefabs/TutorialLandscapeModal.prefab +1 -1
  82. package/Runtime/Resources/UIPrefabs/TutorialPortraitModal.prefab +1 -1
  83. package/Runtime/Shared/DTOs/Enums.cs +22 -6
  84. package/package.json +1 -1
  85. /package/Editor/{HyperSDK.Editor.asmdef.meta → Hyper.Editor.asmdef.meta} +0 -0
  86. /package/Runtime/Resources/Sprites/Frames/{Game Over P.png → Game Over.png} +0 -0
@@ -0,0 +1,327 @@
1
+ using System.Collections;
2
+ using UnityEngine;
3
+ using TMPro;
4
+ using UnityEngine.UI;
5
+ using Hyper.Internal.Animation;
6
+
7
+ namespace Hyper.Internal
8
+ {
9
+ /// <summary>
10
+ /// Manages the display of lives/hearts in the control bar.
11
+ /// Dynamically creates and manages heart icons based on current lives.
12
+ /// </summary>
13
+ internal class LivesDisplay : MonoBehaviour
14
+ {
15
+ [Header("Configuration")]
16
+ [SerializeField] private Sprite heartFullSprite;
17
+ [SerializeField] private Sprite heartEmptySprite;
18
+ [SerializeField] private float heartSize = 50f;
19
+ [SerializeField] private float spacing = 10f;
20
+ [SerializeField, Min(1)] private int maxVisibleHearts = 3;
21
+
22
+ [Header("Animation")]
23
+ [SerializeField] private float fadeDuration = 0.3f;
24
+ [SerializeField] private bool useScaleAnimation = false;
25
+ [SerializeField] private float scaleAmount = 0.8f;
26
+ [SerializeField] private float scaleDuration = 0.15f;
27
+
28
+ [Header("Container")]
29
+ [SerializeField] private RectTransform container;
30
+ [SerializeField] private TextMeshProUGUI overflowLabel;
31
+
32
+ private int _currentLives;
33
+ private int _maxLives;
34
+ private Image[] _heartImages;
35
+ private bool _livesExhaustedTriggered;
36
+
37
+ private void Awake()
38
+ {
39
+ if (container == null)
40
+ {
41
+ container = GetComponent<RectTransform>();
42
+ }
43
+
44
+ ConfigureLayoutGroup();
45
+
46
+ if (overflowLabel != null)
47
+ {
48
+ overflowLabel.gameObject.SetActive(false);
49
+ overflowLabel.text = string.Empty;
50
+ }
51
+ }
52
+
53
+ private void ConfigureLayoutGroup()
54
+ {
55
+ HorizontalLayoutGroup layoutGroup = container.GetComponent<HorizontalLayoutGroup>();
56
+ if (layoutGroup == null)
57
+ {
58
+ layoutGroup = container.gameObject.AddComponent<HorizontalLayoutGroup>();
59
+ }
60
+
61
+ layoutGroup.spacing = spacing;
62
+ layoutGroup.childAlignment = TextAnchor.MiddleLeft;
63
+ layoutGroup.childControlWidth = false;
64
+ layoutGroup.childControlHeight = false;
65
+ layoutGroup.childForceExpandWidth = false;
66
+ layoutGroup.childForceExpandHeight = false;
67
+ }
68
+
69
+ /// <summary>
70
+ /// Initializes the lives display with a maximum number of lives.
71
+ /// Creates heart icons based on the max value.
72
+ /// </summary>
73
+ /// <param name="maxLives">Maximum number of lives to display</param>
74
+ /// <param name="initialLives">Initial number of lives (defaults to max)</param>
75
+ public void Initialize(int maxLives, int initialLives = -1)
76
+ {
77
+ if (maxLives < 0)
78
+ {
79
+ Debug.LogWarning("[LivesDisplay] Max lives cannot be negative. Setting to 0.");
80
+ maxLives = 0;
81
+ }
82
+
83
+ _maxLives = maxLives;
84
+ _currentLives = initialLives >= 0 ? initialLives : maxLives;
85
+
86
+ if (_currentLives > _maxLives)
87
+ {
88
+ _currentLives = _maxLives;
89
+ }
90
+
91
+ _livesExhaustedTriggered = false;
92
+ CreateHeartIcons();
93
+ UpdateDisplay();
94
+ }
95
+
96
+ /// <summary>
97
+ /// Sets the current number of lives and updates the display.
98
+ /// </summary>
99
+ /// <param name="lives">Number of lives to set</param>
100
+ public void SetLives(int lives)
101
+ {
102
+ int previousLives = _currentLives;
103
+ _currentLives = Mathf.Clamp(lives, 0, _maxLives);
104
+ UpdateDisplay();
105
+
106
+ // Only check if lives decreased to 0
107
+ if (previousLives > 0 && _currentLives == 0)
108
+ {
109
+ CheckLivesExhausted();
110
+ }
111
+ }
112
+
113
+ /// <summary>
114
+ /// Adds one life (up to max).
115
+ /// </summary>
116
+ public void AddLife()
117
+ {
118
+ if (_currentLives < _maxLives)
119
+ {
120
+ _currentLives++;
121
+ UpdateDisplay();
122
+ }
123
+ }
124
+
125
+ /// <summary>
126
+ /// Removes one life (down to 0).
127
+ /// </summary>
128
+ public void RemoveLife()
129
+ {
130
+ if (_currentLives > 0)
131
+ {
132
+ int lostLifeIndex = _currentLives - 1;
133
+ _currentLives--;
134
+ UpdateDisplay();
135
+ AnimateLifeLost(lostLifeIndex);
136
+ CheckLivesExhausted();
137
+ }
138
+ }
139
+
140
+ /// <summary>
141
+ /// Gets the current number of lives.
142
+ /// </summary>
143
+ public int GetCurrentLives() => _currentLives;
144
+
145
+ /// <summary>
146
+ /// Gets the maximum number of lives.
147
+ /// </summary>
148
+ public int GetMaxLives() => _maxLives;
149
+
150
+ private void CreateHeartIcons()
151
+ {
152
+ // Clear existing hearts
153
+ ClearHearts();
154
+
155
+ if (_maxLives <= 0)
156
+ {
157
+ _heartImages = new Image[0];
158
+ return;
159
+ }
160
+
161
+ int heartSlots = maxVisibleHearts > 0
162
+ ? Mathf.Min(_maxLives, maxVisibleHearts)
163
+ : _maxLives;
164
+
165
+ _heartImages = new Image[heartSlots];
166
+
167
+ for (int i = 0; i < heartSlots; i++)
168
+ {
169
+ GameObject heartObject = new GameObject($"Heart_{i}");
170
+ heartObject.transform.SetParent(container, false);
171
+
172
+ RectTransform heartRect = heartObject.AddComponent<RectTransform>();
173
+ heartRect.sizeDelta = new Vector2(heartSize, heartSize);
174
+
175
+ Image heartImage = heartObject.AddComponent<Image>();
176
+ heartImage.sprite = heartFullSprite;
177
+ heartImage.preserveAspect = true;
178
+
179
+ _heartImages[i] = heartImage;
180
+ }
181
+ }
182
+
183
+ private void UpdateDisplay()
184
+ {
185
+ if (_heartImages == null) return;
186
+
187
+ for (int i = 0; i < _heartImages.Length; i++)
188
+ {
189
+ if (_heartImages[i] != null)
190
+ {
191
+ bool isFull = i < Mathf.Min(_currentLives, _heartImages.Length);
192
+ _heartImages[i].sprite = isFull ? heartFullSprite : heartEmptySprite;
193
+ _heartImages[i].gameObject.SetActive(true);
194
+
195
+ // Reset color to full opacity for immediate updates
196
+ Color color = _heartImages[i].color;
197
+ color.a = 1f;
198
+ _heartImages[i].color = color;
199
+ }
200
+ }
201
+
202
+ UpdateOverflowLabel();
203
+ }
204
+
205
+ private void AnimateLifeLost(int heartIndex)
206
+ {
207
+ if (_heartImages == null || heartIndex < 0 || heartIndex >= _heartImages.Length)
208
+ return;
209
+
210
+ Image heartImage = _heartImages[heartIndex];
211
+ if (heartImage == null) return;
212
+
213
+ // Update sprite immediately
214
+ Color color = heartImage.color;
215
+ color.a = 0.45f;
216
+ heartImage.color = color;
217
+ heartImage.sprite = heartEmptySprite;
218
+
219
+ // Stop any existing animations on this heart
220
+ HyperTween.Kill(heartImage);
221
+ if (heartImage.transform != null)
222
+ {
223
+ HyperTween.Kill(heartImage.transform);
224
+ }
225
+
226
+ // Fade animation: fade out then fade back in with empty sprite
227
+ AnimateHeartFade(heartImage);
228
+
229
+ // Optional scale animation
230
+ if (useScaleAnimation && heartImage.transform != null)
231
+ {
232
+ AnimateHeartScale(heartImage.transform);
233
+ }
234
+ }
235
+
236
+ private void AnimateHeartFade(Image heartImage)
237
+ {
238
+ if (heartImage == null) return;
239
+
240
+ Color startColor = heartImage.color;
241
+ Color fadeOutColor = new Color(startColor.r, startColor.g, startColor.b, 0f);
242
+ Color fadeInColor = new Color(startColor.r, startColor.g, startColor.b, 1f);
243
+ float halfDuration = fadeDuration * 0.5f;
244
+
245
+ // Fade out, then fade back in
246
+ heartImage.DOColor(fadeOutColor, halfDuration)
247
+ .SetEase(HyperTween.Ease.OutQuad)
248
+ .OnComplete(() =>
249
+ {
250
+ if (heartImage != null)
251
+ {
252
+ heartImage.DOColor(fadeInColor, halfDuration)
253
+ .SetEase(HyperTween.Ease.InQuad);
254
+ }
255
+ });
256
+ }
257
+
258
+ private void AnimateHeartScale(Transform heartTransform)
259
+ {
260
+ if (heartTransform == null) return;
261
+
262
+ Vector3 originalScale = Vector3.one;
263
+ Vector3 scaledDown = originalScale * scaleAmount;
264
+ float halfDuration = scaleDuration * 0.5f;
265
+
266
+ // Scale down, then scale back up
267
+ heartTransform.DOScale(scaledDown, halfDuration)
268
+ .SetEase(HyperTween.Ease.OutQuad)
269
+ .OnComplete(() =>
270
+ {
271
+ if (heartTransform != null)
272
+ {
273
+ heartTransform.DOScale(originalScale, halfDuration)
274
+ .SetEase(HyperTween.Ease.InQuad);
275
+ }
276
+ });
277
+ }
278
+
279
+ private void CheckLivesExhausted()
280
+ {
281
+ if (_currentLives <= 0 && !_livesExhaustedTriggered)
282
+ {
283
+ _livesExhaustedTriggered = true;
284
+ HyperRuntime.EventManager?.InvokeLivesExhaustedEvent();
285
+ }
286
+ }
287
+
288
+ private void ClearHearts()
289
+ {
290
+ if (_heartImages == null) return;
291
+
292
+ foreach (Image heart in _heartImages)
293
+ {
294
+ if (heart != null)
295
+ {
296
+ Destroy(heart.gameObject);
297
+ }
298
+ }
299
+
300
+ _heartImages = null;
301
+ }
302
+
303
+ private void OnDestroy()
304
+ {
305
+ ClearHearts();
306
+ }
307
+
308
+ private void UpdateOverflowLabel()
309
+ {
310
+ if (overflowLabel == null) return;
311
+
312
+ int heartSlots = _heartImages != null ? _heartImages.Length : 0;
313
+ int overflow = Mathf.Max(0, _currentLives - heartSlots);
314
+ if (overflow > 0)
315
+ {
316
+ overflowLabel.gameObject.SetActive(true);
317
+ overflowLabel.text = $"+{overflow}";
318
+ }
319
+ else
320
+ {
321
+ overflowLabel.text = string.Empty;
322
+ overflowLabel.gameObject.SetActive(false);
323
+ }
324
+ }
325
+ }
326
+ }
327
+
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: cb2e75c824ecc1e4f8f4461666f2ae4b
@@ -0,0 +1,46 @@
1
+ using TMPro;
2
+ using UnityEngine;
3
+ using System.Runtime.InteropServices;
4
+ using Hyper.Internal.Managers;
5
+ using Hyper.Shared;
6
+
7
+ namespace Hyper.Internal
8
+ {
9
+ internal class ExitGameMenuModal : MonoBehaviour
10
+ {
11
+ [SerializeField] private CanvasGroup ctaButtonsHolder;
12
+ [SerializeField] private GameObject loadingCircle;
13
+ private GameManager _gameManager;
14
+
15
+ void Awake()
16
+ {
17
+ _gameManager = HyperRuntime.GameManager;
18
+ }
19
+
20
+ private void DisableButtonHolder()
21
+ {
22
+ ctaButtonsHolder.interactable = false;
23
+ ctaButtonsHolder.alpha = 0.6f;
24
+
25
+ loadingCircle.SetActive(true);
26
+ }
27
+
28
+ // Buttons
29
+ public void Exit()
30
+ {
31
+ DisableButtonHolder();
32
+ HyperRuntime.BackendManager.LogEvent(ConsoleEventType.PracticeGameEnd);
33
+ }
34
+
35
+ public void ContinuePlaying()
36
+ {
37
+ Hide();
38
+ }
39
+
40
+ private void Hide()
41
+ {
42
+ _gameManager.HideExitGameMenuModal();
43
+ }
44
+ }
45
+ }
46
+
@@ -0,0 +1,11 @@
1
+ fileFormatVersion: 2
2
+ guid: a90f1b8b2fc0170469bee39da74afb1b
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant:
@@ -1,6 +1,9 @@
1
1
  using System.Runtime.InteropServices;
2
2
  using Hyper.Internal.Managers;
3
+ using Hyper.Shared;
4
+ using TMPro;
3
5
  using UnityEngine;
6
+ using UnityEngine.UI;
4
7
 
5
8
  namespace Hyper.Internal
6
9
  {
@@ -11,10 +14,19 @@ namespace Hyper.Internal
11
14
  [DllImport("__Internal")]
12
15
  private static extern void MarkGameStartedOnHTML();
13
16
  #endif
17
+ [SerializeField] private TextMeshProUGUI startCtaLabel;
18
+ [SerializeField] private BlinkingText blinkingText;
19
+ [SerializeField] private RectTransform swipeGif;
14
20
  private EventManager _eventManager;
15
21
  private DataManager _dataManager;
16
22
  private GameManager _gameManager;
17
23
  private BackendManager _backendManager;
24
+ private StartCTA _currentCTA;
25
+
26
+ // Swipe detection variables
27
+ private Vector2 _swipeStartPosition;
28
+ private bool _isTrackingSwipe;
29
+ private const float SWIPE_THRESHOLD = 50f; // Minimum distance in pixels for a swipe
18
30
 
19
31
  void Awake()
20
32
  {
@@ -24,10 +36,155 @@ namespace Hyper.Internal
24
36
  _backendManager = HyperRuntime.BackendManager;
25
37
  }
26
38
 
27
- public void OnTap()
39
+ void Update()
40
+ {
41
+ if (!gameObject.activeSelf) return;
42
+
43
+ if (_currentCTA == StartCTA.TapToPlay)
44
+ {
45
+ HandleTapInput();
46
+ }
47
+ else
48
+ {
49
+ HandleSwipeInput();
50
+ }
51
+ }
52
+
53
+ /// <summary>
54
+ /// Configures the CTA text and input mode based on the selected StartCTA type.
55
+ /// </summary>
56
+ public void Configure(StartCTA cta)
57
+ {
58
+ _currentCTA = cta;
59
+
60
+ if (startCtaLabel == null)
61
+ {
62
+ // Fallback: try to find it if not assigned
63
+ startCtaLabel = GetComponentInChildren<TextMeshProUGUI>();
64
+ }
65
+
66
+ if (startCtaLabel == null)
67
+ {
68
+ HyperDebug.LogWarning("[StartingInstructionModal] Start CTA label not found. Make sure the TextMeshProUGUI component is assigned in the prefab.");
69
+ return;
70
+ }
71
+
72
+ switch (cta)
73
+ {
74
+ case StartCTA.SwipeToPlayVertical:
75
+ case StartCTA.SwipeToPlayHorizontal:
76
+ startCtaLabel.text = "SWIPE TO PLAY";
77
+ blinkingText.enabled = false;
78
+ break;
79
+ case StartCTA.TapToPlay:
80
+ default:
81
+ startCtaLabel.text = "TAP TO PLAY";
82
+ blinkingText.enabled = true;
83
+ break;
84
+ }
85
+
86
+ UpdateSwipeGraphics();
87
+ }
88
+
89
+ /// <summary>
90
+ /// Handles tap input detection (works with both old and new Input System).
91
+ /// </summary>
92
+ private void HandleTapInput()
93
+ {
94
+ bool tapDetected = false;
95
+
96
+ // Check mouse input (works in editor and desktop)
97
+ if (Input.GetMouseButtonDown(0))
98
+ {
99
+ tapDetected = true;
100
+ }
101
+
102
+ // Check touch input (works on mobile and WebGL)
103
+ if (Input.touchCount > 0)
104
+ {
105
+ Touch touch = Input.GetTouch(0);
106
+ if (touch.phase == TouchPhase.Began)
107
+ {
108
+ tapDetected = true;
109
+ }
110
+ }
111
+
112
+ if (tapDetected)
113
+ {
114
+ StartGame();
115
+ }
116
+ }
117
+
118
+ /// <summary>
119
+ /// Handles swipe input detection (works with both old and new Input System).
120
+ /// </summary>
121
+ private void HandleSwipeInput()
122
+ {
123
+ bool swipeDetected = false;
124
+ Vector2 currentPosition = Vector2.zero;
125
+
126
+ // Check mouse input (works in editor and desktop)
127
+ if (Input.GetMouseButtonDown(0))
128
+ {
129
+ _swipeStartPosition = Input.mousePosition;
130
+ _isTrackingSwipe = true;
131
+ }
132
+ else if (Input.GetMouseButton(0) && _isTrackingSwipe)
133
+ {
134
+ currentPosition = Input.mousePosition;
135
+ Vector2 delta = currentPosition - _swipeStartPosition;
136
+
137
+ if (IsSwipeDirectionValid(delta))
138
+ {
139
+ swipeDetected = true;
140
+ _isTrackingSwipe = false;
141
+ }
142
+ }
143
+ else if (Input.GetMouseButtonUp(0))
144
+ {
145
+ _isTrackingSwipe = false;
146
+ }
147
+
148
+ // Check touch input (works on mobile and WebGL)
149
+ if (Input.touchCount > 0)
150
+ {
151
+ Touch touch = Input.GetTouch(0);
152
+
153
+ if (touch.phase == TouchPhase.Began)
154
+ {
155
+ _swipeStartPosition = touch.position;
156
+ _isTrackingSwipe = true;
157
+ }
158
+ else if (touch.phase == TouchPhase.Moved && _isTrackingSwipe)
159
+ {
160
+ currentPosition = touch.position;
161
+ Vector2 delta = currentPosition - _swipeStartPosition;
162
+
163
+ if (IsSwipeDirectionValid(delta))
164
+ {
165
+ swipeDetected = true;
166
+ _isTrackingSwipe = false;
167
+ }
168
+ }
169
+ else if (touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled)
170
+ {
171
+ _isTrackingSwipe = false;
172
+ }
173
+ }
174
+
175
+ if (swipeDetected)
176
+ {
177
+ StartGame();
178
+ }
179
+ }
180
+
181
+ /// <summary>
182
+ /// Starts the game - called when tap or swipe is detected.
183
+ /// </summary>
184
+ private void StartGame()
28
185
  {
29
186
  _gameManager.HideStartGameDeadlineSnackBar();
30
- _dataManager.UpdateScore(0);
187
+ _dataManager.UpdateScore(0);
31
188
  HyperRuntime.Timer.StartActiveGameTimer();
32
189
 
33
190
  // Only proceed if connected
@@ -39,10 +196,52 @@ namespace Hyper.Internal
39
196
  }
40
197
 
41
198
  #if UNITY_WEBGL && !UNITY_EDITOR
42
- MarkGameStartedOnHTML();
199
+ MarkGameStartedOnHTML();
43
200
  #endif
44
201
  _eventManager.InvokeGameStartEvent();
45
202
  gameObject.SetActive(false);
46
203
  }
204
+
205
+ private void UpdateSwipeGraphics()
206
+ {
207
+ bool showVertical = _currentCTA == StartCTA.SwipeToPlayVertical;
208
+ bool showHorizontal = _currentCTA == StartCTA.SwipeToPlayHorizontal;
209
+
210
+ if (swipeGif != null)
211
+ {
212
+ if (showVertical)
213
+ {
214
+ swipeGif.anchoredPosition = new Vector3(0, 286, 0);
215
+ swipeGif.transform.rotation = Quaternion.Euler(0, 0, 90);
216
+ swipeGif.gameObject.SetActive(true);
217
+ }
218
+ else if (showHorizontal)
219
+ {
220
+ swipeGif.anchoredPosition = new Vector3(0, 220, 0);
221
+ swipeGif.transform.rotation = Quaternion.Euler(0, 0, 0);
222
+ swipeGif.gameObject.SetActive(true);
223
+ }
224
+ else
225
+ {
226
+ swipeGif.gameObject.SetActive(false);
227
+ }
228
+ }
229
+ }
230
+
231
+ private bool IsSwipeDirectionValid(Vector2 delta)
232
+ {
233
+ float absX = Mathf.Abs(delta.x);
234
+ float absY = Mathf.Abs(delta.y);
235
+
236
+ switch (_currentCTA)
237
+ {
238
+ case StartCTA.SwipeToPlayVertical:
239
+ return absY >= SWIPE_THRESHOLD && absY >= absX;
240
+ case StartCTA.SwipeToPlayHorizontal:
241
+ return absX >= SWIPE_THRESHOLD && absX >= absY;
242
+ default:
243
+ return false;
244
+ }
245
+ }
47
246
  }
48
247
  }
@@ -65,6 +65,33 @@ namespace Hyper.Internal
65
65
  return devPath;
66
66
  }
67
67
  }
68
+
69
+ /// <summary>
70
+ /// Returns the control bar preview folder path, checking dev mode (Assets/) first, then package mode (Packages/).
71
+ /// </summary>
72
+ public static string CONTROL_BAR_PREVIEW_FOLDER_PATH
73
+ {
74
+ get
75
+ {
76
+ const string devPath = "Assets/HyperSDK/Editor/Resources/ControlBarPreviews";
77
+ const string packagePath = "Packages/app.hypergames.hypersdk/Editor/Resources/ControlBarPreviews";
78
+
79
+ // Check dev mode first (Assets/)
80
+ if (AssetDatabase.IsValidFolder(devPath))
81
+ {
82
+ return devPath;
83
+ }
84
+
85
+ // Fall back to package mode (Packages/)
86
+ if (AssetDatabase.IsValidFolder(packagePath))
87
+ {
88
+ return packagePath;
89
+ }
90
+
91
+ // Default to dev path if neither found (for backwards compatibility)
92
+ return devPath;
93
+ }
94
+ }
68
95
  #endif
69
96
 
70
97
  #endregion