예제 #1
0
    public void UpdateEmissionRate(ref FireCell cell)
    {
        var emission = particles.emission;

        emission.rate = new ParticleSystem.MinMaxCurve(emissionRateFromFuel.GetValue(cell.fuelRemaining));
//		particles.emission = emission;
    }
    public List <FireCell> GetCellNeighbours(FireCell cell)
    {
        List <FireCell> neighbours = new List <FireCell>();

        for (int i = -1; i <= 1; i += 2)
        {
            Vector3 neighbourPositionX = cell.position + new Vector3(i * _grid.radius * 2, 0, 0);
            Vector3 neighbourPositionY = cell.position + new Vector3(0, i * _grid.radius * 2, 0);
            Vector3 neighbourPositionZ = cell.position + new Vector3(0, 0, i * _grid.radius * 2);
            foreach (var c in _grid.gridCells)
            {
                if (c.Key == neighbourPositionX && !_burningCells.Contains(c.Value))
                {
                    neighbours.Add(c.Value);
                }
                else if (c.Key == neighbourPositionY && !_burningCells.Contains(c.Value))
                {
                    neighbours.Add(c.Value);
                }
                else if (c.Key == neighbourPositionZ && !_burningCells.Contains(c.Value))
                {
                    neighbours.Add(c.Value);
                }
            }
        }
        return(neighbours);
    }
예제 #3
0
    public void Burning()
    {
        if (active)
        {
            // Get all surrounding objects
            Collider[] closeObjects = Physics.OverlapSphere(
                transform.position * Random.Range(0.6f, 1.3f),
                parent.radius * Random.Range(0.2f, 1.0f));

            foreach (Collider obj in closeObjects)
            {
                // Check if it collides with itself
                if (obj.collider != transform.collider && obj.collider != parent.collider)
                {
                    Flammable flammable = obj.GetComponent <Flammable>();
                    FireCell  cell      = obj.GetComponent <FireCell>();

                    // Is it a FireCell?
                    if (cell != null)
                    {
                        cell.FireDamage();
                    }
                    // Is it a Flammable?
                    else if (flammable != null)
                    {
                        flammable.RespondToFire();
                    }
                }
            }
        }
    }
예제 #4
0
    void UpdateSpreading()
    {
        if (!gameObject || !gameObject.transform || !gameObject.transform.parent)
        {
            return;
        }
        GameObject Parent = gameObject.transform.parent.gameObject;

        float    nearestCellDist = float.MaxValue;
        FireCell nearestCell     = null;

        for (int i = 0; i < Parent.transform.childCount; ++i)
        {
            FireCell cell = Parent.transform.GetChild(i).gameObject.GetComponent <FireCell>();

            if (cell != this && cell)
            {
                float magnitude = (cell.transform.position - transform.position).magnitude;
                if (magnitude < nearestCellDist)
                {
                    nearestCellDist = magnitude;
                    nearestCell     = cell;
                }
            }
        }

        if (nearestCell && nearestCell.IsBurning)
        {
            BurningCounter += Time.deltaTime;
        }
    }
 public void IgniteCell(ref FireCell newCell)
 {
     newCell.InitializeFuelInfo(cellExtents, fuelFromCellDensity);
     newCell.burnStartTime = Time.time;
     newCell.groundParticles.StartFire();
     newCell.activated = true;
     activeCells.Add(newCell);
 }
 public void StartFire(Vector3 heatSourcePosition)
 {
     if (_state == FireState.Normal)
     {
         _hasStartedFire = true;
         _flames         = new Dictionary <Vector3, GameObject>();
         FindAllCells();
         FireCell nearestCell = FindNearestCell(heatSourcePosition);
         _burningCells.Add(nearestCell);
     }
 }
	public void InitializeFireGrid()
	{
		activeCells = new List<FireCell> ();
		depletedCells = new List<FireCell> ();

		mapSize = ForestController.Instance.mapSize;
		mapSize.y = ForestController.Instance.maxTerrainHeight;
		cellsX = Mathf.FloorToInt(mapSize.x / gridSize);
		cellsY = Mathf.FloorToInt(mapSize.z / gridSize);
		cells = new FireCell[cellsX,cellsY];

		if (particlesContainer)
		{
			Destroy(particlesContainer.gameObject);
		}

		particlesContainer = new GameObject ("Fire Particles Container").transform;
		particlesContainer.parent = transform;

		burntTextureSettings.InitializeTexture(cellsX, cellsY);

		cellExtents = new Vector3 (gridSize / 2f, mapSize.y / 2f, gridSize / 2f);

		RaycastHit hit;
		for (int x = 0; x < cellsX; x++)
		{
			for (int y = 0; y < cellsY; y++)
			{
				Vector2Int gridPosition = new Vector2Int (x, y);
				Vector3 centerPoint = new Vector3 (((float)x / (float)cellsX - .5f) * mapSize.x,  
					mapSize.y + .5f, 
					((float)y / (float)cellsY - .5f) * mapSize.z);

				Vector3 normal = Vector3.up;
				if (Physics.Raycast(centerPoint, Vector3.down, out hit, mapSize.y + 20f, ForestController.Instance.terrainLayerMask))
				{
					centerPoint = hit.point;
					normal = hit.normal;
				}

				cells[x, y] = new FireCell (gridPosition, centerPoint, normal);
				cells[x, y].InitializeFuelInfo(cellExtents, fuelFromCellDensity);

				GameObject newGroundParticles = GameObject.Instantiate(groundFireParticles, centerPoint, Quaternion.LookRotation(normal)) as GameObject;
				newGroundParticles.name = groundFireParticles.name + " [" + x.ToString() + "," + y.ToString() + "]";
				newGroundParticles.transform.parent = particlesContainer;
				cells[x, y].groundParticles = newGroundParticles.GetComponent<FireParticleEffect>();
				cells[x, y].groundParticles.cell = cells[x, y];
			}
		}

	}
    public void InitializeFireGrid()
    {
        activeCells   = new List <FireCell> ();
        depletedCells = new List <FireCell> ();

        mapSize   = ForestController.Instance.mapSize;
        mapSize.y = ForestController.Instance.maxTerrainHeight;
        cellsX    = Mathf.FloorToInt(mapSize.x / gridSize);
        cellsY    = Mathf.FloorToInt(mapSize.z / gridSize);
        cells     = new FireCell[cellsX, cellsY];

        if (particlesContainer)
        {
            Destroy(particlesContainer.gameObject);
        }

        particlesContainer        = new GameObject("Fire Particles Container").transform;
        particlesContainer.parent = transform;

        burntTextureSettings.InitializeTexture(cellsX, cellsY);

        cellExtents = new Vector3(gridSize / 2f, mapSize.y / 2f, gridSize / 2f);

        RaycastHit hit;

        for (int x = 0; x < cellsX; x++)
        {
            for (int y = 0; y < cellsY; y++)
            {
                Vector2Int gridPosition = new Vector2Int(x, y);
                Vector3    centerPoint  = new Vector3(((float)x / (float)cellsX - .5f) * mapSize.x,
                                                      mapSize.y + .5f,
                                                      ((float)y / (float)cellsY - .5f) * mapSize.z);

                Vector3 normal = Vector3.up;
                if (Physics.Raycast(centerPoint, Vector3.down, out hit, mapSize.y + 20f, ForestController.Instance.terrainLayerMask))
                {
                    centerPoint = hit.point;
                    normal      = hit.normal;
                }

                cells[x, y] = new FireCell(gridPosition, centerPoint, normal);
                cells[x, y].InitializeFuelInfo(cellExtents, fuelFromCellDensity);

                GameObject newGroundParticles = GameObject.Instantiate(groundFireParticles, centerPoint, Quaternion.LookRotation(normal)) as GameObject;
                newGroundParticles.name             = groundFireParticles.name + " [" + x.ToString() + "," + y.ToString() + "]";
                newGroundParticles.transform.parent = particlesContainer;
                cells[x, y].groundParticles         = newGroundParticles.GetComponent <FireParticleEffect>();
                cells[x, y].groundParticles.cell    = cells[x, y];
            }
        }
    }
    public void AddCellToGrid(Vector3 position)
    {
        FireCell cell = new FireCell();

        if (cell != null)
        {
            cell.radius   = _grid.radius;
            cell.position = position;
            cell.settings = fireSettings;
            if (!_grid.gridCells.ContainsKey(position))
            {
                _grid.gridCells.Add(position, cell);
            }
        }
    }
예제 #10
0
    public FireGrid(float x, float y, Vector3 position)
    {
        this.x = (int)x / cellSize;
        this.y = (int)y / cellSize;

        grid = new FireCell[this.x, this.y];

        //TODO Use jagged array? http://stackoverflow.com/questions/7154592/initializing-two-dimensional-array-of-objects
        for (int i = 0; i < this.y; i++)
        {
            for (int j = 0; j < this.x; j++)
            {
                grid[i, j] = new FireCell();
            }
        }
    }
예제 #11
0
    void Start()
    {
        InvokeRepeating("UpdateSpread", 0f, 1.0f);

        // Control if the object should ignite
        if (ignite)
        {
            GenerateGrid();

            // Start a fire at a random position
            while (true)
            {
                FireCell cell = fireGrid[Random.Range(0, fireGrid.Count - 1)];

                if (cell.active)
                {
                    cell.StartFire();
                    break;
                }
            }
        }
    }
    void AttemptSpread(FireCell initialCell)
    {
        for (int i = 0; i < initialCell.adjacentCells.Count; i++)
        {
            FireCell adjacentCell = GetCellFromV2Int(initialCell.adjacentCells[i]);
            if (adjacentCell.activated)
            {
                initialCell.adjacentCells.RemoveAt(i);
                i--;
                continue;
            }

            float spreadAttemptValue = Random.value * Vector3.Dot(initialCell.normal, adjacentCell.normal);
            if (spreadAttemptValue >= burnSpreadChance.GetValue(adjacentCell.fuelRemaining))
            {
                IgniteCell(ref adjacentCell);
                initialCell.adjacentCells.RemoveAt(i);
                i--;
                continue;
            }
        }
    }
예제 #13
0
    void CheckWaterCollision()
    {
        Vector3 Pos = WaterCollisionCheckList[0];

        WaterCollisionCheckList.RemoveAt(0);

        Debug.DrawLine(Pos - Vector3.up * WaterDropRadius, Pos + Vector3.up * WaterDropRadius, Color.red);
        Debug.DrawLine(Pos - Vector3.left * WaterDropRadius, Pos + Vector3.left * WaterDropRadius, Color.red);

        Collider2D[] HitObjects = Physics2D.OverlapCircleAll(Pos, WaterDropRadius);

        foreach (Collider2D coll in HitObjects)
        {
            if (coll.CompareTag("forest"))
            {
                FireCell cell = coll.gameObject.GetComponent <FireCell>();

                if (cell)
                {
                    cell.CurrentHealth -= WaterDamage;
                }
            }
            else if (coll.CompareTag("enemy"))
            {
                HealthBar     demon          = coll.GetComponent <HealthBar>();
                DemonBehavior demon_behavior = coll.GetComponent <DemonBehavior>();
                if (GameObject.Find("Player").GetComponent <ScoreComponent>().bDamageBoost)
                {
                    demon.Health -= WaterDamage * 2;
                }
                else
                {
                    demon.Health -= WaterDamage;
                }
                demon_behavior.Hit();
            }
        }
    }
    public void AddAdjacentCells(FireCell initialCell)
    {
        int thisX = initialCell.gridPosition.x;
        int thisY = initialCell.gridPosition.y;

        for (int x = thisX - 1; x <= thisX + 1; x++)
        {
            if (x >= 0 && x < cellsX)
            {
                initialCell.adjacentCells.Add(new Vector2Int(x, thisY));
            }
            x++;
        }

        for (int y = thisY - 1; y <= thisY + 1; y++)
        {
            if (y >= 0 && y < cellsY)
            {
                initialCell.adjacentCells.Add(new Vector2Int(thisX, y));
            }
            y++;
        }
    }
예제 #15
0
    private FireCell FindNearestCell(Vector3 heatSourcePosition)
    {
        FireCell nearestCell     = null;
        float    nearestDistance = 0;

        foreach (var cell in _grid.gridCells)
        {
            if (nearestCell == null)
            {
                nearestCell     = cell.Value;
                nearestDistance = Vector3.Distance(cell.Key, heatSourcePosition);
            }
            else
            {
                if (Vector3.Distance(cell.Key, heatSourcePosition) < nearestDistance)
                {
                    nearestCell     = cell.Value;
                    nearestDistance = Vector3.Distance(cell.Key, heatSourcePosition);
                }
            }
        }
        return(nearestCell);
    }
예제 #16
0
    public void Water()
    {
        if (active)
        {
            WaterDamage();

            // Get all surrounding objects
            Collider[] closeObjects = Physics.OverlapSphere(transform.position, parent.radius);

            foreach (Collider obj in closeObjects)
            {
                // Check if it collides with itself
                if (obj.collider != transform.collider && obj.collider != parent.collider)
                {
                    FireCell cell = obj.GetComponent <FireCell>();

                    if (cell != null)
                    {
                        cell.WaterDamage();
                    }
                }
            }
        }
    }
예제 #17
0
    private void GenerateGrid()
    {
        Bounds  bounds = transform.collider.bounds;
        Vector3 min    = bounds.min;
        Vector3 max    = bounds.max;

        for (float x = min.x; x <= max.x; x = x + cellSize)
        {
            for (float y = min.y; y <= max.y; y = y + cellSize)
            {
                for (float z = min.z; z <= max.z; z = z + cellSize)
                {
                    Vector3 pos = new Vector3(x, y, z);

                    if (positionInsideThis(pos))
                    {
                        FireCell cell = (FireCell)Instantiate(fireCell, pos, transform.rotation);
                        cell.Instantiate(this);
                        fireGrid.Add(cell);
                    }
                }
            }
        }
    }
예제 #18
0
    // Update is called once per frame
    void Update()
    {
        timeLeft -= Time.deltaTime;
        //Debug.Log(timeLeft);

        if (Pathfinding.Target.Equals(string.Empty) && timeLeft < 0)
        {
            if (Pathfinding.Target != null)
            {
                if (room == null || !Pathfinding.CurrentRoom.Equals(room.name))
                {
                    room          = GameObject.Find(Pathfinding.CurrentRoom);
                    roomInfo      = room.GetComponent <RoomInformation>();
                    roomFlammable = room.GetComponent <Flammable>();
                }
                if (roomInfo.FireCount > 0)
                {
                    if (currentTarget == null || !currentTarget.IsBurning)
                    {
                        FireCell[] fires = roomFlammable.GetComponentsInChildren <FireCell>();
                        if (currentTarget == null)
                        {
                            for (int i = 0; i < fires.Length; i++)
                            {
                                if (fires[i].IsBurning)
                                {
                                    currentTarget = fires[i];
                                    break;
                                }
                            }
                        }
                        else
                        {
                            Collider[] colliders = Physics.OverlapSphere(currentTarget.transform.position, roomFlammable.cellSize);
                            Debug.Log(colliders.Length);
                            for (int i = 0; i < colliders.Length; i++)
                            {
                                FireCell cell = colliders[i].GetComponent <FireCell>();
                                if (cell != null && cell.IsBurning)
                                {
                                    currentTarget = cell;
                                    break;
                                }
                            }
                            if (!currentTarget.IsBurning)
                            {
                                currentTarget = null;
                            }
                        }
                    }

                    if (currentTarget != null)
                    {
                        transform.LookAt(currentTarget.transform);
                        //Water.ShootFluidParticle(this.transform);
                        Water.ShootFluidParticle(this.transform);
                    }
                }
            }

            timeLeft = timeBetweenShots;
        }
    }
	public void AddAdjacentCells (FireCell initialCell)
	{
		int thisX = initialCell.gridPosition.x;
		int thisY = initialCell.gridPosition.y;

		for (int x = thisX - 1; x <= thisX + 1; x++)
		{
			if (x >= 0 && x < cellsX)
			{
				initialCell.adjacentCells.Add(new Vector2Int(x, thisY));
			}
			x++;
		}

		for (int y = thisY - 1; y <= thisY + 1; y++)
		{
			if (y >= 0 && y < cellsY)
			{
				initialCell.adjacentCells.Add(new Vector2Int(thisX, y));
			}
			y++;
		}
	}
	public void IgniteCell (ref FireCell newCell)
	{
		newCell.InitializeFuelInfo(cellExtents, fuelFromCellDensity);
		newCell.burnStartTime = Time.time;
		newCell.groundParticles.StartFire();
		newCell.activated = true;
		activeCells.Add(newCell);
	}
	public void UpdateEmissionRate (ref FireCell cell)
	{
		var emission = particles.emission;
		emission.rate = new ParticleSystem.MinMaxCurve(emissionRateFromFuel.GetValue(cell.fuelRemaining));
//		particles.emission = emission;
	}
예제 #22
0
    void FixedUpdate()
    {
        // Remove all particles that have fallen too low, have expired or hit fire
        if (RemoveExpiredParticles)
        {
            Particles.RemoveAll(p => p.ToBeRemoved || (p.Position.y < -1) || p.Expiry <= 0);
        }
        else
        {
            Particles.RemoveAll(p => p.ToBeRemoved || (p.Position.y < -1));
        }

        // Add new particles
        Particles.AddRange(newParticles);
        newParticles.Clear();

        int newParticleCount = Particles.Count;

        if (newParticleCount != particleCount)
        {
            particleCount = newParticleCount;
            Debug.Log(particleCount + " fluid particles.");
        }

        // Predict the positions of the particles
        // Lines 1-4 from the algorithm in the paper
        foreach (FluidParticle p in Particles)
        {
            // Apply gravity
            p.Velocity -= Gravity;

            Vector3    newPosition = p.Position + p.Velocity;
            RaycastHit hit         = new RaycastHit();
            if (Physics.Linecast(p.Position, newPosition + ParticleDiameter * (newPosition - p.Position).normalized, out hit))
            {
                if (hit.normal.y != 0)
                {
                    p.Velocity += Gravity;
                }
                p.Velocity  = Vector3.Reflect(p.Velocity * ParticleElasticity, hit.normal);
                newPosition = p.Position + p.Velocity;

                FireCell fireCell = hit.collider.GetComponent <FireCell>();
                if (fireCell != null)
                {
                    fireCell.Water();
                    p.ToBeRemoved = true;
                }
            }
            p.PredictedPosition = newPosition;
        }

        // Find neighbours of each particle
        // Lines 5-7 from the algorithm in the paper
        List <FluidParticle>[] neighbours = new List <FluidParticle> [Particles.Count];
        for (int i = 0; i < Particles.Count; i++)
        {
            FluidParticle p = Particles[i];
            p.Index = i;
            List <FluidParticle> foundNeighbours = new List <FluidParticle>();
            foreach (FluidParticle potentialNeighbour in Particles)
            {
                if (potentialNeighbour != p && Vector3.Distance(potentialNeighbour.Position, p.Position) < NeighbourDistance)
                {
                    foundNeighbours.Add(potentialNeighbour);
                }
            }
            neighbours[i] = foundNeighbours;
        }

        float[]   lambdas  = new float[Particles.Count];
        Vector3[] deltaPos = new Vector3[Particles.Count];

        // Refine the predicted positions by taking incompressibilty into account
        // Lines 8-19 from the algorithm in the paper
        for (int iteration = 0; iteration < SolverIterations; iteration++)
        {
            // Find lambda for each particle
            // Lines 9-11 from the algorithm in the paper
            for (int i = 0; i < Particles.Count; i++)
            {
                FluidParticle        p = Particles[i];
                List <FluidParticle> foundNeighbours = neighbours[i];
                float pi        = StdSPHDensityEstimator(p, foundNeighbours);
                float c         = pi / RestDensity - 1;
                float deltaCSum = DerivativeCSum(p, foundNeighbours);
                lambdas[i] = -c / deltaCSum;
            }

            // Find more finely predicted positions
            // Lines 12-15 from the algorithm in the paper
            for (int i = 0; i < Particles.Count; i++)
            {
                FluidParticle        p = Particles[i];
                List <FluidParticle> foundNeighbours = neighbours[i];
                deltaPos[i] = Vector3.zero;
                foreach (FluidParticle neigbour in foundNeighbours)
                {
                    deltaPos[i] += (lambdas[i] + lambdas[neigbour.Index]) * Vector3.Normalize(p.PredictedPosition - neigbour.Position) * SpikyDerivative(p, neigbour);
                }
                deltaPos[i] = 1 / RestDensity * deltaPos[i];
                Vector3 newPosition = p.PredictedPosition + deltaPos[i];
                if (Physics.Linecast(p.PredictedPosition, newPosition + ParticleDiameter * (newPosition - p.Position).normalized))
                {
                    deltaPos[i] = Vector3.zero;
                }
            }

            // Use the new positions
            // Lines 16-18 from the algorithm in the paper
            for (int i = 0; i < Particles.Count; i++)
            {
                FluidParticle p = Particles[i];
                p.PredictedPosition += deltaPos[i];
            }
        }

        // Actually set the new positions and count down the expiry of the particles.
        foreach (FluidParticle p in Particles)
        {
            p.Velocity = p.PredictedPosition - p.Position;
            p.Position = p.PredictedPosition;
            p.Expiry--;
        }
    }
	void AttemptSpread (FireCell initialCell)
	{
		for(int i = 0; i < initialCell.adjacentCells.Count; i++)
		{
			FireCell adjacentCell = GetCellFromV2Int(initialCell.adjacentCells[i]);
			if (adjacentCell.activated)
			{
				initialCell.adjacentCells.RemoveAt(i);
				i--;
				continue;
			}

			float spreadAttemptValue = Random.value * Vector3.Dot(initialCell.normal, adjacentCell.normal);
			if (spreadAttemptValue >= burnSpreadChance.GetValue(adjacentCell.fuelRemaining))
			{
				IgniteCell(ref adjacentCell);
				initialCell.adjacentCells.RemoveAt(i);
				i--;
				continue;
			}
		}
	}