Back to index

gcompris  8.2.2
leftright.c
Go to the documentation of this file.
00001 /* gcompris - leftright.c
00002  *
00003  * Copyright (C) 2002 Pascal Georges
00004  *
00005  *   This program is free software; you can redistribute it and/or modify
00006  *   it under the terms of the GNU General Public License as published by
00007  *   the Free Software Foundation; either version 2 of the License, or
00008  *   (at your option) any later version.
00009  *
00010  *   This program is distributed in the hope that it will be useful,
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *   GNU General Public License for more details.
00014  *
00015  *   You should have received a copy of the GNU General Public License
00016  *   along with this program; if not, write to the Free Software
00017  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018  */
00019 
00020 #include "gcompris/gcompris.h"
00021 
00022 #define SOUNDLISTFILE PACKAGE
00023 
00024 static GcomprisBoard *gcomprisBoard = NULL;
00025 static gboolean board_paused = TRUE;
00026 
00027 static void start_board (GcomprisBoard *agcomprisBoard);
00028 static void pause_board (gboolean pause);
00029 static void end_board (void);
00030 static gboolean is_our_board (GcomprisBoard *gcomprisBoard);
00031 static void set_level (guint level);
00032 static int gamewon;
00033 static int last_hand = -1;
00034 
00035 static void process_ok(void);
00036 static void highlight_selected(int);
00037 static void game_won();
00038 
00039 #define LEFT 0
00040 #define RIGHT 1
00041 
00042 // the values are taken from the backgound image colors-bg.jpg
00043 #define BUTTON_AREA_X1 83
00044 #define BUTTON_AREA_X2 487
00045 #define BUTTON_AREA_Y1 380
00046 
00047 #define CENTER_LEFT_X 200
00048 #define CENTER_LEFT_Y 430
00049 #define CENTER_RIGHT_X 600
00050 #define CENTER_RIGHT_Y CENTER_LEFT_Y
00051 
00052 #define HAND_X 400
00053 #define HAND_Y 200
00054 
00055 // Defines the clickable areas
00056 #define CLICKABLE_X1 90
00057 #define CLICKABLE_X2 300
00058 #define CLICKABLE_X3 490
00059 #define CLICKABLE_X4 700
00060 #define CLICKABLE_Y1 390
00061 #define CLICKABLE_Y2 480
00062 
00063 #define NUMBER_OF_SUBLEVELS 6
00064 #define NUMBER_OF_LEVELS 4
00065 
00066 #define TEXT_COLOR "yellow"
00067 
00068 /* ================================================================ */
00069 static GnomeCanvasGroup *boardRootItem = NULL;
00070 
00071 static GnomeCanvasItem *hand_image_item = NULL;
00072 static GnomeCanvasItem *left_highlight_image_item = NULL, *right_highlight_image_item = NULL;
00073 
00074 static GnomeCanvasItem *leftright_create_item(GnomeCanvasGroup *parent);
00075 static void leftright_destroy_all_items(void);
00076 static void leftright_next_level(void);
00077 static gint item_event(GnomeCanvasItem *item, GdkEvent *event, gpointer data);
00078 static int answer;
00079 
00080 static char *hands[32] = {"main_droite_dessus_0.png","main_droite_paume_0.png",
00081                        "main_gauche_dessus_0.png","main_gauche_paume_0.png",
00082                        "main_droite_dessus_90.png","main_droite_paume_90.png",
00083                        "main_gauche_dessus_90.png","main_gauche_paume_90.png",
00084                        "main_droite_dessus_180.png","main_droite_paume_180.png",
00085                        "main_gauche_dessus_180.png","main_gauche_paume_180.png",
00086                        "main_droite_dessus_270.png","main_droite_paume_270.png",
00087                        "main_gauche_dessus_270.png","main_gauche_paume_270.png",
00088                        "poing_droit_dessus_0.png", "poing_droit_paume_0.png",
00089                        "poing_gauche_dessus_0.png", "poing_gauche_paume_0.png",
00090                        "poing_droit_dessus_90.png", "poing_droit_paume_90.png",
00091                        "poing_gauche_dessus_90.png", "poing_gauche_paume_90.png",
00092                        "poing_droit_dessus_180.png", "poing_droit_paume_180.png",
00093                        "poing_gauche_dessus_180.png", "poing_gauche_paume_180.png",
00094                        "poing_droit_dessus_270.png", "poing_droit_paume_270.png",
00095                        "poing_gauche_dessus_270.png", "poing_gauche_paume_270.png"
00096 };
00097 
00098 /* Description of this plugin */
00099 static BoardPlugin menu_bp =
00100   {
00101     NULL,
00102     NULL,
00103     "Find your left and right hands",
00104     "Given a picture of a hand, work out if it's a right or left hand",
00105     "Pascal Georges pascal.georges1@free.fr>",
00106     NULL,
00107     NULL,
00108     NULL,
00109     NULL,
00110     start_board,
00111     pause_board,
00112     end_board,
00113     is_our_board,
00114     NULL,
00115     process_ok,
00116     set_level,
00117     NULL,
00118     NULL,
00119     NULL,
00120     NULL
00121   };
00122 
00123 /* =====================================================================
00124  *
00125  * =====================================================================*/
00126 GET_BPLUGIN_INFO(leftright)
00127 
00128 /* =====================================================================
00129  * in : boolean TRUE = PAUSE : FALSE = CONTINUE
00130  * =====================================================================*/
00131 static void pause_board (gboolean pause)
00132 {
00133   if(gcomprisBoard==NULL)
00134     return;
00135 
00136   gc_bar_hide(FALSE);
00137   if(gamewon == TRUE && pause == FALSE) /* the game is won */
00138     game_won();
00139 
00140   board_paused = pause;
00141 }
00142 
00143 /* =====================================================================
00144  *
00145  * =====================================================================*/
00146 static void start_board (GcomprisBoard *agcomprisBoard) {
00147   if(agcomprisBoard!=NULL) {
00148     gchar *img;
00149 
00150     gcomprisBoard=agcomprisBoard;
00151     img = gc_skin_image_get("leftright-bg.jpg");
00152     gc_set_background(gnome_canvas_root(gcomprisBoard->canvas),
00153                          img);
00154     g_free(img);
00155     gcomprisBoard->level=1;
00156     gcomprisBoard->maxlevel=NUMBER_OF_LEVELS;
00157     gcomprisBoard->sublevel=1;
00158 
00159     gcomprisBoard->number_of_sublevel = NUMBER_OF_SUBLEVELS;
00160     gc_score_start(SCORESTYLE_NOTE, 10, 50, gcomprisBoard->number_of_sublevel);
00161     gc_bar_set(GC_BAR_LEVEL);
00162 
00163     leftright_next_level();
00164 
00165     gamewon = FALSE;
00166     pause_board(FALSE);
00167   }
00168 }
00169 
00170 /* =====================================================================
00171  *
00172  * =====================================================================*/
00173 static void end_board () {
00174 
00175   if(gcomprisBoard!=NULL){
00176     pause_board(TRUE);
00177     gc_score_end();
00178     leftright_destroy_all_items();
00179   }
00180   gcomprisBoard = NULL;
00181 }
00182 
00183 /* =====================================================================
00184  *
00185  * =====================================================================*/
00186 static void set_level (guint level) {
00187   if(gcomprisBoard!=NULL) {
00188     gcomprisBoard->level=level;
00189     gcomprisBoard->sublevel=1;
00190     leftright_next_level();
00191   }
00192 }
00193 
00194 /* =====================================================================
00195  *
00196  * =====================================================================*/
00197 static gboolean is_our_board (GcomprisBoard *gcomprisBoard) {
00198   if (gcomprisBoard) {
00199     if(g_strcasecmp(gcomprisBoard->type, "leftright")==0) {
00200       /* Set the plugin entry */
00201       gcomprisBoard->plugin=&menu_bp;
00202       return TRUE;
00203     }
00204   }
00205   return FALSE;
00206 }
00207 /* =====================================================================
00208  * set initial values for the next level
00209  * =====================================================================*/
00210 static void leftright_next_level() {
00211   gc_bar_set_level(gcomprisBoard);
00212 
00213   leftright_destroy_all_items();
00214   gamewon = FALSE;
00215 
00216   gc_score_set(gcomprisBoard->sublevel);
00217 
00218   /* Try the next level */
00219   leftright_create_item(gnome_canvas_root(gcomprisBoard->canvas));
00220 
00221 }
00222 /* =====================================================================
00223  * Destroy all the items
00224  * =====================================================================*/
00225 static void leftright_destroy_all_items() {
00226   if(boardRootItem!=NULL)
00227     gtk_object_destroy (GTK_OBJECT(boardRootItem));
00228 
00229   boardRootItem = NULL;
00230 }
00231 
00232 /* =====================================================================
00233  *
00234  * =====================================================================*/
00235 static GnomeCanvasItem *leftright_create_item(GnomeCanvasGroup *parent) {
00236   GdkPixbuf *highlight_pixmap = NULL;
00237   GdkPixbuf *hand_pixmap = NULL;
00238   gchar *str;
00239   int i;
00240 
00241   boardRootItem = GNOME_CANVAS_GROUP(
00242                                  gnome_canvas_item_new (gnome_canvas_root(gcomprisBoard->canvas),
00243                                                      gnome_canvas_group_get_type (),
00244                                                      "x", (double) 0,
00245                                                      "y", (double) 0,
00246                                                      NULL));
00247 
00248   highlight_pixmap = gc_pixmap_load("leftright/leftright-select.png");
00249 
00250   left_highlight_image_item = gnome_canvas_item_new (boardRootItem,
00251                                                gnome_canvas_pixbuf_get_type (),
00252                                                "pixbuf", highlight_pixmap,
00253                                                "x", (double) BUTTON_AREA_X1,
00254                                                "y", (double) BUTTON_AREA_Y1,
00255                                                "width", (double) gdk_pixbuf_get_width(highlight_pixmap),
00256                                                "height", (double) gdk_pixbuf_get_height(highlight_pixmap),
00257                                                "width_set", TRUE,
00258                                                "height_set", TRUE,
00259                                                NULL);
00260 
00261   right_highlight_image_item = gnome_canvas_item_new (boardRootItem,
00262                                                 gnome_canvas_pixbuf_get_type (),
00263                                                 "pixbuf", highlight_pixmap,
00264                                                 "x", (double) BUTTON_AREA_X2,
00265                                                 "y", (double) BUTTON_AREA_Y1,
00266                                                 "width", (double) gdk_pixbuf_get_width(highlight_pixmap),
00267                                                 "height", (double) gdk_pixbuf_get_height(highlight_pixmap),
00268                                                 "width_set", TRUE,
00269                                                 "height_set", TRUE,
00270                                                 NULL);
00271 
00272   gnome_canvas_item_hide(right_highlight_image_item);
00273   gnome_canvas_item_hide(left_highlight_image_item);
00274 
00275   gnome_canvas_item_new (boardRootItem,
00276                       gnome_canvas_text_get_type (),
00277                       "text", _("left"),
00278                       "font", gc_skin_font_board_big,
00279                       "x", (double) CENTER_LEFT_X + 1.0,
00280                       "y", (double) CENTER_LEFT_Y + 1.0,
00281                       "anchor", GTK_ANCHOR_CENTER,
00282                       "fill_color", "black",
00283                       NULL);
00284 
00285   gnome_canvas_item_new (boardRootItem,
00286                       gnome_canvas_text_get_type (),
00287                       "text", _("left"),
00288                       "font", gc_skin_font_board_big,
00289                       "x", (double) CENTER_LEFT_X,
00290                       "y", (double) CENTER_LEFT_Y,
00291                       "anchor", GTK_ANCHOR_CENTER,
00292                       "fill_color", TEXT_COLOR,
00293                       NULL);
00294 
00295   gnome_canvas_item_new (boardRootItem,
00296                       gnome_canvas_text_get_type (),
00297                       "text", _("right"),
00298                       "font", gc_skin_font_board_big,
00299                       "x", (double) CENTER_RIGHT_X + 1.0,
00300                       "y", (double) CENTER_RIGHT_Y + 1.0,
00301                       "anchor", GTK_ANCHOR_CENTER,
00302                       "fill_color", "black",
00303                       NULL);
00304 
00305   gnome_canvas_item_new (boardRootItem,
00306                       gnome_canvas_text_get_type (),
00307                       "text", _("right"),
00308                       "font", gc_skin_font_board_big,
00309                       "x", (double) CENTER_RIGHT_X,
00310                       "y", (double) CENTER_RIGHT_Y,
00311                       "anchor", GTK_ANCHOR_CENTER,
00312                       "fill_color", TEXT_COLOR,
00313                       NULL);
00314 
00315   // make sure that next hand is not the same as previous
00316   do {
00317     i = RAND(0,gcomprisBoard->level*8-1);
00318   } while ( i == last_hand );
00319 
00320   last_hand = i;
00321 
00322   if ( ((int) (i/2)) % 2 == 1)
00323     answer = LEFT;
00324   else
00325     answer = RIGHT;
00326 
00327   str = g_strdup_printf("%s/%s", gcomprisBoard->boarddir, hands[i]);
00328   hand_pixmap = gc_pixmap_load(str);
00329   hand_image_item = gnome_canvas_item_new (boardRootItem,
00330                                       gnome_canvas_pixbuf_get_type (),
00331                                       "pixbuf", hand_pixmap,
00332                                       "x", (double) HAND_X - (gdk_pixbuf_get_width(hand_pixmap)/2),
00333                                       "y", (double) HAND_Y - (gdk_pixbuf_get_height(hand_pixmap)/2),
00334                                       "width", (double) gdk_pixbuf_get_width(hand_pixmap),
00335                                       "height", (double) gdk_pixbuf_get_height(hand_pixmap),
00336                                       "width_set", TRUE,
00337                                       "height_set", TRUE,
00338                                       NULL);
00339 
00340   g_free(str);
00341 
00342   gdk_pixbuf_unref(highlight_pixmap);
00343   gdk_pixbuf_unref(hand_pixmap);
00344 
00345   gtk_signal_connect(GTK_OBJECT(gcomprisBoard->canvas), "event",  (GtkSignalFunc) item_event, NULL);
00346 
00347   return NULL;
00348 }
00349 /* =====================================================================
00350  *
00351  * =====================================================================*/
00352 static void game_won() {
00353   gcomprisBoard->sublevel++;
00354   if(gcomprisBoard->sublevel > gcomprisBoard->number_of_sublevel) {
00355     /* Try the next level */
00356     gcomprisBoard->sublevel=1;
00357     gcomprisBoard->level++;
00358     if(gcomprisBoard->level>gcomprisBoard->maxlevel) { // the current board is finished : bail out
00359       gc_bonus_end_display(BOARD_FINISHED_TUXLOCO);
00360       return;
00361     }
00362   }
00363   leftright_next_level();
00364 }
00365 
00366 /* =====================================================================
00367  *
00368  * =====================================================================*/
00369 static gboolean process_ok_timeout() {
00370   gc_bonus_display(gamewon, BONUS_SMILEY);
00371   return FALSE;
00372 }
00373 
00374 static void process_ok() {
00375   gc_bar_hide(TRUE);
00376   // leave time to display the right answer
00377   g_timeout_add(TIME_CLICK_TO_BONUS, process_ok_timeout, NULL);
00378 }
00379 /* =====================================================================
00380  *
00381  * =====================================================================*/
00382 static gint item_event(GnomeCanvasItem *item, GdkEvent *event, gpointer data) {
00383   double x, y;
00384   int side;
00385 
00386   x = event->button.x;
00387   y = event->button.y;
00388 
00389   if (!gcomprisBoard || board_paused)
00390     return FALSE;
00391 
00392   switch (event->type)
00393     {
00394     case GDK_BUTTON_PRESS:
00395       gnome_canvas_c2w(gcomprisBoard->canvas, x, y, &x, &y);
00396 
00397       if (y>CLICKABLE_Y1 && y<CLICKABLE_Y2) {
00398        if (x>CLICKABLE_X1 && x<CLICKABLE_X2) { // the left button is clicked
00399          board_paused = TRUE;
00400          side = LEFT;
00401          highlight_selected(side);
00402          gamewon = (side == answer);
00403           process_ok();
00404        }
00405        if (x>CLICKABLE_X3 && x<CLICKABLE_X4) { // the left button is clicked
00406          board_paused = TRUE;
00407          side = RIGHT;
00408          highlight_selected(side);
00409          gamewon = (side == answer);
00410           process_ok();
00411        }
00412       }
00413 
00414       break;
00415 
00416     default:
00417       break;
00418     }
00419   return FALSE;
00420 }
00421 
00422 /* =====================================================================
00423  *
00424  * =====================================================================*/
00425 static void highlight_selected(int side) {
00426   if (side == LEFT) {
00427     gnome_canvas_item_hide(right_highlight_image_item);
00428     gnome_canvas_item_show(left_highlight_image_item);
00429   }
00430   if (side == RIGHT) {
00431     gnome_canvas_item_show(right_highlight_image_item);
00432     gnome_canvas_item_hide(left_highlight_image_item);
00433   }
00434 }