示例#1
0
        public override void _PhysicsProcess(float delta)
        {
            var d = 2f;

            if (_isBeingKnockedback)
            {
                if (LinearVelocity.Length() <= d)
                {
                    _isBeingKnockedback = false;
                }
                else
                {
                    return;
                }
            }

            if (!isChasing())
            {
                return;
            }

            try
            {
                var toTarget = GlobalPosition.DirectionTo(_chasing.GlobalPosition);
                LinearVelocity = toTarget.Normalized() * 100;
                PlayAnimation(DirectionService.VelocityToDirection(LinearVelocity));
            }
            catch (ObjectDisposedException e)
            {
                _chasing = null;
            }
        }
示例#2
0
        private void ReflectAcrossNormal(Vector2 normalVector)
        {
            if (normalVector == Vector2.Zero)
            {
                return;
            }

            // Assuming n is the normal of the fixture at the point of the raycast contact
            // We just reflect the previous velocity accross the normal
            // Use angle - pi/2 for current angle

            float normalAngle = ((float)Math.Atan(normalVector.Y / normalVector.X) - (float)Math.PI / 2);

            Rotation += (2 * (normalAngle - (Rotation)));
            Rotation += (float)Math.PI;
            Vector2 oldvel = LinearVelocity;
            Vector2 tempVel;

            tempVel.X = (float)(LinearVelocity.Length() * Math.Sin(Rotation));
            tempVel.Y = -(float)(LinearVelocity.Length() * Math.Cos(Rotation));

            LinearVelocity = tempVel;
            // Manipulate velocity so that collisions reflect at 100% speed. Some weapons might not have this.
            LinearVelocity *= Math.Max(oldvel.Length() / LinearVelocity.Length(), 1f);

            futurePos = Position + (TimeKeeper.MsSinceInitialization - _lastTimeStamp) * LinearVelocity;

            CheckCollisions();
        }
示例#3
0
        /// <summary>
        /// Checks for collisions. Handles collisions and calls terminate() as necessary
        /// </summary>
        public virtual void CheckCollisions()
        {
            if (numRecursiveCalls == 5)
            {
                Terminate();
                return;
            }

            numRecursiveCalls++;//Prevents stack overflow that can result when projectiles get stuck between very close reflectors


            if (LinearVelocity.Length() < 1e-3)//Might need to tweak this tolerance
            {
                //When the projectile velocity becomes very small,
                //the raycast future position becomes tiny and it
                //becomes almost impossible to collide. For now,
                //switch to a point test. TODO: Convert to multi-point test, testing bounds of projectile
                var hitFixtures = _world.TestPointAll(Position);
                foreach (var f in hitFixtures)
                {
                    if (f.Body.UserData != null)
                    {
                        HandleCollision((CollisionDataObject)f.Body.UserData, Vector2.Zero);
                    }
                }
            }

            if (futurePos != Position)
            {
                _world.RayCast(RayCastCallback, Position, futurePos);
            }
        }
示例#4
0
    public override void _PhysicsProcess(float delta)
    {
        if (_picked)
        {
            var axis = (_touchPos - GlobalPosition + _offset.Rotated(GlobalRotation)).Normalized();

            LinearVelocity += axis * _acceleration * delta;

            if (LinearVelocity.Length() > _VelocityLimit)
            {
                LinearVelocity = LinearVelocity.Clamped(_VelocityLimit);
            }
        }
    }
示例#5
0
        public SpeedInfo getSpeed()
        {
            Vector2 direction = new Vector2((float)Math.Cos(Rotation), (float)Math.Sin(Rotation));
            float   angleCos  = 0;

            if (LinearVelocity.Length() != 0 && direction.Length() != 0)
            {
                angleCos = getAngleCos(LinearVelocity, direction);
            }

            Vector2 speed = direction * angleCos * LinearVelocity.Length();

            return(new SpeedInfo()
            {
                speed = speed,
                sideSpeed = LinearVelocity - speed,
                direction = direction,
                angleCos = angleCos
            });
        }
示例#6
0
        /// <summary>
        /// Applies buoyancy, drag and angular drag caused by water
        /// </summary>
        public void ApplyWaterForces()
        {
            //buoyancy
            Vector2 buoyancy = new Vector2(0, Mass * 9.6f);

            Vector2 dragForce = Vector2.Zero;

            if (LinearVelocity.LengthSquared() > 0.00001f)
            {
                //drag
                Vector2 velDir = Vector2.Normalize(LinearVelocity);

                float vel  = LinearVelocity.Length() * 2.0f;
                float drag = vel * vel * Math.Max(height + radius * 2, height);
                dragForce = Math.Min(drag, Mass * 500.0f) * -velDir;
            }

            ApplyForce(dragForce + buoyancy);
            ApplyTorque(body.AngularVelocity * body.Mass * -0.08f);
        }
示例#7
0
        //update the rigidbodies position based on currently applied force, velocity, and gravity
        public void Step(float dt, Vector2D gravity)
        {
            //tick the cooldown
            if (multiUseCooldown > 0.0f)
            {
                multiUseCooldown -= dt;
            }

            //only update position if the object can move
            if (moveable)
            {
                Vector2D acceleration = Force / Mass;
                if (obeysGravity)
                {
                    acceleration += gravity;
                }

                //update velocity, locking it below maximum speed
                LinearVelocity = LinearVelocity + acceleration * dt;
                if (LinearVelocity.Length() > maxSpeed)
                {
                    LinearVelocity = LinearVelocity.Normalised() * maxSpeed;
                }


                //Update position based on velocity (uses Runge Kutta integration)
                Vector2D k1 = LinearVelocity + acceleration * dt;
                Vector2D k2 = LinearVelocity + k1 * (dt / 2);
                Vector2D k3 = LinearVelocity + k2 * (dt / 2);
                Vector2D k4 = LinearVelocity + k3 * dt;
                SetPosition(Position + (k1 + k2 * 2 + k3 * 2 + k4) * (dt / 6));

                //reset force
                Force.X = 0;
                Force.Y = 0;

                //reset collision information (assumes collision detection will take place immediately after stepping all rigidbodies)
                otherBody       = null;
                collisionNormal = null;
            }
        }
示例#8
0
    // Called every frame. 'delta' is the elapsed time since the previous frame.
    public override void _Process(float delta)
    {
        // Get all Node bodies that are currently colliding with the Ball
        Godot.Collections.Array bodies = GetCollidingBodies();

        // The base level class is Node2D, this is why the body variable is being initiliazed as the Node2D type
        foreach (Node2D body in bodies)
        {
            // Check if the collided body is a StaticBody2D type and if the Node is part of the "Bricks" group
            if (body is StaticBody2D hit && hit.IsInGroup("Bricks"))
            {
                // Get the World Node and increment the Score by 10
                GetNode <World>("/root/World").Score += 10;
                // Queue Node for deletion at the end of the current frame
                hit.QueueFree();
            }

            // Check if the Node's name is "Paddle"
            if (body.Name.Equals("Paddle"))
            {
                // Get the speed at which the Ball is travelling
                float currentSpeed = LinearVelocity.Length();
                // Reference to the anchor right below the Paddle object
                Position2D anchor = body.GetNode <Position2D>("Anchor");
                // Get the direction that the ball is travelling in relative to the anchor
                Vector2 direction = Position - anchor.GlobalPosition;
                // Normalize (value of 0-1) the direction and multiply it by the minimum value of the current speed + the speedup constant, or the maximum speed
                Vector2 boostVelocity = direction.Normalized() * Math.Min(currentSpeed + speedUp, MAXSPEED);
                // Set the Ball's LinearVelocity to the new velocity
                LinearVelocity = boostVelocity;
            }
        }
        // If the position of the Ball's Y position exceeds the extend of the ViewPort's Y position
        if (Position.y > GetViewportRect().End.y)
        {
            // Queue the Ball for deletion
            QueueFree();
        }
    }
示例#9
0
    void TriggerJumpDrive()
    {
        var overlaps = overlapArea2D.GetOverlappingAreas();

        foreach (Area2D area in overlaps)
        {
            if (area is WarpGate)
            {
                WarpGate warpGate = area as WarpGate;
                string   departureSolarSystemName = CurrentSolarSystemName;
                bool     warpSuccess = warpGate.TryTeleportShip(this, out string arrivalSolarSystemName, out float jumpCost);
                if (warpSuccess)
                {
                    float jumpSpeedOverLimit = Mathf.Max(0, LinearVelocity.Length() - safeJumpSpeed);
                    ReceiveDamage(jumpSpeedOverLimit * jumpVelocityDamageMultiplier);
                    RecordJumpCost(jumpCost);
                    //GD.Print("Jumpcost: " + jumpCost);

                    OnShipWarped?.Invoke(this, departureSolarSystemName, arrivalSolarSystemName);
                }
            }
        }
    }
示例#10
0
        protected override void Update(float dt)
        {
            if (TimeDeath > 0 && TimeDeath < World.Time)
            {
                Die();
            }

            if (World.DistanceOutOfBounds(Position) > 0)
            {
                var speed = LinearVelocity.Length();
                if (Position != Vector2.Zero)
                {
                    LinearVelocity = Vector2.Normalize(Vector2.Zero - Position) * speed;
                }
            }

            if (Drag != 0)
            {
                LinearVelocity *= (1 - Drag * dt);
            }

            base.Update(dt);
        }
        public String ConcealDetails()
        {
            // Revealed entities cannot be concealed if they
            // Are controlled (i.e. moving)
            // Are near a controlled entity
            // Are "working" (refining, assembling, oxy creating, battery charging)
            // Are needed as a spawn point for a logged-in player

            String result = "";

            // Ids
            result += "\"" + DisplayName + "\" - " + EntityId + "\n";

            // Owners
            // TODO: show owner names instead of playerIds
            result += "  Owners: TODO\n";

            /*
             * if (BigOwners != null) {
             *  result += "  Owners: " + String.Join(", ", BigOwners) + "\n";
             * }
             * else {
             *  Log.Error("Grid had null BigOwners", "ReceiveRevealedGridsResponse");
             * }
             * */

            // Position
            result += "  Position: " + Position.ToRoundedString() + "\n";

            // Concealability
            if (IsConcealable)
            {
                result += "  Concealable:\n";
                //return result;
            }
            else
            {
                result += "  Not concealable:\n";
            }

            //result += "    Frequently Updated:\n";
            if (OldEnoughForConceal)
            {
                result += "      Y Not recently revealed\n";
            }
            else
            {
                result += "      N Too recently revealed\n";
            }

            // Control
            if (IsControlled)
            {
                result += "      N Controlled:\n";

                if (IsPiloted)
                {
                    result += "        Piloted";
                }
                else if (IsMoving)
                {
                    result += "        Moving at " +
                              System.Math.Truncate(LinearVelocity.Length()) + " m/s";
                }
                else if (RecentlyMoved)
                {
                    result += "        Recently moved until " + RecentlyMovedEnds;
                }

                result += "\n";
            }
            else
            {
                result += "      Y Not Controlled.\n";
            }

            // Observed
            if (IsObserved)
            {
                result += "      N Observed by:\n";
                foreach (long id in EntitiesViewedBy.Keys)
                {
                    result += "            " + id + "\n";
                }
            }
            else
            {
                result += "      Y Not Observed.\n";
            }

            // Spawn
            // TODO: show owner names instead of playerIds
            // TODO: actually implement updates to these details
            if (NeededForSpawn)
            {
                result += "      N Needed for spawn.\n";

                /*
                 * result += "    Needed as a spawn point by:\n";
                 * foreach (long id in SpawnablePlayers) {
                 *  result += "      " + id;
                 * }
                 */
            }
            else
            {
                result += "      Y Not Needed for spawn.\n";
            }

            //result += "    Infrequently Updated:\n";

            // Working
            // TODO: send block entity ids
            // TODO: show block types instead of entity Ids
            if (IsProducing)
            {
                result += "      N Producing:\n";
                //foreach (long id in ProductionBlocks.Keys) {
                //    result += "      " + id + "\n";
                //}
            }
            else
            {
                result += "      Y Not Producing.\n";
            }

            if (IsChargingBatteries)
            {
                result += "      N Charging Batteries.\n";
            }
            else
            {
                result += "      Y Not Charging Batteries.\n";
            }

            // NearAsteroid
            if (IsInAsteroid)
            {
                result += "      N Inside Asteroid.\n";
            }
            else
            {
                result += "      Y Not in Asteroid.\n";
            }

            // Blocked
            if (IsRevealBlocked)
            {
                result += "      N Entities within bounding box.\n";
            }
            else
            {
                result += "      Y No entities in bounding box.\n";
            }

            return(result);
        }
示例#12
0
        /*
         * private void MarkDetecting(ObservableEntity e) {
         *  long id = e.EntityId;
         *  if (EntitiesDetecting.ContainsKey(id)) {
         *      Log.Error("Already added " + id, "MarkDetecting");
         *      return;
         *  }
         *
         *  Log.Error("Adding " + id, "MarkDetecting");
         *  EntitiesDetecting.Add(id, e);
         *  e.MarkDetectedBy(this);
         * }
         *
         * private void UnmarkDetecting(ObservableEntity e) {
         *  long id = e.EntityId;
         *  if (!EntitiesDetecting.ContainsKey(id)) {
         *      Log.Error("Not stored " + id, "UnmarkDetecting");
         *      return;
         *  }
         *
         *  Log.Error("Removing " + id, "UnmarkDetecting");
         *  EntitiesDetecting.Remove(id);
         *  e.UnmarkDetectedBy(this);
         * }
         *
         * private void UnmarkDetectingAll() {
         *  Log.Trace("Unmarking all Detected entities", "UnmarkDetectingAll");
         *  foreach (ObservableEntity e in EntitiesDetecting.Values) {
         *      e.UnmarkDetectedBy(this);
         *  }
         *  EntitiesDetecting.Clear();
         * }
         *
         * private void MarkReceivingFrom(ObservableEntity e) {
         *  long id = e.EntityId;
         *  if (EntitiesReceivingFrom.ContainsKey(id)) {
         *      Log.Error("Already added " + id, "ReceivingFrom");
         *      return;
         *  }
         *
         *  Log.Error("Adding " + id, "ReceivingFrom");
         *  EntitiesReceivingFrom.Add(id, e);
         *  e.MarkBroadcastingTo(this);
         * }
         *
         * private void UnmarkReceivingFrom(ObservableEntity e) {
         *  long id = e.EntityId;
         *  if (!EntitiesReceivingFrom.ContainsKey(id)) {
         *      Log.Error("Not stored " + id, "UnmarkReceivingFrom");
         *      return;
         *  }
         *
         *  Log.Error("Removing " + id, "UnmarkReceivingFrom");
         *  EntitiesReceivingFrom.Remove(id);
         *  e.UnmarkBroadcastingTo(this);
         * }
         *
         * private void UnmarkReceivingAll() {
         *  Log.Trace("Unmarking all comm receiving entities", "UnmarkReceivingAll");
         *  foreach (ObservableEntity e in EntitiesReceivingFrom.Values) {
         *      e.UnmarkBroadcastingTo(this);
         *  }
         *  EntitiesReceivingFrom.Clear();
         * }
         */

        #endregion
        #region Describe

        public String ObservationDetails()
        {
            String result = "";

            // Ids
            result += DisplayName + "\" - " + EntityId + "\n";

            // Owners
            // TODO: show owner names instead of playerIds
            result += "  Owners: TODO\n";

            /*
             * if (BigOwners != null) {
             *  result += "  Owners: " + String.Join(", ", BigOwners) + "\n";
             * }
             * else {
             *  Log.Error("Grid had null BigOwners", "ReceiveRevealedGridsResponse");
             * }
             * */

            // Position
            result += "  Position: " + Position.ToRoundedString() + "\n";

            // Control
            if (IsControlled)
            {
                result += "  Controlled:\n";

                if (IsMoving)
                {
                    result += "    Moving at " +
                              System.Math.Truncate(LinearVelocity.Length()) + " m/s";
                }
                else if (RecentlyMoved)
                {
                    result += "    Recently moved until " + RecentlyMovedEnds;
                }

                result += "\n";
            }
            else
            {
                result += "  Not Controlled. (Shouldn't be viewing anything.)\n";
            }

            // Last check details
            if (!PreviouslyObserving)
            {
                result += "  Hasn't yet had an observe check.\n";
            }
            //else {
            result += "  Last View Check at pos: " + LastObservingPosition.ToRoundedString() + "\n";
            result += "  Distance from last view check: " + DistanceSinceLastObservingCheck + "\n";
            result += "  Last View Check at time: " + LastObservingTime.ToLocalTime() + "\n";
            result += "  View radius: " + ViewDistance + "\n";
            result += "  Viewed entities: \n";
            //}



            // TODO: fetch the entities ingame on client side so we can have their details
            foreach (long id in EntitiesViewing.Keys)
            {
                result += "    " + id + "\n";
            }

            return(result);
        }
示例#13
0
        public virtual void Update(IGameTimeService gameTime)
        {
            Pilot.Update(gameTime);

            BodyBehaviors.ForEach(b => b.Update(gameTime));

            // Time dependent updates (e.g. shields)

            var energyRegexRate = ShipStats.EnergyRegenRate * StatBonuses[StatBonusTypes.EnergyRegen] /
                                  (1 + Debuffs[DebuffTypes.EnergyRegen]);

            var amount = (int)(gameTime.ElapsedMilliseconds * energyRegexRate);

            ChangeEnergy(amount);
            //WARNING: Might have to fix on fast computers, if update is too fast, int might be rounded down

            Shields.Update(gameTime.TotalMilliseconds);
            Debuffs.Update(gameTime.TotalMilliseconds);

            // Turning
            // Divided because units are radians/second
            var elapsedTime = ShipStats.TurnRate * StatBonuses[StatBonusTypes.TurnRate];

            if (IsTurningCounterClockwise)
            {
                AngularVelocity = -elapsedTime;
            }
            else if (IsTurningClockwise)
            {
                AngularVelocity = elapsedTime;
            }
            else
            {
                AngularVelocity = 0;
            }

            // Increase Drag if ship is going faster than top speed

            float limitVal = (ShipStats.TopSpeed + StatBonuses[StatBonusTypes.TopSpeed]) / (1 + Debuffs[DebuffTypes.TopSpeed]);

            if (Thrusting)
            {
                limitVal *= ShipStats.BoostBonus;
            }

            LinearDamping = LinearVelocity.Length() >= limitVal ? _speedDampValue : 0.0001f;

            // Check if Outside System

            //// Check if you're outside of the wall // Broken :(
            //if (Vector2.Distance(Vector2.Zero, ConvertUnits.ToDisplayUnits(Position)) > _borderManager.sizeOfSystem
            //    && GameStateManager.getState() == GameStates.space)
            //{
            //    Console.WriteLine("Outside of System");
            //    Vector2 pos;
            //    //pos.X = (float) (Math.Cos(MathHelper.ToRadians(Position.X))*(BorderManager.sizeOfSystem + 700));
            //    //pos.Y = (float) (Math.Sin(MathHelper.ToRadians(Position.Y))*(BorderManager.sizeOfSystem + 700));
            //    //Position = ConvertUnits.ToSimUnits(pos);
            //    Position = new Vector2(1,1);
            //    LinearVelocity *= -1;
            //}

            foreach (Weapon w in _weapons)
            {
                w.Update(gameTime);
            }

            if (!SendPositionUpdates &&
                gameTime.TotalMilliseconds - PositionUpdateDisableTimestamp > PositionUpdateDisableDuration)
            {
                SendPositionUpdates = true;
            }

            lastTimeStamp = gameTime.ElapsedMilliseconds;
        }