Buen entretenimiento...
Solo un detalle inicial: en el juego original de
asteroids lo único que rotaba era la nave del jugador.
En cuanto al procedimiento... debes realizar lo siguiente (una de las muchas soluciones).
* En algún lugar tienes definidas las coordenadas de dibujo de la nave, relativas al centro de la propia nave, que serán las coordenadas (0,0) y se supone que será también el centro de giro.
* A medida que la nave se mueve por la pantalla, llevas el control de su centro de giro (te sirve además para computar las colisiones con el resto de los objetos). Supongamos que sean ($nave_x, $nave_y).
* Cuando el usuario desea rotar la nave, incrementas o decrementas el valor de ese giro, en el ángulo de giro de la nave. Sea ($nave_a) ese ángulo.
* A la hora de pintar la nave, el procedimiento entonces es:
1. Partiendo de las coordenadas originales de definición de la nave, obtienes las nuevas coordenadas, giradas un ángulo $nave_a. Las fórmulas a aplicar son las indicadas por ti, salvo que puedes eliminar toda referencia a ($x0, $y0), ya que las coordenadas de las que partes son (0,0) (el centro de giro), por lo que no es necesario tomarlas en cuenta. Todas las coordenadas van a girar con respecto a ese centro, y como está en el (0,0), las fórmulas se simplifican.
2. Ya teniendo las coordenadas de los puntos de la nave, giradas, hay que trasladarlas al punto de dibujo final. Como el centro de giro de la nave en juego es ($nave_x,$nave_y), resulta que esto se traduce en sumar esas coordenadas de ese centro a cada una de las coordenadas de la nave.
El resultado es la nave, girada, en un punto del espacio 2D. Estos dos pasos los puedes realizar en un solo bucle, ya que el cálculo del "desplazamiento" de las coordenadas de la nave girada en el centro (0,0) no es afectada por la rotación.
Quedaría:
Using perl Syntax Highlighting
$x1[$i] = int( cos($nave_a) * $x[$i] - sin($nave_a) * $y[$i] ) + $nave_x;
$y1[$i] = int( sin($nave_a) * $x[$i] + cos($nave_a) * $y[$i] ) + $nave_y;Coloreado en 0.002 segundos, usando
GeSHi 1.0.8.4
Si estuviéramos en clase de álgebra, diríamos que hemos hecho una traslación, un giro, y una nueva traslación.
En un sentido purista, eso es lo que habría que hacer: a partir de las coordenadas de la nave en su situación espacial en un momento dado, girarla (primero traiéndola al (0,0), girando, y luego desplazándola a su posición final, o segundo, girándola directamente en su posición final 'si' sabemos cuales son las coordenadas del centro de giro). El problema con este planteamiento es que estamos trabajando con coordenadas enteras (posiciones de pixel), pero las operaciones trigonométricas, no. Poco a poco, y debido a la pérdida de la precisión en cada movimiento o giro, la nave se irá deformando. Podríamos evitándolo guardando las coordenadas con un montón de decimales, en lugar de valores enteros, pero al final, siempre hay errores de redondeo.
Pero este es un caso especial: la nave siempre es la misma y queremos que siempre mantenga su aspecto. Por eso giramos siempre a partir de las coordenadas originales de la nave. Eso nos asegura una apariencia idéntica en todas las situaciones y ángulos de rotación.
Una vez resuelto el problema, aparece la necesidad de mejorar el rendimiento: las operaciones trigonométricas son muy costosas para la CPU. Una solución es cambiar cálculo por espacio. Si suponemos que hacemos incrementos de ángulo de 10°, eso significa que solo necesitamos almacenar 35 juegos de coordenadas de dibujo de la nave. Eso lo podemos calcular muy rápido al principio del programa, con lo que, durante el juego, no necesitaremos hacer ningún cálculo trigonométrico: nos bastará con extraer el juego de coordenadas correspondiente al ángulo de giro de la nave en ese momento.
P.D. Las operaciones matemáticas en Perl necesitan ser expresadas en radianes. Puedes usar la función deg2rad() del módulo
Math::Trig para hacer la conversión en el caso de que quieras trabajar con grados.