Noticias

Se ha publicado un nuevo servicio, el Portal de Juegos Online

Comunidad Game Maker

Bienvenid@ a la comunidad hispana de Game Maker. Nuestro objetivo es crear videojuegos y dar soporte en castellano de GM. Para mejorar nuestro servicio hemos implantado, como adicion al reglamento general, algunas normas especificas en los subforos más comunes. ¡No olvides informarte antes de participar!.

Autor Tema: como hacer un juego cartas  (Leído 1250 veces)

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

Desconectado Black_Cat

en: Enero 15, 2020, 02:37:05 am
Hola gente, feliz año nuevo (?
estoy pensando hacer un juego de cartas, pero no me figuro bien como hacerlo. Sé masomenos que clase de estructuras usar para armar la baraja o la mano del jugador, tipo listas y pilas, etc.
De hecho hice estas vacaciones algunas implementaciones de juegos basicos de cartas, tipo comparar 2 cartas de mazos distintos, etc.
Pero yo quiero llegar más lejos, implementar algo tipo magic o yugioh en donde uno tendría un mazo sacaría cartas y podría ponerlas en lo que vendría siendo un campo o encima de la mesa.

La pregunta en cuestión es, qué ideas me pueden aportar para gestionar las cartas encima de la mesa? porque tengo varias implementaciones, usar objetos como slots para ponerle una carta encima. O usar una matriz de NxM para representar el campo. O de ultima usar una estructura de collisionadores o zonas de lectura de mouse para saber donde se está poniendo una carta o donde se esta cliqueando.
No sé bien, a qué idea apuntar, por el tema de rendimiento o el tema de facilidad para programar a futuro.
La pregunta entonces es: ¿Cuál seria la abstraccion correcta para manejar las cartas?
 8) saludos jugadores de magic



 


No Tienes Permisos Para Dar Puntos
point 0 Puntos

Este tema no recibió puntos.


Desconectado BssString

Respuesta #1 en: Enero 16, 2020, 05:20:51 pm
Hola Black_Cat

Si el tablero de juego tiene una estructura definida y fija, mi sugerencia es que uses objetos para la posición del mazo, pila de descarte y cartas del campo. Eso para poder detectar la colisión con mayor facilidad usando las funciones integradas de Game Maker.

Para la mano por otro lado, no es cómodo usar objetos porque tendrías que reposicionarlos cada vez que ganas o pierdes una carta, entonces mi sugerencia es que dinámicamente generes el draw event y detectes la colisión en función de la cantidad de cartas que tengas en la mano.

Saludos

 


Desconectado Black_Cat

Respuesta #2 en: Enero 17, 2020, 01:03:05 am
Gracias por la respuesta colega, estabamos pensando eso mismo que dijsite.
Aunque lo habíamos abordado a hacer la mano con objetos, nos está dando uno que otro problema XD vamos a tener que cambiar eso de momento.
Gracias por la sugerencia! va a ser más como que usar matrices de datos. 8)


 


Desconectado BssString

Respuesta #3 en: Enero 17, 2020, 02:57:37 am
Hola Black_Cat

Es bastante difícil, en ese caso, para dibujar e interactuar con una mano falsa de forma dinámica (donde no existen objetos carta en la mano como tal para detectar mouse o colisión).
Te recomiendo primero crear la mano como una Data Structure de tipo "ds_list" (pienso que es la que mejor aplica para este caso).
Cada carta debe tener un ID único, su ID debe hacer referencia a un sprite y a ciertas estadísticas que tendría la carta en combate, entonces cada vez que ganas una carta a la mano, añades el ID a la DS List.

Create Event
Código: [Seleccionar]
cards = ds_list_create() //Esto crea una DS Structure llamada "cards", ojo que luego hay que eliminarla, sino queda en la memoria cache de GM
card_width = sprite_get_width(spr_card) //yo he llamado "spr_card" a mi sprite y cada subimagen es un ID diferente de carta, tu puedes usar el sistema que quieras
card_height = sprite_get_height(spr_card) //Guardo el ancho y alto para no andar usando "sprite_get" a cada rato.
gap = 32 //Esta es la separación en pixeles que tendrá cada carta cuando se dibujen en la mano.
position_clicked = -1 //La posición de la carta que estoy seleccionando (o -1 si no hay ninguna clickeada)

en el evento Cleanup / Destroy / Game End / o cualquiera que quieras llamar para destuir la DS List. Ojo que si cierras el juego, se hace call al evento "Game End", pero NO al evento "destroy".
Código: [Seleccionar]
if ds_exists(cards,ds_type_list) ds_list_destroy(cards) //destruyes la DS List creada antes de la memoria
En el Draw Event, para dibujar la mano, simplemente usa un "for loop" y dibujas cada carta con la separación de la variable "GAP".
Código: [Seleccionar]
var hand_width = card_width*min(1,ds_list_size(cards))+max(0,ds_list_size(cards)-1)*gap //Esto calcula el ancho en pixeles de la mano, uso una variable local (con Var) en vez de una Instance Variable porque el tamaño de la mano varía constantemente.
for (var i=0; i<ds_list_size(cards); i+=1) { //Inicia el for loop desde 0 hasta la cantidad de cartas menos 1.
var card_id = ds_list_find_value(cards,i) //Esto trae el ID de la carta desde la Data Structure
draw_sprite(spr_card,card_id,(room_width-hand_width)/2+i*gap,room_height-card_height) //Aquí yo he dibujado mi Sprite llamado "spr_card" y la sub-imagen la usé como el ID de mi carta
}

Step Event
Código: [Seleccionar]
if mouse_check_button_pressed(mb_left) { //Esto es para clickear sobre la mano falsa, intenta crear otra condición para evitar que pulses 2 objetos al mismo tiempo, me refiero a los objetos que existen debajo de la mano al mismo tiempo que clickeas la mano.
var hand_width = card_width*min(1,ds_list_size(cards))+max(0,ds_list_size(cards)-1)*gap //Vuelve a calcular el tamaño de la mano en pixeles
if hand_width > 0 && point_in_rectangle(mouse_x,mouse_y,(room_width-hand_width)/2,room_height-card_height,(room_width+hand_width)/2-1,room_height-1) { //En caso que tengas más de
0 cartas (en realidad hago check al ancho en pixeles de la mano, pero si hay 0 cartas la mano mide 0 pixeles), esto detectará la posición de la carta que hayas pulsado, si pulsaste la primera, la segunda, etc.
position_clicked = 0 //Este es el valor por defecto que agarra en caso que tengas 1 carta, para seleccionar la posición cero que es la única que hay.
if ds_list_size(cards) > 0 { //En caso que tengas más de cero cartas
if mouse_x >= (room_width+hand_width)/2 - card_width { position_clicked = ds_list_size(cards)-1 } //Primero revisas si pulsas la carta de la derecha (la carta que se dibuja completa), y luego selecciona la última posición de la DS List.
else { position_clicked = (mouse_x - (room_width-hand_width)/2) div gap } //Sino, calcula la carta que clickeaste según el GAP, si clickeaste a 3 GAP de distancia, entonces es porque pulsaste la tercera carta xD
//Aquí detecta que has clickeado una carta de la mano y guarda la posición en la ds_grid en la variable "position_clicked" para uso futuro.
//Puedes abrir quizás algún objeto menú que diga "inspeccionar Carta", "Colocar en Campo", "Cancelar acción", etc.
//Si por alguna razón creas un objeto menu, debes evitar que este bloque de código te vuelva a detectar un clic sobre la mano falsa mientras esté abierto ese menú, quizás usando algún "if !instance_exists()" adelante de todo.
//Puedes usar la variable "position_clicked" en el Draw Event para darle información visual al player de la carta que clickeó, quizás dibujándola ligeramente más arriba que las otras o dibujarle algún outline de otro color.
}
}
else { position_clicked = -1 } //Esto sirve para deseleccionar la carta en caso que clickees fuera de la mano, puedes dejarlo así o usar tu propio método (quizás con algún botón "Cancelar Acción")
}

Para testear el código, en algún lado debes darte cartas en la mano, quizás cuando pulsas alguna tecla, sólo para testear si el código funciona o no.
Código: [Seleccionar]
if keyboard_check_pressed(ord("N")) { ds_list_add(cards,0) }
Saludos
« última modificación: Enero 17, 2020, 03:57:24 am por BssString »

 


Desconectado Black_Cat

Respuesta #4 en: Enero 19, 2020, 02:36:20 pm
gracias por la respuesta, la verdad casi llegamos al mismo codigo, prácticamente
solo que al usar una sprite con las cartas como subimagenes el variables de card_weigth y card_height la pudimos obviar.

también llegué a eso de tener que poner un ciclo dentro del ciclo draw(aunque en nuestro caso fue en el evento step) y se presentó el problema de que, cuanto mas crecía la lista más lento iba el juego. mas que nada porque había un apartado en donde si uno pasaba el mouse por encima mostraba diferentes caracteristicas de la carta y eso llevaba su tiempo, puesto que al no ser un objeto tenía que tener un indice en alguna lista (en este caso era una grid) donde estuviera almacenada la informacion de la carta, a saber: nombre, descripcion, atributos, etc.
Algo similar pasaba con las verificaciones en el evento step.

Y bue, al parecer el mejor método es usar objetos, ya que de por si maneja las colisiones y se le puede poner los datos dentro.
es lo más fácil de manejar a largo plazo


 


Desconectado BssString

Respuesta #5 en: Enero 19, 2020, 04:32:07 pm
Hola Black_Cat

Concuerdo en que los objetos son mejores para el campo de juego porque le puedes pasar los atributos de la carta cuando la colocas en juego.
Y si clickeas la carta del campo, podrás leer fácilmente todos sus atributos.

Pero insisto que para la mano no sería recomendable a menos que crees un buen sistema de actualización de los objetos, variables y posiciones porque las cartas de la mano van cambiando constantemente, entonces tendrías que modificar los atributos constantemente.

No necesitas un ciclo for para leer los atributos de las cartas. Simplemente con el ID ya lo puedes sacar desde la DS GRID y leer el atributo que quieras.
Con otra persona de la comunidad estamos haciendo un RPG con más de 500 personajes, también guardamos los datos en una DS GRID y durante los combates no se nos lagea el juego cuando nos trae la info.

He asumido que tu grid tiene esta estructura:
0123...
ID1atributo1atributo2etc
ID2atributo1atributo2etc

Una vez conocido el ID de la carta, vas a buscar le ID en la grid
Código: [Seleccionar]
var id_carta = 0 //puse 0 como ejemplo, pero en realidad puedes usar el mouse check para traer el ID real de la carta que tengas
var yy = ds_grid_value_y(grid, 0, 0, 0, ds_grid_height(grid), id_carta) //Esta línea encuentra en que fila se encuentran los datos de tu carta en la GRID, leyendo los datos desde la columna 0
atributo1 = grid[# 1,yy]
atributo2 = grid[# 2,yy]
etc

Puedes actualizarlo cada vez que el mouse entra en las coordenadas de la mano e incluso evitar actualizarlo si mantienes el mouse sobre la misma carta para que no te vaya a leer la GRID en cada STEP.
Puedes usar dos variables "id_carta" e "id_carta_previo" para verificar si el mouse se puso sobre una carta diferente, para no correr el código en cada STEP.

Saludos

 


Desconectado kaliman777

Respuesta #6 en: Enero 28, 2020, 02:59:40 am
Hola Black_Cat:
Recién terminé un juego de póker mira un ejemplo aquí:
Si quieres te puedo asesorar.

Busco aliarme con alguien que me ayude a exportar a Android varios juegos que terminé en GM 8. No tengo licencia para GM STUDIO 2 XD

A la orden

La verdad es como la luz de una vela, que ni la oscuridad inmensa, puede opacarla.