public void FromState(RayState rs) { // Muzzel Flash muzzelFlash.Flash(); // Cast ray int masks = 0; masks |= (1 << LayerMask.NameToLayer("Player")); masks |= (1 << LayerMask.NameToLayer("Map")); var fireDir = new Vector2(Mathf.Cos(rs.zAngle), Mathf.Sin(rs.zAngle)); RaycastHit2D hitInfo = Physics2D.Raycast(rs.pos, fireDir, 1000, masks); if (hitInfo) { // Particle effect var effectPosition = new Vector3(hitInfo.point.x, hitInfo.point.y, -1); var effectRotation = Quaternion.Euler(0, 0, Random.Range(0.0f, 360.0f)); var effect = GameObject.Instantiate(impactEffect, effectPosition, effectRotation); GameObject.Destroy(effect, 1); //DrawRay.DrawLine(firePoint.transform.position, hitInfo.point, Color.red, 0.05f); DrawRay.DrawLine(rs.pos, hitInfo.point, Color.red, 1f); } else { //DrawRay.DrawLine(firePoint.transform.position, rs.zAngle, 100f, Color.red, 0.05f); DrawRay.DrawLine(rs.pos, rs.zAngle, 100f, Color.red, 1f); } }
/// <summary> /// This function is the core of the Lag Compensation Algorithm. /// When a player fires we raycast on all the backtracked colliders on the specific give tick /// </summary> /// <param name="player">This parameter is the player attached to this gamobject.</param> /// <param name="tickAck">This parameter is the last tick seen by the shooting player, /// i.e the tick that this tick answers or refers.</param> public RayState FireShotWithBacktrack(int tickAck) { // Debug.Log("Player " + attachedPlayer.playerId + " Fire"); float zAngle = attachedPlayer.rb.rotation * Mathf.Deg2Rad; Vector2 headingDir = new Vector2(Mathf.Cos(zAngle), Mathf.Sin(zAngle)); Vector2 firePoint = attachedPlayer.firePointGO.transform.position; RayState newRay = new RayState(attachedPlayer.playerId, zAngle, firePoint); // Debug.Log("Was answer for tick: " + tickAck); // Debug.Log("But last tick was: " + (NetworkTick.tickSeq - 1)); Debug.DrawRay(firePoint, headingDir * 100f); // Cast a ray straight down. RaycastHit2D[] results = Physics2D.RaycastAll(firePoint, headingDir, 100, lagCompensationMask); LayerMask mapLayer = LayerMask.NameToLayer("Map"); foreach (RaycastHit2D hit in results) { if (hit.collider.gameObject.layer.Equals(mapLayer)) { // DEBUG intersection Vector2 intersect = hit.point; GameObject circ = GameObject.CreatePrimitive(PrimitiveType.Sphere); circ.transform.position = intersect; circ.transform.localScale = new Vector3(0.7f, 0.7f, 0.7f); GameObject.Destroy(circ, 0.4f); break; } SnapshotInfo colliderInfo = hit.transform.parent.GetComponent <SnapshotInfo>(); if (colliderInfo.Player != attachedPlayer && colliderInfo.SnapshotTick == tickAck) { // Kill the player, destroy its container gameobject GameObject.Destroy(colliderInfo.PlayerContainer); // Check and logs what have we hit, a headshot or a bodyshot ushort hitPlayerID = colliderInfo.Player.playerId; if (hit.collider.gameObject.name == "Head") { Debug.Log("Player " + attachedPlayer.playerId + " Headshot Player " + hitPlayerID); } else if (hit.collider.gameObject.name == "Body") { Debug.Log("Player " + attachedPlayer.playerId + " Bodyshot Player " + hitPlayerID); } // DEBUG intersection Vector2 intersect = hit.point; GameObject circ = GameObject.CreatePrimitive(PrimitiveType.Sphere); circ.transform.position = intersect; circ.transform.localScale = new Vector3(0.7f, 0.7f, 0.7f); GameObject.Destroy(circ, 0.4f); break; } } return(newRay); }
public void AddState(RayState state) { raysState.Add(state); }
isInside(Vertex point, LinearRing outerRing, double radiusOfInterest) { if (DEBUG) { if (radiusOfInterest < 0.0) { throw new Exception("MkGeoAlgo.isInside: radiusOfInterest must be greater than 0"); } } // test the bounding box of the ring with radiusOfInterest var bb = outerRing.boundingBox(); if (!isInsideBoundingBox(bb.bottomLeft, bb.topRight, point, radiusOfInterest)) { return(1, nextFloat(radiusOfInterest)); } double bbScale = maxAbs(bb.bottomLeft, bb.topRight); if (bbScale < 1.0) { bbScale = 1.0; } double epsilon = nextFloat(bbScale) - bbScale; int effectiveLength = outerRing.length - 1; Func <int, int> roundIndex = n => (n + effectiveLength) % effectiveLength; EdgeBBTester edgeBBTester = new EdgeBBTester(point, radiusOfInterest); int numIntersection = 0; int inout = Int32.MaxValue; // should be -1 (inside), 0 (boundary), 1 (outside) double buffer = radiusOfInterest; // Determine the initial state. We wlll loop through the verts from "bottom" // We will start the loop from bottom // bottom is the index of the lowest vert int bottom = outerRing.bottomVert; Vertex v1 = outerRing[bottom]; RayState state = RayState.Below; if (v1.y < point.y) { state = RayState.Below; } else if (v1.y > point.y) { state = RayState.RayDone; inout = 1; // in the following v1.y === point.y } else if (bb.bottomLeft.y == bb.topRight.y) { // bounding box degenerates to horizontal line segment inout = 0; state = RayState.RayDone; } else { // Find the left-most bottom int j = bottom; for (int i = 1; i < outerRing.length; ++i) { int k = roundIndex(bottom - i); Vertex v_k = outerRing[k]; // notice that v1.y is least among all verts // we are sure to find v0 if (v_k.y > v1.y) { break; } else { j = k; } } bottom = j; state = RayState.AboveToMiddle; } // Assertion: state === RayDone || inout == Int32.MaxValue // state !== RayDone || inout != Int32.MaxValue Vertex v2 = outerRing[bottom]; Vertex v0; Vertex xmin, xmax, ymin, ymax; v1 = outerRing[roundIndex(bottom - 1)]; for (int i = 1; i < outerRing.length; ++i) { v0 = v1; v1 = v2; v2 = outerRing[roundIndex(bottom + i)]; if (v1.x < v2.x) { xmin = v1; xmax = v2; } else { xmin = v2; xmax = v1; } if (v1.y < v2.y) { ymin = v1; ymax = v2; } else { ymin = v2; ymax = v1; } if (state == RayState.RayDone) { if (buffer == 0.0) { break; } else { // We have to test edges for the distance if (edgeBBTester.isInBoundingBox(xmin, xmax, ymin, ymax)) { double updated = updateBorderBuffer(buffer, v0, v1, v2, point, epsilon); // Assertion: updated == buffer || |updated| < |buffer| && |updated| < radiusOfInterest if (Math.Abs(updated) < Math.Abs(buffer)) { edgeBBTester.tightenOffset(Math.Abs(updated)); buffer = updated; } } continue; } } else if (state == RayState.Below || state == RayState.Above) { if (point.y == v2.y) { // entering Middle if (point.x == v2.x) { inout = 0; state = RayState.RayDone; } else { state = (state == RayState.Below) ? RayState.BelowToMiddle : RayState.AboveToMiddle; } } else if (state == RayState.Below ? v2.y > point.y : v2.y < point.y) { // Below -> Above || Above -> Below state = state == RayState.Below ? RayState.Above : RayState.Below; if (point.x <= xmax.x) { if (point.x <= xmin.x) { // there must be hit numIntersection += 1; } else { // xmin.x < point.x <= xmax.x double d = signedDist(ymin, ymax, point); if (d == 0.0) { // hit the boundary inout = 0; state = RayState.RayDone; } else if (d > 0.0) { // one hit numIntersection += 1; } // otherwise, Δ < 0: there is no hit } } else { // point.x > xmax.x: there is no hit // if debug // println("Test 8.5") // end } } // otherwise, state === Below ? v2.y < point.y : v2.y > point.y, and we remain in Below/Above } else if (state == RayState.BelowToMiddle || state == RayState.AboveToMiddle) { // We are on the Middle line if (point.y == v2.y) { // Stay on the Middle if (xmin.x <= point.x && point.x <= xmax.x) { // we are on the horizontal edge inout = 0; state = RayState.RayDone; } } else if (state == RayState.BelowToMiddle ? v2.y <point.y : v2.y> point.y) { // Below -> BelowToMiddle -> Below // or, Above -> AboveToMiddle -> Above state = state == RayState.BelowToMiddle ? RayState.Below : RayState.Above; } else { // state === BelowToMiddle ? v2.y > point.y : v2.y < point.y // Below -> BelowToMiddle -> Above // or, Above -> AboveToMiddle -> Below state = state == RayState.BelowToMiddle ? RayState.Above : RayState.Below; if (point.x <= v1.x) { numIntersection += 1; } } } // end of state transition } // end of the loop through all the verts // println("number of intersection = " * string(numIntersection)) if (inout == Int32.MaxValue) { if (numIntersection % 2 == 0) { inout = 1; } else { inout = -1; } } if (buffer == radiusOfInterest) { if (radiusOfInterest >= Double.MaxValue) { string err = "logical error: the distance to the border cannot be infinity"; if (DEBUG) { throw new Exception(err); } else if (geoFenceLogger != null) { geoFenceLogger(err); } } buffer = inout < 0 ? -nextFloat(radiusOfInterest) : nextFloat(radiusOfInterest); } return(inout, buffer); } // isInside(LinearRing )