GM pour un jeu d'échecs sans ia?
Pour commencer, il faut dessiner l'échiquier. Pour cela un objet controler doit être créé afin de lui assigner les tâches de draw (je crois qu'il lui faut quand même une sprite pour que l'action draw soit prise en compte, mais je n'en suis pas sûr.) Ceci fait, il faut mettre un script dans draw (onglet control).
Nous allons utiliser la boucle for, qui sert à répéter un certain nombre de fois une action.
for(i=0;i<8;i+=1)
{
}
i=0 initialise la variable i à 0, i+=1 signifie qu'à chaque fin de boucle i est augmenté d'un. i aura donc les valeurs de 0 à 7, pour dessiner les 8 cases. Il faut cependant définir les conditions selon lesquelles on choisit de dessiner une case noire ou blanche. Avec frac(x), on obtient la partie décimale d'un nombre, donc si cette fonction est égale à 0, c'est que le nombre x, que l'on divisera par 2, est pair. nb je n'ai pas testé.
for(i=0;i<8;i+=1)
{
for(j=0;j<8;j+=1)
{
if frac(i/2)==0
{
if frac(j/2)==0
{
draw_set_color(c_white);
draw_rectangle(i*80+100,j*80+100,i*80+180,j*80+180,false);
}
else
{
draw_set_color(c_black);
draw_rectangle(i*80+100,j*80+100,i*80+180,j*80+180,false);
}
}
else
{
if frac(j/2)==0
{
draw_set_color(c_black);
draw_rectangle(i*80+100,j*80+100,i*80+180,j*80+180,false);
}
else
{
draw_set_color(c_white);
draw_rectangle(i*80+100,j*80+100,i*80+180,j*80+180,false);
}
}
}
}
draw_set_color sert à définir la couleur pour la fonction draw, draw_rectangle dessine la case.
Les deux premiers chiffres sont les coordonnées du rectangle en haut à gauche, les deux autres en bas à droite. On ajoute 100 pour ne pas dessiner l'échiquier tout en haut à gauche, mais ça ne suffira pas pour le centrer. On multiplie les coordonnées par 80 pour faire des cases de 80 pixels, false signifie qu'on ne dessine pas le pourtour.
Voila, en théorie on a un super échiquier en lançant le jeu, mais c'est pas testé.
Bon j'ai mis les espaces à coté des accolades pour des prunes
Ensuite il faut créer des sprites pour toutes les pièces... Ou télécharger des images libres de droit,
créer un objet par type de pièce et par joueur, plus deux objets parents qu'on peut nommer, par exemple, j_piece et o_piece. Il faudra, pour les objets du joueur, spécifier comme parent j_piece, pour celles de l'ordi, qui ne bougeront pas avant longtemps, o_piece. Les objets parents sont en quelque sorte le comportement par défaut pour les objets enfants, mais si ceux-ci ont un event similaire à celui du parent, l'event du parent est ignoré.
On peut ensuite poser les objets dans la room, mais cela est difficile car le quadrillage de l'éditeur ne correspond pas au notre, et assigner dans l'event create de j_piece et o_piece les coordonnées de la case, auquel cas l'objet apparaîtra en haut à gauche de celle-ci, avec:
id.x=floor((id.x-100)/80);
id.y=floor((id.y-100)/80);
Ici, le programme lors de la création de l'instance de l'objet assigne ses coordonnées (x et y), par le biais de "." : id sert à définir l'instance de l'objet, puis ses coordonnées sont modifiées en fonction de l'endroit où il est créé. floor sert à arrondir en dessous.
L'autre solution est de créer les objets un par un dans le creation code de la room:
ex: instance_create(100,100+80*6,j_pion); instance_create(100+80*1,100+80*6,j_pion);
créé des pions en A2, en B2 avec j_pion pour nom de l'objet définissant le pion. On peut utiliser une boucle for pour créer les pions.
Bouger les pions.
On va prendre comme système: un clic sur la pièce signifie qu'elle est sélectionnée, puis un clic sur l'échiquier la déplace.
Il faut d'abord retrouver l'id de l'objet cliqué. Dans l'objet j_piece, on peut mettre un event left pressed, ce qui signifie que l'objet réagit une fois à un clic sur lui-même, avec le code:
oclic=id;
en ajoutant aussi dans l'event create du controler:
globalvar oclic;
oclic=noone;
Nous avons défini une variable globale oclic, qui subsiste tout au long du jeu, contenant par défaut la valeur noone (c'est une valeur spéciale renvoyée par les fonctions comme instance_position signifiant qu'aucun objet n'a été trouvé). Quand l'utilisateur clique sur une pièce, l'opérateur = renvoie l'id dans oclic.
Maintenant, dans le controler, event global left pressed (cet event a lieu lors de n'importe quel clic dans la room):
if (oclic!=noone)&&(mouse_x>100)&&(mouse_x<100+80*8)&&(mouse_y100)
{
locx=floor((oclic.x-100)/80);locy=floor((oclic.y-100)/80);
cibx=floor((mouse_x-100)/80);
ciby=floor((mouse_y-100)/80);
if object_index.oclic==j_pion
{
tst=script_execute(check_line,locx,locy,cibx,ciby,o_piece);
if tst==0
{
if (locy==6)&&(locy-ciby>0)&&(locx==cibx)&&(locy-ciby<3)
{oclic.x=cibx*80+100;oclic.y=ciby*80+100;oclic=noone;}
else if (locy-ciby==1)&&(locx==cibx)
{oclic.x=cibx*80+100;oclic.y=ciby*80+100;oclic=noone;}}}}
La première ligne conditionnelle vérifie qu'un objet a été sélectionné, et que les coordonnées du nouveau clic sont sur l'échiquier. locx... font correspondre les coordonnées sur l'écran à des cases du plateau, de la position de base de la pièce à l'endroit où le joueur a cliqué. La condition suivante s'occupe du cas spécifique du pion, la fonction object_index renvoie l'index d'objet de l'instance qui doit être égal au nom donné à l'objet "pion du joueur". Ensuite, une fonction utilisateur est appelée, il faudra créer ce script par la suite, qui aura pour but de vérifier qu'il n'y a pas de pièce entre le pion et sa case de destination, et qui pourra être utilisé aussi pour les tours et la reine. Cette fonction renvoiera 0 si aucune pièce n'est rencontrée, 1 si la case de destination est occupée par une pièce adverse et qu'il n'y a aucune pièce entre les deux, et 2 si il y a une pièce entre les deux cases ou que la case de destination est occupée par le même joueur. On vérifie ceci en testant la variable "tst", puis on examine deux cas: Soit le pion est sur sa case de départ, soit y=6 si je ne me suis pas trompé, et on autorise un clic jusqu'à deux cases, soit on autorise un clic à une case seulement. Il faut vérifier aussi que le pion ne va pas en arrière et qu'il se déplace sur sa ligne.
Le script "check_line" recevra en argument les coordonnées des deux cases à tester, plus l'objet parent à considérer comme adversaire, "regardera" si aucune pièce ne se situe entre les deux, auquel cas il retournera 2. Si c'est la case de destination qui est occupée par un adversaire, le script retroune 1 (cas d'une prise). Enfin, si rien n'est rencontré, le script retourne 0. Il faut bien sûr d'abord créer un nouveau script et le nommer. Attention, il faut impérativement mettre en premier les coordonnées de la pièce à déplacer.
if (argument0!=argument2)&&(argument1!=argument3)
{return 2}
if (argument0==argument2)&&(argument1>argument3)
{
for(i=argument1-1;i>argument3-1;i-=1)
{
if instance_position(i*80+100,argument0*80+100,all)!=noone
{
if i>argument3
{return 2;}
else if (i==argument3)&&(instance_position(i*80+100,argument0*80+100,argument4)!=noone)
{return 1;}
else
{return 2;}}}}
if (argument0==argument2)&&(argument3>argument1)
{
for(i=argument1+1;i<argument3+1;i+=1)
{
if instance_position(i*80+100,argument0*80+100,all)!=noone
{
if i<argument3
{return 2;}
else if (i==argument3)&&(instance_position(i*80+100,argument0*80+100,argument4)!=noone)
{return 1;}
else
{return 2;}}}}
if (argument1==argument3)&&(argument0>argument2)
{
for(i=argument0-1;i>argument2-1;i-=1)
{
if instance_position(argument1*80+100,i*80+100,all)!=noone
{
if i>argument2
{return 2;}
else if (i==argument2)&&(instance_position(argument1*80+100,i*80+100,argument4)!=noone)
{return 1;}
else
{return 2;}}}}
if (argument1==argument3)&&(argument0<argument2)
{
for(i=argument0+1;i<argument2+1;i+=1)
{
if instance_position(argument1*80+100,i*80+100,all)!=noone
{
if i<argument2
{return 2;}
else if (i==argument2)&&(instance_position(argument1*80+100,i*80+100,argument4)!=noone)
{return 1;}
else
{return 2;}}}}
return 0;
Ainsi la première condition vérifie d'abord que les deux cases à tester sont en ligne, sinon le script retourne false. Notons que la fonction return interrompt le script et donne la variable à droite de return comme valeur retour.
Ensuite il faut tester quelle est la valeur la plus grande entre les coordonnées des cases pour savoir dans quel ordre faire tourner la boucle, et quelle ligne est considérée: horizontale ou verticale? Tout cela pour vérifier que les cases appropriées sont vides.
Pions: prise en diagonale.
Il faut rajouter avant tst=script_execute...
if (cibx==lox-1)&&(locx-1>=0)&&(ciby==locy-1)&&(locy-1>0)&&(instance_position(cibx,ciby,o_piece)!=noone)
{
position_destroy(cibx,ciby,all);
oclic.x=cibx*80+100;oclic.y=ciby*80+100;oclic=noone;
}
if (cibx==lox+1)&&(locx+1<=7)&&(ciby==locy-1)&&(locy-1>0)&&(instance_position(cibx,ciby,o_piece)!=noone)
{
position_destroy(cibx,ciby,all);
oclic.x=cibx*80+100;oclic.y=ciby*80+100;oclic=noone;
}
position_destroy sert à supprimer les instances d'objets dont la sprite couvre la position indiquée.