Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mensajes - BssString

16
Hola FernandoNavarro

No sé si eso sea posible la verdad. Creo que steam ofrece un Cloud Service, pero no estoy seguro cómo funciona, nunca lo he usado.

Saludos
17
Hola Ikaro3d

Que bueno que haya funcionado. Si has programado algo con gamepad, me gustaría testear tu proyecto cuando generes algún ejecutable.

Saludos
18
Preguntas y respuestas / Re:multijugador CO-OP
Abril 21, 2020, 05:41:58 AM
Hola cristopher2545

Eso no es posible, para conectarte a un servidor que está corriendo en otra máquina es mandatorio tener la dirección IP del host.
No puedes simplemente poner una contraseña y ya, sin la IP no hay conexión.
Una vez que ya hayas establecido la conexión con la IP del host puedes añadir una contraseña para filtrar si acepta o no acepta tus paquetes de datos.

Saludos
19
Hola Ikaro3d

Encuentro interesante tu idea de usar LERP para suavizar el movimiento, pero le veo un problema al código de teclado.
Específicamente a la condición: "if keyboard_key" del inicio... no le encuentro sentido, pienso que el código quedaría mejor si la borras.
Esa condición te hace frenar de golpe si sueltas todas las teclas y no dejas que el lerp complete la distancia.
Ejemplo: si vas todo a la derecha, te deberías mover a la derecha con el suavizado y todo perfect, pero si sueltas todas las teclas de golpe, el personaje frena de golpe, pero aún le falta recorrer un 85% de la distancia que el LERP del step anterior no lo hizo recorrer. Eso significa que si ahora pulso izquierda, el personaje primero avanzará ese 85% hacia la derecha y luego irá a la izquierda como era esperado.

Este código debería funcionar con el JoyPad. Va explicado con comentarios para que no te pierdas.

[gml]//Primero recibo en qué porcentaje muevo el Stick (regresa un valor entre -1 y 1).
//En algunos Joystick de mala calidad, el axis queda pulsado ligeramente, para evitar eso, cuando se mueve 0.1 o -0.1, lo interpreta como 0.
var hdir = gamepad_axis_value(0,gp_axislh); if abs(hdir) < 0.1 { hdir = 0 }
var vdir = gamepad_axis_value(0,gp_axislv); if abs(vdir) < 0.1 { vdir = 0 }

//En caso de haber movimiento en cualquiera de los dos ejes:
if hdir != 0 || vdir != 0 {
//Convierte la coordenada cuadrada del X/Y a una coordenada circular (para que no importa a cuál de los 360º se mueva el personaje, nunca supere la máxima velocidad "v", si no haces esto, en diagonal se movería más rápido)
hdir *= sqrt(1 - 0.5*vdir^2)
vdir *= sqrt(1 - 0.5*hdir^2)
//Esto simplemente ajusta el "x" target e "y" target tal como lo tienes en tu código para keyboard.
xx += v*hdir
yy += v*vdir
}
//Esto actualiza las coordenadas del personaje para moverse un 15% de la distancia que hay entre su coordenada actual y su coordenada objetivo.
x=lerp(x,xx,0.15)
y=lerp(y,yy,0.15)[/gml]

Edit: Ojo que si pulsas derecha y al mismo tiempo mueves el Stick a la derecha, te moverás dos veces a la derecha (al doble de rápido). Deberías crear algún "if" que te haga moverte o con teclado o con joypad, pero no ambos a la vez

Saludos
20
Hola FernandoNavarro

Para eso se usa la función "http_get_file", sólo necesita 2 parámetros, el link de donde descargará el archivo y el nombre del archivo que guardará.

Y lo de la descarga directa se refiere a que cuando subes un archivo a tu Google Drive, le puedes dar clic secundario y elegir "get shareable link", no sé exactamente cómo se llama esa opción en español, pero creo que es algo así como "obtener link para compartir".
Y eso te genera una ruta, yo aquí he subido un archivo de prueba y esta es la ruta que me genera:
https://drive.google.com/open?id=1yC-ily-29t6jp7OrTSRcvfCUME4GWBCK
Pero ese NO es el link directo. Porque para descargar debes entrar al link y luego pulsar en el botón "descargar".

Ahora... si haces clic en el logo de descarga en la esquina superior derecha (el logo es una flecha apuntando hacia abajo) entonces eso ya te lleva al enlace de descarga directa que a penas entras te baja el archivo. Este es el link de descarga DIRECTA que me ha generado a mí:
https://drive.google.com/u/0/uc?id=1yC-ily-29t6jp7OrTSRcvfCUME4GWBCK&export=download

Ese link es el que debes meter en Game Maker. El proceso es muy sencillo.

Básicamente esta es la línea de código que te descarga el archivo:
Create Event
[gml]file = http_get_file("https://drive.google.com/u/0/uc?id=1yC-ily-29t6jp7OrTSRcvfCUME4GWBCK&export=download","DLC/test.txt")[/gml]
Le he dicho que me descargue el archivo del link y lo guarde en la Carpeta: "DLC" con el nombre "test.txt".
Y listo, eso es todo xD corres esa línea de código y ya tienes el archivo en la carpeta de tu juego que por defecto es %localappdata%/<nombre de tu proyecto>.

Ahora si quieres ejecutar alguna línea de código una vez que el archivo se haya descargado, puedes usar el siguiente evento:

Asynchronous HTTP Event
[gml]if ds_map_find_value(async_load, "id") == file {
var status = ds_map_find_value(async_load, "status");
if status == 0 {
   var path = ds_map_find_value(async_load, "result");
   if file_exists(path) show_message("Descarga completa");
   }
}[/gml]
En ese ejemplo simplemente ejecuta un "show message" al descargar el archivo.

Ojo que creo (no estoy muy seguro) que Google Drive tiene un límite de descargas por archivo para evitar saturar el servidor o evitar ataques DDOS. No sé si es un límite en la cantidad de descargas o en la cantidad de KB que estás descargando, te sugiero investigar sobre ello.

Saludos
21
Preguntas y respuestas / Re:RANDOM MUY LENTO
Abril 15, 2020, 01:23:21 AM
Hola nonoroman

Se me ocurre que eso puede estar causado por dos cosas:
1- que en uno de los proyectos el Step Event esté muy saturado de cosas y bajen los FPS al ejecutar el juego.
2- que hayas modificado la Room Speed, entonces los proyectos van a tiempos diferentes.

Verifica ambas y comenta si era alguna de esas o no.

Una cosa más. Algo más efectivo que usar:
random_set_seed(current_second);
Es usar:
[gml]randomize()[/gml]

Saludos
22
Hola T789

En vez de usar Arrays, cámbialo por una data structure del tipo "LIST".

CREATE EVENT
[gml]mensaje = ds_list_create()[/gml]

DESTROY EVENT
if mensaje != noone { ds_list_destroy(mensaje); mensaje = noone }

GAME END EVENT
if mensaje != noone { ds_list_destroy(mensaje); mensaje = noone }

Luego en tu STEP EVENT reemplaza todos los:
[gml]mensaje[mensaje_start][/gml]
por:
[gml]ds_list_find_value(mensaje,mensaje_start)[/gml]

Y esta es la función que debes usar para añadir líneas al texto, puedes crear un script para facilitarte las cosas y no repetir estas dos líneas a cada rato.
[gml]ds_list_add(obj_letrero.mensaje,"Tu línea de texto aquí","Puedes añadir hasta 15 líneas usando la misma función")
mensaje_end = ds_list_size(obj_letrero.mensaje) //Asegurate de re-ajustar la cantidad de parrafos cada vez que metes uno nuevo, sino tu STEP EVENT no los leerá todos.[/gml]

Saludos
23
Preguntas y respuestas / Re:barra de espera de texto
Abril 02, 2020, 02:00:03 AM
Hola WMKILLER

Yo en mi juego lo hice con una alarma. Cada vez que pulsaba una tecla, activaba la alarma por 24 STEPS. En el DRAW EVENT puse una condición simple que era: si a la alarma le quedaban más de 10 STEPS para activarse, se dibujaba la barra, si le quedaba menos NO se dibujaba, eso causaba el efecto de parpadeo.
Para encontrar la posición puedes usar "string_width".

Un ejemplo simple:
STEP EVENT
[gml]if keyboard_check(vk_anykey) { alarm[0] = 24 } //Al pulsar cualquier tecla, le mete un delay a la barrita de 24 steps para comenzar a parpadear (se dibuja durante 14 steps y NO se dibuja durante 10 steps)[/gml]
ALARM0 EVENT
[gml]alarm[0] = 18 //Esto hace que se genere un loop infinito donde la barrita parpadeará para siempre (8 steps visible y 10 steps invisible)[/gml]
DRAW EVENT
[gml]if alarm[0] >= 10 draw_text(x+string_width(text),y,"|")[/gml]

Los tiempos te los inventé, tu usa los que encuentres que mejor se adapten a tu juego.
Creo que la función "string_width" se buggea cuando lee un caracter de salto de línea, yo en mi juego lo corregí reemplazando el carácter y ajustando el ancho.
Lo otro que me acuerdo que pasó, es que la barra no se dibujaba en la posición correcta, se dibujaba mucho más a la derecha, así que en el draw_text debes quitarle unos pixeles para ajustar la posición según el tamaño de la fuente que uses.

Saludos
24
Hola VietnamNeko

Si el objeto tiene una colisión cuadrada, puedes revisar cuál boundary box colisionó comparando las distancias entre las "bbox_bottom, bbox_left, bbox_right y bbox_top" de ambos objetos.
Si el objeto tiene una colisión precisa, te recomiendo usar un segundo objeto con una máscara de colisión más pequeña que te detecte la colisión, como una especie de hurt box o hit box (no sé como se le llama).

Pero todo depende de lo que quieras hacer, no me quedó muy claro... Cuando te refieres a "la punta de un objeto colisione con una pared", pienso que es más fácil calcular la coordenada X/Y de la punta y crear los objetos ahí sin hacer ningún cálculo raro con colisiones.

Saludos
25
Hola FernandoNavarro

Te recomiendo usar la función:
[gml]direction = point_direction(x,y,objEnemy.x,objEnemy.y)[/gml]
Que toma el ángulo que se forma entre 2 puntos y luego se lo asigna a la variable "direction".

Saludos
26
Hola Ikaro3d

Intenta con:
[gml]image_angle = direction[/gml]
27
Hola VietnamNeko

Crea variables auxiliares que almacenen la posición del proyectil (antes de crearlo).
Luego calcula la distancia y dirección que hay desde el origen de tu objeto hasta el proyectil creado
Luego crea el objeto en la misma distancia del origen, pero con la dirección afectada por la "image_angle" del objeto, eso hará que el objeto creado rote junto con el objeto creador.

Ejemplo:
[gml]if image_index = 15{
var xx = irandom_range(x,sprite_width); //La futura X donde crearás el objeto
var yy = irandom_range(y,sprite_height); //La futura Y donde crearás el objeto
var len = point_distance(x,y,new_x,new_y); //La distancia lineal entre el x,y del creador hacia la bala
var dir = point_direction(x,y,new_x,new_y); //La inclinación entre el x,y del creador hacia la bala
//Luego creas la bala en el nuevo lugar, alterado por la image_angle del creador, pero basada en la misma distancia original.
    with(instance_create(x+lengthdir_x(len,dir+image_angle),y+lengthdir_y(len,dir+image_angle),obj_hell_bullet)){
        motion_set(point_direction(x,y,jaguar.x,jaguar.y),1)
    }
}[/gml]

Saludos
28
Hola fredred156

En Game Maker cada línea de código se ejecuta una a una en orden, eso quiere decir que no ejecuta la segunda hasta que no haya leido la primera.
Corta el código de movimiento izquierda-derecha y pégalo después de todo el código que nos acabas de mandar.
Eso hará que el código de movimiento se ejecute justo después de caer y así se te actualice el sprite correctamente.

Saludos
29
Hola Clamud

El problema es que he usado objetos para iterar en vez de Data Structures o Arrays... no supe cómo plantearlo y me pareció que con objetos podía manipular más fácilmente las variables. No voy a pegar el código completo porque son muchas líneas de lógica, pero explicaré cómo funciona en términos generales:

El código es "sencillo", tengo un objeto creador de la iteración que es el IA que tiene un array para los recursos que dispone y otro para el nivel en el que tiene cada edificio.
[gml]recursos[recurso.madera] = 100 //Ejemplo, eso siginifica que tiene 100 de madera
recursos[recurso.ladrillo] = 80 //Tiene 80 de ladrillos, etc
edificios[edificio.ayuntamiento] = 3 //Tiene el Ayuntamiento a nivel 3
edificios[edificio.cuartel] = 1 //Tiene el Cuartel a nivel 1, etc[/gml]
Uso "enum" para definir el número asociado al index de cada array y no confundirme con los números.

Al inicio del juego, en un objeto control, cree una DS_GRID para almacenar los costes de construcción y los enfriamientos. El ID de la DS GRID la guardé en una variable global, así cualquier objeto del juego puede acceder a los costos de fabricación y Lead Times.
Luego el código recursivo es en realidad un objeto que se crea a sí mismo n veces (o eso es en la teoría, porque en la práctica sólo se crearon 32 instancias)
El objeto IA que crea el nodo:
[gml]var inst = instance_create(0,0,obj_IA_nodo)
with inst {
creator = other
event_perform(ev_other,ev_user0)
}[/gml]
En el CREATE EVENT del nodo, se genera un array vacío que indica qué decidión ya tomó ese nodo. Un ejemplo rápido:
[gml]subir[2] = 0 //aún NO decide subir el edificio 2
subir[edificio.cuartel] = 0//aún NO decide subir el cuartel
subir[edificio.ayuntamiento] = 0//aún NO decide subir el ayuntamiento[/gml]

En el evento EVENT USER 0 es como un "Post-Create" event falso, el nodo replica las variables de niveles, recursos y tiempo demorado que tiene su creador, suma recursos según la producción (calculada con la misma variable de tiempo), además revisa cuáles decisiones son IMPOSIBLES de tomar (ej: que para subir un edificio tenga como requisito tener construido otro edificio o que el edificio ya esté en el máximo nivel).
Ejemplo:
[gml]tiempo = creator.tiempo //Se trae el tiempo que ha tardado la decisión del nodo anterior para sumarle el tiempo que tomará mi decisión.
subir[edificio.cuartel] = 1 //Por alguna razón este nodo NO puede subir el edificio 1 (Cuartel), los que quedan con valor en "0" sí se pueden seguir subiendo.[/gml]

Luego, en ese mismo ev_user0, toma "n" decisiones por cada variable del array "subir" que aún esté en cero. Si subir[edificio.ayuntamiento] es aún cero, quiere decir que SÍ puedo subir el Ayuntamiento y toma la decisión.
Eso hace la variable "subir[edificio.ayuntamiento] = 1", reduce los recursos según el coste de construcción, considera los Cooldown de construcción en la variable tiempo y crea otro NODO que ahora leerá las variables desde este nodo en vez del IA.

Y ahí es donde ocurre la recursividad, cada nodo crea nuevos nodos cuando aún pueden tomar decisiones y se eliminan a sí mismos cuando ya no quedan más decisiones que tomar, en ese punto se genera un output diciéndole al IA el tiempo que tardará en seguir esa alternativa.
Cuando un nodo se elimina, en el destroy event hace que su nodo creador cargue de nuevo el ev_user0 y traiga de nuevo los recursos y tiempos que tenía antes de tomar la decisión. La única diferencia es que ya no corre el CREATE EVENT, entonces la decisión "subir[edificio.ayuntamiento]" sigue en uno porque está tomada y ahora ese mismo nodo tomará una segunda decisión, ejemplo: "subir[edificio.cuartel]".

La idea original es comparar todos los output para ver cuál alternativa le conviene más al IA y elegir al azar dentro de las mejores alternativas.

En realidad es una locura lo que intento hacer porque con varios edificios para construir, las alternativas posibles se disparaban exponencialmente, lo calculé con estadística y necesitaba hacer como 28mil iteraciones y Game Maker sólo me deja hacer 32 hasta que se cuelga.

De momento el IA se mueve de forma aleatoria, pero es muy noob... es poco eficiente y cuando el juego progresa, el IA se va quedando muy por detrás... se notan mucho las malas decisiones.

Saludos
30
Hola FernandoNavarro

Al ángulo súmale 180 grados y ya inviertes la dirección.

En radianos usando la función "cos" sería multiplicar por la constante "pi".
[gml]X = Xo + cos(angulo+pi) * radio[/gml]

A partir de GMS, se creó la función "dcos" para colocar los ángulos en grados.
[gml]X = Xo + dcos(angulo+180) * radio[/gml]

Saludos