Browse Source

GUI : ajout de display_usermove_pawn : déplacement d'un pion par un joueur (manque des animations)

master
Nikos 8 years ago
parent
commit
3e15e6de69
3 changed files with 173 additions and 55 deletions
  1. +143
    -45
      gui.c
  2. +1
    -0
      gui.h
  3. +29
    -10
      guidemo.c

+ 143
- 45
gui.c View File

@ -56,7 +56,7 @@ struct gui_resource_t display_start() {
}
SDL_Event display_until_event(const struct gui_resource_t *res) {
null_die(res, "ヌルポ。。。! (gui_resource)");
null_die(res, "ヌルポ。。。! (gui_resource)");
#define FIXEDFRAMETIME 125 /* 125ms → 8fps */
SDL_Event event;
@ -88,30 +88,12 @@ SDL_Rect coord_rotate(SDL_Rect coord, double sin, double cos) {
return res;
}
/* permet de sortir des positions en pixels à partir d'indices de plateau */
struct pos_export_t { int pos[2]; SDL_Rect pixpos[2]; };
void draw_all(const struct gui_resource_t *res, const struct game_state_t *gamestate, SDL_Surface *buffer, double angle, int antialias, struct pos_export_t *export) {
if(buffer == NULL)
buffer = res->screen;
/* dessin du fond */
SDL_BlitSurface(res->bgnd_img, NULL, buffer, NULL);
SDL_BlitSurface(res->title_img, NULL, buffer, NULL);
if(angle == 0.0)
/* pas besoin de tourner */
SDL_BlitSurface(res->board_img, NULL, buffer, NULL); /* dessin du plateau */
else {
/* rotation plateau */
SDL_Surface *rotated_board_img = rotozoomSurface(res->board_img, angle*180/M_PI, 1.0, antialias);
SDL_Rect clip = { res->board_img->w/2 - rotated_board_img->w/2, res->board_img->h/2 - rotated_board_img->h/2, 0, 0};
SDL_BlitSurface(rotated_board_img, NULL, buffer, &clip); /* dessin du plateau */
SDL_FreeSurface(rotated_board_img);
}
/* calcul des positions des pions en pixels, avec rotation */
struct pawns_pxcoords_t { SDL_Rect p[121]; };
struct pawns_pxcoords_t calc_pawns_pxcoords(double angle) {
/* positions pour les images de pion */
SDL_Rect pawn_pos, pawn_pos_rot;
SDL_Rect pawn_pos;
struct pawns_pxcoords_t pawns_pos_rot;
/* joueur courant en bas de l'écran */
angle += M_PI;
@ -138,31 +120,64 @@ void draw_all(const struct gui_resource_t *res, const struct game_state_t *games
pawn_pos.x += PAWNSIZE+HORIZSPACING;
}
/* matrix rotation on pawn_pos using cos & sin of param angle */
pawn_pos_rot.x = pawn_pos.x + PAWNSIZE/2 - SCREEN_X/2;
pawn_pos_rot.y = pawn_pos.y + PAWNSIZE/2 - SCREEN_Y/2;
pawn_pos_rot = coord_rotate(pawn_pos_rot, sinA, cosA);
pawn_pos_rot.x -= PAWNSIZE/2 - SCREEN_X/2;
pawn_pos_rot.y -= PAWNSIZE/2 - SCREEN_Y/2;
SDL_BlitSurface(res->pawn_img[gamestate->board[i]], NULL, buffer, &pawn_pos_rot);
/* export coords */
if(export) {
if(i == export->pos[0])
export->pixpos[0] = pawn_pos_rot;
if(i == export->pos[1])
export->pixpos[1] = pawn_pos_rot;
}
pawns_pos_rot.p[i].x = pawn_pos.x + PAWNSIZE/2 - SCREEN_X/2;
pawns_pos_rot.p[i].y = pawn_pos.y + PAWNSIZE/2 - SCREEN_Y/2;
pawns_pos_rot.p[i] = coord_rotate(pawns_pos_rot.p[i], sinA, cosA);
pawns_pos_rot.p[i].x -= PAWNSIZE/2 - SCREEN_X/2;
pawns_pos_rot.p[i].y -= PAWNSIZE/2 - SCREEN_Y/2;
}
return pawns_pos_rot;
}
/* permet de sortir des positions en pixels à partir d'indices de plateau */
struct pos_export_t { int pos[2]; SDL_Rect pixpos[2]; };
void draw_all(const struct gui_resource_t *res, const struct game_state_t *gamestate, SDL_Surface *buffer, double angle, int antialias, struct pos_export_t *export) {
if(buffer == NULL)
buffer = res->screen;
/* dessin du fond */
SDL_BlitSurface(res->bgnd_img, NULL, buffer, NULL);
SDL_BlitSurface(res->title_img, NULL, buffer, NULL);
if(angle == 0.0)
/* pas besoin de tourner */
SDL_BlitSurface(res->board_img, NULL, buffer, NULL); /* dessin du plateau */
else {
/* rotation plateau */
SDL_Surface *rotated_board_img = rotozoomSurface(res->board_img, angle*180/M_PI, 1.0, antialias);
SDL_Rect clip = { res->board_img->w/2 - rotated_board_img->w/2, res->board_img->h/2 - rotated_board_img->h/2, 0, 0};
SDL_BlitSurface(rotated_board_img, NULL, buffer, &clip); /* dessin du plateau */
SDL_FreeSurface(rotated_board_img);
}
/* calcul de toutes les coordonnées en pixels des pions à dessiner */
struct pawns_pxcoords_t pawns_pxcoords = calc_pawns_pxcoords(angle);
/* dessin des pions */
int i;
for(i = 0; i < 121; i++)
SDL_BlitSurface(res->pawn_img[gamestate->board[i]], NULL, buffer, &pawns_pxcoords.p[i]);
/* export des coordonnées pour réutilisation (animation de saut) si demandé */
if(export) {
/* il est déjà prévu un mouvement dans export->pos en cas de position malformée, on n'affecte donc que si c'est un emplacement de pion */
if(export->pos[0] >= 0 && export->pos[0] < 121) /* évite le segfault au passage */
export->pixpos[0] = pawns_pxcoords.p[export->pos[0]];
if(export->pos[1] >= 0 && export->pos[1] < 121)
export->pixpos[1] = pawns_pxcoords.p[export->pos[1]];
}
}
void display_render_board(const struct gui_resource_t *res, const struct game_state_t *gamestate, enum hole_t currentplayer) {
null_die(res, "ヌルポ。。。カ! (gui_resource)");
null_die(gamestate, "ヌルポ。。。カ! (game_state)");
null_die(res, "ヌルポ。。。! (gui_resource)");
null_die(gamestate, "ヌルポ。。。! (game_state)");
draw_all(res, gamestate, NULL, ((((double)currentplayer)-1)*M_PI)/3, 1/*antialias*/, NULL);
}
int display_anirotate_board(const struct gui_resource_t *res, const struct game_state_t *gamestate, enum hole_t currentplayer, enum hole_t nextplayer) {
null_die(res, "ヌルポ。。。カ! (gui_resource)");
null_die(gamestate, "ヌルポ。。。カ! (game_state)");
null_die(res, "ヌルポ。。。! (gui_resource)");
null_die(gamestate, "ヌルポ。。。! (game_state)");
#define ANIFRAMETIME 40 /* 40ms → 25fps */
#define ANIMTIME 2000 /* 2000ms → 2s */
@ -196,7 +211,7 @@ int display_anirotate_board(const struct gui_resource_t *res, const struct game_
}
int display_animove_pawn(const struct gui_resource_t *res, struct game_state_t gamestate, enum hole_t currentplayer, int startpos, int endpos) {
null_die(res, "ヌルポ。。。! (gui_resource)");
null_die(res, "ヌルポ。。。! (gui_resource)");
#define PANIFRAMETIME 40 /* 40ms → 25fps */
#define PANIMTIME 1000 /* 1000ms → 1s */
@ -239,9 +254,92 @@ int display_animove_pawn(const struct gui_resource_t *res, struct game_state_t g
return frame != PANIMTIME/PANIFRAMETIME + 1;
}
int find_pawn_index(Uint16 click_x, Uint16 click_y, const struct pawns_pxcoords_t *pawns_pxcoords) {
int i, res = -1;
for(i = 0; i < 121; i++) {
/* si le clic est dans le carré d'un emplacement de pion */
if(pawns_pxcoords->p[i].x < click_x && click_x < pawns_pxcoords->p[i].x+PAWNSIZE
&& pawns_pxcoords->p[i].y < click_y && click_y < pawns_pxcoords->p[i].y+PAWNSIZE)
{
res = i;
break;
}
}
return res;
}
int display_usermove_pawn(const struct gui_resource_t *res, const struct game_state_t *gamestate, enum hole_t currentplayer, struct move_t *move) {
null_die(res, "ヌルポ。。。ガ! (gui_resource)");
null_die(gamestate, "ヌルポ。。。ガ! (game_state)");
null_die(move, "ヌルポ。。。ガ! (move)");
struct pawns_pxcoords_t pawns_pxcoords = calc_pawns_pxcoords( ((((double)currentplayer)-1)*M_PI)/3 );
SDL_Event event;
int quit = 0;
while(!quit) {
//voir s'il faut dessiner le plateau, on a ptet foutu le bazar avant un continue
/* attente du début de glisser-déposer */
int press = 0;
while(!quit && !press) {
while(SDL_WaitEvent(&event)) {
SDL_Flip(res->screen); /* rafraîchir l'écran à tout événement suffit-il ? TODO poll si c'est pas suffisant et tout noir */
if(event.type == SDL_MOUSEBUTTONDOWN) {
press = 1;
break;
} else if(event.type == SDL_QUIT) {
quit = 1;
break;
}
}
}
if(quit)
break;
/* tentons de trouver un index de pion aux coordonnées du clic enfoncé */
move->startPos = find_pawn_index(event.button.x, event.button.y, &pawns_pxcoords);
if (move->startPos == -1 || gamestate->board[move->startPos] == none) /* si clic en dehors d'un emplacement de pion ou pas de pion dedans */
continue; /* l'utilisateur a cliqué n'importe où, on recommence au début */
/* attente de la fin de glisser-déposer */
int release = 0;
while(!quit && !release){
while(SDL_WaitEvent(&event)) {
if(event.type == SDL_MOUSEBUTTONDOWN) {
release = 1;
break;
} else if(event.type == SDL_QUIT) {
quit = 1;
break;
}
}
//render_board gamestate sans le pion, blit le pion par-dessus dans res->screen à la position curseur (x_mouse - w/2, y_mouse - h/2 ) // ptet seulement s'il a bougé, éco proc (résolu par waitevent !!)
SDL_Flip(res->screen);
}
if(quit)
break;
/* tentons de trouver un index de pion aux coordonnées du relâchement du clic */
move->endPos = find_pawn_index(event.button.x, event.button.y, &pawns_pxcoords);
if (move->startPos == -1) {
// animation de retour du pion à startPos/ (au pixel, obligé) TODO
continue;
} else if(gamestate->board[move->endPos] != none) {
/* animation de retour */
display_animove_pawn(res, *gamestate, currentplayer, move->endPos, move->startPos); //ou au pixel TODO
continue;
}
//rendu ici le mouvement est OK, on affiche le résultat ?
break; // rendu ici le mouvement est OK, on sort
}
return quit;
}
int display_animsg(const struct gui_resource_t *res, const struct game_state_t *gamestate, enum hole_t currentplayer, const char *msg, uint32_t duration) {
null_die(res, "ヌルポ。。。カ! (gui_resource)");
null_die(gamestate, "ヌルポ。。。カ! (game_state)");
null_die(res, "ヌルポ。。。! (gui_resource)");
null_die(gamestate, "ヌルポ。。。! (game_state)");
#define MANIFRAMETIME 40 /* 40ms → 25fps */
@ -294,7 +392,7 @@ int display_animsg(const struct gui_resource_t *res, const struct game_state_t *
}
void display_close(struct gui_resource_t *res) {
null_die(res, "ヌルポ。。。! (gui_resource)");
null_die(res, "ヌルポ。。。! (gui_resource)");
/* Libération mémoire */
SDL_FreeSurface(res->screen);


+ 1
- 0
gui.h View File

@ -20,5 +20,6 @@ int display_anirotate_board(const struct gui_resource_t *res, const struct game_
int display_animove_pawn(const struct gui_resource_t *res, struct game_state_t gamestate, enum hole_t currentplayer, int startpos, int endpos);
int display_usermove_pawn(const struct gui_resource_t *res, const struct game_state_t *gamestate, enum hole_t currentplayer, struct move_t *move);
void display_close(struct gui_resource_t *res);

+ 29
- 10
guidemo.c View File

@ -38,6 +38,9 @@ int main(void) {
/* un peu d'interactivité */
SDL_Event event;
if( display_animsg(&gui_res, &gamestate, 1, "Click to start!", 1200/*ms*/) )
quit = 1;
while(!quit) {
event = display_until_event(&gui_res);
@ -56,11 +59,10 @@ int main(void) {
while(player2 == player1)
player2 = (rand()%6)+1;
while(gamestate.board[pawn2 = rand()%121]); /* trouver un trou vide */
pawn1 = pawn2;
while(gamestate.board[pawn2 = rand()%121]); /* trouver un trou vide */
pawn1 = pawn2;
/* un pion du joueur courant au hasard.
s'il n'y en a pas on déplacera une case vide sur elle-même car pawn1 = pawn2 */
/* un pion du joueur courant au hasard. s'il n'y en a pas on déplacera une case vide sur elle-même car pawn1 = pawn2 */
r = rand()%10;
for(n = i = 0; i < 121; i++) {
if(gamestate.board[i] == player1) {
@ -71,13 +73,30 @@ int main(void) {
n++;
}
}
if( display_animove_pawn(&gui_res, gamestate, player1, pawn1, pawn2) ) {
quit = 1;
break;
struct move_t user_move;
if(player1 == 1) {
if( display_animsg(&gui_res, &gamestate, player1, "Your turn!", 1200/*ms*/) ) {
quit = 1;
break;
}
if( display_usermove_pawn(&gui_res, &gamestate, player1, &user_move) ) {
quit = 1;
break;
}
gamestate.board[user_move.endPos] = gamestate.board[user_move.startPos];
gamestate.board[user_move.startPos] = none;
if( display_animsg(&gui_res, &gamestate, player1, "You’ve done your move!", 1200/*ms*/) ) {
quit = 1;
break;
}
} else {
if( display_animove_pawn(&gui_res, gamestate, player1, pawn1, pawn2) ) {
quit = 1;
break;
}
gamestate.board[pawn2] = gamestate.board[pawn1];
gamestate.board[pawn1] = none;
}
gamestate.board[pawn2] = gamestate.board[pawn1];
gamestate.board[pawn1] = none;
if( display_anirotate_board(&gui_res, &gamestate, player1, player2) ) {
quit = 1;


Loading…
Cancel
Save