void UpdateStaticCollisions() { for (int i = 0; i < currentParticleCount; i++) { WaterParticle particle = waterParticles[i]; if (math.lengthsq(particle.velocity) < 0.01) { continue; } float3 startPosition = particle.position; float3 nextPosition = particle.position + particle.velocity * Time.deltaTime; for (int j = 0; j < boxes.Length; j++) { if (boxes[j].TestCollision(startPosition, nextPosition, out float ratio, out float3 normal)) { particle.velocity = math.reflect(particle.velocity, normal) * elasticity; float3 dir = math.normalize(startPosition - nextPosition); particle.position = math.lerp(startPosition, nextPosition, ratio) + (dir * particleRadius); break; } } waterParticles[i] = particle; } }
void SimulateStartingKopa() { if (IsPlugged) { WaterPlug.GetComponent <KopaWaterplug>().enabled = true; WaterCopaClue.SetActive(true); WaterParticle.SetActive(false); if (WaterContainer.GetComponent <WaterContainerHeight>()) { WaterContainer.GetComponent <WaterContainerHeight>().AbsorbWater(timeToAbsorbWater); } } else { WaterPlug.GetComponent <KopaWaterplug>().enabled = false; WaterCopaClue.SetActive(false); WaterParticle.SetActive(true); if (WaterContainer.GetComponent <WaterContainerHeight>()) { WaterContainer.GetComponent <WaterContainerHeight>().FillWater(timeToFillWater); } particleStartSpeed = 7.5f; particleStartLifetime = 0.7f; AkSoundEngine.PostEvent("waterfall_loop", gameObject); StartCoroutine(stopSFX(timeToStopSFX)); } }
private void OnTapEvent(Vector3 position) { var worldPostion = _camera.ScreenToWorldPoint(position); worldPostion.z = 0; int particleCount = _waterParticles.Count; float distance = 9999999.0f; WaterParticle selected = null; for (int a = 0; a < _waterParticles.Count; ++a) { var pos = _waterParticles[a].Normal * _waterParticles[a].Position; pos.z = 0; float dist = Vector3.Distance(pos, worldPostion); if (dist < distance) { selected = _waterParticles[a]; distance = dist; } } if (selected != null) { selected.Velocity = _clickForce; } }
void UpdatePredictedPosition() { for (int i = 0; i < particles.Length; i++) { WaterParticle particle = particles[i]; particle.predictedPosition += particle.deltaPressure; } }
void UpdatePositions() { for (int i = 0; i < currentParticleCount; i++) { WaterParticle particle = waterParticles[i]; particle.position += particle.velocity * Time.deltaTime; waterParticles[i] = particle; } }
void UpdateVelocity() { for (int i = 0; i < currentParticleCount; i++) { WaterParticle particle = waterParticles[i]; particle.velocity += particle.acceleration * Time.deltaTime; waterParticles[i] = particle; } }
void UpdateAcceleration() { for (int i = 0; i < currentParticleCount; i++) { WaterParticle particle = waterParticles[i]; particle.acceleration += gravity * Time.deltaTime; waterParticles[i] = particle; } }
private void WaterParticleDestroyed(WaterParticle water) { if (GameController.Instance.raceOver) { return; } waterList.Remove(water); waterCountChange.Invoke(waterList.Count); }
void ApplyForcePredictPosition() { for (int i = 0; i < particles.Length; i++) { WaterParticle particle = particles[i]; particle.velocity += new float2(0, -9.81f) * Time.deltaTime; particle.predictedPosition += Time.deltaTime * particle.velocity; particles[i] = particle; } }
public WaterParticle[] UpdateParticle() { WaterParticle[] self = new WaterParticle[] { this }; if (!WithinOneZero(this.Position + Direction)) { Direction *= -1f; } this.Position += Direction; return(self); }
public void Execute(int index) { WaterParticle currentParticle = waterParticles[index]; currentParticle.velocity += deltaTime * currentParticle.force / currentParticle.density; float3 previousPosition = currentParticle.position; float3 nextPosition = currentParticle.position + deltaTime * currentParticle.velocity; //Might get corrected by collision currentParticle.position += deltaTime * currentParticle.velocity; GetAxisBound(ref currentParticle.position.x, ref currentParticle.velocity.x, boxSize.x); GetAxisBound(ref currentParticle.position.y, ref currentParticle.velocity.y, boxSize.y); GetAxisBound(ref currentParticle.position.z, ref currentParticle.velocity.z, boxSize.z); //const float BOUND_DAMPING = -.5f; //if (currentParticle.position.x - particleSize < 0.0f) //{ // currentParticle.velocity.x *= BOUND_DAMPING; // currentParticle.position.x = particleSize; //} //if (currentParticle.position.x + particleSize > boxSize.x) //{ // currentParticle.velocity.x *= BOUND_DAMPING; // currentParticle.position.x = boxSize.x - particleSize; //} //if (currentParticle.position.y - particleSize < 0.0f) //{ // currentParticle.velocity.y *= BOUND_DAMPING; // currentParticle.position.y = particleSize; //} //if (currentParticle.position.y + particleSize > boxSize.y) //{ // currentParticle.velocity.y *= BOUND_DAMPING; // currentParticle.position.y = boxSize.y - particleSize; //} ////bound checking //for (int i = 0; i < boxes.Length; i++) // if(boxes[i].TestCollision(previousPosition, nextPosition, out float ratio, out float3 normal)) // HandleCollision(ref currentParticle, previousPosition, nextPosition, ratio, normal); //for (int i = 0; i < spheres.Length; i++) // if (spheres[i].TestCollision(previousPosition, nextPosition, out float ratio, out float3 normal)) // HandleCollision(ref currentParticle, previousPosition, nextPosition, ratio, normal); //for (int i = 0; i < innerBoxes.Length; i++) // if (innerBoxes[i].TestCollision(previousPosition, nextPosition, out float ratio, out float3 normal)) // HandleCollision(ref currentParticle, previousPosition, nextPosition, ratio, normal); waterParticles[index] = currentParticle; }
//NOT WORKING public WaterParticle[] SubdevideParticles() { WaterParticle [] SubParticles = new WaterParticle[WaveSystem.SubdivitionCount]; for (int i = 0; i < WaveSystem.SubdivitionCount; i++) { SubParticles[i] = new WaterParticle(Position + Direction, Direction, DispersionAngle / WaveSystem.SubdivitionCount); } return(SubParticles); }
void UpdateVelocityVerocityViscosityUpdatePosition() { for (int i = 0; i < particles.Length; i++) { WaterParticle particle = particles[i]; particle.velocity = (1f / Time.deltaTime) * (particle.predictedPosition - particle.position); //apply vorcity confinement and XSPH viscosity particle.position = particle.predictedPosition; } }
public void GenerateInitialParticleData() { float anglePerSegment = 3.14165f * 2.0f / (float)_segmentCount; for (int a = 0; a < _segmentCount; ++a) { WaterParticle particle = new WaterParticle(); _waterParticles.Add(particle); particle.Normal = new Vector3(Mathf.Sin(anglePerSegment * a), Mathf.Cos(anglePerSegment * a), 0); particle.Position = _waterSize; particle.Velocity = 0.0f; } }
public void Execute(int index) { WaterParticle currentParticle = waterParticles[index]; currentParticle.density = 0; for (int i = 0; i < waterParticles.Length; i++) { WaterParticle otherParticle = waterParticles[i]; float3 diff = otherParticle.position - currentParticle.position; float sqrtDistance = math.lengthsq(diff); if (sqrtDistance < radiusSq) { //float x = radiusSq - sqrtDistance; currentParticle.density += mass * poly6 * math.pow(radiusSq - sqrtDistance, 3);//;x * x * x; } } //The ideal gas law, relating pressure to the summed density currentParticle.pressure = gazConst * (currentParticle.density - restDensity); waterParticles[index] = currentParticle; }
public void Execute(int index) { float3 forcePressure = 0; float3 forceViscosity = 0; WaterParticle currentParticle = waterParticles[index]; for (int i = 0; i < waterParticles.Length; i++) { if (i == index) { continue; } WaterParticle otherParticle = waterParticles[i]; float3 diff = otherParticle.position - currentParticle.position; float sqrtDistance = math.lengthsq(diff); if (sqrtDistance < radiusSq) { float distance = math.sqrt(sqrtDistance); float3 ratioDistance = radius - distance; // compute pressure force contribution float3 forcePressure1 = -math.normalize(diff) * mass; float3 forcePressure2 = (currentParticle.pressure + otherParticle.pressure) / (2 * otherParticle.density); forcePressure += forcePressure1 * forcePressure2 * spikyGrad * (ratioDistance * ratioDistance); // compute viscosity force contribution //float3 forceVisc1 = viscosity * mass; float3 forceVisc1 = viscosity * mass; float3 forceVisc2 = (otherParticle.velocity - currentParticle.velocity) / otherParticle.density; float3 forceVisc3 = viscosityKernel * ratioDistance; forceViscosity += forceVisc1 * forceVisc2 * forceVisc3; } } float3 forceGravity = gravity * currentParticle.density; currentParticle.force = forcePressure + forceViscosity + forceGravity; waterParticles[index] = currentParticle; }
private void InitParticles() { int length = size.x * size.y * size.z; waterParticles = new NativeArray <WaterParticle>(length, Allocator.Persistent); int i = 0; for (int x = 0; x < size.x; x++) { for (int y = 0; y < size.y; y++) { for (int z = 0; z < size.z; z++) { WaterParticle waterParticle = new WaterParticle(); waterParticle.position = startPos + spacing * new float3(x, y, z); waterParticles[i] = waterParticle; i++; } } } }
void CalculateLambda() { float POLY6 = 315f / (65f * math.PI * math.pow(particleRadius, 9f)); for (int i = 0; i < particles.Length; i++) { WaterParticle pi = particles[i]; for (int j = 0; j < particles.Length; j++) { WaterParticle pj = particles[i]; float2 diff = pj.position - pi.position; float distanceSq = math.lengthsq(diff); if (distanceSq < particleRadius * particleRadius) { float squaredRatio = particleRadius - distanceSq; pi.density += mass * POLY6 * squaredRatio * squaredRatio * squaredRatio; } } //particle.density = Sum_j -> mass_jj * Kernel(pi-pj, h); float constraint = (pi.density / restDensity) - 1; } }
void HandleCollision(ref WaterParticle currentParticle, float3 previousPosition, float3 nextPosition, float ratio, float3 normal) { currentParticle.velocity = math.reflect(currentParticle.velocity, normal) * collisionElasticity; currentParticle.position = previousPosition;//math.lerp(previousPosition, currentParticle.position, ratio) + (normal * particleSize * 1.1f); }
protected override void Spawn(Vector3 position) { WaterParticle waterParticle = WaterParticleManager.Instance.SpawnWaterParticle(position); waterParticle.RB.drag = 10f; }
private bool PerformFrameProxy(ProxyObject sourceobject, BCBlockGameState gamestate) { var pPaddle = gamestate.PlayerPaddle; if (pPaddle == null) return true; //"bleed" RectangleF paddlerect = pPaddle.Getrect(); for (int i = 0; i < (int) (20f*BCBlockGameState.ParticleGenerationFactor); i++) { //add a random blood particle... PointF randomspot = new PointF((float) (paddlerect.Width*BCBlockGameState.rgen.NextDouble() + paddlerect.Left), (float) (paddlerect.Bottom)); WaterParticle Bloodparticle = new WaterParticle(randomspot, Color.Red); Bloodparticle.Velocity = new PointF((float) BCBlockGameState.rgen.NextDouble()*2 - 1, (float) BCBlockGameState.rgen.NextDouble() - 0.5f); gamestate.Particles.Add(Bloodparticle); } return false; }
void Awake() { WaterPlug.GetComponent <KopaWaterplug>().enabled = true; WaterCopaClue.SetActive(true); WaterParticle.SetActive(false); }
void LateUpdate() { timeElapsed += Time.deltaTime; frameCount++; // Check for frame skip if (emit && timeElapsed >= emitTimeInterval && fo.waterLines.Count > 0f && foamTexCount > 0) { frameCount = 0; timeElapsed = 0; int emitted = 0; int triedToEmit = 0; if (emissionPriority == EmissionPriority.HighestVelocity || emissionPriority == EmissionPriority.RandomVelocityWeighted) { waterLineSorted = fo.waterLines.OrderByDescending(p => p.tri.velocityMagTimesDot).ToList(); } else { waterLineSorted = fo.waterLines.OrderByDescending(p => p.tri.dynamicForce.magnitude * p.tri.dotNormalVelocityNormal).ToList(); } WaterLine fastestLine = waterLineSorted[0]; // Check if object should emit if (fastestLine.tri.velocityMagnitude > sleepTresholdVelocity && fo.IsTouchingWater && fo.enabled) { int pointCount = fo.waterLines.Count; // Check if emit per frame valid if (emitPerCycle >= pointCount) { emitPerCycle = Mathf.Max(0, pointCount - 1); } // If random weighted, take the first quater of the descending list if (emissionPriority == EmissionPriority.RandomVelocityWeighted || emissionPriority == EmissionPriority.RandomForceWeighted) { int cnt = pointCount / 4; if (cnt < emitPerCycle) { cnt = emitPerCycle; } if (cnt < waterLineSorted.Count) { waterLineSorted = waterLineSorted.Take(cnt).ToList(); } } // Emit allowed number of particles while (emitted < emitPerCycle) { // Controls if (emitted >= pointCount) { break; } if (triedToEmit >= pointCount) { break; } // Get emit position line = null; // Get one point from water line if (emissionPriority == EmissionPriority.Random) { line = fo.waterLines[Random.Range(0, fo.waterLines.Count)]; } else if (emissionPriority == EmissionPriority.RandomVelocityWeighted) { line = waterLineSorted[Random.Range(0, waterLineSorted.Count)]; } else if (emitted < waterLineSorted.Count) { line = waterLineSorted[emitted]; } // Create new particle if (line != null && line.tri.velocityMagnitude > sleepTresholdVelocity) { WaterParticle wp = new WaterParticle(); // Determine position Vector3 p = line.p0; p -= line.tri.velocity * Time.deltaTime; // Setup particle GameObject particleGo = GameObject.CreatePrimitive(PrimitiveType.Quad); Destroy(particleGo.GetComponent <MeshCollider>()); float scale = maxParticleSize; particleGo.transform.localScale = new Vector3(scale, scale, scale); particleGo.transform.rotation = Quaternion.Euler(90f, 0f, Random.Range(0f, 360f)); particleGo.transform.parent = particleContainer.transform; MeshRenderer meshRenderer = particleGo.GetComponent <MeshRenderer>(); p.y = surfaceElevation + fo.WaterHeightFunction(p.x, p.z); particleGo.transform.position = p; // Mesh Material matInstance = new Material(Shader.Find("WaterFX/WaterParticle")); matInstance.SetTexture("_MainTex", foamTextures[Random.Range(0, foamTextures.Count)]); meshRenderer.material = matInstance; meshRenderer.material.renderQueue = renderQueue; meshRenderer.enabled = true; // Particle dynamics vel = line.tri.normal * line.tri.velocityMagnitude; localVel = fo.transform.InverseTransformVector(vel); localVel.z = 0f; vel = fo.transform.TransformVector(localVel); vel.y = 0f; wp.initialVelocity = vel * initialVelocityModifier; wp.initialAlpha = Mathf.Clamp(line.tri.dynamicForce.magnitude * 0.033f * initialAlphaModifier, 0f, maxInitialAlpha); // Init wp.initialColor = Color.white; wp.initialColor.a = wp.initialAlpha; wp.initialScale = particleGo.transform.localScale; wp.go = particleGo; wp.t = particleGo.transform; wp.mr = meshRenderer; wp.timeToLive = particleLifetime; wp.mat = meshRenderer.material; wp.initTime = Time.time; // Start from the beginning of the array, replacing the oldest particle if (pIndex >= maxParticles - 1) { pIndex = 0; } if (waterParticles[pIndex] != null) { Destroy(waterParticles[pIndex].go); } waterParticles[pIndex] = wp; pIndex++; emitted++; } triedToEmit++; } } } // Update existing particles for (int i = waterParticles.Length - 1; i >= 0; i--) { wp = waterParticles[i]; if (wp != null) { float timeLived = Time.time - wp.initTime; if (timeLived >= wp.timeToLive) { Destroy(wp.go); waterParticles[i] = null; } else { float livedPercent = timeLived / wp.timeToLive; wp.t.position += Time.deltaTime * velocityOverTime.Evaluate(livedPercent) * wp.initialVelocity; wp.t.localScale = wp.initialScale * sizeOverTime.Evaluate(livedPercent); float currentAlpha = alphaOverTime.Evaluate(livedPercent); if (currentAlpha < 0.05f && livedPercent > 0.4f) { Destroy(wp.go); waterParticles[i] = null; } else { wp.mr.material.SetColor( "_TintColor", new Color(wp.initialColor.r, wp.initialColor.g, wp.initialColor.b, wp.initialColor.a * currentAlpha) ); } } } } }
void UpdateInterWaterParticleCollision(float3 minPosition, float3 maxPosition) { //cache it int resolutionCube = marchingCubeResolution * marchingCubeResolution * marchingCubeResolution; if (waterParticleCountPerVoxel == null || waterParticleCountPerVoxel.Length != resolutionCube) { waterParticleCollisionTensor = new short[marchingCubeResolution, marchingCubeResolution, marchingCubeResolution, maxWaterParticlePerZone]; waterParticleCountPerVoxel = new byte[marchingCubeResolution, marchingCubeResolution, marchingCubeResolution]; particleIndicesInCollisionTensor = new int3[particleCount]; } else { Array.Clear(waterParticleCollisionTensor, 0, resolutionCube * maxWaterParticlePerZone); Array.Clear(waterParticleCountPerVoxel, 0, resolutionCube); Array.Clear(particleIndicesInCollisionTensor, 0, particleCount); } //float3 minPosition = cubeMarchineZone.bounds.min; //float3 maxPosition = cubeMarchineZone.bounds.max; float invResolution = 1f / marchingCubeResolution; float step = math.distance(minPosition, maxPosition) * invResolution; float invStep = 1f / step; //Broad phase for (int i = 0; i < particleCount; i++) { WaterParticle particle = waterParticles[i]; int3 index = WaterMarchingCube.GetPositionIndex(particle.position, minPosition, maxPosition, marchingCubeResolution, invStep); int numberOfParticleInVoxel = waterParticleCountPerVoxel[index.x, index.y, index.z]; if (numberOfParticleInVoxel < maxWaterParticlePerZone) { //Store the index of the particle in the grid particleIndicesInCollisionTensor[i] = index; waterParticleCollisionTensor[index.x, index.y, index.z, numberOfParticleInVoxel] = (short)i; waterParticleCountPerVoxel[index.x, index.y, index.z]++; } } //Narrow phase for (int i = 0; i < particleCount; i++) { //TODO check all 26 adjacent cells WaterParticle currentParticle = waterParticles[i]; int3 index = particleIndicesInCollisionTensor[i]; int numberOfParticleInVoxel = waterParticleCountPerVoxel[index.x, index.y, index.z]; for (int j = 0; j < numberOfParticleInVoxel; j++) { int otherParticleIndex = waterParticleCollisionTensor[index.x, index.y, index.z, j]; if (i == otherParticleIndex) { break; } WaterParticle otherParticle = waterParticles[otherParticleIndex]; float3 diff = otherParticle.position - currentParticle.position; //No collision if (math.lengthsq(diff) > particleRadius * particleRadius) { continue; } //TODO custom burstable functions //On collision vector keep they rejection, but swap projections float3 currentProjection = Vector3.Project(currentParticle.velocity, diff); float3 currentRejection = currentParticle.velocity - currentProjection; float3 otherProjection = Vector3.Project(otherParticle.velocity, diff); float3 otherRejection = currentParticle.velocity - otherProjection; //Swap currentParticle.velocity = (currentRejection + otherProjection) * elasticity; otherParticle.velocity = (otherRejection + currentProjection) * elasticity; //currentParticle.position -= diff * particleRadius; //otherParticle.position += diff * particleRadius; waterParticles[i] = currentParticle; waterParticles[otherParticleIndex] = otherParticle; } } }
public override bool PerformFrame(BCBlockGameState gamestate) { bool rval = base.PerformFrame(gamestate); for (int i = 0; i < (int)(50f * BCBlockGameState.ParticleGenerationFactor); i++) { const float speedmult = 1; //choose a random Angle... double randomangle = Math.PI * 2 * BCBlockGameState.rgen.NextDouble(); //create the appropriate speed vector, based on our radius... double usespeed = (_CurrentRadius / _MaxRadius) * speedmult; //should be proportional to how close we are to the maximum radius; max radius will have particles move 1... usespeed += ((BCBlockGameState.rgen.NextDouble() * 0.5) - 0.25); PointF addpointLocation = new PointF(Location.X + (float)Math.Cos(randomangle) * _CurrentRadius, Location.Y + (float)Math.Sin(randomangle) * _CurrentRadius); //create a dustparticle... Particle addparticle = null; if ((i % 5 == 0) && _ShowOrbs) { addparticle = new LightOrb(addpointLocation, Color.Blue, 5 + (float)(BCBlockGameState.rgen.NextDouble() * 10)); } else { addparticle = new WaterParticle(addpointLocation, new PointF((float)(Math.Cos(randomangle) * usespeed), (float)(Math.Sin(randomangle) * usespeed))); } if (addparticle != null) { addparticle.Velocity = new PointF(addparticle.Velocity.X + Velocity.X, addparticle.Velocity.Y + Velocity.Y); gamestate.Particles.Add(addparticle); } } //is this the first call? if (!flInit) { flInit = true; //initialize data structures. //the idea here is that createblocklocations will store the offset from the CreationEffect's location, rather than an absolute position. for (float x = -_MaxRadius; x < (_MaxRadius); x += BlockCreateSize.Width) { for (float y = -_MaxRadius; y < (_MaxRadius); y += BlockCreateSize.Height) { //add a new rectangle to that cache RectangleF createrect = new RectangleF(x, y, BlockCreateSize.Width, BlockCreateSize.Height); //add it to the list. createblocklocations.Add(createrect); } } } //createblocklocations has the offsets from our position. LINQ-ee-fy it to see if any need to be created. var createthese = from q in createblocklocations where BCBlockGameState.Distance(0, 0, q.CenterPoint().X, q.CenterPoint().Y) < _CurrentRadius select q; List<RectangleF> removethese = new List<RectangleF>(); if (createthese.Any()) { //we need to create some blocks we do. foreach (RectangleF looprect in createthese) { //create the PROPER rectanglef structure by cloning this one and offseting the clone. RectangleF userect = looprect; userect.Offset(Location.X, Location.Y); Block createdblock = DefaultCreationFunction(gamestate, userect); //add this block to the game. gamestate.Blocks.AddLast(createdblock); removethese.Add(looprect); } foreach (var removeit in removethese) { createblocklocations.Remove(removeit); } gamestate.Forcerefresh = true; } return rval; }
protected override void Draw(SpriteBatch sb, Game game, float elapsedSeconds) { if (Treasure.Instance.TimeDilationFast) { elapsedSeconds *= 4; } elapsedSeconds *= TimeDilation; mouseOverTile = null; mouseOverCharacter = null; base.Draw(sb, game, elapsedSeconds); Primitives.FillRectangle(Root.Screen, Color.Black); Rectangle start = ToReal(new Rectangle(0, 0, 1, 1)); Primitives.DrawRectangle(new Rectangle(start.X - 3, start.Y - 3, Session.MapWidth * TILESIZE + 6, Session.MapHeight * TILESIZE + 6), Color.White, 3); for (int x = 0; x < Session.MapWidth; x++) { for (int y = 0; y < Session.MapHeight; y++) { var rectThisTile = new Rectangle(start.X + x * TILESIZE, start.Y + y * TILESIZE, TILESIZE, TILESIZE); if (rectThisTile.Right < 0 || rectThisTile.Bottom < 0 || rectThisTile.X >= Root.ScreenWidth || rectThisTile.Y >= Root.ScreenHeight) { continue; } Session.Map[x, y].Draw(rectThisTile); if (Root.IsMouseOver(rectThisTile)) { mouseOverTile = Session.Map[x, y]; } } } foreach (var character in Session.Characters) { Point p = ToReal(character.Position); Rectangle rect = new Rectangle(p.X, p.Y, TILESIZE, TILESIZE); if (Root.IsMouseOver(rect)) { if (mouseOverCharacter == null || mouseOverCharacter.IsNPC || mouseOverCharacter.Dead) { mouseOverCharacter = character; } } if (character.Dead) { rect = new Rectangle(rect.X + 8, rect.Y + 8, rect.Width - 16, rect.Height - 16); } Primitives.DrawImage(Assets.TextureFromCard(character.Illustration), rect, character.Dead ? Color.Red : Color.White); if (character.ImmediateActivity != null) { Writer.DrawProgressBar(new Rectangle(rect.X, rect.Y - 6, rect.Width, 4), Color.Yellow, character.ImmediateActivity.SecondsProgressed, character.ImmediateActivity.SecondsToComplete, null); } if (character == SelectedCharacter) { Primitives.DrawRectangle(rect, Color.White); } } if (!Treasure.Instance.CheatMode) { for (int x = 0; x < Session.MapWidth; x++) { for (int y = 0; y < Session.MapHeight; y++) { var rectThisTile = new Rectangle(start.X + x * TILESIZE, start.Y + y * TILESIZE, TILESIZE, TILESIZE); if (rectThisTile.Right < 0 || rectThisTile.Bottom < 0 || rectThisTile.X >= Root.ScreenWidth || rectThisTile.Y >= Root.ScreenHeight) { continue; } Tile tile = Session.Map[x, y]; if (tile.Blackened) { Primitives.FillRectangle(rectThisTile, Color.DarkBlue); } } } } for (int x = 0; x < Session.MapWidth; x++) { for (int y = 0; y < Session.MapHeight; y++) { var rectThisTile = new Rectangle(start.X + x * TILESIZE, start.Y + y * TILESIZE, TILESIZE, TILESIZE); if (rectThisTile.Right < 0 || rectThisTile.Bottom < 0 || rectThisTile.X >= Root.ScreenWidth || rectThisTile.Y >= Root.ScreenHeight) { continue; } Tile tile = Session.Map[x, y]; foreach (Overhead overhead in tile.Overheads) { overhead.Draw(rectThisTile); } tile.Overheads.RemoveAll(oh => oh.UpdateAndPossiblyDelete(elapsedSeconds)); } } for (int wi = 0; wi < Session.Particles.Count; wi++) { WaterParticle pp = Session.Particles[wi]; Point asReal = ToReal(pp.Position); Primitives.DrawPoint(new Vector2(asReal.X, asReal.Y), Color.Blue, 6); pp.Position += pp.Speed * elapsedSeconds; pp.TimeLeft -= elapsedSeconds; if (pp.TimeLeft <= 0) { Session.Particles.RemoveAt(wi); wi--; } } DrawTopBar(); DrawBottomBar(); contextMenu?.Draw(); }