private static void FindCrossedTilesInternal_NoBevel(fix2 start, fix2 end, NativeList <int2> crossedTiles) { Line2D line = new Line2D(start, end); int vDir = (int)sign(end.y - start.y); int y = vDir == 1 ? floorToInt(start.y) : ceilToInt(start.y); int endY = vDir == 1 ? floorToInt(end.y) : ceilToInt(end.y); int yOffset = vDir == 1 ? 0 : -1; int x1 = (int)start.x; int x2; while (y != endY) { x2 = (int)line.SolveX(y + vDir); AppendHorizontalTiles(crossedTiles, y + yOffset, x1, x2); x1 = x2; y += vDir; } x2 = (int)end.x; AppendHorizontalTiles(crossedTiles, y + yOffset, x1, x2); }
/// <summary> /// Constructs a new 3d vector. /// </summary> /// <param name="x">X component of the vector.</param> /// <param name="yz">Y and Z components of the vector.</param> /// <param name="w">W component of the vector.</param> public fix4(fix x, fix2 yz, fix w) { this.x = x; this.y = yz.x; this.z = yz.y; this.w = w; }
private bool VerifyEntityForParameters(Entity entity) { GameActionParameterEntity.Description paramDescription = CurrentContext.GetQueryParam <GameActionParameterEntity.Description>(); if (!paramDescription.IncludeSelf && entity == Cache.LocalPawn) { return(false); } if (paramDescription.RequiresAttackableEntity) { if (!Cache.SimWorld.HasComponent <Health>(entity)) { return(false); } } if (paramDescription.CustomPredicate != null) { if (paramDescription.CustomPredicate(SimWorld, entity) == false) { return(false); } } fix2 targetPos = Cache.SimWorld.GetComponent <FixTranslation>(entity); fix squaredDistance = fixMath.distancesq(Cache.LocalPawnPosition, targetPos); if (squaredDistance > paramDescription.RangeFromInstigator * paramDescription.RangeFromInstigator) { return(false); } return(true); }
private void DestroyTiles(fix2 position, fix radius) { TileWorld tileWorld = CommonReads.GetTileWorld(Accessor); NativeList <int2> tiles = new NativeList <int2>(Allocator.Temp); var transformTileRequests = GetSingletonBuffer <SystemRequestTransformTile>(); Job.WithCode(() => { TilePhysics.GetAllTilesWithin(position, radius, tiles); for (int i = 0; i < tiles.Length; i++) { Entity tileEntity = tileWorld.GetEntity(tiles[i]); TileFlagComponent tileFlags = tileWorld.GetFlags(tileEntity); if (!tileFlags.IsOutOfGrid && tileFlags.IsDestructible) { // remove ladder and terrain flags tileFlags.Value &= ~(TileFlags.Ladder | TileFlags.Terrain); transformTileRequests.Add(new SystemRequestTransformTile() { Tile = tiles[i], NewTileFlags = tileFlags }); } } }).Run(); }
/// <summary> /// Constructs a new 3d vector. /// </summary> /// <param name="xy">X and Y components of the vector.</param> /// <param name="zw">Z and W components of the vector.</param> public fix4(fix2 xy, fix2 zw) { this.x = xy.x; this.y = xy.y; this.z = zw.x; this.w = zw.y; }
/// <summary> /// Constructs a new 3d vector. /// </summary> /// <param name="x">X component of the vector.</param> /// <param name="y">Y and Z components of the vector.</param> /// <param name="zw">W component of the vector.</param> public fix4(fix x, fix y, fix2 zw) { this.x = x; this.y = y; this.z = zw.x; this.w = zw.y; }
/// <summary> /// Constructs a new 3d vector. /// </summary> /// <param name="xy">X and Y components of the vector.</param> /// <param name="z">Z component of the vector.</param> /// <param name="w">W component of the vector.</param> public fix4(fix2 xy, fix z, fix w) { this.x = xy.x; this.y = xy.y; this.z = z; this.w = w; }
void IWorldUIPointerClickHandler.OnPointerClick() { if (!Cache.LocalPawnAlive) { return; } fix2 entityPosition = SimWorld.GetComponent <FixTranslation>(SimEntity); fix2 pawnPosition = Cache.LocalPawnPosition; if (fixMath.distancemanhattan(entityPosition, pawnPosition) > SimulationGameConstants.InteractibleMaxDistanceManhattan) { PresentationHelpers.RequestFloatingText((Vector2)entityPosition, "Trop loin", Color.white); return; } switch (_clickAction) { case ClickAction.OpenChest: if (InteractableInventoryDisplaySystem.Instance != null) { InteractableInventoryDisplaySystem.Instance.SetupDisplayForInventory(SimEntity); } break; case ClickAction.TriggerSignal: PresentationHelpers.RequestFloatingText((Vector2)entityPosition, "Click", Color.white); SimWorld.SubmitInput(new SimPlayerInputClickSignalEmitter(SimEntity)); break; } }
/// <summary> /// Given a displacement and a gravity, returns the smallest launch required launch velocity for a projectile. /// <para/> /// <b>NB:</b> If gravity is 0, the return vector will be 0. /// </summary> /// <param name="dx">The horizontal displacement. finalPosition.x - startPosition.x</param> /// <param name="dy">The vertical displacement. finalPosition.y - startPosition.y</param> /// <param name="g">The 2D gravity.</param> /// <returns>The smallest launch required launch velocity.</returns> public static fix2 SmallestLaunchVelocity(fix dx, fix dy, fix2 g) { // No gravity ? return 0 if (lengthsq(g) < global::fix.Epsilon) { return(new fix2(0, 0)); } // Gravity already 1D ? Don't rotate if (g.x == 0) { return(SmallestLaunchVelocity(dx, dy, g.y)); } // Rotate all the values so the gravity points downward fix gravityAngleAdjustment = angle2d(g) + global::fix.PiOver2; fix2x2 rot = fix2x2.Rotate(-gravityAngleAdjustment); fix2 d = new fix2(dx, dy); d = mul(rot, d); g = mul(rot, g); fix2 result = SmallestLaunchVelocity(d.x, d.y, g.y); // Rotate the result in opposite direction return(mul(inverse(rot), result)); }
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { SerializedProperty xProp = property.FindPropertyRelative(nameof(fix2.x)).FindPropertyRelative(nameof(fix.RawValue)); SerializedProperty yProp = property.FindPropertyRelative(nameof(fix2.y)).FindPropertyRelative(nameof(fix.RawValue)); fix xVal; fix yVal; xVal.RawValue = xProp.longValue; yVal.RawValue = yProp.longValue; fix2 oldFixVec = new fix2(xVal, yVal); // Using BeginProperty / EndProperty on the parent property means that // prefab override logic works on the entire property. EditorGUI.BeginProperty(position, label, property); // Editor Field Vector2 oldVec = oldFixVec.ToUnityVec(); Vector2 newVec = EditorGUI.Vector2Field(position, label, oldVec); // Change ? if (oldVec != newVec) { fix2 newFixVec = newVec.ToFixVec(); xProp.longValue = newFixVec.x.RawValue; yProp.longValue = newFixVec.y.RawValue; } EditorGUI.EndProperty(); }
protected override void OnUpdate() { Entities .ForEach((Entity nextLevelPortal, ref NextLevelPortalData nextLevelPortalData, in FixTranslation portalPos) => { bool allPlayersInsidePortal = true; fix2 portalPosition = portalPos.Value; fix2 nextLevelPosition = nextLevelPortalData.NextLevelPos; Entities .ForEach((Entity playerController, in PersistentId playerID, in ControlledEntity pawnControlled) => { if (allPlayersInsidePortal) { fix2 pawnPosition = GetComponent <FixTranslation>(pawnControlled).Value; if ((pawnPosition.x > (portalPosition.x + (fix)0.5)) || (pawnPosition.x < (portalPosition.x - (fix)0.5)) || (pawnPosition.y > (portalPosition.y + (fix)0.5)) || (pawnPosition.y < (portalPosition.y - (fix)0.5))) { allPlayersInsidePortal = false; } } }) .WithoutBurst() .Run(); if (allPlayersInsidePortal) { Entities .ForEach((Entity playerController, in PersistentId playerID, in ControlledEntity pawnControlled) => { SetComponent(pawnControlled.Value, new FixTranslation() { Value = nextLevelPosition }); })
/// <summary> /// Transforms the vector by the matrix. /// </summary> /// <param name="v">FixVector2 to transform. Considered to be a column vector for purposes of multiplication.</param> /// <param name="matrix">FixMatrix to use as the transformation.</param> /// <param name="result">Column vector product of the transformation.</param> public static void Transform(ref fix3 v, ref fix2x3 matrix, out fix2 result) { #if !WINDOWS result = new fix2(); #endif result.x = matrix.M11 * v.x + matrix.M12 * v.y + matrix.M13 * v.z; result.y = matrix.M21 * v.x + matrix.M22 * v.y + matrix.M23 * v.z; }
/// <summary> /// Transforms the vector by the matrix. /// </summary> /// <param name="v">FixVector2 to transform. Considered to be a row vector for purposes of multiplication.</param> /// <param name="matrix">FixMatrix to use as the transformation.</param> /// <param name="result">Row vector product of the transformation.</param> public static void Transform(ref fix3 v, ref fix3x2 matrix, out fix2 result) { #if !WINDOWS result = new fix2(); #endif result.x = v.x * matrix.M11 + v.y * matrix.M21 + v.z * matrix.M31; result.y = v.x * matrix.M12 + v.y * matrix.M22 + v.z * matrix.M32; }
public static fix2 rotateTowards(fix2 currentVector, fix targetAngle, fix maxDeltaAngle) { fix angle = angle2d(currentVector); fix newAngle = moveTowardsAngle(angle, targetAngle, maxDeltaAngle); return(rotate(currentVector, newAngle - angle)); }
public static fix TravelDurationApprox(fix2 velocity, fix2 gravity, fix traveledDistance, fix precision) { if (traveledDistance <= global::fix.Epsilon) // if distance 0, already reached! { return(0); } fix vl2 = lengthsq(velocity); fix gl2 = lengthsq(gravity); if (vl2 + gl2 < global::fix.Epsilon * 2) // if moving or accelerating to slow, takes infinit time { return(global::fix.MaxValue); } // Try approximating the needed travel duration. Slowly getting closer to the real value // NB: With a precision of 0.01f, results usually take between 8 and 20 iterations // WHY ? Why not find the actual formula for this? Because it's hell'a complicated. Try to isolate X in the 'TraveledDistance' formula if you want. fix time = 5 + sqrt(traveledDistance / max(gl2, (fix)0.0001f)); fix radius = time * global::fix.Half; bool maxRadiusSet = false; int iterations = 0; while (radius > precision) { var dist = Trajectory.TravelDistance(velocity, gravity, time); if (dist > traveledDistance) { time -= radius; maxRadiusSet = true; } else { if (!maxRadiusSet) { time *= 2; radius *= 2; } else { time += radius; } } radius *= maxRadiusSet ? global::fix.Half : 1; iterations++; } //Log.Info($"Iterations: {iterations}"); return(time); }
/// <summary> /// Transforms the vector by the matrix. /// </summary> /// <param name="v">FixVector2 to transform. Considered to be a row vector for purposes of multiplication.</param> /// <param name="matrix">FixMatrix to use as the transformation.</param> /// <param name="result">Row vector product of the transformation.</param> public static void Transform(ref fix2 v, ref fix2x3 matrix, out fix3 result) { #if !WINDOWS result = new fix3(); #endif result.x = v.x * matrix.M11 + v.y * matrix.M21; result.y = v.x * matrix.M12 + v.y * matrix.M22; result.z = v.x * matrix.M13 + v.y * matrix.M23; }
/// <summary> /// Transforms the vector by the matrix. /// </summary> /// <param name="v">FixVector2 to transform. Considered to be a column vector for purposes of multiplication.</param> /// <param name="matrix">FixMatrix to use as the transformation.</param> /// <param name="result">Column vector product of the transformation.</param> public static void Transform(ref fix2 v, ref fix3x2 matrix, out fix3 result) { #if !WINDOWS result = new fix3(); #endif result.x = matrix.M11 * v.x + matrix.M12 * v.y; result.y = matrix.M21 * v.x + matrix.M22 * v.y; result.z = matrix.M31 * v.x + matrix.M32 * v.y; }
/// <summary> /// Rotate the vector v by the given radian value /// </summary> public static fix2 rotate(fix2 v, fix radians) { fix sin = fixMath.sin(radians); fix cos = fixMath.cos(radians); return(new fix2( (cos * v.x) - (sin * v.y), // x (sin * v.x) + (cos * v.y))); // y }
public static fix2 clampLength(fix2 v, fix min, fix max) { fix l = length(v); if (l <= global::fix.Epsilon) { return(new fix2(min, 0)); } return(clamp(l, min, max) * (v / l)); }
/// <summary> /// Transforms the vector by the matrix. /// </summary> /// <param name="v">FixVector2 to transform.</param> /// <param name="matrix">FixMatrix to use as the transformation.</param> /// <param name="result">Product of the transformation.</param> public static void Transform(ref fix2 v, ref fix2x2 matrix, out fix2 result) { fix vX = v.x; fix vY = v.y; #if !WINDOWS result = new fix2(); #endif result.x = vX * matrix.M11 + vY * matrix.M21; result.y = vX * matrix.M12 + vY * matrix.M22; }
public static void RaycastAll(fix2 start, fix2 end, fix bevel, NativeList <int2> crossedTiles) { int2 tileStart = int2((int)start.x, (int)start.y); int2 tileEnd = int2((int)end.x, (int)end.y); // Same tile optim if (tileStart.Equals(tileEnd)) { crossedTiles.Add(tileStart); return; } // Only 1 axis optim int2 v = tileEnd - tileStart; if (v.x == 0) { AppendVerticalTiles(crossedTiles, tileStart.x, tileStart.y, tileEnd.y); return; } if (v.y == 0) { AppendHorizontalTiles(crossedTiles, tileStart.y, tileStart.x, tileEnd.x); return; } bool rotateOptim = abs(v.y) > abs(v.x); if (rotateOptim) { start = rotate90(start); end = rotate90(end); } if (bevel > 0) { FindCrossedTilesInternal_WithBevel(start, end, bevel, crossedTiles); } else { FindCrossedTilesInternal_NoBevel(start, end, crossedTiles); } if (rotateOptim) { for (int i = 0; i < crossedTiles.Length; i++) { crossedTiles[i] = rotate270(crossedTiles[i]); } } return; }
protected override void OnUpdate() { Entity playerGroupEntity = GetSingletonEntity <PlayerGroupDataTag>(); fix memberOffset = GetComponent <PlayerGroupSpacing>(playerGroupEntity); fix2 playerGroupPosition = GetComponent <FixTranslation>(playerGroupEntity); fix deltaTime = Time.DeltaTime; Entities.ForEach((ref PhysicsVelocity velocity, in FixTranslation position, in PlayerGroupMemberIndex playerGroupIndex) => { fix2 playerDestination = playerGroupPosition + new fix2(playerGroupIndex.Value * -memberOffset); velocity.Linear.x = (playerDestination.x - position.Value.x) / deltaTime; }).Run();
protected override void OnUpdate() { HandleHookContacts(); var ecb = _ecbSytem.CreateCommandBuffer(); Entities .WithAll <PhysicsVelocity>() .ForEach((Entity entity, ref HookData hookData, in FixTranslation position) => { bool destroy = false; // If hook is uninitialized, initialize it if (hookData.State == HookData.EState.Uninitialized) { hookData.StartPosition = position; hookData.State = HookData.EState.TravelingForward; } // If hook is traveling back (after contact), set its velocity and the contact entity if (hookData.State == HookData.EState.TravelingBack) { fix2 d = hookData.StartPosition - position; fix dLength = length(d); if (dLength < (fix)0.25) { destroy = true; } else { fix2 dir = d / dLength; var newVelocity = new PhysicsVelocity(hookData.TravelBackSpeed * dir); SetComponent(entity, newVelocity); // give same velocity to captured entity if (HasComponent <PhysicsVelocity>(hookData.TouchedEntity)) { SetComponent(hookData.TouchedEntity, newVelocity); } } } if (destroy) { ecb.DestroyEntity(entity); } }).Run(); }
public static fix2 moveTowards(fix2 current, fix2 target, fix maxDistanceDelta) { fix2 delta = target - current; fix sqdist = lengthsq(delta); if (sqdist == 0 || sqdist <= maxDistanceDelta * maxDistanceDelta) { return(target); } fix dist = sqrt(sqdist); fix2 dir = delta / dist; return(current + (dir * maxDistanceDelta)); }
public static bool OverlapPoint(ISimGameWorldReadWriteAccessor accessor, fix2 position, NativeList <OverlapPointHit> outHits, Entity ignoreEntity = default) { var physicsSystem = accessor.GetExistingSystem <PhysicsWorldSystem>(); OverlapPointInput pointDistanceInput = OverlapPointInput.Default; pointDistanceInput.Position = (float2)position; if (ignoreEntity != Entity.Null) { pointDistanceInput.Ignore = new IgnoreHit(physicsSystem.GetPhysicsBodyIndex(ignoreEntity)); } return(physicsSystem.PhysicsWorld.OverlapPoint(pointDistanceInput, ref outHits)); }
private static void FindCrossedTilesInternal_WithBevel(fix2 start, fix2 end, fix bevel, NativeList <int2> crossedTiles) { Line2D line = new Line2D(start, end); int startX = (int)start.x; int endX = (int)end.x; int hDir = sign(endX - startX); int m = startX; fix x1; fix x2; if (hDir == 1) { x1 = start.x; x2 = max(start.x, (m + 1) - bevel); } else { x1 = min(start.x, m + bevel); x2 = start.x; } while (m != endX) { AppendVerticalTiles(crossedTiles, m, (int)line.SolveY(x1), (int)line.SolveY(x2)); m += hDir; x1 = m + bevel; x2 = (m + 1) - bevel; } if (hDir == 1) { x1 = min(x1, end.x); x2 = end.x; } else { x1 = end.x; x2 = max(x2, end.x); } AppendVerticalTiles(crossedTiles, m, (int)line.SolveY(x1), (int)line.SolveY(x2)); }
private void HandleDirectionalMove() { fix2 input = fix2.zero; bool up = Input.GetKey(KeyCode.W); bool down = Input.GetKey(KeyCode.S); bool left = Input.GetKey(KeyCode.A); bool right = Input.GetKey(KeyCode.D); if (_muteVerticalInputUntilRelease && !up && !down) { _muteVerticalInputUntilRelease = false; } if (UIStateMachineController.Instance.CurrentSate.Type == UIStateType.Gameplay) { if (right) { input.x += 1; } if (left) { input.x += -1; } if (up && !_muteVerticalInputUntilRelease) { input.y += 1; } if (down && !_muteVerticalInputUntilRelease) { input.y += -1; } } _moveInput.Set(input); // NB: we only send an input if the direction changes. That way, we minimize network messages if (_moveInput.ClearDirty()) { SimPlayerInputMove simInput = new SimPlayerInputMove(_moveInput); SimWorld.SubmitInput(simInput); } }
private void HandleRadialImpulseRequests() { DynamicBuffer <RadialImpulseRequestData> radialImpulses = GetBuffer <RadialImpulseRequestData>(GetRequestSingleton()); if (radialImpulses.Length > 0) { DynamicBuffer <DirectImpulseRequestData> directImpulseRequests = GetBuffer <DirectImpulseRequestData>(GetRequestSingleton()); foreach (RadialImpulseRequestData request in radialImpulses) { if (!HasComponent <PhysicsColliderBlob>(request.Target)) { continue; } var colliderRef = GetComponent <PhysicsColliderBlob>(request.Target).Collider; if (!colliderRef.IsCreated) { continue; } ref Collider collider = ref colliderRef.Value; fix2 pos = GetComponent <FixTranslation>(request.Target); fix2 centerOfMass = pos + (fix2)collider.MassProperties.MassDistribution.LocalCenterOfMass; fix2 v = centerOfMass - request.Position; fix distance = length(v); fix impulseStrength = remap( 0, request.Radius, request.StrengthMax, request.StrengthMin, distance); fix2 direction = distance < fix.Epsilon ? new fix2(0, 1) : v / distance; directImpulseRequests.Add(new DirectImpulseRequestData() { IgnoreMass = request.IgnoreMass, Strength = impulseStrength * direction, Target = request.Target }); } radialImpulses.Clear(); }
protected override void OnUpdate() { fix deltaTime = Time.DeltaTime; // Influence velocity from moveInput when pawn is on ground or ladder Entities.ForEach((ref PhysicsVelocity velocity, ref ActionPoints ap, in MoveInput moveInputComp, in MoveSpeed moveSpeed, in NavAgentFootingState footing, in MoveCost moveCost) => { if (footing.Value == NavAgentFooting.Ground || footing.Value == NavAgentFooting.Ladder) { fix2 moveInput = moveInputComp.Value; if (footing.Value == NavAgentFooting.Ground) { // NB: If we ever get slopped terrain, we might want to set the move perpendicular to the normal of the floor moveInput.y = 0; } moveInput = clampLength(moveInput, 0, 1); if (ap.Value == 0) { moveInput *= 0; } // consume energy if (moveInput.x != 0 || moveInput.y != 0) { ap.Value = max(0, ap.Value - (deltaTime * moveCost.Value)); } fix2 newVelocity = velocity.Linear; newVelocity.x = moveInput.x * moveSpeed; if (footing.Value == NavAgentFooting.Ladder) { newVelocity.y = moveInput.y * moveSpeed; } velocity.Linear = newVelocity; } }).Run();
public static bool Raycast <T>(fix2 start, fix2 end, fix bevel, T predicate, out int2 result) where T : struct, ITilePredicate { // fbessette: this could be optimized by not performing a 'Raycast All' NativeList <int2> tiles = new NativeList <int2>(Allocator.Temp); RaycastAll(start, end, bevel, tiles); for (int i = 0; i < tiles.Length; i++) { if (predicate.Evaluate(tiles[i])) { result = tiles[i]; return(true); } } result = default; return(false); }