Tutorial: Control de personaje, parte 1 Año: 2011 V.: AS3
[e]
Si algún día nos proponemos programar un juego seguramente echaremos mano de la clase KeyboardEvent para detectar los eventos de teclado
y realizar acciones según la tecla pulsada.
En el caso de querer controlar los movimientos de un personaje empezaríamos declarando los listeners apropiados de la siguiente manera.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
//Escucha cualquier tecla pulsada stage.addEventListener(KeyboardEvent.KEY_DOWN,onKey); //Escucha cualquier tecla soltada stage.addEventListener(KeyboardEvent.KEY_UP,outKey); function onKey(event:KeyboardEvent):void { //Mostramos el código de la tecla pulsada trace(event.keyCode); } function outKey(event:KeyboardEvent):void { //Mostramos el código de la tecla soltada trace(event.keyCode); } |
Una de las características de los eventos de teclado es que mientras permanezcamos pulsando una tecla, el evento se repite de manera constante, esto quiere decir que llamara a la función asociada por cada entrada de frame mientras mantengamos la tecla presionada.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
//Pulsamos la tecla W cuyo código es 87 stage.addEventListener(KeyboardEvent.KEY_DOWN,onKey); function onKey(event:KeyboardEvent):void { /*Se muestra el código por cada entrada de frame mientras mantengamos la tecla pulsada. */ trace("Código tecla "+event.keyCode); } /*Resultado Código tecla 87 Código tecla 87 Código tecla 87 Código tecla 87 Código tecla 87 Código tecla 87 Código tecla 87 ... */ |
Esta característica en según que casos nos puede servir, pero en mi caso no me resultaba útil, imaginemos que queremos manejar un movieclip por pantalla cuyo contenido es un conjunto de fotogramas que representan los estados de una animación de un personaje, si queremos que el personaje salte mandaremos la cabeza lectora al fotograma «saltar» y reproduciremos la animación de saltar.
1 2 3 4 5 6 7 8 9 10 11 |
//Pulsamos la tecla W cuyo código es 87 stage.addEventListener(KeyboardEvent.KEY_DOWN,onKey); function onKey(event:KeyboardEvent):void { // Si la tecla pulsada es la tecla W cuyo codigo es 87 entonces if(event.keyCode == 87){ /*Enviamos la cabeza lectora del personaje_mc al fotograma "saltar" y reproducimos la animación. */ personaje_mc.gotoAndPlay("saltar"); } } |
Aquí podemos observar que nos encontramos con un problema, mientras mantengamos la tecla W pulsada, la acción personaje_mc.gotoAndPlay(«saltar»); se va a estar ejecutando de forma indefinida enviando la cabeza lectora siempre al fotograma «saltar» y no veremos ninguna animación.
Para solucionar este problema deberíamos impedir que el evento se produzca de forma indefinida, es decir que solo llame a la función solamente una vez aunque mantengamos la tecla pulsada, para conseguirlo anduve haciendo varias pruebas y al final la mejor solución que encontré fue la siguiente.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
//CONTROL DEL TECLADO //Crea un bucle que se repite por cada entrada de frame stage.addEventListener(Event.ENTER_FRAME,onFrame); //Variables que serviran para desplazar el mapa el numero de pixeles indicado en ellas; var xPos:Number = 0; var yPos:Number = 0; //Escucha cualquier tecla pulsada; stage.addEventListener(KeyboardEvent.KEY_DOWN,onKey); //Escucha cualquier tecla soltada; stage.addEventListener(KeyboardEvent.KEY_UP,outKey); //almacenará el código de tecla para poder comparar.; var key:int; //Función que recibirá el evento cuando se pulse una tecla. function onKey(event:KeyboardEvent):void { //recuperamos el código de la tecla pulsada. var code:int = event.keyCode; /* Impedimos llamar la función indefinidamente mientras no se cambie de tecla es decir mientras el código de key y el código de code sean iguales la sentencia no se cumplirá, en caso contrario si el código de key no es igual al código de code entonces... */ if (key != code) { /* Envía el código de tecla y el valor 1 como true para decirle a la función keyEvent que la tecla esta pulsada. */ keyEvent(code,1); /* Igualamos el código de la variable key con el código de la tecla pulsada contenido en la variable code .*/ key = code; } } //Función que recibirá el evento cuando se suelte una tecla. function outKey(event:KeyboardEvent):void { //recuperamos el código de la tecla soltada. var code:int = event.keyCode; /*Envía el código de tecla y el valor 0 como false para decirle a la función keyEvent que la tecla a sido soltada. */ keyEvent(code,0); /*Si la tecla soltada es igual a la tecla pulsada entonces reiniciamos las variable para permitir detectar la misma tecla de nuevo si no hiciéramos esto lo que ocurriría es que si soltamos la tecla pulsada y la volvemos a pulsar no funcionaria. */ if (key == code) { key = 0; } } /*Creamos un Array que servirá para almacenar los valores 1 y 0 Por ejemplo si pulsamos la tecla W cuyo código es 87 entonces crearemos en el Array un índice en la posición 87 y le asignaremos el valor 1 si soltáramos la tecla W entonces actualizaríamos el índice 87 del Array con el valor 0. */ var ka:Array = new Array(); /*Funcion que se ejecuta cada vez que presionamos o soltamos una tecla, recive 2 parametros el codigo de la tecla pulsada o soltada para el parametro k y un valor 1 y 0 para el parametro s. */ function keyEvent(k,s) { /*Como solo nos interesa comprobar las teclas implicadas solo permitiremos que la sentencia se cumpla si son estas teclas*/ if (k == 65 || k == 68 || k == 37 || k == 39 || k == 87 || k == 40 || k == 38 || k == 83) { /*Asignamos un espacio en el array con el mismo nombre que el numero de tecla y le pasamos como valor 0 o 1. */ ka[k] = s; /*Comparamos el valor del índice X del array sabiendo que cada índice corresponde a una tecla si contiene un 1 entonces sabemos que a sido pulsada si contiene un 0 entonces a sido soltada.*/ //Key[W] or Key[Up] and Key[D] then move UpRigth("ArribaDerecha"); if ((ka[87]||ka[38])&&ka[68]) { //go to frameName and set rotation goTo("move",-150); /*Seteamos la variable xPos a -4 (negativo) para que el mapa se desplace hacia la izquierda a una velocidad de 4 pixeles*/ xPos = -4; /*Seteamos la variable yPos a 4 para que el mapa se desplace hacia abajo a una velocidad de 4 pixeles*/ yPos = 4; //Key[D] and Key[S] or Key[Down] then move DownRigth("AbajoDerecha"); } else if (ka[68]&&(ka[40]||ka[83])) { goTo("atras",150); xPos = -2; yPos = -2; //Key[S] or Key[Down] and Key[A] then move DownLeft("AbajoIzquierda"); } else if ((ka[40]||ka[83])&&ka[65]) { goTo("atras",-150); xPos = 2; yPos = -2; //Key[A] and Key[W] or Key[Up] then move UpLeft("IzquierdaArriba"); } else if (ka[65]&&(ka[87]||ka[38])) { goTo("move",150); xPos = 4; yPos = 4; //Key[W] or Key[Up] then move Up("Arriba"); } else if (ka[87] || ka[38]) { goTo("move",180); yPos = 4; xPos = 0; //Key[D] then move Rigth("Derecha"); } else if (ka[68]) { /* Invertimos escala para reaprovechar desplazamiento izquierdo para desplazamiento derecho. */ hero.scaleX = -1; goTo("desplzLateral",200); xPos = -3; yPos = 0; //Key[S] or Key[Down] then move Down("Abajo"); } else if (ka[83] || ka[40]) { goTo("atras",180); yPos = -2; xPos = 0; //Key[A] then move Left("Izquierda"); } else if (ka[65]) { goTo("desplzLateral",160); //Reinvertimos de nuevo hero.scaleX = 1; xPos = 3; yPos = 0; //Key[Left] then rotate Left("Rotar Izquierda"); } else if (ka[37]) { /*No hay animacion para esta tecla por lo que asignamos el frame "relax" La animacion deberia representar los pasos que damos cuando pivotamos a la izquierda sobre nosotros mismos, es decir si rotaramos el pj en un mapa ficticio*/ goTo("relax",180); //seteamos xPos e yPos a 0 para que no se mueva xPos = 0; yPos = 0; //Key[Rigth] then rotate Rigth("Rotar Derecha"); } else if (ka[39]) { /*No hay animacion para esta tecla por lo que asignamos el frame "relax" la animacion deberia representar los pasos que damos cuando pivotamos a la derecha sobre nosotros mismos, es decir si rotaramos el pj en un mapa ficticio*/ goTo("relax",180); //seteamos xPos e yPos a 0 para que no se mueva xPos = 0; yPos = 0; //No Key? then Relax } else { /*Si ninguna de las teclas han sido pulsada ni soltada entonces ponemos al personaje en "relax". */ goTo("relax",180); //seteamos xPos e yPos a 0 para que no se mueva xPos = 0; yPos = 0; } }//End if check Keys } /* Funcion encargada de enviar el cabezal al fotograma apropiado y de rotar el personaje hero mediante los parámetros action y rotate. */ function goTo(action,rotate):void { if (action == "relax") { hero.gotoAndStop(action); } else { hero.gotoAndPlay(action); } hero.rotation = rotate; } /* Función que se repite por cada entrada de frame y mueve el mapa según los pixeles indicados en xPos e yPos.*/ function onFrame(e:Event):void { world.mapa.x += xPos; world.mapa.y += yPos; } |
Mismo código de ejemplo pero sin comentarios:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
stage.addEventListener(Event.ENTER_FRAME,onFrame); var xPos:Number = 0; var yPos:Number = 0; stage.addEventListener(KeyboardEvent.KEY_DOWN,onKey); stage.addEventListener(KeyboardEvent.KEY_UP,outKey); var key:int; function onKey(event:KeyboardEvent):void { var code:int = event.keyCode; if (key != code) { keyEvent(code,1); key = code; } } function outKey(event:KeyboardEvent):void { var code:int = event.keyCode; keyEvent(code,0); if (key == code) { key = 0; } } var ka:Array = new Array(); function keyEvent(k,s) { if (k == 65 || k == 68 || k == 37 || k == 39 || k == 87 || k == 40 || k == 38 || k == 83) { ka[k] = s; if ((ka[87]||ka[38])&&ka[68]) { goTo("move",-150); xPos = -4; yPos = 4; } else if (ka[68]&&(ka[40]||ka[83])) { goTo("atras",150); xPos = -2; yPos = -2; } else if ((ka[40]||ka[83])&&ka[65]) { goTo("atras",-150); xPos = 2; yPos = -2; } else if (ka[65]&&(ka[87]||ka[38])) { goTo("move",150); xPos = 4; yPos = 4; } else if (ka[87] || ka[38]) { goTo("move",180); yPos = 4; xPos = 0; } else if (ka[68]) { hero.scaleX = -1; goTo("desplzLateral",200); xPos = -3; yPos = 0; } else if (ka[83] || ka[40]) { goTo("atras",180); yPos = -2; xPos = 0; } else if (ka[65]) { goTo("desplzLateral",160); hero.scaleX = 1; xPos = 3; yPos = 0; } else if (ka[37]) { goTo("relax",180); xPos = 0; yPos = 0; } else if (ka[39]) { goTo("relax",180); xPos = 0; yPos = 0; } else { goTo("relax",180); xPos = 0; yPos = 0; } } } function goTo(action,rotate):void { if (action == "relax") { hero.gotoAndStop(action); } else { hero.gotoAndPlay(action); } hero.rotation = rotate; } function onFrame(e:Event):void { world.mapa.x += xPos; world.mapa.y += yPos; } |
ejemplo:
Pulsa las teclas W,A,S,D y las de dirección up, down, left, rigth. Notarás que las teclas left y rigth no hacen nada porque estarían destinadas a la rotación de un posible mapa y no hay animación para ellas.
.
[download id=»27″ format=»2″]
.
Partiendo de este ejemplo no seria difícil crear una clase pero esto ya lo dejo para vosotros.
Bueno ya hemos visto una manera de controlar a nuestro personaje en un juego, espero que sirva de ayuda y si alguien encuentra o sabe de una formula mejor le invito a compartirla en este blog.
saludos
3 comments on “AS3 – Tutorial – Control de personaje – Parte 1 – Mediante eventos de teclado y KeyboardEvent”
muy buen aporte me ayudas mucho gracias
Muchísimas gracias! Me ha sido de completa utilidad!
Fonseca