public void Execute(Entity e, int jobIndex, ref Translation translation, ref VelocityComponent velocity, [ReadOnly] ref ProjectileComponent projectile) { if (translation.Value.y < 0.15f) { // find all the entities in the nearby quad and destroy it if within the radius int key = QuadrantSystem.GetPositionHashMapKey(translation.Value); if (QuadMap.TryGetFirstValue(key, out var data, out var it)) { do { float distance = distancesq(data.position, translation.Value); if (data.quadEntityData.type == QuadEntityType.Cavalry) { continue; } if (distance < projectile.DamageRadius) { CommandBuffer.DestroyEntity(jobIndex, data.e); } } while (QuadMap.TryGetNextValue(out data, ref it)); } CommandBuffer.DestroyEntity(jobIndex, e); } // apply gravity velocity.Value.y += -0.0098f * projectile.Weight; velocity.Value.y = clamp(velocity.Value.y, -10f, 100f); // apply air resistance velocity.Value.z += projectile.AirResistance * -0.0001f; velocity.Value.z = clamp(velocity.Value.z, 0.5f, 100f); translation.Value += velocity.Value * deltaTime; }
public void Execute([ReadOnly] ref Translation translation, ref TargetComponent target, [ReadOnly] ref QuadrantEntityComponent entityQuadInfo) { float3 entityPosition = translation.Value; // if the entity is so far off the map, it doesn't even need to search for anything if (entityPosition.z > 80 || entityPosition.z < -200) { return; } float closestDistance = 1000f; int hashKey = QuadrantSystem.GetPositionHashMapKey(entityPosition); if (EntityHashMap.TryGetFirstValue(hashKey, out var quadData, out var it)) { do { if (((ushort)(quadData.quadEntityData.type) & target.targetMask) == 0) { continue; } float3 otherUnitLoc = quadData.position; // only care to find a target that is in the approximate same lane if (abs(otherUnitLoc.x - entityPosition.x) > 25f) { continue; } // check distance after float currentDis = distancesq(entityPosition, otherUnitLoc); // if the distance is closer then the minimum, it found the necessary target, // use that cavalry unit as the target immediately if (closestDistance > currentDis) { if ((ushort)(entityQuadInfo.type & QuadEntityType.Cavalry) != 0) { // if this is a cavalry unit make the entity targeted so that other cavalry units can't take it } closestDistance = currentDis; target.entity = quadData.e; target.location = otherUnitLoc; } } while (EntityHashMap.TryGetNextValue(out quadData, ref it)); } if (closestDistance > 999f) { target.entity = Entity.Null; } }
public void Execute(Entity e, int jobIndex, ref Translation translation, ref WidthComponent width) { int hashKey = QuadrantSystem.GetPositionHashMapKey(translation.Value); BlockMap.Add(hashKey, new BlockerData { entity = e, position = translation.Value, width = width.Value }); }
public void Execute(Entity entity, int index, ref Translation translation, ref PhysicsCollider collider, ref CollisionData collisionData) { int hashMapKey = QuadrantSystem.GetPositionHashMapKey(translation.Value); CheckCollisions(hashMapKey, index, ref entity, ref translation, ref collider, ref collisionData); CheckCollisions(hashMapKey + 1, index, ref entity, ref translation, ref collider, ref collisionData); CheckCollisions(hashMapKey - 1, index, ref entity, ref translation, ref collider, ref collisionData); CheckCollisions(hashMapKey + QuadrantSystem.quadrantYMultiplier, index, ref entity, ref translation, ref collider, ref collisionData); CheckCollisions(hashMapKey - QuadrantSystem.quadrantYMultiplier, index, ref entity, ref translation, ref collider, ref collisionData); CheckCollisions(hashMapKey + 1 + QuadrantSystem.quadrantYMultiplier, index, ref entity, ref translation, ref collider, ref collisionData); CheckCollisions(hashMapKey - 1 + QuadrantSystem.quadrantYMultiplier, index, ref entity, ref translation, ref collider, ref collisionData); CheckCollisions(hashMapKey + 1 - QuadrantSystem.quadrantYMultiplier, index, ref entity, ref translation, ref collider, ref collisionData); CheckCollisions(hashMapKey - 1 - QuadrantSystem.quadrantYMultiplier, index, ref entity, ref translation, ref collider, ref collisionData); }
public void Execute(Entity e, int jobIndex, [ReadOnly] ref Translation translation, [ReadOnly] ref MeleeStrengthComponent strength, ref MovementStateComponent state) { int hashKey = QuadrantSystem.GetPositionHashMapKey(translation.Value); state.Value = (ushort)MovementState.Moving; if (BlockerMap.TryGetFirstValue(hashKey, out var blockerData, out var it)) { float zombieX = translation.Value.x; do { float furthestRight = blockerData.position.x + blockerData.width / 2; float furthestLeft = blockerData.position.x - blockerData.width / 2; if (zombieX < furthestLeft || zombieX > furthestRight) { continue; } // within the bounds of the blocker // check how far away are you from the blocker if (abs(translation.Value.z - blockerData.position.z) > 2.5f) { continue; } if (!HealthData.Exists(blockerData.entity)) { // entity is dead return; } // the zombie is right in front of the blocker state.Value = (ushort)MovementState.Blocked; // detect if the blocker has a DamageTag. If not, add one if (!DamageData.Exists(blockerData.entity)) { CommandBuffer.AddComponent(jobIndex, blockerData.entity, new BlockerDamageTag()); return; } } while(BlockerMap.TryGetNextValue(out blockerData, ref it)); } }
public void Execute(Entity entity, int index, [ReadOnly] ref Sight sight, [ReadOnly] ref LocalToWorld location, [ReadOnly] ref QuadrantEntity quadrantEntity, [ReadOnly] ref Diet diet, [ReadOnly] ref AnimalSize size, [ReadOnly] ref LifeStatus lifeStatus) { EntityWithPosition closestDangerTarget = new EntityWithPosition { entity = Entity.Null }; float closestDangerTargetDistance = float.MaxValue; EntityWithPosition closestFoodTarget = new EntityWithPosition { entity = Entity.Null }; float closestFoodTargetDistance = float.MaxValue; int hashMapKey = QuadrantSystem.GetPositionHashMapKey(location.Position); var entityDesc = new EntityDescription() { sight = sight, diet = diet, location = location, quadrantEntity = quadrantEntity, size = size, lifeStatus = lifeStatus }; FindTarget(index, hashMapKey, entityDesc, ref closestDangerTarget, ref closestDangerTargetDistance, ref closestFoodTarget, ref closestFoodTargetDistance); FindTarget(index, hashMapKey + 1, entityDesc, ref closestDangerTarget, ref closestDangerTargetDistance, ref closestFoodTarget, ref closestFoodTargetDistance); FindTarget(index, hashMapKey - 1, entityDesc, ref closestDangerTarget, ref closestDangerTargetDistance, ref closestFoodTarget, ref closestFoodTargetDistance); FindTarget(index, hashMapKey + QuadrantSystem.quadrantYMultiplier, entityDesc, ref closestDangerTarget, ref closestDangerTargetDistance, ref closestFoodTarget, ref closestFoodTargetDistance); FindTarget(index, hashMapKey - QuadrantSystem.quadrantYMultiplier, entityDesc, ref closestDangerTarget, ref closestDangerTargetDistance, ref closestFoodTarget, ref closestFoodTargetDistance); FindTarget(index, hashMapKey + 1 + QuadrantSystem.quadrantYMultiplier, entityDesc, ref closestDangerTarget, ref closestDangerTargetDistance, ref closestFoodTarget, ref closestFoodTargetDistance); FindTarget(index, hashMapKey - 1 + QuadrantSystem.quadrantYMultiplier, entityDesc, ref closestDangerTarget, ref closestDangerTargetDistance, ref closestFoodTarget, ref closestFoodTargetDistance); FindTarget(index, hashMapKey + 1 - QuadrantSystem.quadrantYMultiplier, entityDesc, ref closestDangerTarget, ref closestDangerTargetDistance, ref closestFoodTarget, ref closestFoodTargetDistance); FindTarget(index, hashMapKey - 1 - QuadrantSystem.quadrantYMultiplier, entityDesc, ref closestDangerTarget, ref closestDangerTargetDistance, ref closestFoodTarget, ref closestFoodTargetDistance); closestDangerTargetArray[index] = closestDangerTarget; closestFoodTargetArray[index] = closestFoodTarget; }
// todo: maybe intelligent ones should avoid not only the blockers but also each other? public void Execute([ReadOnly] ref Translation translation, [ReadOnly] ref TargetComponent target, ref MovementComponent movement) { int hashKey = QuadrantSystem.GetPositionHashMapKey(translation.Value); float3 dir = new float3(0, 0, -1); float closestDis = 1000f; float3 closestPos = float3(10000f, 1000f, 1000f); bool bFoundPotentialThreat = false; if (BlockerMap.TryGetFirstValue(hashKey, out var data, out var it)) { float zombieX = translation.Value.x; do { // todo: maybe you should first find the closest target first and then determine if it's worth avoiding // are you close enough to care? float furthestRight = data.position.x + data.width / 2 + 2f; float furthestLeft = data.position.x - data.width / 2 - 2f; if (zombieX < furthestLeft || zombieX > furthestRight) { continue; } float disSq = distancesq(translation.Value, data.position); if (disSq > closestDis) { continue; } closestDis = disSq; closestPos = data.position; bFoundPotentialThreat = true; } while (BlockerMap.TryGetNextValue(out data, ref it)); } if (!bFoundPotentialThreat) { movement.defaultDirection = dir; // todo: cause an irrational movement return; } if (closestDis > 150f) { movement.defaultDirection = dir; return; } // yes avoid float3 vFromAiToBlocker = normalize(closestPos - translation.Value); float dotProd = dot(dir, vFromAiToBlocker); // is it behind? if (dotProd < 0f) { movement.defaultDirection = dir; return; } // detect if to the left or to the right float3 right = new float3(1, 0, 0); float side = dot(right, vFromAiToBlocker); if (side > 0f) { // to the right, go left movement.defaultDirection.x -= ((movement.direction.x - 0.1) < -1) ? 0 : 0.1f; movement.defaultDirection.z += ((movement.direction.z + 0.1) > 0) ? 0 : 0.1f; return; } // to the left, go right movement.defaultDirection.x += ((movement.direction.x + 0.1) > 1) ? 0 : 0.1f; movement.defaultDirection.z += ((movement.direction.z + 0.1) > 0) ? 0 : 0.1f; }
protected override void OnUpdate() { var quadrantMultiHashMap = quadrantMultiHashMap2; float deltaTime = Time.DeltaTime; var ecb = m_EndSimulationEcbSystem.CreateCommandBuffer().ToConcurrent(); NativeArray <long> localInfectedCounter = new NativeArray <long>(1, Allocator.TempJob); localInfectedCounter[0] = 0; NativeArray <long> localTotalInfectedCounter = new NativeArray <long>(1, Allocator.TempJob); localTotalInfectedCounter[0] = 0; NativeArray <long> localSymptomaticCounter = new NativeArray <long>(1, Allocator.TempJob); localSymptomaticCounter[0] = 0; NativeArray <long> localAsymptomaticCounter = new NativeArray <long>(1, Allocator.TempJob); localAsymptomaticCounter[0] = 0; NativeArray <long> localDeathCounter = new NativeArray <long>(1, Allocator.TempJob); localDeathCounter[0] = 0; NativeArray <long> localRecoveredCounter = new NativeArray <long>(1, Allocator.TempJob); localRecoveredCounter[0] = 0; NativeArray <long> localTotalRecoveredCounter = new NativeArray <long>(1, Allocator.TempJob); localTotalRecoveredCounter[0] = 0; //job -> each element, if not infected, check if there are infected in its same quadrant var jobHandle = Entities.ForEach((Entity entity, int nativeThreadIndex, Translation t, ref QuadrantEntity qe, ref HumanComponent humanComponent, ref InfectionComponent ic) => { //for non infected entities, a check in the direct neighbours is done for checking the presence of infected if (ic.status == Status.susceptible) { //not infected-> look for infected in same cell int hashMapKey = QuadrantSystem.GetPositionHashMapKey(t.Value); //Debug.Log("Infected false"); QuadrantData quadrantData; NativeMultiHashMapIterator <int> nativeMultiHashMapIterator; if (quadrantMultiHashMap.TryGetFirstValue(hashMapKey, out quadrantData, out nativeMultiHashMapIterator)) { //cycle through all entries oh hashmap with the same Key do { //Debug.Log(quadrantData.position); if (math.distance(t.Value, quadrantData.position) < 2f) { //TODO consider also social resp other human involved //increment infectionCounter if one/more infected are in close positions (infected at quadrantData.position) //infection counter is determined by time and human responsibility ic.contagionCounter += 1f * deltaTime * (1 - humanComponent.socialResposibility); } //TODO we could add a cap here to speed up the check } while (quadrantMultiHashMap.TryGetNextValue(out quadrantData, ref nativeMultiHashMapIterator)); } else { //no infected in same cell -> human is safe ic.contagionCounter = 0f; } } //infection happened if (ic.contagionCounter >= contagionThreshold && ic.status == Status.susceptible) { //human become infected unsafe { Interlocked.Increment(ref ((long *)localInfectedCounter.GetUnsafePtr())[0]); Interlocked.Increment(ref ((long *)localTotalInfectedCounter.GetUnsafePtr())[0]); } qe.typeEnum = QuadrantEntity.TypeEnum.exposed; ic.status = Status.exposed; ic.exposedCounter = 0; } //Infectious status -> symptoms vs non-symptoms if (ic.exposedCounter > ic.exposedThreshold && ic.status == Status.exposed) { qe.typeEnum = QuadrantEntity.TypeEnum.infectious; ic.status = Status.infectious; ic.infected = true; if (ic.humanSymptomsProbability > (100 - ic.globalSymptomsProbability)) { //symptomatic -> lasts between 0.5 and 1.5 day ic.symptomatic = true; unsafe { Interlocked.Increment(ref ((long *)localSymptomaticCounter.GetUnsafePtr())[0]); } ic.infectiousCounter = 0; } else { //asymptomatic ic.symptomatic = false; unsafe { Interlocked.Increment(ref ((long *)localAsymptomaticCounter.GetUnsafePtr())[0]); } ic.infectiousCounter = 0; } } if (ic.infectiousCounter > ic.infectiousThreshold && ic.status == Status.infectious) { if (ic.humanDeathProbability > (100 - ic.globalDeathProbability)) { //remove entity unsafe { Interlocked.Increment(ref ((long *)localDeathCounter.GetUnsafePtr())[0]); Interlocked.Decrement(ref ((long *)localInfectedCounter.GetUnsafePtr())[0]); } if (ic.symptomatic) { unsafe { Interlocked.Decrement(ref ((long *)localSymptomaticCounter.GetUnsafePtr())[0]); } } else { unsafe { Interlocked.Decrement(ref ((long *)localAsymptomaticCounter.GetUnsafePtr())[0]); } } ic.status = Status.removed; qe.typeEnum = QuadrantEntity.TypeEnum.removed; ecb.DestroyEntity(nativeThreadIndex, entity); } else { //recovery time set up unsafe { Interlocked.Decrement(ref ((long *)localInfectedCounter.GetUnsafePtr())[0]); Interlocked.Increment(ref ((long *)localRecoveredCounter.GetUnsafePtr())[0]); Interlocked.Increment(ref ((long *)localTotalRecoveredCounter.GetUnsafePtr())[0]); } if (ic.symptomatic) { unsafe { Interlocked.Decrement(ref ((long *)localSymptomaticCounter.GetUnsafePtr())[0]); } } else { unsafe { Interlocked.Decrement(ref ((long *)localAsymptomaticCounter.GetUnsafePtr())[0]); } } ic.status = Status.recovered; ic.infected = false; //qe.typeEnum = QuadrantEntity.TypeEnum.recovered; ic.recoveredCounter = 0; } } if (ic.recoveredCounter > ic.recoveredThreshold && ic.status == Status.recovered) { ic.status = Status.susceptible; qe.typeEnum = QuadrantEntity.TypeEnum.susceptible; unsafe { Interlocked.Decrement(ref ((long *)localRecoveredCounter.GetUnsafePtr())[0]); } } if (ic.status == Status.exposed) { ic.exposedCounter += 1f * deltaTime; } if (ic.status == Status.infectious) { ic.infectiousCounter += 1f * deltaTime; } if (ic.status == Status.recovered) { ic.recoveredCounter += 1f * deltaTime; } }).WithReadOnly(quadrantMultiHashMap).ScheduleParallel(Dependency); m_EndSimulationEcbSystem.AddJobHandleForProducer(jobHandle); this.Dependency = jobHandle; jobHandle.Complete(); unsafe { Interlocked.Add(ref infectedCounter, Interlocked.Read(ref ((long *)localInfectedCounter.GetUnsafePtr())[0])); Interlocked.Add(ref totalInfectedCounter, Interlocked.Read(ref ((long *)localTotalInfectedCounter.GetUnsafePtr())[0])); Interlocked.Add(ref symptomaticCounter, Interlocked.Read(ref ((long *)localSymptomaticCounter.GetUnsafePtr())[0])); Interlocked.Add(ref asymptomaticCounter, Interlocked.Read(ref ((long *)localAsymptomaticCounter.GetUnsafePtr())[0])); Interlocked.Add(ref recoveredCounter, Interlocked.Read(ref ((long *)localRecoveredCounter.GetUnsafePtr())[0])); Interlocked.Add(ref deathCounter, Interlocked.Read(ref ((long *)localDeathCounter.GetUnsafePtr())[0])); Interlocked.Add(ref populationCounter, -Interlocked.Read(ref ((long *)localDeathCounter.GetUnsafePtr())[0])); } //Write some text to the test.txt file writer.WriteLine(Interlocked.Read(ref populationCounter) + "\t" + Interlocked.Read(ref infectedCounter) + "\t" + Interlocked.Read(ref totalInfectedCounter) + "\t" + Interlocked.Read(ref symptomaticCounter) + "\t" + Interlocked.Read(ref asymptomaticCounter) + "\t" + Interlocked.Read(ref deathCounter) + "\t" + Interlocked.Read(ref recoveredCounter) + "\t" + Interlocked.Read(ref totalRecoveredCounter) + "\t" + (int)Datetime.total_minutes); localInfectedCounter.Dispose(); localTotalInfectedCounter.Dispose(); localAsymptomaticCounter.Dispose(); localSymptomaticCounter.Dispose(); localRecoveredCounter.Dispose(); localTotalRecoveredCounter.Dispose(); localDeathCounter.Dispose(); }
public void Execute(Entity entity, int index, ref Translation translation, [ReadOnly] ref Rotation rotation, [ReadOnly] ref NonUniformScale nonUniformScale, [ReadOnly] ref MotionProperties motionProperties, ref Planetoid planetoidCrashInfo) { float3 position = translation.Value; float3 scale = nonUniformScale.Value; float qRotationZ = rotation.Value.value.z; float axisA = nonUniformScale.Value.x / 2f; float axisB = nonUniformScale.Value.y / 2f; //TODO read the angle from quaternion //float angleZ = GameHandler.ToEulerAngles(q).z; //angleZ = angleZ % (2 * math.PI); // read z angle of entity rotation by multiplying right vector by quaternion: float3 rotationRightVectorN = math.normalize(qRotationZ * new float3(0, 0, 1)); int hashMapKey = QuadrantSystem.GetPositionHashMapKey(position); if (quadrantMultiHashMap.TryGetFirstValue(hashMapKey, out EntityWithProps inspectedEntityWithProps, out NativeMultiHashMapIterator <int> it)) //TODO check the neighbouring quadrants { //TODO find the closest entity and only monitor that one do { float distance = math.distancesq(position, inspectedEntityWithProps.position); //TODO for ellipses: // calculate angle vector to the target //float3 vectorToTarget = inspectedEntityWithProps.position - position; //float distanceToTargetSq = vectorToTarget.x * vectorToTarget.x + vectorToTarget.y + vectorToTarget.y; float3 vectorToTargetN = math.normalize(inspectedEntityWithProps.position - position); // add angle to rotation angle of active ellipse collider float radiaeAngle = math.acos(math.dot(rotationRightVectorN, vectorToTargetN)); float sinRadiaeAngle = math.sin(radiaeAngle); float cosRadiaeAngle = math.cos(radiaeAngle); // calculate radius in line of target of active ellipse collider float radiusToTarget = axisA * axisB / math.sqrt(axisA * axisA * sinRadiaeAngle * sinRadiaeAngle + axisB * axisB * cosRadiaeAngle * cosRadiaeAngle); // do the same with passive ellipse collider float qRotationZofInspectedEntity = inspectedEntityWithProps.rotation.value.z; float3 rotationRightVectorNofInspectedEntity = math.normalize(qRotationZofInspectedEntity * new float3(0, 0, 1)); float axisAofInspectedEntity = inspectedEntityWithProps.nonUniformScale.x / 2f; float axisBofInspectedEntity = inspectedEntityWithProps.nonUniformScale.y / 2f; float radiaeAngleOfInspectedEntity = math.acos(math.dot(rotationRightVectorNofInspectedEntity, -vectorToTargetN)); float sinRadiaeAngleOfInspectedEntity = math.sin(radiaeAngleOfInspectedEntity); float cosRadiaeAngleOfInspectedEntity = math.cos(radiaeAngleOfInspectedEntity); float radiusFromTarget = axisAofInspectedEntity * axisBofInspectedEntity / math.sqrt(axisAofInspectedEntity * axisAofInspectedEntity * sinRadiaeAngleOfInspectedEntity * sinRadiaeAngleOfInspectedEntity + axisBofInspectedEntity * axisBofInspectedEntity * cosRadiaeAngleOfInspectedEntity * cosRadiaeAngleOfInspectedEntity); // sum the radiae to get the distance float radiaeSum = radiusToTarget + radiusFromTarget; float radiaeSumSq = radiaeSum * radiaeSum; // set the longer axis of ellipse to be the zero degrees rotation vector // or make it so that the x axis of ellipse is always longer // calculate the rotation of the asteroid % 360 // calculate the rotation of the asteroid upon which the check is being made // calculate the vector between two of the asteroids (maybe make it the normal vector) // calculate the angle between asteroid rotation and the connecting vector // and calculate for the radius at that point // same for the other asteroid // sum up the radii to obtain the collision distance // check for the collision distance (below) if (distance < radiaeSumSq && inspectedEntityWithProps.entity != entity && !(inspectedEntityWithProps.planetoidCrashData.crashTime > 0))// TODO and if entity that is being collided with has crashTime zero { planetoidCrashInfo.crashTime = realTimeSinceStartUp; inspectedEntityWithProps.planetoidCrashData.crashTime = realTimeSinceStartUp; destroyedPlanetoidsQueue.Enqueue(entity); destroyedPlanetoidsQueue.Enqueue(inspectedEntityWithProps.entity); //explosion location, TODO put exlosion locations into a persistent queue float3 explosionPoint = position - (position - inspectedEntityWithProps.position) / 2; explosionCoordsQueue.Enqueue(explosionPoint); break; } }while (quadrantMultiHashMap.TryGetNextValue(out inspectedEntityWithProps, ref it)); } }