|
|
|
|
using Duality;
|
|
|
|
|
using Duality.Components;
|
|
|
|
|
using Duality.Components.Renderers;
|
|
|
|
|
using Duality.Resources;
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace BackGroundScroller_Example
|
|
|
|
|
{
|
|
|
|
|
//BackgroundScroller - Maintains/Creates/Moves layerss
|
|
|
|
|
public class BackgroundScroller : Component, ICmpInitializable
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
//vertical offset can be defined
|
|
|
|
|
private float z_PosFront;
|
|
|
|
|
private float z_PosMid;
|
|
|
|
|
private float z_PosBack;
|
|
|
|
|
|
|
|
|
|
public float zOffsetFront
|
|
|
|
|
{
|
|
|
|
|
get { return this.z_PosFront; }
|
|
|
|
|
set { this.z_PosFront = value; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public float zOffsetMid
|
|
|
|
|
{
|
|
|
|
|
get { return this.z_PosMid; }
|
|
|
|
|
set { this.z_PosMid = value; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public float zOffsetBack
|
|
|
|
|
{
|
|
|
|
|
get { return this.z_PosBack; }
|
|
|
|
|
set { this.z_PosBack = value; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//due to vertical offset some layers might need a upscale
|
|
|
|
|
private float scaleFront;
|
|
|
|
|
private float scaleMid;
|
|
|
|
|
private float scaleBack;
|
|
|
|
|
|
|
|
|
|
public float ScaleFrontLayer
|
|
|
|
|
{
|
|
|
|
|
get { return this.scaleFront; }
|
|
|
|
|
set { this.scaleFront = value; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public float ScaleMidLayer
|
|
|
|
|
{
|
|
|
|
|
get { return this.scaleMid; }
|
|
|
|
|
set { this.scaleMid = value; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public float ScaleBackLayer
|
|
|
|
|
{
|
|
|
|
|
get { return this.scaleBack; }
|
|
|
|
|
set { this.scaleBack = value; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Load Prefabs used to generate the spawning background -> further in developement this will be removed for
|
|
|
|
|
//an automation which pics the created prefab due to a master level plan given by the level handler
|
|
|
|
|
private ContentRef<Prefab> frontLayerPrefab;
|
|
|
|
|
private ContentRef<Prefab> midLayerPrefab;
|
|
|
|
|
private ContentRef<Prefab> backLayerPrefab;
|
|
|
|
|
|
|
|
|
|
public ContentRef<Prefab> FrontLayerPrefab
|
|
|
|
|
{
|
|
|
|
|
get { return this.frontLayerPrefab; }
|
|
|
|
|
set { this.frontLayerPrefab = value; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ContentRef<Prefab> MidLayerPrefab
|
|
|
|
|
{
|
|
|
|
|
get { return this.midLayerPrefab; }
|
|
|
|
|
set { this.midLayerPrefab = value; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ContentRef<Prefab> BackLayerPrefab
|
|
|
|
|
{
|
|
|
|
|
get { return this.backLayerPrefab; }
|
|
|
|
|
set { this.backLayerPrefab = value; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//Layerlists to maintain and iterate through all on a certain z-level
|
|
|
|
|
Dictionary<GameObject, ContentRef<Prefab>> FrontLayers;
|
|
|
|
|
Dictionary<GameObject, ContentRef<Prefab>> MidLayers;
|
|
|
|
|
Dictionary<GameObject, ContentRef<Prefab>> BackLayers;
|
|
|
|
|
|
|
|
|
|
public void OnInit(InitContext context)
|
|
|
|
|
{
|
|
|
|
|
FrontLayers = new Dictionary<GameObject, ContentRef<Prefab>>();
|
|
|
|
|
MidLayers = new Dictionary<GameObject, ContentRef<Prefab>>();
|
|
|
|
|
BackLayers = new Dictionary<GameObject, ContentRef<Prefab>>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void OnShutdown(ShutdownContext context)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void Update(float camSpeed, Camera mainCam)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
//Copy of bluebrints given by levelHandler to enable on the fly prefab changing
|
|
|
|
|
//Check if LayerList is empty, if yes startscreen has to be initialized
|
|
|
|
|
if (BackLayers.Count == 0 && MidLayers.Count == 0 && FrontLayers.Count == 0)
|
|
|
|
|
{
|
|
|
|
|
Vector3 tmpPos = new Vector3();
|
|
|
|
|
GameObject tmpLayer;
|
|
|
|
|
float textureWidth;
|
|
|
|
|
float tmpScale;
|
|
|
|
|
|
|
|
|
|
//The startconstellation is a mainscreen, a 1 x left offscreen layer and 1 x rightoffscreen layer
|
|
|
|
|
|
|
|
|
|
//FrontLayers Preset (3 : 1 x LeftOffscreen, 1 x Mainscreen, 1 x RightOffscreen)
|
|
|
|
|
GameObject newFront = FrontLayerPrefab.Res.Instantiate();
|
|
|
|
|
textureWidth = newFront.GetComponent<SpriteRenderer>().SharedMaterial.Res.MainTexture.Res.Size.X;
|
|
|
|
|
tmpScale = scaleFront;
|
|
|
|
|
tmpPos.Z = zOffsetFront;
|
|
|
|
|
|
|
|
|
|
//LeftOffscreen-Front
|
|
|
|
|
tmpPos.X = -textureWidth * tmpScale;
|
|
|
|
|
tmpLayer = createLayer(FrontLayerPrefab, tmpPos,tmpScale, "Front");
|
|
|
|
|
FrontLayers.Add(tmpLayer, FrontLayerPrefab);
|
|
|
|
|
|
|
|
|
|
//MainScreen-Front
|
|
|
|
|
tmpPos.X = 0;
|
|
|
|
|
tmpLayer = createLayer(FrontLayerPrefab, tmpPos, tmpScale, "Front");
|
|
|
|
|
FrontLayers.Add(tmpLayer, FrontLayerPrefab);
|
|
|
|
|
|
|
|
|
|
//RightOffscreen-Front
|
|
|
|
|
tmpPos.X = textureWidth * tmpScale;
|
|
|
|
|
tmpLayer = createLayer(FrontLayerPrefab, tmpPos, tmpScale, "Front");
|
|
|
|
|
FrontLayers.Add(tmpLayer, FrontLayerPrefab);
|
|
|
|
|
|
|
|
|
|
//MidLayers Preset (3 : 1 x LeftOffscreen, 1 x Mainscreen, 1 x RightOffscreen)
|
|
|
|
|
GameObject newMid = MidLayerPrefab.Res.Instantiate();
|
|
|
|
|
textureWidth = newMid.GetComponent<SpriteRenderer>().SharedMaterial.Res.MainTexture.Res.Size.X;
|
|
|
|
|
tmpScale = scaleMid;
|
|
|
|
|
tmpPos.Z = zOffsetMid;
|
|
|
|
|
|
|
|
|
|
//LeftOffscreen-Mid
|
|
|
|
|
tmpPos.X = -textureWidth * tmpScale;
|
|
|
|
|
tmpLayer = createLayer(MidLayerPrefab, tmpPos, tmpScale, "Mid");
|
|
|
|
|
MidLayers.Add(tmpLayer, MidLayerPrefab);
|
|
|
|
|
|
|
|
|
|
//MainScreen-Mid
|
|
|
|
|
tmpPos.X = 0;
|
|
|
|
|
tmpLayer = createLayer(MidLayerPrefab, tmpPos, tmpScale, "Mid");
|
|
|
|
|
MidLayers.Add(tmpLayer, MidLayerPrefab);
|
|
|
|
|
|
|
|
|
|
//RightOffscreen-Mid
|
|
|
|
|
tmpPos.X = textureWidth * tmpScale;
|
|
|
|
|
tmpLayer = createLayer(MidLayerPrefab, tmpPos, tmpScale, "Mid");
|
|
|
|
|
MidLayers.Add(tmpLayer, MidLayerPrefab);
|
|
|
|
|
|
|
|
|
|
//BackLayers Preset (3 : 1 x LeftOffscreen, 1 x Mainscreen, 1 x RightOffscreen)
|
|
|
|
|
GameObject newBack = BackLayerPrefab.Res.Instantiate();
|
|
|
|
|
textureWidth = newBack.GetComponent<SpriteRenderer>().SharedMaterial.Res.MainTexture.Res.Size.X;
|
|
|
|
|
tmpPos.Z = zOffsetBack;
|
|
|
|
|
tmpScale = scaleBack;
|
|
|
|
|
|
|
|
|
|
//LeftOffscreen-Back
|
|
|
|
|
tmpPos.X = -textureWidth * tmpScale;
|
|
|
|
|
tmpLayer = createLayer(BackLayerPrefab, tmpPos, tmpScale, "Back");
|
|
|
|
|
BackLayers.Add(tmpLayer, BackLayerPrefab);
|
|
|
|
|
|
|
|
|
|
//MainScreen-Back
|
|
|
|
|
tmpPos.X = 0;
|
|
|
|
|
tmpLayer = createLayer(BackLayerPrefab, tmpPos, tmpScale, "Back");
|
|
|
|
|
BackLayers.Add(tmpLayer, BackLayerPrefab);
|
|
|
|
|
|
|
|
|
|
//RightOffscreen-Back
|
|
|
|
|
tmpPos.X = textureWidth * tmpScale;
|
|
|
|
|
tmpLayer = createLayer(BackLayerPrefab, tmpPos, tmpScale, "Back");
|
|
|
|
|
BackLayers.Add(tmpLayer, BackLayerPrefab);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check if layers need to be killed/created by iterating through
|
|
|
|
|
//them and check their position relativ to the cam
|
|
|
|
|
UpdatePosition(mainCam, camSpeed);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Mechanisms to instantiate from the given prefabs and to add the new objects to the handled lists
|
|
|
|
|
private GameObject createLayer(ContentRef<Prefab> Prefab, Vector3 StartPos,float scale, string LayerName)
|
|
|
|
|
{
|
|
|
|
|
GameObject newLayer = Prefab.Res.Instantiate();
|
|
|
|
|
newLayer.Transform.MoveToAbs(StartPos*scale);
|
|
|
|
|
newLayer.Transform.Scale = scale;
|
|
|
|
|
newLayer.Parent = this.GameObj.ChildByName(LayerName);
|
|
|
|
|
return newLayer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void UpdatePosition(Camera cam, float speed)
|
|
|
|
|
{
|
|
|
|
|
//temporal list to still be able to delete objects while iterating through
|
|
|
|
|
Dictionary<GameObject, ContentRef<Prefab>> LayersToMove = new Dictionary<GameObject, ContentRef<Prefab>>();
|
|
|
|
|
|
|
|
|
|
//Enlist all layers from all lists to prepare for iteration
|
|
|
|
|
foreach (KeyValuePair<GameObject, ContentRef<Prefab>> KeyPair in BackLayers)
|
|
|
|
|
{
|
|
|
|
|
if (KeyPair.Key != null)
|
|
|
|
|
{
|
|
|
|
|
LayersToMove.Add(KeyPair.Key, KeyPair.Value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (KeyValuePair<GameObject, ContentRef<Prefab>> KeyPair in MidLayers)
|
|
|
|
|
{
|
|
|
|
|
if (KeyPair.Key != null)
|
|
|
|
|
{
|
|
|
|
|
LayersToMove.Add(KeyPair.Key, KeyPair.Value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (KeyValuePair<GameObject, ContentRef<Prefab>> KeyPair in FrontLayers)
|
|
|
|
|
{
|
|
|
|
|
if (KeyPair.Key != null)
|
|
|
|
|
{
|
|
|
|
|
LayersToMove.Add(KeyPair.Key, KeyPair.Value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Dictionary of layers is iterated and each is checked for leaving visible area + extra safety screen
|
|
|
|
|
foreach (KeyValuePair<GameObject, ContentRef<Prefab>> KeyPair in LayersToMove)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
//Calculate the spritesize for the recreation process
|
|
|
|
|
float screenWidth = 1366f; //has to be the actual screensize
|
|
|
|
|
float textureWidth;
|
|
|
|
|
float tmpZOffset = 0f;
|
|
|
|
|
float tmpScale = 1f;
|
|
|
|
|
string layerName = "";
|
|
|
|
|
|
|
|
|
|
//if offscreen the object is erased from the list and disposed at the next cicle
|
|
|
|
|
if (KeyPair.Key.Transform.Pos.X <= cam.GameObj.Transform.Pos.X - (2 * screenWidth * KeyPair.Key.Transform.Scale) ||
|
|
|
|
|
KeyPair.Key.Transform.Pos.X >= cam.GameObj.Transform.Pos.X + (2 * screenWidth * KeyPair.Key.Transform.Scale))
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
KeyPair.Key.DisposeLater();
|
|
|
|
|
|
|
|
|
|
//Create new Layer based on destructed one
|
|
|
|
|
Vector3 tmpPos = new Vector3();
|
|
|
|
|
textureWidth = KeyPair.Key.GetComponent<SpriteRenderer>().SharedMaterial.Res.MainTexture.Res.Size.X *
|
|
|
|
|
KeyPair.Key.GetComponent<Transform>().Scale;
|
|
|
|
|
|
|
|
|
|
//Find type of layer in the whole list and set its config to create a similar layer
|
|
|
|
|
if (BackLayers.ContainsKey(KeyPair.Key))
|
|
|
|
|
{
|
|
|
|
|
BackLayers.Remove(KeyPair.Key);
|
|
|
|
|
layerName = "Back";
|
|
|
|
|
tmpZOffset = z_PosBack;
|
|
|
|
|
tmpScale = scaleBack;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (MidLayers.ContainsKey(KeyPair.Key))
|
|
|
|
|
{
|
|
|
|
|
MidLayers.Remove(KeyPair.Key);
|
|
|
|
|
layerName = "Mid";
|
|
|
|
|
tmpZOffset = z_PosMid;
|
|
|
|
|
tmpScale = scaleMid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (FrontLayers.ContainsKey(KeyPair.Key))
|
|
|
|
|
{
|
|
|
|
|
FrontLayers.Remove(KeyPair.Key);
|
|
|
|
|
layerName = "Front";
|
|
|
|
|
tmpZOffset = z_PosFront;
|
|
|
|
|
tmpScale = scaleFront;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Determine which side the layer has to be knitted onto
|
|
|
|
|
if (KeyPair.Key.Transform.Pos.X <= cam.GameObj.Transform.Pos.X - (2 * screenWidth * tmpScale))
|
|
|
|
|
tmpPos.X = KeyPair.Key.Transform.Pos.X + 3 * textureWidth * tmpScale;
|
|
|
|
|
else
|
|
|
|
|
tmpPos.X = KeyPair.Key.Transform.Pos.X - 3 * textureWidth * tmpScale;
|
|
|
|
|
|
|
|
|
|
tmpPos.Z = tmpZOffset;
|
|
|
|
|
|
|
|
|
|
//Temporary GameObject for Instantiation and temporary Keypair for adding to the dictionary
|
|
|
|
|
GameObject tmpLayer;
|
|
|
|
|
tmpLayer = createLayer(KeyPair.Value, tmpPos, tmpScale, layerName);
|
|
|
|
|
KeyValuePair<GameObject, ContentRef<Prefab>> tmpKeyPair = new KeyValuePair<GameObject, ContentRef<Prefab>>(tmpLayer, KeyPair.Value);
|
|
|
|
|
|
|
|
|
|
switch (layerName)
|
|
|
|
|
{
|
|
|
|
|
case "Front": FrontLayers.Add(tmpKeyPair.Key, tmpKeyPair.Value); break;
|
|
|
|
|
case "Mid": MidLayers.Add(tmpKeyPair.Key, tmpKeyPair.Value); break;
|
|
|
|
|
case "Back": BackLayers.Add(tmpKeyPair.Key, tmpKeyPair.Value); break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|