330 lines
12 KiB
C#
330 lines
12 KiB
C#
using TMPro;
|
|
using UnityEngine;
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
#endif
|
|
|
|
public enum FinishGateStyle {
|
|
None,
|
|
AirportDeparture,
|
|
JapanTorii,
|
|
ChinaPaifang,
|
|
AmericaLiberty
|
|
}
|
|
|
|
public class FinishGate : MonoBehaviour {
|
|
private const string ForegroundSortingLayer = "Foreground";
|
|
private const float DespawnX = -18f;
|
|
private const float RuntimeSpritePixelsPerUnit = 256f;
|
|
|
|
private static Sprite blockSprite;
|
|
private bool cleared = false;
|
|
|
|
public void Setup(FinishGateStyle style) {
|
|
cleared = false;
|
|
|
|
ScrollingObject scrollingObject = GetComponent<ScrollingObject>();
|
|
if(scrollingObject == null)
|
|
{
|
|
scrollingObject = gameObject.AddComponent<ScrollingObject>();
|
|
}
|
|
scrollingObject.speed = 10f;
|
|
|
|
BoxCollider2D trigger = GetComponent<BoxCollider2D>();
|
|
if(trigger == null)
|
|
{
|
|
trigger = gameObject.AddComponent<BoxCollider2D>();
|
|
}
|
|
|
|
ConfigureTrigger(trigger);
|
|
|
|
BuildGate(style);
|
|
}
|
|
|
|
private void Update() {
|
|
if(transform.position.x < DespawnX)
|
|
{
|
|
Destroy(gameObject);
|
|
}
|
|
}
|
|
|
|
private void OnTriggerEnter2D(Collider2D other) {
|
|
if(cleared || !other.CompareTag("Player") || !GameFlowManager.IsGameplayActive)
|
|
{
|
|
return;
|
|
}
|
|
|
|
cleared = true;
|
|
|
|
if(GameManager.instance != null)
|
|
{
|
|
GameManager.instance.CompleteCurrentStageFromFinishGate();
|
|
}
|
|
}
|
|
|
|
private void BuildGate(FinishGateStyle style) {
|
|
ClearChildren();
|
|
|
|
if(TryBuildSpriteGate(style))
|
|
{
|
|
return;
|
|
}
|
|
|
|
switch(style)
|
|
{
|
|
case FinishGateStyle.JapanTorii:
|
|
BuildJapanTorii();
|
|
break;
|
|
case FinishGateStyle.ChinaPaifang:
|
|
BuildChinaPaifang();
|
|
break;
|
|
case FinishGateStyle.AmericaLiberty:
|
|
BuildAmericaLibertyFallback();
|
|
break;
|
|
case FinishGateStyle.AirportDeparture:
|
|
default:
|
|
BuildAirportDepartureGate();
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void ConfigureTrigger(BoxCollider2D trigger) {
|
|
trigger.isTrigger = true;
|
|
trigger.offset = new Vector2(0f, 1.75f);
|
|
trigger.size = new Vector2(2.2f, 4.2f);
|
|
}
|
|
|
|
private bool TryBuildSpriteGate(FinishGateStyle style) {
|
|
string resourcePath = GetSpriteResourcePath(style);
|
|
if(string.IsNullOrEmpty(resourcePath))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Sprite sprite = LoadGateSprite(resourcePath);
|
|
|
|
if(sprite == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
GameObject spriteObject = new GameObject("Finish Gate Sprite");
|
|
spriteObject.transform.SetParent(transform, false);
|
|
|
|
SpriteRenderer spriteRenderer = spriteObject.AddComponent<SpriteRenderer>();
|
|
spriteRenderer.sprite = sprite;
|
|
spriteRenderer.sortingLayerName = ForegroundSortingLayer;
|
|
spriteRenderer.sortingOrder = 6;
|
|
|
|
float targetHeight = GetSpriteGateHeight(style);
|
|
float spriteHeight = Mathf.Max(0.01f, sprite.bounds.size.y);
|
|
float scale = targetHeight / spriteHeight;
|
|
spriteObject.transform.localScale = new Vector3(scale, scale, 1f);
|
|
spriteObject.transform.localPosition = new Vector3(0f, targetHeight * 0.5f - GetSpriteGateBottomInset(style), 0f);
|
|
return true;
|
|
}
|
|
|
|
private Sprite LoadGateSprite(string resourcePath) {
|
|
Sprite sprite = Resources.Load<Sprite>(resourcePath);
|
|
if(sprite != null)
|
|
{
|
|
return sprite;
|
|
}
|
|
|
|
Sprite[] sprites = Resources.LoadAll<Sprite>(resourcePath);
|
|
if(sprites != null && sprites.Length > 0 && sprites[0] != null)
|
|
{
|
|
return sprites[0];
|
|
}
|
|
|
|
Texture2D texture = Resources.Load<Texture2D>(resourcePath);
|
|
if(texture != null)
|
|
{
|
|
return CreateRuntimeSprite(texture);
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
string assetPath = "Assets/Resources/" + resourcePath + ".png";
|
|
sprite = AssetDatabase.LoadAssetAtPath<Sprite>(assetPath);
|
|
if(sprite != null)
|
|
{
|
|
return sprite;
|
|
}
|
|
|
|
texture = AssetDatabase.LoadAssetAtPath<Texture2D>(assetPath);
|
|
if(texture != null)
|
|
{
|
|
return CreateRuntimeSprite(texture);
|
|
}
|
|
#endif
|
|
|
|
return null;
|
|
}
|
|
|
|
private Sprite CreateRuntimeSprite(Texture2D texture) {
|
|
return Sprite.Create(
|
|
texture,
|
|
new Rect(0f, 0f, texture.width, texture.height),
|
|
new Vector2(0.5f, 0.5f),
|
|
RuntimeSpritePixelsPerUnit);
|
|
}
|
|
|
|
private string GetSpriteResourcePath(FinishGateStyle style) {
|
|
switch(style)
|
|
{
|
|
case FinishGateStyle.AirportDeparture:
|
|
return "FinishGate_Tutorial_Incheon";
|
|
case FinishGateStyle.JapanTorii:
|
|
return "FinishGate_Japan_Torii";
|
|
case FinishGateStyle.ChinaPaifang:
|
|
return "FinishGate_China_Paifang";
|
|
case FinishGateStyle.AmericaLiberty:
|
|
return "FinishGate_America_Liberty";
|
|
default:
|
|
return "";
|
|
}
|
|
}
|
|
|
|
private float GetSpriteGateHeight(FinishGateStyle style) {
|
|
switch(style)
|
|
{
|
|
case FinishGateStyle.ChinaPaifang:
|
|
return 4.65f;
|
|
case FinishGateStyle.AmericaLiberty:
|
|
return 4.45f;
|
|
default:
|
|
return 4.35f;
|
|
}
|
|
}
|
|
|
|
private float GetSpriteGateBottomInset(FinishGateStyle style) {
|
|
switch(style)
|
|
{
|
|
case FinishGateStyle.JapanTorii:
|
|
return 0.36f;
|
|
default:
|
|
return 0f;
|
|
}
|
|
}
|
|
|
|
private void BuildAirportDepartureGate() {
|
|
Color navy = new Color(0.05f, 0.2f, 0.34f, 1f);
|
|
Color blue = new Color(0.08f, 0.42f, 0.67f, 1f);
|
|
Color cyan = new Color(0.18f, 0.83f, 0.95f, 1f);
|
|
Color yellow = new Color(1f, 0.78f, 0.22f, 1f);
|
|
Color glass = new Color(0.6f, 0.9f, 1f, 0.55f);
|
|
|
|
CreateBlock("Airport Left Pillar", new Vector2(-1.15f, 1.45f), new Vector2(0.22f, 3.1f), navy, 3);
|
|
CreateBlock("Airport Right Pillar", new Vector2(1.15f, 1.45f), new Vector2(0.22f, 3.1f), navy, 3);
|
|
CreateBlock("Airport Top Sign", new Vector2(0f, 3.05f), new Vector2(2.75f, 0.64f), blue, 4);
|
|
CreateBlock("Airport Sign Highlight", new Vector2(0f, 3.35f), new Vector2(2.75f, 0.08f), cyan, 5);
|
|
CreateBlock("Airport Gate Floor", new Vector2(0f, -0.04f), new Vector2(2.9f, 0.12f), yellow, 4);
|
|
CreateBlock("Airport Glass Left", new Vector2(-0.62f, 1.35f), new Vector2(0.16f, 2.2f), glass, 2);
|
|
CreateBlock("Airport Glass Right", new Vector2(0.62f, 1.35f), new Vector2(0.16f, 2.2f), glass, 2);
|
|
CreateBlock("Airport Clear Light", new Vector2(0f, 2.55f), new Vector2(0.26f, 0.14f), yellow, 5);
|
|
CreateWorldText("DEPARTURE", new Vector2(0f, 3.07f), 0.34f, Color.white, 6);
|
|
}
|
|
|
|
private void BuildJapanTorii() {
|
|
Color red = new Color(0.86f, 0.08f, 0.05f, 1f);
|
|
Color darkRed = new Color(0.48f, 0.02f, 0.02f, 1f);
|
|
Color black = new Color(0.08f, 0.04f, 0.03f, 1f);
|
|
Color gold = new Color(1f, 0.76f, 0.28f, 1f);
|
|
|
|
CreateBlock("Torii Left Pillar", new Vector2(-1.18f, 1.35f), new Vector2(0.28f, 2.9f), red, 4);
|
|
CreateBlock("Torii Right Pillar", new Vector2(1.18f, 1.35f), new Vector2(0.28f, 2.9f), red, 4);
|
|
CreateBlock("Torii Left Base", new Vector2(-1.18f, -0.14f), new Vector2(0.48f, 0.22f), black, 3);
|
|
CreateBlock("Torii Right Base", new Vector2(1.18f, -0.14f), new Vector2(0.48f, 0.22f), black, 3);
|
|
CreateBlock("Torii Lower Beam", new Vector2(0f, 2.55f), new Vector2(2.75f, 0.24f), darkRed, 5);
|
|
CreateBlock("Torii Main Beam", new Vector2(0f, 3.05f), new Vector2(3.35f, 0.32f), red, 6);
|
|
CreateBlock("Torii Top Cap", new Vector2(0f, 3.31f), new Vector2(3.75f, 0.16f), black, 7);
|
|
CreateBlock("Torii Center Plaque", new Vector2(0f, 2.82f), new Vector2(0.36f, 0.5f), gold, 7);
|
|
}
|
|
|
|
private void BuildChinaPaifang() {
|
|
Color red = new Color(0.74f, 0.05f, 0.04f, 1f);
|
|
Color gold = new Color(1f, 0.72f, 0.18f, 1f);
|
|
Color roof = new Color(0.12f, 0.3f, 0.22f, 1f);
|
|
Color dark = new Color(0.24f, 0.04f, 0.03f, 1f);
|
|
|
|
CreateBlock("Paifang Left Pillar", new Vector2(-1.25f, 1.28f), new Vector2(0.28f, 2.8f), red, 4);
|
|
CreateBlock("Paifang Right Pillar", new Vector2(1.25f, 1.28f), new Vector2(0.28f, 2.8f), red, 4);
|
|
CreateBlock("Paifang Center Pillar Left", new Vector2(-0.42f, 1.48f), new Vector2(0.18f, 2.2f), dark, 3);
|
|
CreateBlock("Paifang Center Pillar Right", new Vector2(0.42f, 1.48f), new Vector2(0.18f, 2.2f), dark, 3);
|
|
CreateBlock("Paifang Sign", new Vector2(0f, 2.65f), new Vector2(2.45f, 0.46f), gold, 5);
|
|
CreateBlock("Paifang Roof", new Vector2(0f, 3.18f), new Vector2(3.25f, 0.26f), roof, 6);
|
|
CreateBlock("Paifang Roof Cap", new Vector2(0f, 3.42f), new Vector2(2.35f, 0.2f), roof, 7);
|
|
CreateBlock("Paifang Lantern Left", new Vector2(-0.78f, 2.18f), new Vector2(0.26f, 0.34f), red, 7);
|
|
CreateBlock("Paifang Lantern Right", new Vector2(0.78f, 2.18f), new Vector2(0.26f, 0.34f), red, 7);
|
|
}
|
|
|
|
private void BuildAmericaLibertyFallback() {
|
|
Color metal = new Color(0.48f, 0.56f, 0.58f, 1f);
|
|
Color green = new Color(0.03f, 0.38f, 0.22f, 1f);
|
|
Color yellow = new Color(1f, 0.8f, 0.18f, 1f);
|
|
Color white = Color.white;
|
|
|
|
CreateBlock("Road Sign Left Pole", new Vector2(-1.3f, 1.35f), new Vector2(0.18f, 3.0f), metal, 3);
|
|
CreateBlock("Road Sign Right Pole", new Vector2(1.3f, 1.35f), new Vector2(0.18f, 3.0f), metal, 3);
|
|
CreateBlock("Road Sign Panel", new Vector2(0f, 2.65f), new Vector2(3.05f, 0.9f), green, 5);
|
|
CreateBlock("Road Sign Stripe", new Vector2(0f, 2.25f), new Vector2(2.75f, 0.08f), white, 6);
|
|
CreateBlock("Road Sign Arrow", new Vector2(0f, 2.72f), new Vector2(0.5f, 0.16f), yellow, 7);
|
|
CreateWorldText("ARRIVAL", new Vector2(0f, 2.88f), 0.36f, white, 8);
|
|
}
|
|
|
|
private SpriteRenderer CreateBlock(string objectName, Vector2 localPosition, Vector2 size, Color color, int sortingOrder) {
|
|
GameObject block = new GameObject(objectName);
|
|
block.transform.SetParent(transform, false);
|
|
block.transform.localPosition = new Vector3(localPosition.x, localPosition.y, 0f);
|
|
block.transform.localScale = new Vector3(size.x, size.y, 1f);
|
|
|
|
SpriteRenderer renderer = block.AddComponent<SpriteRenderer>();
|
|
renderer.sprite = GetBlockSprite();
|
|
renderer.color = color;
|
|
renderer.sortingLayerName = ForegroundSortingLayer;
|
|
renderer.sortingOrder = sortingOrder;
|
|
return renderer;
|
|
}
|
|
|
|
private TextMeshPro CreateWorldText(string text, Vector2 localPosition, float fontSize, Color color, int sortingOrder) {
|
|
GameObject textObject = new GameObject("Gate Text " + text);
|
|
textObject.transform.SetParent(transform, false);
|
|
textObject.transform.localPosition = new Vector3(localPosition.x, localPosition.y, -0.05f);
|
|
|
|
TextMeshPro textMesh = textObject.AddComponent<TextMeshPro>();
|
|
textMesh.text = text;
|
|
textMesh.fontSize = fontSize;
|
|
textMesh.alignment = TextAlignmentOptions.Center;
|
|
textMesh.color = color;
|
|
textMesh.textWrappingMode = TextWrappingModes.NoWrap;
|
|
textMesh.rectTransform.sizeDelta = new Vector2(3f, 0.55f);
|
|
textMesh.renderer.sortingLayerName = ForegroundSortingLayer;
|
|
textMesh.renderer.sortingOrder = sortingOrder;
|
|
return textMesh;
|
|
}
|
|
|
|
private static Sprite GetBlockSprite() {
|
|
if(blockSprite != null)
|
|
{
|
|
return blockSprite;
|
|
}
|
|
|
|
Texture2D texture = new Texture2D(1, 1);
|
|
texture.SetPixel(0, 0, Color.white);
|
|
texture.Apply();
|
|
texture.wrapMode = TextureWrapMode.Clamp;
|
|
texture.filterMode = FilterMode.Point;
|
|
|
|
blockSprite = Sprite.Create(texture, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f), 1f);
|
|
blockSprite.name = "Runtime Finish Gate Block";
|
|
return blockSprite;
|
|
}
|
|
|
|
private void ClearChildren() {
|
|
for(int i = transform.childCount - 1; i >= 0; i--)
|
|
{
|
|
Destroy(transform.GetChild(i).gameObject);
|
|
}
|
|
}
|
|
}
|