} //testPolygonVsPolygon /** Internal api - test a ray against a circle */ public static bool TestRayVsCircle(Ray ray, Circle circle, out RayCollision rayCollision) { Vector2 delta = ray.End - ray.Start; Vector2 ray2Circle = ray.Start - circle.Position; float a = delta.LengthSquared(); float b = 2 * Vector2.Dot(delta, ray2Circle); float c = Vector2.Dot(ray2Circle, ray2Circle) - (circle.Radius * circle.Radius); float d = b * b - 4 * a * c; if (d >= 0) { d = (float)System.Math.Sqrt(d); float t1 = (-b - d) / (2 * a); float t2 = (-b + d) / (2 * a); if (ray.IsInfinite || (t1 <= 1.0 && t1 >= 0.0)) { rayCollision = new RayCollision { Shape = circle, Ray = ray, Start = t1, End = t2 }; return(true); } // } //d >= 0 rayCollision = new RayCollision(); return(false); }
} //testPolygonVsPolygon /** Internal api - test a ray against a circle */ public static RayCollision testRayVsCircle(Ray ray, Circle circle) { var deltaX = ray.end.x - ray.start.x; var deltaY = ray.end.y - ray.start.y; var ray2circleX = ray.start.x - circle.position.x; var ray2circleY = ray.start.y - circle.position.y; var a = Util.vec_lengthsq(deltaX, deltaY); var b = 2 * Util.vec_dot(deltaX, deltaY, ray2circleX, ray2circleY); var c = Util.vec_dot(ray2circleX, ray2circleY, ray2circleX, ray2circleY) - (circle.radius * circle.radius); var d = b * b - 4 * a * c; if (d >= 0) { d = (float)System.Math.Sqrt(d); var t1 = (-b - d) / (2 * a); var t2 = (-b + d) / (2 * a); if (ray.infinite || (t1 <= 1.0 && t1 >= 0.0)) { var result = new RayCollision(); result.shape = circle; result.ray = ray; result.start = t1; result.end = t2; return(result); } // } //d >= 0 return(null); }
/** Internal api - test a ray against a polygon */ public static bool TestRayVsPolygon(Ray ray, Polygon polygon, out RayCollision rayCollision) { float minU = float.PositiveInfinity; float maxU = 0.0f; float startX = ray.Start.X; float startY = ray.Start.Y; float deltaX = ray.End.X - startX; float deltaY = ray.End.Y - startY; var verts = polygon.TransformedVertices; Vector2 v1 = verts[^ 1];
public override void onUpdate() { Vector dir = Input.MousePosition - new Vector(ScreenWidth / 2, ScreenHeight / 2); target.Position = Input.MouseGamePosition; mouse.Position = Input.MouseGamePosition; Vector start = Gob.GunTipPosition - Gob.Position; //dir = Input.MouseGamePosition - start; //mouse.Position = Gob.Position + dir.UnitSafe * 200; RayCollisions <Wall> rayColls = Gob.currentRayCollisions <Wall>(start, dir); RayCollision rc = null; if (rayColls.Count > 0) { rc = rayColls[0]; target.Position = rc.ContactPoint; } RayCollisions <Badguy> badguyColls = Gob.currentRayCollisions <Badguy>(start, dir); if (badguyColls.Count > 0) { if (rc == null || rc.Length > badguyColls[0].Length) { rc = badguyColls[0]; target.Position = rc.ContactPoint; } } if (rc != null) { Gob.LookAngle = rc.RayDirection.Angle - (float)Math.PI / 2; } if (rayColls.Count > 0) { target.Position = rc.ContactPoint; Vector screenPos = Level.Camera.getScreenCoordinate(Gob.GunTipPosition); Bounds b = new Bounds(Vector.Zero, new Vector(ScreenWidth, ScreenHeight), 0); RayCollisionInfo info = b.getRayCollisionInfo(screenPos, (rc.RayDirection)); if (info != null) { screenPos = info.ContactPoint; screenPos = Level.Camera.getGameCoordinate(screenPos); if ((screenPos - Gob.GunTipPosition).Length < (Gob.GunTipPosition - target.Position).Length) { target.Position = screenPos; } } } if (Input.isNewMouseDown(MouseButtons.Left) && rc != null) { laserSound.duplicate().play(); //laserSound.Pan = 0; if (rc is RayCollision <Badguy> ) { RayCollision <Badguy> brc = (RayCollision <Badguy>)rc; brc.Gob.close(); } float height = (Rand.Instance.nextFloat() * 20 - 10); Tracer tracer = new Tracer(Level); tracer.Light.Visible = true; float scaleAmt = .9f - (Rand.Instance.nextFloat() * .45f); scaleAmt = 1; tracer.Sprite.Scale = new Vector((rc.Length - 0) * scaleAmt / 10f, .5f + (Rand.Instance.nextFloat() * .3f - .15f)); tracer.Sprite.Rotation = rc.RayDirection.Angle; tracer.Position = (rc.ContactPoint + rc.RayStart) / 2; tracer.Sprite.Color = Rand.Instance.nextColorVariation(Color.DarkOrange, .1f, .1f, .1f, .2f); //tracer.Position += rc.RayDirection * (0 + ((1 - scaleAmt) * (rc.Length)/2 * (Rand.Instance.nextFloat() * 2 - 1))); tracer.Position += rc.RayDirection.Perpendicular * height; tracer.Decay = 5; tracer = new Tracer(Level); tracer.Light.Visible = true; //scaleAmt = .9f - (Rand.Instance.nextFloat()*.45f); //scaleAmt = (scaleAmt + 0) / 2; tracer.Sprite.Scale = new Vector((rc.Length - 0) * scaleAmt / 10f, .2f + (Rand.Instance.nextFloat() * .3f - .15f)); tracer.Sprite.Rotation = rc.RayDirection.Angle; tracer.Position = (rc.ContactPoint + rc.RayStart) / 2; tracer.Sprite.Color = Rand.Instance.nextColorVariation(Color.White, .1f, .1f, .1f, 0); tracer.Decay = 4; //tracer.Position += rc.rayDirection * (0 + ((1 - scaleAmt) * (rc.Length)/2 * (Rand.Instance.nextFloat() * 2 - 1))); //tracer.Position += -rc.RayDirection * (rc.Length/2 - tracer.Sprite.ImageSize.X/2); tracer.Position += rc.RayDirection.Perpendicular * height; tracer.Dir = rc.RayDirection; tracer.Speed = 1f; SpriteEffect fx = new SpriteEffect(Level); fx.Effect = "smokePlume3"; fx.Position = rc.ContactPoint - rc.RayDirection * 10; fx.Sprite.Scale *= .4f; fx.Frames = Vector.One * 4; fx.Speed = 2; fx.Sprite.Color = Color.Orange; fx.Light.Visible = true; fx.Light.Radius = 256f; float f = 256f; fx.OnUpdate = (a) => { f *= .95f; fx.Light.Radius = f; }; fx = new SpriteEffect(Level); fx.Effect = "muzzle"; fx.Position = rc.RayStart - rc.RayDirection * 10; fx.Frames = new Vector(4, 2); fx.Speed = 2; fx.Sprite.Scale *= .4f; fx.Sprite.Rotation = rc.RayDirection.Angle; fx.Sprite.Color = Color.Orange; } }
/** Internal api - test a ray against a polygon */ public static RayCollision testRayVsPolygon(Ray ray, Polygon polygon) { var min_u = float.PositiveInfinity; var max_u = 0.0f; var startX = ray.start.x; var startY = ray.start.y; var deltaX = ray.end.x - startX; var deltaY = ray.end.y - startY; var verts = polygon.transformedVertices; var v1 = verts[verts.Length - 1]; var v2 = verts[0]; var ud = (v2.y - v1.y) * deltaX - (v2.x - v1.x) * deltaY; var ua = rayU(ud, startX, startY, v1.x, v1.y, v2.x - v1.x, v2.y - v1.y); var ub = rayU(ud, startX, startY, v1.x, v1.y, deltaX, deltaY); if (ud != 0.0 && ub >= 0.0 && ub <= 1.0) { if (ua < min_u) { min_u = ua; } if (ua > max_u) { max_u = ua; } } for (var i = 1; i < verts.Length; i++) { v1 = verts[i - 1]; v2 = verts[i]; ud = (v2.y - v1.y) * deltaX - (v2.x - v1.x) * deltaY; ua = rayU(ud, startX, startY, v1.x, v1.y, v2.x - v1.x, v2.y - v1.y); ub = rayU(ud, startX, startY, v1.x, v1.y, deltaX, deltaY); if (ud != 0.0 && ub >= 0.0 && ub <= 1.0) { if (ua < min_u) { min_u = ua; } if (ua > max_u) { max_u = ua; } } } //each vert if (ray.infinite || (min_u <= 1.0 && min_u >= 0.0)) { var result = new RayCollision(); result.shape = polygon; result.ray = ray; result.start = min_u; result.end = max_u; return(result); } return(null); }
public override bool IntersectsRay(Ray ray, out RayCollision rayCollision) => Sat2D.TestRayVsCircle(ray, this, out rayCollision);
public override void onUpdate() { Vector dir = Input.MousePosition - Level.Camera.getScreenCoordinate(Gob.Position); dir = Vector.Zero; if (Input.isKeyDown(Keys.Right)) { dir.X += 1; } if (Input.isKeyDown(Keys.Left)) { dir.X -= 1; } if (Input.isKeyDown(Keys.Up)) { dir.Y -= 1; } if (Input.isKeyDown(Keys.Down)) { dir.Y += 1; } if (dir.Equals(Vector.Zero)) { dir.X = Math.Sign(Gob.Velocity.X); } dir = dir.UnitSafe; Gob.LookAngle = dir.Angle - (float)Math.PI / 2; Vector start = Gob.GunTipPosition - Gob.Position; RayCollisions <Wall> rayColls = Gob.currentRayCollisions <Wall>(start, dir); RayCollision rc = null; if (rayColls.Count > 0) { rc = rayColls[0]; target.Position = rc.ContactPoint; } RayCollisions <Drone> badguyColls = Gob.currentRayCollisions <Drone>(start, dir); if (badguyColls.Count > 0) { if (rc == null || rc.Length > badguyColls[0].Length) { rc = badguyColls[0]; target.Position = rc.ContactPoint; } } RayCollisions <Worm> badguyCollsWorms = Gob.currentRayCollisions <Worm>(start, dir); if (badguyCollsWorms.Count > 0) { if (rc == null || rc.Length > badguyCollsWorms[0].Length) { rc = badguyCollsWorms[0]; target.Position = rc.ContactPoint; } } RayCollisions <FlyBug> badguyCollsBugs = Gob.currentRayCollisions <FlyBug>(start, dir); if (badguyCollsBugs.Count > 0) { if (rc == null || rc.Length > badguyCollsBugs[0].Length) { rc = badguyCollsBugs[0]; target.Position = rc.ContactPoint; } } if (rayColls.Count > 0) { target.Position = rc.ContactPoint; Vector screenPos = Level.Camera.getScreenCoordinate(Gob.GunTipPosition); Bounds b = new Bounds(Vector.Zero, new Vector(ScreenWidth, ScreenHeight), 0); RayCollisionInfo info = b.getRayCollisionInfo(screenPos, (rc.RayDirection)); if (info != null) { screenPos = info.ContactPoint; screenPos = Level.Camera.getGameCoordinate(screenPos); if ((screenPos - Gob.GunTipPosition).Length < (Gob.GunTipPosition - target.Position).Length) { target.Position = screenPos; } } } bool space = Input.isNewKeyDown(Keys.LeftShift) || Input.isNewKeyDown(Keys.RightControl); if (space) { Log.debug("space"); } if (space && rc != null) { Log.debug("shoot"); laserSound.duplicate().setVolume(.4f).play(); //laserSound.Pan = 0; if (rc is RayCollision <Drone> ) { RayCollision <Drone> brc = (RayCollision <Drone>)rc; brc.Gob.close(); } // if (rc is RayCollision<Worm>){ // RayCollision<Worm> brc = (RayCollision<Worm>) rc; // brc.Gob.close(); // } if (rc is RayCollision <FlyBug> ) { RayCollision <FlyBug> brc = (RayCollision <FlyBug>)rc; brc.Gob.close(); } float height = (Rand.Instance.nextFloat() * 20 - 10); Tracer tracer = new Tracer(Level); tracer.Light.Visible = true; float scaleAmt = .9f - (Rand.Instance.nextFloat() * .45f); scaleAmt = 1; tracer.Sprite.Scale = new Vector((rc.Length - 0) * scaleAmt / 10f, .5f + (Rand.Instance.nextFloat() * .3f - .15f)); tracer.Sprite.Rotation = rc.RayDirection.Angle; tracer.Position = (rc.ContactPoint + rc.RayStart) / 2; tracer.Sprite.Color = Rand.Instance.nextColorVariation(Color.DarkOrange, .1f, .1f, .1f, .2f); //tracer.Position += rc.RayDirection * (0 + ((1 - scaleAmt) * (rc.Length)/2 * (Rand.Instance.nextFloat() * 2 - 1))); tracer.Position += rc.RayDirection.Perpendicular * height; tracer.Decay = 5; tracer = new Tracer(Level); tracer.Light.Visible = true; //scaleAmt = .9f - (Rand.Instance.nextFloat()*.45f); //scaleAmt = (scaleAmt + 0) / 2; tracer.Sprite.Scale = new Vector((rc.Length - 0) * scaleAmt / 10f, .2f + (Rand.Instance.nextFloat() * .3f - .15f)); tracer.Sprite.Rotation = rc.RayDirection.Angle; tracer.Position = (rc.ContactPoint + rc.RayStart) / 2; tracer.Sprite.Color = Rand.Instance.nextColorVariation(Color.White, .1f, .1f, .1f, 0); tracer.Decay = 4; //tracer.Position += rc.rayDirection * (0 + ((1 - scaleAmt) * (rc.Length)/2 * (Rand.Instance.nextFloat() * 2 - 1))); //tracer.Position += -rc.RayDirection * (rc.Length/2 - tracer.Sprite.ImageSize.X/2); tracer.Position += rc.RayDirection.Perpendicular * height; tracer.Dir = rc.RayDirection; tracer.Speed = 1f; SpriteEffect fx = new SpriteEffect(Level); fx.Effect = "smokePlume3"; fx.Position = rc.ContactPoint - rc.RayDirection * 10; fx.Sprite.Scale *= .4f; fx.Frames = Vector.One * 4; fx.Speed = 2; fx.Sprite.Depth = .3f; fx.Sprite.Color = Color.Orange; fx.Light.Visible = true; fx.Light.Radius = 256f; float f = 256f; fx.OnUpdate = (a) => { f *= .95f; fx.Light.Radius = f; }; fx = new SpriteEffect(Level); fx.Effect = "muzzle"; fx.Position = rc.RayStart - rc.RayDirection * 10; fx.Frames = new Vector(4, 2); fx.Speed = 2; fx.Sprite.Scale *= .4f; fx.Sprite.Rotation = rc.RayDirection.Angle; fx.Sprite.Color = Color.Orange; } }