Esempio n. 1
0
        protected override void CalculateLines()
        {
            float w = Scale.X / 2.0f;
            float h = Scale.Y / 2.0f;

            // the first one is left-top, clock-wise
            Vector3[] vertices = new Vector3[4];
            vertices[0] = new Vector3(-w, -h, 0.0f);
            vertices[1] = new Vector3(w, -h, 0.0f);
            vertices[2] = new Vector3(w, h, 0.0f);
            vertices[3] = new Vector3(-w, h, 0.0f);

            Quaternion rotation = Quaternion.BetweenDirections(Vector3.UnitZ, normal);

            for (int i = 0; i < vertices.Length; i++)
            {
                rotation.Rotate(ref vertices[i]);
                vertices[i] += Transform.Position;
            }

            // contour
            lines[0] = new Line(vertices[0], vertices[1], Color);
            lines[1] = new Line(vertices[1], vertices[2], Color);
            lines[2] = new Line(vertices[2], vertices[3], Color);
            lines[3] = new Line(vertices[3], vertices[0], Color);

            // cross
            lines[4] = new Line(vertices[0], vertices[2], Color);
            lines[5] = new Line(vertices[1], vertices[3], Color);

            NotifyPropertyChanged();
        }
Esempio n. 2
0
        public static (VertexPositionTexture[] Vertices, int[] Indices) GenerateQuad(float width, float height)
        {
            var quadMeshData = GeometricPrimitive.Plane.New(width, height);

            VertexPositionTexture[] vertices = new VertexPositionTexture[quadMeshData.Vertices.Length];
            int[] indices = new int[quadMeshData.Indices.Length];

            CopyFromGeometricPrimitive(quadMeshData, ref vertices, ref indices);

            /* transform it because in its default orientation it isnt flat to the normal up */
            Quaternion rotation = Quaternion.BetweenDirections(Vector3.UnitZ, Vector3.UnitY);

            for (int i = 0; i < vertices.Length; ++i)
            {
                vertices[i].Position = Vector3.Transform(vertices[i].Position, rotation);
            }

            return(vertices, indices);
        }
Esempio n. 3
0
        protected override async Task Shoot(Entity targetEntity)
        {
            // Play shooting animation
            Drone.Animation.Shoot();

            // Wait a bit
            await Task.Delay(TimeSpan.FromSeconds(AnimationDelay));

            // Spawn projectile
            var projectileEntity = ProjectilePrefab.Instantiate().Single();
            var projectile       = projectileEntity.Get <Projectile>();

            projectile.Owner = Drone.Entity;

            projectileEntity.Transform.Position = ProjectileSpawnPoint.Transform.WorldMatrix.TranslationVector;
            projectileEntity.Transform.Rotation = Quaternion.BetweenDirections(Vector3.UnitZ, Drone.HeadDirection);

            Drone.SceneSystem.SceneInstance.RootScene.Entities.Add(projectile.Entity);
            projectile.SetDirection(Drone.HeadDirection);

            shootSoundSelector.PlayAndForget();
        }
Esempio n. 4
0
        public override void Update()
        {
            Vector3 targetDir = TargetPosition - Entity.Transform.WorldMatrix.TranslationVector;

            if (targetDir.LengthSquared() < 1.0f)
            {
                return;
            }
            targetDir.Normalize();

            var projectile       = Entity.Get <Projectile>();
            var currentDirection = Vector3.Normalize(projectile.Rigidbody.LinearVelocity);

            // Bend towards target direction
            targetDir = currentDirection + Vector3.Normalize(targetDir) * HomingSpeed * (float)Game.UpdateTime.Elapsed.TotalSeconds;
            targetDir.Normalize();

            // Reset velocity based on adjusted direction
            projectile.Rigidbody.LinearVelocity = Vector3.Zero;
            projectile.SetDirection(targetDir);

            projectile.Entity.Transform.Rotation = Quaternion.BetweenDirections(Vector3.UnitZ, targetDir);
        }
Esempio n. 5
0
        public override async Task Execute()
        {
            while (Game.IsRunning)
            {
                var target = await weaponFiredEvent.ReceiveAsync();

                if (target.DidFire)
                {
                    SpawnEvent("MuzzleFlash", Entity, Matrix.Identity);
                }

                if (target.DidHit)
                {
                    SpawnEvent("BulletImpact", null, Matrix.RotationQuaternion(Quaternion.BetweenDirections(Vector3.UnitY, target.HitResult.Normal)) * Matrix.Translation(target.HitResult.Point));
                }

                if (target.HitResult.Collider is RigidbodyComponent rigidBody)
                {
                    var rand = new Random();
                    SpawnEvent("DamagedTrail", rigidBody.Entity, Matrix.Translation(new Vector3((float)rand.NextDouble() - 0.5f, (float)rand.NextDouble() - 0.5f, (float)rand.NextDouble() - 0.5f)));
                }
            }
        }
        /// <summary>
        /// Update and recreate a page if necessary
        /// </summary>
        private void UpdatePages(TerrainComponent terrain, TerrainVegetationComponent component, TerrainVegetationRenderData renderData)
        {
            if (renderData.Pages != null && renderData.MaskImage != null && !component.IsDirty)
            {
                return;
            }

            if (renderData.MaskImage == null || renderData.Mask != component.Mask)
            {
                renderData.Mask = component.Mask;
                renderData.MaskImage?.Dispose();

                // Get mask image data
                try
                {
                    var game            = Services.GetService <IGame>();
                    var graphicsContext = game.GraphicsContext;
                    var commandList     = graphicsContext.CommandList;
                    renderData.MaskImage = component.Mask.GetDataAsImage(commandList);
                }
                catch
                {
                    // Image probably not loaded yet .. try again next frame :)
                    return;
                }
            }

            // Cache render data so we won't need to recreate pages
            var mask        = renderData.MaskImage.PixelBuffer[0];
            var maskChannel = (int)component.MaskChannel;

            // Calculate terrain center offset
            var terrainOffset = terrain.Size / 2.0f;

            // Create vegetation pages
            var rng         = new Random(component.Seed);
            var pagesPerRow = (int)terrain.Size / PageSize;

            var instancesPerRow     = (int)(PageSize * component.Density);
            var distancePerInstance = PageSize / (float)instancesPerRow;

            renderData.Pages = new TerrainVegetationPage[pagesPerRow * pagesPerRow];
            var scaleRange = component.MaxScale - component.MinScale;

            for (var pz = 0; pz < pagesPerRow; pz++)
            {
                for (var px = 0; px < pagesPerRow; px++)
                {
                    var radius = PageSize * 0.5f;

                    var pagePosition = new Vector3(px * PageSize - terrainOffset, 0, pz * PageSize - terrainOffset);

                    var page = new TerrainVegetationPage();
                    renderData.Pages[pz * pagesPerRow + px] = page;

                    for (var iz = 0; iz < instancesPerRow; iz++)
                    {
                        for (var ix = 0; ix < instancesPerRow; ix++)
                        {
                            var position = pagePosition;

                            position.X += ix * distancePerInstance;
                            position.Z += iz * distancePerInstance;

                            position.X += (float)rng.NextDouble() * distancePerInstance * 2.0f - distancePerInstance;
                            position.Z += (float)rng.NextDouble() * distancePerInstance * 2.0f - distancePerInstance;

                            position.Y = terrain.GetHeightAt(position.X, position.Z);

                            var tx = (int)((position.X + terrainOffset) / terrain.Size * mask.Width);
                            var ty = (int)((position.Z + terrainOffset) / terrain.Size * mask.Height);

                            if (tx < 0 || tx >= mask.Width || ty < 0 || ty >= mask.Height)
                            {
                                continue;
                            }

                            var maskDensity = mask.GetPixel <Color>(tx, ty)[maskChannel] / 255.0;
                            if (rng.NextDouble() > maskDensity)
                            {
                                continue;
                            }

                            var normal = terrain.GetNormalAt(position.X, position.Z);
                            var slope  = 1.0f - Math.Abs(normal.Y);
                            if (slope < component.MinSlope || slope > component.MaxSlope)
                            {
                                continue;
                            }

                            var scale = (float)rng.NextDouble() * scaleRange + component.MinScale;

                            var rotation = Quaternion.RotationAxis(Vector3.UnitY, (float)rng.NextDouble() * MathUtil.TwoPi) * Quaternion.BetweenDirections(Vector3.UnitY, normal);

                            var scaling = new Vector3(scale);

                            Matrix.Transformation(ref scaling, ref rotation, ref position, out var transformation);

                            page.Instances.Add(transformation);
                        }
                    }

                    page.WorldPosition = pagePosition + new Vector3(radius, 0, radius);
                }
            }

            component.IsDirty = false;
        }
Esempio n. 7
0
        public override void Update()
        {
            if (Input.HasMouse)
            {
                ClickResult clickResult;
                Utils.ScreenPositionToWorldPositionRaycast(Input.MousePosition, Camera, this.GetSimulation(), out clickResult);

                bool isMoving = (Input.IsMouseButtonDown(MouseButton.Left) && lastClickResult.Type
                                 == ClickType.Ground && clickResult.Type == ClickType.Ground);

                bool isHighlit = (!isMoving && clickResult.Type == ClickType.Container);

                // Character continuous moving
                if (isMoving)
                {
                    lastClickResult.WorldPosition = clickResult.WorldPosition;
                    MoveDestinationEventKey.Broadcast(lastClickResult);
                }

                // Object highlighting
                if (isHighlit)
                {
                    ModelComponent modelComponentA = Highlight?.Get <ModelComponent>();
                    ModelComponent modelComponentB = clickResult.ClickedEntity.Get <ModelComponent>();

                    if (modelComponentA != null && modelComponentB != null)
                    {
                        int materialCount = modelComponentB.Model.Materials.Count;
                        modelComponentA.Model = modelComponentB.Model;
                        modelComponentA.Materials.Clear();

                        for (int i = 0; i < materialCount; i++)
                        {
                            modelComponentA.Materials.Add(i, HighlightMaterial);
                        }

                        modelComponentA.Entity.Transform.UseTRS      = false;
                        modelComponentA.Entity.Transform.LocalMatrix = modelComponentB.Entity.Transform.WorldMatrix;
                    }
                }
                else
                {
                    ModelComponent modelComponentA = Highlight?.Get <ModelComponent>();

                    if (modelComponentA != null)
                    {
                        modelComponentA.Entity.Transform.LocalMatrix = Matrix.Scaling(0);
                    }
                }
            }

            // Mouse-based camera rotation. Only enabled after you click the screen to lock your cursor, pressing escape cancels this
            foreach (PointerEvent pointerEvent in Input.PointerEvents.Where(x => x.EventType == PointerEventType.Pressed))
            {
                ClickResult clickResult;

                if (Utils.ScreenPositionToWorldPositionRaycast(pointerEvent.Position, Camera, this.GetSimulation(),
                                                               out clickResult))
                {
                    lastClickResult = clickResult;
                    MoveDestinationEventKey.Broadcast(clickResult);

                    if (ClickEffect != null && clickResult.Type == ClickType.Ground)
                    {
                        this.SpawnPrefabInstance(ClickEffect, null, 1.2f, Matrix.RotationQuaternion(Quaternion.BetweenDirections(Vector3.UnitY,
                                                                                                                                 clickResult.HitResult.Normal)) * Matrix.Translation(clickResult.WorldPosition));
                    }
                }
            }
        }
Esempio n. 8
0
        public override void Update()
        {
            // HACK: should probably not rely on accessing this UI component directly.
            if (_inGameScreenPageHandler == null)
            {
                var uiManager = SceneSystem.GetUIManagerFromRootScene();
                _inGameScreenPageHandler = uiManager.TopPageHandler as InGameScreenPageHandler;
                if (_inGameScreenPageHandler == null)
                {
                    // UI not loaded yet
                    return;
                }
            }
            if (!_inGameScreenPageHandler.IsTopMostScreen)
            {
                // Don't process any input, since it's probably in a sub-menu!
                return;
            }

            if (Input.HasMouse)
            {
                ClickResult clickResult;
                Utils.ScreenPositionToWorldPositionRaycast(Input.MousePosition, Camera, this.GetSimulation(), out clickResult);

                var isMoving = (Input.IsMouseButtonDown(MouseButton.Left) && lastClickResult.Type == ClickType.Ground && clickResult.Type == ClickType.Ground);

                var isHighlit = (!isMoving && clickResult.Type == ClickType.LootCrate);

                // Character continuous moving
                if (isMoving)
                {
                    lastClickResult.WorldPosition = clickResult.WorldPosition;
                    MoveDestinationEventKey.Broadcast(lastClickResult);
                }

                // Object highlighting
                if (isHighlit)
                {
                    var modelComponentA = Highlight?.Get <ModelComponent>();
                    var modelComponentB = clickResult.ClickedEntity.Get <ModelComponent>();

                    if (modelComponentA != null && modelComponentB != null)
                    {
                        var materialCount = modelComponentB.Model.Materials.Count;
                        modelComponentA.Model = modelComponentB.Model;
                        modelComponentA.Materials.Clear();
                        for (int i = 0; i < materialCount; i++)
                        {
                            modelComponentA.Materials.Add(i, HighlightMaterial);
                        }

                        modelComponentA.Entity.Transform.UseTRS      = false;
                        modelComponentA.Entity.Transform.LocalMatrix = modelComponentB.Entity.Transform.WorldMatrix;
                    }
                }
                else
                {
                    var modelComponentA = Highlight?.Get <ModelComponent>();
                    if (modelComponentA != null)
                    {
                        modelComponentA.Entity.Transform.LocalMatrix = Matrix.Scaling(0);
                    }
                }
            }

            // Mouse-based camera rotation. Only enabled after you click the screen to lock your cursor, pressing escape cancels this
            foreach (var pointerEvent in Input.PointerEvents.Where(x => x.EventType == PointerEventType.Pressed))
            {
                ClickResult clickResult;
                if (Utils.ScreenPositionToWorldPositionRaycast(pointerEvent.Position, Camera, this.GetSimulation(),
                                                               out clickResult))
                {
                    lastClickResult = clickResult;
                    MoveDestinationEventKey.Broadcast(clickResult);

                    if (ClickEffect != null && clickResult.Type == ClickType.Ground)
                    {
                        this.SpawnPrefabInstance(ClickEffect, null, 1.2f, Matrix.RotationQuaternion(Quaternion.BetweenDirections(Vector3.UnitY, clickResult.HitResult.Normal)) * Matrix.Translation(clickResult.WorldPosition));
                    }
                }
            }
        }
Esempio n. 9
0
        /// <summary>
        /// Spawns rockets in a grid
        /// </summary>
        protected override async Task Shoot(Entity targetEntity)
        {
            // Play shooting animation
            Drone.Animation.Shoot();

            // Wait a bit
            await Task.Delay(TimeSpan.FromSeconds(AnimationDelay));

            List <Projectile> projectiles = new List <Projectile>();

            Vector2 stepOffset = new Vector2(1.0f / ArraySize.X, 1.0f / ArraySize.Y) * ArrayExtent;

            // Generate random spawn position
            List <Vector2> spawnOffsets = new List <Vector2>();

            for (int y = 0; y < ArraySize.Y; y++)
            {
                float stepY = (ArraySize.Y == 0) ? 0.0f : (y / (float)(ArraySize.Y - 1) * 2.0f - 1.0f);
                for (int x = 0; x < ArraySize.X; x++)
                {
                    float   stepX       = (ArraySize.X == 0) ? 0.0f : (x / (float)(ArraySize.X - 1) * 2.0f - 1.0f);
                    Vector2 spawnOffset = new Vector2((stepOffset.X * stepX), (stepOffset.Y * stepY));
                    spawnOffsets.Add(spawnOffset);
                }
            }

            // Spawn in random order
            while (spawnOffsets.Count > 0)
            {
                // Recalculate directions and start position since drone might have moved
                var     position     = ProjectileSpawnPoint.Transform.WorldMatrix.TranslationVector;
                Vector3 up           = Drone.Entity.Transform.WorldMatrix.Up;
                Vector3 aimDirection = Drone.HeadDirection;
                Vector3 right        = Vector3.Normalize(Vector3.Cross(up, aimDirection));

                // Retrieve spawn position for this missile based on the offsets
                int     targetPositionIndex = random.Next(0, spawnOffsets.Count - 1);
                Vector2 spawnOffset         = spawnOffsets[targetPositionIndex];
                Vector3 spawnPosition       = position + spawnOffset.X * right + spawnOffset.Y * up;
                spawnPosition += aimDirection * ((float)random.NextDouble() - 0.5f) * 0.1f;
                spawnOffsets.RemoveAt(targetPositionIndex);

                // Spawn rocket
                var projectileEntity = ProjectilePrefab.Instantiate().Single();
                var projectile       = projectileEntity.Get <Projectile>();
                projectile.Owner = Drone.Entity;

                projectiles.Add(projectile);
                projectileEntity.Transform.Position = spawnPosition;
                projectileEntity.Transform.Rotation = Quaternion.BetweenDirections(Vector3.UnitZ, Drone.HeadDirection);

                // Random Pitch/Roll (relative to shooting direction)
                Vector2 randomDeviation = new Vector2((float)random.NextDouble(), (float)random.NextDouble());
                randomDeviation.X  = randomDeviation.X * SpreadAngle.Radians; // Pitch
                randomDeviation.Y *= MathUtil.TwoPi;                          // Roll
                projectileEntity.Transform.Rotation = projectileEntity.Transform.Rotation * Quaternion.RotationAxis(right, randomDeviation.X) * Quaternion.RotationAxis(aimDirection, randomDeviation.Y);

                var rocket = (projectile as RocketProjectile);
                if (targetEntity != null)
                {
                    rocket?.SetTarget(targetEntity.Transform.WorldMatrix.TranslationVector);
                }
                else
                {
                    rocket?.SetTarget(position + aimDirection * ShootingRange);
                }

                Drone.SceneSystem.SceneInstance.RootScene.Entities.Add(projectile.Entity);

                // Set initial direction
                Vector3 initialRocketDirection = Vector3.Transform(Vector3.UnitZ, projectileEntity.Transform.Rotation);
                projectile.SetDirection(initialRocketDirection);

                shootSound.PlayAndForget();

                await Task.Delay(2 + random.Next(0, 8));
            }
        }