Bienvenidos sean a este post, hoy veremos como crear la opcion de poder personalizar o «customizar» los controles para nuestro jugador.
Nuestra «customizacion» o personalizacion de controles lo haremos atraves de la union entre las teclas que le asignemos y las flechas que vinimos usando hasta ahora, esta «union» o binding sera almacenada en nuestro archivo INI, entre todas las opciones que agregaremos seran para cambiar las de direccion, la de Enter y la de Pausa, nuestro primer paso sera crear un nuevo sprite para esta opcion, tal como hicimos con los otros casos y sera para el cambio de botones o teclas, le llamaremos spr_Teclas, les dejo un ejemplo
Nota: Usen la opcion Duplicate para duplicar uno de los sprites que hicimos y ajustenlo a como se ve el ejemplo.

Nota: No olviden establecer el fps a 0.
Recuerden hacerlo de dos subimages y con distintos colores para diferenciar cuando esta seleccionado o no, nuestro siguiente paso sera ir a obj_Pausa, vamos al evento Create y agregaremos la siguiente linea:
union = false;
Esta variable sera la encargada de indicar si existe la vinculacion entre las teclas, esto lo veremos un poco mas adelante, o no por medio de su estado booleano por esta razon la creamos con false, nuestro siguiente paso sera ir al evento Draw y buscaremos el condicional donde establecemos el valor de eleccion:
if (keyboard_check_pressed(vk_up))
{
eleccion = 0;
}
else if (keyboard_check_pressed(vk_down))
{
eleccion = 1;
}
Y lo modificaremos de la siguiente manera:
if (keyboard_check_pressed(vk_up) && !union)
{
if (eleccion <=0) eleccion = 2;
else --eleccion;
}
else if (keyboard_check_pressed(vk_down) && !union)
{
if (eleccion >=2) eleccion = 0;
else ++eleccion;
}
Aca no solo vamos a chequear si presionamos las flechas de arriba o abajo pero siempre y cuando que union sea false, si esto se cumple primero verificamos si presionamos la tecla hacia arriba donde usaremos otro condicional que verifica si eleccion es menor o igual a 0 y en caso de ser verdadero cambiamos a eleccion con el valor de 2 de lo contrario decrenentamos el valor de eleccion, el siguiente condicional trabaja de la misma solo que chequea a union y la flecha hacia abajo, tenemos el mismo condicional pero en este caso si eleccion es mayor o igual a 2 asignaremos el valor de 0 a eleccion de lo contrario incrementamos a eleccion, basicamente lo que hace es pasar a la ultima o primera eleccion dependiendo de si subimos o bajamos pero porque hicimos esto tambien? Porque el anterior estaba pensado para dos opciones y ahora tendremos tres y esto es una forma mas practica, con esto ya tenemos cubierto el movimiento de las tres opciones, vamos a ver el switch que se encargaba de dibujar en pantalla:
switch(eleccion)
{
case 0:
draw_sprite(spr_Retomar,0,128,352);
draw_sprite(spr_Salir,1,128,422);
break;
case 1:
draw_sprite(spr_Retomar,1,128,352);
draw_sprite(spr_Salir,0,128,422);
break;
}
Este estaba justo debajo del condicional anterior, ahora lo modificaremos de la siguiente manera:
switch(eleccion)
{
case 0:
draw_sprite(spr_Retomar,0,128,352);
draw_sprite(spr_Teclas,1,128,422);
draw_sprite(spr_Salir,1,128,492);
break;
case 1:
draw_sprite(spr_Retomar,1,128,352);
draw_sprite(spr_Teclas,0,128,422);
draw_sprite(spr_Salir,1,128,492);
break;
case 2:
draw_sprite(spr_Retomar,1,128,352);
draw_sprite(spr_Teclas,1,128,422);
draw_sprite(spr_Salir,0,128,492);
break;
}
En este caso agregamos un case mas, el case 2, pero observen que ahora dibujamos un sprite mas, spr_Teclas, y por ende tuvimos que reubicarlos mediante la variacion del eje Y pero trabaja de la misma forma que vimos antes, la otra diferencia va a estar que ahora el case 1 va a ser para reconfigurar nuestras teclas y el case 2 va a ser para salir al menu de inicio, aunque todavia no funciona, con esto pueden probarlo pero todavia nos faltan un par de modificaciones mas, nuestra siguiente modificacion sera en el condicional que verifica si presionamos Enter:
if (keyboard_check(vk_enter))
{
switch(eleccion)
{
case 0:
instance_destroy();
break;
case 1:
ini_open("score.ini");
record_codificado = base64_encode(
string(global.puntaje_alto));
ini_write_string("puntajealto",
"puntajealto",
record_codificado);
ini_close();
global.room_destino = rm_setup;
instance_create_depth(
0,0,0,
obj_Transicion);
break;
}
}
Al cual modificaremos de la siguiente manera:
if (keyboard_check(global.seleccion) && !union
&& !solo_seleccion_unida)
{
switch(eleccion)
{
case 0:
instance_destroy();
break;
case 1:
union = true;
izquierda_unida = false;
derecha_unida = false;
seleccion_unida = false;
break;
case 2:
ini_open("score.ini");
record_codificado = base64_encode(
string(global.puntaje_alto));
ini_write_string("puntajealto",
"puntajealto",
record_codificado);
ini_close();
global.room_destino = rm_setup;
instance_create_depth(
0,0,0,
obj_Transicion);
break;
}
}
La diferencia mas importante va a ser en el condicional, en este caso no chequearemos si se presiono la tecla Enter sino el contenido de una variable global, global.seleccion, y a su vez que union y solo_seleccion_unida tengan el valor false, proximamente hablaremos sobre las dos nuevas variables, la otra modificacion va a estar en el case 1 donde ahora establecera a union como true y otras tres variables como false pero al igual que en el caso anterior en un minuto hablaremos sobre las mismas, por ultimo el contenido de case 1 ahora estara en case 2 sin modificaciones, lo mas importante es que establecimos a union como true cuando queremos reasignar las teclas, pasemos a trabajar sobre esta y para ello debemos agregar el siguiente bloque al comienzo del evento pero despues de cuando creamos el rectangulo que tapa toda la pantalla:
if (union)
{
draw_set_font(fnt_Menu);
draw_set_color(c_black);
draw_set_alpha(1);
if (!izquierda_unida)
{
draw_text(120,50,
"Presiona la nueva tecla para la izquierda");
if (keyboard_check_pressed(vk_anykey))
{
global.izquierda = keyboard_lastkey;
izquierda_unida = true;
}
}
else if (!derecha_unida)
{
draw_text(120,50,
"Presiona la nueva tecla para la derecha");
if (keyboard_check_pressed(vk_anykey))
{
global.derecha = keyboard_lastkey;
derecha_unida = true;
}
}
else if (!seleccion_unida)
{
draw_text(120,50,
"Presiona la nueva tecla para seleccionar");
if (keyboard_check_pressed(vk_anykey))
{
global.seleccion = keyboard_lastkey;
seleccion_unida = true;
union = false;
solo_seleccion_unida = true;
}
}
}
Lo primero que haremos es establecer como false a solo_seleccion_unida, el siguiente paso es un condicional donde verificamos si union es true, recuerden que lo establecimos con este estado en el switch anterior, lo siguiente que haremos es establecer la fuente, el color y el alfa de los textos que mostraremos a continuacion, el siguiente paso es chequear si izquierda_unida es igual a false, despues de esto mostraremos un texto para que el usuario presione una tecla para la izquierda, el condicional verifica si presiono alguna tecla, en caso de ser verdadero asignaremos a una variable global llamada izquierda la ultima tecla que se presiono (keyboard_lastkey) y establecemos a izquierda_unida como true, el siguiente condicional trabaja de la misma forma pero solamente para movernos a la derecha, obviamente reemplazando la izquierda por derecha, por ultimo tenemos un condicional para modificar a la tecla de seleccion, la unica diferencia es que esta vez estableceremos a la variable global seleccion con el nuevo valor, luego establecemos a seleccion_unida como true, volvemos a establecer a union como false porque consideramos que ya hicimos todas las modificaciones y volvemos a la normalidad, por ultimo establecemos a solo_seleccion_unida como true, esto es para evitar que la pausa entre en un ciclo con el condicional visto anteriormente, solo nos resta agregar la siguiente linea arriba del codigo del evento por fuera del condicional donde verificamos si podemos proceder:
solo_seleccion_unida = false;
Con esto tenemos el valor predeterminado que se cambiara solo si union es verdadero, con esto terminamos todas las modificaciones en el evento Draw del objeto, veamos su codigo final:
solo_seleccion_unida = false;
if (puede_proceder)
{
if (surface_exists(superficie_pausa))
{
draw_surface(superficie_pausa,0,0);
}
else
{
event_perform(ev_create,0);
}
if (!esta_pausado)
{
esta_pausado = true;
surface_set_target(superficie_pausa);
draw_surface(application_surface,0,0);
surface_reset_target();
instance_deactivate_all(true);
}
draw_set_alpha(0.75);
draw_roundrect_color(0,0,
room_width-1,
room_height-1,
c_gray,
c_white,
false);
if (union)
{
draw_set_font(fnt_Menu);
draw_set_color(c_black);
draw_set_alpha(1);
if (!izquierda_unida)
{
draw_text(20, 50,
"Presiona la nueva tecla para la izquierda");
if (keyboard_check_pressed(vk_anykey))
{
global.izquierda = keyboard_lastkey;
izquierda_unida = true;
}
}
else if (!derecha_unida)
{
draw_text(20,50,
"Presiona la nueva tecla para la derecha");
if (keyboard_check_pressed(vk_anykey))
{
global.derecha = keyboard_lastkey;
derecha_unida = true;
}
}
else if (!seleccion_unida)
{
draw_text(20,50,
"Presiona la nueva tecla para seleccionar");
if (keyboard_check_pressed(vk_anykey))
{
global.seleccion = keyboard_lastkey;
seleccion_unida = true;
union = false;
solo_seleccion_unida = true;
}
}
}
if (keyboard_check_pressed(vk_up) && !union)
{
if (eleccion <=0) eleccion = 2;
else --eleccion;
}
else if (keyboard_check_pressed(vk_down) && !union)
{
if (eleccion >=2) eleccion = 0;
else ++eleccion;
}
switch(eleccion)
{
case 0:
draw_sprite(spr_Retomar,0,128,282);
draw_sprite(spr_Teclas,1,128,352);
draw_sprite(spr_Salir,1,128,422);
break;
case 1:
draw_sprite(spr_Retomar,1,128,282);
draw_sprite(spr_Teclas,0,128,352);
draw_sprite(spr_Salir,1,128,422);
break;
case 2:
draw_sprite(spr_Retomar,1,128,282);
draw_sprite(spr_Teclas,1,128,352);
draw_sprite(spr_Salir,0,128,422);
break;
}
if (keyboard_check_pressed(global.seleccion) && !union
&& !solo_seleccion_unida)
{
switch(eleccion)
{
case 0:
instance_destroy();
break;
case 1:
union = true;
izquierda_unida = false;
derecha_unida = false;
seleccion_unida = false;
break;
case 2:
ini_open("score.ini");
record_codificado = base64_encode(
string(global.puntaje_alto));
ini_write_string("puntajealto",
"puntajealto",
record_codificado);
ini_close();
global.room_destino = rm_setup;
instance_create_depth(
0,0,0,
obj_Transicion);
break;
}
}
}
Nuestra siguiente modificacion sera en el obj_Pepe donde aplicaremos los cambios que hicimos recientemente, para ello debemos ir al evento Step e iremos al switch donde chequeamos las teclas:
switch(keyboard_key)
{
case vk_left:
hspeed = -4;
image_index = 0;
break;
case vk_right:
hspeed = 4;
image_index = 1;
break;
case ord("P"):
instance_create_depth(0,0,0,obj_Pausa);
break;
default:
hspeed = 0;
image_index = 2;
break;
}
Y a este lo modificaremos de la siguiente manera:
switch(keyboard_key)
{
case global.izquierda:
hspeed = -4;
image_index = 0;
break;
case global.derecha:
hspeed = 4;
image_index = 1;
break;
case ord("P"):
instance_create_depth(0,0,0,obj_Pausa);
break;
default:
hspeed = 0;
image_index = 2;
break;
}
Tecnicamente lo unico que hicimos fue reemplazar las constantes internas que equivalen a las teclas de cursores por los valores que almacenamos en las variables globales, nuestra ultima modificacion antes de probarlo sera en rm_setup, para ello abrimos el room y presionamos el boton Creation Code para abrir el codigo y agregaremos las siguientes lineas:
global.seleccion = vk_enter;
global.izquierda = vk_left;
global.derecha = vk_right;
Por el momento no es obligatorio agregarlo en ningun lugar en especifico pero les recomiendo hacerlo antes del bloque encargado de leer el archivo INI, estas tres lo unico que hacen es inicializar las tres variables globales para evitar que en algun momento manejemos un valor null, con todas modificaciones podemos probarlo, veamos el siguiente video
En el video podemos ver como nos pidio que asignemos las nuevas teclas para nuestro jugador, si bien no se observa pero comence a jugar con las nuevas teclas asignadas, solo nos falta una modificacion mas como es el grabar nuestros cambios y poder cargarlos, para ello vamos a utilizar a nuestro archivo INI.
Para comenzar vamos a hacer las modificaciones del archivo INI, iremos al archivo source.ini que se encuentra en datafiles, carpeta dentro de nuestro proyecto, y agregaremos el siguiente bloque:
[teclas]
izquierda = 37
derecha = 39
seleccion = 13
La seccion se llamara teclas, y en ella tenemos tres valores para dos desplazamientos y la seleccion, en este caso le paso los valores que equivalen a vk_left, vk_right y vk_enter respectivamente, con esto tendremos un valor predeterminado, el archivo nos quedara de la siguiente manera:
[puntajealto]
puntajealto = "0"
[teclas]
izquierda = 37
derecha = 39
seleccion = 13
Nuestro siguiente paso sera eliminar el archivo que se genera en %localappdata%\SaltaPepe, para volver a crearlo cuando abramos nuevamente nuestro proyecto, el siguiente paso sera modificar el codigo de Creation Code de rm_setup donde eliminaremos o comentaremos las siguientes lineas:
global.seleccion = vk_enter;
global.izquierda = vk_left;
global.derecha = vk_right;
Y agregaremos las siguientes dentro del bloque encargado de abrir y cerrar el archivo INI:
global.izquierda = ini_read_real(
"teclas", "izquierda", vk_left);
global.derecha = ini_read_real(
"teclas", "derecha", vk_right);
global.seleccion = ini_read_real(
"teclas", "seleccion", vk_enter);
En este caso lo que hacemos es utilizar a ini_read_real para que saque cada valor que agregamos en el INI y a lo asigne a la variable global que corresponda, la forma de trabajar es la misma que describimos cuando hablamos del puntaje maximo, observen que como valores predeterminados pasamos las constantes que teniamos de antes, veamos como quedo del bloque que maneja al INI:
ini_open("score.ini");
record_decodificado = base64_decode(
ini_read_string("puntajealto",
"puntajealto",
0));
if (record_decodificado!="")
{
global.puntaje_alto = real(
record_decodificado);
}
else
{
global.puntaje_alto = 0;
}
global.izquierda = ini_read_real(
"teclas", "izquierda", vk_left);
global.derecha = ini_read_real(
"teclas", "derecha", vk_right);
global.seleccion = ini_read_real(
"teclas", "seleccion", vk_enter);
ini_close();
Nuestra ultima modificacion es la capacidad de almacenar las modificaciones, para ello debemos ir a obj_Pausa y en el condicional que verificamos si se presiono Enter en los alguno de los botones, debemos agregar este bloque en el ultimo de los case entre donde se abre y se cierra el archivo INI:
ini_write_real("teclas",
"izquierda",
global.izquierda);
ini_write_real("teclas",
"derecha",
global.derecha);
ini_write_real("teclas",
"seleccion",
global.seleccion);
Aca podemos ver que usamos a ini_write_real para escribir los tres parametros que configuramos, tal como lo vimos anteriormente, veamos como quedo nuestro condicional:
if (keyboard_check_pressed(global.seleccion) && !union
&& !solo_seleccion_unida)
{
switch(eleccion)
{
case 0:
instance_destroy();
break;
case 1:
union = true;
izquierda_unida = false;
derecha_unida = false;
seleccion_unida = false;
break;
case 2:
ini_open("score.ini");
record_codificado = base64_encode(
string(global.puntaje_alto));
ini_write_string("puntajealto",
"puntajealto",
record_codificado);
ini_write_real("teclas",
"izquierda",
global.izquierda);
ini_write_real("teclas",
"derecha",
global.derecha);
ini_write_real("teclas",
"seleccion",
global.seleccion);
ini_close();
global.room_destino = rm_setup;
instance_create_depth(
0,0,0,
obj_Transicion);
break;
}
}
Con todo esto ya tenemos todas las modificaciones realizadas pero solo nos falta un cambio mas, diria que solamente es estetico, para ello debemos ir al obj_Inicio y dentro del evento Draw buscaremos esta linea:
else if (keyboard_check_pressed(vk_enter))
Al cual reemplazaremos de la siguiente manera:
else if (keyboard_check_pressed(global.seleccion))
En este caso vemos como ahora en lugar de esperar solamente a Enter usara a la tecla que asignamos como seleccion, con todas estas modificaciones realizadas podemos pasar a probar nuestro juego mediante el siguiente video
En el video podemos ver como nuestro juego sigue funcionando pero ahora al crear nuestro archivo INI no solamente almacenamos el record codificado sino tambien almacenaremos las nuevas teclas que cambamos en el juego, antes de finalizar les comparto como quedo finalmente
En resumen, hoy hemos visto como podemos agregar la posibilidad de cambiar las teclas para controlar a nuestro jugador, hemos visto como podemos hacerlo de una manera simple, como podemos esparcirlo por todo nuestro juego, como grabarlo en nuestro archivo INI y como podemos recuperar esa informacion, espero les haya gustado sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.


Donación
Es para mantenimento del sitio, gracias!
$1.00
