package collision type Point struct { X float64 Y float64 } type Polygon struct { Points []Point } type ObjectType int const ( Hero ObjectType = 1 << iota Zombie Bullet Ending Starting ) type Collidable interface { CollisionShape() Polygon HandleCollisionEvent(other Collidable) CollisionObjectType() ObjectType } // Helper function to calculate the dot product of two points func dot(p1, p2 Point) float64 { return p1.X*p2.X + p1.Y*p2.Y } // Helper function to get the normal of the edge between two points func edgeNormal(p1, p2 Point) Point { return Point{X: p2.Y - p1.Y, Y: p1.X - p2.X} } // Project a polygon onto an axis and return the min and max projections func projectPolygon(axis Point, polygon Polygon) (float64, float64) { min := dot(axis, polygon.Points[0]) max := min for _, p := range polygon.Points[1:] { projection := dot(axis, p) if projection < min { min = projection } if projection > max { max = projection } } return min, max } // Check if two projections on an axis overlap func overlap(minA, maxA, minB, maxB float64) bool { if minA > maxB || minB > maxA { return false } return true } // Overlaps checks if two polygons overlap using the Separating Axis Theorem func (p Polygon) Overlaps(p2 Polygon) bool { if len(p.Points) == 0 || len(p2.Points) == 0 { return false } for i := 0; i < len(p.Points); i++ { next := (i + 1) % len(p.Points) axis := edgeNormal(p.Points[i], p.Points[next]) minA, maxA := projectPolygon(axis, p) minB, maxB := projectPolygon(axis, p2) if !overlap(minA, maxA, minB, maxB) { return false } } for i := 0; i < len(p2.Points); i++ { next := (i + 1) % len(p2.Points) axis := edgeNormal(p2.Points[i], p2.Points[next]) minA, maxA := projectPolygon(axis, p) minB, maxB := projectPolygon(axis, p2) if !overlap(minA, maxA, minB, maxB) { return false } } return true }