Build TravelRun intro and tutorial flow
This commit is contained in:
@@ -0,0 +1,316 @@
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
public class ItemFeedbackEffect : MonoBehaviour
|
||||
{
|
||||
private const string SortingLayerName = "Foreground";
|
||||
private const float Lifetime = 0.85f;
|
||||
|
||||
private static Sprite ringSprite;
|
||||
private static Sprite dotSprite;
|
||||
private static Sprite sparkleSprite;
|
||||
|
||||
private SpriteRenderer ringRenderer;
|
||||
private SpriteRenderer iconRenderer;
|
||||
private SpriteRenderer[] sparkleRenderers;
|
||||
private TextMeshPro labelText;
|
||||
private Color mainColor;
|
||||
private float elapsedTime;
|
||||
|
||||
public static void Spawn(Vector3 worldPosition, Sprite itemSprite, GameManager.TutorialItemType itemType, bool blockedDamage)
|
||||
{
|
||||
GameObject effectObject = new GameObject(blockedDamage ? "Item Block Feedback" : "Item Pickup Feedback");
|
||||
effectObject.transform.position = worldPosition + new Vector3(0f, blockedDamage ? 1.1f : 0.85f, 0f);
|
||||
|
||||
ItemFeedbackEffect effect = effectObject.AddComponent<ItemFeedbackEffect>();
|
||||
effect.Initialize(itemSprite, itemType, blockedDamage);
|
||||
}
|
||||
|
||||
private void Initialize(Sprite itemSprite, GameManager.TutorialItemType itemType, bool blockedDamage)
|
||||
{
|
||||
mainColor = GetItemColor(itemType, blockedDamage);
|
||||
sparkleRenderers = new SpriteRenderer[5];
|
||||
|
||||
ringRenderer = CreateSpriteChild("Ring", GetRingSprite(), Vector3.zero, 1.4f, 28);
|
||||
iconRenderer = CreateSpriteChild("Icon", itemSprite != null ? itemSprite : GetDotSprite(), new Vector3(0f, 0.03f, 0f), itemSprite != null ? 0.52f : 0.72f, 29);
|
||||
|
||||
labelText = CreateLabel(GetLabel(itemType, blockedDamage));
|
||||
|
||||
for(int i = 0; i < sparkleRenderers.Length; i++)
|
||||
{
|
||||
float angle = (Mathf.PI * 2f / sparkleRenderers.Length) * i;
|
||||
Vector3 localPosition = new Vector3(Mathf.Cos(angle) * 0.58f, Mathf.Sin(angle) * 0.38f, 0f);
|
||||
sparkleRenderers[i] = CreateSpriteChild("Sparkle " + i, GetSparkleSprite(), localPosition, 0.18f, 30);
|
||||
}
|
||||
|
||||
ApplyAlpha(1f);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
elapsedTime += Time.unscaledDeltaTime;
|
||||
float t = Mathf.Clamp01(elapsedTime / Lifetime);
|
||||
float fade = 1f - Mathf.SmoothStep(0f, 1f, Mathf.InverseLerp(0.55f, 1f, t));
|
||||
float popScale = Mathf.Lerp(0.72f, 1.16f, EaseOut(t));
|
||||
|
||||
transform.localScale = Vector3.one * popScale;
|
||||
transform.position += Vector3.up * (Time.unscaledDeltaTime * 0.28f);
|
||||
|
||||
if(ringRenderer != null)
|
||||
{
|
||||
ringRenderer.transform.localScale = Vector3.one * Mathf.Lerp(0.82f, 1.38f, EaseOut(t));
|
||||
}
|
||||
|
||||
for(int i = 0; i < sparkleRenderers.Length; i++)
|
||||
{
|
||||
if(sparkleRenderers[i] == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
sparkleRenderers[i].transform.localScale = Vector3.one * Mathf.Lerp(0.16f, 0.32f, EaseOut(t));
|
||||
sparkleRenderers[i].transform.Rotate(Vector3.forward, 180f * Time.unscaledDeltaTime);
|
||||
}
|
||||
|
||||
ApplyAlpha(fade);
|
||||
|
||||
if(elapsedTime >= Lifetime)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
private SpriteRenderer CreateSpriteChild(string objectName, Sprite sprite, Vector3 localPosition, float scale, int sortingOrder)
|
||||
{
|
||||
GameObject child = new GameObject(objectName, typeof(SpriteRenderer));
|
||||
child.transform.SetParent(transform, false);
|
||||
child.transform.localPosition = localPosition;
|
||||
child.transform.localScale = Vector3.one * scale;
|
||||
|
||||
SpriteRenderer spriteRenderer = child.GetComponent<SpriteRenderer>();
|
||||
spriteRenderer.sprite = sprite;
|
||||
spriteRenderer.color = mainColor;
|
||||
spriteRenderer.sortingLayerName = SortingLayerName;
|
||||
spriteRenderer.sortingOrder = sortingOrder;
|
||||
return spriteRenderer;
|
||||
}
|
||||
|
||||
private TextMeshPro CreateLabel(string text)
|
||||
{
|
||||
GameObject textObject = new GameObject("Label", typeof(TextMeshPro));
|
||||
textObject.transform.SetParent(transform, false);
|
||||
textObject.transform.localPosition = new Vector3(0f, 0.62f, 0f);
|
||||
textObject.transform.localScale = Vector3.one * 0.28f;
|
||||
|
||||
TextMeshPro textMesh = textObject.GetComponent<TextMeshPro>();
|
||||
textMesh.text = text;
|
||||
textMesh.alignment = TextAlignmentOptions.Center;
|
||||
textMesh.fontSize = 3.2f;
|
||||
textMesh.fontStyle = FontStyles.Bold;
|
||||
textMesh.color = Color.white;
|
||||
textMesh.textWrappingMode = TextWrappingModes.NoWrap;
|
||||
|
||||
MeshRenderer textRenderer = textMesh.GetComponent<MeshRenderer>();
|
||||
textRenderer.sortingLayerName = SortingLayerName;
|
||||
textRenderer.sortingOrder = 31;
|
||||
return textMesh;
|
||||
}
|
||||
|
||||
private void ApplyAlpha(float alpha)
|
||||
{
|
||||
if(ringRenderer != null)
|
||||
{
|
||||
ringRenderer.color = WithAlpha(mainColor, alpha * 0.72f);
|
||||
}
|
||||
|
||||
if(iconRenderer != null)
|
||||
{
|
||||
iconRenderer.color = WithAlpha(Color.white, alpha);
|
||||
}
|
||||
|
||||
if(labelText != null)
|
||||
{
|
||||
labelText.color = WithAlpha(Color.white, alpha);
|
||||
}
|
||||
|
||||
if(sparkleRenderers == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for(int i = 0; i < sparkleRenderers.Length; i++)
|
||||
{
|
||||
if(sparkleRenderers[i] != null)
|
||||
{
|
||||
sparkleRenderers[i].color = WithAlpha(mainColor, alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetLabel(GameManager.TutorialItemType itemType, bool blockedDamage)
|
||||
{
|
||||
if(blockedDamage)
|
||||
{
|
||||
return itemType == GameManager.TutorialItemType.InvincibleRamen ? "SAFE" : "BLOCK";
|
||||
}
|
||||
|
||||
switch(itemType)
|
||||
{
|
||||
case GameManager.TutorialItemType.InvincibleRamen:
|
||||
return "SAFE";
|
||||
case GameManager.TutorialItemType.Shield:
|
||||
return "SHIELD";
|
||||
case GameManager.TutorialItemType.SpeedShoes:
|
||||
return "SPEED";
|
||||
case GameManager.TutorialItemType.MileageCard:
|
||||
return "x2";
|
||||
case GameManager.TutorialItemType.HealthSushi:
|
||||
default:
|
||||
return "+1";
|
||||
}
|
||||
}
|
||||
|
||||
private static Color GetItemColor(GameManager.TutorialItemType itemType, bool blockedDamage)
|
||||
{
|
||||
if(blockedDamage)
|
||||
{
|
||||
return itemType == GameManager.TutorialItemType.InvincibleRamen
|
||||
? new Color(1f, 0.76f, 0.24f, 1f)
|
||||
: new Color(0.36f, 0.82f, 1f, 1f);
|
||||
}
|
||||
|
||||
switch(itemType)
|
||||
{
|
||||
case GameManager.TutorialItemType.InvincibleRamen:
|
||||
return new Color(1f, 0.58f, 0.12f, 1f);
|
||||
case GameManager.TutorialItemType.Shield:
|
||||
return new Color(0.32f, 0.78f, 1f, 1f);
|
||||
case GameManager.TutorialItemType.SpeedShoes:
|
||||
return new Color(0.35f, 1f, 0.5f, 1f);
|
||||
case GameManager.TutorialItemType.MileageCard:
|
||||
return new Color(1f, 0.92f, 0.26f, 1f);
|
||||
case GameManager.TutorialItemType.HealthSushi:
|
||||
default:
|
||||
return new Color(1f, 0.34f, 0.42f, 1f);
|
||||
}
|
||||
}
|
||||
|
||||
private static float EaseOut(float value)
|
||||
{
|
||||
return 1f - Mathf.Pow(1f - Mathf.Clamp01(value), 3f);
|
||||
}
|
||||
|
||||
private static Color WithAlpha(Color color, float alpha)
|
||||
{
|
||||
return new Color(color.r, color.g, color.b, Mathf.Clamp01(alpha));
|
||||
}
|
||||
|
||||
private static Sprite GetRingSprite()
|
||||
{
|
||||
if(ringSprite == null)
|
||||
{
|
||||
ringSprite = CreateRingSprite(64, 21f, 29f);
|
||||
}
|
||||
|
||||
return ringSprite;
|
||||
}
|
||||
|
||||
private static Sprite GetDotSprite()
|
||||
{
|
||||
if(dotSprite == null)
|
||||
{
|
||||
dotSprite = CreateDiscSprite(48, 19f);
|
||||
}
|
||||
|
||||
return dotSprite;
|
||||
}
|
||||
|
||||
private static Sprite GetSparkleSprite()
|
||||
{
|
||||
if(sparkleSprite == null)
|
||||
{
|
||||
sparkleSprite = CreateSparkleSprite(24);
|
||||
}
|
||||
|
||||
return sparkleSprite;
|
||||
}
|
||||
|
||||
private static Sprite CreateRingSprite(int size, float innerRadius, float outerRadius)
|
||||
{
|
||||
Texture2D texture = CreateTexture(size);
|
||||
Color[] pixels = new Color[size * size];
|
||||
Vector2 center = new Vector2((size - 1) * 0.5f, (size - 1) * 0.5f);
|
||||
|
||||
for(int y = 0; y < size; y++)
|
||||
{
|
||||
for(int x = 0; x < size; x++)
|
||||
{
|
||||
float distance = Vector2.Distance(new Vector2(x, y), center);
|
||||
float outerAlpha = 1f - Mathf.SmoothStep(outerRadius - 2f, outerRadius, distance);
|
||||
float innerAlpha = Mathf.SmoothStep(innerRadius - 2f, innerRadius, distance);
|
||||
pixels[y * size + x] = new Color(1f, 1f, 1f, outerAlpha * innerAlpha);
|
||||
}
|
||||
}
|
||||
|
||||
texture.SetPixels(pixels);
|
||||
texture.Apply();
|
||||
return Sprite.Create(texture, new Rect(0f, 0f, size, size), new Vector2(0.5f, 0.5f), size);
|
||||
}
|
||||
|
||||
private static Sprite CreateDiscSprite(int size, float radius)
|
||||
{
|
||||
Texture2D texture = CreateTexture(size);
|
||||
Color[] pixels = new Color[size * size];
|
||||
Vector2 center = new Vector2((size - 1) * 0.5f, (size - 1) * 0.5f);
|
||||
|
||||
for(int y = 0; y < size; y++)
|
||||
{
|
||||
for(int x = 0; x < size; x++)
|
||||
{
|
||||
float distance = Vector2.Distance(new Vector2(x, y), center);
|
||||
float alpha = 1f - Mathf.SmoothStep(radius - 2f, radius, distance);
|
||||
pixels[y * size + x] = new Color(1f, 1f, 1f, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
texture.SetPixels(pixels);
|
||||
texture.Apply();
|
||||
return Sprite.Create(texture, new Rect(0f, 0f, size, size), new Vector2(0.5f, 0.5f), size);
|
||||
}
|
||||
|
||||
private static Sprite CreateSparkleSprite(int size)
|
||||
{
|
||||
Texture2D texture = CreateTexture(size);
|
||||
Color[] pixels = new Color[size * size];
|
||||
float center = (size - 1) * 0.5f;
|
||||
|
||||
for(int y = 0; y < size; y++)
|
||||
{
|
||||
for(int x = 0; x < size; x++)
|
||||
{
|
||||
float horizontal = Mathf.Abs(y - center);
|
||||
float vertical = Mathf.Abs(x - center);
|
||||
float diagonalA = Mathf.Abs((x - center) - (y - center));
|
||||
float diagonalB = Mathf.Abs((x - center) + (y - center));
|
||||
float alpha = Mathf.Max(
|
||||
1f - horizontal * 0.42f - Mathf.Abs(x - center) * 0.08f,
|
||||
1f - vertical * 0.42f - Mathf.Abs(y - center) * 0.08f);
|
||||
alpha = Mathf.Max(alpha, 0.62f - Mathf.Min(diagonalA, diagonalB) * 0.28f);
|
||||
pixels[y * size + x] = new Color(1f, 1f, 1f, Mathf.Clamp01(alpha));
|
||||
}
|
||||
}
|
||||
|
||||
texture.SetPixels(pixels);
|
||||
texture.Apply();
|
||||
return Sprite.Create(texture, new Rect(0f, 0f, size, size), new Vector2(0.5f, 0.5f), size);
|
||||
}
|
||||
|
||||
private static Texture2D CreateTexture(int size)
|
||||
{
|
||||
Texture2D texture = new Texture2D(size, size, TextureFormat.RGBA32, false);
|
||||
texture.wrapMode = TextureWrapMode.Clamp;
|
||||
texture.filterMode = FilterMode.Bilinear;
|
||||
texture.hideFlags = HideFlags.HideAndDontSave;
|
||||
return texture;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user