/* gcompris - enumerate.c * * Copyright (C) 2001 Bruno Coudoin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ #include #include "gcompris/gcompris.h" #define SOUNDLISTFILE PACKAGE static GcomprisBoard *gcomprisBoard = NULL; static gboolean board_paused = TRUE; static void start_board (GcomprisBoard *agcomprisBoard); static gint key_press(guint keyval, gchar *commit_str, gchar *preedit_str); static void pause_board (gboolean pause); static void end_board (void); static void process_ok(void); static gboolean is_our_board (GcomprisBoard *gcomprisBoard); static void set_level (guint level); static int gamewon; static void game_won(void); static GnomeCanvasGroup *boardRootItem = NULL; static GnomeCanvasItem *enumerate_create_item(GnomeCanvasGroup *parent); static void enumerate_destroy_all_items(void); static void enumerate_next_level(void); static gint item_event(GnomeCanvasItem *item, GdkEvent *event, gpointer data); static gint item_event_focus(GnomeCanvasItem *item, GdkEvent *event, guint index); #define ANSWER_X BOARDWIDTH - 150 #define ANSWER_WIDTH 40 #define ANSWER_HEIGHT 40 static int number_of_item_type = 0; static int number_of_item_max = 0; // List of images to use in the game static gchar *imageList[] = { "gcompris/food/banana.png", "gcompris/food/orange.png", "gcompris/food/milk_shake.png", "gcompris/food/pear.png", "gcompris/food/grapefruit.png", "gcompris/food/yahourt.png", "gcompris/food/milk_cup.png", "gcompris/food/suggar_box.png", "gcompris/food/butter.png", "gcompris/food/chocolate.png", "gcompris/food/cookie.png", "gcompris/food/french_croissant.png", "gcompris/food/chocolate_cake.png", "gcompris/food/marmelade.png", "gcompris/food/baby_bottle.png", "gcompris/food/bread_slice.png", "gcompris/food/round_cookie.png", }; #define NUMBER_OF_IMAGES G_N_ELEMENTS(imageList) static guint answer[NUMBER_OF_IMAGES]; static guint answer_to_find[NUMBER_OF_IMAGES]; static GnomeCanvasItem *answer_item[NUMBER_OF_IMAGES]; static GnomeCanvasItem *answer_item_focus[NUMBER_OF_IMAGES]; static guint current_focus = 0; /* Description of this plugin */ static BoardPlugin menu_bp = { NULL, NULL, N_("Numeration training"), N_("Place the items in the best way to count them"), "Bruno Coudoin ", NULL, NULL, NULL, NULL, start_board, pause_board, end_board, is_our_board, key_press, process_ok, set_level, NULL, NULL, NULL, NULL }; /* * Main entry point mandatory for each Gcompris's game * --------------------------------------------------- * */ GET_BPLUGIN_INFO(enumerate) /* * in : boolean TRUE = PAUSE : FALSE = CONTINUE * */ static void pause_board (gboolean pause) { if(gcomprisBoard==NULL) return; if(gamewon == TRUE && pause == FALSE) /* the game is won */ { game_won(); } board_paused = pause; } /* */ static void start_board (GcomprisBoard *agcomprisBoard) { if(agcomprisBoard!=NULL) { gcomprisBoard=agcomprisBoard; /* disable im_context */ gcomprisBoard->disable_im_context = TRUE; gcomprisBoard->level=1; gcomprisBoard->maxlevel=9; gcomprisBoard->sublevel=1; gcomprisBoard->number_of_sublevel=1; /* Go to next level after this number of 'play' */ gc_bar_set(GC_BAR_LEVEL|GC_BAR_OK); gc_set_background(gnome_canvas_root(gcomprisBoard->canvas), "opt/enumerate_background.png"); enumerate_next_level(); gamewon = FALSE; pause_board(FALSE); } } /* ======================================= */ static void end_board () { if(gcomprisBoard!=NULL) { pause_board(TRUE); enumerate_destroy_all_items(); } gcomprisBoard = NULL; } /* Get the user keys to use to get the answer */ static gint key_press(guint keyval, gchar *commit_str, gchar *preedit_str) { char str[2]; GnomeCanvasItem *item = NULL; if(board_paused || !boardRootItem || !gcomprisBoard) return FALSE; /* Add some filter for control and shift key */ switch (keyval) { case GDK_Shift_L: case GDK_Shift_R: case GDK_Control_L: case GDK_Control_R: case GDK_Caps_Lock: case GDK_Shift_Lock: case GDK_Meta_L: case GDK_Meta_R: case GDK_Alt_L: case GDK_Alt_R: case GDK_Super_L: case GDK_Super_R: case GDK_Hyper_L: case GDK_Hyper_R: case GDK_Mode_switch: case GDK_dead_circumflex: case GDK_Num_Lock: return FALSE; case GDK_KP_Enter: case GDK_Return: process_ok(); return TRUE; } sprintf(str, "%c", keyval); item = answer_item[current_focus]; if(GNOME_IS_CANVAS_TEXT(item)) { gchar *oldtext; gchar *newtext; gtk_object_get (GTK_OBJECT (item), "text", &oldtext, NULL); switch(keyval) { case GDK_BackSpace: case GDK_Delete: if(oldtext[1] != '\0') newtext = g_strndup(oldtext, strlen(oldtext)-1); else newtext = "?"; break; default: if(keyval<'0' || keyval>'9') str[0]='0'; if(oldtext[0] == '?' && strlen(oldtext)==1) { oldtext[0] = ' '; g_strstrip(oldtext); } if(strlen(oldtext)<2) newtext = g_strconcat(oldtext, &str, NULL); else newtext = g_strdup(oldtext); break; } if(newtext[0] != '?') answer[current_focus] = atoi(newtext); gnome_canvas_item_set (item, "text", newtext, NULL); g_free(oldtext); } return TRUE; } /* ======================================= */ static void set_level (guint level) { if(gcomprisBoard!=NULL) { gcomprisBoard->level=level; gcomprisBoard->sublevel=1; enumerate_next_level(); } } /* ======================================= */ static gboolean is_our_board (GcomprisBoard *gcomprisBoard) { if (gcomprisBoard) { if(g_strcasecmp(gcomprisBoard->type, "enumerate")==0) { /* Set the plugin entry */ gcomprisBoard->plugin=&menu_bp; return TRUE; } } return FALSE; } /*-------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------*/ /* set initial values for the next level */ static void enumerate_next_level() { gc_bar_set_level(gcomprisBoard); enumerate_destroy_all_items(); gamewon = FALSE; /* Select level difficulty */ switch(gcomprisBoard->level) { case 1: number_of_item_type = 1; number_of_item_max = 5; break; case 2: number_of_item_type = 2; number_of_item_max = 5; break; case 3: number_of_item_type = 3; number_of_item_max = 5; break; case 4: number_of_item_type = 3; number_of_item_max = 5; break; case 5: number_of_item_type = 4; number_of_item_max = 5; break; case 6: number_of_item_type = 4; number_of_item_max = 6; break; case 7: number_of_item_type = 4; number_of_item_max = 7; break; case 8: number_of_item_type = 4; number_of_item_max = 10; break; default: number_of_item_type = 5; number_of_item_max = 10; } current_focus = 0; /* Try the next level */ enumerate_create_item(gnome_canvas_root(gcomprisBoard->canvas)); } /* ==================================== */ /* Destroy all the items */ static void enumerate_destroy_all_items() { if(boardRootItem!=NULL) gtk_object_destroy (GTK_OBJECT(boardRootItem)); boardRootItem = NULL; } /* ==================================== */ static GnomeCanvasItem *enumerate_create_item(GnomeCanvasGroup *parent) { int i,j; int current_y; GnomeCanvasItem *item = NULL; GdkPixbuf *pixmap = NULL; GdkPixbuf *pixmap_answer = NULL; boardRootItem = GNOME_CANVAS_GROUP( gnome_canvas_item_new (gnome_canvas_root(gcomprisBoard->canvas), gnome_canvas_group_get_type (), "x", (double) 0, "y", (double) 0, NULL)); current_y = BOARDHEIGHT; for(i=0; isublevel++; if(gcomprisBoard->sublevel>gcomprisBoard->number_of_sublevel) { /* Try the next level */ gcomprisBoard->sublevel=1; gcomprisBoard->level++; if(gcomprisBoard->level>gcomprisBoard->maxlevel) { // the current board is finished : bail out gc_bonus_end_display(GC_BOARD_FINISHED_RANDOM); return; } gc_sound_play_ogg ("sounds/bonus.wav", NULL); } enumerate_next_level(); } /* ==================================== */ static gint item_event_focus(GnomeCanvasItem *item, GdkEvent *event, guint index) { switch (event->type) { case GDK_BUTTON_PRESS: gc_sound_play_ogg ("sounds/prompt.wav", NULL); gnome_canvas_item_hide(answer_item_focus[current_focus]); current_focus = index; gnome_canvas_item_show(answer_item_focus[current_focus]); return TRUE; break; default: break; } return FALSE; } /* ==================================== */ static gint item_event(GnomeCanvasItem *item, GdkEvent *event, gpointer data) { static double x, y; double item_x, item_y; GdkCursor *fleur; static int dragging; double new_x, new_y; item_x = event->button.x; item_y = event->button.y; gnome_canvas_item_w2i(item->parent, &item_x, &item_y); if(board_paused) return FALSE; switch (event->type) { case GDK_BUTTON_PRESS: switch(event->button.button) { case 1: gc_sound_play_ogg ("sounds/bleep.wav", NULL); x = item_x; y = item_y; gnome_canvas_item_raise_to_top(item); fleur = gdk_cursor_new(GDK_FLEUR); gc_canvas_item_grab(item, GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, fleur, event->button.time); gdk_cursor_destroy(fleur); dragging = TRUE; break; case 3: case 4: /* fish up */ gnome_canvas_item_move(item, 0.0, -3.0); break; case 2: case 5: /* fish down */ gnome_canvas_item_move(item, 0.0, 3.0); break; default: break; } break; case GDK_MOTION_NOTIFY: if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) { double x1, x2, y1, y2; gnome_canvas_item_get_bounds(item, &x1, &y1, &x2, &y2); new_x = item_x; new_y = item_y; /* Check board boundaries */ if((x1 < 0 && new_x BOARDWIDTH && new_x>x)) { new_x = x; } if((y1 < 0 && new_y BOARDHEIGHT && new_y>y)) { new_y = y; } gnome_canvas_item_move(item, new_x - x, new_y - y); x = new_x; y = new_y; } break; case GDK_BUTTON_RELEASE: if(dragging) { gc_canvas_item_ungrab(item, event->button.time); dragging = FALSE; } break; default: break; } return FALSE; } static void process_ok() { guint i; gboolean win = TRUE; for(i=0; i