Example #1
0
        public override void OnFixedUpdate(float timeMult)
        {
            base.OnFixedUpdate(timeMult);

            if (frozenTimeLeft > 0)
            {
                return;
            }

            if (canJump)
            {
                if (MathF.Abs(speedX) > float.Epsilon && !CanMoveToPosition(speedX * 4, 0))
                {
                    SetTransition(AnimState.TransitionWithdraw, false, delegate {
                        HandleTurn(true);
                    });
                    isTurning     = true;
                    canHurtPlayer = false;
                    speedX        = 0;
                    PlaySound("Withdraw", 0.4f);
                }
            }

            if (!isTurning && !isWithdrawn && !isAttacking)
            {
                AABB aabb = AABBInner + new Vector2(speedX * 32, 0);
                if (levelHandler.TileMap.IsTileEmpty(ref aabb, true))
                {
                    foreach (Player player in levelHandler.GetCollidingPlayers(aabb + new Vector2(speedX * 32, 0)))
                    {
                        if (!player.IsInvulnerable)
                        {
                            Attack();
                            break;
                        }
                    }
                }
            }
        }
Example #2
0
        private void DrawLayer(IDrawDevice device, ref TileMapLayer layer, int cacheIndex)
        {
            if (!layer.Visible)
            {
                return;
            }

            Vector2 viewSize   = device.TargetSize;
            Vector3 viewCenter = device.ViewerPos;

            Point2  tileCount = new Point2(layer.LayoutWidth, layer.Layout.Length / layer.LayoutWidth);
            Vector2 tileSize  = new Vector2(tileset.TileSize, tileset.TileSize);

            // Update offsets for moving layers
            if (MathF.Abs(layer.AutoSpeedX) > 0)
            {
                layer.OffsetX += layer.AutoSpeedX * Time.TimeMult;
                if (layer.RepeatX)
                {
                    if (layer.AutoSpeedX > 0)
                    {
                        while (layer.OffsetX > (tileCount.X * 32))
                        {
                            layer.OffsetX -= (tileCount.X * 32);
                        }
                    }
                    else
                    {
                        while (layer.OffsetX < 0)
                        {
                            layer.OffsetX += (tileCount.X * 32);
                        }
                    }
                }
            }
            if (MathF.Abs(layer.AutoSpeedY) > 0)
            {
                layer.OffsetY += layer.AutoSpeedY * Time.TimeMult;
                if (layer.RepeatY)
                {
                    if (layer.AutoSpeedY > 0)
                    {
                        while (layer.OffsetY > (tileCount.Y * 32))
                        {
                            layer.OffsetY -= (tileCount.Y * 32);
                        }
                    }
                    else
                    {
                        while (layer.OffsetY < 0)
                        {
                            layer.OffsetY += (tileCount.Y * 32);
                        }
                    }
                }
            }

            // Get current layer offsets and speeds
            float loX = layer.OffsetX;
            float loY = layer.OffsetY - (layer.UseInherentOffset ? (viewSize.Y - 200) / 2 : 0);

            // Find out coordinates for a tile from outside the boundaries from topleft corner of the screen
            float x1 = viewCenter.X - 70 - (viewSize.X * 0.5f);
            float y1 = viewCenter.Y - 70 - (viewSize.Y * 0.5f);

            if (layer.BackgroundStyle != BackgroundStyle.Plain && tileCount.Y == 8 && tileCount.X == 8)
            {
                const float PerspectiveSpeedX = 0.4f;
                const float PerspectiveSpeedY = 0.16f;
                RenderTexturedBackground(device, ref layer, cacheIndex,
                                         (x1 * PerspectiveSpeedX + loX),
                                         (y1 * PerspectiveSpeedY + loY));
            }
            else
            {
                // Figure out the floating point offset from the calculated coordinates and the actual tile
                // corner coordinates
                float xt = TranslateCoordinate(x1, layer.SpeedX, loX, false, viewSize.Y, viewSize.X);
                float yt = TranslateCoordinate(y1, layer.SpeedY, loY, true, viewSize.Y, viewSize.X);

                float remX = xt % 32f;
                float remY = yt % 32f;

                // Calculate the index (on the layer map) of the first tile that needs to be drawn to the
                // position determined earlier
                int tileX, tileY, tileAbsX, tileAbsY;

                // Get the actual tile coords on the layer layout
                if (xt > 0)
                {
                    tileAbsX = (int)Math.Floor(xt / 32f);
                    tileX    = tileAbsX % tileCount.X;
                }
                else
                {
                    tileAbsX = (int)Math.Ceiling(xt / 32f);
                    tileX    = tileAbsX % tileCount.X;
                    while (tileX < 0)
                    {
                        tileX += tileCount.X;
                    }
                }

                if (yt > 0)
                {
                    tileAbsY = (int)Math.Floor(yt / 32f);
                    tileY    = tileAbsY % tileCount.Y;
                }
                else
                {
                    tileAbsY = (int)Math.Ceiling(yt / 32f);
                    tileY    = tileAbsY % tileCount.Y;
                    while (tileY < 0)
                    {
                        tileY += tileCount.Y;
                    }
                }

                // update x1 and y1 with the remainder so that we start at the tile boundary
                // minus 1 because indices are updated in the beginning of the loops
                x1 -= remX - 32f;
                y1 -= remY - 32f;

                // Save the tile Y at the left border so that we can roll back to it at the start of
                // every row iteration
                int tileYs = tileY;

                // Calculate the last coordinates we want to draw to
                float x3 = x1 + 100 + viewSize.X;
                float y3 = y1 + 100 + viewSize.Y;

                Material  material  = null;
                Texture   texture   = null;
                ColorRgba mainColor = ColorRgba.White;

                // Reserve the required space for vertex data in our locally cached buffer
                int neededVertices = (int)((((x3 - x1) / 32) + 1) * (((y3 - y1) / 32) + 1) * 4);
                if (cachedVertices == null || cachedVertices.Length < neededVertices)
                {
                    cachedVertices = new VertexC1P3T2[neededVertices];
                }

                int vertexIndex = 0;

                int tile_xo = -1;
                for (float x2 = x1; x2 < x3; x2 += 32)
                {
                    tileX = (tileX + 1) % tileCount.X;
                    tile_xo++;
                    if (!layer.RepeatX)
                    {
                        // If the current tile isn't in the first iteration of the layer horizontally, don't draw this column
                        if (tileAbsX + tile_xo + 1 < 0 || tileAbsX + tile_xo + 1 >= tileCount.X)
                        {
                            continue;
                        }
                    }
                    tileY = tileYs;
                    int tile_yo = -1;
                    for (float y2 = y1; y2 < y3; y2 += 32)
                    {
                        tileY = (tileY + 1) % tileCount.Y;
                        tile_yo++;

                        LayerTile tile = layer.Layout[tileX + tileY * layer.LayoutWidth];

                        if (!layer.RepeatY)
                        {
                            // If the current tile isn't in the first iteration of the layer vertically, don't draw it
                            if (tileAbsY + tile_yo + 1 < 0 || tileAbsY + tile_yo + 1 >= tileCount.Y)
                            {
                                continue;
                            }
                        }

                        Point2 offset;
                        bool   isFlippedX, isFlippedY;
                        if (tile.IsAnimated)
                        {
                            if (tile.TileID < animatedTiles.Count)
                            {
                                offset     = animatedTiles[tile.TileID].CurrentTile.MaterialOffset;
                                isFlippedX = (animatedTiles[tile.TileID].CurrentTile.IsFlippedX != tile.IsFlippedX);
                                isFlippedY = (animatedTiles[tile.TileID].CurrentTile.IsFlippedY != tile.IsFlippedY);

                                //mainColor.A = tile.MaterialAlpha;
                                mainColor.A = animatedTiles[tile.TileID].CurrentTile.MaterialAlpha;
                            }
                            else
                            {
                                continue;
                            }
                        }
                        else
                        {
                            offset     = tile.MaterialOffset;
                            isFlippedX = tile.IsFlippedX;
                            isFlippedY = tile.IsFlippedY;

                            mainColor.A = tile.MaterialAlpha;
                        }

                        if (material != tile.Material)
                        {
                            // Submit all the vertices as one draw batch
                            device.AddVertices(
                                material,
                                VertexMode.Quads,
                                cachedVertices,
                                0,
                                vertexIndex);

                            vertexIndex = 0;

                            material = tile.Material.Res;
                            texture  = material.MainTexture.Res;
                        }

                        Rect uvRect = new Rect(
                            offset.X * texture.UVRatio.X / texture.ContentWidth,
                            offset.Y * texture.UVRatio.Y / texture.ContentHeight,
                            tileset.TileSize * texture.UVRatio.X / texture.ContentWidth,
                            tileset.TileSize * texture.UVRatio.Y / texture.ContentHeight
                            );

                        // ToDo: Flip normal map somehow
                        if (isFlippedX)
                        {
                            uvRect.X += uvRect.W;
                            uvRect.W *= -1;
                        }
                        if (isFlippedY)
                        {
                            uvRect.Y += uvRect.H;
                            uvRect.H *= -1;
                        }

                        Vector3 renderPos = new Vector3(x2, y2, layer.Depth);

                        renderPos.X = MathF.Round(renderPos.X);
                        renderPos.Y = MathF.Round(renderPos.Y);
                        if (MathF.RoundToInt(device.TargetSize.X) != (MathF.RoundToInt(device.TargetSize.X) / 2) * 2)
                        {
                            renderPos.X += 0.5f;
                        }
                        if (MathF.RoundToInt(device.TargetSize.Y) != (MathF.RoundToInt(device.TargetSize.Y) / 2) * 2)
                        {
                            renderPos.Y += 0.5f;
                        }

                        cachedVertices[vertexIndex + 0].Pos.X      = renderPos.X;
                        cachedVertices[vertexIndex + 0].Pos.Y      = renderPos.Y;
                        cachedVertices[vertexIndex + 0].Pos.Z      = renderPos.Z;
                        cachedVertices[vertexIndex + 0].TexCoord.X = uvRect.X;
                        cachedVertices[vertexIndex + 0].TexCoord.Y = uvRect.Y;
                        cachedVertices[vertexIndex + 0].Color      = mainColor;

                        cachedVertices[vertexIndex + 1].Pos.X      = renderPos.X;
                        cachedVertices[vertexIndex + 1].Pos.Y      = renderPos.Y + tileSize.Y;
                        cachedVertices[vertexIndex + 1].Pos.Z      = renderPos.Z;
                        cachedVertices[vertexIndex + 1].TexCoord.X = uvRect.X;
                        cachedVertices[vertexIndex + 1].TexCoord.Y = uvRect.Y + uvRect.H;
                        cachedVertices[vertexIndex + 1].Color      = mainColor;

                        cachedVertices[vertexIndex + 2].Pos.X      = renderPos.X + tileSize.X;
                        cachedVertices[vertexIndex + 2].Pos.Y      = renderPos.Y + tileSize.Y;
                        cachedVertices[vertexIndex + 2].Pos.Z      = renderPos.Z;
                        cachedVertices[vertexIndex + 2].TexCoord.X = uvRect.X + uvRect.W;
                        cachedVertices[vertexIndex + 2].TexCoord.Y = uvRect.Y + uvRect.H;
                        cachedVertices[vertexIndex + 2].Color      = mainColor;

                        cachedVertices[vertexIndex + 3].Pos.X      = renderPos.X + tileSize.X;
                        cachedVertices[vertexIndex + 3].Pos.Y      = renderPos.Y;
                        cachedVertices[vertexIndex + 3].Pos.Z      = renderPos.Z;
                        cachedVertices[vertexIndex + 3].TexCoord.X = uvRect.X + uvRect.W;
                        cachedVertices[vertexIndex + 3].TexCoord.Y = uvRect.Y;
                        cachedVertices[vertexIndex + 3].Color      = mainColor;

                        vertexIndex += 4;
                    }
                }

                // Submit all the vertices as one draw batch
                device.AddVertices(
                    material,
                    VertexMode.Quads,
                    cachedVertices,
                    0,
                    vertexIndex);
            }
        }
Example #3
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;
        }