Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Ayuda con cálculos para que la trayectoria de una pelota cumpla ciertas condicio

Iniciado por Tachikomaia, 29 de Abril de 2023, 07:45:19 AM

« anterior - próximo »

Tachikomaia

Nota: Esto lo escribí en noviembre, puede que haya cambiado algunas cosas, perdón pero no le veo sentido a revisar todo.

1- Su velocidad de caída aumenta 0.01 por segundo (segundo es un decir, es más bien una centésima de segundo).

2- Sus velocidades hacia los costados (X), adelante (Y, arriba) y arriba (Z, distancia con respecto al suelo) deben ser acordes a la fuerza del jugador que realiza el tiro. La velocidad hacia abajo aumentará, pero me refiero a las velocidades iniciales. Si por ejemplo tiene fuerza 4 y aplicó 3 para que la pelota avance 3 pixeles (es un decir) por segundo entonces no puede ser que la pelota se eleve 2 pixeles por segundo, ya que la fuerza que queda disponible es sólo 1.

3- Cuando llega a la red la Z de la pelota debe ser igual o mayor a cierto valor, es decir, se debe preestablecer un valor que represente la mínima Z con la que la pelota pasa por encima de la red sin tocarla, y cuando llegue a la red debe tener ese valor o uno mayor. En mi caso es 17.5 pero elijan el que gusten.

4- Debe caer en la cancha rival.

5- Las velocidades deben ser tales que la pelota caiga en cierto punto. Por ejemplo:


6- Su velocidad hacia adelante (Y) debe ser la máxima posible.


Es decir, se intenta que se cumpla una condición en tanto eso no cause que no se cumplan las otras.
3- Se quiere que la pelota pase por encima de la red, pero sin que ello implique que haya caído más/menos de lo que debe (condición 1) ni que se le haya aplicado más fuerza de la que se estableció como posible (condición 2). Si el jugador no tiene suficiente fuerza como para que se cumpla esta condición, no se cumple.
4- La oración anterior.
5- Lo mismo. Si para cumplir las condiciones anteriores es necesario que el tiro no vaya tan diagonal como se quiere, entonces no irá tan así, irá más bien verticalmente.
6- En tanto se cumplan las condiciones anteriores... Si la fuerza es 10 la velocidad Y no debe ser mayor que eso. Si queriendo asignar determinada fuerza a Y luego sin importar cuánta se asigne a Z la pelota no pasa la red o no cae en la cancha rival, entonces habrá que reducir la velocidad Y...


Por si los necesitan o quieren, les dejo los datos del caso (pero pueden inventar otros, lo que sí debe tenerse en cuenta es que no necesito simplemente averiguar 3 numeritos basados en otros, sino un método para averiguarlos teniendo en cuenta que los otros pueden variar, por ejemplo se puede elegir hacer un saque hacia al medio o puede que el personaje tenga distinta fuerza):
NOTA: Ignoren lo de "_level0."
  Variable _level0.AlexFuerza = 10
  Variable _level0.BallX = 417
  Variable _level0.BallY = 548
  Variable _level0.BallZ = 43.8
  Variable _level0.DistanciahastaDestinoX = 136.9
  Variable _level0.DistanciahastaDestinoY = 368
  Variable _level0.DistanciahastaRed = 248
  Variable _level0.DistanciahastaMinsafeBallZ = 26.3


Gracias.

Ah: El incremento de Y está invertido, es decir, entre más abajo más valor.
0,0________600,0
0,800______600,800


ACTUALIZADO:
Intenté seguir un método que me recomendaron pero la persona desapareció, así que a ver si alguien lo puede completar. Esto es lo que tengo:
Código completo:
[spoiler]// La mínima BallZ que no toca la red es 18.6.
fscommand ("fullscreen", "true");
Fuerzaderebotedepelota = -0;
// En ese caso menos es más.
Influenciadelrozamiento = 0.02;
AlexFuerzadebrazos = 2000;
Alextimetodownracket = (10-Math.floor(AlexFuerzadebrazos/1000))*2+5;
Alextimetoupracket = Alextimetodownracket*2;
AlexFuerzadepiernas = 1000;
AlexFuerzadetiros = (AlexFuerzadebrazos/1000+AlexFuerzadepiernas/5000)*1;
Alexrunspeed = AlexFuerzadepiernas/10000;
Alexrunspeedonserving = AlexFuerzadepiernas/1000;
AlexMinXposonserving = 408+Alexrunspeedonserving;
AlexMaxXposonserving = 512-Alexrunspeedonserving;
// ///////////////////////////////////////////////////////
// ////////////////////  Saca Alex  //////////////////////
// ///////////////////////////////////////////////////////
AlexX = 460;
AlexY = 548;
attachMovie("AlexMovie", "Alex", 100);
setProperty (Alex, _x, AlexX);
setProperty (Alex, _y, AlexY);
MaxBallZwhenstriked = 0;
Teclafuesoltada = 0;
// ///////////////////////////////////////////////////////
// ///////////////////////  Alex  ////////////////////////
// ///////////////////////////////////////////////////////
function Alexmovetoserve () {
// Se asume que el jugador elevó la pelota y no soltó la tecla, o que quizá empezó el juego con la tecla presionada.
// Hasta que se capte que la tecla no está presionada no se podrá elevar la pelota.
// Es para evitar que en caso de mantener la tecla presionada se eleve la pelota a penas vuelva a la mano.
if (Key.isDown(37)) {
// Se mueve a la izquierda, si no se sale del límite.
if (AlexX>AlexMinXposonserving) {
AlexX = AlexX-Alexrunspeedonserving;
} else {
AlexX = AlexMinXposonserving-Alexrunspeedonserving;
}
setProperty (Alex, _x, AlexX);
} else if (Key.isDown(39)) {
// Se mueve a la derecha, si no se sale del límite.
if (AlexX<AlexMaxXposonserving) {
AlexX = AlexX+Alexrunspeedonserving;
} else {
AlexX = AlexMaxXposonserving+Alexrunspeedonserving;
}
setProperty (Alex, _x, AlexX);
}
if (Teclafuesoltada == 0) {
if (Key.isDown(65)) {
} else {
Teclafuesoltada = 1;
// Ahora al presionar la tecla de nuevo Alex elevará la pelota.
}
} else if (Key.isDown(65)) {
// Tecla A, eleva la pelota.
Funcencurso = "Alexelevandoball";
Teclafuesoltada = 0;
// Qué tan arriba está la pelota y a qué Velocidad sube (todo al revés).
BallZ = -37.6;
BallZSpeed = -0.4;
Alex.gotoAndStop(2);
gotoAndStop (3);
}
}
//
function Alexelevandoball () {
if (Teclafuesoltada == 1 && Key.isDown(65)) {
// La tecla fue soltada y vuelta a presionar; Alex saca.
// La pelota y su sombra, que estaban en la movie Alex (para que se pudieran mover simplemente con mover a Alex), ahora son attached al lv0.
Funcencurso = "Alexserving";
BallX = AlexX+9;
BallY = AlexY;
attachMovie("BallShadowMovie", "BallShadow", 50);
setProperty (BallShadow, _x, BallX);
setProperty (BallShadow, _y, BallY);
BallZ = BallZ*-1;
BallZoom = 100+BallZ;
attachMovie("BallMovie", "Ball", 99);
setProperty (Ball, _x, BallX);
setProperty (Ball, _y, BallY-BallZ);
setProperty (Ball, _xscale, BallZoom);
setProperty (Ball, _yscale, BallZoom);
Timesincebeginserve = -1;
Alex.gotoAndStop(3);
setProperty (Alex.Chispa, _y, BallZ*-1-getProperty("Ball", _height)/2);
setProperty (Alex.Chispa, _xscale, AlexFuerzadetiros*10);
setProperty (Alex.Chispa, _yscale, AlexFuerzadetiros*10);
// Datos para determinar velocidades del tiro.
DistanciahastaDestinoX = 280.1-BallX;
DistanciahastaDestinoY = 180-BallY;
DistanciahastaMinsafeBallZ = BallZ-18.6;
BallZwhenstriked = BallZ;
DistanciahastaDestinoXY = Math.sqrt(DistanciahastaDestinoX*DistanciahastaDestinoX+DistanciahastaDestinoY*DistanciahastaDestinoY);
DistanciahastaRed = DistanciahastaDestinoXY * Math.abs(BallY-300) / DistanciahastaDestinoY;
// Determinando velocidades del tiro.
BallXSpeed = DistanciahastaDestinoX/DistanciahastaDestinoXY*AlexFuerzadetiros;
BallYSpeed = DistanciahastaDestinoY/DistanciahastaDestinoXY*AlexFuerzadetiros;
BallZSpeed = 0;
// Datos para determinar posiciones de la pelota.
Tiempotranscurridodeltiro = 0;
BallXwhenstriked = BallX;
BallYwhenstriked = BallY;
Ballreachedred = 0;
gotoAndStop (4);
} else {
if (Teclafuesoltada == 0) {
// Aún no se soltó la tecla.
if (Key.isDown(65)) {
} else {
Teclafuesoltada = 1;
// Ahora al presionarla de nuevo Alex saca.
}
}
// Disminuye la velocidad de subida y varía la altura.
BallZSpeed = BallZSpeed+0.01;
BallZ = BallZ+BallZSpeed;
if (BallZ<MaxBallZwhenstriked) {
MaxBallZwhenstriked = BallZ;
}
setProperty (Alex.Ball, _y, BallZ);
// Varía el tamaño de la pelota.
BallZoom = 100+BallZ*-1;
setProperty (Alex.Ball, _xscale, BallZoom);
setProperty (Alex.Ball, _yscale, BallZoom);
if (BallZ>=-37.6) {
// Si queda muy abajo (BallZ muy alto), vuelve a la etapa Alexmovetoserve.
Teclafuesoltada = 0;
Funcencurso = "Alexmovetoserve";
Alex.gotoAndStop(1);
gotoAndStop (2);
}
}
}
//
function Ballmoving () {
Tiempotranscurridodeltiro = Tiempotranscurridodeltiro+1;
BallX = BallXwhenstriked+BallXSpeed*Tiempotranscurridodeltiro;
setProperty (BallShadow, _x, BallX);
setProperty (Ball, _x, BallX);
BallY = BallYwhenstriked+BallYSpeed*Tiempotranscurridodeltiro;
setProperty (BallShadow, _y, BallY);
DistanciaXYrecorrida = AlexFuerzadetiros * Tiempotranscurridodeltiro * C;
Senodelangulodeltiro = Math.sqrt(1-C*C);
BallZ = BallZwhenstriked + AlexFuerzadetiros * Tiempotranscurridodeltiro * Senodelangulodeltiro;
BallZ = BallZ - 0.01 * Tiempotranscurridodeltiro*Tiempotranscurridodeltiro /2;
// BallZSpeed = BallZSpeed-0.01;
// BallZ = BallZ+BallZSpeed;
if (BallZ<=0) {
// Si la pelota llega al suelo, BallZSpeed se invierte con disminución según la cancha.
BallZ = 0;
BallZSpeed = BallZSpeed*Fuerzaderebotedepelota;
// Si BallZSpeed es menor que 0.01: Queda en 0.
if (BallZSpeed<0.01) {
BallZSpeed = 0;
}
// La pelots, al rozarse con el suelo, disminuye sus velocidades.
// BallXSpeed = BallXSpeed+Influenciadelrozamiento;
if (BallXSpeed>0) {
BallXSpeed = 0;
}
// BallYSpeed = BallYSpeed+Influenciadelrozamiento;
if (BallYSpeed>0) {
BallYSpeed = 0;
}
}
setProperty (Ball, _y, BallY-BallZ);
BallZoom = 100+BallZ;
setProperty (Ball, _xscale, BallZoom);
setProperty (Ball, _yscale, BallZoom);
if (Ballreachedred == 0) {
if (BallY <= 300) {
        // Si llegó a la red.
        Ballreachedred = 1;
        BallZwhenreachedred = BallZ;
attachMovie("BallShadowMovie", "BallShadow2", 49);
setProperty (BallShadow2, _x, BallX);
setProperty (BallShadow2, _y, BallY);
attachMovie("BallMovie", "Ball2", 98);
setProperty (Ball2, _x, BallX);
setProperty (Ball2, _y, BallY-BallZ);
setProperty (Ball2, _xscale, BallZoom);
setProperty (Ball2, _yscale, BallZoom);
        }
    }
}
//
function Alexserving () {
Ballmoving();
Timesincebeginserve = Timesincebeginserve+1;
if (Timesincebeginserve == Alextimetodownracket) {
// Desaparece la chispa y Alex queda con la raqueta abajo.
Alex.gotoAndStop(5);
} else if (Timesincebeginserve == 5) {
// Deaaparece la chispa.
Alex.gotoAndStop(4);
} else if (Timesincebeginserve == Alextimetoupracket) {
// Alex queda listo para moverse, etc.
Alex.gotoAndStop(6);
gotoAndStop (5);
// Funcencurso = ""; hay q ver si el saque toca la red.
}
}
// falta indicar dirección
// El rozamiento funciona mal, uno se reduce a 0 antes que el otro.
// El tamaño de la chispa debería depender de cuánta fuerza se use, no de la usable.
// Asignar demasiada fuerza hace que la animación no ocurra bien
Funcencurso = "Alexmovetoserve";
[/spoiler]

Sólo lo relevante:
[spoiler] // La mínima BallZ que no toca la red es 18.6.
// Datos para determinar velocidades del tiro.
DistanciahastaDestinoX = 280.1-BallX;
DistanciahastaDestinoY = 180-BallY;
DistanciahastaMinsafeBallZ = BallZ-18.6;
BallZwhenstriked = BallZ;
DistanciahastaDestinoXY = Math.sqrt(DistanciahastaDestinoX*DistanciahastaDestinoX+DistanciahastaDestinoY*DistanciahastaDestinoY);
DistanciahastaRed = DistanciahastaDestinoXY * Math.abs(BallY-300) / DistanciahastaDestinoY;
// Determinando velocidades del tiro.
BallXSpeed = DistanciahastaDestinoX/DistanciahastaDestinoXY*AlexFuerzadetiros;
BallYSpeed = DistanciahastaDestinoY/DistanciahastaDestinoXY*AlexFuerzadetiros;
BallZSpeed = 0;
// Datos para determinar posiciones de la pelota.
Tiempotranscurridodeltiro = 0;
BallXwhenstriked = BallX;
BallYwhenstriked = BallY;
function Ballmoving () {
Tiempotranscurridodeltiro = Tiempotranscurridodeltiro+1;
BallX = BallXwhenstriked+BallXSpeed*Tiempotranscurridodeltiro;
BallY = BallYwhenstriked+BallYSpeed*Tiempotranscurridodeltiro;
        DistanciaXYrecorrida = AlexFuerzadetiros * Tiempotranscurridodeltiro * C;
        Senodelangulodeltiro = Math.sqrt(1-C*C);
        BallZ = BallZwhenstriked + AlexFuerzadetiros * Tiempotranscurridodeltiro * Senodelangulodeltiro;
        BallZ = BallZ - 0.01 * Tiempotranscurridodeltiro*Tiempotranscurridodeltiro /2;
}
[/spoiler]

Si el personaje tiene poca fuerza:
https://drive.google.com/file/d/1bY60WE73Gvh7eUFoRX8NAeuBoWIaYtNJ/view?usp=share_link

Algún error cometí o cometió porque el personaje está aplicando más fuerza de la que tiene y además la pelota debe pasar más cerca de la red.

Con un poco más:
https://drive.google.com/file/d/1YEhAz8nrcztWpttScLOeMekfXlZHUVZ9/view?usp=share_link

¿Qué está mal en el código? ¿o qué falta, qué hago?

mariahcarey

Asegúrate de que la velocidad hacia abajo también cumpla con la restricción de aumento de 0.01 por segundo.

telldesigner

Los problemas realmente difíciles requieren conocimientos para dar respuestas adecuadas. Disfrute de las diversas actualizaciones de conocimientos. Experimenta más!

ughtomato

Cita de: mariahcarey en 02 de Noviembre de 2023, 05:04:11 AMAsegúrate de que la velocidad hacia abajo también cumpla con la restricción de aumento de 0.01 por segundo.

Agrega la influencia del rozamiento en las velocidades X y Y de manera más adecuada. Deberías reducir estas velocidades gradualmente con el tiempo en función del rozamiento, de modo que la pelota se desacelere conforme se acerque a la meta (la red y la cancha rival).






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.