Comunidad Game Maker

Ayuda => Preguntas y respuestas => Mensaje iniciado por: Fashion_Trozos en Mayo 28, 2019, 01:16:13 PM

Título: Mi personaje no ataca cuando esta parado
Publicado por: Fashion_Trozos en Mayo 28, 2019, 01:16:13 PM
Buenas a todo el mundo. Llevo ya unos días intentando hacer que funcione una maquina de estados, es a primera vez que lo hago y al final salvando problemillas de por aquí y por allá al final mi personaje se mueve, se esta quieto y ataca. Ahora el problema lo tengo en que cuando esta parado no ataca. He intentado hacer otro estado de "parado_atacando" pero ni aun así lo consigo. Debugueando por la consola veo que entra al estado de atacar parado, pero solo lo hace por un minisegundo, por lo tanto veo que entra en ese estado, pero no se mantiene allí y se sale rapidísimo. Os paso la parte del código de atacar:

if mouse_check_button_pressed(mb_left)
and pico_equipado = true
and estado != estado_personaje.atacando
and dir != "parado"

{
estado = estado_personaje.atacando;
image_index = 0;
}
   
if mouse_check_button_pressed(mb_left)
and pico_equipado = true
and estado != estado_personaje.atacando
and dir = "parado" 

{
estado = estado_personaje.atacando_parado;
image_index = 0;
}

show_debug_message(estado)


Os paso tambien el script de atacar parado, que es exactamente igual que el de atacar. Por ahora solo ataca cuando voy moviendome   :)

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;
}

if image_index >= image_number-1{
estado = estado_personaje.parado_pico
}
Título: Re:Mi personaje no ataca cuando esta parado
Publicado por: Fashion_Trozos en Mayo 28, 2019, 08:29:09 PM
Creo que he encontrado cual es el problema. En el script de ataque, tengo el switch determinando hacia que lado se esta moviendo el personaje, derecha, izquierda, arriba o abajo, pero cuando quiero que el personaje ataque sin estar moviéndose realmente no se encuentra en ninguna de esas direcciones por que las establezco así, a traves de las velocidades:

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"


Claro, al final cuando esta parado no esta en ninguna "dir" mas que en la de "parado" pero no indica la dirección. Puede que este sea el error?
De ser así, como lo solucionaríais? Como podría definir en que dirección se encuentra mirando el personaje cuando no pulso una tecla?

Se me ocurre algo como "Si la ultima "dir" a sido hacia abajo (por ejemplo), el personaje se encuentra en "dir" "abajo". Como podría hacer algo así?.
Seguro que me estoy liando mas de la cuenta jejej. Un saludo!
Título: Re:Mi personaje no ataca cuando esta parado
Publicado por: Fashion_Trozos en Mayo 29, 2019, 12:38:58 PM
Buenas gente, voy probando cosas que se me ocurren y no consigo que ataque mientra esta parado. Lo último que he probado es esto...

if mouse_check_button_pressed(mb_left)
and pico_equipado = true
and estado != estado_personaje.atacando{
if dir = "parado"{
estado = estado_personaje.atacando_parado
}else{
estado = estado_personaje.atacando;
image_index = 0;
}
}


La cosa es que no entra en estado = estado_personaje.atacando_parado y no se porque. Se que esta en dir = "parado" porque lo veo en la consola. Veo que entra pero solo un minisegundo y vuelve al estado de parado. Porque no pasa al estado de atacando_parado, puede haber algo en el script que lo devuelva a parado?

Título: Re:Mi personaje no ataca cuando esta parado
Publicado por: FridaFlowers en Mayo 29, 2019, 07:01:37 PM
Lo mas probable es que, hay parte de codigo en el evento step que cambie constantemente el estado por eso solo cambia en una fraccion de segundo.

Título: Re:Mi personaje no ataca cuando esta parado
Publicado por: Fashion_Trozos en Mayo 29, 2019, 11:33:43 PM
Muchas gracias por responder!! Si quieres paso el evento step a ver si me puedes decir si ves e fallo (se que debe ser un coñazo repasar código de principiantes como yo jejej)

//------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;




//-----------------DETECCION DE DIRECCION-------------------------------------------------

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      (keyboard_check_pressed(ord("S"))) dir1 = "abajo1";
else if (keyboard_check_pressed(ord("W"))) dir1 = "arriba1";
else if (keyboard_check_pressed(ord("D"))) dir1 = "derecha";
else if (keyboard_check_pressed(ord("A"))) dir1 = "izquierda1";





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


//Si el estado es distinto a atacando
if estado != estado_personaje.atacando{

if pico_equipado == true {
   
   //Parte grafica con pico
   if dir != ""             estado = estado_personaje.caminando_pico;
   if (vh == 0 and vv == 0) estado = estado_personaje.parado_pico;
   }
   
   
if pico_equipado == false {   
      
   //Parte grafica sin pico   
   if (dir != "")            estado = estado_personaje.caminando;
   if (vh == 0 and vv == 0)  estado = estado_personaje.parado;
   }
}


//Si esta atacando ponemos a cero las velocidades
else{
      vv = 0;
      vh = 0;
   }


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

if mouse_check_button_pressed(mb_left)
and pico_equipado = true
and estado != estado_personaje.atacando{   
   if dir = "parado"{
      estado = estado_personaje.atacando_parado   
   }else{
      estado = estado_personaje.atacando;
      image_index = 0;
      }
   }
/*if mouse_check_button_pressed(mb_left)
and pico_equipado = true
and estado != estado_personaje.atacando
and vv = 0
and vh = 0


   {
      estado = estado_personaje.atacando_parado;
      image_index = 0;
   }
*/

show_debug_message(estado)




 
   
 


//----------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_execute(estado);

Como podreis ver por mis anotaciones no tengo ni puta idea de programar, ara tres meses no sabía ni que quería decir jejej
Hay una parte que esta comentada porque estaba intentando ver de donde viene el fallo. Muchas gracias por contestar!
Título: Re:Mi personaje no ataca cuando esta parado
Publicado por: FridaFlowers en Mayo 30, 2019, 04:54:19 PM
Hmmm si recién estas empezando, te recomendaria no usar esa notacion tan resumida.
de todas maneras, si pudieras pasar el editable para debuggearlo sería mas fácil.
Porque de momento no tengo mucho tiempo libre
Título: Re:Mi personaje no ataca cuando esta paradoes
Publicado por: 3dgeminis en Mayo 30, 2019, 05:19:19 PM
Puedes atacar en todo momento, cuando estas quieto y moviendote?
Te mueves y atacas en 4 direcciones solamente?.
Pudes atacar continuamente o hay una pausa entre ataques?
Antes de continuar con el mismo codigo, podrias planteate el hacerlo de nuevo y de otra forma.
Título: Re:Mi personaje no ataca cuando esta parado
Publicado por: Fashion_Trozos en Mayo 30, 2019, 06:57:34 PM
Muchas gracias por responder! mmmm que es el editable?  :-[
MMMmm y hacerlo de otra manera,... por mi encantado!, lo he echo de esta manera porque es de la única manera que se (que realmente no se jeje), como lo harias?.
Por ahora uede atacar en todas direcciones pero siempre y cuando me este moviendo, si me paro no ataca.
Mi idea es muy básica, quiero que el personaje pueda atacar en todas las direcciones estando quieto y en movimiento. (direcciones arriba, abajo, derecha e izquierda)
Mi idea es hacer un juego ARPG pixelart
Pero sobre todo lo que mas intringulis me tiene es el porque no entra en el estado de ataque, bueno entra pero se sale en cero coma.
Título: Re:Mi personaje no ataca cuando esta parado
Publicado por: FridaFlowers en Mayo 31, 2019, 12:23:38 AM
El editable es el archivo que editas para hacer el juego. El gmk? ya no me acuerdo que extension tiene xD

La verdad que es una buena idea eso de re-factorizar el código. A lo mejor más limpio y entendible tal vez.
Título: Re:Mi personaje no ataca cuando esta parado
Publicado por: Fashion_Trozos en Mayo 31, 2019, 09:58:01 AM
Pues ahí va! si a alguien no le da un montón de pereza...
Y como podría hacer una máquina de estados o simplemente lo que comento que quiero hacer de una manera mas fácil?
Lo paso en dos formatos, no se cual será el bueno  :-[
PD: Ataque y picar roca son lo mismo en realidad. Puse ataque por no liarme, pero igual te pica una roca que te revienta a un enemigo XD

Título: Re:Mi personaje no ataca cuando esta parado
Publicado por: FridaFlowers en Mayo 31, 2019, 03:50:25 PM
Bien, el problema ocurre aqui. Linea 34 evento Step.

https://www.comunidadgm.org/preguntas-y-respuestas/mi-personaje-no-ataca-cuando-esta-parado/?action=dlattach;attach=18348;image

El estado es distinto de "atacando". Más concretamente su valor es "atacando_parado".
Luego, eventualmente dir es distinto de "", puesto que esta en "parado" por lo que automaticamente el estado pasa a ser "caminando_pico". (Linea 39)


Sin embargo, al estar quieto (es decir vv=0 y vh=0), cambia de nuevo el estado a "parado_pico" (linea 40).
Basicamente el personaje cambia dos veces de estado en el evento step, por eso que no se ve la animación.



Luego, para hacer algo acotado y sencillo simplemente piensa en eso, que sea simple y natural.
Creo que es un error bastante grande, usar las enum como llamadas a script, primero que no deja claro el codigo en sí. Lo enreda más aún.
Segundo, expresiones como:
[gml]
vh = (-keyboard_check(ord("A")) + keyboard_check(ord("D"))) * v;
[/gml]
Es anti natural.
Es preferible hacer 10 o 15 lineas mas pero que sean auto explicativas, por decir algo:
[gml]
if keyboard_check(ord("D"))
    vh = 5
if keyboard_check(ord("A"))
    vh = -5

x += vh
[/gml]

Igual, ojo, usar enums para una maquina de estados está bien, lo que está mal es asignarle valores enteros pasados como indices de scripts.
No sé de donde estás sacando los tutoriales pero eso amigo, no te lo recomiendo yo ni ningun curso decente de programacion estructurada XD

Una idea podria ser:
[gml]
enum acciones{
         esperando,
         caminando,
         picando
}
[/gml]
Ah, y una constante para cada accion, no importa si "picando", "atacando" o "pegandole_al_aire_con_el_pico" es la misma accion. Simplicidad
Te vas a ahorrar lineas de programacion extra al verificar tal o cual y hace mas legible el codigo.

Luego para mover, por ejemplo:
[gml]
if keyboard_check(ord("D")) or keyboard_check(ord("A")) //si se presionan teclas, cambiar estado a caminado
     estado = acciones.caminando
else //si no se presionan teclas, es porque esta parado
     estado = acciones.esperando

if keyboard_check(ord("D"))
    vh = 5
if keyboard_check(ord("A"))
    vh = -5

x += vh


if keyboard_check(ord("G")){ //si ataca...
       if estado == acciones.esperando //y esta parado
                   scr_atacar_parado() // ataca parado
       if estado == acciones.caminado //si al atacar, estaba caminando
                  scr_atacar_caminando()  // atacar caminando
}
[/gml]
Bueno esa es una idea de como yo programaría.

Ah, por ultimo, esto:
[gml]
if dir != ""             estado = estado_personaje.caminando_pico;
[/gml]

Acostumbrate a usar el sangrado y los espacios de linea:
[gml]
if dir != ""           
         estado = estado_personaje.caminando_pico;
[/gml]

Si algun dia llegas a programar con gente competente te lo va a agradecer. Y seguramente a tu "yo" del futuro xD si decides algun dia releer el codigo.

Nada más, creo.
Título: Re:Mi personaje no ataca cuando esta parado
Publicado por: Fashion_Trozos en Mayo 31, 2019, 07:30:22 PM
Wuoouu wuouu wuouu, vaya currazo de respuesta! Te invito a una cerveza! Muchas gracias en serio. Cuando llegue a casa lo reviso minuciosamente. De nuevo, gracias!
Título: Re:Mi personaje no ataca cuando esta parado
Publicado por: Fashion_Trozos en Junio 03, 2019, 01:40:21 PM
Buenas! he intentado cambiar algo el código y hacerlo "mas fácil", pero no consigo que funcione. Intentare exponer el problema lo mas fragmentado que pueda y a ver si así es mas fácil.

Como decía he cambiado el código siguiendo tus consejos:

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



if (keyboard_check(ord("S")))
or (keyboard_check(ord("W")))
or (keyboard_check(ord("D")))
or (keyboard_check(ord("A"))) {
estado = estado_personaje.caminando
}
else{
estado = estado_personaje.parado
}

if pico_equipado == true {
if (keyboard_check(ord("S")))
or (keyboard_check(ord("W")))
or (keyboard_check(ord("D")))
or (keyboard_check(ord("A"))) {
estado = estado_personaje.caminando_pico
}else{
estado = estado_personaje.parado_pico
}
}


Esto funciona bien. El personaje se mueve en la 4 direcciones y cuando cojo el pico aparece con el pico y también cambia la animación en las 4 direcciones, esto funciona!

El problema viene cuando quiero que ataque y no se porque. Simplemente he puesto lo siguiente

if keyboard_check(vk_space) and estado = estado_personaje.caminando_pico
{
estado = estado_personaje.atacando
}


Poniendo esto ataca pero si mantengo pulsado la tecla y me muevo. En cambio, si pongo esto otro (que es lo que me interesa para que solo pueda atacar una vez por pulsación y animación):

if keyboard_check_pressed(vk_space) and estado = estado_personaje.caminando_pico
{
estado = estado_personaje.atacando
}


Solo se ve un mini segundo la animación pero enseguida vuelve al estado de caminando con pico. Entiendo que esto es porque solo esta en el estado de atacando durante el tiempo de la pulsación de la tecla, esto es así?

Como puedo hacer para que cuando pulse la tecla ataque y no se salga del script de ataque enseguida?

Script 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;
}

if image_index >= image_number-1{
estado = estado_personaje.parado_pico
}
Título: Re:Mi personaje no ataca cuando esta parado
Publicado por: FridaFlowers en Junio 03, 2019, 04:33:15 PM
Como no lo especifícas asumo que está todo en el evento step.
El problema es ese, que al estar en el evento step, tanto como presionas la barra espaciadora para atacar, el siguiente step evalua las condiciones de las teclas direccionales WASD.

Hmmm yo para arreglaro usaría una variable que indicase cúando ataca o no:

[gml]
if keyboard_check_pressed(vk_space) and estado = estado_personaje.caminando_pico
{
   estado = estado_personaje.atacando
        esta_atacando = true
}
[/gml]

Eso indicaría que está atacando, por lo que no debería reproducirse otra animacion sino, unicamente la de atacar:

[gml]
if (not esta_atacando) // si no se esta atacando cambiar a los estados habituales
{
   if (keyboard_check(ord("S")))
   or (keyboard_check(ord("W")))
   or (keyboard_check(ord("D")))
   or (keyboard_check(ord("A"))) {
      estado = estado_personaje.caminando
      }
      else{
         estado = estado_personaje.parado
      }

   if pico_equipado == true {
   if (keyboard_check(ord("S")))
   or (keyboard_check(ord("W")))
   or (keyboard_check(ord("D")))
   or (keyboard_check(ord("A"))) {

      estado = estado_personaje.caminando_pico
      }else{
         estado = estado_personaje.parado_pico
         }
      }
}
[/gml]

Ya luego cuando termine la animacion de atacar deberías cambiar la variable a false.
Imagino que el evento "Animation end" es el evento apropiado.
Título: Re:Mi personaje no ataca cuando esta parado
Publicado por: Fashion_Trozos en Junio 04, 2019, 12:38:59 PM
Bhuaa ya queda poquísimo! Ahora el personaje sigue atacando cuando estoy en movimiento, pero ahora hace algo extraño. Cuando me paro a veces hace el ataque y esta en estado de atacando parado, pero otras veces cuando me paro y presiono space sigue entrando en modo atacando parado pero la animación no es la correcta, se pone a mover los pies como si caminara. Es extrañisimo porque lo hace un poco como quiere, lo explicare con un ejemplo:

Si voy pulsando "A" o sea izquierda y voy pulsando space va atacando y realiza la animación de ataque en movimiento, en cuanto me paro (con el personaje mirando a la izquierda) a veces si que hace la animación de atacar pero a veces hace la de caminar y si sigo insistiendo dando toquecitos a la tecla "A" a veces se queda en la animación de atacar estando parado y a veces en la de caminar tambien estando parado. Par dar mas detalles, cuando dando toquecitos se queda en la animación de atacar ya cada vez que pulso space hace la animación de atacar sin moverse, pero si me muevo,  al pararme otra vez puede que haga una u otra animación. No se si me he conseguido explicar lo suficientemente bien. En todos los casos yo veo en la pantalla que entra en el script de atacar_parado, por eso no entiendo como puede hacer una animación u otra  ???

Normalmente es tan difícil conseguir que el personaje ataque parado?

Esto e slo que tengo en el step:

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

if keyboard_check_pressed(vk_space)
and dir!= "parado"
{
esta_atacando = true;
estado = estado_personaje.atacando
}

if keyboard_check_pressed(vk_space)
and dir = "parado"
{
esta_atacando = true;
estado = estado_personaje.atacando_parado
}


Título: Re:Mi personaje no ataca cuando esta parado
Publicado por: FridaFlowers en Junio 04, 2019, 04:09:54 PM
No, nada es complicado de hacer cuanto a lógica.  En realidad el problema viene cuando tienes que hacer calculos matematicos, y dibujar con surfaces(?

Ya, en serio, no es complicado si tienes anotado el flujo de acciones. Claramente, no se puede tener una idea en la cabeza y simplemente ponerse a escribir código esperando que funciones. Primeramente porque se te olvidan muchos casos en los que podria o no estar aplicandose.
En todo caso, lo mejor y mas recomendable sería escribir maso omenos en papel el flujo que debiera tener la logica del juego. Al menos en parte, la que estas intentando implementar.

Yo pienso que el problema no está en el script de ataque sino más bien, en que sprite estás colocando luego de que se realiza el ataque o bien, el sprite que colocas luego de que se deja de pulsar las teclas de direccion.

En cualquier caso, si quieres pasar el proyecto, usa el formato "yyz" puesto que es ese el que trae los recursos anexados. El "yyp" es solo la estructura del proyecto, osea , le faltan los sonidos, los sprites, etc.
Título: Re:Mi personaje no ataca cuando esta parado
Publicado por: Fashion_Trozos en Junio 04, 2019, 06:10:11 PM
Ahhh  okk, muchas gracias!