Hola, buenas. He estado buscando la manera de hacer un inventario en el cual se vayan ordenando los objetos conforme los "coges" o bien los "fabricas". Se que hay mil maneras de hacer inventarios, me he estado mirando el tema de los arreglos y listas, pero me falta base y me pierdo con facilidad. Me gustaría hacer un pequeño ejemplo, con digamos 4 slots me basta. Se que la pregunta es muy amplia y da como para un megatutorial, por el momento me bastaría con entender como puedo conseguir que detecte que un slot esta acupado por un objeto y que debe colocar el objeto en el siguiente. Como haríais el inventario, dibujando un sprite que sean 4 cuadrados, o usando un objeto que use ese sprite. Una vez dibujado el inventario, he conseguido que al fabricar, por ejemplo, un acha, se dibuje en el primer "slot" o recuadro, pero entiendo que no termino de ir por el camino correcto, creo que de esa manera game maker no sabe que el slot siguiente esta vacío. No se si me he explicado demasiado bien, en resumen, me gustaría hacer un inventario de 4 casillas en el que se coloquen los objetos en los huecos. (digo 4 huecos para simpificar una posible respuesta) Un saludo!
hola amigooou
hay dos maneras de trabajar con arreglos(vectores, arrays, listas, etc).
una es usando los arreglos convencionales de gm: vector
la segunda es usando listas dinamicas de gm: ds_list_create()
yo te voy a explicar usando arreglos estandar.
primero hay que declarar el arreglo e inicializarlo con un valor que nos indique que esta vacio, por ejemplo vamos a poner el 0:
(Evento Create)
[GML]
global.MAX = 4; //maximo de slots disponibles en el inventario
for(i=0; i<global.MAX; i++)
inventario = 0; // el cero indica que no hay nada en el inventario
[/GML]
Esto crea el arreglo con 4 elementos, que son el numero 0 que a efectos practicos, nos indicaria que no tienen items.
Luego, creamos un script desde el panel de recursos, que usaremos para obtener un espacio libre.
scr_obtener_slot
[GML]
for(i=0; i<global.MAX; i++){ //recorremos el arreglo
if (inventario == 0) //si hay un slot que este vacio
return i; // devolvemos la posicion que esta desocupada (puede ser 0, 1, 2, 3)
}
return -1; //en caso de que este todo ocupado, devolveremos el indice -1 que no existe, por lo tanto es un error
[/GML]
Este script nos devolvera el primer indice que esté desocupado. O -1 si esta todo lleno de items.
Luego para dibuijar las cosas tendrias que ir al Evento Draw y colocar algo como:
[GML]
for(i=0; i<global.MAX; i++){
draw_sprite(spr_cuadradito_del_inventario, x + (sprite_get_width(spr_cuadradito_del_inventario) * i, y); //esto dibujaria tantos cuadraditos como maximo de slots haya en el inventario
}
for(i=0; i<global.MAX; i++){ //este ciclo dibujaria los items
if (inventario == "navaja") //si en el espacio "i" hay una navaja, dibujarla
draw_sprite(spr_navaja, x + (sprite_get_width(spr_cuadradito_del_inventario) * i, y);
if (inventario == "comida") //si en el espacio "i" hay una navaja, dibujarla
draw_sprite(spr_comida, x + (sprite_get_width(spr_cuadradito_del_inventario) * i, y);
}
[/GML]
eso dibujaria el inventario y los items necesarios, Cabe resaltar que los sprites tienen que ser igual tamaño que el sprite que hace de cuadradito en el inventario
Luego la forma de guardar un item, por ejemplo Evento Colision de Player contra Pocima:
[GML]
var espacio_vacio = scr_obtener_slot();
if (espacio_vacio != -1) //si hay espacio vacio
inventario[espacio_vacio] = "pocima"
[/GML]
no probe el codigo, pero creo que la idea está
Uahh tio, muchas gracias, es exactamente lo que necesitaba. No he entendido exactamente todo, pero si veo que esa es la lógica correcta para hacer el tipo de inventario que quiero. Echaré un vistazo al "for" i a ver si entiendo exactamente como funciona. Gracias por el curro de respuesta! gracias!
amigo te dejo un grafico de como funciona el ciclo for en 4 pasos:
El ciclo for es eso, un ciclo, que se reptite contadas veces. En programación se conoce como "ciclo definido o ciclo finito" puesto que se sabe, cuantas vueltas va a dar el ciclo de antemano.
En nuestro ejemplo del inventario iba a dar 4 vueltas.
analizemos la estructura de FOR:
1º) se crea una variable contador, generalmente y por comodidad, en muchos lugares se la llama "i" del "iterator" en español iterador. Que es la variable que cuenta las iteraciones(repeticiones de codigo).
Esta parte se ejecuta 1 sola vez. Declara la variable para usarla como contador.
2º) la condicion que repite el ciclo. Esta parte se ejecuta varias veces y te indica la condicion que tiene el ciclo para seguir ejecutandose. Generalmente es un numero entero o una expresion de "i es menor a 10" y de ese estilo para que el ciclo se repita determinada cantidad de veces.
3º) aqui se ejecutan las acciones que se quieren repetir. Todo el codigo dentro se repite cada vez que el ciclo da vuelta.
4º) aqui se aumenta (o disminuye) el contador de manera de que se vaya sumando éste y termine en algun momento la condicion.
Por lo general se le suma de a 1 , raras veces vá hacia atrás o se suman en mas cantidad.
Luego de este 4º paso se vuelve a repetir el 2º paso y así, hasta que la condicion deje de cumplise.
Un ejemplo:
[gml]
for(i=0; i<2; i++){
instance_create(o_nave_enemiga, x,y)
audio_play_sound(snd_campana,1,0);
}
[/gml]
1) Este codigo inicializa la variable "i" en cero.
2) Verifica si la condicion es verdadera. "i" es menor a 3? en efecto, puesto que es igual a cero.
3) se crea una nave espacial y hace un sonido
4) aumenta el contador en 1 (i++ o bien se puede escribir como i+= 1), ahora vale 1
5) se verifica la condicion: "i" es menor a 3? en efecto, puesto que es igual a 1
6) se crea una nave y se hace un sonido
7) se aumenta el contador "i" en 1, ahora vale 2
8 ) se verifica la condicion "i" es menor a 2? no, puesto que es igual a 2, y 2 no es menor a 2.
9) termina el ciclo sin ejecutar acciones. No se vuelve a entrar en él
Uauu, compañero, muchísimas gracias por el esfuerzo, lo pondre como solucionado, lo has explicado super bien.
Ohhh, no. Hace un rato llgué a casa y lo he probado, me ha dado este error:
FATAL ERROR in
action number 1
of Step Eventob_piedra
for object ob_prota:
trying to index a variable which is not an array
at gml_Script_scr_obtener_slot_libre (line 6) - if inventario = 0 {
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Script_scr_obtener_slot_libre (line 6)
called from - gml_Object_ob_prota_Collision_b588f200_861f_4b56_ae28_73bb5befb700 (line 7) - var espacio_vacio = scr_obtener_slot_libre();
Que debo estar haciendo mal?
No encuentro cual es el problema. Puede ser que me de error por intentar cambiar un 0 de la matriz (inventario = 0) por una cadena de texto que aparece de la nada? en el caso del ejemplo del compañero "pócima"? (en mi caso lo estoy probando con "piedra"). Os pongo el código.
CREATE del ob_inventario
global.maximo_slots = 4
for (i=0;i<global.maximo_slots;i++) {
inventario[i] = 0
}
Esto es e evento colision del ob_prota con ob_piedra
if scr_obtener_slot_libre() != -1
inventario[scr_obtener_slot_libre()] = "piedra"
Y este es el script para comprobar slot libre
for (i=0;i<global.maximo_slots;i++) {
if inventario[i] == 0
return i
}
return -1
Y este el error que me da:
FATAL ERROR in
action number 1
of Step Eventob_piedra
for object ob_prota:
trying to index a variable which is not an array
at gml_Script_scr_obtener_slot_libre (line 6) - if inventario == 0
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Script_scr_obtener_slot_libre (line 6)
called from - gml_Object_ob_prota_Collision_b588f200_861f_4b56_ae28_73bb5befb700 (line 9) - if scr_obtener_slot_libre() != -1
Veis de donde me viene el error?. Estoy atascado aquí :-[
Buenas noticias!. He puesto global.inventario en lugar de inventario y ha funcionado!!!!. La única pega ahora mismo es que nada mas hacer la colisión con el ob_piedra se me llenan los 4 slots de "piedra" al instante.
Como puedo "regular" que cada vez que colisione o lo que sea, solo se llene el primer slot libre de piedra y no uno con cada step?
Buenas, en la pregunta que hice yo sobre random use una variable flag (boolean) para hacer que algo se ejecutase una sola vez dentro del evento step, pones la flag a true con la colision, y tras dar 1 de piedra la pones a false. Creo que eso podria solucionar ese pequeño problema.
Espero que te sirva :D
Al final lo solucione poniendo instance_destroy y funciona perfectamente. Avora el siguiente paso es hacer que los items del mismo tipo se amontonen en un mismo slot. Pondre este tema como solucionado. Muchas gracias a todos por ayudarme.