Exemple #1
0
        /// <summary>
        /// Peforms a physics tick
        /// </summary>
        /// <param name="worldPlayer">The player</param>
        private void Tick(WorldPlayer worldPlayer)
        {
            int cx = ((int)(worldPlayer.X + 8) >> 4);
            int cy = ((int)(worldPlayer.Y + 8) >> 4);

            worldPlayer.m_current = (int)World[cx, cy, Layer.Foreground].ID;
            if (worldPlayer.Current == (BlockID)4 || IsClimbable(worldPlayer.Current))
            {
                worldPlayer.m_delayed  = worldPlayer.m_queue[1];
                worldPlayer.m_queue[0] = worldPlayer.m_current;
            }
            else
            {
                worldPlayer.m_delayed  = worldPlayer.m_queue[0];
                worldPlayer.m_queue[0] = worldPlayer.m_queue[1];
            }

            worldPlayer.m_queue[1] = worldPlayer.m_current;

            if (worldPlayer.IsDead)
            {
                worldPlayer.Horizontal = 0;
                worldPlayer.Vertical   = 0;
            }

            bool isGodMode = worldPlayer.IsGod();

            if (isGodMode)
            {
                worldPlayer.m_morx = 0;
                worldPlayer.m_mory = 0;
                worldPlayer.m_mox  = 0;
                worldPlayer.m_moy  = 0;
            }
            else
            {
                switch (worldPlayer.Current)
                {
                case BlockID.GravityLeft:
                case BlockID.InvisibleGravityLeft:
                    worldPlayer.m_morx = -Gravity;
                    worldPlayer.m_mory = 0;
                    break;

                case BlockID.GravityUp:
                case BlockID.InvisibleGravityUp:
                    worldPlayer.m_morx = 0;
                    worldPlayer.m_mory = -Gravity;
                    break;

                case BlockID.GravityRight:
                case BlockID.InvisibleGravityRight:
                    worldPlayer.m_morx = Gravity;
                    worldPlayer.m_mory = 0;
                    break;

                case BlockID.BoostLeft:
                case BlockID.BoostRight:
                case BlockID.BoostUp:
                case BlockID.BoostDown:
                case BlockID.LadderNinja:
                case BlockID.LadderCastle:
                case BlockID.LadderJungleHorizontal:
                case BlockID.LadderJungleVertical:
                case BlockID.InvisibleGravityDot:
                case BlockID.GravityDot:
                    worldPlayer.m_morx = 0;
                    worldPlayer.m_mory = 0;
                    break;

                case BlockID.Water:
                    worldPlayer.m_morx = Gravity;
                    worldPlayer.m_mory = (int)WaterBuoyancy;
                    break;

                case BlockID.Mud:
                    worldPlayer.m_morx = Gravity;
                    worldPlayer.m_mory = (int)MudBuoyancy;
                    break;

                case BlockID.HazardFire:
                case BlockID.HazardSpike:
                    if (!worldPlayer.IsDead && !worldPlayer.HasProtection)
                    {
                        worldPlayer.KillPlayerInternal();
                    }
                    break;

                default:
                    worldPlayer.m_morx = 0;
                    worldPlayer.m_mory = Gravity;
                    break;
                }

                switch ((BlockID)worldPlayer.m_delayed)
                {
                case BlockID.GravityLeft:
                case BlockID.InvisibleGravityLeft:
                    worldPlayer.m_mox = -Gravity;
                    worldPlayer.m_moy = 0;
                    break;

                case BlockID.GravityUp:
                case BlockID.InvisibleGravityUp:
                    worldPlayer.m_mox = 0;
                    worldPlayer.m_moy = -Gravity;
                    break;

                case BlockID.GravityRight:
                case BlockID.InvisibleGravityRight:
                    worldPlayer.m_mox = Gravity;
                    worldPlayer.m_moy = 0;
                    break;

                case BlockID.BoostLeft:
                case BlockID.BoostRight:
                case BlockID.BoostUp:
                case BlockID.BoostDown:
                case BlockID.LadderNinja:
                case BlockID.LadderCastle:
                case BlockID.LadderJungleHorizontal:
                case BlockID.LadderJungleVertical:
                case BlockID.InvisibleGravityDot:
                case BlockID.GravityDot:
                    worldPlayer.m_mox = 0;
                    worldPlayer.m_moy = 0;
                    break;

                case BlockID.Water:
                    worldPlayer.m_mox = Gravity;
                    worldPlayer.m_moy = (int)WaterBuoyancy;
                    break;

                case BlockID.Mud:
                    worldPlayer.m_mox = Gravity;
                    worldPlayer.m_moy = (int)MudBuoyancy;
                    break;

                default:
                    worldPlayer.m_mox = 0;
                    worldPlayer.m_moy = Gravity;
                    break;
                }
            }

            if (worldPlayer.m_moy == WaterBuoyancy || worldPlayer.m_moy == MudBuoyancy)
            {
                worldPlayer.m_mx = worldPlayer.Horizontal;
                worldPlayer.m_my = worldPlayer.Vertical;
            }
            else if (worldPlayer.m_moy != 0)
            {
                worldPlayer.m_mx = worldPlayer.Horizontal;
                worldPlayer.m_my = 0;
            }
            else if (worldPlayer.m_mox != 0)
            {
                worldPlayer.m_mx = 0;
                worldPlayer.m_my = worldPlayer.Vertical;
            }
            else
            {
                worldPlayer.m_mx = worldPlayer.Horizontal;
                worldPlayer.m_my = worldPlayer.Vertical;
            }

            worldPlayer.m_mx  *= worldPlayer.SpeedMultiplier;
            worldPlayer.m_my  *= worldPlayer.SpeedMultiplier;
            worldPlayer.m_mox *= World.Gravity;
            worldPlayer.m_moy *= World.Gravity;

            worldPlayer.ModifierX = worldPlayer.m_mox + worldPlayer.m_mx;
            worldPlayer.ModifierY = worldPlayer.m_moy + worldPlayer.m_my;

            if (!ApproachingZero(worldPlayer.m_speedX) || worldPlayer.m_modifierX != 0)
            {
                worldPlayer.m_speedX += worldPlayer.m_modifierX;
                worldPlayer.m_speedX *= BaseDrag;
                if ((worldPlayer.m_mx == 0 && worldPlayer.m_moy != 0) ||
                    (worldPlayer.m_speedX < 0 && worldPlayer.m_mx > 0) ||
                    (worldPlayer.m_speedX > 0 && worldPlayer.m_mx < 0) ||
                    (IsClimbable(worldPlayer.Current) && !isGodMode))
                {
                    worldPlayer.m_speedX *= NoModifierDrag;
                }
                else if (worldPlayer.Current == BlockID.Water && !isGodMode)
                {
                    worldPlayer.m_speedX *= WaterDrag;
                }
                else if (worldPlayer.Current == BlockID.Mud && !isGodMode)
                {
                    worldPlayer.m_speedX *= MudDrag;
                }

                if (worldPlayer.m_speedX > 16)
                {
                    worldPlayer.m_speedX = 16;
                }
                else if (worldPlayer.m_speedX < -16)
                {
                    worldPlayer.m_speedX = -16;
                }
                else if (worldPlayer.m_speedX < 0.0001 && worldPlayer.m_speedX > -0.0001)
                {
                    worldPlayer.m_speedX = 0;
                }
            }
            if (!ApproachingZero(worldPlayer.m_speedY) || worldPlayer.m_modifierY != 0)
            {
                worldPlayer.m_speedY += worldPlayer.m_modifierY;
                worldPlayer.m_speedY *= BaseDrag;
                if ((worldPlayer.m_my == 0 && worldPlayer.m_mox != 0) ||
                    (worldPlayer.m_speedY < 0 && worldPlayer.m_my > 0) ||
                    (worldPlayer.m_speedY > 0 && worldPlayer.m_my < 0) ||
                    (IsClimbable(worldPlayer.Current) && !isGodMode))
                {
                    worldPlayer.m_speedY *= NoModifierDrag;
                }
                else if (worldPlayer.Current == BlockID.Water && !isGodMode)
                {
                    worldPlayer.m_speedY *= WaterDrag;
                }
                else if (worldPlayer.Current == BlockID.Mud && !isGodMode)
                {
                    worldPlayer.m_speedY *= MudDrag;
                }

                if (worldPlayer.m_speedY > 16)
                {
                    worldPlayer.m_speedY = 16;
                }
                else if (worldPlayer.m_speedY < -16)
                {
                    worldPlayer.m_speedY = -16;
                }
                else if (worldPlayer.m_speedY < 0.0001 && worldPlayer.m_speedY > -0.0001)
                {
                    worldPlayer.m_speedY = 0;
                }
            }
            if (!isGodMode)
            {
                switch (worldPlayer.Current)
                {
                case BlockID.BoostLeft:
                    worldPlayer.m_speedX = -Boost;
                    break;

                case BlockID.BoostRight:
                    worldPlayer.m_speedX = Boost;
                    break;

                case BlockID.BoostUp:
                    worldPlayer.m_speedY = -Boost;
                    break;

                case BlockID.BoostDown:
                    worldPlayer.m_speedY = Boost;
                    break;
                }
            }

            double remainderX = worldPlayer.X % 1;
            double currentSX  = worldPlayer.m_speedX;
            double remainderY = worldPlayer.Y % 1;
            double currentSY  = worldPlayer.m_speedY;

            worldPlayer.m_donex = false;
            worldPlayer.m_doney = false;

            while ((currentSX != 0 && !worldPlayer.m_donex) || (currentSY != 0 && !worldPlayer.m_doney))
            {
                ProcessPortals(worldPlayer, ref remainderX, ref currentSX, ref remainderY, ref currentSY);

                StepX(worldPlayer, ref remainderX, ref currentSX, ref remainderY, ref currentSY);
                StepY(worldPlayer, ref remainderX, ref currentSX, ref remainderY, ref currentSY);
            }

            if (!worldPlayer.IsDead)
            {
                if (worldPlayer.SpaceDown)
                {
                    if (worldPlayer.HasLevitation)
                    {
                        worldPlayer.m_isThrusting   = true;
                        worldPlayer.m_currentThrust = MaxThrust;
                    }
                }
                else if (worldPlayer.HasLevitation)
                {
                    worldPlayer.m_isThrusting = false;
                }

                switch (worldPlayer.Current)
                {
                case BlockID.CoinGold:
                    lock (worldPlayer.CollectedGoldCoins)
                    {
                        bool alreadyCollected = false;
                        for (int i = 0; i < worldPlayer.CollectedGoldCoins.Count; i++)
                        {
                            if (worldPlayer.CollectedGoldCoins[i].X == cx &&
                                worldPlayer.CollectedGoldCoins[i].Y == cy)
                            {
                                alreadyCollected = true;
                                break;
                            }
                        }

                        if (!alreadyCollected)
                        {
                            worldPlayer.CollectedGoldCoins.Add(World[cx, cy, Layer.Foreground]);
                        }
                    }
                    break;

                case BlockID.CoinBlue:
                    lock (worldPlayer.CollectedBlueCoins)
                    {
                        bool alreadyCollected = false;
                        for (int i = 0; i < worldPlayer.CollectedBlueCoins.Count; i++)
                        {
                            if (worldPlayer.CollectedBlueCoins[i].X == cx &&
                                worldPlayer.CollectedBlueCoins[i].Y == cy)
                            {
                                alreadyCollected = true;
                                break;
                            }
                        }

                        if (!alreadyCollected)
                        {
                            worldPlayer.CollectedBlueCoins.Add(World[cx, cy, Layer.Foreground]);
                        }
                    }
                    break;
                }

                if (worldPlayer.m_pastx != cx || worldPlayer.m_pasty != cy)
                {
                    switch (worldPlayer.Current)
                    {
                    case BlockID.SwitchPurple:
                        if (World[cx, cy, Layer.Foreground] is PurpleBlock)
                        {
                            PurpleBlock block = (PurpleBlock)World[cx, cy, Layer.Foreground];
                            worldPlayer.m_switches[block.SwitchID] = !worldPlayer.m_switches[block.SwitchID];
                        }
                        break;

                    case BlockID.ToolCheckpoint:
                        if (!isGodMode)
                        {
                            worldPlayer.LastCheckpoint = World[cx, cy, Layer.Foreground];
                        }
                        break;
                    }

                    worldPlayer.m_pastx = cx;
                    worldPlayer.m_pasty = cy;
                }

                if (worldPlayer.HasLevitation)
                {
                    UpdateThrust(worldPlayer);
                }
            }

            var imx = ((int)worldPlayer.m_speedX << 8);
            var imy = ((int)worldPlayer.m_speedY << 8);

            if (worldPlayer.Current != BlockID.Water && worldPlayer.Current != BlockID.Mud)
            {
                if (imx == 0)
                {
                    if (worldPlayer.m_modifierX < 0.1 && worldPlayer.m_modifierX > -0.1)
                    {
                        double tx = worldPlayer.X % 16;
                        if (tx < 2)
                        {
                            if (tx < 0.2)
                            {
                                worldPlayer.X = Math.Floor(worldPlayer.X);
                            }
                            else
                            {
                                worldPlayer.X -= tx / 15;
                            }
                        }
                        else
                        {
                            if (tx > 14)
                            {
                                if (tx > 15.8)
                                {
                                    worldPlayer.X = Math.Ceiling(worldPlayer.X);
                                }
                                else
                                {
                                    worldPlayer.X += (tx - 14) / 15;
                                }
                            }
                        }
                    }
                }

                if (imy == 0)
                {
                    if (worldPlayer.m_modifierY < 0.1 && worldPlayer.m_modifierY > -0.1)
                    {
                        double ty = worldPlayer.Y % 16;
                        if (ty < 2)
                        {
                            if (ty < 0.2)
                            {
                                worldPlayer.Y = Math.Floor(worldPlayer.Y);
                            }
                            else
                            {
                                worldPlayer.Y -= ty / 15;
                            }
                        }
                        else
                        {
                            if (ty > 14)
                            {
                                if (ty > 15.8)
                                {
                                    worldPlayer.Y = Math.Ceiling(worldPlayer.Y);
                                }
                                else
                                {
                                    worldPlayer.Y += (ty - 14) / 15;
                                }
                            }
                        }
                    }
                }
            }
        }