Estoy tratando de entender este problema de Hello World-y en el desarrollo de juegos. He creado un juego TicTacToe en XNA, así que supongo que el siguiente paso sería un clon de Breakout .
Tenga en cuenta que no tengo ningún conocimiento de programación de juegos de matemáticas o incluso lo que debería aplicarse a dónde. Por eso estoy haciendo esta pregunta.
A la pregunta: ¿Cómo puedo determinar dónde debe rebotar la pelota cuando golpea la paleta en la parte inferior de la pantalla?
Me imagino que sería algo así como:
- Capture la velocidad y el ángulo de la pelota entrante.
- Detecta dónde tocó la barra (extremo izquierdo, extremo derecho, centro) y de acuerdo con eso dale una mayor velocidad si tocó las áreas externas.
- Aquí es donde estoy atrapado. Jeje.
Alguna idea? Me doy cuenta de que esta no es una pregunta del tipo de respuesta directa, pero estoy seguro de que es una pregunta que todos enfrentan en algún momento.
Estoy leyendo el libro Álgebra lineal que se recomendó en este sitio web, pero todavía no tengo idea de si debo aplicarlo aquí.
Respuestas:
Aquí está la lógica relevante que usé en el pong en mi página de inicio : (por favor, juegue antes de leer, para que sepa el efecto que estoy logrando con el siguiente código)
Esencialmente, cuando la pelota choca con la pala, su dirección se ignora por completo; se le da una nueva dirección de acuerdo a qué tan lejos del centro de la pala chocó. Si la pelota golpea la paleta justo en el centro, se envía exactamente horizontal; Si golpea justo en el borde, vuela en un ángulo extremo (75 grados). Y siempre viaja a una velocidad constante.
Tome el valor medio Y de la pala y reste la intersección Y de la pelota. Si la paleta tiene una altura de 10 píxeles, este número estará entre -5 y 5. Yo lo llamo la "intersección relativa" porque ahora está en el "espacio de la paleta", la intersección de la pelota con respecto al centro de la paleta.
Tome la intersección relativa y divídala por la mitad de la altura de la pala. Ahora nuestro número de -5 a 5 es un decimal de -1 a 1; se normalizó . Luego multiplíquelo por el ángulo máximo por el cual desea que la pelota rebote. Lo configuré en 5 * Pi / 12 radianes (75 grados).
Finalmente, calcule las nuevas velocidades de la pelota, usando trigonometría simple.
Es posible que este no sea el efecto que busca, o que también desee determinar una velocidad multiplicando la intersección relativa normalizada por una velocidad máxima; esto haría que la pelota vaya más rápido si golpea cerca del borde de una pala, o más lenta si golpea cerca del centro.
Un vector contiene velocidad y dirección, implícitamente. Almaceno mi vector como "vx" y "vy"; es decir, la velocidad en la dirección x y la velocidad en la dirección y. Si no ha tomado un curso introductorio de física, esto puede parecerle algo extraño.
La razón por la que hago esto es porque reduce los cálculos necesarios por cuadro; cada cuadro, simplemente lo hace
x += vx * time;
yy += vy * time;
donde el tiempo es el tiempo desde el último cuadro, en milisegundos (por lo tanto, las velocidades están en píxeles por milisegundo).Con respecto a la implementación de la capacidad de curvar la pelota:
En primer lugar, necesitaría saber la velocidad de la pala en el momento en que golpea la pelota; lo que significa que necesitaría hacer un seguimiento del historial de la pala, para poder conocer una o más de las posiciones pasadas de la pala para poder compararlas con su posición actual para ver si se movió. (cambio de posición / cambio en el tiempo = velocidad; por lo que necesita 2 o más posiciones, y los tiempos de esas posiciones)
Ahora también necesita rastrear una velocidad angular de la pelota, que prácticamente representa la curva a lo largo de la que viaja, pero es equivalente al giro de la pelota en el mundo real. De manera similar a cómo interpolaría el ángulo de rebote desde la posición relativa de la pelota en colisión con la pala, también necesitaría interpolar esta velocidad angular (o giro) desde la velocidad de la pala en colisión. En lugar de simplemente establecer el giro como lo hace con el ángulo de rebote, es posible que desee sumar o restar el giro existente de la pelota, porque eso tiende a funcionar bien en los juegos (el jugador puede notar que la pelota está girando y hacer que gire) incluso más salvajemente, o contrarresta el giro en un intento de hacer que viaje en línea recta).
Sin embargo, tenga en cuenta que, si bien este es el sentido más común y probablemente la forma más fácil de implementarlo, la física real de un rebote no depende únicamente de la velocidad del objeto que golpea; un objeto sin velocidad angular (sin giro) que golpea una superficie en ángulo tendrá un giro impartido sobre él. Esto podría conducir a una mejor mecánica de juego, por lo que es posible que desee investigar esto, pero no estoy seguro de la física detrás de esto, así que no voy a tratar de explicarlo.
fuente
Ha pasado un tiempo desde que hice esto, pero creo que lo he hecho bien.
Dada una colisión perfecta, el ángulo de reflexión es igual al ángulo de incidencia.
Conoces la normalidad de tu remo (suponiendo una superficie plana): N Conoces la posición original de tu pelota (al comienzo de tu paso de tiempo): P Conoces tu nueva posición de la pelota (al final del paso de tiempo): P 'Conoces tu punto de colisión: C Suponiendo que calculaste que el segmento P -> P' pasa a través de tu pala, tu nueva posición reflejada (P '') sería:
P '+ 2 * (N * (P' punto -N))
La subexpresión N * (P 'dot -N) calcula la profundidad a lo largo de la colisión normal que recorrió la pelota. El signo menos es corregir el hecho de que estamos verificando la profundidad opuesta a la dirección de lo normal.
El P '+ 2 *, la parte de la subexpresión, mueve la pelota hacia atrás por encima del plano de colisión 2 veces la profundidad de la colisión.
Si desea una colisión menos que perfecta, cambie el factor 2 para que sea (1 + (1-k)) donde k es su coeficiente de fricción. Una colisión perfecta tiene un valor k de 0, lo que hace que el ángulo de reflexión sea exactamente el del ángulo entrante. Un valor k de 1 provoca una colisión donde la bola permanecería en la superficie del plano de colisión.
Su nuevo vector de velocidad, V '', dirección sería P '' - C. Normalícelo y multiplíquelo por su velocidad entrante y su magnitud de velocidad resultante sería la misma, pero en la nueva dirección. Puede simular con esa velocidad multiplicándola por un coeficiente, l, que aumentaría (l> 1) o disminuiría (l <1) la velocidad resultante.
Para resumir:
P '' = P '+ (1-k) * (N * (P punto -N)) V' '= l * V * ((P' '- C) / | P' '- C |)
Donde k y l son coeficientes de su elección.
fuente
La reflexión puede hacerse "bien" o "fácil".
La forma "correcta" es calcular vectores perpendiculares a las paredes. En 2D eso es bastante fácil y probablemente puedas codificarlos. Luego, el paso de reflexión esencialmente deja intacto el componente "paralelo" del movimiento e invierte el componente "perpendicular". Probablemente hay información detallada en la web para esto, incluso en MathWorld.
La forma "fácil" es negar el movimiento X o Y cuando golpeas una pared. Si golpeas las paredes laterales, negarías X. Si golpeas la parte superior niegas Y. Si quieres acelerar la pelota, solo aumenta lo que quieras; puede acelerarlo en su dirección actual multiplicando las velocidades X e Y o puede acelerar solo en un eje.
fuente
También estoy haciendo un juego arkanoid-ish y creo que la solución sobre cómo debe comportarse la pelota al golpear la pala es bastante más simple y más rápida que entrar en el enfoque de pecado / cos ... funciona bien para los propósitos de un juego como este Esto es lo que hago:
Por supuesto, dado que la velocidad de la bola aumenta en el tiempo, interpolo los pasos x / y antes / después para mantener una detección de colisión precisa, recorriendo todos los "pasos X" y "pasos Y" que se calculan dividiendo cada componente de velocidad por el módulo del vector formado por las posiciones actuales y futuras de la pelota.
Si ocurre una colisión contra la pala, divido la velocidad Y entre 20. Este "20" es el valor más conveniente que encontré para obtener mi ángulo máximo resultante cuando la pelota golpea a los lados de la pala, pero puede cambiarlo a lo que sea sus necesidades son, solo juegue con algunos valores y elija el mejor para usted. Al dividir, digamos una velocidad de 5, que es mi velocidad inicial del juego por este número (20), obtengo un "factor de rebote" de 0.25. Este cálculo mantiene mis ángulos bastante proporcionales cuando la velocidad aumenta en el tiempo hasta mi valor de velocidad máxima que, por ejemplo, podría ser 15 (en ese caso: 15/20 = 0,75). Teniendo en cuenta que mis palas x, y coords están en el medio (x e y representan el centro de la pala), entonces multiplico este resultado por la diferencia entre la posición de la pelota y la posición de la pala. Cuanto mayor es la diferencia, cuanto mayor sea el ángulo resultante. Además, al usar una paleta intermedia, obtienes el signo correcto para el incremento x dependiendo del lado donde golpee la pelota sin tener que preocuparte por calcular el centro. En pseudocódigo:
Para n = 0 al módulo ...
si collision_detected entonces speedX = - (speedY / 20) * (paddleX - ballX); velocidadY = -velocidadY;
salida; terminara si
...
x = x + stepX; y = y + stepY;
fin para
Recuerde, siempre trate de mantener las cosas SIMPLES. ¡Espero que ayude!
fuente
La paleta en Breakout, cuando sigue el estilo que está describiendo, generalmente se modela como una superficie curva. El ángulo de incidencia cambia en función de dónde golpea la paleta. En el punto muerto, la línea tangente a la curva es absolutamente horizontal, y la pelota se refleja como se esperaba. A medida que te alejas del centro, la tangente a la curva se vuelve cada vez más angulada y, como resultado, la pelota se refleja de manera diferente.
El punto clave es que el ángulo de reflexión, no la velocidad de la pelota, es lo que cambia. La velocidad de la pelota generalmente solo aumenta lentamente con el tiempo.
fuente
angle = 1 - 2 * (ball.x - paddle.left) / paddle.width
le dará un número entre 1 y -1; esto (multiplicado por un valor ajustado para la mecánica del juego) es la pendiente de la línea tangente en el punto en que colisionó la pelota. Refleje esa línea en lugar de la estrictamente horizontal.Nolan Bushnell dio una conferencia magistral en SIEGE el pasado fin de semana y habló sobre un problema similar con el pong original. No tiene que hacer muchos cálculos complicados. Si golpeas hacia la parte izquierda del panel, envía la pelota hacia la izquierda. Haz lo mismo para el lado derecho.
Para comenzar, puede hacer que el ángulo para los lados izquierdo y derecho sea de 45 grados. Una vez que termine el juego, podría hacerlo si desea volver y hacer esto más complicado, pero para empezar, hágalo lo más simple posible.
fuente
Breakout es un trabajo clásico para principiantes para comenzar a sumergirse en el mundo de la programación de juegos basada en la física. Básicamente, la pelota tiene un movimiento de rebote cuando golpea la pared. Como alguien sugirió anteriormente, el ángulo de incidencia es igual al ángulo de reflexión. Pero cuando consideras que la pelota golpea la pala. La lógica se divide en 3 secciones. 1.) La pelota golpea la parte central de la pala. 2.) La pelota golpea la parte izquierda de la pala. 3.) La pelota golpea la posición derecha de la pala.
Cuando considera la parte central: no necesita diferir el efecto de rebote de lo que se aplica al golpear la pelota. La pelota simplemente se desvía normalmente, pero cuando se golpea en cualquier dirección, el caso es diferente.
Cuando la pelota es golpeada en el lado izquierdo, es decir, considere la pelota que viene del lado izquierdo de la pantalla y usted viene con la pala desde el lado derecho. Luego, cuando golpeas la pelota con la porción hacia la izquierda, la pelota debe reflejarse en la dirección de donde vino. Igual es el caso al revés. En la parte derecha también se aplica lo mismo.
Este movimiento de la pelota hacia la izquierda o hacia la derecha cuando está siendo golpeada la hace más creíble.
Espero que tengas la idea, al menos lógicamente, gracias.
fuente
Imagine que calcula la distancia entre el centro de la pala y el punto donde la bola Y golpeó y la llamó
d
. Supongamos qued
tiene un valor positivo cuando la pelota golpea por encima del centro de la pala. Ahora puede agregard * -0.1
a la velocidad Y de su bola y comenzará a cambiar de dirección. ¡Aquí hay un ejemplo en javascript que se puede traducir fácilmente a c #!fuente
esto ayudará a http://www-classes.usc.edu/engr/ee-s/477p/s00/pong.html simplemente invertir x e y dependiendo de dónde golpee la pantalla. si sube y toca la parte superior, invierte la velocidad y manteniendo la velocidad x
fuente
Hola, recientemente he intentado hacer un juego de pelota y encontré una solución para esto. Entonces, lo que hice: la paleta se mueve mientras jugamos. Mi sistema de coordenadas se deja como está, el punto superior izquierdo del lienzo es 0,0. La paleta se mueve en este sistema de coordenadas. El eje x apunta de 0 al ancho del lienzo, y el eje y apunta a 0 a la altura del lienzo. Creé una pala con un tamaño fijo de 100 de ancho y 20 de altura. Y luego dibujo un círculo imaginario a su alrededor. Cuando la pelota golpea la pala, calculo el punto central de la pala
Luego resto el centro de la posición actual de la pelota de esta manera el sistema de coordenadas estará en el centro de la paleta, ballCenter es el punto donde la pelota golpeó la paleta (- (ancho de paleta + r) .. 0 .. (ancho de paleta + r )) esto no es más que reescalar el punto de golpe en la pala
calcule el punto de intersección del círculo con la ayuda del punto de golpe de la bola (x0), esto es una nueva calculación, pedimos la coordenada y en el círculo con la coordenada x0 ya conocida y se necesitaba un giro para el eje y
calcule la derivada de la ecuación normal del círculo que se define alrededor de la paleta con radis paddleRadius f (x, y) = x ^ 2 + y ^ 2-r ^ 2
normalizar el vector N, para obtener un vector unitario para la superficie normal
ahora tenemos las normales de superficie normalizadas (unidad) para la pala. Calcule la nueva dirección con estas normales de superficie, esto se calculará con la ayuda de la fórmula del vector de reflexión: new_direction = old_direction-2 * dot (N, old_direction) * N, pero en cambio con la superficie normal apuntando siempre hacia arriba, la normal estar cambiando de un punto a otro donde la pelota golpea la pala
He publicado mi solución a este problema. Para más detalles y para el juego completo puedes ver mi repositorio de github:
https://github.com/zoli333/BricksGame
escrito en java con eclipse. Hay otra solución para esto comentada en Ball.java, donde el cambio de escala no ocurre. No muevo el sistema de coordenadas al punto central de la paleta, sino que calculo todo esto desde el sistema de coordenadas superior 0.0 relativo a El punto central de la pala. Esto tambien funciona.
fuente