Noticias

Importante: ¡Si quieres publicar tu juego no olvides leer este tema!

Comunidad Game Maker

Bienvenid@ a la comunidad hispana de Game Maker. Nuestro objetivo es crear videojuegos y dar soporte en castellano de GM. Para mejorar nuestro servicio hemos implantado, como adicion al reglamento general, algunas normas especificas en los subforos más comunes. ¡No olvides informarte antes de participar!.

Autor Tema: Maquina de estados simple (muy difícil para mi)  (Leído 180 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Fashion_Trozos

  • Habitual
  • *
  • Puntos: 141
  • Mensajes: 72
    • Ver Perfil
en: Mayo 15, 2019, 08:26:18 pm
Hola, buenas tardes a todo el mundo. Llevo unos días intentando aprender un poco sobre las maquinas de estados. He conseguido hacerla funcionar, pero solo en parte. Por ahora mi personaje se mueve en todas direcciones con su animación en la dirección concreta, cuando esta parado simplemente se queda quieto mirando hacia la dirección en la que iba, si iba a la derecha y dejo de pulsar, pues eso, se detiene mirando a la derecha. Hasta ahí bien, el problema me ha surgido al querer que mi personaje ataque. He echo unas animaciones cutres del personaje atacando en todas direcciones y he preparado un script de "ataque" pero no ha funcionado lo bien que me gustaría. Os pongo algo del código y a ver si me podéis echar un cable.

En el evento Crate no he puesto nada referente a la maquina de estados, lo probé como explicaba Hektor Profe en un video de Youtube pero no hubo manera, me daba errores y decidí seguir adelante sin hacer un enumerador con los estados (a lo mejor ahí empezó mi fallo).

En el Step primero tengo esto:

if      (vv > 0) dir = "abajo";
else if (vv < 0) dir = "arriba";
else if (vh > 0) dir = "derecha";
else if (vh < 0) dir = "izquierda";
else if (vh == 0 and vv == 0) dir = "parado"

if pico_equipado == true {
   
    //Parte grafica con pico
    if dir != "" scr_prota_moviendose_con_pico()
    if (vh == 0 and vv == 0) scr_parado_con_pico()
    }
   
    else{
       
    //Parte grafica sin pico
    if dir != ""   scr_prota_moviendose()
    if (vh == 0 and vv == 0) scr_parado()
    }

Tengo como dos modos que digamos, uno con un pico equipado y otro sin.

Estos son los scripts (pondré solo los de sin pico)

Script parado:

image_speed = 0;
image_index = 0;

Script moviendose:

image_speed = 1

switch(dir){
    case "abajo":
        sprite_index = spr_prota_frente;
        break;
    case "arriba":
        sprite_index = spr_prota_detras;
        break;
    case "derecha":
        sprite_index = spr_prota_derecha;
        break;
    case "izquierda":
        sprite_index = spr_prota_izquierda;
        break;
}

Esto es lo que tengo para que se mueva, y se mueve. El problema viene cuando quiero añadir el ataque. Realmente lo único que he echo para añadir el ataque es lo siguiente:

Step:

if mouse_check_button_pressed(mb_left) {    
   atacando = true;
}


if atacando == true {
    scr_prota_picando()
}

Y el script de "ataque":

image_speed = 1

switch(dir){
    case "abajo":
        sprite_index = spr_prota_frente_picando;
        break;
    case "arriba":
        sprite_index = spr_prota_detras_picando;
        break;
    case "derecha":
        sprite_index = spr_prota_derecha_picando;
        break;
    case "izquierda":
        sprite_index = spr_prota_izquierda_picando;
        break;
    case "parado":
        sprite_index = spr_prota_frente_picando;
        break;
}

if image_index = 4 {

    atacando = false;

}

Lo que me sucede haciéndolo así es que al pulsar el botón del mouse el personaje entra en el modo ataque por decirlo de alguna manera y ya no lo abandona, a parte no funciona como me gustaría que es que cuando pulso ataca y cuando no, pues no. Lo que sucede es que se activa la animación dependiendo de hacía que lado me muevo y se queda activada todo el tiempo mientras me mueva, si voy a la derecha veo al personaje atacando sin parar hacía la derecha y en cuando me detengo se detiene la animación también. Me imagino que no lo estoy haciendo bien, me cuesto mucho imaginarme la lógica para que todo funcione bien.
« última modificación: Mayo 15, 2019, 08:47:18 pm por Johann »

 


No Tienes Permisos Para Dar Puntos
point 0 Puntos

Este tema no recibió puntos.


Desconectado Clamud

Respuesta #1 en: Mayo 15, 2019, 10:32:27 pm
Lo que falta es una condición para que la variable atacando se haga false. Se podría hacer false en el evento End Animation o en una Alarm.

No está bien definido el código de cada estado. Puedes crear un script para cada estado, en cada estado se asignan sprites diferentes y los controles pueden ser diferentes. Por ejemplo, en estado normal el personaje responde al botón para iniciar el ataque, pero cuando está atacando ya no debe responder a ese botón hasta que termina de atacar. En step coloca un switch que elija que script ejecutar:
switch (estado) {
  case 0: sc_estado_normal();
  case 1: sc_estado_atacando();
}

 
Los siguientes usuarios dieron las gracias a este tema: Fashion_Trozos


Desconectado Fashion_Trozos

  • Habitual
  • *
  • Puntos: 141
  • Mensajes: 72
    • Ver Perfil
Respuesta #2 en: Mayo 16, 2019, 12:48:15 pm
Hola y muchas gracias por responder. Quieres decir que con la linea del script de "Ataque/picando" que pone:

Código: [Seleccionar]
if image_index = 4 {

atacando = false;

}

No es suficiente para parar el ataque, no?

Voy a intentar hacer algunos cambios a ver si puedo afinar mas mi pregunta, es que dudo tanto que no se que preguntar

 


Desconectado Fashion_Trozos

  • Habitual
  • *
  • Puntos: 141
  • Mensajes: 72
    • Ver Perfil
Respuesta #3 en: Mayo 16, 2019, 02:21:47 pm
No hay manera, jejej no se como se hace! llevo toda la mañana intentando hacerlo de otras maneras y no consigo mas que romperlo aun mas jejeje. He estado mirando tutoriales pero la mayoría son demasiado complicados y por ahora me pierdo. He intentado hacerlo con un enumerador  pero no hay manera, no entiendo muy bien como funcionan. entiendo que es hacer una simple lista, pero realmente me hace falta para hacer una maquina de estados? Podría programar que mi personaje camine, ataque y este quieto en cada una de las direcciones que vengan al caso sin hacer una máquina de estados? Os paso el código que tengo echo a ver si me podéis encarrilar aun que sea un poco jeje.

En el Create

Código: [Seleccionar]
vh = 0;
vv = 0;
v  = 3;

//------MAQUINA DE ESTADOS----------------


scr_parado()
dir = "abajo"


//--------ESTADOS ANIMACION---------------

pico_equipado = false;
picando       = false;
atacando      = false;


//--------PERMISOS------------------------

poder_picar = true;


//-------CONTADORES RECURSOS---------------

recurso_roca = 0;

En el Step

Código: [Seleccionar]
//------DETECCION DE TECLAS Y DIRECCION----------------------------------------

vh = (-keyboard_check(ord("A")) + keyboard_check(ord("D"))) * v;
vv = (-keyboard_check(ord("W")) + keyboard_check(ord("S"))) * v;




//-------DIRECCION, MOVIMIENTO o PARADO, PARTE GRAFICA-------------------------

if      (vv > 0) dir = "abajo";
else if (vv < 0) dir = "arriba";
else if (vh > 0) dir = "derecha";
else if (vh < 0) dir = "izquierda";
else if (vh == 0 and vv == 0) dir = "parado"




//------SI ME MUEVO O NO PARTE GRAFICA-----------------------------------------

if !scr_prota_picando(){

if pico_equipado == true {

//Parte grafica con pico
if dir != "" scr_prota_moviendose_con_pico()
if (vh == 0 and vv == 0) scr_parado_con_pico()
}

else{

//Parte grafica sin pico
if dir != ""  scr_prota_moviendose()
if (vh == 0 and vv == 0) scr_parado()
}
}

else{

vh = 0;
vv = 0;

}

//--------------ATAQUE---------------------------------------------------------

if mouse_check_button_pressed(mb_left)
and pico_equipado == true
and !scr_prota_picando(){
   scr_prota_picando();
  }


//----------PICAR ROCA---------------------------------------------------------



//Picar roca con o sin pico
if distance_to_object(ob_roca) < 4
and mouse_check_button_pressed(mb_left)
and position_meeting(mouse_x,mouse_y,ob_roca)
and poder_picar == true {

//Si no llevo pico
if pico_equipado == false{
ob_roca.vida_roca--;
recurso_roca++;
poder_picar = false;
alarm[0] = room_speed * 1.5;
}
else {

//Si llevo pico
ob_roca.vida_roca -= 2;
recurso_roca      += 2;
poder_picar = false;
alarm[0] = room_speed * 1.5;
}
}

//Destruir la roca si es posible
if instance_exists(ob_roca){

if ob_roca.vida_roca = 0 {

instance_destroy(instance_nearest(x,y,ob_roca))
if instance_exists(ob_roca) {ob_roca.vida_roca += 4}
}
}


//-------SUMAR VELOCIDADES------------------------------------------------------

x += vh;
y += vv;


//--------REINICIAR ROOM---------------------------------------------------------

if keyboard_check_pressed(vk_enter) {
room_restart()
}


Script parado

Código: [Seleccionar]
image_speed = 0;
image_index = 0;

Script parado con pico

Código: [Seleccionar]
image_speed = 0;
image_index = 0;

Script caminando

Código: [Seleccionar]
image_speed = 1

switch(dir){
case "abajo":
sprite_index = spr_prota_frente;
break;
case "arriba":
sprite_index = spr_prota_detras;
break;
case "derecha":
sprite_index = spr_prota_derecha;
break;
case "izquierda":
sprite_index = spr_prota_izquierda;
break;
}

Script moviendose con pico

Código: [Seleccionar]
image_speed = 1;

switch(dir){
case "abajo":
sprite_index = spr_prota_frente_con_pico;
break;
case "arriba":
sprite_index = spr_prota_detras_con_pico;
break;
case "derecha":
sprite_index = spr_prota_derecha_con_pico;
break;
case "izquierda":
sprite_index = spr_prota_izquierda_con_pico;
break;
}

Script atacando

Código: [Seleccionar]
image_speed = 1

switch(dir){
case "abajo":
sprite_index = spr_prota_frente_picando;
break;
case "arriba":
sprite_index = spr_prota_detras_picando;
break;
case "derecha":
sprite_index = spr_prota_derecha_picando;
break;
case "izquierda":
sprite_index = spr_prota_izquierda_picando;
break;
case "parado":
sprite_index = spr_prota_frente_picando;
break;
}
show_debug_message(image_index)
if image_number >= image_number-1 {
scr_parado()
}

 


Desconectado Seirlord_Games

  • Asiduo
  • *
  • Puntos: 267
  • Mensajes: 182
  • Agradecido: 33 veces
  • Sexo: Masculino
  • Esfuérzate por tus sueños, sino es imposible.
    • Ver Perfil
Respuesta #4 en: Mayo 16, 2019, 03:47:48 pm
Hola y muchas gracias por responder. Quieres decir que con la linea del script de "Ataque/picando" que pone:

Código: [Seleccionar]
if image_index = 4 {

atacando = false;

}

No es suficiente para parar el ataque, no?

Voy a intentar hacer algunos cambios a ver si puedo afinar mas mi pregunta, es que dudo tanto que no se que preguntar

El image_index no solo puede ser 1, 2, 3, 4, etc, sino que es más probable que tenga un decimal, ya que va aumentando en decimales. Podrias hacer algo como:
Código: [Seleccionar]
if floor(image_index) = 4 {

atacando = false;

}

Esto lo que hace es redondear el valor de 'image_index' hacia abajo, lo que pasa es que el código 'atacando = false;' se ejecutará varias veces, pero creo que no debería afectar negativamente en tu caso.

Un Saludo!



 
Los siguientes usuarios dieron las gracias a este tema: Fashion_Trozos