Junio 13, 2021, 06:31:08 PM Ultima modificación: Junio 22, 2021, 03:02:24 PM por Bangaran
Hola amigos

tengo un inventario echo por un tutorial de youtube que pertenece a Woynert:

-Se puede abrir y cerrar el inventario
-Se pueden agregar los items
-Se pueden intercambiar los items
-Se pueden sacar los items del inventario

Pero quisiera que algunos items como por ejemplo las pociones se apilen
pero las espadas o las hachas no se apilen
los items en el create code de la room tiene su ID

no se si alguno me puede ayudar con eso
dejare el codigo

dejo el exportable por si acaso lo necesitan

sirve para GSM1 y para GSM2


ObjInventario

CREATE
[gml]///Variables
open = true;

L = 18; //Distancia entre dos slots
slotT = 16; //Total de slots

for (i = 1; i<=slotT; i++;) {
   slot = 0; //Item que almacena el slot i
}

//variables del mouse
mouse = 0;[/gml]

DRAW
[gml]//Dibujar Inventario

if open {
   var h = 0,
      k = 0,
      vx = view_xport,
      vy = view_yport,
      color = c_ltgray;
      
   for (i=1; i<=slotT; i++;) {
      //coordenadas individuales
      var sx = vx + L*k, sy = vy + L*h;
      
      //interaccion
      if point_in_rectangle(mouse_x, mouse_y, sx, sy, sx+16, sy+16) {
         //click
         if mouse_check_button_pressed(mb_left){
            //mouse vacio y slot lleno
            if mouse = 0 and slot != 0 {
               mouse = slot;
               slot = 0;
            }
            //mouse lleno y slot vacio
            else if mouse != 0 and slot = 0 {
               slot = mouse;
               mouse = 0;
            }
            //mouse lleno y slot lleno
            else if mouse != 0 and slot != 0 {
               //variable de respaldo
               var _item = slot;
               
               slot = mouse;
               mouse = _item;
            }
         }
         color = c_yellow;
      } else {
         color = c_white;
      }
      
      //fondo
      draw_sprite_ext(spr_borde, 1, sx, sy, 1, 1, 0, color, 1);
      
      //borde
      draw_sprite_ext(spr_borde, 0, sx, sy, 1, 1, 0, c_white, 1);
      
      //item
      if slot != 0 {
         draw_sprite(spr_items, slot, sx, sy);
      }
      
      //aumentar coordenadas
      k++;
      if frac(i/4) = 0 {
         h += 1;
         k = 0;
      }
   }
}

//Dibujar item del mouse
if mouse != 0 {
   //Dibujar item
   draw_sprite(spr_items, mouse, mouse_x-8, mouse_y-8);
   
   //Soltar item
   if mouse_check_button_pressed(mb_right) {
      with(instance_create_depth(obj_player.x-8, obj_player.y-8, 0, obj_item)){
         item = other.mouse;
      }
      mouse = 0;
   }
}[/gml]

KEY-PRESS-E
[gml]//Abrir y Cerrar

if open {
   open = false;
} else {
   open = true;
}
[/gml]


ObjItem

DRAW
[gml]//Dibuja inventario

image_index = item;
draw_self();[/gml]

LEFT PRESSED
[gml]//Agarra item

if scr_agregar(item) {
   instance_destroy();
}
[/gml]

SCRIPTS
[gml]
   var _item = argument0;
   
   with obj_inventario {
      for ( i = 1; i <= slotT; i++;) {
         if slot = 0 {
            slot = _item;
            return(1);
            exit;
         }
      }
      return(0);
   }[/gml]


https://www.youtube.com/watch?v=PVKWKjJh3rs Aca esta el link del video

Ok, primero creamos nuevas variables para mantener la cantidad de objetos por casilla:

[gml]///Variables
open = true;

L = 18; //Distancia entre dos slots
slotT = 16; //Total de slots

for (i = 1; i<=slotT; i++;) {
   slot = 0; //Item que almacena el slot i
   slot_n = 0;//Cantidad de ítems en el slot
}

//variables del mouse
mouse = 0;
mouse_n = 0;//Cantidad de ítems en el mouse[/gml]

Como puedes ver tenemos dos variables nuevas, un nuevo array llamado slot_n, que contendrá la cantidad de objetos que las casillas del inventario tienen, y una variable llamada mouse_n que contendrá la cantidad de objetos que el mouse tiene.

Ahora cambiamos la función scr_agregar, en la función original se buscaba en las casillas del inventario hasta encontrar un espacio vacío y se ponía ahí el ítem. Con los cambios que le hacemos:

[gml]function scr_agregar(){
   //scsr_agregar(item)
   
   var _item = argument0;
   
   with obj_inventario {
      //Busca si el ítem ya existe en el inventario y es apilable
      for ( i = 1; i <= slotT; i++;) {
         if scr_stackable(i,_item) {
            slot = _item;
            slot_n++
            return(1);
         }
      }//Busca si hay un espacio vació para poner el ítem
      for ( i = 1; i <= slotT; i++;) {
         if slot = 0{
            slot = _item;
            slot_n = 1
            return(1);
         }
      }
      return(0);
   }
}[/gml]

Ahora hace dos búsquedas, una para ver si el ítem ya existe dentro del inventario y es apilable, y si esa falla entonces una para buscar un espacio vacío donde poner el objeto. Nota como cuando el ítem ya existe dentro del inventario le sumamos 1 a slot_n en lugar de ponerle un valor predeterminado.

También notaras que llamamos una función nueva, scr_stackable, esta es la función que determinara que ítems se pueden apilar:

[gml]function scr_stackable(i,item){
   //Busca si el item es uno de los apilables
   if item == 1 || item == 2 {
      //Busca si la casilla actual tiene el mismo tipo de ítem
      if slot == item{
         return 1;
      }
      else return 0;
   }
   else return 0;
}[/gml]

Ahora hay que cambiar las interacciones con el mouse, con un par de excepciones esta parte es simple, simplemente hay que asegurarse de que los valores de las variables que contienen la cantidad de ítems en la casilla también se cambien.

[gml]//Dibujar Inventario

if open {
   var h = 0,
      k = 0,
      vx = view_xport,
      vy = view_yport,
      color = c_ltgray;
      
   for (i=1; i<=slotT; i++;) {
      //coordenadas individuales
      var sx = vx + L*k, sy = vy + L*h;
      
      //interaccion
      if point_in_rectangle(mouse_x, mouse_y, sx, sy, sx+16, sy+16) {
         //click
         if mouse_check_button_pressed(mb_left){
            //mouse vacio y slot lleno
            if mouse = 0 and slot != 0 {
               mouse = slot;
               mouse_n = slot_n;
               slot = 0;
               slot_n = 0;
            }
            //mouse lleno y slot vacio
            else if mouse != 0 and slot = 0 {
               slot = mouse;
               slot_n = mouse_n;
               mouse = 0;
               mouse_n = 0;
            }
            //mouse lleno y slot lleno
            else if mouse != 0 and slot != 0 {
               //variable de respaldo
               var _item = slot;
               var _item_n = slot_n;
               
               //Si ambos items son iguales
               if slot == mouse{
               slot_n += mouse_n
               mouse = 0
               mouse_n = 0
               }
               //Si los items son diferentes
               else{
               slot = mouse;
               slot_n = mouse_n;
               mouse = _item;
               mouse_n = _item_n;
               }
            }
         }
         color = c_yellow;
      } else {
         color = c_white;
      }
      
      //fondo
      draw_sprite_ext(spr_borde, 1, sx, sy, 1, 1, 0, color, 1);
      
      //borde
      draw_sprite_ext(spr_borde, 0, sx, sy, 1, 1, 0, c_white, 1);
      
      //item
      if slot != 0 {
         draw_sprite(spr_items, slot, sx, sy);
         
         //Dibuja la cantidad de items si es mayor que 1
         if slot_n>1 {
            draw_set_colour(c_black)
            draw_text_transformed(sx+12,sy+12,"x"+string(slot_n),0.25,0.25,0)
            draw_set_color(c_white)
         }
         
      }
      
      //aumentar coordenadas
      k++;
      if frac(i/4) = 0 {
         h += 1;
         k = 0;
      }
   }
}

//Dibujar item del mouse
if mouse != 0 {
   //Dibujar item
   draw_sprite(spr_items, mouse, mouse_x-8, mouse_y-8);
   //Dibuja la cantidad de items si es mayor que 1
   if mouse_n>1 {
      draw_set_colour(c_black)
      draw_text_transformed(mouse_x+4,mouse_y+4,"x"+string(mouse_n),0.25,0.25,0)
      draw_set_color(c_white)
   }
   
   //Soltar item
   if mouse_check_button_pressed(mb_right) {
      with(instance_create_depth(obj_player.x-8, obj_player.y-8, 0, obj_item)){
         item = other.mouse;
      }
      mouse_n--;
      if mouse_n == 0 mouse = 0;
   }
}[/gml]

Podrás notar que por ejemplo, en mouse vacio y slot lleno también movemos el valor de slot_n a mouse_n, para así asegurarnos de que la cantidad de objetos que había en ese slot sea la misma que cuando esta en el mouse, igualmente en cada interacción con el mouse deben tenerse en cuenta esas variables.

Las excepciones que mencione son en mouse lleno y slot lleno, donde agregamos una condición para que combine la cantidad de ítems si el ítem en la casilla y el que esta en el mouse son del mismo tipo, de lo contrario hace su comportamiento normal de cambiar ítems.

La otra excepción es en soltar ítem, ya que ahora es posible tener más de un ítem en el mouse se agrego un código para que suelte los ítems de uno en uno. Cada vez que suelta un ítem mouse_n se reduce en 1 y cuando llega a 0 es cuando se limpia el ítem del mouse.

También se agrego un dibujo de texto para mostrar la cantidad de ítems en una casilla si dicha cantidad es mayor a uno.

Dejo el editable para que veas los cambios.

Amigo Excelente gracias por tu ayuda
Muy muy buena tu ayuda
todo muy bn explicado

solo quede con una duda

veo q se apilan los dos primeros items q es la poción roja y la azul
pero por ejemplo si cambio de orden los items entonces se apilarian la espada y el pico

mi pregunta seria si hay alguna forma o manera de saber cual puedo apilar o cual no?

lo digo por si tengo por ejemplo 50 items

Como dije en el post anterior, la función scr_stackable es la función que determinará que ítems se pueden apilar:

[gml]function scr_stackable(i,item){
    //Busca si el item es uno de los apilables
    if item == 1 || item == 2 {
        //Busca si la casilla actual tiene el mismo tipo de ítem
        if slot == item{
            return 1;
        }
        else return 0;
    }
    else return 0;
}[/gml]

En la función se buscan los items 1 y 2, si se quiere cambiar a otros items o agregar más seria cuestión de modificar esa parte del código.

Entonces si quiero que otro ítem sea apilable en ese script lo colocaría

Ir ítem==1||ítem==2||ítem==3|| etc etc ...???

Amigo si quisiera que por ejemplo una de las pociones Rojas tenga por por ejemplo 5

Tendría que agregarle en el create code del la instancia algún number= 5

Algo asi??

Cita de: Bangaran en Junio 17, 2021, 03:50:52 PM
Entonces si quiero que otro ítem sea apilable en ese script lo colocaría

Ir ítem==1||ítem==2||ítem==3|| etc etc ...???
Correcto, por cierto, esto es algo que podrías haber probado tu mismo usando ese código que pusiste. Si bien acá siempre estamos dispuestos a responder las dudas de los miembros del foro, un poco de experimentación por cuenta propia va a ser esencial si realmente quieres aprender.

Cita de: Bangaran en Junio 17, 2021, 08:07:19 PM
Amigo si quisiera que por ejemplo una de las pociones Rojas tenga por por ejemplo 5

Tendría que agregarle en el create code del la instancia algún number= 5

Algo asi??
Si quieres que una variable number determine la cantidad de items que se agregan al inventario por instancia entonces tienes que cambiar la función scr_agregar para que tome en cuenta dicho valor:

[gml]function scr_agregar(){
   //scsr_agregar(item)
   
   var _item = argument0;
   var _number = argument1;
   
   with obj_inventario {
      //Busca si el item ya existe en el inventario y es apilable
      for ( i = 1; i <= slotT; i++;) {
         if scr_stackable(i,_item) {
            slot = _item;
            slot_n+=_number;
            return(1);
         }
      }//Busca si hay un espacio vacio para poner el item
      for ( i = 1; i <= slotT; i++;) {
         if slot = 0{
            slot = _item;
            slot_n = _number;
            return(1);
         }
      }
      return(0);
   }
}[/gml]

Ahí se le estaría pasando el número de items a agregar como argument1, y en lugar de aumentar el valor de un slot de 1 en 1 se aumenta de acuerdo a dicho valor. Solo quedaría cambiar la llamada de scr_agregar para agregar la nueva variable:

[gml]if scr_agregar(item,number) {
   instance_destroy();
}[/gml]

Algo a tener en cuenta es que esto hace que la variable number sea obligatoria y deberá agregarse al evento create del objeto, o al create code de cada instancia.

Si muchas gracias por tu ayuda de verdad eres un grande en esto

Disculpa q te moleste tanto

hay algunos errores a la hora se soltar el objeto y volverlo a agarrar
pero tratare de resolverlo!! muy agradecido contigoo