~ubuntu-branches/ubuntu/maverick/gcompris/maverick

« back to all changes in this revision

Viewing changes to src/advanced_colors-activity/advanced_colors.c

  • Committer: Bazaar Package Importer
  • Author(s): Marc Gariepy, Marc Gariepy, Stephane Graber
  • Date: 2010-01-04 17:42:49 UTC
  • mfrom: (1.1.14 upstream)
  • Revision ID: james.westby@ubuntu.com-20100104174249-7bupatd9dtxyhvs4
Tags: 9.0-0ubuntu1
[Marc Gariepy]
* New upstream release (9.0).
* Remove cache.c from POTFILES to avoid FTBFS
* Remove unneeded rm in debian/rules (file no longer exists upstream)

[Stephane Graber]
* Bump Debian standards to 3.8.3
* Add patch system (dpatch)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* gcompris - advanced_colors.c
 
2
 *
 
3
 * Copyright (C) 2002, 2008 Pascal Georges
 
4
 *
 
5
 *   This program is free software; you can redistribute it and/or modify
 
6
 *   it under the terms of the GNU General Public License as published by
 
7
 *   the Free Software Foundation; either version 3 of the License, or
 
8
 *   (at your option) any later version.
 
9
 *
 
10
 *   This program is distributed in the hope that it will be useful,
 
11
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *   GNU General Public License for more details.
 
14
 *
 
15
 *   You should have received a copy of the GNU General Public License
 
16
 *   along with this program; if not, see <http://www.gnu.org/licenses/>.
 
17
 */
 
18
 
 
19
#include <string.h>
 
20
 
 
21
/* libxml includes */
 
22
#include <libxml/tree.h>
 
23
#include <libxml/parser.h>
 
24
 
 
25
#include "gcompris/gcompris.h"
 
26
 
 
27
#define SOUNDLISTFILE PACKAGE
 
28
 
 
29
static GcomprisBoard *gcomprisBoard = NULL;
 
30
static gboolean board_paused = TRUE;
 
31
 
 
32
static void              start_board (GcomprisBoard *agcomprisBoard);
 
33
static void              pause_board (gboolean pause);
 
34
static void              end_board (void);
 
35
static gboolean          is_our_board (GcomprisBoard *gcomprisBoard);
 
36
static int gamewon, errors;
 
37
 
 
38
static void              ok(void);
 
39
static void              highlight_selected(int);
 
40
static void              game_won(void);
 
41
static void              init_xml(void);
 
42
static gboolean          read_xml_file(char *fname);
 
43
 
 
44
/* ================================================================ */
 
45
static GooCanvasItem *boardRootItem = NULL;
 
46
static GooCanvasItem *highlight_image_item = NULL;
 
47
static GooCanvasItem *clock_image_item = NULL;
 
48
static GooCanvasItem *color_item = NULL;
 
49
 
 
50
static GooCanvasItem *colors_create_item(GooCanvasItem *parent);
 
51
static void colors_destroy_all_items(void);
 
52
static void colors_next_level(void);
 
53
static void set_level (guint);
 
54
static void update_clock();
 
55
static gboolean item_event (GooCanvasItem  *item,
 
56
                            GooCanvasItem  *target,
 
57
                            GdkEventButton *event,
 
58
                            gpointer data);
 
59
static int highlight_width, highlight_height;
 
60
static GList * listColors = NULL;
 
61
static gint timer_id = 0;
 
62
 
 
63
#define LAST_COLOR 8
 
64
#define LAST_BOARD 9
 
65
#define MAX_ERRORS 10
 
66
#define CLOCK_X 40
 
67
#define CLOCK_Y 420
 
68
 
 
69
 
 
70
static char* colors[LAST_COLOR];
 
71
static char *backgroundFile = NULL;
 
72
 
 
73
static int X[] = {57,229,236,389,413,567,573,744,
 
74
                  7,207,212,388,415,589,594,794};
 
75
static int Y[] = {158,255,268,380};
 
76
 
 
77
/* (x1,y1) and (x2, y2) are the coordinates of the rectangle where to
 
78
   draw the color's name */
 
79
static int color_x1 = 199, color_x2 = 582;
 
80
static int color_y1 = 47, color_y2 = 133;
 
81
 
 
82
/* Description of this plugin */
 
83
static BoardPlugin menu_bp =
 
84
  {
 
85
    NULL,
 
86
    NULL,
 
87
    "Advanced colors",
 
88
    "Click on the right color",
 
89
    "Pascal Georges pascal.georges1@free.fr>",
 
90
    NULL,
 
91
    NULL,
 
92
    NULL,
 
93
    NULL,
 
94
    start_board,
 
95
    pause_board,
 
96
    end_board,
 
97
    is_our_board,
 
98
    NULL,
 
99
    NULL,
 
100
    set_level,
 
101
    NULL,
 
102
    NULL,
 
103
    NULL,
 
104
    NULL
 
105
  };
 
106
 
 
107
/* =====================================================================
 
108
 *
 
109
 * =====================================================================*/
 
110
GET_BPLUGIN_INFO(advanced_colors)
 
111
 
 
112
/* =====================================================================
 
113
 * in : boolean TRUE = PAUSE : FALSE = CONTINUE
 
114
 * =====================================================================*/
 
115
static void pause_board (gboolean pause)
 
116
{
 
117
  if(gcomprisBoard==NULL)
 
118
    return;
 
119
 
 
120
  if (timer_id) {
 
121
    gtk_timeout_remove (timer_id);
 
122
    timer_id = 0;
 
123
  }
 
124
 
 
125
  if(gamewon == TRUE && pause == FALSE) /* the game is won */
 
126
    game_won();
 
127
 
 
128
  board_paused = pause;
 
129
}
 
130
 
 
131
/* =====================================================================
 
132
 *
 
133
 * =====================================================================*/
 
134
static void start_board (GcomprisBoard *agcomprisBoard) {
 
135
  if(agcomprisBoard!=NULL) {
 
136
    gcomprisBoard=agcomprisBoard;
 
137
    gcomprisBoard->level=1;
 
138
    gcomprisBoard->maxlevel=LAST_BOARD;
 
139
    gcomprisBoard->sublevel = 1;
 
140
    gcomprisBoard->number_of_sublevel = 8;
 
141
 
 
142
    gc_bar_set(GC_BAR_LEVEL);
 
143
    gc_score_start(SCORESTYLE_NOTE,
 
144
                   BOARDWIDTH - 195,
 
145
                   BOARDHEIGHT - 30,
 
146
                   gcomprisBoard->number_of_sublevel);
 
147
 
 
148
    gamewon = FALSE;
 
149
    errors = MAX_ERRORS;
 
150
    init_xml();
 
151
 
 
152
    g_signal_connect(goo_canvas_get_root_item(gcomprisBoard->canvas),
 
153
                     "button_press_event",
 
154
                     (GtkSignalFunc) item_event, NULL);
 
155
 
 
156
    colors_next_level();
 
157
    pause_board(FALSE);
 
158
  }
 
159
}
 
160
 
 
161
/* =====================================================================
 
162
 *
 
163
 * =====================================================================*/
 
164
static void end_board () {
 
165
 
 
166
  if(gcomprisBoard!=NULL){
 
167
    pause_board(TRUE);
 
168
    gc_score_end();
 
169
    colors_destroy_all_items();
 
170
    // free list
 
171
    while (g_list_length(listColors) > 0)
 
172
      listColors = g_list_remove(listColors, g_list_nth_data(listColors,0));
 
173
  }
 
174
  gcomprisBoard = NULL;
 
175
}
 
176
 
 
177
/* =====================================================================
 
178
 *
 
179
 * =====================================================================*/
 
180
static void set_level (guint level) {
 
181
  if(gcomprisBoard!=NULL) {
 
182
    gcomprisBoard->level=level;
 
183
    gcomprisBoard->sublevel=1;
 
184
    init_xml();
 
185
    colors_next_level();
 
186
  }
 
187
}
 
188
 
 
189
/* =====================================================================
 
190
 *
 
191
 * =====================================================================*/
 
192
static gboolean is_our_board (GcomprisBoard *gcomprisBoard) {
 
193
  if (gcomprisBoard) {
 
194
    if(g_strcasecmp(gcomprisBoard->type, "advanced_colors")==0) {
 
195
      /* Set the plugin entry */
 
196
      gcomprisBoard->plugin=&menu_bp;
 
197
      return TRUE;
 
198
    }
 
199
  }
 
200
  return FALSE;
 
201
}
 
202
/* =====================================================================
 
203
 * set initial values for the next level
 
204
 * =====================================================================*/
 
205
static void colors_next_level() {
 
206
  gchar *str = NULL;
 
207
  int i, list_length;
 
208
  GList * list = NULL;
 
209
  int * item;
 
210
 
 
211
  colors_destroy_all_items();
 
212
  gamewon = FALSE;
 
213
 
 
214
  gc_score_set(gcomprisBoard->sublevel);
 
215
  gc_bar_set_level(gcomprisBoard);
 
216
 
 
217
  /* initialize board only once*/
 
218
  if (gcomprisBoard->sublevel == 1) {
 
219
    // we generate a list of color indexes in a random order
 
220
    while (g_list_length(listColors) > 0)
 
221
      listColors = g_list_remove(listColors, g_list_nth_data(listColors,0));
 
222
 
 
223
    for (i=0; i<LAST_COLOR; i++)
 
224
      list = g_list_append(list, GINT_TO_POINTER(i));
 
225
 
 
226
    while((list_length = g_list_length(list))) {
 
227
      i = list_length == 1 ? 0 : g_random_int_range(0,g_list_length(list)-1);
 
228
      item = g_list_nth_data(list, i);
 
229
      listColors = g_list_append(listColors, item);
 
230
      list = g_list_remove(list, item);
 
231
    }
 
232
 
 
233
    /* set background */
 
234
    str = g_strdup_printf("%s/%s", gcomprisBoard->boarddir, backgroundFile);
 
235
    g_warning("background = %s\n", str);
 
236
    gc_set_background(goo_canvas_get_root_item(gcomprisBoard->canvas), str);
 
237
    g_free(str);
 
238
  }
 
239
 
 
240
  colors_create_item(goo_canvas_get_root_item(gcomprisBoard->canvas));
 
241
 
 
242
  /* show text of color to find */
 
243
  color_item = goo_canvas_text_new (boardRootItem,
 
244
                                    colors[GPOINTER_TO_INT(g_list_nth_data(listColors,0))],
 
245
                                    (color_x1+color_x2)/2,
 
246
                                    (color_y1+color_y2)/2,
 
247
                                    -1,
 
248
                                    GTK_ANCHOR_CENTER,
 
249
                                    "font", gc_skin_font_board_title_bold,
 
250
                                    "fill-color", "darkblue",
 
251
                                    NULL);
 
252
 
 
253
}
 
254
/* =====================================================================
 
255
 * Destroy all the items
 
256
 * =====================================================================*/
 
257
static void colors_destroy_all_items()
 
258
{
 
259
  if (timer_id) {
 
260
    gtk_timeout_remove (timer_id);
 
261
    timer_id = 0;
 
262
  }
 
263
 
 
264
  if(boardRootItem!=NULL)
 
265
    goo_canvas_item_remove(boardRootItem);
 
266
 
 
267
  boardRootItem = NULL;
 
268
}
 
269
 
 
270
/* =====================================================================
 
271
 *
 
272
 * =====================================================================*/
 
273
static GooCanvasItem *colors_create_item(GooCanvasItem *parent)
 
274
{
 
275
  GdkPixbuf *pixmap;
 
276
  char *str = NULL;
 
277
  int i;
 
278
 
 
279
  boardRootItem = goo_canvas_group_new (goo_canvas_get_root_item(gcomprisBoard->canvas),
 
280
                                        NULL);
 
281
 
 
282
 
 
283
  str = g_strdup_printf("%s/%s", gcomprisBoard->boarddir,
 
284
                        "highlight.png");
 
285
  pixmap = gc_pixmap_load(str);
 
286
 
 
287
  highlight_image_item = goo_canvas_image_new (boardRootItem,
 
288
                                               pixmap,
 
289
                                               0,
 
290
                                               0,
 
291
                                               NULL);
 
292
 
 
293
  highlight_width = gdk_pixbuf_get_width(pixmap);
 
294
  highlight_height = gdk_pixbuf_get_height(pixmap);
 
295
 
 
296
  g_free(str);
 
297
  g_object_set (highlight_image_item,
 
298
                "visibility", GOO_CANVAS_ITEM_INVISIBLE,
 
299
                NULL);
 
300
  i = g_random_int_range(0,LAST_COLOR);
 
301
 
 
302
  gdk_pixbuf_unref(pixmap);
 
303
 
 
304
  /* setup the clock */
 
305
  str = g_strdup_printf("%s%d.png", "timers/clock",errors);
 
306
  pixmap = gc_skin_pixmap_load(str);
 
307
 
 
308
  clock_image_item = goo_canvas_image_new (boardRootItem,
 
309
                                           pixmap,
 
310
                                           CLOCK_X,
 
311
                                           CLOCK_Y,
 
312
                                           NULL);
 
313
 
 
314
  gdk_pixbuf_unref(pixmap);
 
315
  g_free(str);
 
316
 
 
317
  return NULL;
 
318
}
 
319
/* =====================================================================
 
320
 *
 
321
 * =====================================================================*/
 
322
static void game_won() {
 
323
 
 
324
  listColors = g_list_remove(listColors, g_list_nth_data(listColors,0));
 
325
 
 
326
  if( g_list_length(listColors) <= 0 ) { // the current board is finished
 
327
    gcomprisBoard->level++;
 
328
    gcomprisBoard->sublevel = 1;
 
329
    if (gcomprisBoard->level > gcomprisBoard->maxlevel) {
 
330
      gcomprisBoard->level = gcomprisBoard->maxlevel;
 
331
      return;
 
332
    }
 
333
 
 
334
    init_xml();
 
335
  } else { // the current board is not finished
 
336
    gcomprisBoard->sublevel++;
 
337
  }
 
338
 
 
339
  colors_next_level();
 
340
}
 
341
/* =====================================================================
 
342
 *
 
343
 * =====================================================================*/
 
344
static gboolean ok_timeout()
 
345
{
 
346
  timer_id = 0;
 
347
  gc_bonus_display(gamewon, GC_BONUS_SMILEY);
 
348
  if (!gamewon)
 
349
    errors--;
 
350
  if (errors <1)
 
351
    errors = 1;
 
352
  update_clock();
 
353
 
 
354
  if (errors <= 1) {
 
355
    gamewon = TRUE;
 
356
    gc_bonus_display(gamewon, GC_BOARD_LOOSE);
 
357
  }
 
358
 
 
359
  return FALSE;
 
360
}
 
361
 
 
362
static void ok() {
 
363
  // leave time to display the right answer
 
364
  timer_id = g_timeout_add(TIME_CLICK_TO_BONUS, ok_timeout, NULL);
 
365
}
 
366
 
 
367
/* =====================================================================
 
368
 *
 
369
 * =====================================================================*/
 
370
static gboolean item_event (GooCanvasItem  *item,
 
371
                            GooCanvasItem  *target,
 
372
                            GdkEventButton *event,
 
373
                            gpointer data)
 
374
{
 
375
  double x, y;
 
376
  int i, j, clicked;
 
377
 
 
378
  x = event->x;
 
379
  y = event->y;
 
380
 
 
381
  if (!gcomprisBoard || board_paused)
 
382
    return FALSE;
 
383
 
 
384
  //goo_canvas_c2w (gcomprisBoard->canvas, x, y, &x, &y);
 
385
  clicked = -1;
 
386
  for (i=0; i<4; i++) {
 
387
    for (j=0; j<2; j++) {
 
388
      if (x>X[i*2] && x<X[i*2+1] && y>Y[j*2] && y<Y[j*2+1]) {
 
389
        clicked = j*4 + i;
 
390
      }
 
391
    }
 
392
  }
 
393
  if (clicked >= 0) {
 
394
    gc_sound_play_ogg ("sounds/bleep.wav", NULL);
 
395
    board_paused = TRUE;
 
396
    highlight_selected(clicked);
 
397
    gamewon = (clicked == GPOINTER_TO_INT(g_list_nth_data(listColors,0)));
 
398
    ok();
 
399
  }
 
400
 
 
401
  return FALSE;
 
402
}
 
403
 
 
404
/* =====================================================================
 
405
 *
 
406
 * =====================================================================*/
 
407
static void update_clock()
 
408
{
 
409
  GdkPixbuf *pixmap;
 
410
  char *str = g_strdup_printf("%s%d.png", "timers/clock", errors);
 
411
 
 
412
  pixmap = gc_skin_pixmap_load(str);
 
413
 
 
414
  g_object_set(clock_image_item,
 
415
               "pixbuf", pixmap,
 
416
               NULL);
 
417
 
 
418
  gdk_pixbuf_unref(pixmap);
 
419
  g_free(str);
 
420
}
 
421
/* =====================================================================
 
422
 *
 
423
 * =====================================================================*/
 
424
static void highlight_selected(int c)
 
425
{
 
426
  int x, y;
 
427
 
 
428
  g_assert(c>=0 && c<8);
 
429
 
 
430
  x = (X[c*2] + X[c*2+1]) /2;
 
431
  y = (Y[(int)(c/4)*2] + Y[(int)(c/4)*2+1]) /2;
 
432
 
 
433
  x -= highlight_width/2;
 
434
  y -= highlight_height;
 
435
  g_object_set (highlight_image_item,
 
436
                "visibility", GOO_CANVAS_ITEM_VISIBLE,
 
437
                NULL);
 
438
  gc_item_absolute_move(highlight_image_item, x, y);
 
439
}
 
440
 
 
441
/* ===================================
 
442
 *                XML stuff
 
443
 * ==================================== */
 
444
static void init_xml()
 
445
{
 
446
  char *filename;
 
447
 
 
448
  filename = gc_file_find_absolute("%s/board%d.xml",
 
449
                             gcomprisBoard->boarddir,
 
450
                             gcomprisBoard->level);
 
451
 
 
452
  g_assert(read_xml_file(filename)== TRUE);
 
453
 
 
454
  g_free(filename);
 
455
}
 
456
 
 
457
/* ==================================== */
 
458
static void add_xml_data(xmlDocPtr doc, xmlNodePtr xmlnode, GNode * child)
 
459
{
 
460
  char *text = NULL;
 
461
  char *sColor = NULL;
 
462
  int i;
 
463
 
 
464
  xmlnode = xmlnode->xmlChildrenNode;
 
465
 
 
466
  xmlnode = xmlnode->next;
 
467
 
 
468
  while (xmlnode != NULL)
 
469
    {
 
470
      if (!strcmp((char *)xmlnode->name, "pixmapfile"))
 
471
        backgroundFile = (char *)xmlNodeListGetString(doc, xmlnode->xmlChildrenNode, 1);
 
472
 
 
473
      // try to match color[i]
 
474
      for (i=0; i<8; i++)
 
475
        {
 
476
          sColor = g_strdup_printf("color%d", i+1);
 
477
          if (!strcmp((char *)xmlnode->name, sColor))
 
478
            {
 
479
              text = (char*)xmlNodeListGetString(doc, xmlnode->xmlChildrenNode, 1);
 
480
              if(text)
 
481
                {
 
482
                  colors[i] = gettext((char *)text);
 
483
                  // We got a translation, free the original value
 
484
                  if ( text != colors[i] )
 
485
                    g_free(text);
 
486
                }
 
487
              text = NULL;
 
488
              g_free(sColor);
 
489
              break;
 
490
            }
 
491
          g_free(sColor);
 
492
        } // end for
 
493
      xmlnode = xmlnode->next;
 
494
    }
 
495
 
 
496
  // I really don't know why this test, but otherwise, the list is doubled
 
497
  // with 1 line on 2 filled with NULL elements
 
498
  if ( backgroundFile == NULL || text == NULL)
 
499
    return;
 
500
 
 
501
}
 
502
 
 
503
/* ==================================== */
 
504
static void parse_doc(xmlDocPtr doc)
 
505
{
 
506
  xmlNodePtr node;
 
507
 
 
508
  for(node = doc->children->children; node != NULL; node = node->next) {
 
509
    if ( g_strcasecmp((char *)node->name, "Board") == 0 )
 
510
      add_xml_data(doc, node, NULL);
 
511
  }
 
512
 
 
513
}
 
514
/* ==================================== */
 
515
/* read an xml file into our memory structures and update our view,
 
516
   dump any old data we have in memory if we can load a new set */
 
517
static gboolean read_xml_file(char *fname)
 
518
{
 
519
  /* pointer to the new doc */
 
520
  xmlDocPtr doc;
 
521
 
 
522
  g_return_val_if_fail(fname!=NULL,FALSE);
 
523
 
 
524
  /* parse the new file and put the result into newdoc */
 
525
  doc = xmlParseFile(fname);
 
526
 
 
527
  /* in case something went wrong */
 
528
  if(!doc)
 
529
    return FALSE;
 
530
 
 
531
  if(/* if there is no root element */
 
532
     !doc->children ||
 
533
     /* if it doesn't have a name */
 
534
     !doc->children->name ||
 
535
     /* if it isn't a ImageId node */
 
536
     g_strcasecmp((char *)doc->children->name,"AdvancedColors")!=0) {
 
537
    xmlFreeDoc(doc);
 
538
    return FALSE;
 
539
  }
 
540
 
 
541
  parse_doc(doc);
 
542
  xmlFreeDoc(doc);
 
543
  return TRUE;
 
544
}
 
545