Detectar y memorizar objetos en cada room

Publicado por JohnW, Marzo 28, 2022, 12:14:30 AM

Tema anterior - Siguiente tema

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

JohnW

Hola, estoy creando un juego de aventura grafica, (estilo El Enigma De Aceps de Amstrad) pero sin escribir, todo a base de botones.

Tengo un boton que se llama "examinar" otro que se llama "coger" y otro "dejar"
Necesito crear una lista de objetos (los cuales no seran reales ya que en las pantallas no habran objetos). La idea es que al entrar en X room y le de al boton "examinar" me diga algo como "Veo la linterna y un pedernal".
Luego con el boton "coger" Pueda coger esa linterna o lo que sea y que desaparezca de la room esa (la room tiene que memorizar que ya se a cogido)
Luego si mas tarde suelto los objetos con el boton "dejar" en otras rooms, que la room memorize que se a soltado ahi por si luego vuelvo a esa room y me interesa cogerlo.
Y que a la vez me escriba por la pantalla las acciones "Veo X objeto" "Has cogido X objeto" "Has dejado X objeto"

Todo esto sin tener objetos fisicos dentro de la room ya que en la room solo se vera el fondo... los objetos realmente seran "imaginarios"

Tengo 31 rooms creadas, con los botones, la interfaz y demas... me falta algo asi para poner el juego a funcionar.

¿Me ayuda alguien?
Gracias a todos!



JohnW

#1
Hola de nuevo, he leido un poco acerca sobre las listas "array" y no consigo llevarlo a cabo.

Lo que he hecho es lo siguiente:

En un objeto control >  evento create: (Defino el inventario del PJ)
[gml]global.invpj[0] = "linterna"
global.invpj[1] = "pedernal"
global.invpj[2] = "anillo"
global.invpj[3] = "espada"
global.invpj[4] = ""[/gml]

En el boton examinar:

Evento create:
[gml]activo = 0;[/gml] Para controlar si pulsamos o no.

Evento Left Button:
[gml]activo = 1;[/gml] Confirmo que hemos pulsado el raton.

Evento Draw GUI:
[gml]if activo = 1 {           
        draw_text(32,32, + string("Tengo ") + string(global.invpj[]));
}[/gml] Me muestra mi inventario por pantalla.

El problema es que me lo muestra asi:
[gml]Veo { { linterna,pedernal,anillo,espada, },  }[/gml] Me muestra los signos { } y los espacios dnd no tengo nada.


¿Alguien me ayuda please?

JohnW

#2
Muchisimas gracias Void !!

Lo habia solucionado temporalmente de esta manera:
[gml]if activo == 1 {
for ( var i = 0 ; i < 5 ; ++i)
    {
    draw_text(400,550+i*20,+global.invpj);
    }[/gml]
Asi no me salian los signos raros, aunque no me gusta porque no funcionaba del todo bien, me hacia espacios dobles entre palabras.

Ahora he probado tu codigo y me gusta muchisimo!! Y esa idea de las comas y del "y" si es palabra final es genial.

Aunque ahora no se muy bien si servira todo esto para lo que quiero hacer te explico:

Resulta que estaba intentando poner en los "creation code" de cada room... su propio inventario es decir:
[gml]Room 1 > creation code
inv=[0];
inv=[1];

Room 2 > creation code
inv=[0];
inv=[1];[/gml]

Y desde el boton no me deja acceder si no las pongo como global.inv, el problema de ponerlo global es que al pulsar el boton mirar me mostraria todas las globales independientemente en la room que me encuentre.
Y ademas tendria que poner en el boton mirar el mismo codigo que me has pasado pero repetido por XX veces segun rooms tenga con global.inv

Asi que, de que otra manera podria hacerlo?

Por cierto, una vez me muestra los objetos del inventario, al cambiar de room se siguen viendo los textos de la array. ¿Se pueden borrar cada vez que cambias de room?

Muchas gracias de nuevo

JohnW

Cita de: Void en Marzo 29, 2022, 11:44:36 AM
Para que se deje de mostrar el texto cambia la variable activo de nuevo a 0.

El Creation Code de un room no es un buen lugar para controlar que items hay en un room, si el room no es persistente entonces se ejecutará cada vez que entres al room, lo que significa que aún si ya tomaste el item de un room cuando vuelvas lo volverá a generar. Y si el room es persistente el código se ejecutara una sola vez cuando entres al room por primera vez, así que no podrás controlar cambios como dejar otro objeto en el room.

De verdad te sugiero que uses objetos para controlar que items hay en cada room, puedes usar un único objeto que sea populado desde el Creation Code de un room persistente, de esta manera puedes accesar su contenido mientras estas en el room, cualquier cambio que se realize en su lista de items se mantendrá cuando salgas y vuelvas al room y cada room tendrá una lista de items propia.

Te dejo un pequeño ejemplo.

No me deja abrir el archivo, me sale el error de steam.

Otra cosa, he creado un "input text" basico, con la intencion de usar una ventana de comandos. La idea es que al escribir "X" comando te haga la misma funcion que el boton mirar.
Lo tengo creado asi:
[gml]Evento create:
keyboard_string = "";[/gml]

[gml]Evento Step:
if keyboard_check_pressed(vk_enter){
    Unlock = keyboard_string;
}[/gml]

[gml]Evento Draw:
draw_set_color(c_orange);
draw_text(550,950,keyboard_string + "|");

if keyboard_check_pressed(vk_enter){
    Unlock = keyboard_string
    if Unlock == "mirar"{
    draw_text(32,100,global.invpj);
}else{
    draw_text(32,100,"No comprendo");
    }keyboard_string = "";
}[/gml]

Con esto me surgen 2 problemas... el primero es que me salta el error:
[gml]Push :: Execution Error - Variable Get 100002.i(100029, -2147483648)
at gml_Object_inputBox_DrawEvent_1 (line 7) -     draw_text(32,100,global.invpj);[/gml]

Se ve que no puede entrar a la lista "array" a leerme esos objetos igual que hace el boton mirar.
Y el segundo error que tengo, es que al escribir algo... el mensaje por ejemplo "No comprendo" Me sale por pantalla pero al segundo se borra... cuando tendria que permanecer en pantalla hasta que cambies de room a otra.

Ahora mirare la manera que tu dices de crear objetos por pantalla y ponerlos en invisible... para que no se vean y aver si asi consigo mejores resultados.

JohnW

#4
Hola de nuevo,
he probado a copiar el codigo que me pasaste en un script... y desde el inputbox cargarlo al escribir "mirar" pero no hace nada.
[gml]draw_set_color(c_lime);
draw_set_font(Fpantalla);

draw_text(550,950,"[Consola]> "+keyboard_string);

if keyboard_check_pressed(vk_enter){
    if Unlock == "mirar"{
    script_execute(inventariopj);     
}else{
    draw_text(550,900,">No comprendo");}
    keyboard_string = "";
}[/gml]

Aunque me dado cuenta que si primero pulso el boton "mirar" y luego escribo en el inputtext "mirar" Si que me ejecuta el script, pero si no pulso el boton y escribo de primeras "mirar" no me carga nada.

JohnW

#5
Hola de nuevo, siento ser molesto.

He probado lo que me dices.
Escribir mirar y que entre al array a buscar... me funciona solo que me muestra el primer objeto, (Ahora mirare de crear un for para recorrer todo)
Pero haciendo lo que me dices, anulamos por completo el codigo que me hisciste del array con el boton "mirar" y suyo seria que al escribir "mirar" funcionara igual. Por eso intentaba copiarlo todo a un script y desde el inputtext cargar dicho script. Pero no se hacerlo.

El problema de que desaparece el mensaje despues de pulsar enter me sigue pasando. He probado de todas las maneras, incluso creando alarmas, timers creados por mi.... y nada funciona. Cuando apreto el enter se borra tanto el contenido del "array" que me muestra, como el "No comprendo" en caso de error.

[gml]draw_set_color(c_lime);
draw_set_font(Fpantalla);
draw_text(550,950,"[Consola]> "+keyboard_string + cursor);

var String = "";

if keyboard_check_pressed(vk_enter){
    Unlock = keyboard_string
    if Unlock == "mirar"{
    draw_text(550,900,">Correcto");
    for (var i=0;i<5;i+=1){
    String = string(global.invpj);}
}else{
    draw_text(550,900,">No comprendo");
    }keyboard_string = "";
}
draw_text(32,100,String)[/gml]

Añadi un ciclo FOR, no se porque pero solo me muestra el ultimo objeto de la lista array en vez de todos, pero repito, haciendo esto... no sale igual que cuando apretas el boton "mirar" con el codigo que me hiciste.

JohnW

#6
Muchas gracias!!
Me estas ayudando muchisimo con este proyecto!

Ahora me surge la duda:
Con este codigo creado, si quisiera poner un comando mas digamos "examinar" para examinar la room en la que me encuentro, teniendo en cuenta que tengo 31 rooms...

¿Seria posible que ese comando "examinar" pudiera examinar cada room, y decirme que objetos hay?

Con objetos me refiero a listas array no a objetos reales...

Yo la idea que tenia para esto era:
Crear un script como ese para cada room llamados "examinarroom1" "examinarroom2" etc... luego en el comando "examinar" del inputbox decirle algo como...
Si escribes examinar, y estas en la room 1 pues examina "examinarroom1", etc...

Es un poco tedioso y largo de hacer... pero no se me ocurre por ahora otra forma de hacerlo.

¿Es muy dificil lograr eso con menos codigo?
Teniendo en cuenta que tengo que añadir mas comandos, como "coger X objeto" etc...

Y la otra cosa es:
Quiero poner el comando "Coger X objeto" si estas en una room que haya un objeto.
Entonces los objetos de las rooms pertenecerian a diferentes arrays... cada array para una room.
Y al escribir "coger X objeto" tendria que sacar el objeto de esa array de la room y ponerla en la array del inventario del pj siempre que haya espacio y en caso de que no, decir "No puedes llevar mas objetos"

Claro que luego abria que añadir el comando "Dejar X objeto" y que hiciera lo mismo pero a la inversa, sacarlo del array del PJ y meterlo en la array de room actual.

No se si esto que pido ya es mas complicado... o deberia hacerse de otra manera que no sean arrays.

JohnW

#7
Gracias de nuevo la verdad que soy patoso con esto... voy programando a medias porque me quedo atascado sin saber ver mas alla.

Aver si lo he hecho bien:
En las 31 rooms, las he marcado como "Persistente" y en Creation Code de cada una de ellas he puesto esto:
[gml]var Inst = instance_create(0,0,obj_inventario_room);[/gml]
En las rooms que por defecto tiene objetos he puesto esto:
[gml]var Inst = instance_create(0,0,obj_inventario_room);
with Inst {
    inv[0] = "linterna";
    inv[1] = "pedernal";
}[/gml]
He creado el objeto "obj_inventario_room":
[gml]inv[0] = 0;[/gml]
He creado un script llamado "mirarinventarioroom" con el mismo codigo del pj pero cambiando el array:
[gml]var Length = array_length_1d(inv),
    String = "",
    Temp_Array,
    c = 0;

for (var i=0;i<Length;++i){
    if is_string(inv) && inv!="" {
        Temp_Array[c] = inv;
        c++;
    }
}

Length = array_length_1d(Temp_Array);
for(var i = 0; i < Length; ++i){
    String += Temp_Array;
    if i == Length-2 String += " y ";
    else if i < Length-2 String += ", ";
}
return String[/gml]

Y aqui me viene el primer problema que no se hacer... he colocado el comando "mirar" en el inputbox, antes del else, despues del else, incluso copiando todo el codigo debajo con el nuevo comando. Pero no se hacerlo y me da error.
Ahora lo tengo asi:
[gml]if keyboard_check_pressed(vk_enter){
    Unlock = keyboard_string
    if Unlock == "inventario"{
    String = "Tengo " + mirarinventariopj();
}   if Unlock == "mirar"{
    String = "Veo " + mirarinventarioroom();
}
else{
    String = ">No comprendo";
    }keyboard_string = "";
}
draw_text(550,900,String)[/gml]

Me da 2 errores, el primero es en el script nuevo:
[gml]Push :: Execution Error - Variable Get 100001.inv(100006, -2147483648)
at gml_Script_mirarinventarioroom (line 1) - var Length = array_length_1d(inv),[/gml]
El segundo es logicamente en el inputbox porque no se añadirlo bien:
[gml]stack frame is
gml_Script_mirarinventarioroom (line 1)
called from - gml_Object_inputBox_DrawEvent_1 (line 10) -     String = "Veo " + mirarinventarioroom();[/gml]

Respecto a lo de coger y soltar los items del inv pj a los inv room supongo que se hace asi no?:

Si en la room 4 tengo:
[gml]var Inst = instance_create(0,0,obj_inventario_room);
with Inst {
    inv[0] = "linterna";
    inv[1] = "pedernal";
}[/gml]
Y quiero pasar la linterna del inv al global.inpj sera asi:

En el comando coger linterna:
[gml]array_delete(inv, linterna, 1);     //Para borrarlo del inv de la room
array_push(global.invpj, linterna);   //Para añadirlo al global.invpj del PJ[/gml]

Y luego en el comando dejar linterna al reves:
[gml]array_delete(global.invpj linterna, 1);     //Para borrarlo del inv de la room
array_push(inv, linterna);   //Para añadirlo al inv de la room[/gml]

Voy bien encaminado?

Ahora para que me diga que el personaje no puede llevar nada mas (El limite del PJ es 5) ya no sabria hacerlo.
Y otra duda que me surge de todo esto, los "inv" que he puesto en las rooms... cada vez que se suelte un objeto, ese inventario va creciendo solo? Es decir puedes soltar objetos infinitos y el array crece asignando una id a cada uno.

JohnW

#8
Cambie el script por ese pero al escribir mirar me sigue dando los errores estos:
[gml]Push :: Execution Error - Variable Get -7.Temp_Array(100005, -2147483648)
at gml_Script_mirarinventarioroom (line 13) - Length = array_length_1d(Temp_Array);
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Script_mirarinventarioroom (line 13)
called from - gml_Object_inputBox_DrawEvent_1 (line 10) -     String = "Veo " + mirarinventarioroom();[/gml]

Perdon modifico... me sigue dando error... pero el error me lo da en las rooms dnd no tengo objetos.. en las que tengo objetos me funciona bien.
Y al poner el comando mirar,... deja de funcionar el comando inventario.

[gml]var Pos = array_find(global.invpj,"")
if  Pos != -1 {
obj_inventario_room.inv = array_delete(obj_inventario_room.inv,array_find("Nombre del item"),1)
global.invpj[Pos] = "Nombre del item"
String = "Tomas " + "Nombre del item"
}
else String = "No tengo espacio para tomar " + "nombre del item"[/gml]

Luego este codigo me dice que la funcion "array_find" Unknown function or script
El "array_push" me pone lo mismo.

JohnW

#9
Creo que la estoy liando...

Aver primero de todo he declarado la variable en mi objeto control principal del inicio del jueto:
[gml]Temp_Array[0] = "";[/gml]
He intentado convertir el inputbox con switch como me dijiste pero me tira error y ahora no me deja ni escribir se borra todo lo que escribo, no se si lo hize mal:
[gml]if keyboard_check_pressed(vk_enter){
    Unlock = keyboard_string;
    switch (Unlock){
        case 1: if (Unlock) == "inventario"{
                    String = "Tengo " + mirarinventariopj()}; break;
        case 2: if (Unlock) == "mirar"{
                    String = "Veo " + mirarinventarioroom()}; break;
}keyboard_string = "";}else{
String = ">No comprendo";}
draw_text(550,900,String)[/gml]

Los scripts me daba error en esas lineas pero ya arregle lo de los scripts que no me los detectaba y me tiraba error.... reiniciando el programa se arreglo.
Falta arreglar el switch del inputbox.

Siento molestarte tanto... pero ahora mismo estoy muy liado con todos estos cambios y estoy muy perdido.

Muchas gracias por toda la ayuda que me estas ofreciendo.

JohnW

#10
Lo de los scripts ya lo arregle, me daba error aun creando los scripts pero guarde todo, y reinicie el programa... aveces me pasa no se porque... sera que tengo algo corrupto en la instalacion que a veces me falla.

El codigo del Temp_Array me da error de escritura la linea.

Unexpected symbol in expression. Como si estuviera mal definida


Los codigos para coger y dejar objetos que me pusiste... los copio en un script y luego en el inputbox los llamo asi?
[gml]case ("coge linterna"):cogeobjeto(); break;
case ("deja linterna"):dejaobjeto(); break;[/gml]

Porque de esa forma me da error:
Function "array_find" expects 2 arguments, 1 provided

JohnW

#11
Entonces para que funcione los comandos "coger objeto" y "dejar objeto" he de copiar los scripts de coger y tantas veces como objetos tenga sustituyendo en cada copia el "nombre del item" por el nombre del objeto, no?

Por ejemplo para coger linterna:
[gml]var Pos = array_find(global.invpj,"")
if  Pos != -1 {
obj_inventario_room.inv = array_delete(obj_inventario_room.inv,array_find("Linterna"),1)
global.invpj[Pos] = "Linterna"
String = "Cojo " + "Linterna"
}
else String = "No tengo espacio para coger " + "Linterna"[/gml]
Y ahora justo debajo copio todo ese codigo pero con otro item... asi con todos, y con el script de dejar items lo mismo no?

El error que me daba era que faltaba un "1" al lado de linterna xq pedia 2 argumentos y le estabamos dando 1 quedando asi:
[gml]var Pos = array_find(global.invpj,"")
if  Pos != -1 {
obj_inventario_room.inv = array_delete(obj_inventario_room.inv,array_find("linterna",1),1)
global.invpj[Pos] = "linterna"
String = "Cojo " + "linterna"
}
else String = "No tengo espacio para coger " + "linterna"[/gml]

Ahora me da error al coger un objeto me da error en array_delete:
[gml]Push :: Execution Error - Variable Get -7.temp_array(100008, -2147483648)
at gml_Script_array_delete (line 9) - return temp_array;
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Script_array_delete (line 9)
called from - gml_Script_cogeobjeto (line 3) - obj_inventario_room.inv = array_delete(obj_inventario_room.inv,array_find("linterna",1),1)
called from - gml_Object_inputBox_DrawEvent_1 (line 10) -         case ("coge linterna"):cogeobjeto(); break;
[/gml]
De momento para que no me diera error he comentado la linea: return del array_delete:
[gml]//return temp_array;[/gml]
con eso no me da error pero supongo que evitar eso me causara problemas futuros.

He intentado copiar los scripts de dejar y coger uno debajo de otro con diferentes items... pero no funciona...

Y he localizado otro fallo... cuando estoy en una room donde hay mas de 1 objeto... por ejemplo room 4 hay linterna y pedernal... si le dijo coge linterna... desaparece la linterna y el pedernal de la room. No se queda el pedernal.

Resumido:
Fallos:
el return temp_array que de momento lo he dejado comentado.
en una room con mas de 1 objeto, coge el primero y los demas que hay en la room los borra.
Al copiar los scripts de coger y dejar uno debajo de otro con mas objetos. No funciona.
Al escribir el comando inventario, con el inventario del PJ vacio salta este error:
[gml]Push :: Execution Error - Variable Get -7.Temp_Array(100005, -2147483648)
at gml_Script_mirarinventariopj (line 13) - Length = array_length_1d(Temp_Array);
[/gml]

JohnW

#12
Cita de: Void en Marzo 31, 2022, 02:39:29 AM
No crees un código adicional por item, en su lugar usa un solo script al que se le pueda pasar el nombre del item como argumento.
No se hacer esto, he intentado hacer un script con switch agregando en cada case un objeto y luego pasarle ese script al codigo de coger y dejar objetos pero no me aclaro.
CitarNo, como te dije, lo que le falta es el nombre del array, obj_inventario_room.inv. No pongas argumentos al azar, solo porque deja de tirar error no significa que esta funcionando. Si tienes que adivinar un argumento estudia el código primero para al menos tener alguna idea de lo que pide.
No se a que te refieres con el array del obj_inventario_room.inv porque ya esta puesto eso.
[gml]var Pos = array_find(global.invpj,"")
if  Pos != -1 {
obj_inventario_room.inv = array_delete(obj_inventario_room.inv,array_find("linterna"),0,1)
global.invpj[Pos] = "linterna"
String = "Cojo " + "linterna"
}
else String = "No tengo espacio para coger " + "linterna"[/gml]

CitarEl error que te da con array_delete es el mismo de antes, temp_array debe ser inicializado como un array con una cadena vacía, el problema fue que no anticipe que pasaría con arrays que tienen solo un elemento.
En un script si me deja inicializar el temp_array como un array vacio pero en otros me da error de escritura y no me deja guardarlo con ese error.
Aporto imagen:
https://ibb.co/rbMQnF8
CitarSin ver el código me imagino que el problema es que, como dijiste al principio, incluiste más código para el resto de los items en el mismo script, y sin nada que lo detenga el código sigue corriendo para todos los items que encuentre en el room.
En el codigo del inputbox cada comando esta cerrado por un break con lo que deberia detenerse ahi.
[gml]if keyboard_check_pressed(vk_enter){
    Unlock = keyboard_string;
    switch (Unlock){
        case ("inventario"): String = "Tengo " + mirarinventariopj(); break;
        case ("mirar"): String = "Veo " + mirarinventarioroom(); break;
        case ("coge linterna"):cogeobjeto(); break;
        case ("deja linterna"):dejaobjeto(); break;
        default: String = ">No Comprendo"; break;
    }
    keyboard_string = "";
}
draw_text(550,900,String);[/gml]
Yo creo que el fallo de que me coja un objeto y los demas los borre de la room esta en este otro codigo:
[gml]var Pos = array_find(global.invpj,"")
if  Pos != -1 {
obj_inventario_room.inv = array_delete(obj_inventario_room.inv,array_find("linterna"),0,1)
global.invpj[Pos] = "linterna"
String = "Cojo " + "linterna"
}
else String = "No tengo espacio para coger " + "linterna"[/gml]

JohnW

Muchas gracias de nuevo amigo.

Entiendo que lo mismo que has hecho en este codigo:
[gml]var Pos = array_find(global.invpj,"")
if  Pos != -1 {
obj_inventario_room.inv = array_delete(obj_inventario_room.inv,array_find(obj_inventario_room.inv,argument0),1)
global.invpj[Pos] = argument0
String = "Cojo " + argument0
}
else String = "No tengo espacio para coger " + argument0[/gml]
Lo he de hacer igual en el "dejaobjeto" quedando asi:
[gml]var Pos = array_find(global.invpj,argument0)
if  Pos != -1 {
obj_inventario_room.inv = array_push(obj_inventario_room.inv,argument0)
global.invpj[Pos] = ""
String = "Dejo " + argument0
}
else String = "No tengo " + argument0;[/gml]

Ahora parece que no falla, pero sigo teniendo el error de que cuando estoy en una room con varios items... al coger 1 los demas los borra de la room.
¿Es posible que el fallo este aqui?
[gml]var temp_array,
    Length = array_length_1d(argument0)
    c = 0;
    temp_array[0]="";
for (var i = 0; i<Length;++i){
    if i<argument1 && i > argument1+argument2-1
    temp_array[c] = temp_array;
    c++;
}
return temp_array;[/gml]
Que le estemos diciendo argument1 y 2 y por eso coge 2 items?

JohnW

Me habia fijado en eso y probe tambien poner los "||" y tambien probe de poner "or"... pero con esa modificacion me tira este error:

[gml]Push :: Execution Error - Variable Index [0,1] out of range [1,1] - -7.temp_array(100008,1)
at gml_Script_array_delete (line 7) -     temp_array[c] = temp_array;[/gml]

Tambien tengo un error al escribir el comando "coge (objeto)" en una room donde no hay objetos:
[gml]DoSet :: Invalid comparison type
at gml_Script_array_find (line 3) -     if argument0 == argument1 return i;[/gml]
Refiriendose al script array_find:
[gml]var Length = array_length_1d(argument0);
for(var i=0;i<Length;++i){
    if argument0 == argument1 return i;
}
return -1;[/gml]

Powered by EzPortal
SMF spam blocked by CleanTalk