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

31
Hola WMKILLER

Tu cuadro de texto no dibuja nada porque el evento que trae la "Keyboard String" se ejecuta cuando haces clic con el "mouse_check_button".

En resumen:
Si lo haces al revés: primero escribes algo y luego haces clic en el cuadro de texto, ahí si se te actualiza la variable "global.nombre" y podrás dibujarla en tu Draw Event.

Saludos
32
Hola masalaja

Se me ocurre que tu problema puede estar causado por cualquiera de estas dos situaciones:

1- Si la imagen se queda quieta y no avanza, puede ser que hayas usado esta función en alguna parte para detener la animación:
[gml]image_speed = 0[/gml]
Identificala y eliminala. O si la necesitas, asignale valor 1 cada vez que cambies a un nuevo sprite para re-activar la animación.

2- Si ese no era el caso, lo que veo más probable es que hayas puesto mal el "Draw Event".
Revisa que en el "Draw Event" estés dibujando correctamente el sprite actual con:
[gml]draw_sprite(sprite_index,image_index,x,y)[/gml]
Si has usado "0" en vez de "image_index", eso causaría que se está dibujando el sprite actual, pero sólo el frame 0, sin dibujar al resto de la animación.
Nota: Si no tienes "Draw Event", por defecto Game Maker automáticamente te dibuja el sprite actual y el frame actual de la animación que tiene asignado tu objeto.

Saludos
33
Preguntas y respuestas / Problema con recursividad
Marzo 25, 2020, 06:34:38 AM
Estimados

Tengo un problema místico con un juego de estrategia de construcción. Quizás el problema parezca simple, pero no me funciona el código.
Estoy realizando un código de recursividad que correrá en mi IA al inicio del juego.

La idea es simple:
El robot puede gastar sus recursos para construir edificios, y si se queda sin recursos, tendrá que esperar para seguir construyendo.

No quiero que los bots suban los edificios al azar, quiero que cada bot tenga una personalidad diferente que le haga llevar ciertos edificios diferentes a cierto nivel y le de "señales" al player de la estrategia que está tomando para que el player pueda arruinar su estrategia o perecer en el intento.

La idea es que el robot calcule cuál es el orden en el que debe subir sus edificios para reducir al máximo el tiempo de construcción. Algunos edificios aumentan la producción en un monto fijo, otros la aumentan la producción de forma porcentual y otros reducen el tiempo de creación de los edificios.

Para programar la estrategia del robot, usé un sistema de "nodos" o "ramas" de decisión. El robot toma todas las decisiones posibles al mismo tiempo en todos los órdenes de construcción posibles y luego compara el tiempo que se demoró en subir TODOS los edificios por los diferentes caminos y elije el menor.

Al menos esa es la teoría, porque en la práctica Game Maker me arroja un error en la iteración número 32 diciendo que no puedo usar un sistema recursivo.
Este es el error que aparece:
PerformEvent recursion depth failure - check for infinite loops, check objects for parenting


Alguien tiene alguna idea de cómo resolver este problema?
34
Que bien que te haya funcionado. Éxito solucionando el resto de problemas.

Saludos
35
Hola DarkKRuleR

No entiendo bien lo que quisiste hacer, pero que bueno que lo hayas resuelto.
Lo que se me ocurriría a mí, es dibujar la corbata después de aplicar las transformaciones en el Stickman para que no le afecten sus rotaciones e inclinaciones y luego inclinar la corbata con el mismo ángulo que tiene la proyección de la cámara, eso haría que la corbata siempre se dibuje de espalda a la cámara. (si es un gráfico 2D, supongo que es lo mismo dibujarlo de cara o de espalda)

Saludos
36
Hola Zhekken

El error que ves: "Unexpected symbol in expression" es en realidad un bug de Game Maker. Cuando se usa la palabra "var" y se termina la línea en una función o script (como el instance_create) Game Maker no cierra la línea y arroja ese bug.

Para corregirlo, a la fila anterior, cierra la línea manualmente con un signo punto y coma " ; " y se arregla:
[gml]var inst = instance_create(x,y,obj_bala); //Con el signo al final ya funciona bien[/gml]

El problema fue que cree el código sin probarlo en mi GM antes y me olvidé de ese bug.

Citary ahora eso me confundió porque no se exactamente que quisiste colocar ahí.
Lo que hice fue crear una variable local en el evento alarma llamada "inst". Esa variable local existe sólo en el evento que se llama y luego se borra, eso quiere decir que la puedes editar y leer sólo durante la ejecución de ese evento alarm. Si la intentas leer en el evento STEP, te dirá que la variable ya no existe.
Hacer que la torre cree una bala, luego guarda el ID único que la bala que acaba de crear en la variable "inst" para poder manipular las variables de sólo esa nueva bala sin afectar a las balas que ya existen.

Luego la expresión:
[gml]inst.enemigo = enemigo[/gml]
El problema fue que a la bala y a la torre les cree la misma variable "enemigo", por eso es un poco confuso, pero significan cosas diferentes.
La variable "enemigo" de la bala es el Instance ID del enemigo que tengo que perseguir hasta la muerte.
La variable "enemigo" de la torre es el Instance ID del objeto enemigo más cercano a la torre.

Entonces le estoy diciendo a la bala que acabo de crear, que persiga a muerte al enemigo que actualmente está más cercano a la torre.
Es como hacer:
obj_bala.x = 12, pero si hiciera eso, se cambiaría la variable de todos los "obj_bala" del juego y eso no es lo que se quiere.

Saludos
37
Hola T789

Crea un objeto maestro, ejemplo "obj_master_enemy".
Y a todos los objetos enemigo, le asignas ese objeto como padre en la opción "parent" que da el editor de objetos de Game Maker.

Así en el código usas:
[gml]if place_meeting(x,y,obj_master_enemy) {}[/gml]
y eso detectará la colisión también en todos los hijos que ese objeto tenga.

Saludos.
38
Hola Zhekken

La manera en la que funcionan las alarmas, es que Game Maker gestiona una variable como cualquier otra (como X, sprite_index, vspeed, etc), pero que se llama alarm[0].
A esa variable le asignamos un valor para que se active, ej: "alarm[0] = 2". Entonces Game Maker automáticamente al final de cada STEP, le quitará uno al contador (y tendrá valor 1) y cuando llega a cero, se activa el evento "Alarm0".
[gml]if distance_to_object(obj_enemigo) < rango_vision {
    alarm[0] = 2
    }[/gml]
El problema de tu código, es que mientras el enemigo se encuentra en rango, recargas el contador de la alarma a 2, entonces nunca dejas que baje a cero.
La alarma baja de 2 a 1, pero como el enemigo sigue en rango, la alarma se recarga y vuelve a quedar en 2 Steps y nunca se activa sino hasta que el enemigo sale del rango y ahí recién la alarma se puede activar.

Se debe añadir una condición para detectar si la alarma no está contando. Ejemplo:
[gml]&& alarm[0] = -1 { hace algo }[/gml]

El otro problema que veo, es que cuando usas el código:
[gml]move_towards_point(obj_enemigo.x,obj_enemigo.y,5)[/gml]
Le estás diciendo a la bala que se mueva hacia el enemigo, pero no le estás diciendo hacia cuál enemigo.


Solución propuesta:
Mi consejo es que en vez de hacer que la bala siga a un enemigo en específico, siga las coordenadas de ese enemigo.
Así cuando el enemigo muera, las balas que ya fueron creadas e iban en camino, seguirán su trayectoria hacia el cadaver.

Para ello te sugiero dejar lo siguiente
Create Event de la torre:
[gml]enemigo = noone //El ID único del objeto más cercano al que quiero que mi bala ataque[/gml]

Create Event de la bala:
[gml]enemigo = noone //Es el enemigo del que tomará las coordenadas la bala. Use el mismo nombre de variable anterior, pero significan cosas diferentes, no las vayas a confundir.
enemigo_x = 0 //Las coordenadas a las que irá mi bala.
enemigo_y = 0
velocidad = 12 //La cantidad de pixeles que avanzará la bala por cada STEP (ponle el valor que gustes, yo usé 12 como ejemplo)[/gml]

Primero la programación de la torre:

Step Event de la torre:
[gml]if alarm[0] = -1 && instance_exists(obj_enemigo) { //Revisa el cooldown de la torreta para ver si NO está disparando actualmente.
var inst = instance_nearest(x, y, obj_enemigo) //Esto trae el ID del enemigo más cercano
if distance_to_object(inst) < rango_vision { //Revisa si el enemigo más cercano está a rango de la torreta
    alarm[0] = 2 //Dispara y pone un cooldown de 2 STEPS en la torreta para que no dispare de nuevo
enemigo = inst //Esto guarda el ID del enemigo más cercano en la variable "enemigo". La necesitará la BALA después para perseguirlo
    }
}[/gml]

Alarm0 de la torre:
[gml]if instance_exists(enemigo) { //Primero revisa que el enemigo no haya muerto durante estos 2 Steps de Cooldown. Si el enemigo murió, entonces no dispara nada.
var inst = instance_create(x,y,obj_bala) //Después de los 2 Steps, crea la bala y guarda el ID de la nueva bala creada en la variable "inst".
inst.enemigo = enemigo //Le dice a la bala a qué enemigo debo perseguir. La variable "enemigo" del objeto "inst" (o sea la bala), toma ahora el valor de la variable "enemigo" de la torre.
inst.enemigo_x = enemigo.x //Le dice a la bala a qué coordenada debe ir
inst.enemigo_y = enemigo.y //Le dice a la bala a qué coordenada debe ir
}[/gml]

Step de la Bala
[gml]if instance_exists(obj_enemigo) { //Si aún existe el enemigo, recarga las coordenadas a las que me debo dirigir.
enemigo_x = enemigo.x
enemigo_y = enemigo.y
}
//Ahora me muevo
if point_distance(x,y,enemigo_x,enemigo_y) <= velocidad { //Si la velocidad de la bala es menor a la distancia que tiene contra el enemigo, teletransporta la bala hacia el enemigo.
x = enemigo_x;
y = enemigo_y
if instance_exists(enemigo) enemigo.vida -= 4 //Un ejemplo de cómo quitarle vida al enemigo, esto reduce en 4 puntos el valor de la variable "Vida" del objeto enemigo que recibió la bala.
instance_destroy() //Destruye la bala porque ya llegó a su objetivo
}
else {
x += lengthdir_x(velocidad,point_direction(x,y,enemigo_x,enemigo_y)) //Esto hace que la bala avance hacia las últimas coordenadas registradas por el enemigo
y += lengthdir_y(velocidad,point_direction(x,y,enemigo_x,enemigo_y))
}[/gml]

Saludos
39
Hola HiperGlue

Mi consejo es que en vez de usar una alarma, cada botón tenga una velocidad y una "coordenada objetivo" a la que debe llegar.
ejemplo:
En el Create Event:
[gml]y = 0 //Esta línea es irrelevante y se puede borrar porque al crear el objeto ya asignas su Y, pero es para que entiendas la idea de lo que hace el código.
y_objetivo = 300 //La coordenada final a la que debe bajar el botón.
velocidad = 10 //La cantidad de pixeles que sumará en cada STEP[/gml]

En el Step lo mueves:
[gml]if y != y_objetivo {
y = min(y+velocidad, y_objetivo)
}[/gml]
La función "MIN" es para evitar que la coordenada se pase, cuando la coordenada objetivo NO es múltiplo de la velocidad

Nota: Si los 3 botones son el mismo objeto, debes crearles variables diferente, sino los 3 botones bajarán "para abajo" hasta el mismo "y_objetivo", eso lo puedes hacer de varias maneras, ya sea creandolos desde otro objeto y pasandoles variables de creación o editando el "Creation Code" en el editor de rooms de Game Maker, dandole clic secundario a la instancia.

Saludos
40
Hola Dager

En el "Step End Event" del Objeto cuchillo.
[gml]x = obj_player.x
y = obj_player.y + 20[/gml]
Ese código hará que el objeto "cuchillo" se mueva a la posición de mi objeto "obj_player", pero 20 pixeles hacia abajo (tú ponle como hayas llamado a tu objeto y en la coordenada respectiva según el tamaño de tus sprites y los puntos de origenes)

Si dices que la animación de ataque con el cuchillo tiene 3 sprites, al crearlo debes hacer que la animación no se ejecute hasta que sueltas la tecla "K".
En el "Create Event" del Objeto cuchillo:
[gml]image_speed = 0 //Esto evita que la animación se dibuje[/gml]

Hace que el ataque se ejecute al soltar la tecla.
En el "Step Event" normal del Objeto cuchillo, coloca:
[gml]if keyboard_check_release(ord("K")) {
image_speed = 1 //Esto reactiva la animación. Si la animación va muy rápido, en vez de 1, ponle una velocidad más lenta, ej: 0.25, eso hará que la animación avance 1 sub-imagen cada 4 steps.
}[/gml]

En el evento "End Animation" del Objeto cuchillo (que está en other), ponle que haga daño a los enemigos y una alarma que desaparezca la mano con cierto delay.
ejemplo:
[gml]if image_speed != 0 { //Esta condición hace que el ciclo de animación no se repita y el tiempo de la Alarma se ejecute sólo 1 vez.
image_speed = 0 //Cuando termina la animación, esta línea frena nuevamente la animación hasta que la mano desaparece
alarm[0] = 6 //Esto activa una alarma en 6 Steps para poder eliminar la mano.
}[/gml]

en "Alarm[0]" del Objeto cuchillo, después de que pasan esos 6 Steps:
[gml]instance_destroy() //Elimina la mano con el cuchillo cuando se activa la alarma 0[/gml]

Está de más decir que el player NO puede crear otro cuchillo hasta que el primero desaparezca, añade una condición para revisar si el objeto ya existe antes de crearlo
En el Step Event del Personaje
[gml]if keyboard_check_pressed(ord("K")) && !instance_exists(obj_cuchillo) { instance_create(x,y,obj_cuchillo) }[/gml]

Saludos
41
Hola T789

[gml]randomx = random_range(192,room_height-8);[/gml]
Primero: sí sabes que "room_height" es el alto de la room?? para el ancho puedes usar: "room_width".

Lo que se me ocurre para resolver tu problema, es que la instancia creada corra un código de colisión y se desplace hacia el lado en caso de haber detectado colisión.
Ejemplo:
[gml]var inst = instance_create(randomx,-100,obj_enemy1)
with inst {
if place_meeting(x,y,obj_enemy1) { //Nota: Si "obj_enemy" es una variable en vez de un objeto, deberás llamarla con: "ohter.obj_enemy", si es objeto, déjalo tal cual.
var offset = 1,free = false;
while (free = false) {
if !place_meeting(x+offset,y,obj_enemy1) { x = x+offset; free = true } //Revisa "n" pixeles a la derecha
else if !place_meeting(x-offset,y,obj_enemy1) { x = x-offset; free = true } //Revisa "n" pixeles a la izquierda
offset += 1
}
}
}[/gml]

Lo que hace ese código, es que al momento de que crees el objeto (almacenado en la variable local "inst"), ese objeto "inst" creado revisará si colisiona con otro (justo donde fue creado).
En caso de colisionar, hace una Iteración infinita para buscar un espacio vacío a 1 pixel a la derecha o 1 pixel a la izquierda (usé la variable local "offset" para medir la distancia).
Si no encuentra espacios libres, entonces repite la iteración pero ahora buscando un espacio libre a 2 pixeles a la derecha o a 2 pixeles a la izquierda. etc.
La iteración se detiene cuando el objeto encuentra un espacio vacío (cuando la variable local "free" se hace "true").

Advertencia: No he testeado el código antes, espero que no tengas problemas porque al hacer mal un "while", se te congelará el juego jejeje.

Saludos
42
Hola KayasamiX

Eso se logra con una Shader.

Puedes usar este video como guía donde generan un efecto similar con algunas variaciones:
https://www.youtube.com/watch?v=pTHBVH5z0mQ

Saludos
43
Hola RyZeX

Puede ser que hayas equivocado escribiendo los "else". Si no veo el código será difícil de resolver.

Saludos
44
Preguntas y respuestas / Re:CREAR ACELERACION
Marzo 01, 2020, 10:24:21 PM
Hola nonoroman

El problema es que el "while" repite ese mismo código infinitas veces en el mismo step hasta que la condición se deje de cumplir, por eso ves que se mueve de golpe.
Reemplaza el "while" por un "if" y se debería solucionar.

Saludos
45
Hola Taki-A

Subí un rar file a mi Google Drive con el proyecto escrito en GMS 1.4

Descárgalo, extraelo, abre tu Game Maker e importalo desde "File > Import".
https://drive.google.com/u/0/uc?id=1Fu-3FKyRnZSuTjMQmPpXbX78asO8TZ8G&export=download

Cree un GIF con un ejemplo de lo que el código hace.
Cuando la bala se crea por primera vez, no hace nada, el código simplemente la genera y hace que se mueva en una cierta dirección.
Cuando la bala colisiona con un enemigo. Primero revisa si ya ha tocado antes a ese enemigo (si lo ha tocado, lo ignora)
Si no lo ha tocado, entonces le causa daño y busca al siguiente enemigo de entre todos los enemigos disponibles que aún no toca, y cambia de dirección hacia el más cercano.
Si ya no quedan más enemgios disponibles, entonces el código no se ejecuta y la bala sigue su curso hacia el infinito.

Cada bala es independiente y hace los checks por sí sola, sin importar cuantas balas hay en la room

Usé 2 objetos enemigo diferente (pintados de colores diferentes) y el check se hace contra un objeto parent y funciona perfecto, a menos que haya entendido mal tu duda y eso no es lo que quieres lograr.

GIF: https://drive.google.com/open?id=1zPr2FCOPcBRgeZbbr4MnO0d4oPEAfh9b

Saludos