void BreakBlockEffect(object sender, BlockChangedEventArgs e) { if (e.Block != 0) { return; } Vector3I position = e.Coords; byte block = e.OldBlock; Vector3 startPos = new Vector3(position.X, position.Y, position.Z); int texLoc = game.BlockInfo.GetTextureLoc(block, Side.Left), texIndex = 0; TextureRec baseRec = game.TerrainAtlas1D.GetTexRec(texLoc, 1, out texIndex); float uScale = (1 / 16f), vScale = (1 / 16f) * game.TerrainAtlas1D.invElementSize; Vector3 minBB = game.BlockInfo.MinBB[block]; Vector3 maxBB = game.BlockInfo.MaxBB[block]; int minU = Math.Min((int)(minBB.X * 16), (int)(minBB.Z * 16)); int maxU = Math.Min((int)(maxBB.X * 16), (int)(maxBB.Z * 16)); int minV = (int)(16 - maxBB.Y * 16), maxV = (int)(16 - minBB.Y * 16); int maxUsedU = maxU, maxUsedV = maxV; // This way we can avoid creating particles which outside the bounds and need to be clamped if (minU < 12 && maxU > 12) { maxUsedU = 12; } if (minV < 12 && maxV > 12) { maxUsedV = 12; } for (int i = 0; i < 30; i++) { double velX = rnd.NextDouble() * 0.8 - 0.4; // [-0.4, 0.4] double velZ = rnd.NextDouble() * 0.8 - 0.4; double velY = rnd.NextDouble() + 0.2; Vector3 velocity = new Vector3((float)velX, (float)velY, (float)velZ); double xOffset = rnd.NextDouble() - 0.5; // [-0.5, 0.5] double yOffset = (rnd.NextDouble() - 0.125) * maxBB.Y; double zOffset = rnd.NextDouble() - 0.5; Vector3 pos = startPos + new Vector3(0.5f + (float)xOffset, (float)yOffset, 0.5f + (float)zOffset); TextureRec rec = baseRec; rec.U1 = baseRec.U1 + rnd.Next(minU, maxUsedU) * uScale; rec.V1 = baseRec.V1 + rnd.Next(minV, maxUsedV) * vScale; rec.U2 = Math.Min(baseRec.U1 + maxU * uScale, rec.U1 + 4 * uScale) - 0.01f * uScale; rec.V2 = Math.Min(baseRec.V1 + maxV * vScale, rec.V1 + 4 * vScale) - 0.01f * vScale; double life = 0.3 + rnd.NextDouble() * 0.7; TerrainParticle p = AddParticle(terrainParticles, ref terrainCount, false); p.ResetState(pos, velocity, life); p.rec = rec; p.texLoc = texLoc; } }
void RemoveTerrainAt(int index) { TerrainParticle removed = terrainParticles[index]; for (int i = index; i < terrainCount - 1; i++) { terrainParticles[i] = terrainParticles[i + 1]; } terrainParticles[terrainCount - 1] = removed; terrainCount--; }
public void BreakBlockEffect(Vector3I position, byte block) { Vector3 startPos = new Vector3(position.X, position.Y, position.Z); int texLoc = game.BlockInfo.GetTextureLoc(block, TileSide.Left); TextureRec baseRec = game.TerrainAtlas.GetTexRec(texLoc); const float uvScale = (1 / 16f) * TerrainAtlas2D.invElementSize; const float elemSize = 4 * uvScale; Vector3 minBB = game.BlockInfo.MinBB[block]; Vector3 maxBB = game.BlockInfo.MaxBB[block]; int minU = Math.Min((int)(minBB.X * 16), (int)(minBB.Z * 16)); int maxU = Math.Min((int)(maxBB.X * 16), (int)(maxBB.Z * 16)); int minV = (int)(16 - maxBB.Y * 16), maxV = (int)(16 - minBB.Y * 16); // This way we can avoid creating particles which outside the bounds and need to be clamped if (minU < 13 && maxU > 13) { maxU = 13; } if (minV < 13 && maxV > 13) { maxV = 13; } for (int i = 0; i < 30; i++) { double velX = rnd.NextDouble() * 0.8 - 0.4; // [-0.4, 0.4] double velZ = rnd.NextDouble() * 0.8 - 0.4; double velY = rnd.NextDouble() + 0.2; Vector3 velocity = new Vector3((float)velX, (float)velY, (float)velZ); double xOffset = rnd.NextDouble() - 0.5; // [-0.5, 0.5] double yOffset = (rnd.NextDouble() - 0.125) * maxBB.Y; double zOffset = rnd.NextDouble() - 0.5; Vector3 pos = startPos + new Vector3(0.5f + (float)xOffset, (float)yOffset, 0.5f + (float)zOffset); TextureRec rec = baseRec; rec.U1 = baseRec.U1 + rnd.Next(minU, maxU) * uvScale; rec.V1 = baseRec.V1 + rnd.Next(minV, maxV) * uvScale; rec.U2 = Math.Min(baseRec.U1 + maxU * uvScale, rec.U1 + elemSize); rec.V2 = Math.Min(baseRec.V1 + maxV * uvScale, rec.V1 + elemSize); double life = 0.3 + rnd.NextDouble() * 0.7; TerrainParticle p = AddParticle(terrainParticles, ref terrainCount, false); p.ResetState(pos, velocity, life); p.rec = rec; } }
TerrainParticle GetTerrainParticle() { if (terrainCount == maxParticles) { RemoveTerrainAt(0); } terrainCount++; TerrainParticle particle = terrainParticles[terrainCount - 1]; if (particle != null) { return(particle); } particle = new TerrainParticle(); terrainParticles[terrainCount - 1] = particle; return(particle); }
void BreakBlockEffect(object sender, BlockChangedEventArgs e) { if (e.Block != 0) { return; } Vector3I position = e.Coords; BlockID block = e.OldBlock; Vector3 worldPos = new Vector3(position.X, position.Y, position.Z); int texLoc = game.BlockInfo.GetTextureLoc(block, Side.Left), texIndex = 0; TextureRec baseRec = game.TerrainAtlas1D.GetTexRec(texLoc, 1, out texIndex); float uScale = (1 / 16f), vScale = (1 / 16f) * game.TerrainAtlas1D.invElementSize; Vector3 minBB = game.BlockInfo.MinBB[block]; Vector3 maxBB = game.BlockInfo.MaxBB[block]; int minU = Math.Min((int)(minBB.X * 16), (int)(minBB.Z * 16)); int maxU = Math.Min((int)(maxBB.X * 16), (int)(maxBB.Z * 16)); int minV = (int)(16 - maxBB.Y * 16), maxV = (int)(16 - minBB.Y * 16); int maxUsedU = maxU, maxUsedV = maxV; // This way we can avoid creating particles which outside the bounds and need to be clamped if (minU < 12 && maxU > 12) { maxUsedU = 12; } if (minV < 12 && maxV > 12) { maxUsedV = 12; } const int gridSize = 4; // gridOffset gives the centre of the cell on a grid const float cellCentre = (1f / gridSize) * 0.5f; for (int x = 0; x < gridSize; x++) { for (int y = 0; y < gridSize; y++) { for (int z = 0; z < gridSize; z++) { float cellX = (float)x / gridSize, cellY = (float)y / gridSize, cellZ = (float)z / gridSize; Vector3 cell = new Vector3(cellCentre + cellX, cellCentre / 2 + cellY, cellCentre + cellZ); if (cell.X < minBB.X || cell.X > maxBB.X || cell.Y < minBB.Y || cell.Y > maxBB.Y || cell.Z < minBB.Z || cell.Z > maxBB.Z) { continue; } double velX = cellCentre + (cellX - 0.5f) + (rnd.NextDouble() * 0.4 - 0.2); // centre random offset around [-0.2, 0.2] double velY = cellCentre + (cellY - 0.0f) + (rnd.NextDouble() * 0.4 - 0.2); double velZ = cellCentre + (cellZ - 0.5f) + (rnd.NextDouble() * 0.4 - 0.2); Vector3 velocity = new Vector3((float)velX, (float)velY, (float)velZ); TextureRec rec = baseRec; rec.U1 = baseRec.U1 + rnd.Next(minU, maxUsedU) * uScale; rec.V1 = baseRec.V1 + rnd.Next(minV, maxUsedV) * vScale; rec.U2 = Math.Min(baseRec.U1 + maxU * uScale, rec.U1 + 4 * uScale) - 0.01f * uScale; rec.V2 = Math.Min(baseRec.V1 + maxV * vScale, rec.V1 + 4 * vScale) - 0.01f * vScale; double life = 0.3 + rnd.NextDouble() * 1.2; TerrainParticle p = AddParticle(terrainParticles, ref terrainCount, false); p.ResetState(worldPos + cell, velocity, life); p.rec = rec; p.texLoc = (byte)texLoc; p.block = block; } } } }
void BreakBlockEffect(Vector3I coords, BlockID old, BlockID now) { if (now != Block.Air || BlockInfo.Draw[old] == DrawType.Gas) { return; } Vector3 worldPos = new Vector3(coords.X, coords.Y, coords.Z); int texLoc = BlockInfo.GetTextureLoc(old, Side.Left), texIndex = 0; TextureRec baseRec = Atlas1D.GetTexRec(texLoc, 1, out texIndex); float uScale = (1 / 16f), vScale = (1 / 16f) * Atlas1D.invTileSize; Vector3 minBB = BlockInfo.MinBB[old]; Vector3 maxBB = BlockInfo.MaxBB[old]; int minU = Math.Min((int)(minBB.X * 16), (int)(minBB.Z * 16)); int maxU = Math.Min((int)(maxBB.X * 16), (int)(maxBB.Z * 16)); int minV = (int)(16 - maxBB.Y * 16), maxV = (int)(16 - minBB.Y * 16); int maxUsedU = maxU, maxUsedV = maxV; // This way we can avoid creating particles which outside the bounds and need to be clamped if (minU < 12 && maxU > 12) { maxUsedU = 12; } if (minV < 12 && maxV > 12) { maxUsedV = 12; } const int gridSize = 4; // gridOffset gives the centre of the cell on a grid const float cellCentre = (1f / gridSize) * 0.5f; for (int x = 0; x < gridSize; x++) { for (int y = 0; y < gridSize; y++) { for (int z = 0; z < gridSize; z++) { float cellX = (float)x / gridSize, cellY = (float)y / gridSize, cellZ = (float)z / gridSize; Vector3 cell = new Vector3(cellCentre + cellX, cellCentre / 2 + cellY, cellCentre + cellZ); if (cell.X < minBB.X || cell.X > maxBB.X || cell.Y < minBB.Y || cell.Y > maxBB.Y || cell.Z < minBB.Z || cell.Z > maxBB.Z) { continue; } double velX = cellCentre + (cellX - 0.5f) + (rnd.NextDouble() * 0.4 - 0.2); // centre random offset around [-0.2, 0.2] double velY = cellCentre + (cellY - 0.0f) + (rnd.NextDouble() * 0.4 - 0.2); double velZ = cellCentre + (cellZ - 0.5f) + (rnd.NextDouble() * 0.4 - 0.2); Vector3 velocity = new Vector3((float)velX, (float)velY, (float)velZ); TextureRec rec = baseRec; rec.U1 = baseRec.U1 + rnd.Next(minU, maxUsedU) * uScale; rec.V1 = baseRec.V1 + rnd.Next(minV, maxUsedV) * vScale; rec.U2 = Math.Min(baseRec.U1 + maxU * uScale, rec.U1 + 4 * uScale) - 0.01f * uScale; rec.V2 = Math.Min(baseRec.V1 + maxV * vScale, rec.V1 + 4 * vScale) - 0.01f * vScale; double life = 0.3 + rnd.NextDouble() * 1.2; TerrainParticle p = GetTerrainParticle(); p.ResetState(worldPos + cell, velocity, life); p.rec = rec; p.texLoc = (TexLoc)texLoc; p.block = old; int type = rnd.Next(0, 30); p.Size = (byte)(type >= 28 ? 12 : (type >= 25 ? 10 : 8)); } } } }