Contains indicates whether or not the given point is within the shape defined by this `SpaceComponent`. If it's on the border, it is considered "not within". If there is no shape defined, then this uses a rectangular area defined by the Width/Height of the SpaceComponent instead.
(p engo.Point)
| 211 | // If there is no shape defined, then this uses a rectangular area defined by the |
| 212 | // Width/Height of the SpaceComponent instead. |
| 213 | func (sc SpaceComponent) Contains(p engo.Point) bool { |
| 214 | if len(sc.hitboxes) == 0 { |
| 215 | points := sc.Corners() |
| 216 | halfArea := (sc.Width * sc.Height) / 2 |
| 217 | for i := 0; i < 4; i++ { |
| 218 | for j := i + 1; j < 4; j++ { |
| 219 | if t := triangleArea(points[i], points[j], p); t > halfArea || engo.FloatEqual(t, halfArea) { |
| 220 | return false |
| 221 | } |
| 222 | } |
| 223 | } |
| 224 | return true |
| 225 | } |
| 226 | // test line from the point to an arbitrary point far away |
| 227 | // hopefully this is big enough |
| 228 | // TODO: Make it editable? |
| 229 | testline := engo.Line{ |
| 230 | P1: p, |
| 231 | P2: engo.Point{ |
| 232 | X: 1e10, |
| 233 | Y: 1e10, |
| 234 | }, |
| 235 | } |
| 236 | sin, cos := math.Sincos(sc.Rotation * math.Pi / 180) |
| 237 | // test point for ellipse testing. It is rotated and translated such that the |
| 238 | // axis is that of the unrotated / translated AABB |
| 239 | testpoint := engo.Point{ |
| 240 | X: (p.X-sc.Position.X)*cos + (p.Y-sc.Position.Y)*sin, |
| 241 | Y: (p.Y-sc.Position.Y)*cos - (p.X-sc.Position.X)*sin, |
| 242 | } |
| 243 | i := 0 |
| 244 | for _, hb := range sc.hitboxes { |
| 245 | if !engo.FloatEqual(hb.Ellipse.Rx, 0) || !engo.FloatEqual(hb.Ellipse.Ry, 0) { |
| 246 | if testpoint.X < hb.Ellipse.Cx+hb.Ellipse.Rx && testpoint.X > hb.Ellipse.Cx-hb.Ellipse.Rx { |
| 247 | s := math.Sqrt((1 - ((testpoint.X-hb.Ellipse.Cx)*(testpoint.X-hb.Ellipse.Cx))/((hb.Ellipse.Rx)*(hb.Ellipse.Rx))) * (hb.Ellipse.Ry) * (hb.Ellipse.Ry)) |
| 248 | if testpoint.Y < hb.Ellipse.Cy+s && testpoint.Y > hb.Ellipse.Cy-s { |
| 249 | return true |
| 250 | } |
| 251 | } |
| 252 | continue |
| 253 | } |
| 254 | for _, line := range hb.Lines { |
| 255 | l := engo.Line{ |
| 256 | P1: engo.Point{ |
| 257 | X: sc.Position.X + line.P1.X*cos - line.P1.Y*sin, |
| 258 | Y: sc.Position.Y + line.P1.Y*cos + line.P1.X*sin, |
| 259 | }, |
| 260 | P2: engo.Point{ |
| 261 | X: sc.Position.X + line.P2.X*cos - line.P2.Y*sin, |
| 262 | Y: sc.Position.Y + line.P2.Y*cos + line.P2.X*sin, |
| 263 | }, |
| 264 | } |
| 265 | if _, ok := engo.LineIntersection(l, testline); ok { |
| 266 | i++ |
| 267 | } |
| 268 | } |
| 269 | if i%2 == 1 { |
| 270 | return true |