Beispiel #1
0
        protected virtual void OnUpdate()
        {
            if (ControlScheme.MenuActionHit(PlayerActions.Menu))
            {
                Scene.SwitchTo(new InGameMenu(root, this));
            }

            Hud.ShowDebugText("- FPS: " + Time.Fps.ToString("N0") + "  (" + Math.Round(Time.UnscaledDeltaTime * 1000, 1).ToString("N1") + " ms)");
            Hud.ShowDebugText("  Diff.: " + difficulty + " | Actors: " + actors.Count.ToString("N0"));
            Hud.ShowDebugText("  Ambient Light: " + ambientLightCurrent.ToString("0.00") + " / " + ambientLightTarget.ToString("0.00"));
            Hud.ShowDebugText("  Collisions: " + collisionsCountA + " > " + collisionsCountB + " > " + collisionsCountC);
        }
        private void OnPacketShowMessage(ref ShowMessage p)
        {
            byte   flags = p.Flags;
            string text  = p.Text;

            Await.NextAfterUpdate().OnCompleted(() => {
                if (players.Count > 0)
                {
                    Hud hud = players[0].AttachedHud;
                    if (hud != null)
                    {
                        hud.ShowLevelText(text, (flags & 0x01) == 0x01);
                    }
                }
            });
        }
        /// <summary>
        /// Player is allowed to join game, controllable actor should be created
        /// </summary>
        private void OnPacketCreateControllablePlayer(ref CreateControllablePlayer p)
        {
            // ToDo: throw on mismatch?
            localPlayerIndex = p.Index;

            PlayerType type         = p.Type;
            Vector3    pos          = p.Pos;
            byte       health       = p.Health;
            bool       controllable = p.Controllable;

            Await.NextAfterUpdate().OnCompleted(() => {
                if (players.Count > 0)
                {
                    Player oldPlayer = players[0];
                    if (oldPlayer.PlayerType == type)
                    {
                        oldPlayer.Respawn(pos.Xy);
                        oldPlayer.Health = health;
                        return;
                    }

                    RemoveActor(oldPlayer);
                    Players.Remove(oldPlayer);
                }

                Player player = new Player();
                player.OnActivated(new ActorActivationDetails {
                    LevelHandler = this,
                    Pos          = pos,
                    Params       = new[] { (ushort)type, (ushort)0 }
                });
                player.Health = health;
                AddPlayer(player);

                cameras[0].Transform.Pos = new Vector3(pos.Xy, 0);
                cameras[0].GetComponent <CameraController>().TargetObject = player;

                Hud hud          = rootObject.AddComponent <Hud>();
                hud.LevelHandler = this;
                player.AttachToHud(hud);

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

                // Wait for server to start game
                player.IsControllableExternal = controllable;
            });
        }
Beispiel #4
0
        private void ActivateBoss(ushort musicFile)
        {
            if (activeBoss != null)
            {
                return;
            }

            foreach (GameObject obj in ActiveObjects)
            {
                activeBoss = obj as BossBase;
                if (activeBoss != null)
                {
                    break;
                }
            }

            if (activeBoss == null)
            {
                return;
            }

            if (!activeBoss.HandleBossActivated())
            {
                return;
            }

            Hud hud = rootObject.GetComponent <Hud>();

            if (hud != null)
            {
                hud.ActiveBoss = activeBoss;
            }

#if !DISABLE_SOUND
            if (music != null)
            {
                music.FadeOut(3f);
            }

            // ToDo: Hardcoded music file
            string musicPath = PathOp.Combine(DualityApp.DataDirectory, "Music", "boss" + (musicFile + 1).ToString(CultureInfo.InvariantCulture) + ".j2b");

            music = new OpenMptStream(musicPath, true);
            music.BeginFadeIn(1f);
            DualityApp.Sound.PlaySound(music);
#endif
        }
Beispiel #5
0
        public bool ActivateBoss(ushort musicFile)
        {
            if (activeBoss != null)
            {
                return(false);
            }

            foreach (GameObject obj in ActiveObjects)
            {
                activeBoss = obj as BossBase;
                if (activeBoss != null)
                {
                    break;
                }
            }

            if (activeBoss == null)
            {
                return(false);
            }

            activeBoss.OnBossActivated();

            Hud hud = rootObject.GetComponent <Hud>();

            if (hud != null)
            {
                hud.ActiveBoss = activeBoss;
            }

            if (music != null)
            {
                music.FadeOut(3f);
            }

            // ToDo: Hardcoded music file
            string musicPath = PathOp.Combine(DualityApp.DataDirectory, "Music", "Boss" + (musicFile + 1).ToString(CultureInfo.InvariantCulture) + ".j2b");

            music = DualityApp.Sound.PlaySound(new OpenMptStream(musicPath));
            music.BeginFadeIn(1f);

            return(true);
        }
Beispiel #6
0
        protected virtual void OnUpdate()
        {
            if (ControlScheme.PlayerActionHit(0, PlayerActions.Menu))
            {
                Scene.SwitchTo(new InGameMenu(root, this));
            }

#if !DISABLE_CHEATS
            if (root.EnableCheats && difficulty != GameDifficulty.Multiplayer)
            {
                ProcessCheats();
            }
#endif

            Hud.ShowDebugText("- FPS: " + Time.Fps.ToString("N0") + "  (" + Math.Round(Time.UnscaledDeltaTime * 1000, 1).ToString("N1") + " ms)");
            Hud.ShowDebugText("  Diff.: " + difficulty + " | Actors: " + actors.Count.ToString("N0"));
            Hud.ShowDebugText("  Ambient Light: " + ambientLightCurrent.ToString("0.00") + " / " + ambientLightTarget.ToString("0.00"));
            Hud.ShowDebugText("  Collisions: " + collisionsCountA + " > " + collisionsCountB + " > " + collisionsCountC);
        }
Beispiel #7
0
        protected virtual void OnFixedUpdate(float timeMult)
        {
            if (currentCarryOver.HasValue)
            {
                bool playersReady = true;
                foreach (Player player in players)
                {
                    // Exit type is already provided
                    playersReady &= player.OnLevelChanging(ExitType.None);
                }

                if (playersReady)
                {
                    if (levelChangeTimer > 0)
                    {
                        levelChangeTimer -= timeMult;
                    }
                    else
                    {
                        root.ChangeLevel(currentCarryOver.Value);
                        currentCarryOver = null;
                        initState        = InitState.Disposed;
                        return;
                    }
                }
            }

            if (difficulty != GameDifficulty.Multiplayer)
            {
                if (players.Count > 0)
                {
                    Vector3 pos = players[0].Transform.Pos;
                    int     tx1 = (int)pos.X >> 5;
                    int     ty1 = (int)pos.Y >> 5;
                    int     tx2 = tx1;
                    int     ty2 = ty1;

#if ENABLE_SPLITSCREEN
                    for (int i = 1; i < players.Count; i++)
                    {
                        Vector3 pos2 = players[i].Transform.Pos;
                        int     tx   = (int)pos2.X >> 5;
                        int     ty   = (int)pos2.Y >> 5;
                        if (tx1 > tx)
                        {
                            tx1 = tx;
                        }
                        else if (tx2 < tx)
                        {
                            tx2 = tx;
                        }
                        if (ty1 > ty)
                        {
                            ty1 = ty;
                        }
                        else if (ty2 < ty)
                        {
                            ty2 = ty;
                        }
                    }
#endif

                    // ToDo: Remove this branching
#if __ANDROID__
                    const int ActivateTileRange = 20;
#else
                    const int ActivateTileRange = 26;
#endif
                    tx1 -= ActivateTileRange;
                    ty1 -= ActivateTileRange;
                    tx2 += ActivateTileRange;
                    ty2 += ActivateTileRange;

                    for (int i = 0; i < actors.Count; i++)
                    {
                        if (actors[i].OnTileDeactivate(tx1 - 2, ty1 - 2, tx2 + 2, ty2 + 2))
                        {
                            i--;
                        }
                    }

                    eventMap.ActivateEvents(tx1, ty1, tx2, ty2, initState != InitState.Initializing);
                }

                eventMap.ProcessGenerators(timeMult);
            }

            ResolveCollisions();

            // Ambient Light Transition
            if (ambientLightCurrent != ambientLightTarget)
            {
                float step = timeMult * 0.012f;
                if (MathF.Abs(ambientLightCurrent - ambientLightTarget) < step)
                {
                    ambientLightCurrent = ambientLightTarget;
                }
                else
                {
                    ambientLightCurrent += step * ((ambientLightTarget < ambientLightCurrent) ? -1 : 1);
                }
            }

            // Weather
            if (weatherType != WeatherType.None && commonResources.Graphics != null)
            {
                // ToDo: Apply weather effect to all other cameras too
                Vector3 viewPos = cameras[0].Transform.Pos;
                for (int i = 0; i < weatherIntensity; i++)
                {
                    TileMap.DebrisCollisionAction collisionAction;
                    if (weatherOutdoors)
                    {
                        collisionAction = TileMap.DebrisCollisionAction.Disappear;
                    }
                    else
                    {
                        collisionAction = (MathF.Rnd.NextFloat() > 0.7f
                            ? TileMap.DebrisCollisionAction.None
                            : TileMap.DebrisCollisionAction.Disappear);
                    }

                    Vector3 debrisPos = viewPos + MathF.Rnd.NextVector3((LevelRenderSetup.TargetSize.X / -2) - 40,
                                                                        (LevelRenderSetup.TargetSize.Y * -2 / 3), MainPlaneZ,
                                                                        LevelRenderSetup.TargetSize.X + 120, LevelRenderSetup.TargetSize.Y, 0);

                    if (weatherType == WeatherType.Rain)
                    {
                        GraphicResource res      = commonResources.Graphics["Rain"];
                        Material        material = res.Material.Res;
                        Texture         texture  = material.MainTexture.Res;

                        float scale  = MathF.Rnd.NextFloat(0.4f, 1.1f);
                        float speedX = MathF.Rnd.NextFloat(2.2f, 2.7f) * scale;
                        float speedY = MathF.Rnd.NextFloat(7.6f, 8.6f) * scale;

                        debrisPos.Z = MainPlaneZ * scale;

                        tileMap.CreateDebris(new TileMap.DestructibleDebris {
                            Pos   = debrisPos,
                            Size  = res.Base.FrameDimensions,
                            Speed = new Vector2(speedX, speedY),

                            Scale = scale,
                            Angle = MathF.Atan2(speedY, speedX),
                            Alpha = 1f,

                            Time = 180f,

                            Material       = material,
                            MaterialOffset = texture.LookupAtlas(res.FrameOffset + MathF.Rnd.Next(res.FrameCount)),

                            CollisionAction = collisionAction
                        });
                    }
                    else
                    {
                        GraphicResource res      = commonResources.Graphics["Snow"];
                        Material        material = res.Material.Res;
                        Texture         texture  = material.MainTexture.Res;

                        float scale  = MathF.Rnd.NextFloat(0.4f, 1.1f);
                        float speedX = MathF.Rnd.NextFloat(-1.6f, -1.2f) * scale;
                        float speedY = MathF.Rnd.NextFloat(3f, 4f) * scale;
                        float accel  = MathF.Rnd.NextFloat(-0.008f, 0.008f) * scale;

                        debrisPos.Z = MainPlaneZ * scale;

                        tileMap.CreateDebris(new TileMap.DestructibleDebris {
                            Pos          = debrisPos,
                            Size         = res.Base.FrameDimensions,
                            Speed        = new Vector2(speedX, speedY),
                            Acceleration = new Vector2(accel, -MathF.Abs(accel)),

                            Scale      = scale,
                            Angle      = MathF.Rnd.NextFloat(MathF.TwoPi),
                            AngleSpeed = speedX * 0.02f,
                            Alpha      = 1f,

                            Time = 180f,

                            Material       = material,
                            MaterialOffset = texture.LookupAtlas(res.FrameOffset + MathF.Rnd.Next(res.FrameCount)),

                            CollisionAction = collisionAction
                        });
                    }
                }
            }

            // Active Boss
            if (activeBoss != null && activeBoss.Scene == null)
            {
                activeBoss = null;

                Hud hud = rootObject.GetComponent <Hud>();
                if (hud != null)
                {
                    hud.ActiveBoss = null;
                }

                InitLevelChange(ExitType.Normal, null);
                levelChangeTimer = 300;
            }

            if (initState == InitState.Initializing)
            {
                initState = InitState.Initialized;
            }


            collisionsCountA = 0;
            collisionsCountB = 0;
            collisionsCountC = 0;
        }
Beispiel #8
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");
        }
Beispiel #9
0
        private void OnUpdate()
        {
            if (currentCarryOver.HasValue)
            {
                if (levelChangeTimer > 0)
                {
                    levelChangeTimer -= Time.TimeMult;
                }
                else
                {
                    root.ChangeLevel(currentCarryOver.Value);
                    currentCarryOver = null;
                    return;
                }
            }

            Vector3 pos = players[0].Transform.Pos;
            //int tx = (int)(pos.X / 32);
            //int ty = (int)(pos.Y / 32);
            int tx = (int)pos.X >> 5;
            int ty = (int)pos.Y >> 5;

            // ToDo: Remove this branching
#if __ANDROID__
            const int ActivateTileRange = 20;
#else
            const int ActivateTileRange = 26;
#endif

            for (int i = 0; i < actors.Count; i++)
            {
                if (actors[i].OnTileDeactivate(tx, ty, ActivateTileRange + 2))
                {
                    i--;
                }
            }

            eventMap.ActivateEvents(tx, ty, ActivateTileRange);

            eventMap.ProcessGenerators();

            ResolveCollisions();

            // Ambient Light Transition
            if (ambientLightCurrent != ambientLightTarget)
            {
                float step = Time.TimeMult * 0.012f;
                if (MathF.Abs(ambientLightCurrent - ambientLightTarget) < step)
                {
                    ambientLightCurrent = ambientLightTarget;
                }
                else
                {
                    ambientLightCurrent += step * ((ambientLightTarget < ambientLightCurrent) ? -1 : 1);
                }
            }

            // Weather
            if (weatherType != WeatherType.None)
            {
                Vector3 viewPos = camera.Transform.Pos;
                for (int i = 0; i < weatherIntensity; i++)
                {
                    TileMap.DebrisCollisionAction collisionAction;
                    if (weatherOutdoors)
                    {
                        collisionAction = TileMap.DebrisCollisionAction.Disappear;
                    }
                    else
                    {
                        collisionAction = (MathF.Rnd.NextFloat() > 0.7f
                            ? TileMap.DebrisCollisionAction.None
                            : TileMap.DebrisCollisionAction.Disappear);
                    }

                    Vector3 debrisPos = viewPos + MathF.Rnd.NextVector3((LevelRenderSetup.TargetSize.X / -2) - 40,
                                                                        (LevelRenderSetup.TargetSize.Y * -2 / 3), MainPlaneZ,
                                                                        LevelRenderSetup.TargetSize.X + 120, LevelRenderSetup.TargetSize.Y, 0);

                    if (weatherType == WeatherType.Rain)
                    {
                        GraphicResource res      = commonResources.Graphics["Rain"];
                        Material        material = res.Material.Res;
                        Texture         texture  = material.MainTexture.Res;

                        float scale  = MathF.Rnd.NextFloat(0.4f, 1.1f);
                        float speedX = MathF.Rnd.NextFloat(2.2f, 2.7f) * scale;
                        float speedY = MathF.Rnd.NextFloat(7.6f, 8.6f) * scale;

                        debrisPos.Z = MainPlaneZ * scale;

                        tileMap.CreateDebris(new TileMap.DestructibleDebris {
                            Pos   = debrisPos,
                            Size  = res.Base.FrameDimensions,
                            Speed = new Vector2(speedX, speedY),

                            Scale = scale,
                            Angle = MathF.Atan2(speedY, speedX),
                            Alpha = 1f,

                            Time = 180f,

                            Material       = material,
                            MaterialOffset = texture.LookupAtlas(res.FrameOffset + MathF.Rnd.Next(res.FrameCount)),

                            CollisionAction = collisionAction
                        });
                    }
                    else
                    {
                        GraphicResource res      = commonResources.Graphics["Snow"];
                        Material        material = res.Material.Res;
                        Texture         texture  = material.MainTexture.Res;

                        float scale  = MathF.Rnd.NextFloat(0.4f, 1.1f);
                        float speedX = MathF.Rnd.NextFloat(-1.6f, -1.2f) * scale;
                        float speedY = MathF.Rnd.NextFloat(3f, 4f) * scale;
                        float accel  = MathF.Rnd.NextFloat(-0.008f, 0.008f) * scale;

                        debrisPos.Z = MainPlaneZ * scale;

                        tileMap.CreateDebris(new TileMap.DestructibleDebris {
                            Pos          = debrisPos,
                            Size         = res.Base.FrameDimensions,
                            Speed        = new Vector2(speedX, speedY),
                            Acceleration = new Vector2(accel, -MathF.Abs(accel)),

                            Scale      = scale,
                            Angle      = MathF.Rnd.NextFloat(MathF.TwoPi),
                            AngleSpeed = speedX * 0.02f,
                            Alpha      = 1f,

                            Time = 180f,

                            Material       = material,
                            MaterialOffset = texture.LookupAtlas(res.FrameOffset + MathF.Rnd.Next(res.FrameCount)),

                            CollisionAction = collisionAction
                        });
                    }
                }
            }

            // Active Boss
            if (activeBoss != null && activeBoss.ParentScene == null)
            {
                activeBoss = null;

                Hud hud = rootObject.GetComponent <Hud>();
                if (hud != null)
                {
                    hud.ActiveBoss = null;
                }

                InitLevelChange(ExitType.Normal, null);
                levelChangeTimer *= 2;
            }

            if (DualityApp.Keyboard.KeyHit(Key.Escape))
            {
                Scene.SwitchTo(new InGameMenu(root, this));
            }

            Hud.ShowDebugText("- FPS: " + Time.Fps.ToString("N0") + "  (" + Math.Round(Time.UnscaledDeltaTime * 1000, 1).ToString("N1") + " ms)");
            Hud.ShowDebugText("  Diff.: " + difficulty + " | Actors: " + actors.Count.ToString("N0"));
            Hud.ShowDebugText("  Ambient Light: " + ambientLightCurrent.ToString("0.00") + " / " + ambientLightTarget.ToString("0.00"));


            Hud.ShowDebugText("  Collisions: " + collisionsCountA + " > " + collisionsCountB + " > " + collisionsCountC);
            collisionsCountA = 0;
            collisionsCountB = 0;
            collisionsCountC = 0;
        }
Beispiel #10
0
        public LevelHandler(App 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.Projection = ProjectionMode.Orthographic;

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

            // 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.OnAttach(new ActorInstantiationDetails {
                        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;
            }
            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);

                targetPlayer.AttachToHud(hud);
            }

            // 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;

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