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); } } } }
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); } } } }