Back to index

gcompris  8.2.2
reversecount.c
Go to the documentation of this file.
00001 /* gcompris - reversecount.c
00002  *
00003  * Copyright (C) 2002,2003 Bruno Coudoin
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 static gint    animate_id = 0;
00027 static int     leavenow;
00028 
00029 static void    start_board (GcomprisBoard *agcomprisBoard);
00030 static gint    key_press(guint keyval, gchar *commit_str, gchar *preedit_str);
00031 static void    pause_board (gboolean pause);
00032 static void    end_board (void);
00033 static gboolean       is_our_board (GcomprisBoard *gcomprisBoard);
00034 static void    set_level (guint level);
00035 static int     gamewon;
00036 static void    game_won(void);
00037 
00038 #define TUX_IMG_NORTH "gcompris/misc/tux_top_north.png"
00039 #define TUX_IMG_SOUTH "gcompris/misc/tux_top_south.png"
00040 #define TUX_IMG_WEST  "gcompris/misc/tux_top_west.png"
00041 #define TUX_IMG_EAST  "gcompris/misc/tux_top_east.png"
00042 #define TUX_TO_BORDER_GAP 10
00043 
00044 static GnomeCanvasGroup *boardRootItem = NULL;
00045 
00046 static void           process_ok(void);
00047 static void           process_error(void);
00048 static GnomeCanvasItem      *reversecount_create_item(GnomeCanvasGroup *parent);
00049 static void           reversecount_destroy_all_items(void);
00050 static void           reversecount_next_level(void);
00051 static gint           item_event(GnomeCanvasItem *item, GdkEvent *event, gint *dice_index);
00052 static GnomeCanvasItem      *display_item_at(gchar *imagename, int block, double ratio);
00053 static void           display_random_fish();
00054 static void           create_clock(double x, double y, int value);
00055 static void           update_clock(int value);
00056 static gint           animate_tux();
00057 
00058 static int number_of_item   = 0;
00059 static int number_of_item_x = 0;
00060 static int number_of_item_y = 0;
00061 
00062 static int errors           = 0;
00063 static int number_of_dices  = 0;
00064 static int max_dice_number  = 0;
00065 static int number_of_fish   = 0;
00066 
00067 static int tux_index     = 0;
00068 static int tux_destination  = 0;
00069 static int fish_index           = 0;
00070 static int animate_speed    = 0;
00071 
00072 #define ANIMATE_SPEED       800
00073 
00074 static double tux_ratio = 0;
00075 
00076 static int dicevalue_array[10];
00077 static GnomeCanvasItem *fishItem;
00078 static GnomeCanvasItem *tuxItem;
00079 static GnomeCanvasItem *clock_image_item;
00080 
00081 // List of images to use in the game
00082 static gchar *imageList[] =
00083 {
00084   "reversecount/baleine.png",
00085   "reversecount/phoque.png",
00086   "reversecount/ourspolaire.png",
00087   "reversecount/morse.png",
00088   "reversecount/elephant_mer.png",
00089   "reversecount/epaulard.png",
00090   "reversecount/narval.png",
00091 };
00092 #define NUMBER_OF_IMAGES 10
00093 
00094 // List of fish to use in the game
00095 static gchar *fishList[] =
00096 {
00097   "fishes/blueking2_0.png",
00098   "fishes/butfish_0.png",
00099   "fishes/cichlid1_0.png",
00100   "fishes/cichlid4_0.png",
00101   "fishes/collaris_0.png",
00102   "fishes/discus2_0.png",
00103   "fishes/discus3_0.png",
00104   "fishes/eel_0.png",
00105   "fishes/f00_0.png",
00106   "fishes/f01_0.png",
00107   "fishes/f02_0.png",
00108   "fishes/f03_0.png",
00109   "fishes/f04_0.png",
00110   "fishes/f05_0.png",
00111   "fishes/f06_0.png",
00112   "fishes/f07_0.png",
00113   "fishes/f08_0.png",
00114   "fishes/f09_0.png",
00115   "fishes/f10_0.png",
00116   "fishes/f11_0.png",
00117   "fishes/f12_0.png",
00118   "fishes/f13_0.png",
00119   "fishes/manta_0.png",
00120   "fishes/newf1_0.png",
00121   "fishes/QueenAngel_0.png",
00122   "fishes/shark1_0.png",
00123   "fishes/six_barred_0.png",
00124   "fishes/teeth_0.png"
00125 };
00126 #define NUMBER_OF_FISHES 27
00127 
00128 /* Description of this plugin */
00129 static BoardPlugin menu_bp =
00130   {
00131     NULL,
00132     NULL,
00133     "Reverse count",
00134     "Practice substraction with a funny game",
00135     "Bruno Coudoin <bruno.coudoin@free.fr>",
00136     NULL,
00137     NULL,
00138     NULL,
00139     NULL,
00140     start_board,
00141     pause_board,
00142     end_board,
00143     is_our_board,
00144     key_press,
00145     process_ok,
00146     set_level,
00147     NULL,
00148     NULL,
00149     NULL,
00150     NULL
00151   };
00152 
00153 /*
00154  * Main entry point mandatory for each Gcompris's game
00155  * ---------------------------------------------------
00156  *
00157  */
00158 
00159 GET_BPLUGIN_INFO(reversecount)
00160 
00161 /*
00162  * in : boolean TRUE = PAUSE : FALSE = CONTINUE
00163  *
00164  */
00165 static void pause_board (gboolean pause)
00166 {
00167   if(gcomprisBoard==NULL)
00168     return;
00169 
00170   if(gamewon == TRUE && pause == FALSE) /* the game is won */
00171     {
00172       game_won();
00173     }
00174 
00175   if(leavenow == TRUE && pause == FALSE)
00176     gc_bonus_end_display(BOARD_FINISHED_TOOMANYERRORS);
00177 
00178   board_paused = pause;
00179 }
00180 
00181 /*
00182  */
00183 static void start_board (GcomprisBoard *agcomprisBoard)
00184 {
00185 
00186   if(agcomprisBoard!=NULL)
00187     {
00188       gcomprisBoard=agcomprisBoard;
00189 
00190       /* disable im_context */
00191       gcomprisBoard->disable_im_context = TRUE;
00192 
00193       gcomprisBoard->level=1;
00194       gcomprisBoard->maxlevel=7;
00195       gcomprisBoard->sublevel=1;
00196       gcomprisBoard->number_of_sublevel=1; /* Go to next level after this number of 'play' */
00197       gc_bar_set(GC_BAR_LEVEL|GC_BAR_OK);
00198 
00199       reversecount_next_level();
00200 
00201       gamewon = FALSE;
00202       leavenow = FALSE;
00203 
00204       pause_board(FALSE);
00205     }
00206 }
00207 /* ======================================= */
00208 static void end_board ()
00209 {
00210   if(gcomprisBoard!=NULL)
00211     {
00212       pause_board(TRUE);
00213       reversecount_destroy_all_items();
00214     }
00215   gcomprisBoard = NULL;
00216 }
00217 
00218 /* ======================================= */
00219 static void set_level (guint level)
00220 {
00221 
00222   if(gcomprisBoard!=NULL)
00223     {
00224       gcomprisBoard->level=level;
00225       gcomprisBoard->sublevel=1;
00226       reversecount_next_level();
00227     }
00228 }
00229 
00230 /* ======================================= */
00231 gboolean is_our_board (GcomprisBoard *gcomprisBoard)
00232 {
00233   if (gcomprisBoard)
00234     {
00235       if(g_strcasecmp(gcomprisBoard->type, "reversecount")==0)
00236        {
00237          /* Set the plugin entry */
00238          gcomprisBoard->plugin=&menu_bp;
00239 
00240          return TRUE;
00241        }
00242     }
00243   return FALSE;
00244 }
00245 
00246 /* ======================================= */
00247 gint key_press(guint keyval, gchar *commit_str, gchar *preedit_str)
00248 {
00249 
00250   if(!gcomprisBoard)
00251     return FALSE;
00252 
00253   /* Add some filter for control and shift key */
00254   switch (keyval)
00255     {
00256       /* Avoid all this keys to be interpreted by this game */
00257     case GDK_Shift_L:
00258     case GDK_Shift_R:
00259     case GDK_Control_L:
00260     case GDK_Control_R:
00261     case GDK_Caps_Lock:
00262     case GDK_Shift_Lock:
00263     case GDK_Meta_L:
00264     case GDK_Meta_R:
00265     case GDK_Alt_L:
00266     case GDK_Alt_R:
00267     case GDK_Super_L:
00268     case GDK_Super_R:
00269     case GDK_Hyper_L:
00270     case GDK_Hyper_R:
00271     case GDK_Num_Lock:
00272       return FALSE;
00273     case GDK_KP_Enter:
00274     case GDK_Return:
00275       process_ok();
00276       return TRUE;
00277     }
00278 
00279   return TRUE;
00280 }
00281 
00282 
00283 static void process_error()
00284 {
00285   gc_sound_play_ogg ("sounds/crash.ogg", NULL);
00286   errors--;
00287   if(errors==0)
00288     {
00289       gamewon = FALSE;
00290       leavenow = TRUE;
00291       reversecount_destroy_all_items();
00292       gc_bonus_display(gamewon, BONUS_SMILEY);
00293     }
00294   else
00295     {
00296       update_clock(errors);
00297     }
00298 }
00299 
00300 /* ======================================= */
00301 static void process_ok()
00302 {
00303   guint i;
00304 
00305   tux_destination = tux_index;
00306 
00307   for(i=0; i<number_of_dices; i++)
00308       tux_destination += dicevalue_array[i];
00309 
00310   // Wrapping
00311   if(tux_destination >= number_of_item)
00312     tux_destination = tux_destination - (number_of_item);
00313 
00314   // Do not allow going at a position after the fish
00315   if((tux_destination > fish_index)
00316      || (tux_destination == tux_index))
00317     {
00318       process_error();
00319       return;
00320     }
00321 
00322   if(!animate_id) {
00323     animate_id = gtk_timeout_add (animate_speed, (GtkFunction) animate_tux, NULL);
00324   }
00325 
00326 }
00327 
00328 /*-------------------------------------------------------------------------------*/
00329 /*-------------------------------------------------------------------------------*/
00330 
00331 /* set initial values for the next level */
00332 static void reversecount_next_level()
00333 {
00334 
00335   gc_set_background(gnome_canvas_root(gcomprisBoard->canvas),
00336                        imageList[gcomprisBoard->level-1]);
00337 
00338   gc_bar_set_level(gcomprisBoard);
00339 
00340   reversecount_destroy_all_items();
00341   gamewon = FALSE;
00342 
00343   /* Select level difficulty */
00344   switch(gcomprisBoard->level)
00345     {
00346     case 1:
00347       number_of_item_x = 5;
00348       number_of_item_y = 5;
00349       number_of_dices = 1;
00350       max_dice_number = 3;
00351       number_of_fish = 3;
00352       break;
00353     case 2:
00354       number_of_item_x = 5;
00355       number_of_item_y = 5;
00356       number_of_dices = 1;
00357       max_dice_number = 6;
00358       number_of_fish = 6;
00359       break;
00360     case 3:
00361       number_of_item_x = 6;
00362       number_of_item_y = 6;
00363       number_of_dices = 1;
00364       max_dice_number = 9;
00365       number_of_fish = 6;
00366       break;
00367     case 4:
00368       number_of_item_x = 8;
00369       number_of_item_y = 6;
00370       number_of_dices = 1;
00371       max_dice_number = 3;
00372       number_of_fish = 6;
00373       break;
00374     case 5:
00375       number_of_item_x = 8;
00376       number_of_item_y = 6;
00377       number_of_dices = 2;
00378       max_dice_number = 6;
00379       number_of_fish = 10;
00380       break;
00381     case 6:
00382       number_of_item_x = 8;
00383       number_of_item_y = 8;
00384       number_of_dices = 2;
00385       max_dice_number = 9;
00386       number_of_fish = 10;
00387       break;
00388     default:
00389       number_of_item_x = 10;
00390       number_of_item_y = 10;
00391       number_of_dices = 3;
00392       max_dice_number = 9;
00393       number_of_fish = 10;
00394       break;
00395     }
00396 
00397   animate_speed = ANIMATE_SPEED - gcomprisBoard->level * 60;
00398 
00399   number_of_item = number_of_item_x * 2 + (number_of_item_y - 2) * 2;
00400 
00401   /* Try the next level */
00402   reversecount_create_item(gnome_canvas_root(gcomprisBoard->canvas));
00403 }
00404 /* ==================================== */
00405 /* Destroy all the items */
00406 static void reversecount_destroy_all_items()
00407 {
00408 
00409   gc_timer_end();
00410 
00411   if(boardRootItem!=NULL)
00412     gtk_object_destroy (GTK_OBJECT(boardRootItem));
00413 
00414   boardRootItem = NULL;
00415 }
00416 /* ==================================== */
00417 static GnomeCanvasItem *reversecount_create_item(GnomeCanvasGroup *parent)
00418 {
00419   int i,j,d;
00420   GnomeCanvasItem *item = NULL;
00421   GdkPixbuf   *pixmap = NULL;
00422   double block_width, block_height;
00423   double dice_area_x;
00424   double xratio, yratio;
00425   GcomprisProperties *properties = gc_prop_get();
00426 
00427   boardRootItem = GNOME_CANVAS_GROUP(
00428                                  gnome_canvas_item_new (gnome_canvas_root(gcomprisBoard->canvas),
00429                                                      gnome_canvas_group_get_type (),
00430                                                      "x", (double) 0,
00431                                                      "y", (double) 0,
00432 
00433                                                      NULL));
00434 
00435   block_width =  BOARDWIDTH/number_of_item_x;
00436   block_height = BOARDHEIGHT/number_of_item_y;
00437 
00438   /* Timer is not requested */
00439   if(properties->timer>0)
00440     {
00441       errors = number_of_dices + 4 - (MIN(properties->timer, 4));
00442       create_clock(BOARDWIDTH - block_width - 100, BOARDHEIGHT - block_height - 100,
00443                  errors) ;
00444     }
00445   else
00446     {
00447       errors = -1;
00448     }
00449 
00450   /* Calc the tux best ratio to display it */
00451   pixmap = gc_pixmap_load(TUX_IMG_EAST);
00452   xratio =  block_width  / (gdk_pixbuf_get_width (pixmap) + TUX_TO_BORDER_GAP);
00453   yratio =  block_height / (gdk_pixbuf_get_height(pixmap) + TUX_TO_BORDER_GAP);
00454   tux_ratio = yratio = MIN(xratio, yratio);
00455   gdk_pixbuf_unref(pixmap);
00456 
00457   pixmap = gc_pixmap_load("reversecount/iceblock.png");
00458 
00459   for(i=0; i<BOARDWIDTH; i+=block_width)
00460     {
00461       j=0;
00462       item = gnome_canvas_item_new (boardRootItem,
00463                                 gnome_canvas_pixbuf_get_type (),
00464                                 "pixbuf", pixmap,
00465                                 "x", (double) i,
00466                                 "y", (double) j,
00467                                 "width", (double) block_width,
00468                                 "height", (double)  block_height,
00469                                 "width_set", TRUE,
00470                                 "height_set", TRUE,
00471                                    NULL);
00472 
00473       j=BOARDHEIGHT-block_height;
00474       item = gnome_canvas_item_new (boardRootItem,
00475                                 gnome_canvas_pixbuf_get_type (),
00476                                 "pixbuf", pixmap,
00477                                 "x", (double) i,
00478                                 "y", (double) j,
00479                                 "width", (double) block_width,
00480                                 "height", (double)  block_height,
00481                                 "width_set", TRUE,
00482                                 "height_set", TRUE,
00483                                    NULL);
00484     }
00485 
00486   for(j=block_height; j<=BOARDHEIGHT-(block_height*2); j+=block_height)
00487     {
00488       i = 0;
00489       item = gnome_canvas_item_new (boardRootItem,
00490                                 gnome_canvas_pixbuf_get_type (),
00491                                 "pixbuf", pixmap,
00492                                 "x", (double) i,
00493                                 "y", (double) j,
00494                                 "width", (double) block_width,
00495                                 "height", (double)  block_height,
00496                                 "width_set", TRUE,
00497                                 "height_set", TRUE,
00498                                    NULL);
00499 
00500       i = BOARDWIDTH - block_width;
00501       item = gnome_canvas_item_new (boardRootItem,
00502                                 gnome_canvas_pixbuf_get_type (),
00503                                 "pixbuf", pixmap,
00504                                 "x", (double) i,
00505                                 "y", (double) j,
00506                                 "width", (double) block_width,
00507                                 "height", (double)  block_height,
00508                                 "width_set", TRUE,
00509                                 "height_set", TRUE,
00510                                    NULL);
00511     }
00512 
00513   gdk_pixbuf_unref(pixmap);
00514 
00515 
00516   //----------------------------------------
00517   // Create the dice area
00518   pixmap = gc_pixmap_load("reversecount/dice_area.png");
00519 
00520   dice_area_x = BOARDWIDTH - block_width - gdk_pixbuf_get_width (pixmap) - 20;
00521 
00522   gnome_canvas_item_new (boardRootItem,
00523                       gnome_canvas_pixbuf_get_type (),
00524                       "pixbuf", pixmap,
00525                       "x", (double) dice_area_x,
00526                       "y", (double) block_height + 20,
00527                       NULL);
00528 
00529   gdk_pixbuf_unref(pixmap);
00530 
00531   //----------------------------------------
00532   // Create the dices
00533   pixmap = gc_pixmap_load("gcompris/dice/gnome-dice1.png");
00534 
00535   for(d=0; d<number_of_dices; d++)
00536     {
00537       int *val;
00538 
00539       i = dice_area_x + gdk_pixbuf_get_width(pixmap) * d + 30;
00540       j = block_height + 25 + d*7;
00541 
00542       item = gnome_canvas_item_new (boardRootItem,
00543                                 gnome_canvas_pixbuf_get_type (),
00544                                 "pixbuf", pixmap,
00545                                 "x", (double) i,
00546                                 "y", (double) j,
00547                                 NULL);
00548       dicevalue_array[d] = 1;
00549       val = g_new(gint, 1);
00550       *val = d;
00551       gtk_signal_connect(GTK_OBJECT(item), "event", (GtkSignalFunc) item_event,
00552                       val);
00553       gtk_signal_connect(GTK_OBJECT(item), "event",
00554                       (GtkSignalFunc) gc_item_focus_event,
00555                       NULL);
00556 
00557     }
00558   gdk_pixbuf_unref(pixmap);
00559 
00560   tux_index = 0;
00561   tuxItem = display_item_at(TUX_IMG_EAST, tux_index, tux_ratio);
00562 
00563   // Display the first fish
00564   display_random_fish();
00565 
00566   return NULL;
00567 }
00568 
00569 static void display_random_fish()
00570 {
00571 
00572   fish_index = tux_index +
00573     rand()%(max_dice_number*number_of_dices) + 1;
00574 
00575   // Wrapping
00576   if(fish_index >= number_of_item)
00577     fish_index = fish_index - (number_of_item);
00578 
00579   fishItem = display_item_at(fishList[rand()%NUMBER_OF_FISHES],
00580                           fish_index, -1);
00581 }
00582 
00583 /* ==================================== */
00587 static GnomeCanvasItem *display_item_at(gchar *imagename, int block, double ratio)
00588 {
00589   double block_width, block_height;
00590   double xratio, yratio;
00591   GnomeCanvasItem *item = NULL;
00592   GdkPixbuf   *pixmap = NULL;
00593   int i,j;
00594 
00595   block_width  = BOARDWIDTH/number_of_item_x;
00596   block_height = BOARDHEIGHT/number_of_item_y;
00597 
00598   pixmap = gc_pixmap_load(imagename);
00599 
00600   if(block < number_of_item_x)
00601     {
00602       // Upper line
00603       g_warning("      // Upper line\n");
00604       i = block_width * block;
00605       j = 0;
00606     }
00607   else if(block < number_of_item_x + number_of_item_y - 2)
00608     {
00609       // Right line
00610       g_warning("      // Right line\n");
00611       i = block_width * (number_of_item_x - 1);
00612       j = block_height * (block - (number_of_item_x-1));
00613     }
00614   else if(block < number_of_item_x*2 + number_of_item_y - 2)
00615     {
00616       // Bottom line
00617       g_warning("      // Bottom line\n");
00618       i = block_width * (number_of_item_x - (block-
00619                                         (number_of_item_x+number_of_item_y-1))-2);
00620       j = block_height * (number_of_item_y-1);
00621     }
00622   else
00623     {
00624       // Left line
00625       g_warning("      // Left line\n");
00626       i = 0;
00627       j = block_height * (number_of_item_y - (block - (number_of_item_x*2 +
00628                                                 number_of_item_y-4)));
00629     }
00630 
00631   g_warning("display_tux %d i=%d j=%d\n", block, i, j);
00632 
00633   /* Calculation to thrink the item while keeping the ratio */
00634   if(ratio==-1)
00635     {
00636       xratio =  block_width  / (gdk_pixbuf_get_width (pixmap) + TUX_TO_BORDER_GAP);
00637       yratio =  block_height / (gdk_pixbuf_get_height(pixmap) + TUX_TO_BORDER_GAP);
00638       xratio = yratio = MIN(xratio, yratio);
00639     }
00640   else
00641     {
00642       xratio = yratio = ratio;
00643     }
00644 
00645   item = gnome_canvas_item_new (boardRootItem,
00646                             gnome_canvas_pixbuf_get_type (),
00647                             "pixbuf", pixmap,
00648                             "x", (double) i + (block_width -
00649                                              (gdk_pixbuf_get_width (pixmap) * xratio)) / 2,
00650                             "y", (double) j + (block_height -
00651                                              (gdk_pixbuf_get_height (pixmap) * yratio)) / 2,
00652                             "width", (double) gdk_pixbuf_get_width (pixmap) * xratio,
00653                             "height", (double)  gdk_pixbuf_get_height (pixmap) * yratio,
00654                             "width_set", TRUE,
00655                             "height_set", TRUE,
00656                             NULL);
00657 
00658   gdk_pixbuf_unref(pixmap);
00659 
00660   return(item);
00661 }
00662 
00663 /* ==================================== */
00664 static void game_won()
00665 {
00666   gcomprisBoard->sublevel++;
00667 
00668   if(gcomprisBoard->sublevel>gcomprisBoard->number_of_sublevel) {
00669     /* Try the next level */
00670     gcomprisBoard->sublevel=1;
00671     gcomprisBoard->level++;
00672     if(gcomprisBoard->level>gcomprisBoard->maxlevel) { // the current board is finished : bail out
00673       gc_bonus_end_display(BOARD_FINISHED_RANDOM);
00674       return;
00675     }
00676     gc_sound_play_ogg ("sounds/bonus.ogg", NULL);
00677   }
00678   reversecount_next_level();
00679 }
00680 
00681 /* ==================================== */
00686 static gint
00687 item_event(GnomeCanvasItem *item, GdkEvent *event, gint *dice_index)
00688 {
00689   gchar *str;
00690   GdkPixbuf   *pixmap = NULL;
00691   gint i = *dice_index;
00692 
00693   if(board_paused)
00694     return FALSE;
00695 
00696   switch (event->type)
00697     {
00698     case GDK_BUTTON_PRESS:
00699       switch(event->button.button)
00700        {
00701        case 1:
00702          if(dicevalue_array[i]++ >= max_dice_number)
00703            dicevalue_array[i] = (number_of_dices==1 ? 1 : 0);
00704          break;
00705        case 2:
00706        case 3:
00707          if(dicevalue_array[i]-- == (number_of_dices==1 ? 1 : 0))
00708            dicevalue_array[i] = max_dice_number;
00709          break;
00710        default:
00711          break;
00712        }
00713 
00714       str = g_strdup_printf("gcompris/dice/gnome-dice%d.png", dicevalue_array[i]);
00715 
00716       pixmap = gc_pixmap_load(str);
00717 
00718       /* Warning changing the image needs to update pixbuf_ref for the focus usage */
00719       gc_item_focus_free(item, NULL);
00720       gnome_canvas_item_set (item,
00721                           "pixbuf", pixmap,
00722                           NULL);
00723       gdk_pixbuf_unref(pixmap);
00724 
00725       g_free(str);
00726       break;
00727 
00728     default:
00729       break;
00730     }
00731 
00732   return FALSE;
00733 }
00734 
00735 /*
00736  * Clock management
00737  */
00738 static void create_clock(double x, double y, int value)
00739 {
00740   GdkPixbuf   *pixmap = NULL;
00741   char       *str = NULL;
00742 
00743   if(value<0)
00744     return;
00745 
00746   str = g_strdup_printf("%s%d.png", "gcompris/timers/clock",value);
00747 
00748   pixmap = gc_pixmap_load(str);
00749 
00750   clock_image_item = gnome_canvas_item_new (boardRootItem,
00751                                        gnome_canvas_pixbuf_get_type (),
00752                                        "pixbuf", pixmap,
00753                                        "x", (double) x,
00754                                        "y", (double) y,
00755                                        NULL);
00756 
00757   gdk_pixbuf_unref(pixmap);
00758   g_free(str);
00759 }
00760 
00761 static void update_clock(int value)
00762 {
00763   GdkPixbuf   *pixmap = NULL;
00764   char        *str = NULL;
00765 
00766   if(value<0)
00767     return;
00768 
00769   str = g_strdup_printf("%s%d.png", "gcompris/timers/clock",value);
00770 
00771   pixmap = gc_pixmap_load(str);
00772 
00773   gnome_canvas_item_set (clock_image_item,
00774                       "pixbuf", pixmap,
00775                       NULL);
00776 
00777   gdk_pixbuf_unref(pixmap);
00778   g_free(str);
00779 }
00780 
00781 static gint animate_tux()
00782 {
00783   // Move tux
00784   if(tuxItem!=NULL)
00785     gtk_object_destroy(GTK_OBJECT(tuxItem));
00786 
00787   tux_index++;
00788 
00789   g_warning("=========== tux_index=%d tux_destination=%d fish_index=%d\n", tux_index, tux_destination, fish_index);
00790 
00791   // Wrapping
00792   if(tux_index >= number_of_item)
00793     tux_index = tux_index - (number_of_item);
00794 
00795   /* Caclulate which tux should be displayed */
00796   if(tux_index<number_of_item_x-1)
00797     tuxItem = display_item_at(TUX_IMG_EAST, tux_index, tux_ratio);
00798   else if(tux_index<number_of_item_x+number_of_item_y-2)
00799     tuxItem = display_item_at(TUX_IMG_SOUTH, tux_index, tux_ratio);
00800   else if(tux_index<2*number_of_item_x+number_of_item_y-3)
00801     tuxItem = display_item_at(TUX_IMG_WEST, tux_index, tux_ratio);
00802   else
00803     tuxItem = display_item_at(TUX_IMG_NORTH, tux_index, tux_ratio);
00804 
00805   /* Rearm the timer to go to the next spot */
00806   if(tux_index != tux_destination)
00807     {
00808       animate_id = gtk_timeout_add (animate_speed,
00809                                 (GtkFunction) animate_tux, NULL);
00810     }
00811   else
00812     {
00813       animate_id = 0;
00814 
00815       if(tux_destination != fish_index)
00816        {
00817          process_error();
00818        }
00819       else
00820        {
00821          // Remove the fish
00822          if(fishItem!=NULL)
00823            gtk_object_destroy(GTK_OBJECT(fishItem));
00824 
00825          gc_sound_play_ogg ("sounds/gobble.ogg", NULL);
00826 
00827          if(--number_of_fish == 0)
00828            {
00829              gamewon = TRUE;
00830              reversecount_destroy_all_items();
00831              gc_bonus_display(gamewon, BONUS_SMILEY);
00832            }
00833          else
00834            {
00835              display_random_fish();
00836            }
00837        }
00838     }
00839 
00840   return(FALSE);
00841 }