/* gcompris - read_colors.c * * Copyright (C) 2002 Pascal Georges * * 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 /* libxml includes */ #include #include #include "gcompris/gcompris.h" #define SOUNDLISTFILE PACKAGE static GcomprisBoard *gcomprisBoard = NULL; static gboolean board_paused = TRUE; static void start_board (GcomprisBoard *agcomprisBoard); static void pause_board (gboolean pause); static void end_board (void); static gboolean is_our_board (GcomprisBoard *gcomprisBoard); static int gamewon; static void process_ok(void); static void highlight_selected(int); static void game_won(void); static void init_xml(); static gboolean read_xml_file(char *fname); /* ================================================================ */ static GnomeCanvasGroup *boardRootItem = NULL; static GnomeCanvasItem *highlight_image_item = NULL; static GnomeCanvasItem *color_item = NULL; static GnomeCanvasItem *clock_image_item = NULL; static GdkPixbuf *clock_pixmap = NULL; static GnomeCanvasItem *read_colors_create_item(GnomeCanvasGroup *parent); static void read_colors_destroy_all_items(void); static void read_colors_next_level(void); static gint item_event(GnomeCanvasItem *item, GdkEvent *event, gpointer data); static void update_clock(); static int highlight_width, highlight_height, errors; static GList * listColors = NULL; #define LAST_COLOR 11 #define MAX_ERRORS 10 #define CLOCK_X 40 #define CLOCK_Y 420 static char* colors[LAST_COLOR]; static int X[] = {100,300,500,700,200,400,600,100,300,500,700}; static int Y[] = {90,90,90,90,180,180,180,270,270,270,270}; /* (x1,y1) and (x2, y2) are the coordinates of the rectangle where to draw the color's name */ static int color_x1 = 240, color_x2 = 570; static int color_y1 = 395, color_y2 = 490; #define RADIUS 60 /* Description of this plugin */ static BoardPlugin menu_bp = { NULL, NULL, "Read Colors", "Click on the corresponding color", "Pascal Georges pascal.georges1@free.fr>", NULL, NULL, NULL, NULL, start_board, pause_board, end_board, is_our_board, NULL, process_ok, NULL,//set_level, NULL, NULL, NULL, NULL }; /* ===================================================================== * * =====================================================================*/ GET_BPLUGIN_INFO(read_colors) /* ===================================================================== * in : boolean TRUE = PAUSE : FALSE = CONTINUE * =====================================================================*/ static void pause_board (gboolean pause) { if(gcomprisBoard==NULL) return; gc_bar_hide(FALSE); if(gamewon == TRUE && pause == FALSE) /* the game is won */ game_won(); board_paused = pause; } /* ===================================================================== * * =====================================================================*/ static void start_board (GcomprisBoard *agcomprisBoard) { GList * list = NULL; int * item; int i,list_length; if(agcomprisBoard!=NULL) { gcomprisBoard=agcomprisBoard; gc_set_background(gnome_canvas_root(gcomprisBoard->canvas), "read_colors/read_colors_background.png"); gcomprisBoard->level=1; gcomprisBoard->maxlevel=1; gc_bar_set(0); gamewon = FALSE; errors = MAX_ERRORS; init_xml(); // we generate a list of color indexes in a random order while (g_list_length(listColors) > 0) listColors = g_list_remove(listColors, g_list_nth_data(listColors,0)); for (i=0; icanvas), "event", (GtkSignalFunc) item_event, NULL); read_colors_next_level(); pause_board(FALSE); } } /* ===================================================================== * * =====================================================================*/ static void end_board () { if(gcomprisBoard!=NULL){ pause_board(TRUE); gc_score_end(); read_colors_destroy_all_items(); // free list while (g_list_length(listColors) > 0) listColors = g_list_remove(listColors, g_list_nth_data(listColors,0)); g_list_free(listColors); listColors = NULL; } gcomprisBoard = NULL; } /* ===================================================================== * * =====================================================================*/ static gboolean is_our_board (GcomprisBoard *gcomprisBoard) { if (gcomprisBoard) { if(g_strcasecmp(gcomprisBoard->type, "read_colors")==0) { /* Set the plugin entry */ gcomprisBoard->plugin=&menu_bp; return TRUE; } } return FALSE; } /* ===================================================================== * set initial values for the next level * =====================================================================*/ static void read_colors_next_level() { read_colors_destroy_all_items(); gamewon = FALSE; /* Try the next level */ read_colors_create_item(gnome_canvas_root(gcomprisBoard->canvas)); /* show text of color to find */ color_item = gnome_canvas_item_new (boardRootItem, gnome_canvas_text_get_type (), "text", colors[GPOINTER_TO_INT(g_list_nth_data(listColors,0))], "font", gc_skin_font_board_title_bold, "x", (double) (color_x1+color_x2)/2, "y", (double) (color_y1+color_y2)/2, "anchor", GTK_ANCHOR_CENTER, "fill_color", "darkblue", NULL); } /* ===================================================================== * Destroy all the items * =====================================================================*/ static void read_colors_destroy_all_items() { if(boardRootItem!=NULL) gtk_object_destroy (GTK_OBJECT(boardRootItem)); boardRootItem = NULL; } /* ===================================================================== * * =====================================================================*/ static GnomeCanvasItem *read_colors_create_item(GnomeCanvasGroup *parent) { GdkPixbuf *highlight_pixmap = NULL; char *str = 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)); str = g_strdup_printf("%s/%s", gcomprisBoard->boarddir, "read_colors_highlight.png"); highlight_pixmap = gc_pixmap_load(str); highlight_image_item = gnome_canvas_item_new (boardRootItem, gnome_canvas_pixbuf_get_type (), "pixbuf", highlight_pixmap, "x", (double) 0, "y", (double) 0, "width", (double) gdk_pixbuf_get_width(highlight_pixmap), "height", (double) gdk_pixbuf_get_height(highlight_pixmap), "width_set", TRUE, "height_set", TRUE, NULL); highlight_width = gdk_pixbuf_get_width(highlight_pixmap); highlight_height = gdk_pixbuf_get_height(highlight_pixmap); g_free(str); gnome_canvas_item_hide(highlight_image_item); gdk_pixbuf_unref(highlight_pixmap); /* setup the clock */ str = g_strdup_printf("%s%d.png", "gcompris/timers/clock",errors); clock_pixmap = gc_pixmap_load(str); clock_image_item = gnome_canvas_item_new (boardRootItem, gnome_canvas_pixbuf_get_type (), "pixbuf", clock_pixmap, "x", (double) CLOCK_X, "y", (double) CLOCK_Y, "width", (double) gdk_pixbuf_get_width(clock_pixmap), "height", (double) gdk_pixbuf_get_height(clock_pixmap), "width_set", TRUE, "height_set", TRUE, NULL); g_free(str); return NULL; } /* ===================================================================== * * =====================================================================*/ static void update_clock() { char *str = g_strdup_printf("%s%d.png", "gcompris/timers/clock",errors); gtk_object_destroy (GTK_OBJECT(clock_image_item)); clock_pixmap = gc_pixmap_load(str); clock_image_item = gnome_canvas_item_new (boardRootItem, gnome_canvas_pixbuf_get_type (), "pixbuf", clock_pixmap, "x", (double) CLOCK_X, "y", (double) CLOCK_Y, "width", (double) gdk_pixbuf_get_width(clock_pixmap), "height", (double) gdk_pixbuf_get_height(clock_pixmap), "width_set", TRUE, "height_set", TRUE, NULL); gdk_pixbuf_unref(clock_pixmap); g_free(str); } /* ===================================================================== * * =====================================================================*/ static void game_won() { gcomprisBoard->sublevel++; listColors = g_list_remove(listColors, g_list_nth_data(listColors,0)); if( g_list_length(listColors) <= 0 ) { // the current board is finished : bail out gc_bonus_end_display(GC_BOARD_FINISHED_TUXLOCO); return; } read_colors_next_level(); } /* ===================================================================== * * =====================================================================*/ static gboolean process_ok_timeout() { gc_bonus_display(gamewon, GC_BONUS_SMILEY); if (!gamewon) errors--; if (errors <1) errors = 1; update_clock(); if (errors <= 1) { gc_bonus_end_display(GC_BOARD_FINISHED_TOOMANYERRORS); } return FALSE; } static void process_ok() { gc_bar_hide(TRUE); // leave time to display the right answer g_timeout_add(TIME_CLICK_TO_BONUS, process_ok_timeout, NULL); } /* ===================================================================== * * =====================================================================*/ static gint item_event(GnomeCanvasItem *item, GdkEvent *event, gpointer data) { double x, y; int i, clicked; x = event->button.x; y = event->button.y; if (!gcomprisBoard || board_paused) return FALSE; switch (event->type) { case GDK_BUTTON_PRESS: gnome_canvas_c2w (gcomprisBoard->canvas, x, y, &x, &y); clicked = -1; for (i=0; i= 0) { gc_sound_play_ogg ("sounds/bleep.wav", NULL); board_paused = TRUE; highlight_selected(clicked); gamewon = (clicked == GPOINTER_TO_INT(g_list_nth_data(listColors,0))); process_ok(); } break; default: break; } return FALSE; } /* ===================================================================== * * =====================================================================*/ static void highlight_selected(int c) { int x, y; g_assert(c>=0 && cboarddir); g_assert(read_xml_file(filename)== TRUE); g_free(filename); } /* ==================================== */ static void add_xml_data(xmlDocPtr doc, xmlNodePtr xmlnode, GNode * child) { char *text = NULL; char *sColor = NULL; int i; xmlnode = xmlnode->xmlChildrenNode; xmlnode = xmlnode->next; while (xmlnode != NULL) { // try to match color[i] for (i=0; iname, sColor)) { text = \ gettext((char *)xmlNodeListGetString(doc, xmlnode->xmlChildrenNode, 1)); colors[i] = text; g_free(sColor); break; } g_free(sColor); } // end for xmlnode = xmlnode->next; } // I really don't know why this test, but otherwise, the list is doubled // with 1 line on 2 filled with NULL elements if ( text == NULL) return; } /* ==================================== */ static void parse_doc(xmlDocPtr doc) { xmlNodePtr node; for(node = doc->children->children; node != NULL; node = node->next) { if ( g_strcasecmp((gchar *)node->name, "Board") == 0 ) add_xml_data(doc, node,NULL); } } /* ==================================== */ /* read an xml file into our memory structures and update our view, dump any old data we have in memory if we can load a new set */ static gboolean read_xml_file(char *fname) { /* pointer to the new doc */ xmlDocPtr doc; g_return_val_if_fail(fname!=NULL,FALSE); /* parse the new file and put the result into newdoc */ doc = xmlParseFile(fname); /* in case something went wrong */ if(!doc) return FALSE; if(/* if there is no root element */ !doc->children || /* if it doesn't have a name */ !doc->children->name || /* if it isn't a ImageId node */ g_strcasecmp((char *)doc->children->name,"ReadColors")!=0) { xmlFreeDoc(doc); return FALSE; } parse_doc(doc); xmlFreeDoc(doc); return TRUE; }