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

151
Preguntas y respuestas / Re:Buffer <-> String
Septiembre 20, 2018, 04:16:44 PM
Hola Edgamer63

Sí se puede, pero no es necesario porque el buffer ya tiene una estructura de array. Solamente debes leer el dato correcto en el mismo orden que lo guardaste.
Ej: si guardaste:
buffer_write(buffer,buffer_u8,10) //El num 10 como u8
buffer_write(buffer,buffer_string,player_name) //El nombre como string
buffer_write(buffer,buffer_u16,2000) //El num 2000 como u16


Debes leerlos en el mismo orden:
buffer_seek(buff, buffer_seek_start, 0) //Regresa la posición de lectura/escritura del buffer al inicio.
array[0] = buffer_read(buffer,buffer_u8) //Lee el 10
array[1] = buffer_read(buffer,buffer_string) //Lee el nombre del player
array[2] = buffer_read(buffer,buffer_u16) //Lee el 2000


O en vez de guardar la info en un array, lo puedes asignar directamente a la variable correspondiente.

Saludos
152
Preguntas y respuestas / Re:Buffer <-> String
Septiembre 20, 2018, 03:02:54 PM
Hola Edgamer63

No es necesario convertir un buffer en string.
Si quieres leer una string que has guardado en un buffer, puedes usar:
var value = buffer_read(buffer_id,buffer_string)
Esa función leerá la string que sigue de la posición de lectura.
Favor notar que los buffers van guardando la información como Stacks, tienes que elegir que byte quieres leer usando buffer_seek para leer la información correcta en la posición correcta.

Si quieres enviar el buffer a través del Networking, es enviarlo y ya con network_send_raw o network_send_packet.

Si quieres guardar el buffer en un archivo, es usar buffer_save y listo.

Si quieres "Literalmente" convertir el buffer completo en string, puedes usar buffer_base64_encode, pero la string es no legible hasta que lo conviertas a buffer de nuevo.

Los buffers ocupan el cache, recuerda eliminarlos cuando no sean necesarios con buffer_delete

Saludos
153
Hola cristopher2545

Podrías intentar usar las ecuaciones físicas de movimiento en dos ejes.
Eje x:
X = X inicial + V inicial * coseno(angulo) * tiempo
Eje y:
Y = Y inicial + V inicial * seno(angulo) * tiempo - (g/2) * (tiempo^2)

"X" e "Y" son las coordenadas del player, "X inicial" e "Y inicial" son las coordenadas del cañón (o de la bala cuando se crea)
"V inicial" es la velocidad con la que sale disparada la bala del cañón.
"angulo" es la inclinación del cañón (que es también la dirección en la que sale disparada la bala)
"tiempo" es el tiempo que tarda la bala en llegar a su objetivo.

1- En esta ecuación, la mayoría de valores son constantes y conocidos, salvo dos variables, que son ángulo del cañon y velocidad de la bala, ambas variables pueden variar de manera infinita entre ellas y en TODOS esos casos pueden generar infinitas combinaciones posible donde alcanzan al player, así que debes hacer una de las dos constantes (ej, el ángulo del cañón) para que la ecuación funcione.

2- Como el tiempo en que la bala alcanza al player en el EJE X es el mismo tiempo que tarda la bala en alcanzar al player en el EJE Y, podemos combinar el tiempo como un tiempo único y olvidarnos de esa variable.

3- Después de mucha matemática, la fórmula se reduce a esto en game maker:

En el Evento Step
var rango_max = 240
var rango_min = 16
if abs(obj_player.x-x) >= rango_min && abs(obj_player.x-x) <= rango_max && alarm[0] = -1 { //Verifica que el player esté en rango para hacer el disparo (entre 16 y 240 pixeles en el eje X)
var shot_angle = 0;
if obj_player.x < x { shot_angle = 135 }
else { shot_angle = 45 }

var bala = instance_create(x,y,obj_bala)
with bala {
gravity = 0.4 //Setea la gravedad de la bala
direction = other.shot_angle //La dirección de la bala es el ángulo del cañón
speed = sqrt((sqr(obj_player.x-x)) / ((2/-gravity)*((y-obj_player.y)-dtan(direction)*(obj_player.x-x))*sqr(dcos(direction)))) //Esta es la ecuación resultante de combinar las dos ecuaciones de arriba
}
alarm[0] = 2*room_speed //Le da un cooldown de 2 segundos para efectuar el siguiente disparo
}


En el Evento ALARM0
//Sólo pon un comentario para que se active el contador y se pueda usar como delay o cooldown entre disparos

Eso calcula la velocidad que debe tomar la bala para que pueda golpear al player. Mi recomendación es que en vez de usar las físicas de la realidad, uses tu propio código de movimiento aunque sea algo irreal, ej: que la bala se deslice de forma horizontal hasta que está cerca del player y recién ahí tome gravedad.
Ese movimiento no está apegado a la realidad, pero dará un mejor efecto in-game.

Algunos juegos utilizan mecánicas falsas que hacen que el juego se sienta mejor a la vista o en jugabilidad. En Fifa por ejemplo, el caminar y disparo al arco de los jugadores es más exagerado que lo que pasa en la vida real para dar una mejor sensación al jugador, así puedes controlar mejor al personaje. En GTA, cuando dos autos colisionan, rebotan con un efecto de partículas que muestra la destrucción. En la vida real en cambio, quedarían prácticamente unidos los autos al chocar rápido, pero si se hiciera así el GTA, no podrías ni manejar.

Saludos
154
Preguntas y respuestas / Re:Duda con los Stast y niveles
Septiembre 20, 2018, 04:17:34 AM
Hola HKaichim

Yo te sugiero utilizar DS GRID, aunque puedes utilizar cualquier otro tipo de DS o incluso arrays o variables como sean de tu agrado.
No sé si eres un experto en Game Maker o recién estás empezando, así que empezaré explicando cómo funcionan las DS Grid.
Una DS GRID es como una hoja de excel, puedes almacenar información en forma de tabla. Esta "tabla" se guarda en el caché de Game Maker y puedes acceder mediante el ID que te entrega Game Maker cada vez que creas una tabla.
En teoría las DS GRIDs son "globales", cualquier objeto en cualquier room puede acceder a la información mientras la DS GRID exista en la memoria, el problema es la variable con la que accedes, si pierdes esa variable (destruyendo el objeto que la tenía o cambiando de room por ejemplo), la información sigue existiendo pero ya no podrás acceder a ella.

Las funciones principales son:
ds_grid_create(columnas,filas): Esta función crea la grid y retorna su ID, así que debes guardarla en una variable
ds_grid_set(grid,x,y,valor): Esta función te permite asignarle valores a una celda de la GRID.
ds_grid_get(grid,x,y): Esta función lee el valor que tiene una celda.

Como ejemplo, voy a crear una DS GRID de 4x2 para almacenar 4 stats: HP, nombre, ataque, defensa. para dos personajes.
globalvar stats; //Crea una variable global llamada "stats"
stats = ds_grid_create(4,2) //Crea la grid y guarda su ID en la variable global
//Crea los stats del primer personaje
ds_grid_set(stats,0,0,100) //hp personaje1
ds_grid_set(stats,1,0,"HKaichim") //nombre
ds_grid_set(stats,2,0,25) //ataque
ds_grid_set(stats,3,0,15) //defensa

ds_grid_set(stats,0,1,90) //hp personaje 2
ds_grid_set(stats,1,1,"BssString") //nombre
ds_grid_set(stats,2,1,15) //ataque
ds_grid_set(stats,3,1,30) //defensa


Eso creará la siguiente información:




filaHPnombreataquedefensa
0100"HKaichim"2515
190"BssString"1530

Game Maker Studio implementó los "accessors" que es una manera rápida de acceder a la información almacenada en Arrays, Lists, entre otros. Para el caso de las grids, su accessor es el signo "#", puedes usar la siguiente notación, tanto para leer info, como para escribir info:
CitarID_DE_LA_GRID[# x,y] <- notación de las GRIDS
Ejemplos:
my_hp = stats[# 0,0] <- Lee la grid "stats", el dato de la celda x=0;y=0
stats[# 0,0] = 120 <- Ahora a esa celda le asigna valor 120

Finalmente las GRIDs entregan la posibilidad de convertir la información de grid a string y de string a grid con sus funciones "ds_grid_write" y "ds_grid_read".
string = ds_grid_write(stats) //Esta función convierte la grid "STATS" en una cadena de texto NO LEGIBLE para el ser humano y lo almacena en la variable "string".
Esa cadena de texto generada puede ser almacenada en un archivo de forma local e incluso enviada vía Networking hacia otro juego conectado.

Ejemplo de guardado
ini_open("data.ini") //Abre (o crea) el archivo "data.ini"
ini_write_string("save","save1",string) //Busca (o crea) la sección "save" y la llave "save1" para guardar la string que creamos antes
ini_close() //Cierra el archivo


Para cargar la partida y leer nuevamente tus variables.
stats = ds_grid_create(4,2) //Crea una nueva grid (debe existir antes de cargar)
ini_open("data.ini") //Lee el archivo donde guardamos la info
var string = ini_read_string("save","save1","") //Lee la información guardada (lee "" si no había nada) y lo guarda en la variable string
ds_grid_read(stats,string) //A la grid que acabamos de crear, le carga la info de la variable "string"
ini_close() //Cierra el archivo

Y listo, tu grid ya tiene cargada de nuevo la información que tenía antes, cuando guardamos el archivo.

Debes recordar que las ds_grid deben ser eliminadas del cache cuando ya no sean necesarias, ejemplo, al finalizar la ejecución del juego o cuando vuelves al menú principal para evitar que en muchos reinicios, el juego se quede sin memoria disponible.
La función es:
ds_grid_destroy(grid_id)

Espero que haya quedado bien explicado

Saludos
155
Preguntas y respuestas / Re:Duda con los Stast y niveles
Septiembre 20, 2018, 02:58:10 AM
Hola HKaichim

Si estás declarando las variables como globales, entonces ya estás conservándolos por el resto del juego, cualquier objeto en cualquier room podrá acceder a esa información y modificarla, así que puedes leer el mismo stat tanto dentro como fuera de combate.

Para crear stats pienso que una mejor alternativa es utilizar Arrays (que también se pueden crear de forma global).
Un array puede contener datos de texto como numéricos.
ejemplo:
globalvar stats;
stats[0] = "HKaichim" //El nombre del personaje
stats[1] = 100 //El hp
stats[2] = 15 //El ataque
stats[3] = 10 //La defensa
stats[4] = "rayo magico" //alguna habilidad que posea el personaje
stats[5] = "nada" //Una segunda habilidad (en este caso no la ha aprendido xD)

etc.

Puedes crear un array de 2 dimensiones para crear (en la misma variable) los stats de todos tus personajes.
Si pretendes guardar tus stats en algún archivo del dispositivo para que estén disponibles cuando el jugador inicie nuevamente el juego (lo que ocurre típicamente en los RPG, que no son juegos que te acabas en un día), entonces lo más fácil es utilizar DS LIST o DS GRID por sus funciones "write" y "read" con las que fácilmente puedes convertirlas a texto, guardarlas y leerlas.

Saludos
156
Preguntas y respuestas / Re:rotar sprite al jugador
Septiembre 18, 2018, 09:00:13 PM
Hola Sr.Mojon

Con el mismo código anterior. Sólo cambia el "image_angle" que estás leyendo del objeto nuevo por tu variable de ángulo que estés usando
Esta línea:
image_angle = other.image_angle
Déjala como:
image_angle = other.tu_variable_de_angulo_aqui

Saludos
157
Preguntas y respuestas / Re:rotar sprite al jugador
Septiembre 18, 2018, 06:42:38 PM
hola Sr.Mojon

Eso te pasa entonces porque no estás usando la image_angle de Game Maker y estás dibujando a tu sprite con tu propia variable de giro. Para corregir el error llama a tu variable cuando crees el cadaver

Saludos
158
Hola Kiwi Chan

Para escribir un texto, puedes usar la función "Draw_text" en el evento "Draw Event".

Puedes concatenar texto usando el "signo más", pero si tu variable contiene un número, el programa erroneamente puede detectar el signo más como una suma y arrojar error. Para evitar el error, debes convertir el número a cadena de texto usando la función "string".

Intenta escribiendo un código similar a este en el Draw Event.
draw_text(10, 15, "Vidas = "+string(Vidas))
Eso escribirá el texto "Vidas =" y luego escribirá el número de vidas que tengas (como texto).
Resultado final:
CitarVidas = 3

Saludos
159
Preguntas y respuestas / Re:rotar sprite al jugador
Septiembre 18, 2018, 03:44:35 AM
Hola Sr.Mojon

Algo parecido a eso, en realidad pusiste el código fuera de la condición, así que se te va a ejecutar siempre.

if (vidas_enemigo<1) {
instance_create(x,y,obj_sangre)
var cadaver = instance_create(x,y,obj_sangre) //Crea el objeto "obj_cadaver" y guarda su ID en la variable local "cadaver"
with (cadaver) {
image_angle = other.image_angle //La nueva image_angle del objeto "cadaver" va a ser la image_angle del objeto que llama el código
}
}


Recuerda usar "instance_destroy" también para destruir al objeto original, sino estarás creando infinitos cadáveres una vez por cada step.

Saludos
160
Preguntas y respuestas / Re:rotar sprite al jugador
Septiembre 18, 2018, 03:28:58 AM
Hola Sr.Mojon.

Cuando usas la función "instance_create" (o las nuevas del GMS2), estas te devuelven el ID del objeto que acaban de crear.
Si creas el objeto cadaver desde el objeto original, puedes tomar ese ID que se acaba de crear y asignarle la variable "image_angle" según la "image_angle" que tenía el objeto original con la función "with".

Ejemplo de lo que acabo de decir sería algo así:
var cadaver = instance_create(x,y,obj_cadaver) //Crea el objeto "obj_cadaver" y guarda su ID en la variable local "cadaver"
with (cadaver) {
image_angle = other.image_angle //La nueva image_angle del objeto "cadaver" va a ser la image_angle del objeto que llama el código
}


Saludos
161
Hola FridaFlowers

No entiendo mucho el sistema de D&D que tiene GMS2. Pero lo que veo ahí es que tus variables tienen distinto nombre.
hue_rnd
hue_rand

Saludos
162
Hola HKaichim

No funcionó porque mi código tenía fallas, sorry.
Usé "if (distancia = -1)" en vez de "if (other.id_seguir = noone)".
Además declaré la varible dirección con 3 "c".

Prueba con esta versión corregida del código, ahora sí lo he testeado y por lo menos a mi me ha funcionado xD:
//Código1 - El obj2 elige al obj1 más cercano para comenzar a seguirlo
id_seguir = noone //Declaramos una variable de instance (debes llamar el Id del objeto para leerla)
var distancia = -1 //Declaramos una variable local (Existe en el código y cualquier objeto la puede leer, es casi como una variable global, pero se destruye al terminar de ejecutar este código)
with (obj2) if (my_id = 0 || my_id = 1) {
if (other.id_seguir = noone) { other.id_seguir = id; distancia = point_distance(other.x,other.y,x,y) }
else {
var new_distancia = point_distance(other.x,other.y,x,y)
if new_distancia < distancia { other.id_seguir = id; }
}
}

//Código2 - El obj2 se desplaza hacia el objetivo que quiere seguir
if id_seguir != noone {
var velocidad = 1
if point_distance(x,y,id_seguir.x,id_seguir.y) > velocidad {
var direccion = point_direction(x,y,id_seguir.x,id_seguir.y);
x += lengthdir_x(velocidad,direccion)
y += lengthdir_y(velocidad,direccion)
}
}


Si lo pones en el STEP EVENT del obj1, lo que hace es que el obj1 va a buscar al obj2 más cercano (cuyo my_id del obj2 sea "0" o "1"), entonces el obj1 comienza a moverse en línea recta hacia el obj2.
Si el obj2 tiene "my_id" con un valor 2 o cualquier otro que no sea los antes mencionados, entonces será ignorado por el obj1.

Saludos
163
hola HKaichim

Cuidado que Game Maker por defecto corre la misma semilla en cada ejecución, para efectos de testeo.
La semilla es lo que usan los computadores para generar números aleatorios (hasta las calculadoras para su función rand).
Usar la misma semilla siempre significa que tus eventos aleatorios siempre tendrán el mismo resultado, en cada ejecución.
Para evitar eso utiliza la función "randomize()" al momento de iniciar tu juego, eso hará que la semilla se cambie por una aleatoria.

Si aún después del randomize no te funciona el Test Chance, puedes probar con la función "choose".
instance_change( choose(obj2,obj3,obj4), true )

Saludos
164
Hola HKaichim

No es posible seguir dos objetos a la vez, con ningún método, tienes que discriminar bajo tus condiciones a qué objeto quieres seguir.

Puedes iterar a través de todos los objetos usando un "with (object_index)" para ver cuál es el más cercano y cuál cumple con tu condición.
Es un poco complicado usar la función with porque el objeto dentro del "with" se convierte ahora en el objeto principal que corre el código, mientras el objeto que originalmente llamó el with, se convierte en "other".

Sabiendo eso, si quieres hacer que el obj2 siga al obj1, puedes hacer lo siguiente en el obj2:
id_seguir = noone //Declaramos una variable de instance (debes llamar el Id del objeto para leerla)
var distancia = -1 //Declaramos una variable local (Existe en el código y cualquier objeto la puede leer, es casi como una variable global, pero se destruye al terminar de ejecutar este código)
with (obj1) if (my_id = 0 || my_id = 1) {
if (distancia = -1) { other.id_seguir = id; distancia = point_distance(x,y,other.x,other.y) }
else {
var new_distancia = point_distance(x,y,other.x,other.y)
if new_distancia < distancia { other.id_seguir = id; distancia = point_distance(x,y,other.x,other.y) }
}
}


Al finalizar la ejecución, El obj2 tendrá guardada una variable de instance llamada "id_seguir" que guarda el instance id del obj1 más cercano.
Favor notar que antes de hacer el cálculo, filtra entre los obj1 para incluir sólo los que tengan la variable "my_id = 0" o "my_id = 1" (le puedes poner lo que necesites ahí).

Después puedes crear el código de seguimiento que quieras, incluso con motion planning. Acá te entrego un movimiento lineal sencillo.
if id_seguir != noone {
var velocidad = 8
if point_distance(x,y,id_seguir.x,id_seguir.y) > velocidad {
var direcccion = point_direction(x,y,id_seguir.x,id_seguir.y)
x += lengthdir_x(velocidad,direccion)
y += lengthdir_y(velocidad,direccion)
}

}


No tengo mi GM a mano, así que cree el código a ciegas, si ocurre algún error favor indícalo y revisamos qué pasó y cómo resolverlo.

Saludos
165
Preguntas y respuestas / Re:Colocarle una id a mi objeto
Septiembre 14, 2018, 05:10:12 AM
Hola HKaichim

Si es posible y es bastante útil. En general hay muchas formas de hacerlo. Te comento mis dos favoritas:

Forma manual:
En el editor de rooms de Game Maker, puedes hacer clic secundario y seleccionar "creation code". Ahí te permite crear un bloque de código específico para esa instance en particular. Este "creation code" ocurrirá después de su "Create Event" normal, así que cuidado con el orden en que asignas y revisas las variables, desde el "Create Event" normal no podrás conocer la variable que asignaste en el creation code del objeto hasta que llegas al Step Event.

Forma automática:
Si tienes un objeto único (ejemplo: un objeto control) que se crea antes que los demás objetos de la room, le puedes asignar una variable como por ejemplo "contador = 0".
En el "Create Event" de tus objetos, haces simplemente:
my_id = obj_control.contador
obj_control.contador += 1

Eso hará que cada objeto tome como ID el valor actual de contador y le sume uno para que después venga el objeto que sigue a hacer el checkeo y reciba un id diferente.
Como alternativa, puedes reemplazar la variable en el objeto control por una variable global.
Si vas a "rooms" > "settings" > "instance_order" puedes cambiar el orden en el que se crean los objetos para que tu variable "contador" se declare antes de que hagas el check.

Saludos