示例#1
0
        private static void explode(Main main, Voxel map, Voxel.Coord coord, Vector3 pos, int radius, float physicsRadius)
        {
            float distanceToCamera = (main.Camera.Position.Value - pos).Length();

            // Kaboom
            Sound.PostEvent(distanceToCamera < physicsRadius * 1.5f ? AK.EVENTS.PLAY_EXPLOSION_CLOSE : AK.EVENTS.PLAY_EXPLOSION, pos);

            Entity lightEntity = Factory.Get <PointLightFactory>().CreateAndBind(main);

            lightEntity.Serialize = false;
            PointLight light = lightEntity.Get <PointLight>();

            light.Color.Value       = new Vector3(1.3f, 1.1f, 0.9f);
            light.Attenuation.Value = 20.0f;
            light.Position.Value    = pos;
            lightEntity.Add(new Animation
                            (
                                new Animation.FloatMoveTo(light.Attenuation, 0.0f, 1.0f),
                                new Animation.Execute(light.Delete)
                            ));
            main.Add(lightEntity);

            SmokeFactory smokeFactory = Factory.Get <SmokeFactory>();

            for (int i = 0; i < 5; i++)
            {
                Entity smoke = smokeFactory.CreateAndBind(main);
                smoke.Get <Transform>().Position.Value = pos;
                main.Add(smoke);
            }

            ParticleEmitter.Emit(main, "Smoke", pos, physicsRadius * 0.4f, 250);

            Entity player = PlayerFactory.Instance;

            if (player != null && player.Active)
            {
                player.Get <CameraController>().Shake.Execute(pos, 50.0f);
            }

            const float physicsImpulse         = 70.0f;
            const float minPlayerDamage        = 0.1f;
            const float playerDamageMultiplier = 2.0f;

            // Remove the cells
            BlockFactory blockFactory = Factory.Get <BlockFactory>();

            foreach (Voxel m in Voxel.ActiveVoxels.ToList())
            {
                List <Voxel.Coord> removals = new List <Voxel.Coord>();

                Voxel.Coord c           = m.GetCoordinate(pos);
                Vector3     relativePos = m.GetRelativePosition(c);

                Quaternion quat = m.Entity.Get <Transform>().Quaternion;

                for (Voxel.Coord x = c.Move(Direction.NegativeX, radius - 1); x.X < c.X + radius; x.X++)
                {
                    for (Voxel.Coord y = x.Move(Direction.NegativeY, radius - 1); y.Y < c.Y + radius; y.Y++)
                    {
                        for (Voxel.Coord z = y.Move(Direction.NegativeZ, radius - 1); z.Z < c.Z + radius; z.Z++)
                        {
                            Voxel.State s = m[z];
                            if (s.ID == 0 || s.Permanent)
                            {
                                continue;
                            }

                            Vector3 cellPos = m.GetRelativePosition(z);
                            if ((cellPos - relativePos).Length() < radius - 1)
                            {
                                removals.Add(z);
                                if (random.NextDouble() > 0.5)
                                {
                                    Entity    block          = blockFactory.CreateAndBind(main);
                                    Transform blockTransform = block.Get <Transform>();
                                    blockTransform.Position.Value   = m.GetAbsolutePosition(cellPos);
                                    blockTransform.Quaternion.Value = Quaternion.CreateFromYawPitchRoll(((float)random.NextDouble() - 0.5f) * 2.0f * (float)Math.PI, ((float)random.NextDouble() - 0.5f) * 2.0f * (float)Math.PI, ((float)random.NextDouble() - 0.5f) * 2.0f * (float)Math.PI);
                                    s.ApplyToBlock(block);
                                    main.Add(block);
                                }
                            }
                        }
                    }
                }
                if (removals.Count > 0)
                {
                    m.Empty(removals);
                    m.Regenerate();
                }
            }

            // Damage the player
            if (player != null && player.Active)
            {
                Vector3 toPlayer = player.Get <Transform>().Position - pos;
                float   d        = toPlayer.Length();
                if (d < physicsRadius)
                {
                    float attenuation = 1.0f;
                    if (d > 0)
                    {
                        Voxel.GlobalRaycast(pos, toPlayer / d, d, delegate(int x, Voxel.t c)
                        {
                            Voxel.State s = Voxel.States.All[c];
                            if (s.Permanent)
                            {
                                attenuation = 0.0f;
                                return(true);
                            }
                            else if (s.Hard)
                            {
                                attenuation -= 0.6f;
                            }
                            else
                            {
                                attenuation -= 0.35f;
                            }
                            return(false);
                        });
                        attenuation = Math.Max(0, attenuation);
                    }
                    player.Get <Agent>().Damage.Execute(attenuation * (minPlayerDamage + (1.0f - (d / physicsRadius)) * playerDamageMultiplier));
                }
            }

            // Apply impulse to dynamic maps
            foreach (Voxel m in Voxel.ActiveVoxels)
            {
                DynamicVoxel dm = m as DynamicVoxel;
                if (dm == null)
                {
                    continue;
                }

                Vector3 toMap         = dm.Transform.Value.Translation - pos;
                float   distanceToMap = toMap.Length();
                toMap /= distanceToMap;

                toMap *= Math.Max(0.0f, 1.0f - (distanceToMap / physicsRadius)) * Math.Min(200.0f, dm.PhysicsEntity.Mass) * physicsImpulse;

                dm.PhysicsEntity.ApplyImpulse(dm.Transform.Value.Translation + new Vector3(((float)random.NextDouble() - 0.5f) * 2.0f, ((float)random.NextDouble() - 0.5f) * 2.0f, ((float)random.NextDouble() - 0.5f) * 2.0f), toMap);
            }

            // Apply impulse to physics blocks
            foreach (Entity b in main.Get("Block"))
            {
                PhysicsBlock block         = b.Get <PhysicsBlock>();
                Vector3      fromExplosion = b.Get <Transform>().Position.Value - pos;
                float        distance      = fromExplosion.Length();
                if (distance > 0.0f && distance < physicsRadius)
                {
                    float blend = 1.0f - (distance / physicsRadius);
                    block.Box.LinearVelocity  += fromExplosion * blend * 10.0f / distance;
                    block.Box.AngularVelocity += new Vector3(((float)random.NextDouble() - 0.5f) * 2.0f, ((float)random.NextDouble() - 0.5f) * 2.0f, ((float)random.NextDouble() - 0.5f) * 2.0f) * blend;
                }
            }
        }
示例#2
0
        public bool BreakWalls(Vector3 forward, Vector3 right)
        {
            BlockFactory blockFactory = Factory.Get <BlockFactory>();
            Vector3      basePos      = this.Position + new Vector3(0, 0.2f + (this.Height * -0.5f) - this.SupportHeight, 0) + forward * -1.0f;
            bool         broke        = false;

            foreach (Voxel map in Voxel.ActivePhysicsVoxels.ToList())
            {
                List <Voxel.Coord> removals      = new List <Voxel.Coord>();
                Quaternion         mapQuaternion = Quaternion.CreateFromRotationMatrix(map.Transform);
                Voxel.Coord        top           = map.GetCoordinate(basePos + new Vector3(0, this.Height + this.SupportHeight + 0.5f, 0));
                Direction          upDir         = map.GetRelativeDirection(Vector3.Up);
                Direction          rightDir      = map.GetRelativeDirection(right);
                Direction          forwardDir    = map.GetRelativeDirection(forward);
                Voxel.Coord        center        = map.GetCoordinate(basePos);
                for (Voxel.Coord y = center.Clone(); y.GetComponent(upDir) <= top.GetComponent(upDir); y = y.Move(upDir))
                {
                    int minZ = center.GetComponent(rightDir) - 10;
                    int maxZ = minZ + 20;
                    foreach (Voxel.Coord x in this.spreadFromCenter(y, rightDir))
                    {
                        Voxel.Coord z = x.Clone();
                        for (int i = 0; i < 4; i++)
                        {
                            Voxel.State state           = map[z];
                            int         zRightDimension = z.GetComponent(rightDir);
                            if (zRightDimension > minZ && zRightDimension < maxZ && state.ID != 0 && !removals.Contains(z))
                            {
                                if (state.Permanent || state.Hard)
                                {
                                    if (zRightDimension >= center.GetComponent(rightDir))
                                    {
                                        maxZ = zRightDimension;
                                    }
                                    else
                                    {
                                        minZ = zRightDimension;
                                    }
                                    break;
                                }
                                else
                                {
                                    broke = true;
                                    removals.Add(z);
                                    Vector3   cellPos        = map.GetAbsolutePosition(z);
                                    Vector3   toCell         = cellPos - basePos;
                                    Entity    block          = blockFactory.CreateAndBind(this.main);
                                    Transform blockTransform = block.Get <Transform>();
                                    blockTransform.Position.Value   = cellPos;
                                    blockTransform.Quaternion.Value = mapQuaternion;
                                    state.ApplyToBlock(block);
                                    toCell += forward * 4.0f;
                                    toCell.Normalize();
                                    PhysicsBlock physicsBlock = block.Get <PhysicsBlock>();
                                    physicsBlock.LinearVelocity.Value  = toCell * 15.0f;
                                    physicsBlock.AngularVelocity.Value = new Vector3(((float)this.random.NextDouble() - 0.5f) * 2.0f, ((float)this.random.NextDouble() - 0.5f) * 2.0f, ((float)this.random.NextDouble() - 0.5f) * 2.0f);
                                    main.Add(block);
                                }
                            }
                            z = z.Move(forwardDir);
                        }
                    }
                }

                if (removals.Count > 0)
                {
                    map.Empty(removals);
                    map.Regenerate();
                }
            }
            return(broke);
        }