No hay mucho de donde mejorarla. Técnicamente es correcta. Aunque es cierto que algo si se puede.
Te comento. Tu estás considerando siempre dos áreas, pero vamos a hacernos una imagen mental, para que sea más fácil entender donde quiero ir a parar.
imagina que tienes una espda y luchas contra otro que también tiene una espada. El área de cada uno, entonces es uno mismo y las dimensiones de la propia espada. es fácil de entender, verdad?
Bien, entonces la cuestión es... a quién le importa, tu espalda o 'su' espalda?. quiero decir, que la intercepción se basará en un punto, y no es preciso un área.
Supongamos que 'el jugador' es This (tu, yo, el que lo lea que se ponga en primera persona) y que el 'enemigo' es el área (rect).... con esto y lo dicho previamente pasemos al pseudocódigo...
Clase cThis
entero X, Y, Width, Height
entero Right, Bottom
// Asignación de todos los datos del área (se reposiciona y redimensiona)
Funcion MoverYDimensionar(rect Area) // puedes pasar valores individuales, (x,y,Width,Height) o incluso solo dos puntos de la diagonal principal '\' y calcular como proceda, o bien sobrecargar la función si se usan más que solo una.
This.x = Area.X
This.y = Area.Y
This.Width = Area.Width
This.Height = Area.Height
This.Right = (This.X + This.Width)
This.Bottom = (This.Y + This.Height)
Fin Funcion
// Cuando se desplaza (pero mantiene el tamaño):
// ('Inc'remento indica si los valores son relativos o absolutos)
Funcion Mover(entero X, entero Y, buleano Inc)
Si (Inc = FALSE)
This.X = X
This.Y = Y
Sino
This.X += X
This.Y += Y
Fin si
This.Right = (This.X + This.Width)
This.Bottom = (This.Y + This.Height)
Fin funcion
// Cuando se cambia de tamaño (pero mantiene su posición):
// ('Inc'remento indica si los valores son relativos o absolutos)
Funcion Dimensionar(entero Witdth, entero Height, buleano Inc)
Si (Inc = FALSE)
This.Width = Width
This.Height = Height
Sino
This.Width += Width
This.Height += Height
Fin si
This.Right = (This.X + This.Width)
This.Bottom = (This.Y + This.Height)
Fin Funcion
// y por fin la detección de la colisión.
// El detector de colisión, ahora exige menos matemáticas.
Buleano = Funcion ColisionaCon(cThis cT)
// si de entrada se aleja horizontalmente, no perdemos tiempo en comprobaciones verticales
Si ( cT.Rigth > This.X) y (cT.X < This.Right) luego
Devolver ( cT.Bottom > This.Y) y (cT.Y < This.Bottom)
Sino
Devolver FALSE
Fin si
Fin Funcion
Fin clase
Tanto 'nosotros' (player) como el 'enemigo' seríamos instancias de cThis, y se llamaría así:
Si Player.ColisionaCon(Enemigo) luego
...
Funciona y es más rápido, porque:
A - Se calcula una única vez, el valor 'Right y Botton', y se guardan, en lo sucesivo ya no se calculan. Por tanto cada vez que haya que hacer la detección de colisión, nos ahorramos 4 sumas.
B - También contribuye a la velocidad que la comparación la dividimos en dos pasos, primero horizontal y luego vertical, (no importa si fuera al revés, de hecho si fuere más frecuente los movimientos verticales, sería mejor poner delante la comprobación vertical). al dividirlo en dos pasos no forzamos una posterior comprobación si la previa ya falló, pero incluso si es necesario la segunda comprobación también es ligera (no realiza sumas).
En Resumen, la detección ahora solo requiere:
2 ó 4 comparaciones y 0 sumas
Antes requería:
4 comparaciones y 4 sumasLas sumas se hacen una sola vez cuando se establece/modifica el tamaño o se reposiciona, pero no con cada verificación de colisión.
Aunque al final viene a ser lo mismo, sin embargo el momento es diferente, al mover o redimensionar, no suele haber tanta carga de trabajo, luego... deja más tiempo para actualizar valores, en cambio cuando se exige detectar suele haber más trabajo 'pesado' en curso, entonces aligerar de ahí es adecuado.
En resumen, desplazamos la carga de trabajao a momentos menos activos, aligerando los momentos más activos. Aunque siempre va a depender de cada caso concreto...
...pero bueno, lo que pedías es posible...
---------------------
p.d.: Al publicar ya había más respuestas... te comento: asegúrate tras rehacer tu código que funciona en todos los casos... he aquí una imagen de los casos posibles (considera el cuadro rosado como el jugador y los azules como el enemigo), falta el caso de que el jugador esté completamente dentro del área del enemigo (el cuadro rosa dentro de uno azul), en las imágenes quedaba sobrecargado y se prestaba a confusión así que la he evitado.