Foro de elhacker.net

Programación => Programación General => Mensaje iniciado por: Tachikomaia en 3 Noviembre 2025, 20:53 pm



Título: El meteoro, cuya trayectoria se curva cada vez menos, debe...
Publicado por: Tachikomaia en 3 Noviembre 2025, 20:53 pm
terminar en el centro sin haber tocado las paredes.

Ya analicé esto bastante y no encuentro el motivo de la falla.

Explicaré este video:
https://youtu.be/O3L7eNHPpp8

Cuando el meteoro sale desde la nave naranja, o cuando la toca, se le asigna (medio al azar) una rotación hacia un lado u otro.

Y una velocidad (también) hacia arriba, hacia la nave azul.

Por ahora, quiero que en ese caso, cuando el meteoro vaya a tocar la nave azul, el meteoro esté en el centro de la pantalla.

En el video se ve que en esos casos queda en cualquier lado, a veces choca contra una pared porque va muy hacia un costado, otras va un poco al centro pero no suficiente, etc.

Eso es lo que quiero arreglar.

Por ejemplo, sabiendo que el meteoro debido a la rotación se moverá cierta cantidad de píxeles hacia la izquierda, hay que asignarle una velocidad X hacia la derecha para contrarrestar. ¿Cuánto se debe asignar, cómo se calcula? Es lo que quiero averiguar.

En cada frame, o ejecución del código, la velocidad X del meteoro es influída por su rotación así:
MeteorXSpeed = MeteorXSpeed+MeteorRotation/1000

Luego la rotación disminuye así:
MeteorRotation = MeteorRotation/1.01;

No sé si necesitan más que eso.

Los cálculos los intento así:

Calculo la distancia Y entre el meteoro y el lugar Y al que debe llegar:
DistanciaY = MeteorY-ApuntandoY;

Calculo cuántos frames o ejecuciones tardará en llegar hasta ese punto (o línea, es el eje X, en un punto de Y):
TardanzaY = Math.ceil(DistanciaY/-MeteorYSpeed);

La distancia X entre el meteoro y el lugar X al que debe llegar:
DistanciaX = ApuntandoX+400-MeteorX;
400 es la mitad x de la pantalla.

Cuánto se va a mover el meteoro debido a la rotación:
MovimientoPorCurva = MeteorRotation*0.101*(1-Math.pow(1.01, -TardanzaY));
Creo haber comprobado que esa fórmula está bien.

Finalmente: La velocidad X que el meteoro debe tener para que cuando llegue a la nave azul, el meteoro esté en el medio de la pantalla:
MeteorXSpeed = DistanciaX/TardanzaY-MovimientoPorCurva/TardanzaY;
También creo haber comprobado que eso está bien, aunque tengo más dudas.

Entiendo que quizá haya algún error de mi lenguaje, que maneja mal los decimales, pero no debería haber las diferencias abismales que hay.

Puedo asignar los valores que quieran para ir buscando el motivo del error:
- Rotación inicial
- Velocidad Y inicial.
- Posición X inicial

Les pongo un ejemplo de salida de datos:
MeteorRotation: 10
MeteorYSpeed: -1.85306421986458
ApuntandoX: 0
ApuntandoY: 20.5
DistanciaY: 525
TardanzaY: 284
DistanciaX: 0
MovimientoPorCurva: 0.950151782573888
MeteorXSpeed: -0.00334560486821792
Frames: 260
MeteorX final: 568.329278266145
InfluenciaDeRotacion final: 0.934008644681193

La rotación fue poca, y cuando eso sucede no termina tan alejado de x 400, pero hay bastante diferencia entre 400 y 568.
Frames es la cantidad de frames o ejecuciones ocurridas. Es menor que tardanzaY, eso puede ser un problema, pero mi teoría es que como el meteoro es grande el choque con la nave azul se capta antes de que su centro llegue al punto calculado. Y yo no observo que por 24 frames más vaya a cambiar mucho, además cuando llega arriba se está alejando del medio, o sea, la distancia sería aún mayor.
InfluenciaDeRotacion final es lo que medí, con el programa, que la rotación influyó. O sea, hizo que el meteoro se mueva 0.9 algo hacia la derecha. La diferencia con lo que calculé, MovimientoPorCurva, es mínima así que no debería haber problema.

El meteoro debe terminar en x 400 ¿por qué no lo hace?

Les dejo el archivo editable y el ejecutable:
https://drive.google.com/file/d/1vRwS4DG3JhaKutOI1FEW-vjmTfNR0u9Z/view?usp=sharing

Lo que supongo relevante del código, puede que falte algo:
Código
  1. function MeteorMoves () {
  2. MeteorXSpeed = MeteorXSpeed+MeteorRotation/1000*MeteorYDirection;
  3. if (MeteorYDirection == 1) {
  4. InfluenciaDeRotacion = InfluenciaDeRotacion+MeteorRotation/1000;
  5. trace("InfluenciaDeRotacion: "+InfluenciaDeRotacion);
  6. }
  7. MeteorRotation = MeteorRotation/1.01;
  8. MeteorX = MeteorX+MeteorXSpeed;
  9. Meteor._x = MeteorX;
  10. MeteorY = MeteorY+MeteorYSpeed;
  11. Meteor._y = MeteorY;
  12. if (Meteor.hitTest(Player) && MeteorYSpeed>0) {
  13. // Determinar rotación y velocidad Y al azar:
  14. MeteorRotation = Math.random()*(180+Dificultad)*(2*random(2)-1);
  15. MeteorYSpeed = -Math.random()*(2+Dificultad)-1;
  16. // Distancia Y desde el meteoro hasta el punto hacia donde se lo apuntó:
  17. DistanciaY = MeteorY-ApuntandoY;
  18. // Cuánto tardará el meteoro en recorrerla:
  19. TardanzaY = Math.ceil(DistanciaY/-MeteorYSpeed);
  20. // Distancia X desde el meteoro hasta el punto hacia donde se lo apuntó:
  21. DistanciaX = ApuntandoX+400-MeteorX;
  22. // Determinar cuánto de moverá debido a la curva (falta considerar la reducción):
  23. MovimientoPorCurva = MeteorRotation*0.101*(1-Math.pow(1.01, -TardanzaY));
  24. // Determinar la velocidad X para que el meteoro llegue...
  25. // al punto X apuntado justo cuando llega al punto Y apuntado:
  26. MeteorXSpeed = DistanciaX/TardanzaY-MovimientoPorCurva/TardanzaY;
  27.  

Si lo testean, tengan en cuenta que InfluenciaDeRotacion no tendrá el valor debido si el meteoro choca con una pared, se resetea cuando toca la nave naranja.
Y no, que eso falle no es la causa de que el programe falle, eso es sólo un contador para ver que MovimientoPorCurva se haya calculado bien.


Título: Re: El meteoro, cuya trayectoria se curva cada vez menos, debe...
Publicado por: Tachikomaia en 9 Noviembre 2025, 04:28 am
Puse que la velocidad del meteoro sea alta, -100, o sea va muy rápido hacia arriba, pero también puse que el juego funcione muy lento, aunque eso no importa en lo que descubrí.
Resulta que estaba midiendo mal la influencia de la rotación.
Puse que la rotación sea 1000 sin disminución, por lo que es 1+2+3+4+5, es decir 15, pero miren los resultados:
MeteorRotation: 1000
MeteorYSpeed: -100
ApuntandoX: 0
ApuntandoY: 20.5
DistanciaY: 525
TardanzaY: 6
DistanciaX: 0
MeteorXSpeed: 0

InfluenciaDeRotacion: 1
Frames: 1
MeteorX: 401

InfluenciaDeRotacion: 2
Frames: 2
MeteorX: 403

InfluenciaDeRotacion: 3
Frames: 3
MeteorX: 406

InfluenciaDeRotacion: 4
Frames: 4
MeteorX: 410

InfluenciaDeRotacion: 5
Frames: 5
MeteorX: 415

Frames: 5
MeteorX final: 415
InfluenciaDeRotacion final: 5

Ah, no puse cambios en la velocidad X, es 0, así que la posición X del meteoro sólo es influída por la rotación, como ven termina en 415, significa que la rotación influyó 15, pero lo que medí que influyó fue sólo 5, medí mal, mido así:
InfluenciaDeRotacion = InfluenciaDeRotacion+MeteorRotation/1000;
Supongo que con eso mido lo que influye extra en cada frame, sin incluir lo que influye por lo de antes. En vez de ir sumando 1+2+3... sumo lo que aumentó cada vez, 1+1+1...
Supongo que debo sumar la velocidad X cada vez, restando la inicial ¿cada vez?

Seguiré probando...


Título: Re: El meteoro, cuya trayectoria se curva cada vez menos, debe...
Publicado por: Tachikomaia en 23 Noviembre 2025, 08:26 am
Creo que ya Deepseek y yo lo resolvimos.

Para que se vea claro:
- Quité las paredes.
- Puse que al tocar la nave azul el meteoro vaya derecho (sino podría salirse de la pantalla).
https://youtu.be/FYUkhNFrLsU

Al tocar la nave naranja, el meteoro va hacia arriba y termina en el centro aproximadamente sin importar la rotación inicial.

Solución:
Cuando el meteoro toca la nave naranja:
Código
  1. if (Meteor.hitTest(Player) && MeteorYSpeed>0) {
  2. // Determinar rotación y velocidad Y al azar:
  3. MeteorRotation = Math.random()*(180+Dificultad)*(2*random(2)-1);
  4. MeteorYSpeed = -Math.random()*(2+Dificultad)-1;
  5. // Distancia Y desde el meteoro hasta el punto hacia donde se lo apuntó:
  6. DistanciaY = MeteorY-ApuntandoY;
  7. // Cuánto tardará el meteoro en recorrerla:
  8. TardanzaY = Math.ceil(DistanciaY/-MeteorYSpeed);
  9. // Distancia X desde el meteoro hasta el punto hacia donde se lo apuntó:
  10. DistanciaX = ApuntandoX+400-MeteorX;
  11. // Determinar cuánto de moverá debido a la curva (falta considerar la reducción):
  12. MovimientoPorCurva = MeteorRotation/1000*(101*TardanzaY-10100+10100*Math.pow(1.01, -TardanzaY));
  13. // Determinar la velocidad X para que el meteoro llegue...
  14. // al punto X apuntado justo cuando llega al punto Y apuntado:
  15. MeteorXSpeed = (DistanciaX-MovimientoPorCurva)/TardanzaY;

ApuntandoY y ApuntandoX es que se está apuntando hacia arriba y al centro, ya lo puedo cambiar, pero era en vano si no podía hacer que la velocidad X se ajuste a la rotación.

Lo que Deepseek me dijo evidentemente es la fórmula esta:
MovimientoPorCurva = MeteorRotation/1000*(101*TardanzaY-10100+10100*Math.pow(1.01, -TardanzaY));

La conversación:
https://chat.deepseek.com/share/16y0pm66c099tzo5cb
Si no la ven copio los mensajes, pero como tienen fórmulas matemáticas con "renglones" y otras cosas, sería complicado.