XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

AshfallFrontier

【Unity】灰烬边境,一款生存策略游戏

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Collections.Generic;
using UnityEngine;

namespace Ashfall.Runtime
{
    public sealed class SpriteLibrary : System.IDisposable
    {
        private readonly Dictionary<string, Sprite> sprites = new Dictionary<string, Sprite>();
        public Material Lit { get; }
        public Material Unlit { get; }
        public SpriteLibrary()
        {
            var lit = Shader.Find("Universal Render Pipeline/2D/Sprite-Lit-Default");
            var unlit = Shader.Find("Universal Render Pipeline/2D/Sprite-Unlit-Default");
            Lit = new Material(lit != null ? lit : Shader.Find("Sprites/Default"));
            Unlit = new Material(unlit != null ? unlit : Shader.Find("Sprites/Default"));
            AddAtlas("ExpeditionAtlas", "human", 0, true);
            AddAtlas("ExpeditionAtlas", "adult", 1, true);
            AddAtlas("ExpeditionAtlas", "crawler", 2, false);
            AddAtlas("ExpeditionAtlas", "prop", 3, false);
            AddAtlas("LifeformsAtlas", "worm", 0, false);
            AddAtlas("LifeformsAtlas", "beast", 1, false);
            AddAtlas("LifeformsAtlas", "ark", 2, false);
            AddAtlas("LifeformsAtlas", "extra", 3, false);
            sprites["white"] = MakeTile("white", false, false);
            sprites["soil"] = MakeTile("soil", true, false);
            sprites["metal"] = MakeTile("metal", true, true);
            sprites["shadow"] = MakeShadow();
        }
        public Sprite Get(string key) => sprites.TryGetValue(key, out var sprite) ? sprite : sprites["white"];
        public void Dispose()
        {
            foreach (var pair in sprites)
            {
                if (pair.Key == "white" || pair.Key == "soil" || pair.Key == "metal" || pair.Key == "shadow") Object.Destroy(pair.Value.texture);
                Object.Destroy(pair.Value);
            }
            sprites.Clear(); Object.Destroy(Lit); Object.Destroy(Unlit);
        }
        public Sprite Direction(string name, float heading)
        {
            int column = Mathf.RoundToInt(Mathf.Repeat(-heading, 360) / 90) % 4;
            return Get(name + column);
        }
        private void AddAtlas(string file, string name, int row, bool feet)
        {
            var texture = Resources.Load<Texture2D>("Art/" + file); if (texture == null) return;
            float cellW = texture.width / 4f, cellH = texture.height / 4f;
            for (int column = 0; column < 4; column++)
                sprites[name + column] = Sprite.Create(texture, new Rect(column * cellW, (3 - row) * cellH, cellW, cellH),
                    new Vector2(.5f, feet ? .12f : .5f), cellW, 0, SpriteMeshType.FullRect);
        }
        private static Sprite MakeTile(string name, bool noise, bool seams)
        {
            const int n = 64; var tex = new Texture2D(n, n, TextureFormat.RGBA32, false) { name = "Procedural " + name, filterMode = FilterMode.Bilinear, wrapMode = TextureWrapMode.Repeat };
            var pixels = new Color[n * n];
            for (int y = 0; y < n; y++) for (int x = 0; x < n; x++)
            {
                uint h = unchecked((uint)(x * 374761393 + y * 668265263 + 71)); h = (h ^ (h >> 13)) * 1274126177;
                float v = noise ? .74f + (h & 255) / 255f * .22f : 1;
                if (seams && (x < 2 || y < 2)) v *= .48f;
                if (seams && x > 4 && x < 8 && y > 4 && y < 8) v *= .7f;
                pixels[y * n + x] = new Color(v, v, v, 1);
            }
            tex.SetPixels(pixels); tex.Apply(); return Sprite.Create(tex, new Rect(0, 0, n, n), new Vector2(.5f, .5f), n);
        }
        private static Sprite MakeShadow()
        {
            const int n = 64; var tex = new Texture2D(n, n, TextureFormat.RGBA32, false) { name = "Contact shadow", filterMode = FilterMode.Bilinear };
            var pixels = new Color[n * n];
            for (int y = 0; y < n; y++) for (int x = 0; x < n; x++)
            { float d = Vector2.Distance(new Vector2(x, y), new Vector2(31.5f, 31.5f)) / 31.5f; pixels[y * n + x] = new Color(0, 0, 0, Mathf.Pow(Mathf.Clamp01(1 - d), .7f) * .7f); }
            tex.SetPixels(pixels); tex.Apply(); return Sprite.Create(tex, new Rect(0, 0, n, n), new Vector2(.5f, .5f), n);
        }
    }
}