Dos veces al mes, volvemos a visitar algunas de las publicaciones favoritas de nuestros lectores de toda la historia de Activetuts +. Este tutorial se publicó por primera vez hace mucho tiempo, en mayo de 2009..
A continuación, describiré cómo crear una escena 3D básica con las opciones 3D nativas de Flash Player 10. Luego, explicaré cómo agregar interactividad a los elementos y configurar un juego de pong básico. Vamonos?
Preparemos el escenario y creemos la escena 3D. En un juego de mesa regular, la pelota rebota en la parte superior e inferior de la pantalla, pero como estamos agregando algo de perspectiva a la mezcla, también deberemos proporcionar estos bordes. Se necesitan cinco clips de movimiento: el piso y las cuatro paredes (dos de las cuales son paletas en realidad). Los puntos de registro de las paredes deben estar ubicados contra el piso. Puede crear todo esto simplemente con la herramienta Rectángulo o usar una imagen de mapa de bits importada (recuerde activar "Permitir suavizado" en las propiedades). Haga un clip de movimiento de cada una de las paredes y dele un nombre de instancia (las llamé "wallTop", "wallBottom", "wallLeft" y "wallRight" y las consultaré más adelante). Nombra el fondo "piso".
Selecciona todas las paredes y el piso, crea un gran clip de movimiento de esos y llámalo "bg".
Para mostrar la puntuación más adelante, también necesitaremos dos campos de texto dinámico. Si los colocas dentro del movieclip "bg" también tendrán la perspectiva 3D. Nombra estos "scoreLeft" y "scoreRight" y luego incrusta las fuentes.
Crea la bola usando la herramienta ovalada y degradada en el escenario. No coloque la bola dentro del movieclip "bg" o la perspectiva lo distorsionará. No le daremos a la pelota propiedades reales en 3D, sino que la haremos actuar como si fuera 3D. Coloca la bola en el centro de la pantalla y dale un nombre de instancia como "bola".
Ahora configuraremos la escena 3D utilizando las nuevas propiedades de rotación X, Y y Z que se agregaron en Flash Player 10. Sin embargo, antes de que podamos ejecutar algún código ActionScript, necesitamos crear la clase de documento. Crea un Main.as vacío y rellénalo con el código de abajo.
paquete import flash.display.MovieClip; public class Main extiende MovieClip public function Main (): void // Reemplace este comentario con el código más adelante
Ahora, para usar esto como la clase principal, podemos completar "Principal" en el cuadro de entrada "Clase:" de las propiedades de los documentos..
Probemos la rotación. Agregue esta línea a la función Main () para darle a todo algo de perspectiva:
bg.rotationX = -30;
Como puede ver, todos los clips de movimiento ahora se giran 30 ° alrededor del eje x.
Cada una de las paredes necesita una rotación de 90º para levantarse. Como puede ver, también he cambiado el modo de fusión de las paredes a "pantalla" para que los gradientes se vean mejor. El siguiente código es solo para propósitos de vista previa, ya que lo reemplazaremos por interpolaciones en el siguiente paso (así que elimínelo después de la prueba).
bg.wallTop.rotationX = 90; bg.wallBottom.rotationX = -90; bg.wallRight.rotationY = 90; bg.wallLeft.rotationY = -90;
Para agregar un efecto a las paredes primero debemos crear un botón de inicio. Cree un clip de película con el texto "Haga clic aquí para comenzar". De nuevo, puedes colocar esto dentro de "bg" si quieres que también tenga una perspectiva. Asígnele un nombre de instancia como "startText". Ahora podemos referenciarlo en el código y agregarle un eventlistener. También establezca buttonMode en true, que devolverá un cursor de mano cuando el mouse se desplace sobre el botón. Cuando se hace clic, se llama a la función de inicio y se oculta el botón. También ocultamos el puntero del mouse porque el usuario controlará la pared derecha con el mouse.
función pública Main (): void bg.rotationX = -30; startText.addEventListener (MouseEvent.MOUSE_UP, inicio); startText.buttonMode = true; inicio de función privada (_e: Evento): void startText.buttonMode = false; startText.visible = false; Mouse.hide (); // Esto contendrá las interpolaciones
Podemos usar TweenLite para interpolar las paredes de 0 a 90 ° de rotación. Por supuesto, cualquier motor de interpolación funcionará, pero prefiero este. El siguiente código interpolará las paredes en 2 segundos y utilizará la función de suavizado "Bounce.easeOut". Para interpolar el valor alfa de las paredes también debemos establecerlo en 0 primero. Puede hacer esto en Flash estableciendo el alfa en 0 en la configuración de color. Una vez que se completen estas interpolaciones, el juego debería comenzar, así que agregue una propiedad "onComplete" a una de las interpolaciones y adjúntele un nombre de función (puede dejar esto fuera para la prueba ya que la función aún no existe).
inicio de la función privada (_e: Evento): void startText.buttonMode = false; startText.visible = false; Mouse.hide (); nuevo TweenLite (bg.wallRight, 2, rotationY: 90, alpha: 1, ease: Bounce.easeOut); nuevo TweenLite (bg.wallLeft, 2, rotationY: -90, alpha: 1, ease: Bounce.easeOut); nuevo TweenLite (bg.wallTop, 2, rotationX: 90, alpha: 1, ease: Bounce.easeOut); nuevo TweenLite (bg.wallBottom, 2, rotationX: -90, alfa: 1, facilidad: Bounce.easeOut, onComplete: goBall);
Antes de que podamos comenzar el juego, necesitaremos agregar interactividad a las paredes izquierda y derecha y al balón. Vamos a empezar con la paleta del jugador. Cree una nueva clase "Player.as" y agregue el siguiente código.
paquete import flash.display.MovieClip; import flash.events.MouseEvent; public class Player extiende MovieClip public function Player (): void stage.addEventListener (MouseEvent.MOUSE_MOVE, moveAlong); función privada moveAlong (_e: MouseEvent): void var mousePos: Number = stage.mouseY - parent.y; si (mousepos < 0 ) y = 0; else if ( mousePos > 340) y = 340; else y = mousePos;
En el constructor (la función Player), agregamos un listador de eventos al escenario para verificar cuándo se mueve el mouse y llamar a la función "moveAlong" siempre que lo haga. En la función moveAlong calculamos la posición local del mouse (solo la posición y, ya que solo nos estamos moviendo verticalmente). A continuación, verificamos si el mouse se sale de los límites y restablecemos la posición si lo hace. Encontré el valor 340 por prueba y error ya que "parent.height - height" no devuelve el valor esperado cuando usamos la perspectiva 3D.
A continuación, cambie las propiedades del movieclip wallRight; marque "Exportar para ActionScript" y configure la Clase en "Jugador". Deje "Clase base" vacío.
Crear la IA es muy similar a crear el jugador. Solo que esta vez haremos que se mueva hacia el valor y de la pelota, pero con una velocidad ligeramente menor que la pelota. Crear otra clase "AI.as":
paquete import flash.display.MovieClip; import flash.events.Event; la clase pública AI amplía MovieClip public function AI (): void addEventListener (Event.ENTER_FRAME, followBall); Función privada followBall (_e: Evento): void var ball: MovieClip = MovieClip (parent.parent) .ball; if (ball.xspeed || ball.yspeed) var newy: Number = ball.y - height; if (newy> 345) newy = 345; Si y <= newy ) y += 9; else y -= 9;
Primero necesitamos poder hacer referencia a la pelota. Dado que el movieclip wallLeft está dentro del movieclip "bg", llamar a "parent" hará referencia a "bg". Por esta razón necesitamos usar "parent.parent". La primera declaración "if" verifica si la bola tiene una x o yspeed. Estas son variables públicas de la bola que pondremos más adelante. La comprobación evita que la IA se mueva antes de que comience el juego. El valor "newy" contiene el valor y de la bola menos la altura de wallLeft. Este es el valor al que debe moverse para golpear la bola. Como antes, cambia la clase de wallLeft a "AI".
La pelota necesita la mayor funcionalidad: necesita moverse, rebotar en las paredes, buscar un golpe con las palas y actualizar su propia profundidad, ya que no es un objeto 3D.
paquete import flash.display.MovieClip; import flash.events.Event; la clase pública Ball extiende MovieClip public var xspeed: Number = 0; public var yspeed: Number = 0; función pública Ball (): void public function start (): void xspeed = -12; yspeed = 12; addEventListener (Event.ENTER_FRAME, moveBall); función privada moveBall (_e: Event): void depth (); colisión(); x + = velocidad; y + = yspeed; profundidad de la función privada (): vacío // Escala la pelota según su posición y función privada colisión (): vacío // Haz que rebote la bola
En primer lugar le damos a la pelota una x y una yspeed. Estos se configuran en público para que podamos verificar desde otros objetos si la bola se está moviendo. A continuación, agregue un "onenterframe" eventlistener a la función de inicio. Cuando se llama la función de inicio, la bola comenzará a mover cada cuadro. Le di a la pelota una velocidad inicial de 12 píxeles por cuadro. Puedes cambiar esto para acelerar el juego, pero también puedes subir la velocidad de fotogramas. La función moveBall en realidad aumenta los valores de x e y de la bola en función de x y yspeed. También llama a las funciones de profundidad y colisión en cada cuadro..
Debido a que la bola no es un objeto 3D y no tiene valor z, no aparecerá más pequeña una vez que cambie el valor y. Cuanto más alto esté el balón en la pantalla (valor bajo y), más pequeño debería aparecer. Podemos cambiar esto simplemente escalando en función de su posición:
profundidad de la función privada (): vacío var más pequeño: Número = ((y / stage.stageHeight) * 0.6) + 0.6; escalaX = escalaY = menor;
La función de "colisión" decidirá cómo y cuándo la pelota rebotará sobre otros objetos. En la primera declaración "si", simplemente verificamos el valor de y para averiguar si la bola toca la pared superior o inferior. Nuevamente encontré estos valores por prueba y error porque la bola necesita rebotar de una manera plausible. Si la verificación es verdadera, se cambia la velocidad de y así que la bola cambia la dirección vertical.
función privada collision (): void if (y> = 463 || y <= 105 ) yspeed *= -1;
Verificar los bordes x no es tan fácil debido a la perspectiva y las paletas que se mueven. Podemos realizar un "hitTest" con las paredes y enviar el balón si es verdadero. Los HitTests son un poco pesados, por lo que es mejor no usarlos en exceso. Sin embargo, debido a que estamos tratando con un juego de pong simple, no ralentizará notablemente el juego. Sin embargo, agregué un cheque extra; para ver si el valor x de la bola está en el lado izquierdo o derecho del escenario y verifique la pared en consecuencia. Esto asegura que solo se necesita un hitTest por fotograma en lugar de dos.
if ((x> stage.stageWidth / 2 && hitTestObject (MovieClip (parent) .bg.wallRight)) || (x < stage.stageWidth / 2 && hitTestObject( MovieClip(parent).bg.wallLeft)) ) xspeed *= -1;
Por último, necesitamos averiguar si la pelota todavía está en la plataforma. Podemos averiguar si un punto en la parte inferior de la bola todavía se encuentra en el "piso". El punto exacto tiene el valor x de la bola y el valor del radio más y. Si esto es cierto, averiguamos si la bola se disparó en el lado izquierdo o derecho (nuevamente, comparando el valor de x con el centro de la pantalla) y actualizamos la puntuación de manera acorde. Al final, establece los valores x e y de la bola de nuevo en el centro para que el juego pueda continuar.
if (! MovieClip (parent) .bg.floor.hitTestPoint (x, y + (altura / 2 * escalaY), verdadero)) if (x < stage.stageWidth / 2 ) MovieClip(parent).bg.scoreRight.text = Number(MovieClip(parent).bg.scoreRight.text) + 1; else MovieClip(parent).bg.scoreLeft.text = Number(MovieClip(parent).bg.scoreLeft.text) + 1; y = stage.stageHeight / 2; x = stage.stageWidth / 2;
Cambia la Clase de la bola a "Bola"..
Ahora que hemos creado las paletas y la pelota, todo lo que se necesita es poner el juego en acción. Agregue esta función a la clase Main y asegúrese de que onComplete que usamos en el paso 6 hace referencia a esta función.
función privada goBall (): void ball.start ();
Después de que se haya actualizado el marcador, la pelota simplemente regresa al centro y comienza a rodar nuevamente. Necesitamos animar el balón un poco al volver antes de que el juego comience de nuevo..
Reemplace este código en la función de colisión de la bola:
y = stage.stageHeight / 2; x = stage.stageWidth / 2;
Por:
xspeed = yspeed = 0; removeEventListener (Event.ENTER_FRAME, moveBall); y = - altura; x = stage.stageWidth / 2; escala var: Número = (0.5 * 0.6) + 0.6; nuevo TweenLite (este, 1.5, y: stage.stageHeight / 2, scaleX: scale, scaleY: scale, facilidad: Bounce.easeOut, onComplete: start);
Esto evitará que la bola se mueva primero. A continuación, establece la posición de la bola justo encima de la pantalla, pero centrada horizontalmente. Si luego usamos la función de aceleración de rebotes, aparecerá como si la bola cayera desde arriba justo antes de reiniciar el juego..
Espero que hayas podido seguir sin demasiados problemas. El juego tal como está ahora es muy básico y puede usar algunas mejoras. La pelota, por ejemplo, siempre rebota en esquinas de 90 °, lo que hace que el movimiento sea muy predecible..
Si desea seguir avanzando, puede intentar variar la velocidad de x y la yspeed según la forma en que la bola golpea la paleta (compare los valores de y). La detección de colisiones con las palas no es ni mucho menos perfecta, pero le muestra una forma básica de verificar un golpe. Por último, si no usaste gradientes para las paredes, notarás que la bola parece rodar sobre la pared inferior en lugar de desaparecer debajo de ella. Para solucionar este problema, puede separar fácilmente los objetos que deberían aparecer sobre la bola y colocarlos en un nuevo clip de película que distorsione tanto como el clip de película "bg" y colocar más alto que la bola en Flash.