public void PlaceSprites(Level level, int amount)
        {
            spriteGrid = new List <BackgroundSprite> [
                (int)Math.Ceiling(level.Size.X / GridSize),
                (int)Math.Ceiling((level.Size.Y - level.BottomPos) / GridSize)];

            sprites = new List <BackgroundSprite>();

            for (int i = 0; i < amount; i++)
            {
                BackgroundSpritePrefab prefab = GetRandomPrefab(level.GenerationParams.Name);
                GraphEdge selectedEdge        = null;
                Vector2   edgeNormal          = Vector2.One;
                Vector2?  pos = FindSpritePosition(level, prefab, out selectedEdge, out edgeNormal);

                if (pos == null)
                {
                    continue;
                }

                float rotation = 0.0f;
                if (prefab.AlignWithSurface)
                {
                    rotation = MathUtils.VectorToAngle(new Vector2(edgeNormal.Y, edgeNormal.X));
                }

                rotation += Rand.Range(prefab.RandomRotation.X, prefab.RandomRotation.Y, Rand.RandSync.Server);

                var newSprite = new BackgroundSprite(prefab,
                                                     new Vector3((Vector2)pos, Rand.Range(prefab.DepthRange.X, prefab.DepthRange.Y, Rand.RandSync.Server)), Rand.Range(prefab.Scale.X, prefab.Scale.Y, Rand.RandSync.Server), rotation);

                //calculate the positions of the corners of the rotated sprite
                Vector2 halfSize      = newSprite.Prefab.Sprite.size * newSprite.Scale / 2;
                var     spriteCorners = new List <Vector2>
                {
                    -halfSize, new Vector2(-halfSize.X, halfSize.Y),
                    halfSize, new Vector2(halfSize.X, -halfSize.Y)
                };

                Vector2 pivotOffset = newSprite.Prefab.Sprite.Origin * newSprite.Scale - halfSize;
                pivotOffset.X = -pivotOffset.X;
                pivotOffset   = new Vector2(
                    (float)(pivotOffset.X * Math.Cos(-rotation) - pivotOffset.Y * Math.Sin(-rotation)),
                    (float)(pivotOffset.X * Math.Sin(-rotation) + pivotOffset.Y * Math.Cos(-rotation)));

                for (int j = 0; j < 4; j++)
                {
                    spriteCorners[j] = new Vector2(
                        (float)(spriteCorners[j].X * Math.Cos(-rotation) - spriteCorners[j].Y * Math.Sin(-rotation)),
                        (float)(spriteCorners[j].X * Math.Sin(-rotation) + spriteCorners[j].Y * Math.Cos(-rotation)));

                    spriteCorners[j] += pos.Value + pivotOffset;
                }

                float minX = spriteCorners.Min(c => c.X) - newSprite.Position.Z;
                float maxX = spriteCorners.Max(c => c.X) + newSprite.Position.Z;

                float minY = spriteCorners.Min(c => c.Y) - newSprite.Position.Z - level.BottomPos;
                float maxY = spriteCorners.Max(c => c.Y) + newSprite.Position.Z - level.BottomPos;

#if CLIENT
                if (newSprite.ParticleEmitters != null)
                {
                    foreach (ParticleEmitter emitter in newSprite.ParticleEmitters)
                    {
                        Rectangle particleBounds = emitter.CalculateParticleBounds(pos.Value);
                        minX = Math.Min(minX, particleBounds.X);
                        maxX = Math.Max(maxX, particleBounds.Right);
                        minY = Math.Min(minY, particleBounds.Y - level.BottomPos);
                        maxY = Math.Max(maxY, particleBounds.Bottom - level.BottomPos);
                    }
                }
#endif

                sprites.Add(newSprite);

                int xStart = (int)Math.Floor(minX / GridSize);
                int xEnd   = (int)Math.Floor(maxX / GridSize);
                if (xEnd < 0 || xStart >= spriteGrid.GetLength(0))
                {
                    continue;
                }

                int yStart = (int)Math.Floor(minY / GridSize);
                int yEnd   = (int)Math.Floor(maxY / GridSize);
                if (yEnd < 0 || yStart >= spriteGrid.GetLength(1))
                {
                    continue;
                }

                xStart = Math.Max(xStart, 0);
                xEnd   = Math.Min(xEnd, spriteGrid.GetLength(0) - 1);
                yStart = Math.Max(yStart, 0);
                yEnd   = Math.Min(yEnd, spriteGrid.GetLength(1) - 1);

                for (int x = xStart; x <= xEnd; x++)
                {
                    for (int y = yStart; y <= yEnd; y++)
                    {
                        if (spriteGrid[x, y] == null)
                        {
                            spriteGrid[x, y] = new List <BackgroundSprite>();
                        }
                        spriteGrid[x, y].Add(newSprite);
                    }
                }
            }
        }
Пример #2
0
        public void PlaceSprites(Level level, int amount)
        {
            sprites = new List <BackgroundSprite> [
                (int)Math.Ceiling(level.Size.X / GridSize),
                (int)Math.Ceiling(level.Size.Y / GridSize)];

            for (int x = 0; x < sprites.GetLength(0); x++)
            {
                for (int y = 0; y < sprites.GetLength(1); y++)
                {
                    sprites[x, y] = new List <BackgroundSprite>();
                }
            }

            for (int i = 0; i < amount; i++)
            {
                BackgroundSpritePrefab prefab = GetRandomPrefab(level.GenerationParams.Name);
                GraphEdge selectedEdge        = null;
                Vector2   edgeNormal          = Vector2.One;
                Vector2?  pos = FindSpritePosition(level, prefab, out selectedEdge, out edgeNormal);

                if (pos == null)
                {
                    continue;
                }

                float rotation = 0.0f;
                if (prefab.AlignWithSurface)
                {
                    rotation = MathUtils.VectorToAngle(new Vector2(edgeNormal.Y, edgeNormal.X));
                }

                rotation += Rand.Range(prefab.RandomRotation.X, prefab.RandomRotation.Y, Rand.RandSync.ClientOnly);

                var newSprite = new BackgroundSprite(prefab,
                                                     new Vector3((Vector2)pos, Rand.Range(prefab.DepthRange.X, prefab.DepthRange.Y, Rand.RandSync.ClientOnly)), Rand.Range(prefab.Scale.X, prefab.Scale.Y, Rand.RandSync.ClientOnly), rotation);

                //calculate the positions of the corners of the rotated sprite
                Vector2 halfSize      = newSprite.Prefab.Sprite.size * newSprite.Scale / 2;
                var     spriteCorners = new Vector2[]
                {
                    -halfSize, new Vector2(-halfSize.X, halfSize.Y),
                    halfSize, new Vector2(halfSize.X, -halfSize.Y)
                };

                Vector2 pivotOffset = newSprite.Prefab.Sprite.Origin * newSprite.Scale - halfSize;
                pivotOffset.X = -pivotOffset.X;
                pivotOffset   = new Vector2(
                    (float)(pivotOffset.X * Math.Cos(-rotation) - pivotOffset.Y * Math.Sin(-rotation)),
                    (float)(pivotOffset.X * Math.Sin(-rotation) + pivotOffset.Y * Math.Cos(-rotation)));

                for (int j = 0; j < 4; j++)
                {
                    spriteCorners[j] = new Vector2(
                        (float)(spriteCorners[j].X * Math.Cos(-rotation) - spriteCorners[j].Y * Math.Sin(-rotation)),
                        (float)(spriteCorners[j].X * Math.Sin(-rotation) + spriteCorners[j].Y * Math.Cos(-rotation)));

                    spriteCorners[j] += (Vector2)pos + pivotOffset;
                }

                //newSprite.spriteCorners = spriteCorners;

                int minX = (int)Math.Floor((spriteCorners.Min(c => c.X) - newSprite.Position.Z) / GridSize);
                int maxX = (int)Math.Floor((spriteCorners.Max(c => c.X) + newSprite.Position.Z) / GridSize);
                if (minX < 0 || maxX >= sprites.GetLength(0))
                {
                    continue;
                }

                int minY = (int)Math.Floor((spriteCorners.Min(c => c.Y) - newSprite.Position.Z) / GridSize);
                int maxY = (int)Math.Floor((spriteCorners.Max(c => c.Y) + newSprite.Position.Z) / GridSize);
                if (minY < 0 || maxY >= sprites.GetLength(1))
                {
                    continue;
                }

                for (int x = minX; x <= maxX; x++)
                {
                    for (int y = minY; y <= maxY; y++)
                    {
                        sprites[x, y].Add(newSprite);
                    }
                }
            }
        }