1
/* gcompris - enumerate.c
3
* Copyright (C) 2001 Bruno Coudoin
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/>.
21
#include "gcompris/gcompris.h"
23
#define SOUNDLISTFILE PACKAGE
25
static GcomprisBoard *gcomprisBoard = NULL;
26
static gboolean board_paused = TRUE;
28
static void start_board (GcomprisBoard *agcomprisBoard);
29
static gint key_press(guint keyval, gchar *commit_str, gchar *preedit_str);
30
static void pause_board (gboolean pause);
31
static void end_board (void);
32
static void process_ok(void);
33
static gboolean is_our_board (GcomprisBoard *gcomprisBoard);
34
static void set_level (guint level);
36
static void game_won(void);
38
static GnomeCanvasGroup *boardRootItem = NULL;
40
static GnomeCanvasItem *enumerate_create_item(GnomeCanvasGroup *parent);
41
static void enumerate_destroy_all_items(void);
42
static void enumerate_next_level(void);
43
static gint item_event(GnomeCanvasItem *item, GdkEvent *event, gpointer data);
44
static gint item_event_focus(GnomeCanvasItem *item, GdkEvent *event, guint index);
46
#define ANSWER_X BOARDWIDTH - 150
47
#define ANSWER_WIDTH 40
48
#define ANSWER_HEIGHT 40
50
static int number_of_item_type = 0;
51
static int number_of_item_max = 0;
53
// List of images to use in the game
54
static gchar *imageList[] =
56
"gcompris/food/banana.png",
57
"gcompris/food/orange.png",
58
"gcompris/food/milk_shake.png",
59
"gcompris/food/pear.png",
60
"gcompris/food/grapefruit.png",
61
"gcompris/food/yahourt.png",
62
"gcompris/food/milk_cup.png",
63
"gcompris/food/suggar_box.png",
64
"gcompris/food/butter.png",
65
"gcompris/food/chocolate.png",
66
"gcompris/food/cookie.png",
67
"gcompris/food/french_croissant.png",
68
"gcompris/food/chocolate_cake.png",
69
"gcompris/food/marmelade.png",
70
"gcompris/food/baby_bottle.png",
71
"gcompris/food/bread_slice.png",
72
"gcompris/food/round_cookie.png",
74
#define NUMBER_OF_IMAGES G_N_ELEMENTS(imageList)
76
static guint answer[NUMBER_OF_IMAGES];
77
static guint answer_to_find[NUMBER_OF_IMAGES];
78
static GnomeCanvasItem *answer_item[NUMBER_OF_IMAGES];
79
static GnomeCanvasItem *answer_item_focus[NUMBER_OF_IMAGES];
80
static guint current_focus = 0;
83
/* Description of this plugin */
84
static BoardPlugin menu_bp =
88
N_("Numeration training"),
89
N_("Place the items in the best way to count them"),
90
"Bruno Coudoin <bruno.coudoin@free.fr>",
109
* Main entry point mandatory for each Gcompris's game
110
* ---------------------------------------------------
114
GET_BPLUGIN_INFO(enumerate)
117
* in : boolean TRUE = PAUSE : FALSE = CONTINUE
120
static void pause_board (gboolean pause)
122
if(gcomprisBoard==NULL)
125
if(gamewon == TRUE && pause == FALSE) /* the game is won */
130
board_paused = pause;
135
static void start_board (GcomprisBoard *agcomprisBoard)
138
if(agcomprisBoard!=NULL)
140
gcomprisBoard=agcomprisBoard;
142
/* disable im_context */
143
gcomprisBoard->disable_im_context = TRUE;
145
gcomprisBoard->level=1;
146
gcomprisBoard->maxlevel=9;
147
gcomprisBoard->sublevel=1;
148
gcomprisBoard->number_of_sublevel=1; /* Go to next level after this number of 'play' */
149
gc_bar_set(GC_BAR_LEVEL|GC_BAR_OK);
151
gc_set_background(gnome_canvas_root(gcomprisBoard->canvas),
152
"opt/enumerate_background.png");
154
enumerate_next_level();
160
/* ======================================= */
161
static void end_board ()
163
if(gcomprisBoard!=NULL)
166
enumerate_destroy_all_items();
168
gcomprisBoard = NULL;
171
/* Get the user keys to use to get the answer */
172
static gint key_press(guint keyval, gchar *commit_str, gchar *preedit_str)
175
GnomeCanvasItem *item = NULL;
177
if(board_paused || !boardRootItem || !gcomprisBoard)
180
/* Add some filter for control and shift key */
197
case GDK_Mode_switch:
198
case GDK_dead_circumflex:
207
sprintf(str, "%c", keyval);
209
item = answer_item[current_focus];
211
if(GNOME_IS_CANVAS_TEXT(item))
216
gtk_object_get (GTK_OBJECT (item), "text", &oldtext, NULL);
223
if(oldtext[1] != '\0')
224
newtext = g_strndup(oldtext, strlen(oldtext)-1);
232
if(keyval<'0' || keyval>'9')
235
if(oldtext[0] == '?' && strlen(oldtext)==1)
241
if(strlen(oldtext)<2)
242
newtext = g_strconcat(oldtext, &str, NULL);
244
newtext = g_strdup(oldtext);
249
if(newtext[0] != '?')
250
answer[current_focus] = atoi(newtext);
252
gnome_canvas_item_set (item,
262
/* ======================================= */
263
static void set_level (guint level)
266
if(gcomprisBoard!=NULL)
268
gcomprisBoard->level=level;
269
gcomprisBoard->sublevel=1;
270
enumerate_next_level();
273
/* ======================================= */
274
static gboolean is_our_board (GcomprisBoard *gcomprisBoard)
278
if(g_strcasecmp(gcomprisBoard->type, "enumerate")==0)
280
/* Set the plugin entry */
281
gcomprisBoard->plugin=&menu_bp;
289
/*-------------------------------------------------------------------------------*/
290
/*-------------------------------------------------------------------------------*/
291
/* set initial values for the next level */
292
static void enumerate_next_level()
295
gc_bar_set_level(gcomprisBoard);
297
enumerate_destroy_all_items();
300
/* Select level difficulty */
301
switch(gcomprisBoard->level)
304
number_of_item_type = 1;
305
number_of_item_max = 5;
308
number_of_item_type = 2;
309
number_of_item_max = 5;
312
number_of_item_type = 3;
313
number_of_item_max = 5;
316
number_of_item_type = 3;
317
number_of_item_max = 5;
320
number_of_item_type = 4;
321
number_of_item_max = 5;
324
number_of_item_type = 4;
325
number_of_item_max = 6;
328
number_of_item_type = 4;
329
number_of_item_max = 7;
332
number_of_item_type = 4;
333
number_of_item_max = 10;
336
number_of_item_type = 5;
337
number_of_item_max = 10;
342
/* Try the next level */
343
enumerate_create_item(gnome_canvas_root(gcomprisBoard->canvas));
346
/* ==================================== */
347
/* Destroy all the items */
348
static void enumerate_destroy_all_items()
350
if(boardRootItem!=NULL)
351
gtk_object_destroy (GTK_OBJECT(boardRootItem));
353
boardRootItem = NULL;
355
/* ==================================== */
356
static GnomeCanvasItem *enumerate_create_item(GnomeCanvasGroup *parent)
360
GnomeCanvasItem *item = NULL;
361
GdkPixbuf *pixmap = NULL;
362
GdkPixbuf *pixmap_answer = NULL;
364
boardRootItem = GNOME_CANVAS_GROUP(
365
gnome_canvas_item_new (gnome_canvas_root(gcomprisBoard->canvas),
366
gnome_canvas_group_get_type (),
372
current_y = BOARDHEIGHT;
374
for(i=0; i<number_of_item_type; i++)
377
pixmap = gc_pixmap_load(imageList[i]);
379
answer_to_find[i] = g_random_int_range(1, number_of_item_max);
382
for(j=0; j<answer_to_find[i]; j++)
386
x = g_random_int_range(0, ANSWER_X-gdk_pixbuf_get_width(pixmap)-ANSWER_WIDTH);
387
y = g_random_int_range(0, BOARDHEIGHT-gdk_pixbuf_get_height(pixmap));
389
item = gnome_canvas_item_new (boardRootItem,
390
gnome_canvas_pixbuf_get_type (),
396
gtk_signal_connect(GTK_OBJECT(item), "event", (GtkSignalFunc) item_event, NULL);
399
/* Display the answer area */
400
current_y -= ANSWER_HEIGHT*2;
402
pixmap_answer = gc_pixmap_load("images/enumerate_answer_focus.png");
405
gnome_canvas_item_new (boardRootItem,
406
gnome_canvas_pixbuf_get_type (),
407
"pixbuf", pixmap_answer,
408
"x", (double) ANSWER_X - ANSWER_WIDTH/2,
409
"y", (double) current_y - ANSWER_HEIGHT/2,
412
gtk_signal_connect(GTK_OBJECT(item), "event", (GtkSignalFunc) item_event_focus, GINT_TO_POINTER(i));
414
gdk_pixbuf_unref(pixmap_answer);
416
pixmap_answer = gc_pixmap_load("images/enumerate_answer.png");
418
answer_item_focus[i] = \
419
gnome_canvas_item_new (boardRootItem,
420
gnome_canvas_pixbuf_get_type (),
421
"pixbuf", pixmap_answer,
422
"x", (double) ANSWER_X - ANSWER_WIDTH/2,
423
"y", (double) current_y - ANSWER_HEIGHT/2,
426
gdk_pixbuf_unref(pixmap_answer);
427
gnome_canvas_item_hide(answer_item_focus[i]);
429
item = gnome_canvas_item_new (boardRootItem,
430
gnome_canvas_pixbuf_get_type (),
432
"x", (double) ANSWER_X,
433
"y", (double) current_y,
434
"width", (double) gdk_pixbuf_get_width(pixmap)*ANSWER_HEIGHT/gdk_pixbuf_get_height(pixmap),
435
"height", (double) ANSWER_HEIGHT,
440
gdk_pixbuf_unref(pixmap);
442
gtk_signal_connect(GTK_OBJECT(item), "event", (GtkSignalFunc) item_event_focus, GINT_TO_POINTER(i));
444
gtk_signal_connect(GTK_OBJECT(item), "event",
445
(GtkSignalFunc) gc_item_focus_event,
449
gnome_canvas_item_new (boardRootItem,
450
gnome_canvas_text_get_type (),
452
"font", gc_skin_font_board_big,
453
"x", (double) ANSWER_X + 2.5*ANSWER_WIDTH,
454
"y", (double) current_y + ANSWER_HEIGHT/2,
455
"anchor", GTK_ANCHOR_EAST,
456
"fill_color", "blue",
458
gtk_signal_connect(GTK_OBJECT(answer_item[i]), "event", (GtkSignalFunc) item_event_focus,
463
gnome_canvas_item_show(answer_item_focus[current_focus]);
467
/* ==================================== */
468
static void game_won()
470
gcomprisBoard->sublevel++;
472
if(gcomprisBoard->sublevel>gcomprisBoard->number_of_sublevel) {
473
/* Try the next level */
474
gcomprisBoard->sublevel=1;
475
gcomprisBoard->level++;
476
if(gcomprisBoard->level>gcomprisBoard->maxlevel) { // the current board is finished : bail out
477
gc_bonus_end_display(GC_BOARD_FINISHED_RANDOM);
480
gc_sound_play_ogg ("sounds/bonus.wav", NULL);
482
enumerate_next_level();
485
/* ==================================== */
487
item_event_focus(GnomeCanvasItem *item, GdkEvent *event, guint index)
492
case GDK_BUTTON_PRESS:
493
gc_sound_play_ogg ("sounds/prompt.wav", NULL);
494
gnome_canvas_item_hide(answer_item_focus[current_focus]);
495
current_focus = index;
496
gnome_canvas_item_show(answer_item_focus[current_focus]);
506
/* ==================================== */
508
item_event(GnomeCanvasItem *item, GdkEvent *event, gpointer data)
511
double item_x, item_y;
516
item_x = event->button.x;
517
item_y = event->button.y;
518
gnome_canvas_item_w2i(item->parent, &item_x, &item_y);
526
case GDK_BUTTON_PRESS:
527
switch(event->button.button)
530
gc_sound_play_ogg ("sounds/bleep.wav", NULL);
534
gnome_canvas_item_raise_to_top(item);
536
fleur = gdk_cursor_new(GDK_FLEUR);
537
gc_canvas_item_grab(item,
538
GDK_POINTER_MOTION_MASK |
539
GDK_BUTTON_RELEASE_MASK,
542
gdk_cursor_destroy(fleur);
549
gnome_canvas_item_move(item, 0.0, -3.0);
555
gnome_canvas_item_move(item, 0.0, 3.0);
563
case GDK_MOTION_NOTIFY:
564
if (dragging && (event->motion.state & GDK_BUTTON1_MASK))
566
double x1, x2, y1, y2;
568
gnome_canvas_item_get_bounds(item, &x1, &y1, &x2, &y2);
573
/* Check board boundaries */
574
if((x1 < 0 && new_x<x)|| (x2 > BOARDWIDTH && new_x>x))
578
if((y1 < 0 && new_y<y) || (y2 > BOARDHEIGHT && new_y>y))
583
gnome_canvas_item_move(item, new_x - x, new_y - y);
589
case GDK_BUTTON_RELEASE:
592
gc_canvas_item_ungrab(item, event->button.time);
604
static void process_ok()
609
for(i=0; i<number_of_item_type; i++)
611
if(answer[i] != answer_to_find[i])
617
gc_bonus_display(gamewon, GC_BONUS_SMILEY);
620
gc_bonus_display(gamewon, GC_BONUS_SMILEY);