Octubre 08, 2014, 11:33:11 PM Ultima modificación: Octubre 16, 2014, 04:15:09 PM por Marth
Tras observar a algunos presentes hacer con game maker cosas de estilo RPG tradicionales o incluso juegos de estrategia militar, me anime a hacer un rudimentario sistema de batalla por turnos, por si algún día hacia lo mismo, pero me ha surgido una complicación.
Verán, aunque ya he realizado el sistema de batalla por turnos con éxito, me encuentro conque, si quiero que esto progrese, necesito utilizar estructuras de datos, en las cuales almacenaría para cada uno de los combatientes parámetros tales como sus puntos de vida y su ataque, pero me encuentro conque no es tan fácil como el struct del lenguaje C en el que creaba un registro g y creaba las variables g.vida y g.ataque. La información del tutorial de game maker es bastante escasa, por lo que me sirve de poco.
¿Alguien sabe como monto un registro de datos en game maker?

Esta es una de las grandes limitaciones del GM: la falta de clases o de estructuras.
Podés hacer dos cosas.

1) Usar objetos como si fueran clases/estructuras. En vez de:
struct Personaje {
    int vida;
    int attack;
};

Creás un objeto y le das las variables vida y ataque en el evento create. Después lo instanciás y le das valor a las variables como a cualquier otro objeto.

2) Usar arrays.
[gml]Personaje[0, 0] = 0;  // Vida del personaje 0.
Personaje[0, 1] = 0;  // Ataque del personaje 0.
Personaje[1, 0] = 0;  // Vida del personaje 1.
Personaje[1, 1] = 0;  // Ataque del personaje 1.
// etc[/gml]

Ninguna de las dos maneras es óptima pero es lo que brinda el GM.
Vim.

#2 Octubre 09, 2014, 09:13:33 PM Ultima modificación: Octubre 09, 2014, 09:25:21 PM por jokin666
Mi recomendacion para hacer lo que quieres es que uses las bases de datos incluidas en Gamemaker. Son muy parecidas a los arrays, pero tienen varios comandos para ordenar, salvar y cargar datos que lo hacen mucho mas util que los arrays.

Si solo tienes un personaje, te recomiendo guardar sus datos en un ds_map, que guarda los datos por parejas y es facil de utilizar

CREAR Y AÑADIR VALORES

global.heroe_stats=ds_map_create();  // Crear base de datos tipo map
global.heroe_stats[?"nombre"]="Clark"; // Creamos una entrada de nombre "nombre" con el valor "Clark"
global.heroe_stats[?"nivel"]=1;           // Creamos una entrada de nombre "nivel" que valdra 1
global.heroe_stats[?"hp"]=25;            // Creamos una entrada de nombre "hp" que valdra 25

COMPROBAR Y MODIFICAR

if global.heroe_stats[?"xp"]>=global.heroe_stats[?"xp max"]{ // si "xp" es igual o mayor que "xp max...
   global.heroe_stats[?"nivel"]+=1; // sumamos 1 a nivel...
   global.heroe_stats[?"xp"]=0; // ponemos la "xp" a 0 ..
   global.heroe_stats[?"xp max"]=global.heroe_stats[?"nivel"]*100 // y damos el valor de "nivel" *100 a "xp max"
}


Como ves no es algo muy complicado si ya estas acostumbrado a usar variables.

Si vas a usar varios heroes, o para el sistema de inventario, equipo, etc...te recomiendo usar la base de datos de tipo "grid", que es practicamente lo mismo que un array. Puede parecer un poco mas confuso que el map, pero no cuesta mucho acostumbrarse.

CREACION

global.inventario=ds_grid_create(5,10) // A diferencia de ds_map, al crear un ds_grid hay que indicar el tamaño en ancho y altura que tendra nuestra rejilla
global.inventario[#0,0]="puñal";                    // Nombre del objeto del inventairo 1
global.inventairo[#1,0]="pequeña arma"         // Descripcion del objeto del inventario 1
global.inventario[#2,0]=2;                          // daño que provoca el objeto del inventario 1
global.inventario[#3,0]=25;                        // precio del objeto del inventario 1
global.inventario[#4,0]="arma"                    // el tipo de objeto que tenemos en el inventario 1
global.inventario[#0,1]="escudo de madera"; // Nombre del objeto del inventario 2
global.inventario[#1,1]="Escudo basico";      // Descripcion del objeto del inventario 2
global.inventario[#2,1]=3                          // Defensa del objeto del inventario 2
global.inventario[#3,1]=30                        // Valor del objeto del inventario 2
global.inventario[#4,1]="escudo";               // Tipo de objeto que tenemos en el inventario 2


Si te has dado cuenta en el detalle, las coordenadas empiezan en 0,0 , por lo que si indicas que quieres 10 de ancho, no sera del 1 al 10, sera del 0 al 9.
Para modificar los datos es parecido al ds_map

// Al usar un item
if global.inventario[#4,seleccion]="pocion"{ // Si es de tipo "pocion"
  global.invnetario[#5,seleccion]-=1;          // restamos 1 a la cantidad de pociones que tenemos
  global.status[?"hp"]+=global.inventario[#2,seleccion] // y recuperamos la potencia que tenga la pocion
}


Puede parecer complicado, pero en cuanto hagas algunas pruebas veras que es mas facil de lo que parece. Y si estas acostumbrado a usar variables y arrays sera mas facil todavia :D

Para los enemigos, yo suelo crear sus estadisticas en su evento create, ya que cada instancia tiene sus propias variables locales, y dichas variables, a diferencia de las del jugador y el equipo, no son necesarias guardarlas permanentemente, por que son fijas.

Espero que te haya servido de ayuda, y recuerda revisar la ayuda de gamemaker, hay muchos comandos mas para usar con ds_map y ds_grid, puede que encuentres alguno mas que te sea util. Como el ds_grid_read/ds_map_read y ds_grid_write/ds_map_write para guardar todos los datos en una string encriptada que despues puedes guardar en un txt o .ini para guardar y cargar partidas :D

#3 Octubre 09, 2014, 11:28:30 PM Ultima modificación: Octubre 16, 2014, 04:16:28 PM por Marth
Gracias, algunas de estas cosas son interesantes, aunque debo explicar una cosa.
Yo lo que hago es que existe una sola instancia, que almacena unos vectores con lo que serían los datos de aliados y enemigos. No existen varios objetos representando a cada combatiente.
Aunque el uso de matrices no es más que una chapuza, ha funcionado. Ha avanzado bastante el sistema de batalla gracias a esto. :D
Y lastima de esa carencia del GM. Quizás podría yoyo games añadir alguna opción en una actualización o futura versión de game maker. ;)

#4 Abril 18, 2015, 10:16:25 PM Ultima modificación: Abril 19, 2015, 01:12:48 AM por Marth
Por cierto, he descubierto un sistema alternativo.
Tendría un objeto llamado "combate" que crearía unos objetos llamados luchadores: w[j]=instance_create(0,0,Luchador)
Luchador tendrá atributos de vida, ataque, defensa, etc. y cuando los quiera no tendría que hacer más que hacer por ejemplo para el ataque: b[z].vida-=w[j].ataque

Ya tengo hecho el juego y ya lo voy a hacer con el chapucero sistema, pero este sistema utilizando los objetos era lo que había estado buscando desde el inicio. :o