1
/* gcompris - advanced_colors.c
3
* Copyright (C) 2002, 2008 Pascal Georges
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.
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.
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/>.
22
#include <libxml/tree.h>
23
#include <libxml/parser.h>
25
#include "gcompris/gcompris.h"
27
#define SOUNDLISTFILE PACKAGE
29
static GcomprisBoard *gcomprisBoard = NULL;
30
static gboolean board_paused = TRUE;
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;
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);
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;
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,
59
static int highlight_width, highlight_height;
60
static GList * listColors = NULL;
61
static gint timer_id = 0;
70
static char* colors[LAST_COLOR];
71
static char *backgroundFile = NULL;
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};
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;
82
/* Description of this plugin */
83
static BoardPlugin menu_bp =
88
"Click on the right color",
89
"Pascal Georges pascal.georges1@free.fr>",
107
/* =====================================================================
109
* =====================================================================*/
110
GET_BPLUGIN_INFO(advanced_colors)
112
/* =====================================================================
113
* in : boolean TRUE = PAUSE : FALSE = CONTINUE
114
* =====================================================================*/
115
static void pause_board (gboolean pause)
117
if(gcomprisBoard==NULL)
121
gtk_timeout_remove (timer_id);
125
if(gamewon == TRUE && pause == FALSE) /* the game is won */
128
board_paused = pause;
131
/* =====================================================================
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;
142
gc_bar_set(GC_BAR_LEVEL);
143
gc_score_start(SCORESTYLE_NOTE,
146
gcomprisBoard->number_of_sublevel);
152
g_signal_connect(goo_canvas_get_root_item(gcomprisBoard->canvas),
153
"button_press_event",
154
(GtkSignalFunc) item_event, NULL);
161
/* =====================================================================
163
* =====================================================================*/
164
static void end_board () {
166
if(gcomprisBoard!=NULL){
169
colors_destroy_all_items();
171
while (g_list_length(listColors) > 0)
172
listColors = g_list_remove(listColors, g_list_nth_data(listColors,0));
174
gcomprisBoard = NULL;
177
/* =====================================================================
179
* =====================================================================*/
180
static void set_level (guint level) {
181
if(gcomprisBoard!=NULL) {
182
gcomprisBoard->level=level;
183
gcomprisBoard->sublevel=1;
189
/* =====================================================================
191
* =====================================================================*/
192
static gboolean is_our_board (GcomprisBoard *gcomprisBoard) {
194
if(g_strcasecmp(gcomprisBoard->type, "advanced_colors")==0) {
195
/* Set the plugin entry */
196
gcomprisBoard->plugin=&menu_bp;
202
/* =====================================================================
203
* set initial values for the next level
204
* =====================================================================*/
205
static void colors_next_level() {
211
colors_destroy_all_items();
214
gc_score_set(gcomprisBoard->sublevel);
215
gc_bar_set_level(gcomprisBoard);
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));
223
for (i=0; i<LAST_COLOR; i++)
224
list = g_list_append(list, GINT_TO_POINTER(i));
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);
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);
240
colors_create_item(goo_canvas_get_root_item(gcomprisBoard->canvas));
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,
249
"font", gc_skin_font_board_title_bold,
250
"fill-color", "darkblue",
254
/* =====================================================================
255
* Destroy all the items
256
* =====================================================================*/
257
static void colors_destroy_all_items()
260
gtk_timeout_remove (timer_id);
264
if(boardRootItem!=NULL)
265
goo_canvas_item_remove(boardRootItem);
267
boardRootItem = NULL;
270
/* =====================================================================
272
* =====================================================================*/
273
static GooCanvasItem *colors_create_item(GooCanvasItem *parent)
279
boardRootItem = goo_canvas_group_new (goo_canvas_get_root_item(gcomprisBoard->canvas),
283
str = g_strdup_printf("%s/%s", gcomprisBoard->boarddir,
285
pixmap = gc_pixmap_load(str);
287
highlight_image_item = goo_canvas_image_new (boardRootItem,
293
highlight_width = gdk_pixbuf_get_width(pixmap);
294
highlight_height = gdk_pixbuf_get_height(pixmap);
297
g_object_set (highlight_image_item,
298
"visibility", GOO_CANVAS_ITEM_INVISIBLE,
300
i = g_random_int_range(0,LAST_COLOR);
302
gdk_pixbuf_unref(pixmap);
304
/* setup the clock */
305
str = g_strdup_printf("%s%d.png", "timers/clock",errors);
306
pixmap = gc_skin_pixmap_load(str);
308
clock_image_item = goo_canvas_image_new (boardRootItem,
314
gdk_pixbuf_unref(pixmap);
319
/* =====================================================================
321
* =====================================================================*/
322
static void game_won() {
324
listColors = g_list_remove(listColors, g_list_nth_data(listColors,0));
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;
335
} else { // the current board is not finished
336
gcomprisBoard->sublevel++;
341
/* =====================================================================
343
* =====================================================================*/
344
static gboolean ok_timeout()
347
gc_bonus_display(gamewon, GC_BONUS_SMILEY);
356
gc_bonus_display(gamewon, GC_BOARD_LOOSE);
363
// leave time to display the right answer
364
timer_id = g_timeout_add(TIME_CLICK_TO_BONUS, ok_timeout, NULL);
367
/* =====================================================================
369
* =====================================================================*/
370
static gboolean item_event (GooCanvasItem *item,
371
GooCanvasItem *target,
372
GdkEventButton *event,
381
if (!gcomprisBoard || board_paused)
384
//goo_canvas_c2w (gcomprisBoard->canvas, x, y, &x, &y);
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]) {
394
gc_sound_play_ogg ("sounds/bleep.wav", NULL);
396
highlight_selected(clicked);
397
gamewon = (clicked == GPOINTER_TO_INT(g_list_nth_data(listColors,0)));
404
/* =====================================================================
406
* =====================================================================*/
407
static void update_clock()
410
char *str = g_strdup_printf("%s%d.png", "timers/clock", errors);
412
pixmap = gc_skin_pixmap_load(str);
414
g_object_set(clock_image_item,
418
gdk_pixbuf_unref(pixmap);
421
/* =====================================================================
423
* =====================================================================*/
424
static void highlight_selected(int c)
428
g_assert(c>=0 && c<8);
430
x = (X[c*2] + X[c*2+1]) /2;
431
y = (Y[(int)(c/4)*2] + Y[(int)(c/4)*2+1]) /2;
433
x -= highlight_width/2;
434
y -= highlight_height;
435
g_object_set (highlight_image_item,
436
"visibility", GOO_CANVAS_ITEM_VISIBLE,
438
gc_item_absolute_move(highlight_image_item, x, y);
441
/* ===================================
443
* ==================================== */
444
static void init_xml()
448
filename = gc_file_find_absolute("%s/board%d.xml",
449
gcomprisBoard->boarddir,
450
gcomprisBoard->level);
452
g_assert(read_xml_file(filename)== TRUE);
457
/* ==================================== */
458
static void add_xml_data(xmlDocPtr doc, xmlNodePtr xmlnode, GNode * child)
464
xmlnode = xmlnode->xmlChildrenNode;
466
xmlnode = xmlnode->next;
468
while (xmlnode != NULL)
470
if (!strcmp((char *)xmlnode->name, "pixmapfile"))
471
backgroundFile = (char *)xmlNodeListGetString(doc, xmlnode->xmlChildrenNode, 1);
473
// try to match color[i]
476
sColor = g_strdup_printf("color%d", i+1);
477
if (!strcmp((char *)xmlnode->name, sColor))
479
text = (char*)xmlNodeListGetString(doc, xmlnode->xmlChildrenNode, 1);
482
colors[i] = gettext((char *)text);
483
// We got a translation, free the original value
484
if ( text != colors[i] )
493
xmlnode = xmlnode->next;
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)
503
/* ==================================== */
504
static void parse_doc(xmlDocPtr doc)
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);
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)
519
/* pointer to the new doc */
522
g_return_val_if_fail(fname!=NULL,FALSE);
524
/* parse the new file and put the result into newdoc */
525
doc = xmlParseFile(fname);
527
/* in case something went wrong */
531
if(/* if there is no root element */
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) {