miepzerino
2025-04-07 ab5a24f4c0cffbc8e8f76e40293f2201027b7c50
#49 added parallax and tiling to background
2 files modified
4 files added
469 ■■■■■ changed files
Assets/BackgroundManager.cs 203 ●●●● patch | view | raw | blame | history
Assets/Scenes/GameplayScene.unity 12 ●●●● patch | view | raw | blame | history
Assets/Sprites/BG/Ground_tiling.png patch | view | raw | blame | history
Assets/Sprites/BG/Ground_tiling.png.meta 127 ●●●●● patch | view | raw | blame | history
Assets/Sprites/BG/Sky_tiling.png patch | view | raw | blame | history
Assets/Sprites/BG/Sky_tiling.png.meta 127 ●●●●● patch | view | raw | blame | history
Assets/BackgroundManager.cs
@@ -14,27 +14,40 @@
    }
    [SerializeField] private SpriteRenderer spriteRenderer;
    [SerializeField] private SpriteRenderer transitionRenderer; // Add this field
    [SerializeField] private BackgroundLayer[] backgroundLayers;
    [SerializeField] private Transform playerTransform; // Add this field
    [SerializeField] private float tileBuffer = 1f; // Extra tiles beyond camera view
    private bool isTransitioning = false; // Add this field
    private Transform cameraTransform;
    private Vector3 lastCameraPosition;
    private int currentLayerIndex = 0;
    private int lastLayerIndex = 0;
    private float startPositionX;
    private float startPositionY;
    private float lastUpdatePlayerY = 0f; // Track the last Y position of the player
    private bool isMovingUp = false; // Track if the player is moving up
    private Dictionary<Vector2Int, SpriteRenderer> backgroundTiles = new Dictionary<Vector2Int, SpriteRenderer>();
    private Dictionary<Vector2Int, SpriteRenderer> transitionTiles = new Dictionary<Vector2Int, SpriteRenderer>();
    private Vector2 tileSize;
    private Camera mainCamera;
    private void Start()
    {
        cameraTransform = Camera.main.transform;
        mainCamera = Camera.main;
        cameraTransform = mainCamera.transform;
        lastCameraPosition = cameraTransform.position;
        
        if (spriteRenderer == null)
            spriteRenderer = GetComponent<SpriteRenderer>();
        if (backgroundLayers != null && backgroundLayers.Length > 0)
        {
            Sprite firstSprite = backgroundLayers[0].backgroundSprite;
            tileSize = new Vector2(firstSprite.bounds.size.x, firstSprite.bounds.size.y);
        }
        // Set initial background based on player position
        if (backgroundLayers != null && backgroundLayers.Length > 0)
        {
@@ -53,39 +66,77 @@
            spriteRenderer.sprite = backgroundLayers[initialLayerIndex].backgroundSprite;
            currentLayerIndex = initialLayerIndex;
            lastLayerIndex = currentLayerIndex;
        }
        InitializeInitialTiles();
        startPositionX = playerTransform.position.x;
        startPositionY = playerTransform.position.y;
    }
    private void InitializeInitialTiles()
    {
        // Calculate visible area
        float cameraHeight = 2f * mainCamera.orthographicSize;
        float cameraWidth = cameraHeight * mainCamera.aspect;
        // Calculate number of tiles needed
        int horizontalTiles = Mathf.CeilToInt(cameraWidth / tileSize.x) + 2;
        int verticalTiles = Mathf.CeilToInt(cameraHeight / tileSize.y) + 2;
        // Create initial grid of tiles
        for (int x = -horizontalTiles; x <= horizontalTiles; x++)
        {
            for (int y = -verticalTiles; y <= verticalTiles; y++)
            {
                CreateTile(new Vector2Int(x, y));
            }
        }
        }
        if (transitionRenderer == null)
    private void CreateTile(Vector2Int gridPosition)
        {
            var transitionObj = new GameObject("TransitionLayer");
            transitionObj.transform.parent = transform;
            transitionObj.transform.localPosition = new Vector3(0, 0, -2); // Set Z to -2
            transitionObj.transform.localScale = Vector3.one; // Match scale
            transitionRenderer = transitionObj.AddComponent<SpriteRenderer>();
            transitionRenderer.sortingOrder = spriteRenderer.sortingOrder + 1;
            transitionRenderer.sortingLayerName = spriteRenderer.sortingLayerName; // Match background layer
        }
        transitionRenderer.color = new Color(1, 1, 1, 0); // Start fully transparent
        if (backgroundTiles.ContainsKey(gridPosition))
            return;
        GameObject tileObj = new GameObject($"Tile_{gridPosition.x}_{gridPosition.y}");
        tileObj.transform.parent = transform;
        SpriteRenderer tileSR = tileObj.AddComponent<SpriteRenderer>();
        tileSR.sprite = backgroundLayers[currentLayerIndex].backgroundSprite;
        tileSR.sortingOrder = spriteRenderer.sortingOrder;
        tileSR.sortingLayerName = spriteRenderer.sortingLayerName;
        // Position the tile
        Vector3 position = new Vector3(
            gridPosition.x * tileSize.x,
            gridPosition.y * tileSize.y,
            transform.position.z
        );
        tileObj.transform.localPosition = position;
        tileObj.transform.localScale = Vector3.one; // Match scale
        backgroundTiles.Add(gridPosition, tileSR);
    }
    private void Update()
    {
        UpdateTiles();
        // Calculate parallax movement
        Vector3 cameraDelta = cameraTransform.position - lastCameraPosition;
        Vector3 newPosition = transform.position;
        // Update X position with parallax
        float parallaxX = (cameraTransform.position.x - startPositionX) * GetCurrentParallaxEffect();
        newPosition.x = startPositionX + parallaxX;
        // Update Y position to follow camera
        newPosition.y = cameraTransform.position.y;
        float parallaxY = (cameraTransform.position.y - startPositionY) * GetCurrentParallaxEffect();
        newPosition.y = startPositionY + parallaxY;
        transform.position = newPosition;
        // Check for background change
        float currentY = cameraTransform.position.y;
        float currentY = playerTransform.position.y;
        int newLayerIndex = currentLayerIndex;
        for (int i = 0; i < backgroundLayers.Length; i++)
@@ -120,6 +171,57 @@
        }
    }
    private void UpdateTiles()
    {
        // Calculate visible area with buffer
        float cameraHeight = 2f * mainCamera.orthographicSize * (1f + tileBuffer);
        float cameraWidth = cameraHeight * mainCamera.aspect * (1f + tileBuffer);
        // Calculate parallax offset
        float parallaxX = (cameraTransform.position.x - startPositionX) * GetCurrentParallaxEffect();
        float parallaxY = (cameraTransform.position.y - startPositionY) * GetCurrentParallaxEffect();
        // Calculate grid positions that should be visible
        Vector2 cameraPos = mainCamera.transform.position;
        // Adjust the buffer based on parallax effect
        float parallaxBuffer = 1f; // Base buffer size
        float effectiveBuffer = parallaxBuffer * (1f + GetCurrentParallaxEffect());
        int minX = Mathf.FloorToInt((parallaxX - (cameraWidth / 2 * effectiveBuffer)) / tileSize.x);
        int maxX = Mathf.CeilToInt((parallaxX + (cameraWidth / 2 * effectiveBuffer)) / tileSize.x);
        int minY = Mathf.FloorToInt((parallaxY - (cameraHeight / 2 * effectiveBuffer)) / tileSize.y);
        int maxY = Mathf.CeilToInt((parallaxY + (cameraHeight / 2 * effectiveBuffer)) / tileSize.y);
        // Create new tiles
        for (int x = minX; x <= maxX; x++)
        {
            for (int y = minY; y <= maxY; y++)
            {
                CreateTile(new Vector2Int(x, y));
            }
        }
        // Remove out-of-view tiles
        List<Vector2Int> tilesToRemove = new List<Vector2Int>();
        foreach (var tile in backgroundTiles)
        {
            if (tile.Key.x < minX - 1 || tile.Key.x > maxX + 1 ||
                tile.Key.y < minY - 1 || tile.Key.y > maxY + 1)
            {
                tilesToRemove.Add(tile.Key);
            }
        }
        foreach (var tilePos in tilesToRemove)
        {
            if (!transitionTiles.ContainsKey(tilePos))
            {
                Destroy(backgroundTiles[tilePos].gameObject);
                backgroundTiles.Remove(tilePos);
            }
        }
    }
    private float GetCurrentParallaxEffect()
    {
@@ -130,51 +232,78 @@
    private IEnumerator TransitionBackground(BackgroundLayer newLayer)
    {
        // Check if the transition is already in progress or if the new sprite is the same as the current one
        if (isTransitioning || newLayer.backgroundSprite.name == spriteRenderer.sprite.name) yield break;
        if (isTransitioning || newLayer.backgroundSprite.name == backgroundLayers[lastLayerIndex].backgroundSprite.name)
            yield break;
        isTransitioning = true;
        // Setup transition renderer
        transitionRenderer.sprite = newLayer.backgroundSprite;
        transitionRenderer.transform.localPosition = Vector3.zero;
        bool initialMovingUp = isMovingUp; // Store the initial moving direction
        bool initialMovingUp = isMovingUp;
        float initialY = playerTransform.position.y;
        //bool movingUp = playerTransform.position.y > initialY;
        // Fade in new sprite over old one
        // Create transition renderers for all existing tiles
        foreach (var tile in backgroundTiles)
        {
            GameObject transObj = new GameObject($"TransitionTile_{tile.Key.x}_{tile.Key.y}");
            transObj.transform.parent = transform;
            transObj.transform.localPosition = tile.Value.transform.localPosition + new Vector3(0, 0, -0.1f);
            transObj.transform.localScale = Vector3.one;
            SpriteRenderer transSR = transObj.AddComponent<SpriteRenderer>();
            transSR.sprite = newLayer.backgroundSprite;
            transSR.sortingOrder = tile.Value.sortingOrder + 1;
            transSR.sortingLayerName = tile.Value.sortingLayerName;
            transSR.color = new Color(1, 1, 1, 0);
            transitionTiles.Add(tile.Key, transSR);
        }
        // Fade in new sprites over old ones
        while (true)
        {
            float currentY = playerTransform.position.y;
            // Check if the direction has changed
            // Check if direction changed
            if (initialMovingUp != isMovingUp && 
                ((initialMovingUp ? initialY > currentY : initialY < currentY)
                ))
                ((initialMovingUp ? initialY > currentY : initialY < currentY)))
            {
                transitionRenderer.color = new Color(1, 1, 1, 0);
                foreach (var transTile in transitionTiles.Values)
                {
                    Destroy(transTile.gameObject);
                }
                transitionTiles.Clear();
                isTransitioning = false;
                yield break;
            }
            // Calculate the alpha based on the distance moved
            // Calculate alpha
            float alpha = Mathf.Abs(currentY - initialY) / newLayer.transitionDistance;
            transitionRenderer.color = new Color(1, 1, 1, Mathf.Clamp01(alpha));
            Color newColor = new Color(1, 1, 1, Mathf.Clamp01(alpha));
            // Check if transition is complete
            // Update all transition tiles
            foreach (var transTile in transitionTiles.Values)
            {
                transTile.color = newColor;
            }
            if (alpha >= 1f)
                break;
            yield return null;
        }
        // Ensure the final alpha value is set correctly
        transitionRenderer.color = new Color(1, 1, 1, 1);
        // Switch sprites on all tiles
        foreach (var tile in backgroundTiles.Values)
        {
            tile.sprite = newLayer.backgroundSprite;
        }
        // Switch the sprites
        spriteRenderer.sprite = newLayer.backgroundSprite;
        transitionRenderer.color = new Color(1, 1, 1, 0);
        // Cleanup transition tiles
        foreach (var transTile in transitionTiles.Values)
        {
            Destroy(transTile.gameObject);
        }
        transitionTiles.Clear();
        isTransitioning = false;
        lastLayerIndex = currentLayerIndex;
    }
}
Assets/Scenes/GameplayScene.unity
@@ -5244,7 +5244,7 @@
  serializedVersion: 2
  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
  m_LocalPosition: {x: 0, y: 0, z: -2}
  m_LocalScale: {x: 5, y: 5, z: 1}
  m_LocalScale: {x: 1, y: 1, z: 1}
  m_ConstrainProportionsScale: 0
  m_Children: []
  m_Father: {fileID: 796676099}
@@ -5314,17 +5314,17 @@
  m_Name: 
  m_EditorClassIdentifier: 
  spriteRenderer: {fileID: 2136420134}
  transitionRenderer: {fileID: 0}
  backgroundLayers:
  - yThreshold: -5
    backgroundSprite: {fileID: 21300000, guid: 7d5be99b0261348468ab492c35422f1b, type: 3}
    backgroundSprite: {fileID: 21300000, guid: 7e7e3a72941b2294c8323b1d6db71aaa, type: 3}
    transitionDistance: 4
    parallaxEffect: 0.439
    parallaxEffect: 0.5
  - yThreshold: -300
    backgroundSprite: {fileID: 21300000, guid: 58a6eeb45a0e2674ab35114433129f28, type: 3}
    backgroundSprite: {fileID: 21300000, guid: 3597d973a54f81842a7c183a2bc8b55a, type: 3}
    transitionDistance: 5
    parallaxEffect: 0.482
    parallaxEffect: 0.5
  playerTransform: {fileID: 254538002}
  tileBuffer: 0.5
--- !u!114 &18669457987763773
MonoBehaviour:
  m_ObjectHideFlags: 0
Assets/Sprites/BG/Ground_tiling.png
Assets/Sprites/BG/Ground_tiling.png.meta
New file
@@ -0,0 +1,127 @@
fileFormatVersion: 2
guid: 3597d973a54f81842a7c183a2bc8b55a
TextureImporter:
  internalIDToNameTable: []
  externalObjects: {}
  serializedVersion: 12
  mipmaps:
    mipMapMode: 0
    enableMipMap: 0
    sRGBTexture: 1
    linearTexture: 0
    fadeOut: 0
    borderMipMap: 0
    mipMapsPreserveCoverage: 0
    alphaTestReferenceValue: 0.5
    mipMapFadeDistanceStart: 1
    mipMapFadeDistanceEnd: 3
  bumpmap:
    convertToNormalMap: 0
    externalNormalMap: 0
    heightScale: 0.25
    normalMapFilter: 0
    flipGreenChannel: 0
  isReadable: 0
  streamingMipmaps: 0
  streamingMipmapsPriority: 0
  vTOnly: 0
  ignoreMipmapLimit: 0
  grayScaleToAlpha: 0
  generateCubemap: 6
  cubemapConvolution: 0
  seamlessCubemap: 0
  textureFormat: 1
  maxTextureSize: 2048
  textureSettings:
    serializedVersion: 2
    filterMode: 0
    aniso: 1
    mipBias: 0
    wrapU: 1
    wrapV: 1
    wrapW: 1
  nPOTScale: 0
  lightmap: 0
  compressionQuality: 50
  spriteMode: 1
  spriteExtrude: 1
  spriteMeshType: 1
  alignment: 0
  spritePivot: {x: 0.5, y: 0.5}
  spritePixelsToUnits: 16
  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
  spriteGenerateFallbackPhysicsShape: 1
  alphaUsage: 1
  alphaIsTransparency: 1
  spriteTessellationDetail: -1
  textureType: 8
  textureShape: 1
  singleChannelComponent: 0
  flipbookRows: 1
  flipbookColumns: 1
  maxTextureSizeSet: 0
  compressionQualitySet: 0
  textureFormatSet: 0
  ignorePngGamma: 0
  applyGammaDecoding: 0
  swizzle: 50462976
  cookieLightType: 0
  platformSettings:
  - serializedVersion: 3
    buildTarget: DefaultTexturePlatform
    maxTextureSize: 4096
    resizeAlgorithm: 0
    textureFormat: -1
    textureCompression: 0
    compressionQuality: 50
    crunchedCompression: 0
    allowsAlphaSplitting: 0
    overridden: 0
    ignorePlatformSupport: 0
    androidETC2FallbackOverride: 0
    forceMaximumCompressionQuality_BC6H_BC7: 0
  - serializedVersion: 3
    buildTarget: Standalone
    maxTextureSize: 2048
    resizeAlgorithm: 0
    textureFormat: -1
    textureCompression: 1
    compressionQuality: 50
    crunchedCompression: 0
    allowsAlphaSplitting: 0
    overridden: 0
    ignorePlatformSupport: 0
    androidETC2FallbackOverride: 0
    forceMaximumCompressionQuality_BC6H_BC7: 0
  - serializedVersion: 3
    buildTarget: Server
    maxTextureSize: 2048
    resizeAlgorithm: 0
    textureFormat: -1
    textureCompression: 1
    compressionQuality: 50
    crunchedCompression: 0
    allowsAlphaSplitting: 0
    overridden: 0
    ignorePlatformSupport: 0
    androidETC2FallbackOverride: 0
    forceMaximumCompressionQuality_BC6H_BC7: 0
  spriteSheet:
    serializedVersion: 2
    sprites: []
    outline: []
    physicsShape: []
    bones: []
    spriteID: 5e97eb03825dee720800000000000000
    internalID: 0
    vertices: []
    indices:
    edges: []
    weights: []
    secondaryTextures: []
    nameFileIdTable: {}
  mipmapLimitGroupName:
  pSDRemoveMatte: 0
  userData:
  assetBundleName:
  assetBundleVariant:
Assets/Sprites/BG/Sky_tiling.png
Assets/Sprites/BG/Sky_tiling.png.meta
New file
@@ -0,0 +1,127 @@
fileFormatVersion: 2
guid: 7e7e3a72941b2294c8323b1d6db71aaa
TextureImporter:
  internalIDToNameTable: []
  externalObjects: {}
  serializedVersion: 12
  mipmaps:
    mipMapMode: 0
    enableMipMap: 0
    sRGBTexture: 1
    linearTexture: 0
    fadeOut: 0
    borderMipMap: 0
    mipMapsPreserveCoverage: 0
    alphaTestReferenceValue: 0.5
    mipMapFadeDistanceStart: 1
    mipMapFadeDistanceEnd: 3
  bumpmap:
    convertToNormalMap: 0
    externalNormalMap: 0
    heightScale: 0.25
    normalMapFilter: 0
    flipGreenChannel: 0
  isReadable: 0
  streamingMipmaps: 0
  streamingMipmapsPriority: 0
  vTOnly: 0
  ignoreMipmapLimit: 0
  grayScaleToAlpha: 0
  generateCubemap: 6
  cubemapConvolution: 0
  seamlessCubemap: 0
  textureFormat: 1
  maxTextureSize: 2048
  textureSettings:
    serializedVersion: 2
    filterMode: 0
    aniso: 1
    mipBias: 0
    wrapU: 1
    wrapV: 1
    wrapW: 1
  nPOTScale: 0
  lightmap: 0
  compressionQuality: 50
  spriteMode: 1
  spriteExtrude: 1
  spriteMeshType: 1
  alignment: 0
  spritePivot: {x: 0.5, y: 0.5}
  spritePixelsToUnits: 16
  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
  spriteGenerateFallbackPhysicsShape: 1
  alphaUsage: 1
  alphaIsTransparency: 1
  spriteTessellationDetail: -1
  textureType: 8
  textureShape: 1
  singleChannelComponent: 0
  flipbookRows: 1
  flipbookColumns: 1
  maxTextureSizeSet: 0
  compressionQualitySet: 0
  textureFormatSet: 0
  ignorePngGamma: 0
  applyGammaDecoding: 0
  swizzle: 50462976
  cookieLightType: 0
  platformSettings:
  - serializedVersion: 3
    buildTarget: DefaultTexturePlatform
    maxTextureSize: 4096
    resizeAlgorithm: 0
    textureFormat: -1
    textureCompression: 0
    compressionQuality: 50
    crunchedCompression: 0
    allowsAlphaSplitting: 0
    overridden: 0
    ignorePlatformSupport: 0
    androidETC2FallbackOverride: 0
    forceMaximumCompressionQuality_BC6H_BC7: 0
  - serializedVersion: 3
    buildTarget: Standalone
    maxTextureSize: 2048
    resizeAlgorithm: 0
    textureFormat: -1
    textureCompression: 1
    compressionQuality: 50
    crunchedCompression: 0
    allowsAlphaSplitting: 0
    overridden: 0
    ignorePlatformSupport: 0
    androidETC2FallbackOverride: 0
    forceMaximumCompressionQuality_BC6H_BC7: 0
  - serializedVersion: 3
    buildTarget: Server
    maxTextureSize: 2048
    resizeAlgorithm: 0
    textureFormat: -1
    textureCompression: 1
    compressionQuality: 50
    crunchedCompression: 0
    allowsAlphaSplitting: 0
    overridden: 0
    ignorePlatformSupport: 0
    androidETC2FallbackOverride: 0
    forceMaximumCompressionQuality_BC6H_BC7: 0
  spriteSheet:
    serializedVersion: 2
    sprites: []
    outline: []
    physicsShape: []
    bones: []
    spriteID: 5e97eb03825dee720800000000000000
    internalID: 0
    vertices: []
    indices:
    edges: []
    weights: []
    secondaryTextures: []
    nameFileIdTable: {}
  mipmapLimitGroupName:
  pSDRemoveMatte: 0
  userData:
  assetBundleName:
  assetBundleVariant: