root/gemmes_sdl.c

Revision 106, 10.9 kB (checked in by ng, 5 years ago)

mise a jour licence

Line 
1 /***************************************************************************
2  *   This file is part of the 'gemmes' project                             *
3  *                                                                         *
4  *                                                                         *
5  *   Copyright (C) 2007 by                                                 *
6  *         GARCH Soufiane                                                  *
7  *         GUILLAUME Nicolas <ng@ngsoft-fr.com>                            *
8  *                                                                         *
9  *                                                                         *
10  *   This program is free software; you can redistribute it and/or modify  *
11  *   it under the terms of the GNU General Public License as published by  *
12  *   the Free Software Foundation; version 2 of the License only.          *
13  *   See the COPYING file.                                                 *
14  ***************************************************************************/
15
16
17 #include <unistd.h>
18
19 #include "assert.h"
20 #include "gemmes.h"
21
22 #ifdef G_WINDOWS
23 # include "SDL.h"
24 # include "SDL_thread.h" /* depuis animation, rev > 76 */
25 #else
26 # include "SDL/SDL.h"
27 # include "SDL/SDL_thread.h" /* depuis animation, rev > 76 */
28 #endif
29
30 #include "sdl_draw.h"
31
32 #define RES_GEMMES "res/gemmes.bmp"
33 #define RES_FONT "res/font.bmp"
34 #define RES_SEL "res/selecteur.bmp"
35
36 #define GRID_WIDTH 2
37 #define BGCOLOR 0x000000
38 #define GRIDCOLOR 0xffffff
39
40 /* emplacement du plateau */
41 #define BOARD_START_X 10
42 #define BOARD_START_Y 10
43
44 /* emplacement du score depuis le bord droit */
45 static int SCORE_POS_X;
46 #define SCORE_POS_Y 20
47
48 /* espace apres le plateau */
49 static int BOARD_RIGHT;
50 #define BOARD_BOTTOM 10
51
52 /* taille d'une gemme */
53 #define GEMME_SIZE_X 52
54 #define GEMME_SIZE_Y 48
55 #define GEMME_ANIM_COUNT 10
56
57 #define RECT_COUNT 4
58
59
60 static volatile int over_x;
61 static volatile int over_y;
62 static volatile int sel_x;
63 static volatile int sel_y;
64 static volatile int stop;
65 static volatile unsigned int total_seg_count;
66 static SDL_Rect rects[RECT_COUNT];
67
68 volatile int current_frame;
69 volatile int changed;
70
71 SDL_Surface *screen;
72 SDL_Surface *sgemmes;
73 SDL_Surface *font;
74 SDL_Surface *sel;
75
76 void render(board_t b);
77 void init(board_t);
78 void draw_gemme(char gemme, int x, int y);
79 void do_move(board_t b, int x, int y, int dir_x, int dir_y);
80 void show_hint(board_t b);
81 int thread_draw(void* d);
82
83 void gemmes_start_ihm(board_t b)
84 {
85
86     if(SDL_Init(SDL_INIT_VIDEO) < 0)
87     {
88         fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
89         return;
90     }
91
92 /* plus il y a de case plus le score est grand !*/
93     SCORE_POS_X = 140 + b->xsize * b->ysize / 5;
94     BOARD_RIGHT = SCORE_POS_X + 10;
95
96     screen = SDL_SetVideoMode(b->xsize * (GEMME_SIZE_X + GRID_WIDTH) + GRID_WIDTH + BOARD_START_X + BOARD_RIGHT,
97                               (b->ysize == 2 ? 3 : b->ysize) * (GEMME_SIZE_Y + GRID_WIDTH) + GRID_WIDTH + BOARD_START_Y + BOARD_BOTTOM,
98                               32, SDL_SWSURFACE | SDL_DOUBLEBUF);
99
100     SDL_WM_SetCaption("Gemmified", NULL);
101
102     if (screen == NULL)
103     {
104         fprintf(stderr, "Unable to set %dx%d video: %s\n", screen->w, screen->h, SDL_GetError());
105         return;
106     }
107  
108     init(b);
109
110     changed = 1;
111
112     SDL_Thread * thread = SDL_CreateThread(thread_draw, b);
113    
114     while(!stop)
115     {
116
117         changed = 0;
118
119         SDL_Event event;
120         while (SDL_PollEvent(&event))
121         {
122             switch (event.type)
123             {
124             case SDL_KEYUP:
125             {
126                 switch(event.key.keysym.sym)
127                 {
128                 case SDLK_a:
129                     gemmes_autoplay(b);
130                     stop = 1;
131                     break;
132                 case SDLK_t:
133                     b->silent = 1;
134                     gemmes_autoplay_createtest(b);
135                     stop = 1;
136                     break;
137                 case SDLK_d:
138                     gemmes_dump(b);
139                     break;
140                 case SDLK_ESCAPE:
141                 case SDLK_q:
142                     stop = 1;
143                     break;
144                 case SDLK_h:
145                     show_hint(b);
146                     break;
147                 default:
148                     break;
149                 }
150             }
151             break;
152             case SDL_MOUSEMOTION:
153                 {
154                     int old_x = over_x;
155                     int old_y = over_y;
156
157                     /* si on est sur le plateau */
158                     if(event.button.x >= BOARD_START_X && event.button.x <= screen->w - BOARD_RIGHT &&
159                        event.button.y >= BOARD_START_Y && event.button.y <= screen->h - BOARD_BOTTOM)
160                     {
161                         int x, y;
162                         x = (event.button.x - BOARD_START_X) / (GEMME_SIZE_X + GRID_WIDTH);
163                         y = (event.button.y - BOARD_START_Y) / (GEMME_SIZE_Y + GRID_WIDTH);
164
165                         /* si on a une case cliquee, on permet de cliquer que celles autour */
166                         if( (sel_x == -1) ||
167                             (x == sel_x && y == sel_y) ||
168                             (x == sel_x + 1 && y == sel_y) ||
169                             (x == sel_x - 1 && y == sel_y) ||
170                             (x == sel_x && y == sel_y + 1) ||
171                             (x == sel_x && y == sel_y - 1) )
172                         {
173                             over_x = x;
174                             over_y = y;
175                         }
176                         else
177                             over_x = over_y = -1;
178
179                     }
180                     else
181                         over_x = over_y = -1;
182
183                     if(old_x != over_x || old_y != over_y)
184                         changed = 1;
185                 }
186                 break;
187             case SDL_MOUSEBUTTONDOWN:
188             {
189                     /* si on est sur le plateau */
190                     if(over_x != -1)
191                     {
192                         /* on déslectionne si deja selectionné */
193                         if(over_x == sel_x && over_y == sel_y)
194                             sel_x = sel_y = -1;
195                         else
196                         {
197                             /* si on a deja selectionne une case*/
198                             if(sel_x != -1)
199                             {
200                                 do_move(b, sel_x, sel_y, over_x, over_y);
201                                 over_x = over_y = sel_x = sel_y = -1;
202                             }
203                             else
204                             {
205                                 sel_x = over_x;
206                                 sel_y = over_y;
207                             }
208                         }
209                         changed = 1;
210                     }
211                 }
212                 break;
213             case SDL_QUIT:
214                 stop = 1;
215                 break;
216             }
217         }
218     }
219
220     SDL_WaitThread(thread, NULL);
221
222     SDL_FreeSurface(font);
223     SDL_FreeSurface(sel);
224     SDL_FreeSurface(sgemmes);
225     SDL_FreeSurface(screen);
226     SDL_Quit();
227 }
228
229 void init(board_t b)
230 {
231     /* on charge les gemmes */
232     SDL_Surface *temp = SDL_LoadBMP(RES_GEMMES);
233     c_assert2(temp, "unable to load " RES_GEMMES);
234     sgemmes = SDL_ConvertSurface(temp, screen->format, SDL_SWSURFACE);
235     c_assert(sgemmes);
236     SDL_FreeSurface(temp);
237
238     /* on charge la police */
239     temp = SDL_LoadBMP(RES_FONT);
240     c_assert2(temp, "unable to load " RES_FONT);
241     font = SDL_ConvertSurface(temp, screen->format, SDL_SWSURFACE);
242     c_assert(font);
243     SDL_FreeSurface(temp);
244
245     /* on charge les selecteur */
246     temp = SDL_LoadBMP(RES_SEL);
247     c_assert2(temp, "unable to load " RES_SEL);
248     sel = SDL_ConvertSurface(temp, screen->format, SDL_SWSURFACE);
249     c_assert(sel);
250     SDL_FreeSurface(temp);
251
252
253     draw_rect(screen, 0, 0, screen->w, screen->h, BGCOLOR);
254
255
256     /* on trace la grille */
257
258     /* traits verticaux */
259     int board_size =  b->ysize * (GEMME_SIZE_Y + GRID_WIDTH) + GRID_WIDTH;
260     int i;
261
262     for(i = 0; i <= b->xsize; ++i)
263     {
264         draw_rect(screen,
265                   i * (GEMME_SIZE_X + GRID_WIDTH) + BOARD_START_X,
266                   BOARD_START_Y,
267                   GRID_WIDTH,
268                   board_size,
269                   GRIDCOLOR
270             );
271     }
272
273     /* traits horizontaux */
274     board_size =  b->xsize * (GEMME_SIZE_X + GRID_WIDTH) + GRID_WIDTH;
275
276     for(i = 0; i <= b->ysize; ++i)
277     {
278         draw_rect(screen,
279                   BOARD_START_X,
280                   i * (GEMME_SIZE_Y + GRID_WIDTH) + BOARD_START_Y,
281                   board_size,
282                   GRID_WIDTH,
283                   GRIDCOLOR
284             );
285     }
286
287     /* score */
288     draw_string(screen, font, screen->w - SCORE_POS_X,  SCORE_POS_Y, "Score:");
289
290     over_x = over_y = sel_x = sel_y = -1;
291
292     /* nombre de segments */
293     draw_string(screen, font, screen->w - SCORE_POS_X,  SCORE_POS_Y + 3 * font->w, "Created\nsegments:");
294
295     /* nombre de segments total */
296     draw_string(screen, font, screen->w - SCORE_POS_X,  SCORE_POS_Y + 7 * font->w, "Total:");
297
298     stop = 0;
299     total_seg_count = 0;
300
301     /* rectangle du plateau */
302     rects[0].x = BOARD_START_X;
303     rects[0].y = BOARD_START_Y;
304     rects[0].w = screen->w - BOARD_RIGHT - BOARD_START_X;
305     rects[0].h = screen->h - BOARD_BOTTOM - BOARD_START_Y;
306
307     /* rectangle du score */
308     rects[1].x = screen->w - SCORE_POS_X;
309     rects[1].y = SCORE_POS_Y + font->w;
310     rects[1].w = SCORE_POS_X;
311     rects[1].h = font->w;
312
313     /* rectangle du nombre de segment */
314     rects[2].x = screen->w - SCORE_POS_X;
315     rects[2].y = SCORE_POS_Y + font->w * 5;
316     rects[2].w = SCORE_POS_X;
317     rects[2].h = font->w;
318
319     /* rectangle du nombre de segment total*/
320     rects[3].x = screen->w - SCORE_POS_X;
321     rects[3].y = SCORE_POS_Y + font->w * 8;
322     rects[3].w = SCORE_POS_X;
323     rects[3].h = font->w;
324
325     SDL_UpdateRect(screen, 0, 0, screen->w, screen->h);
326     //printf("rand=%s\n", b->rs->data);
327 }
328
329 void render(board_t b)
330 {
331
332     if(SDL_MUSTLOCK(screen))
333         if(SDL_LockSurface(screen) < 0)
334             return;
335
336     int x, y;
337    
338     /* on trace le plateau */
339     for(x = 0; x < b->xsize; ++x)
340         for(y = 0; y < b->ysize; ++y)
341         {
342
343             int xx = x * (GEMME_SIZE_X + GRID_WIDTH) + BOARD_START_X + GRID_WIDTH;
344             int yy = y * (GEMME_SIZE_Y + GRID_WIDTH) + BOARD_START_Y + GRID_WIDTH;
345
346             draw_gemme(board_pos(b, x, y), xx, yy);
347
348             if(x == sel_x && y == sel_y)
349                 draw_transparent_tile(screen, sel, 1,
350                                       GEMME_SIZE_Y, GEMME_SIZE_X,
351                                       xx, yy, 0x000000);
352             else if(x == over_x && y == over_y)
353                 draw_transparent_tile(screen, sel, 0,
354                                       GEMME_SIZE_Y, GEMME_SIZE_X,
355                                       xx, yy, 0x000000);
356
357         }
358
359     /* on trace le score etc */
360
361     char s[30];
362
363     sprintf(s, "%u", b->score);
364     draw_string(screen, font, screen->w - SCORE_POS_X,  SCORE_POS_Y + font->w, s);
365
366     sprintf(s, "%u", b->last_seg_count);
367     draw_rect(screen, rects[2].x, rects[2].y, rects[2].w, rects[2].h,  BGCOLOR);
368     draw_string(screen, font, screen->w - SCORE_POS_X,  SCORE_POS_Y + font->w * 5, s);
369
370     sprintf(s, "%u", total_seg_count);
371     draw_string(screen, font, screen->w - SCORE_POS_X,  SCORE_POS_Y + font->w * 8, s);
372
373     if(SDL_MUSTLOCK(screen))
374         SDL_UnlockSurface(screen);
375
376
377     /* update score,  board... rects */
378     SDL_UpdateRects(screen, RECT_COUNT, rects);
379
380 }
381
382 void draw_gemme(char gemme, int x, int y)
383 {
384
385         draw_tile2(screen, sgemmes,
386                   current_frame, ((gemme == ' ') ? 0 : (gemme - 'A' + 1)),
387                   GEMME_SIZE_Y,
388                   GEMME_SIZE_X,
389                   x, y);
390 }
391
392
393 void do_move(board_t b, int x, int y, int dir_x, int dir_y)
394 {
395     dir_t d;
396
397     if(x - dir_x == 1)
398         d = left;
399     else if(x - dir_x == -1)
400         d = right;
401     else if(y - dir_y == 1)
402         d = up;
403     else if(y - dir_y == -1)
404         d = down;
405
406     //printf("%c%d%c\n", x + 'A', y + 1, dir_to_string(d)[0]);
407
408     over_x = over_y = sel_x = sel_y = -1;
409
410     int ret = !board_move(b, x, y, d);
411
412     total_seg_count += b->last_seg_count;
413
414     if(ret && board_get_hint(b).x == -1) /* partie finie */
415     {
416         if(!b->silent)
417             fprintf(stderr,"Game over! Score %d\n", b->score);
418        
419         stop = 1;
420     }
421
422 }
423
424 void show_hint(board_t b)
425 {
426     coord_t c = board_get_hint(b);
427
428     c_assert(c.x != -1 && c.y != -1);
429
430     int old_sel_x = sel_x;
431     int old_sel_y = sel_y;
432
433     int i;
434     for(i = 1; i < 15; ++i)
435     {
436         if(i % 2 == 0)
437             sel_x = sel_y = -1;
438         else
439         {
440             sel_x = c.x;
441             sel_y = c.y;
442         }
443         changed = 1;
444         usleep(100000);
445     }
446
447     sel_x = old_sel_x;
448     sel_y = old_sel_y;
449 }
450
451
452 int thread_draw(void* d)
453 {
454     current_frame = 0;
455
456     int i = 0;
457     while(!stop)
458     {
459         if(changed)
460             render((board_t)d);
461
462         usleep(1000);
463
464         i++;
465
466         if(i > 15)
467         {
468             i = 0;
469             changed = 1;
470             current_frame++;
471             if(current_frame == GEMME_ANIM_COUNT)
472                 current_frame = 0;
473         }
474     }
475
476     return 0;
477 }
Note: See TracBrowser for help on using the browser.