public MultiplayerLevelHandler(App root, GameClient client, LevelInitialization data, MultiplayerLevelType levelType, byte playerIndex) : base(root, data)
        {
            this.client           = client;
            this.localPlayerIndex = playerIndex;
            this.levelType        = levelType;

            client.OnUpdateAllActors += OnUpdateAllActors;
            client.AddCallback <CreateControllablePlayer>(OnPacketCreateControllablePlayer);
            client.AddCallback <CreateRemoteActor>(OnPacketCreateRemoteActor);
            client.AddCallback <DestroyRemoteActor>(OnPacketDestroyRemoteActor);
            client.AddCallback <RefreshActorAnimation>(OnPacketRefreshActorAnimation);
            client.AddCallback <ShowMessage>(OnPacketShowMessage);
            client.AddCallback <PlaySound>(OnPacketPlaySound);

            client.AddCallback <PlayerTakeDamage>(OnPacketPlayerTakeDamage);
            client.AddCallback <PlayerAddHealth>(OnPacketPlayerAddHealth);
            client.AddCallback <PlayerActivateForce>(OnPacketPlayerActivateForce);
            client.AddCallback <PlayerRefreshAmmo>(OnPacketPlayerRefreshAmmo);
            client.AddCallback <PlayerRefreshWeaponUpgrades>(OnPacketPlayerRefreshWeaponUpgrades);
            client.AddCallback <PlayerWarpToPosition>(OnPacketPlayerWarpToPosition);
            client.AddCallback <PlayerSetDizzyTime>(OnPacketPlayerSetDizzyTime);
            client.AddCallback <PlayerSetModifier>(OnPacketPlayerSetModifier);
            client.AddCallback <PlayerSetLaps>(OnPacketPlayerSetLaps);
            client.AddCallback <PlayerSetStats>(OnPacketPlayerSetStats);
            client.AddCallback <PlayerSetInvulnerability>(OnPacketPlayerSetInvulnerability);
            client.AddCallback <PlayerSetControllable>(OnPacketPlayerSetControllable);

            client.AddCallback <AdvanceTileAnimation>(OnPacketAdvanceTileAnimation);
            client.AddCallback <RevertTileAnimation>(OnPacketRevertTileAnimation);
            client.AddCallback <SetTrigger>(OnPacketSetTrigger);

            // Wait 3 frames and then inform server that loading is complete
            isStillLoading = 3;
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Player was requested to load a new level
        /// </summary>
        private void OnPacketLoadLevel(ref LoadLevel p)
        {
            int i = p.LevelName.IndexOf('/');

            if (i == -1)
            {
                return;
            }

            string serverName = p.ServerName;

            string episodeName = p.LevelName.Substring(0, i);
            string levelName   = p.LevelName.Substring(i + 1);

            byte playerIndex = p.AssignedPlayerIndex;
            MultiplayerLevelType levelType = p.LevelType;

            Await.NextAfterUpdate().OnCompleted(() => {
                LevelInitialization levelInit = new LevelInitialization(episodeName, levelName, GameDifficulty.Multiplayer);

                Scene.Current.Dispose();
                Scene.SwitchTo(new MultiplayerLevelHandler(this, client, levelInit, levelType, playerIndex));

                GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
                GC.Collect();
                GC.WaitForPendingFinalizers();

                GCSettings.LatencyMode = GCLatencyMode.LowLatency;

                ControlScheme.IsSuspended = false;

                UpdateRichPresence(levelInit, serverName);
            });
        }
Ejemplo n.º 3
0
        private void OnNetworkLoadLevel(ref LoadLevel p)
        {
            string episodeName;
            string levelName = p.LevelName;
            int    i         = levelName.IndexOf('/');

            if (i != -1)
            {
                episodeName = levelName.Substring(0, i);
                levelName   = levelName.Substring(i + 1);
            }
            else
            {
                return;
            }

            byte playerIndex = p.AssignedPlayerIndex;

            DispatchToMainThread(delegate {
                Scene.Current.Dispose();

                LevelInitialization levelInit = new LevelInitialization(episodeName, levelName, GameDifficulty.Multiplayer);

                Scene.SwitchTo(new NetworkLevelHandler(this, net, levelInit, playerIndex));

                UpdateRichPresence(levelInit);
            });
        }
Ejemplo n.º 4
0
        public NetworkLevelHandler(Controller root, NetworkHandler network, LevelInitialization data, int playerIndex) : base(root, data)
        {
            this.network     = network;
            this.playerIndex = playerIndex;

            rootObject.AddComponent(new LocalController(this));

            network.RegisterCallback <CreateRemotePlayer>(OnCreateRemotePlayer);
            network.RegisterCallback <UpdateRemotePlayer>(OnUpdateRemotePlayer);
            network.RegisterCallback <DestroyRemotePlayer>(OnDestroyRemotePlayer);
        }
Ejemplo n.º 5
0
        public override void OnUpdate()
        {
            if (animation < 1f)
            {
                animation = Math.Min(animation + Time.TimeMult * 0.016f, 1f);
            }

            if (ControlScheme.MenuActionHit(PlayerActions.Fire))
            {
                if (selectedIndex == 2)
                {
                    ControlScheme.IsSuspended = true;

                    api.PlaySound("MenuSelect", 0.5f);
                    api.BeginFadeOut(() => {
                        ControlScheme.IsSuspended = false;

                        LevelInitialization levelInit = new LevelInitialization(
                            episodeName,
                            levelName,
                            (GameDifficulty.Easy + selectedDifficulty),
                            (PlayerType.Jazz + selectedPlayerType)
                            );

                        if (!string.IsNullOrEmpty(previousEpisodeName))
                        {
                            ref PlayerCarryOver player = ref levelInit.PlayerCarryOvers[0];

                            byte lives      = Preferences.Get <byte>("EpisodeEnd_Lives_" + previousEpisodeName);
                            uint score      = Preferences.Get <uint>("EpisodeEnd_Score_" + previousEpisodeName);
                            short[] ammo    = Preferences.Get <short[]>("EpisodeEnd_Ammo_" + previousEpisodeName);
                            byte[] upgrades = Preferences.Get <byte[]>("EpisodeEnd_Upgrades_" + previousEpisodeName);

                            if (lives > 0)
                            {
                                player.Lives = lives;
                            }
                            if (score > 0)
                            {
                                player.Score = score;
                            }
                            if (ammo != null)
                            {
                                player.Ammo = ammo;
                            }
                            if (upgrades != null)
                            {
                                player.WeaponUpgrades = upgrades;
                            }
                        }

                        api.SwitchToLevel(levelInit);
                    });
Ejemplo n.º 6
0
    public static LevelInitialization Instance()
    {
        if (!levelInitialization)
        {
            levelInitialization = FindObjectOfType(typeof(LevelInitialization)) as LevelInitialization;
            if (!levelInitialization)
            {
                Debug.LogError("There needs to be one active LevelInitialization script on a GameObject in your scene.");
            }
        }

        return(levelInitialization);
    }
Ejemplo n.º 7
0
        public void InitLevelChange(ExitType exitType, string nextLevel)
        {
            if (initState == InitState.Disposing)
            {
                return;
            }

            initState = InitState.Disposing;

            foreach (Player player in players)
            {
                player.OnLevelChanging(exitType);
            }

            if (nextLevel == null)
            {
                nextLevel = (exitType == ExitType.Bonus ? defaultSecretLevel : defaultNextLevel);
            }

            LevelInitialization data = default(LevelInitialization);

            if (nextLevel != null)
            {
                int i = nextLevel.IndexOf('/');
                if (i == -1)
                {
                    data.EpisodeName = episodeName;
                    data.LevelName   = nextLevel;
                }
                else
                {
                    data.EpisodeName = nextLevel.Substring(0, i);
                    data.LevelName   = nextLevel.Substring(i + 1);
                }
            }

            data.Difficulty = difficulty;
            data.ExitType   = exitType;

            data.PlayerCarryOvers = new PlayerCarryOver[players.Count];
            for (int i = 0; i < players.Count; i++)
            {
                data.PlayerCarryOvers[i] = players[i].PrepareLevelCarryOver();
            }

            data.LastEpisodeName = episodeName;

            currentCarryOver = data;

            levelChangeTimer = 50f;
        }
Ejemplo n.º 8
0
 // Use this for initialization
 void Awake()
 {
     if (jarvis == null)
     {
         DontDestroyOnLoad(gameObject);
         jarvis = this;
     }
     else if (jarvis != this)
     {
         Destroy(gameObject);
     }
     displayManager      = DisplayManager.Instance();
     levelInitialization = LevelInitialization.Instance();
 }
Ejemplo n.º 9
0
        public NetworkLevelHandler(App root, NetworkHandler net, LevelInitialization data, byte playerIndex) : base(root, data)
        {
            this.net = net;
            this.localPlayerIndex = playerIndex;

            net.OnUpdateAllPlayers += OnUpdateAllPlayers;
            net.RegisterCallback <CreateControllablePlayer>(OnCreateControllablePlayer);
            net.RegisterCallback <CreateRemotePlayer>(OnCreateRemotePlayer);
            net.RegisterCallback <DestroyRemotePlayer>(OnDestroyRemotePlayer);
            net.RegisterCallback <CreateRemoteObject>(OnCreateRemoteObject);
            net.RegisterCallback <DestroyRemoteObject>(OnDestroyRemoteObject);
            net.RegisterCallback <DecreasePlayerHealth>(OnDecreasePlayerHealth);
            net.RegisterCallback <RemotePlayerDied>(OnRemotePlayerDied);

            // Wait 3 frames and then inform server that loading is complete
            isStillLoading = 3;
        }
Ejemplo n.º 10
0
        public override void OnUpdate()
        {
            if (animation < 1f)
            {
                animation = Math.Min(animation + Time.TimeMult * 0.016f, 1f);
            }

            if (ControlScheme.MenuActionHit(PlayerActions.Fire))
            {
                if (selectedIndex == 2)
                {
                    api.PlaySound("MenuSelect", 0.5f);
                    LevelInitialization carryOver = new LevelInitialization(
                        episodeName,
                        levelName,
                        (GameDifficulty.Easy + selectedDifficulty),
                        (PlayerType.Jazz + selectedPlayerType)
                        );

                    if (!string.IsNullOrEmpty(previousEpisodeName))
                    {
                        ref PlayerCarryOver player = ref carryOver.PlayerCarryOvers[0];

                        byte   lives    = Preferences.Get <byte>("EpisodeEnd_Lives_" + previousEpisodeName);
                        int[]  ammo     = Preferences.Get <int[]>("EpisodeEnd_Ammo_" + previousEpisodeName);
                        byte[] upgrades = Preferences.Get <byte[]>("EpisodeEnd_Upgrades_" + previousEpisodeName);

                        if (lives > 0)
                        {
                            player.Lives = lives;
                        }
                        if (ammo != null)
                        {
                            player.Ammo = ammo;
                        }
                        if (upgrades != null)
                        {
                            player.WeaponUpgrades = upgrades;
                        }
                    }

                    api.SwitchToLevel(carryOver);
                }
            }
Ejemplo n.º 11
0
 public void SwitchToLevel(LevelInitialization data)
 {
     throw new NotImplementedException();
 }
Ejemplo n.º 12
0
 public void SwitchToLevel(LevelInitialization data)
 {
     root.ChangeLevel(data);
 }
Ejemplo n.º 13
0
 public EditorLevelHandler(App root, LevelInitialization data) : base(root, data)
 {
 }
Ejemplo n.º 14
0
        public void ChangeLevel(LevelInitialization levelInit = default(LevelInitialization))
        {
            ContentResolver.Current.ResetReferenceFlag();

            if (string.IsNullOrEmpty(levelInit.LevelName))
            {
                // Next level not specified, so show main menu
                ShowMainMenu(false);
            }
            else if (levelInit.LevelName == ":end")
            {
                // End of episode

                if (!string.IsNullOrEmpty(levelInit.LastEpisodeName) && levelInit.LastEpisodeName != "unknown")
                {
                    // ToDo: Implement time
                    Preferences.Set("EpisodeEnd_Time_" + levelInit.LastEpisodeName, (int)1);

                    if (levelInit.PlayerCarryOvers.Length == 1)
                    {
                        // Save CarryOvers only in SinglePlayer mode
                        ref PlayerCarryOver player = ref levelInit.PlayerCarryOvers[0];

                        Preferences.Set("EpisodeEnd_Lives_" + levelInit.LastEpisodeName, (byte)player.Lives);
                        Preferences.Set("EpisodeEnd_Score_" + levelInit.LastEpisodeName, player.Score);
                        if (player.Ammo != null)
                        {
                            Preferences.Set("EpisodeEnd_Ammo_" + levelInit.LastEpisodeName, player.Ammo);
                        }

                        // Save WeaponUpgrades only if at least one of them is upgraded
                        if (player.WeaponUpgrades != null)
                        {
                            for (int i = 0; i < player.WeaponUpgrades.Length; i++)
                            {
                                if (player.WeaponUpgrades[i] != 0)
                                {
                                    Preferences.Set("EpisodeEnd_Upgrades_" + levelInit.LastEpisodeName, player.WeaponUpgrades);
                                    break;
                                }
                            }
                        }
                    }

                    // Remove existing continue data
                    Preferences.Remove("EpisodeContinue_Misc_" + levelInit.LastEpisodeName);
                    Preferences.Remove("EpisodeContinue_Score_" + levelInit.LastEpisodeName);
                    Preferences.Remove("EpisodeContinue_Level_" + levelInit.LastEpisodeName);
                    Preferences.Remove("EpisodeContinue_Ammo_" + levelInit.LastEpisodeName);
                    Preferences.Remove("EpisodeContinue_Upgrades_" + levelInit.LastEpisodeName);

                    Preferences.Commit();

                    Episode lastEpisode = GetEpisode(levelInit.LastEpisodeName);
                    if (lastEpisode != null && !string.IsNullOrEmpty(lastEpisode.NextEpisode))
                    {
                        // Redirect to next episode
                        Episode nextEpisode = GetEpisode(lastEpisode.NextEpisode);

                        levelInit.EpisodeName = lastEpisode.NextEpisode;
                        levelInit.LevelName   = nextEpisode.FirstLevel;

                        // Start new level
                        LevelHandler handler = new LevelHandler(this, levelInit);

                        Scene.Current.DisposeLater();
                        Scene.SwitchTo(handler);

                        GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
                        GC.Collect();
                        GC.WaitForPendingFinalizers();

                        GCSettings.LatencyMode = GCLatencyMode.LowLatency;

                        UpdateRichPresence(levelInit, null);
                    }
                    else
                    {
                        // Next episode not found...
                        ShowMainMenu(false);
                    }
                }
                else
                {
                    // Shouldn't happen...
                    ShowMainMenu(false);
                }
            }
Ejemplo n.º 15
0
        public LevelHandler(Controller root, LevelInitialization data)
        {
            this.root = root;

            //levelName = data.LevelName;
            levelFileName = data.LevelName;
            episodeName   = data.EpisodeName;
            difficulty    = data.Difficulty;

            gravity = DefaultGravity;

            collisions = new DynamicTreeBroadPhase();

            api          = new ActorApi(this);
            eventSpawner = new EventSpawner(api);

            rootObject = new GameObject("LevelManager");
            rootObject.AddComponent(new LocalController(this));
            AddObject(rootObject);

            // Setup camera
            camera = new GameObject("MainCamera");
            Transform cameraTransform = camera.AddComponent <Transform>();

            Camera cameraInner = camera.AddComponent <Camera>();

            cameraInner.NearZ       = NearZ;
            cameraInner.FarZ        = FarZ;
            cameraInner.Perspective = PerspectiveMode.Flat;

            CameraController cameraController = camera.AddComponent <CameraController>();

            // Load level
            LoadLevel(levelFileName, episodeName);

            // Process carry overs
            if (data.PlayerCarryOvers != null)
            {
                for (int i = 0; i < data.PlayerCarryOvers.Length; i++)
                {
                    Vector2 spawnPosition = eventMap.GetSpawnPosition(data.PlayerCarryOvers[i].Type);
                    if (spawnPosition == new Vector2(-1, -1))
                    {
                        spawnPosition = eventMap.GetSpawnPosition(PlayerType.Jazz);
                        if (spawnPosition == new Vector2(-1, -1))
                        {
                            continue;
                        }
                    }

                    Player player = new Player();
                    player.OnAttach(new ActorInstantiationDetails {
                        Api    = api,
                        Pos    = new Vector3(spawnPosition, PlayerZ),
                        Params = new[] { (ushort)data.PlayerCarryOvers[i].Type, (ushort)i }
                    });
                    AddPlayer(player);

                    player.ReceiveLevelCarryOver(data.ExitType, ref data.PlayerCarryOvers[i]);
                }
            }

            Player  targetPlayer;
            Vector3 targetPlayerPosition;

            if (players.Count > 0)
            {
                targetPlayer         = players[0];
                targetPlayerPosition = targetPlayer.Transform.Pos;
            }
            else
            {
                Debug.WriteLine("No spawn point found, used default location instead!");

                targetPlayerPosition = new Vector3(120, 160, PlayerZ);

                targetPlayer = new Player();
                targetPlayer.OnAttach(new ActorInstantiationDetails {
                    Api    = api,
                    Pos    = targetPlayerPosition,
                    Params = new[] { (ushort)PlayerType.Jazz, (ushort)0 }
                });
                AddPlayer(targetPlayer);
            }

            // Bind camera to player
            cameraInner.RenderingSetup = new LevelRenderSetup(this);

            cameraTransform.Pos = new Vector3(targetPlayerPosition.X, targetPlayerPosition.Y, 0);

            cameraController.TargetObject = targetPlayer;
            ((ICmpUpdatable)cameraController).OnUpdate();
            camera.Parent = rootObject;

            DualityApp.Sound.Listener = camera;

            // Attach player to UI
            targetPlayer.AttachToHud(rootObject.AddComponent <Hud>());

            // Common sounds
            commonResources = ContentResolver.Current.RequestMetadata("Common/Scenery");
        }
Ejemplo n.º 16
0
        public override void OnUpdate()
        {
            if (selectAnimation < 1f)
            {
                selectAnimation = Math.Min(selectAnimation + Time.TimeMult * 0.016f, 1f);
            }

            if (expanded && expandedAnimation < 1f)
            {
                expandedAnimation = Math.Min(expandedAnimation + Time.TimeMult * 0.016f, 1f);
            }

            if (ControlScheme.MenuActionHit(PlayerActions.Fire))
            {
                if (episodes.Count > 0 && episodes[selectedIndex].IsAvailable)
                {
                    api.PlaySound("MenuSelect", 0.5f);

                    if (episodes[selectedIndex].CanContinue)
                    {
                        if (expanded)
                        {
                            // Restart episode
                            // Clear continue data
                            string episodeName = episodes[selectedIndex].Episode.Token;
                            Preferences.Remove("EpisodeContinue_Misc_" + episodeName);
                            Preferences.Remove("EpisodeContinue_Level_" + episodeName);
                            Preferences.Remove("EpisodeContinue_Ammo_" + episodeName);
                            Preferences.Remove("EpisodeContinue_Upgrades_" + episodeName);

                            Preferences.Commit();

                            episodes.Data[selectedIndex].CanContinue = false;
                            expanded          = false;
                            expandedAnimation = 0f;

                            api.SwitchToSection(new StartGameOptionsSection(
                                                    episodes[selectedIndex].Episode.Token,
                                                    episodes[selectedIndex].Episode.FirstLevel,
                                                    episodes[selectedIndex].Episode.PreviousEpisode
                                                    ));
                        }
                        else
                        {
                            ControlScheme.IsSuspended = true;

                            api.BeginFadeOut(() => {
                                ControlScheme.IsSuspended = false;

                                string episodeName = episodes[selectedIndex].Episode.Token;
                                string levelName   = Preferences.Get <string>("EpisodeContinue_Level_" + episodeName);

                                // Lives, Difficulty and PlayerType is saved in Misc array [Jazz2.Core/Game/Controller.cs: ~146]
                                byte[] misc = Preferences.Get <byte[]>("EpisodeContinue_Misc_" + episodeName);

                                LevelInitialization carryOver = new LevelInitialization(
                                    episodeName,
                                    levelName,
                                    (GameDifficulty)misc[1],
                                    (PlayerType)misc[2]
                                    );

                                ref PlayerCarryOver player = ref carryOver.PlayerCarryOvers[0];

                                if (misc[0] > 0)
                                {
                                    player.Lives = misc[0];
                                }

                                short[] ammo = Preferences.Get <short[]>("EpisodeContinue_Ammo_" + episodeName);
                                if (ammo != null)
                                {
                                    player.Ammo = ammo;
                                }

                                byte[] upgrades = Preferences.Get <byte[]>("EpisodeContinue_Upgrades_" + episodeName);
                                if (upgrades != null)
                                {
                                    player.WeaponUpgrades = upgrades;
                                }

                                api.SwitchToLevel(carryOver);
                            });
Ejemplo n.º 17
0
        public LevelHandler(App root, LevelInitialization data)
        {
            this.root = root;

            levelFileName = data.LevelName;
            episodeName   = data.EpisodeName;
            difficulty    = data.Difficulty;

            gravity = DefaultGravity;

            collisions = new DynamicTreeBroadPhase <ActorBase>();

            api          = new ActorApi(this);
            eventSpawner = new EventSpawner(api);

            rootObject = new GameObject();
            rootObject.AddComponent(new LocalController(this));
            AddObject(rootObject);

            // Load level
            LoadLevel(levelFileName, episodeName);

            // Create HUD
            Hud hud = rootObject.AddComponent <Hud>();

            // Process carry overs
            if (data.PlayerCarryOvers != null)
            {
                for (int i = 0; i < data.PlayerCarryOvers.Length; i++)
                {
                    Vector2 spawnPosition = eventMap.GetSpawnPosition(data.PlayerCarryOvers[i].Type);
                    if (spawnPosition == new Vector2(-1, -1))
                    {
                        spawnPosition = eventMap.GetSpawnPosition(PlayerType.Jazz);
                        if (spawnPosition == new Vector2(-1, -1))
                        {
                            continue;
                        }
                    }

                    Player player = new Player();
                    player.OnActivated(new ActorActivationDetails {
                        Api    = api,
                        Pos    = new Vector3(spawnPosition, PlayerZ),
                        Params = new[] { (ushort)data.PlayerCarryOvers[i].Type, (ushort)i }
                    });
                    AddPlayer(player);

                    if (i == 0)
                    {
                        player.AttachToHud(hud);
                    }

                    player.ReceiveLevelCarryOver(data.ExitType, ref data.PlayerCarryOvers[i]);
                }
            }

            Player  targetPlayer;
            Vector3 targetPlayerPosition;

            if (players.Count > 0)
            {
                targetPlayer         = players[0];
                targetPlayerPosition = targetPlayer.Transform.Pos;

                // Setup all cameras
                float relativeViewRange = (1f / players.Count);
                for (int i = 0; i < players.Count; i++)
                {
                    GameObject camera          = new GameObject(/*"MainCamera " + i*/);
                    Transform  cameraTransform = camera.AddComponent <Transform>();

                    Camera cameraInner = camera.AddComponent <Camera>();
                    cameraInner.NearZ          = NearZ;
                    cameraInner.FarZ           = FarZ;
                    cameraInner.Projection     = ProjectionMode.Orthographic;
                    cameraInner.VisibilityMask = VisibilityFlag.Group0 | VisibilityFlag.ScreenOverlay | (VisibilityFlag)(1 << i);

                    switch (players.Count)
                    {
                    case 1: cameraInner.TargetRect = new Rect(0f, 0f, 1f, 1f); break;

                    case 2: cameraInner.TargetRect = new Rect(0f, i * relativeViewRange, 1f, relativeViewRange); break;

                    case 3: cameraInner.TargetRect = new Rect(0f, i * relativeViewRange, 1f, relativeViewRange); break;

                    case 4: cameraInner.TargetRect = new Rect((i % 2) * 0.5f, (i / 2) * 0.5f, 0.5f, 0.5f); break;
                    }

                    // Create controller
                    CameraController cameraController = camera.AddComponent <CameraController>();
                    cameraController.ViewBounds = levelBounds;

                    // Bind camera to player
                    cameraInner.RenderingSetup = new LevelRenderSetup(this);

                    Player currentPlayer = players[i];
                    cameraTransform.Pos           = new Vector3(currentPlayer.Transform.Pos.Xy, 0);
                    cameraController.TargetObject = currentPlayer;

                    ((ICmpFixedUpdatable)cameraController).OnFixedUpdate(1f);
                    camera.Parent = rootObject;

                    cameras.Add(camera);

                    if (i == 0)
                    {
                        // First camera is always sound listener
                        DualityApp.Sound.Listener = camera;
                    }
                }
            }
            else
            {
                GameObject camera          = new GameObject(/*"MainCamera " + i*/);
                Transform  cameraTransform = camera.AddComponent <Transform>();

                Camera cameraInner = camera.AddComponent <Camera>();
                cameraInner.NearZ          = NearZ;
                cameraInner.FarZ           = FarZ;
                cameraInner.Projection     = ProjectionMode.Orthographic;
                cameraInner.VisibilityMask = VisibilityFlag.Group0 | VisibilityFlag.ScreenOverlay | (VisibilityFlag)(1 << 0);

                // Create controller
                CameraController cameraController = camera.AddComponent <CameraController>();
                cameraController.ViewBounds = levelBounds;

                // Bind camera to player
                cameraInner.RenderingSetup = new LevelRenderSetup(this);

                cameraTransform.Pos = new Vector3(levelBounds.Center, 0);

                ((ICmpUpdatable)cameraController).OnUpdate();
                camera.Parent = rootObject;

                cameras.Add(camera);

                // First camera is always sound listener
                DualityApp.Sound.Listener = camera;

                hud.BeginFadeIn(true);
            }

            // Common sounds
            commonResources = ContentResolver.Current.RequestMetadata("Common/Scenery");
        }