En este artículo, examinaremos el uso de la física para simular efectos de proyectiles en juegos como Angry Birds. Veremos los conceptos básicos del uso de la física 2D en el espacio del mundo del juego, como crear cuerpos y aplicar impulsos y fuerzas..
¿Por qué usar un motor de física? Qué es lo que hace?
Un motor de física nos ayuda a hacer dos cosas muy importantes para nuestro juego:
Detección de colisiones: Los juegos no serían muy divertidos si tu personaje cayera por el suelo antes de que pudieras saltar, o si, cuando golpeas a un enemigo con tu pie, caes en la recta final. La detección de colisiones con un motor de física permite una escucha de contacto muy precisa y permite simular interacciones entre objetos utilizando efectivo.
Simulación de fuerza:Después de una colisión, ¿qué debería pasar? La lógica del juego podría llamarse, podría rebotar, el otro objeto del juego podría rebotar, o simplemente podría seguir sin moverse. Todo esto se maneja detrás de las escenas, usando las fuerzas calculadas del motor. Pero las fuerzas no se limitan al contacto; Pueden ocurrir otras fuerzas, como la gravedad y los impulsos, sin que los objetos se toquen. Las fuerzas afectan las acciones en el juego y el movimiento de objetos, personajes e incluso el espacio del mundo mismo.
Vamos a ver cómo Los motores de física funcionan en breve, pero primero veamos qué motores que desee utilizar, y por qué Puede decidir usarlos, según sus necesidades particulares.
Cuando empiece a pensar en utilizar la física en su juego, deberá decidir cómo desea abordar el problema y qué requerirá su juego en términos de simulación. Tienes dos opciones para usar la física:
Existen varias opciones excelentes para motores de física predefinidos y listos para usar. Una de las opciones más populares para juegos 2D es Box2D; es un motor nativo de C ++ escrito, pero tiene envoltorios, puertos y extensiones que permiten su uso en casi cualquier plataforma 2D. Otra opción popular es Chipmunk 2D, que se usa en varios motores de juegos convencionales, como Cocos2D.
En algunos juegos, usar un motor predefinido no es necesariamente la mejor opción. El uso de un motor de física puede causar una sobrecarga innecesaria cuando no se requiere su función completa. En casos como los juegos de plataformas sencillos o los juegos de romper ladrillos, en los que no necesita la detección de colisiones con un píxel perfecto o algunas de las otras capacidades de un motor, es posible que se consuman recursos innecesariamente que podrían utilizarse mejor en otros lugares..
Construir su propio motor puede darle más flexibilidad sobre el producto final, pero también puede hacer las cosas más complicadas si se trata de más de unos pocos casos de personajes y objetos..
Antes de discutir las propiedades y los detalles de una simulación física, veamos cómo se llama en el bucle de la escena del juego..
El bucle de juego típico se ejecutará a través de lo siguiente para cada fotograma, en orden:
Esto significa que el cálculo de la física resultante es la última tarea realizada en el bucle antes de que se actualice la pantalla. Esto tiene sentido, ya que el punto de la simulación es reaccionar a lo que ha ocurrido dentro del espacio-mundo del juego..
Tenga en cuenta que esta imagen muestra que la física se simula durante cada cuadro de su bucle de juego. Esto puede resultar en una gran sobrecarga si su simulación se vuelve demasiado grande o complicada. Por esta razón, es mejor mantener la administración del juego y las llamadas a la simulación y a sus oyentes limitados.
Ahora tiene sentido discutir dos métodos diferentes de sondear la simulación de física: las tasas de dependencia de marco fijo vs. Considera el Actualización (nula):
Método consistente dentro de la mayoría de los bucles de juego. Este bucle se llama una vez por fotograma de la escena del juego. Si su método de "simular física" se llama desde Actualización (nula):
, La física de tu mundo de juego dependerá de tu velocidad de cuadro, y esto puede Conduce a algunas simulaciones entrecortadas y poco realistas. En iOS, este efecto se ve mitigado por el uso del usesPreciseCollisionDetection
Propiedad booleana, pero ¿qué pasa en otros motores??
Considere el siguiente segmento de código:
CFTimeInterval timeSinceLast = currentTime - self.lastUpdateTimeInterval; self.lastUpdateTimeInterval = currentTime; if (timeSinceLast> 1) timeSinceLast = 1.0 / 60.0;
Este código está diseñado para compensar problemas con el valor delta por el tiempo. Considere una situación en la que estaba jugando el juego en su teléfono y recibió una llamada: le ayudaría a su juego restablecer su delta a la 1/60 esperada (para un juego de 60 fps).
Este es realmente el primer paso en una discusión sobre el desacoplamiento de la simulación física del paso temporal del Actualización (nula):
método. Si bien un intervalo de tiempo modificado sin duda ayudaría en una llamada de simulación de física más estable, no se corrige para todas las situaciones. Para hacer esto, necesitaríamos realmente retirar La llamada de simulación física desde el bucle de renderizado del juego, y crea un ciclo fijo dentro del cual podría ejecutarse. Por ejemplo; Si tu juego está diseñado para funcionar a 60 fps, configuras la física para simular 60 veces por segundo. Este desacoplamiento elimina cualquier inquietud de problemas de renderizado que causan retroalimentación entrecortada en su simulación física.
En resumen, sea concienzudo en su implementación de la física. Si se encuentra usando un motor en un entorno en el que está gravando los recursos del sistema, considere una simulación física de pasos fijos para mantener la imparcialidad y la fidelidad..
UNA duende Es una imagen renderizada en la pantalla de tu juego. Un sprite no tiene propiedades por defecto dentro de una simulación física. Puede "falsificar" algunos de los comportamientos de un mundo físico mediante el uso de propiedades de un sprite, como un cuadro delimitador y una llamada de intersección, pero luego debe escribir toda la lógica resultante. ¿No sería mejor si el juego pudiera manejar todo esto por nosotros??
En estos fragmentos, creamos un sprite:
SKSpriteNode * sprite = [SKSpriteNode spriteNodeWithImageNamed: @ "image"]; sprite.position = ubicación; [auto addChild: sprite];
... y llamar a una colisión entre dos sprites:
-(void) update: (CFTimeInterval) currentTime / * Se invoca antes de que se renderice cada cuadro * / if (CGRectIntersectsRect (sprite1.frame, sprite2.frame)) // haz algo
Física cuerpos son formas "simples" que definen el tamaño aproximado y la forma de su sprite, o quizás definen un área activa de su sprite. Considera lo siguiente:
Un cuerpo físico no está predefinido por la imagen de tu sprite, y es típicamente invisible dentro del juego. Usted crea la forma dinámicamente, a menudo llamando a un método para dibujar la forma que conformará el cuerpo o utilizando un programa que lo ayude a dibujar y definir el cuerpo. A continuación, adjunta el cuerpo al sprite y obtiene acceso a los efectos simulados y las propiedades asignadas a ese cuerpo..
Puedes tener múltiples cuerpos de física atados a un solo sprite. Tomemos, como ejemplo, un sprite de un héroe que lleva una espada. Tendría sentido crear un cuerpo para el personaje héroe y otro para la espada que porta. Esto te permitiría crear una lógica de juego basada en colisiones entre diferentes cuerpos.
En pseudocódigo, la lógica se vería así:
// lógica física - (void) physicsCollisionDidOccur switch (máscara de bits de colisión) caso (Jugador || Espada): // no hacer nada; descanso; caso (Jugador || Enemigo): // ouch !!; descanso; caso (Espada || Enemigo): // hacer daño !!; descanso; por defecto: // no hacer nada; descanso;
Considera la situación de un juego espacial, donde tienes una nave de héroe y una nave enemiga:
Es probable que desee que el cuerpo físico del jugador sea un poco más pequeño que la imagen del sprite base por dos razones:
Colisión visual mejorada: Cuando un jugador choca con un objeto en tu juego, al crear este cuerpo físico más pequeño, las imágenes de sprites se superpondrán temporalmente en el punto de contacto, lo que se ve bien visualmente. (Más allá de este punto: al dibujar valores z, mantenga el carácter de su jugador en el frente de la jerarquía de la escena).
Equidad percibida por el usuario: Para tratar de hacer que su juego se sienta "justo" para el jugador, mantenga el cuerpo capaz de colisionar limitado a la mayor parte del objeto y alejado de salientes extraños como la aleta trasera de la imagen de arriba. De esta manera, no habrá ningún "golpe barato" para molestar a los jugadores de tu juego. A la inversa, normalmente quieres que el cuerpo físico del enemigo tenga al menos el tamaño de la imagen base; Si le damos a nuestro héroe espacial un láser para disparar a su enemigo, un cuerpo enemigo ligeramente demasiado grande hace que sea más razonable para nuestro jugador obtener un impacto. También considere este mismo enfoque para las fichas en un juego de plataformas o rompecabezas que requiere que su jugador salte de una plataforma a otra. Los jugadores están acostumbrados a un poco de "gracia" en este tipo de juegos; extender el cuerpo físico un poco ayudará a mantener su juego razonablemente "justo".
Hay dos tipos principales de cuerpos de física:
Un cuerpo basado en bordes es una línea estática e inamovible que crea un límite para que otros cuerpos colisionen. Tiene un espacio negativo Dentro de ella eso no tiene efecto sobre ningún cuerpo. Una gran aplicación de esto sería crear un límite alrededor de su pantalla para contener cualquier cuerpo dentro de.
Un cuerpo basado en volumen tiene volumen y masa, y puede ser dinámico o estático. Debido a que estos cuerpos tienen masa, los objetos rebotan y pueden verse afectados por los contactos de fuerza. Los cuerpos basados en volumen pueden ser cualquiera de las cuatro formas principales:
Existen algunas limitaciones para usar cuerpos dentro de su motor de física 2D típico. Aquí están las dos limitaciones principales:
Si una forma es convexo, significa que ningún ángulo interior es menor a 180 grados.
Para ser claros, puede ser posible ejecutar simulaciones físicas en formas cóncavas, pero el costo de procesamiento es tan alto que simplemente no es realista para 2D, especialmente cuando se ejecuta en una computadora de mano o un dispositivo menos potente. Cóncavo-me gusta Las formas pueden construirse uniendo dos formas convexas usando algo llamado Articulación estática. Las juntas son otra gran característica disponible con los motores 2D, pero están fuera del alcance de esta discusión..
Cuando una pelota golpea una pared, en el mundo "real" ocurrirá algo como esto:
De tu personaje duende Puede sufrir este tipo de transformación, pero su cuerpo de física. no poder. Puedes controlar ciertas propiedades del cuerpo para afectar su "rebote", pero en realidad no puede tener una forma mutable. Esto se conoce como Cuerpo rígido, lo que significa que el propio cuerpo no puede ser deformado o aplastado.
Veamos brevemente cuáles son algunas de las propiedades más útiles disponibles en un cuerpo de física típico:
La mayoría de los motores tienen más propiedades disponibles que esto, pero para los fines de esta discusión, serán suficientes para comenzar.
En un mundo de física simulada, los cuerpos se mueven por la aplicación de efectivo y impulsos.
Efectivo: Las fuerzas generales típicamente afectan a los cuerpos más gradualmente que los impulsos. Son una fuerza constante que se aplica durante una unidad de tiempo (como la gravedad o un motor).
Impulsos (Fuerzas de Impulso): Los impulsos son ajustes aplicados inmediatamente al impulso de un cuerpo. Los impulsos generalmente se aplican a una simulación basada en la entrada del usuario.
Ahora que comprende la teoría, la mejor manera de consolidar su comprensión de los motores de física de proyectiles es construir uno usted mismo. A continuación, desglosaré el código de un juego simple basado en la física que he escrito, para que pueda ver exactamente cómo funciona.!