From ab5a24f4c0cffbc8e8f76e40293f2201027b7c50 Mon Sep 17 00:00:00 2001
From: miepzerino <o.skotnik@gmail.com>
Date: Mon, 07 Apr 2025 22:59:16 +0000
Subject: [PATCH] #49 added parallax and tiling to background
---
Assets/Sprites/BG/Sky_tiling.png.meta | 127 +++++++++++++++
Assets/Sprites/BG/Ground_tiling.png.meta | 127 +++++++++++++++
Assets/Scenes/GameplayScene.unity | 12
Assets/BackgroundManager.cs | 203 ++++++++++++++++++++----
Assets/Sprites/BG/Ground_tiling.png | 0
Assets/Sprites/BG/Sky_tiling.png | 0
6 files changed, 426 insertions(+), 43 deletions(-)
diff --git a/Assets/BackgroundManager.cs b/Assets/BackgroundManager.cs
index 2722ba7..306cac4 100644
--- a/Assets/BackgroundManager.cs
+++ b/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();
- if (transitionRenderer == null)
+ 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++)
{
- 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
+ for (int y = -verticalTiles; y <= verticalTiles; y++)
+ {
+ CreateTile(new Vector2Int(x, y));
+ }
}
- transitionRenderer.color = new Color(1, 1, 1, 0); // Start fully transparent
+ }
+
+ private void CreateTile(Vector2Int gridPosition)
+ {
+ 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
- if (initialMovingUp != isMovingUp &&
- ((initialMovingUp ? initialY > currentY : initialY < currentY)
- ))
+ // Check if direction changed
+ if (initialMovingUp != isMovingUp &&
+ ((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;
}
}
diff --git a/Assets/Scenes/GameplayScene.unity b/Assets/Scenes/GameplayScene.unity
index 1d75531..a0b7bb5 100644
--- a/Assets/Scenes/GameplayScene.unity
+++ b/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
diff --git a/Assets/Sprites/BG/Ground_tiling.png b/Assets/Sprites/BG/Ground_tiling.png
new file mode 100644
index 0000000..6ee272a
--- /dev/null
+++ b/Assets/Sprites/BG/Ground_tiling.png
Binary files differ
diff --git a/Assets/Sprites/BG/Ground_tiling.png.meta b/Assets/Sprites/BG/Ground_tiling.png.meta
new file mode 100644
index 0000000..8c6a6bf
--- /dev/null
+++ b/Assets/Sprites/BG/Ground_tiling.png.meta
@@ -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:
diff --git a/Assets/Sprites/BG/Sky_tiling.png b/Assets/Sprites/BG/Sky_tiling.png
new file mode 100644
index 0000000..ecfc0a2
--- /dev/null
+++ b/Assets/Sprites/BG/Sky_tiling.png
Binary files differ
diff --git a/Assets/Sprites/BG/Sky_tiling.png.meta b/Assets/Sprites/BG/Sky_tiling.png.meta
new file mode 100644
index 0000000..aef5fda
--- /dev/null
+++ b/Assets/Sprites/BG/Sky_tiling.png.meta
@@ -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:
--
Gitblit v1.10.0