Browse Source

GUI : implémentation de l'animation de déplacement de pion.

Démo GUI : implémentation d'une stratégie aléatoire en passant le tour à un joueur aléatoirement. Ça sert à rien mais c'est beau.
gui.h : interface stabilisée et cohérente.
master
Nikos 8 years ago
parent
commit
f23a0dfaa8
3 changed files with 106 additions and 27 deletions
  1. +65
    -12
      gui.c
  2. +6
    -11
      gui.h
  3. +35
    -4
      guidemo.c

+ 65
- 12
gui.c View File

@ -73,26 +73,32 @@ SDL_Rect coord_rotate(SDL_Rect coord, double sin, double cos) {
return res;
}
void draw_all(struct gui_resource_t *res, struct game_state_t *gamestate, double angle, int antialias) {
/* pour ne les calculer qu'une fois */
double sinA = sin(angle), cosA = cos(angle);
/* 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(struct gui_resource_t *res, struct game_state_t *gamestate, SDL_Surface *buffer, double angle, int antialias, struct pos_export_t *export) {
if(buffer == NULL)
buffer = res->screen;
/* positions pour les images */
SDL_Rect zero_pos = {0, 0}, pawn_pos, pawn_pos_rot;
/* pour ne les calculer qu'une fois et pas 121 */
double sinA = sin(angle), cosA = cos(angle);
/* dessin du fond */
SDL_BlitSurface(res->bgnd_img, NULL, res->screen, &zero_pos);
SDL_BlitSurface(res->title_img, NULL, res->screen, &zero_pos);
SDL_BlitSurface(res->bgnd_img, NULL, buffer, NULL);
SDL_BlitSurface(res->title_img, NULL, buffer, NULL);
#ifdef sdl_gfx /* 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};
SDL_BlitSurface(rotated_board_img, NULL, res->screen, &clip); /* dessin du plateau */
SDL_BlitSurface(rotated_board_img, NULL, buffer, &clip); /* dessin du plateau */
SDL_FreeSurface(rotated_board_img);
#else
SDL_BlitSurface(res->board_img, NULL, res->screen, &zero_pos); /* dessin du plateau */
SDL_BlitSurface(res->board_img, NULL, buffer, NULL); /* dessin du plateau */
#endif
/* positions pour les images de pion */
SDL_Rect pawn_pos, pawn_pos_rot;
/* dessin des pions */
int index_lines[] = {1, 3, 6, 10, 23, 35, 46, 56, 65, 75, 86, 98, 111, 115, 118, 120};
int index_line_offsets[] = {0, 0, 2, 2, 8, 11, 11, 9, 9, 8, 10, 10, 12, 7, 3, 1, 1};
@ -120,12 +126,19 @@ void draw_all(struct gui_resource_t *res, struct game_state_t *gamestate, double
pawn_pos_rot = coord_rotate(pawn_pos_rot, sinA, cosA);
pawn_pos_rot.x -= PAWNSIZE/2 - CENTER_X;
pawn_pos_rot.y -= PAWNSIZE/2 - CENTER_Y;
SDL_BlitSurface(res->pawn_img[gamestate->board[i]], NULL, res->screen, &pawn_pos_rot);
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;
}
}
}
void display_render_board(struct gui_resource_t res, struct game_state_t gamestate, enum hole_t currentplayer) {
draw_all(&res, &gamestate, ((((double)currentplayer)-1)*M_PI)/3, 1/*antialias*/);
draw_all(&res, &gamestate, NULL, ((((double)currentplayer)-1)*M_PI)/3, 1/*antialias*/, NULL);
}
int display_anirotate_board(struct gui_resource_t res, struct game_state_t gamestate, enum hole_t currentplayer, enum hole_t nextplayer) {
@ -145,7 +158,7 @@ int display_anirotate_board(struct gui_resource_t res, struct game_state_t games
double anim_progress = ( ((double)nextplayer) - ((double)currentplayer) ) * ( cos(M_PI*((double)frame)/((double)(ANIMTIME/ANIFRAMETIME))+M_PI) + 1 ) / 2;
double angle = ( anim_progress + (((double)currentplayer)-1) ) * M_PI / 3;
draw_all(&res, &gamestate, angle, frame == ANIMTIME/ANIFRAMETIME); /* antialiasing si dernière frame, sinon pas */
draw_all(&res, &gamestate, NULL, angle, frame == ANIMTIME/ANIFRAMETIME, NULL); /* antialiasing si dernière frame, sinon pas */
SDL_Flip(res.screen);
/* attente du temps restant dans la frame : stabilisation de la vitesse d'exécution */
@ -158,6 +171,46 @@ int display_anirotate_board(struct gui_resource_t res, struct game_state_t games
return 0;
}
int display_animove_pawn(struct gui_resource_t res, struct game_state_t gamestate, enum hole_t currentplayer, int startpos, int endpos) {
#define PANIFRAMETIME 40 /* 40ms → 25fps */
#define PANIMTIME 2000 /* 2000ms → 2s */
enum hole_t pawn = gamestate.board[startpos]; /* conserve la couleur du pion qui sera déplacé */
gamestate.board[startpos] = none; /* on dessine un trou dans le fond, car le pion va en partir */
SDL_Surface *buffer = SDL_ConvertSurface(res.bgnd_img, res.bgnd_img->format, res.bgnd_img->flags);;
struct pos_export_t pos_import = { {startpos, endpos} };
draw_all(&res, &gamestate, buffer, ((((double)currentplayer)-1)*M_PI)/3, 1/*antialias*/, &pos_import);
uint32_t time1, time2; /* mesure du temps de rendu de frame */
SDL_Event event;
SDL_Rect pawn_pos;
int frame;
for(frame = 0; frame <= ANIMTIME/ANIFRAMETIME; frame++) {
time1 = SDL_GetTicks();
while(SDL_PollEvent(&event))
if(event.type == SDL_QUIT)
return 1;
/* interpolation de position pour obtenir pawn_pos */
double cos_progress = ( cos(M_PI*((double)frame)/((double)(ANIMTIME/ANIFRAMETIME))+M_PI) + 1 ) / 2;
pawn_pos.x = pos_import.pixpos[0].x + (short)round( ((double)(pos_import.pixpos[1].x - pos_import.pixpos[0].x)) * cos_progress);
pawn_pos.y = pos_import.pixpos[0].y + (short)round( ((double)(pos_import.pixpos[1].y - pos_import.pixpos[0].y)) * cos_progress);
SDL_BlitSurface(buffer, NULL, res.screen, NULL);
SDL_BlitSurface(res.pawn_img[pawn], NULL, res.screen, &pawn_pos);
SDL_Flip(res.screen);
/* attente du temps restant dans la frame */
time2 = SDL_GetTicks();
if(time2-time1 > ANIFRAMETIME)
fprintf(stderr,"(rant) animation: the machine is slow, frame took %dms\n", time2-time1);
else
SDL_Delay(ANIFRAMETIME - (time2-time1));
}
return 0;
}
void display_close(struct gui_resource_t res) {
int i;


+ 6
- 11
gui.h View File

@ -3,20 +3,15 @@ struct gui_resource_t {
};
struct gui_resource_t display_start();
SDL_Event display_until_event(struct gui_resource_t res);
void display_render_board(struct gui_resource_t res, struct game_state_t gamestate, enum hole_t currentplayer);
int display_anirotate_board(struct gui_resource_t res, struct game_state_t gamestate, enum hole_t currentplayer, enum hole_t nextplayer);
/* retourne 1 si l'animation a été interrompue par quitter l'application, sinon 0 */
/*void display_animove_pawn(struct gui_resource_t res, struct game_state_t board, int startpos, int endpos); */
/*
SDL_Rect pos_board = {0,0}; ou plus, à voir
(blit la board en utilisant du code commun à display_board() sans le pion de startpos) buffer
loop {
interpolation de position pour obtenir &pawn_pos
SDL_BlitSurface(buffer, NULL, screen, &pos_board);
SDL_BlitSurface(res.pawn_imgs[], NULL, screen, &pawn_pos);
SDL_Flip(screen)
}
*/
int display_animove_pawn(struct gui_resource_t res, struct game_state_t gamestate, enum hole_t currentplayer, int startpos, int endpos);
/* retourne 1 si l'animation a été interrompue par quitter l'application, sinon 0 */
void display_close();

+ 35
- 4
guidemo.c View File

@ -37,23 +37,54 @@ int main(int argc, char* argv[]) {
/* un peu d'interactivité */
SDL_Event event;
while(!quit) {
event = display_until_event(gui_res);
if(event.type == SDL_QUIT)
if(event.type == SDL_QUIT) {
quit = 1;
break;
}
if(event.type == SDL_MOUSEBUTTONDOWN)
break;
}
srand(time(NULL));
int pawn1, pawn2, r, i, n;
enum hole_t player1 = 1, player2 = player1;
while(!quit) {
while(player2 == player1)
player2 = rand()%6;
if( display_anirotate_board(gui_res, gamestate, player1, player2) )
player2 = (rand()%6)+1;
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 */
r = rand()%10;
for(n = i = 0; i < 121; i++) {
if(gamestate.board[i] == player1) {
if(n == r) {
pawn1 = i;
break;
}
n++;
}
}
if( display_animove_pawn(gui_res, gamestate, player1, pawn1, pawn2) ) {
quit = 1;
break;
}
gamestate.board[pawn2] = gamestate.board[pawn1];
gamestate.board[pawn1] = none;
if( display_anirotate_board(gui_res, gamestate, player1, player2) ) {
quit = 1;
break;
}
player1 = player2;
display_until_event(gui_res);
}
display_close(gui_res);


Loading…
Cancel
Save