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: Mi personaje no ataca cuando esta parado  (Leído 1669 veces)

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

Desconectado Fashion_Trozos

  • Habitual
  • *
  • Puntos: 141
  • Mensajes: 72
    • Ver Perfil
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:

Código: [Seleccionar]
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   :)

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

if image_index >= image_number-1{
estado = estado_personaje.parado_pico
}

 


No Tienes Permisos Para Dar Puntos
point 0 Puntos

Este tema no recibió puntos.


Desconectado Fashion_Trozos

  • Habitual
  • *
  • Puntos: 141
  • Mensajes: 72
    • Ver Perfil
Respuesta #1 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:

Código: [Seleccionar]
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!
« última modificación: Mayo 28, 2019, 08:30:50 pm por Fashion_Trozos »

 


Desconectado Fashion_Trozos

  • Habitual
  • *
  • Puntos: 141
  • Mensajes: 72
    • Ver Perfil
Respuesta #2 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...

Código: [Seleccionar]
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?

« última modificación: Mayo 29, 2019, 12:48:50 pm por Fashion_Trozos »

 


Desconectado FridaFlowers

Respuesta #3 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.


 
Los siguientes usuarios dieron las gracias a este tema: Fashion_Trozos


Desconectado Fashion_Trozos

  • Habitual
  • *
  • Puntos: 141
  • Mensajes: 72
    • Ver Perfil
Respuesta #4 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!
« última modificación: Mayo 29, 2019, 11:48:29 pm por Fashion_Trozos »

 


Desconectado FridaFlowers

Respuesta #5 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

 


Desconectado 3dgeminis

Respuesta #6 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.
« última modificación: Mayo 30, 2019, 07:52:18 pm por 3dgeminis »

 


Desconectado Fashion_Trozos

  • Habitual
  • *
  • Puntos: 141
  • Mensajes: 72
    • Ver Perfil
Respuesta #7 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.
« última modificación: Mayo 30, 2019, 06:59:12 pm por Fashion_Trozos »

 


Desconectado FridaFlowers

Respuesta #8 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.

 
Los siguientes usuarios dieron las gracias a este tema: Fashion_Trozos


Desconectado Fashion_Trozos

  • Habitual
  • *
  • Puntos: 141
  • Mensajes: 72
    • Ver Perfil
Respuesta #9 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

 
« última modificación: Mayo 31, 2019, 10:03:33 am por Fashion_Trozos »

 


Desconectado FridaFlowers

Respuesta #10 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:
vh = (-keyboard_check(ord("A")) + keyboard_check(ord("D"))) * v;
Es anti natural.
Es preferible hacer 10 o 15 lineas mas pero que sean auto explicativas, por decir algo:
if keyboard_check(ord("D"))
    vh = 5
if keyboard_check(ord("A"))
    vh = -5

x += vh

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:
enum acciones{
         esperando,
         caminando,
         picando
}
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:
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
}
Bueno esa es una idea de como yo programaría.

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

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

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.
 
« última modificación: Mayo 31, 2019, 03:52:15 pm por FridaFlowers »

 


Desconectado Fashion_Trozos

  • Habitual
  • *
  • Puntos: 141
  • Mensajes: 72
    • Ver Perfil
Respuesta #11 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!

 


Desconectado Fashion_Trozos

  • Habitual
  • *
  • Puntos: 141
  • Mensajes: 72
    • Ver Perfil
Respuesta #12 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:

Código: [Seleccionar]
//-------------------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

Código: [Seleccionar]
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):

Código: [Seleccionar]
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:

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

if image_index >= image_number-1{
estado = estado_personaje.parado_pico
}
« última modificación: Junio 03, 2019, 01:47:43 pm por Fashion_Trozos »

 


Desconectado FridaFlowers

Respuesta #13 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:

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

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

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

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.

 
Los siguientes usuarios dieron las gracias a este tema: Fashion_Trozos


Desconectado Fashion_Trozos

  • Habitual
  • *
  • Puntos: 141
  • Mensajes: 72
    • Ver Perfil
Respuesta #14 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:

Código: [Seleccionar]
//--------------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
}

« última modificación: Junio 04, 2019, 12:42:47 pm por Fashion_Trozos »