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; } }
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(); }
/// <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); } }
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); } } }
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 }); }
/// <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); }
//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; } }
// 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(); } }
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); } } } }
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); }
/* * 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); }
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; }