/// <summary> /// Fires a traceline and collects collision information. /// </summary> /// <param name="trace">Object containing the trace line parameters.</param> /// <returns> /// A value containing the result of the trace. /// </returns> public TraceResult TraceLine(TraceQuery trace) { double x0, y0, x1, y1; List <GameEntity> entities = _entListPool.GetObject(); x0 = trace.Line.Start.X; y0 = trace.Line.Start.Y; x1 = trace.Line.End.X; y1 = trace.Line.End.Y; if ((trace.Options & TraceLineOptions.IgnoreEntities) == TraceLineOptions.None) { GetPossibleCollidersForTraceline(trace, entities); } var dx = Math.Abs(x1 - x0); var dy = Math.Abs(y1 - y0); int x = (int)Math.Floor(x0); int y = (int)Math.Floor(y0); int n = 1; int x_inc, y_inc; double error = 0.0D; if (dx == 0) { x_inc = 0; error = double.MaxValue; } else if (x1 > x0) { x_inc = 1; n += (int)Math.Floor(x1) - x; error = (Math.Floor(x0) + 1 - x0) * dy; } else { x_inc = -1; n += x - (int)Math.Floor(x1); error = (x0 - Math.Floor(x0)) * dy; } if (dy == 0) { y_inc = 0; error -= double.MaxValue; } else if (y1 > y0) { y_inc = 1; n += (int)Math.Floor(y1) - y; error -= (Math.Floor(y0) + 1 - y0) * dx; } else { y_inc = -1; n += y - (int)Math.Floor(y1); error -= (y0 - Math.Floor(y0)) * dx; } var hit = false; GeometryTile tile = null; GameEntity entity = null; for (; n > 0; --n) { // visit if (entities.Count > 0) { hit = IsPointInEntity(entities, x, y, trace, out entity); } if (!hit && ((trace.Options & TraceLineOptions.IgnoreTiles) == TraceLineOptions.None)) { hit = IsPointOnSolidTile(x, y, tile, trace, out tile); } if (hit) { break; } if (error > 0) { y += y_inc; error -= dx; } else { x += x_inc; error += dy; } } if (_varShowTracelines.Value) { if (hit) { _renderService.DrawLine(new Line(trace.Line.Start.X, trace.Line.Start.Y, x, y), 0); _renderService.DrawLine(new Line(x, y, trace.Line.End.X, trace.Line.End.Y), 0, 0, 255, 0); } else { _renderService.DrawLine(trace.Line, 0); } } entities.Clear(); _entListPool.PutObject(entities); var retval = new TraceResult(); retval.Hit = hit; retval.ContactPoint = new Point(x, y); retval.Entity = entity; retval.Tile = tile; return(retval); }