~ubuntu-branches/ubuntu/maverick/gcompris/maverick

« back to all changes in this revision

Viewing changes to src/reversecount-activity/reversecount.c

  • Committer: Bazaar Package Importer
  • Author(s): Marc Gariepy, Marc Gariepy, Stephane Graber
  • Date: 2010-01-04 17:42:49 UTC
  • mfrom: (1.1.14 upstream)
  • Revision ID: james.westby@ubuntu.com-20100104174249-7bupatd9dtxyhvs4
Tags: 9.0-0ubuntu1
[Marc Gariepy]
* New upstream release (9.0).
* Remove cache.c from POTFILES to avoid FTBFS
* Remove unneeded rm in debian/rules (file no longer exists upstream)

[Stephane Graber]
* Bump Debian standards to 3.8.3
* Add patch system (dpatch)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* gcompris - reversecount.c
 
2
 *
 
3
 * Copyright (C) 2002, 2008 Bruno Coudoin
 
4
 *
 
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.
 
9
 *
 
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.
 
14
 *
 
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/>.
 
17
 */
 
18
 
 
19
#include "gcompris/gcompris.h"
 
20
 
 
21
#define SOUNDLISTFILE PACKAGE
 
22
 
 
23
static GcomprisBoard    *gcomprisBoard = NULL;
 
24
static gboolean  board_paused = TRUE;
 
25
static gint      animate_id = 0;
 
26
 
 
27
static void      start_board (GcomprisBoard *agcomprisBoard);
 
28
static gint      key_press(guint keyval, gchar *commit_str, gchar *preedit_str);
 
29
static void      pause_board (gboolean pause);
 
30
static void      end_board (void);
 
31
static gboolean  is_our_board (GcomprisBoard *gcomprisBoard);
 
32
static void      set_level (guint level);
 
33
static int       gamewon;
 
34
static void      game_won(void);
 
35
 
 
36
#define NORTH 1
 
37
#define WEST 2
 
38
#define SOUTH 4
 
39
#define EAST 8
 
40
 
 
41
#define TUX_TO_BORDER_GAP 10
 
42
 
 
43
static GooCanvasItem *boardRootItem = NULL;
 
44
 
 
45
static void              process_ok(void);
 
46
static void              process_error(void);
 
47
static GooCanvasItem    *reversecount_create_item(GooCanvasItem *parent);
 
48
static void              reversecount_destroy_all_items(void);
 
49
static void              reversecount_next_level(void);
 
50
static gboolean          item_event (GooCanvasItem  *item,
 
51
                                     GooCanvasItem  *target,
 
52
                                     GdkEventButton *event,
 
53
                                     gint *dice_index);
 
54
static GooCanvasItem    *display_item_at(gchar *imagename, int block);
 
55
static void              display_random_fish();
 
56
static void              create_clock(double x, double y, int value);
 
57
static void              update_clock(int value);
 
58
static gint              animate_tux();
 
59
static void              rotate_tux(GooCanvasItem *tuxitem, gint direction,
 
60
                                    gdouble scale);
 
61
static void              move_item_at(GooCanvasItem *item,
 
62
                                      int block, double ratio);
 
63
 
 
64
static int number_of_item   = 0;
 
65
static int number_of_item_x = 0;
 
66
static int number_of_item_y = 0;
 
67
 
 
68
static int errors           = 0;
 
69
static int number_of_dices  = 0;
 
70
static int max_dice_number  = 0;
 
71
static int number_of_fish   = 0;
 
72
 
 
73
static int tux_index        = 0;
 
74
static int tux_destination  = 0;
 
75
static int fish_index       = 0;
 
76
static int animate_speed    = 0;
 
77
 
 
78
#define ANIMATE_SPEED   800
 
79
 
 
80
static gdouble tux_ratio = 0;
 
81
 
 
82
static int dicevalue_array[10];
 
83
static GooCanvasItem *fishItem;
 
84
static GooCanvasItem *tuxItem;
 
85
static GooCanvasItem *tuxRootItem;
 
86
static GooCanvasItem *clock_image_item;
 
87
 
 
88
// List of images to use in the game
 
89
static gchar *imageList[] =
 
90
{
 
91
  "reversecount/baleine.svgz",
 
92
  "reversecount/phoque.svgz",
 
93
  "reversecount/ourspolaire.svgz",
 
94
  "reversecount/morse.svgz",
 
95
  "reversecount/elephant_mer.svgz",
 
96
  "reversecount/epaulard.svgz",
 
97
  "reversecount/narval.svgz",
 
98
};
 
99
#define NUMBER_OF_IMAGES 10
 
100
 
 
101
// List of fish to use in the game
 
102
static gchar *fishList[] =
 
103
{
 
104
  "reversecount/blueking2_0.png",
 
105
  "reversecount/butfish_0.png",
 
106
  "reversecount/cichlid1_0.png",
 
107
  "reversecount/cichlid4_0.png",
 
108
  "reversecount/collaris_0.png",
 
109
  "reversecount/discus2_0.png",
 
110
  "reversecount/discus3_0.png",
 
111
  "reversecount/eel_0.png",
 
112
  "reversecount/f00_0.png",
 
113
  "reversecount/f01_0.png",
 
114
  "reversecount/f02_0.png",
 
115
  "reversecount/f03_0.png",
 
116
  "reversecount/f04_0.png",
 
117
  "reversecount/f05_0.png",
 
118
  "reversecount/f06_0.png",
 
119
  "reversecount/f07_0.png",
 
120
  "reversecount/f08_0.png",
 
121
  "reversecount/f09_0.png",
 
122
  "reversecount/f10_0.png",
 
123
  "reversecount/f11_0.png",
 
124
  "reversecount/f12_0.png",
 
125
  "reversecount/f13_0.png",
 
126
  "reversecount/manta_0.png",
 
127
  "reversecount/newf1_0.png",
 
128
  "reversecount/QueenAngel_0.png",
 
129
  "reversecount/shark1_0.png",
 
130
  "reversecount/six_barred_0.png",
 
131
  "reversecount/teeth_0.png"
 
132
};
 
133
#define NUMBER_OF_FISHES 27
 
134
 
 
135
/* Description of this plugin */
 
136
static BoardPlugin menu_bp =
 
137
  {
 
138
    NULL,
 
139
    NULL,
 
140
    "Reverse count",
 
141
    "Practice substraction with a funny game",
 
142
    "Bruno Coudoin <bruno.coudoin@free.fr>",
 
143
    NULL,
 
144
    NULL,
 
145
    NULL,
 
146
    NULL,
 
147
    start_board,
 
148
    pause_board,
 
149
    end_board,
 
150
    is_our_board,
 
151
    key_press,
 
152
    NULL,
 
153
    set_level,
 
154
    NULL,
 
155
    NULL,
 
156
    NULL,
 
157
    NULL
 
158
  };
 
159
 
 
160
/*
 
161
 * Main entry point mandatory for each Gcompris's game
 
162
 * ---------------------------------------------------
 
163
 *
 
164
 */
 
165
 
 
166
GET_BPLUGIN_INFO(reversecount)
 
167
 
 
168
/*
 
169
 * in : boolean TRUE = PAUSE : FALSE = CONTINUE
 
170
 *
 
171
 */
 
172
static void pause_board (gboolean pause)
 
173
{
 
174
  if(gcomprisBoard==NULL)
 
175
    return;
 
176
 
 
177
  if(gamewon == TRUE && pause == FALSE) /* the game is won */
 
178
    {
 
179
      game_won();
 
180
    }
 
181
 
 
182
 
 
183
  board_paused = pause;
 
184
}
 
185
 
 
186
/*
 
187
 */
 
188
static void start_board (GcomprisBoard *agcomprisBoard)
 
189
{
 
190
 
 
191
  if(agcomprisBoard!=NULL)
 
192
    {
 
193
      gcomprisBoard=agcomprisBoard;
 
194
 
 
195
      /* disable im_context */
 
196
      gcomprisBoard->disable_im_context = TRUE;
 
197
 
 
198
      gcomprisBoard->level=1;
 
199
      gcomprisBoard->maxlevel=7;
 
200
      gcomprisBoard->sublevel=1;
 
201
      gcomprisBoard->number_of_sublevel=1; /* Go to next level after this number of 'play' */
 
202
      gc_bar_set(GC_BAR_LEVEL);
 
203
      gc_bar_location(10, -1, 0.7);
 
204
 
 
205
      reversecount_next_level();
 
206
 
 
207
      gamewon = FALSE;
 
208
 
 
209
      pause_board(FALSE);
 
210
    }
 
211
}
 
212
/* ======================================= */
 
213
static void end_board ()
 
214
{
 
215
  if(gcomprisBoard!=NULL)
 
216
    {
 
217
      pause_board(TRUE);
 
218
      reversecount_destroy_all_items();
 
219
    }
 
220
  gcomprisBoard = NULL;
 
221
}
 
222
 
 
223
/* ======================================= */
 
224
static void set_level (guint level)
 
225
{
 
226
 
 
227
  if(gcomprisBoard!=NULL)
 
228
    {
 
229
      gcomprisBoard->level=level;
 
230
      gcomprisBoard->sublevel=1;
 
231
      reversecount_next_level();
 
232
    }
 
233
}
 
234
 
 
235
/* ======================================= */
 
236
gboolean is_our_board (GcomprisBoard *gcomprisBoard)
 
237
{
 
238
  if (gcomprisBoard)
 
239
    {
 
240
      if(g_strcasecmp(gcomprisBoard->type, "reversecount")==0)
 
241
        {
 
242
          /* Set the plugin entry */
 
243
          gcomprisBoard->plugin=&menu_bp;
 
244
 
 
245
          return TRUE;
 
246
        }
 
247
    }
 
248
  return FALSE;
 
249
}
 
250
 
 
251
/* ======================================= */
 
252
gint key_press(guint keyval, gchar *commit_str, gchar *preedit_str)
 
253
{
 
254
 
 
255
  if(!gcomprisBoard)
 
256
    return FALSE;
 
257
 
 
258
  /* Add some filter for control and shift key */
 
259
  switch (keyval)
 
260
    {
 
261
      /* Avoid all this keys to be interpreted by this game */
 
262
    case GDK_Shift_L:
 
263
    case GDK_Shift_R:
 
264
    case GDK_Control_L:
 
265
    case GDK_Control_R:
 
266
    case GDK_Caps_Lock:
 
267
    case GDK_Shift_Lock:
 
268
    case GDK_Meta_L:
 
269
    case GDK_Meta_R:
 
270
    case GDK_Alt_L:
 
271
    case GDK_Alt_R:
 
272
    case GDK_Super_L:
 
273
    case GDK_Super_R:
 
274
    case GDK_Hyper_L:
 
275
    case GDK_Hyper_R:
 
276
    case GDK_Num_Lock:
 
277
      return FALSE;
 
278
    case GDK_KP_Enter:
 
279
    case GDK_Return:
 
280
      process_ok();
 
281
      return TRUE;
 
282
    }
 
283
 
 
284
  return TRUE;
 
285
}
 
286
 
 
287
 
 
288
static void process_error()
 
289
{
 
290
  gc_sound_play_ogg ("sounds/crash.wav", NULL);
 
291
  errors--;
 
292
  if(errors==0)
 
293
    {
 
294
      gamewon = FALSE;
 
295
      reversecount_destroy_all_items();
 
296
      gc_bonus_display(gamewon, GC_BONUS_SMILEY);
 
297
    }
 
298
  else
 
299
    {
 
300
      update_clock(errors);
 
301
    }
 
302
}
 
303
 
 
304
/* ======================================= */
 
305
static void process_ok()
 
306
{
 
307
  guint i;
 
308
 
 
309
  tux_destination = tux_index;
 
310
 
 
311
  for(i=0; i<number_of_dices; i++)
 
312
      tux_destination += dicevalue_array[i];
 
313
 
 
314
  // Wrapping
 
315
  if(tux_destination >= number_of_item)
 
316
    tux_destination = tux_destination - (number_of_item);
 
317
 
 
318
  // Do not allow going at a position after the fish
 
319
  if((tux_destination > fish_index)
 
320
     || (tux_destination == tux_index))
 
321
    {
 
322
      process_error();
 
323
      return;
 
324
    }
 
325
 
 
326
  if(!animate_id) {
 
327
    animate_id = gtk_timeout_add (animate_speed,
 
328
                                  (GtkFunction) animate_tux, NULL);
 
329
  }
 
330
 
 
331
}
 
332
 
 
333
/*-------------------------------------------------------------------------------*/
 
334
/*-------------------------------------------------------------------------------*/
 
335
 
 
336
/* set initial values for the next level */
 
337
static void reversecount_next_level()
 
338
{
 
339
 
 
340
  gc_set_background(goo_canvas_get_root_item(gcomprisBoard->canvas),
 
341
                    imageList[gcomprisBoard->level-1]);
 
342
 
 
343
  reversecount_destroy_all_items();
 
344
  gamewon = FALSE;
 
345
 
 
346
  /* Select level difficulty */
 
347
  switch(gcomprisBoard->level)
 
348
    {
 
349
    case 1:
 
350
      number_of_item_x = 5;
 
351
      number_of_item_y = 5;
 
352
      number_of_dices = 1;
 
353
      max_dice_number = 3;
 
354
      number_of_fish = 3;
 
355
      break;
 
356
    case 2:
 
357
      number_of_item_x = 5;
 
358
      number_of_item_y = 5;
 
359
      number_of_dices = 1;
 
360
      max_dice_number = 6;
 
361
      number_of_fish = 6;
 
362
      break;
 
363
    case 3:
 
364
      number_of_item_x = 6;
 
365
      number_of_item_y = 6;
 
366
      number_of_dices = 1;
 
367
      max_dice_number = 9;
 
368
      number_of_fish = 6;
 
369
      break;
 
370
    case 4:
 
371
      number_of_item_x = 8;
 
372
      number_of_item_y = 6;
 
373
      number_of_dices = 1;
 
374
      max_dice_number = 3;
 
375
      number_of_fish = 6;
 
376
      break;
 
377
    case 5:
 
378
      number_of_item_x = 8;
 
379
      number_of_item_y = 6;
 
380
      number_of_dices = 2;
 
381
      max_dice_number = 6;
 
382
      number_of_fish = 10;
 
383
      break;
 
384
    case 6:
 
385
      number_of_item_x = 8;
 
386
      number_of_item_y = 8;
 
387
      number_of_dices = 2;
 
388
      max_dice_number = 9;
 
389
      number_of_fish = 10;
 
390
      break;
 
391
    default:
 
392
      number_of_item_x = 10;
 
393
      number_of_item_y = 10;
 
394
      number_of_dices = 3;
 
395
      max_dice_number = 9;
 
396
      number_of_fish = 10;
 
397
      break;
 
398
    }
 
399
 
 
400
  animate_speed = ANIMATE_SPEED - gcomprisBoard->level * 60;
 
401
 
 
402
  number_of_item = number_of_item_x * 2 + (number_of_item_y - 2) * 2;
 
403
 
 
404
  /* Try the next level */
 
405
  reversecount_create_item(goo_canvas_get_root_item(gcomprisBoard->canvas));
 
406
 
 
407
  gc_bar_set_level(gcomprisBoard);
 
408
 
 
409
}
 
410
/* ==================================== */
 
411
/* Destroy all the items */
 
412
static void reversecount_destroy_all_items()
 
413
{
 
414
 
 
415
  gc_timer_end();
 
416
 
 
417
  if(boardRootItem!=NULL)
 
418
    goo_canvas_item_remove(boardRootItem);
 
419
 
 
420
  boardRootItem = NULL;
 
421
}
 
422
/* ==================================== */
 
423
static GooCanvasItem *reversecount_create_item(GooCanvasItem *parent)
 
424
{
 
425
  gint i, j, d;
 
426
  GooCanvasItem *item = NULL;
 
427
  gdouble block_width, block_height;
 
428
  gdouble dice_area_x;
 
429
  gdouble xratio, yratio;
 
430
  GcomprisProperties    *properties = gc_prop_get();
 
431
  RsvgHandle *svg_handle;
 
432
 
 
433
  boardRootItem = goo_canvas_group_new (goo_canvas_get_root_item(gcomprisBoard->canvas),
 
434
                                        NULL);
 
435
 
 
436
 
 
437
  block_width =  BOARDWIDTH/number_of_item_x;
 
438
  block_height = (BOARDHEIGHT-BARHEIGHT)/number_of_item_y;
 
439
 
 
440
  /* Timer is not requested */
 
441
  if(properties->timer > 0)
 
442
    {
 
443
      errors = number_of_dices + 4 - (MIN(properties->timer, 4));
 
444
      create_clock(BOARDWIDTH - block_width - 100,
 
445
                   BOARDHEIGHT - block_height - 100 - BARHEIGHT,
 
446
                   errors) ;
 
447
    }
 
448
  else
 
449
    {
 
450
      errors = -1;
 
451
    }
 
452
 
 
453
  // Ice blocks
 
454
  svg_handle = gc_rsvg_load("reversecount/iceblock.svgz");
 
455
  RsvgDimensionData rsvg_dimension;
 
456
  rsvg_handle_get_dimensions (svg_handle, &rsvg_dimension);
 
457
 
 
458
  xratio = block_width / rsvg_dimension.width;
 
459
  yratio =  block_height / rsvg_dimension.height;
 
460
 
 
461
  for(i=0; i<BOARDWIDTH; i+=block_width)
 
462
    {
 
463
      j=0;
 
464
      item = goo_canvas_svg_new (boardRootItem, svg_handle, NULL);
 
465
      goo_canvas_item_translate(item, i, j);
 
466
      goo_canvas_item_scale(item, xratio, yratio);
 
467
 
 
468
      j=BOARDHEIGHT-BARHEIGHT-block_height;
 
469
      item = goo_canvas_svg_new (boardRootItem, svg_handle, NULL);
 
470
      goo_canvas_item_translate(item, i, j);
 
471
      goo_canvas_item_scale(item, xratio, yratio);
 
472
    }
 
473
 
 
474
  for(j = block_height; j<=BOARDHEIGHT - (block_height*2) - BARHEIGHT;
 
475
      j += block_height)
 
476
    {
 
477
      i = 0;
 
478
      item = goo_canvas_svg_new (boardRootItem, svg_handle, NULL);
 
479
      goo_canvas_item_translate(item, i, j);
 
480
      goo_canvas_item_scale(item, xratio, yratio);
 
481
 
 
482
 
 
483
      i = BOARDWIDTH - block_width;
 
484
      item = goo_canvas_svg_new (boardRootItem, svg_handle, NULL);
 
485
      goo_canvas_item_translate(item, i, j);
 
486
      goo_canvas_item_scale(item, xratio, yratio);
 
487
    }
 
488
 
 
489
  g_object_unref(svg_handle);
 
490
 
 
491
 
 
492
  //----------------------------------------
 
493
  // Create the dice area
 
494
  svg_handle = gc_rsvg_load("reversecount/dice_area.svgz");
 
495
  rsvg_handle_get_dimensions (svg_handle, &rsvg_dimension);
 
496
 
 
497
  dice_area_x = BOARDWIDTH - block_width - rsvg_dimension.width - 20;
 
498
 
 
499
  item = goo_canvas_svg_new (boardRootItem, svg_handle, NULL);
 
500
  goo_canvas_item_translate(item,
 
501
                            dice_area_x, block_height + 20);
 
502
 
 
503
  g_object_unref(svg_handle);
 
504
 
 
505
  //----------------------------------------
 
506
  // Create the dices
 
507
  svg_handle = gc_rsvg_load("reversecount/dice1.svgz");
 
508
  rsvg_handle_get_dimensions (svg_handle, &rsvg_dimension);
 
509
  guint dice_width = 78;
 
510
 
 
511
  for(d=0; d<number_of_dices; d++)
 
512
    {
 
513
      int *val;
 
514
 
 
515
      i = dice_area_x + dice_width * d + 20;
 
516
      j = block_height + 24 + d*7;
 
517
 
 
518
      item = goo_canvas_svg_new (boardRootItem, svg_handle, NULL);
 
519
      goo_canvas_item_translate(item,
 
520
                                i, j);
 
521
 
 
522
      xratio = (gdouble)dice_width / rsvg_dimension.width;
 
523
      goo_canvas_item_scale(item, xratio, xratio);
 
524
 
 
525
      dicevalue_array[d] = 1;
 
526
      val = g_new(gint, 1);
 
527
      *val = d;
 
528
 
 
529
      g_signal_connect(item, "button_press_event",
 
530
                       (GtkSignalFunc) item_event,
 
531
                       val);
 
532
      gc_item_focus_init(item, NULL);
 
533
    }
 
534
  g_object_unref(svg_handle);
 
535
 
 
536
  // OK Button (Validation)
 
537
  item = goo_canvas_svg_new (boardRootItem,
 
538
                             gc_skin_rsvg_get(),
 
539
                             "svg-id", "#OK",
 
540
                             NULL);
 
541
  SET_ITEM_LOCATION(item,
 
542
                    dice_area_x - 60,
 
543
                    block_height + 20);
 
544
  g_signal_connect(item, "button_press_event",
 
545
                   (GtkSignalFunc) process_ok, NULL);
 
546
  gc_item_focus_init(item, NULL);
 
547
 
 
548
  // Tux
 
549
  tuxRootItem = goo_canvas_group_new (boardRootItem, NULL);
 
550
 
 
551
  svg_handle = gc_rsvg_load("reversecount/tux_top_south.svgz");
 
552
  tuxItem = goo_canvas_svg_new (tuxRootItem, svg_handle, NULL);
 
553
 
 
554
  RsvgDimensionData dimension;
 
555
  rsvg_handle_get_dimensions(svg_handle, &dimension);
 
556
 
 
557
  /* Calc the tux best ratio to display it */
 
558
  xratio =  block_width  / (dimension.width + TUX_TO_BORDER_GAP);
 
559
  yratio =  block_height / (dimension.height + TUX_TO_BORDER_GAP);
 
560
  tux_ratio = yratio = MIN(xratio, yratio);
 
561
 
 
562
  goo_canvas_item_scale(tuxItem, tux_ratio, tux_ratio);
 
563
 
 
564
  goo_canvas_item_translate(tuxItem, (BOARDWIDTH - dimension.width)/2,
 
565
                            (BOARDHEIGHT - dimension.height)/2);
 
566
  rotate_tux(tuxItem, EAST, tux_ratio);
 
567
  g_object_unref (svg_handle);
 
568
 
 
569
  tux_index = 0;
 
570
 
 
571
  // Display the first fish
 
572
  display_random_fish();
 
573
 
 
574
  return NULL;
 
575
}
 
576
 
 
577
static void display_random_fish()
 
578
{
 
579
 
 
580
  fish_index = tux_index +
 
581
    g_random_int()%(max_dice_number*number_of_dices) + 1;
 
582
 
 
583
  // Wrapping
 
584
  if(fish_index >= number_of_item)
 
585
    fish_index = fish_index - (number_of_item);
 
586
 
 
587
  fishItem = display_item_at(fishList[g_random_int()%NUMBER_OF_FISHES],
 
588
                             fish_index);
 
589
}
 
590
 
 
591
/* ==================================== */
 
592
/**
 
593
 * Display given imagename on the given ice block.
 
594
 */
 
595
static GooCanvasItem*
 
596
display_item_at(gchar *imagename, int block)
 
597
{
 
598
  double block_width, block_height;
 
599
  double xratio, yratio;
 
600
  GooCanvasItem *item;
 
601
  GdkPixbuf *pixmap;
 
602
  GdkPixbuf *pixmap2;
 
603
  int i,j;
 
604
 
 
605
  block_width  = BOARDWIDTH/number_of_item_x;
 
606
  block_height = (BOARDHEIGHT-BARHEIGHT)/number_of_item_y;
 
607
 
 
608
  if(block < number_of_item_x)
 
609
    {
 
610
      // Upper line
 
611
      g_warning("      // Upper line\n");
 
612
      i = block_width * block;
 
613
      j = 0;
 
614
    }
 
615
  else if(block < number_of_item_x + number_of_item_y - 2)
 
616
    {
 
617
      // Right line
 
618
      g_warning("      // Right line\n");
 
619
      i = block_width * (number_of_item_x - 1);
 
620
      j = block_height * (block - (number_of_item_x-1));
 
621
    }
 
622
  else if(block < number_of_item_x*2 + number_of_item_y - 2)
 
623
    {
 
624
      // Bottom line
 
625
      g_warning("      // Bottom line\n");
 
626
      i = block_width * (number_of_item_x - (block-
 
627
                                             (number_of_item_x+number_of_item_y-1))-2);
 
628
      j = block_height * (number_of_item_y-1);
 
629
    }
 
630
  else
 
631
    {
 
632
      // Left line
 
633
      g_warning("      // Left line\n");
 
634
      i = 0;
 
635
      j = block_height * (number_of_item_y - (block - (number_of_item_x*2 +
 
636
                                                      number_of_item_y-4)));
 
637
    }
 
638
 
 
639
  g_warning("display_tux %d i=%d j=%d\n", block, i, j);
 
640
 
 
641
  /* Calculation to thrink the item while keeping the ratio */
 
642
  pixmap = gc_pixmap_load(imagename);
 
643
  xratio =  block_width  / (gdk_pixbuf_get_width (pixmap) + TUX_TO_BORDER_GAP);
 
644
  yratio =  block_height / (gdk_pixbuf_get_height(pixmap) + TUX_TO_BORDER_GAP);
 
645
  xratio = yratio = MIN(xratio, yratio);
 
646
 
 
647
  pixmap2 = gdk_pixbuf_scale_simple(pixmap,
 
648
                                    gdk_pixbuf_get_width (pixmap) * xratio,
 
649
                                    gdk_pixbuf_get_height(pixmap) * xratio,
 
650
                                    GDK_INTERP_BILINEAR);
 
651
  gdk_pixbuf_unref(pixmap);
 
652
 
 
653
  item = goo_canvas_image_new (boardRootItem,
 
654
                               pixmap2,
 
655
                               i + (block_width -
 
656
                                    (gdk_pixbuf_get_width (pixmap2))) / 2,
 
657
                               j + (block_height -
 
658
                                    (gdk_pixbuf_get_height (pixmap2))) / 2,
 
659
                               NULL);
 
660
 
 
661
  gdk_pixbuf_unref(pixmap2);
 
662
 
 
663
  return(item);
 
664
}
 
665
 
 
666
/**
 
667
 * Move given GooCanvasItem on the given ice block.
 
668
 */
 
669
static void
 
670
move_item_at(GooCanvasItem *item, int block, double ratio)
 
671
{
 
672
  double block_width, block_height;
 
673
  int i,j;
 
674
  GooCanvasBounds bounds;
 
675
 
 
676
  block_width  = BOARDWIDTH/number_of_item_x;
 
677
  block_height = (BOARDHEIGHT-BARHEIGHT)/number_of_item_y;
 
678
 
 
679
  if(block < number_of_item_x)
 
680
    {
 
681
      // Upper line
 
682
      g_warning("      // Upper line\n");
 
683
      i = block_width * block;
 
684
      j = 0;
 
685
    }
 
686
  else if(block < number_of_item_x + number_of_item_y - 2)
 
687
    {
 
688
      // Right line
 
689
      g_warning("      // Right line\n");
 
690
      i = block_width * (number_of_item_x - 1);
 
691
      j = block_height * (block - (number_of_item_x-1));
 
692
    }
 
693
  else if(block < number_of_item_x*2 + number_of_item_y - 2)
 
694
    {
 
695
      // Bottom line
 
696
      g_warning("      // Bottom line\n");
 
697
      i = block_width * (number_of_item_x - (block-
 
698
                                             (number_of_item_x+number_of_item_y-1))-2);
 
699
      j = block_height * (number_of_item_y-1);
 
700
    }
 
701
  else
 
702
    {
 
703
      // Left line
 
704
      g_warning("      // Left line\n");
 
705
      i = 0;
 
706
      j = block_height * (number_of_item_y - (block - (number_of_item_x*2 +
 
707
                                                      number_of_item_y-4)));
 
708
    }
 
709
 
 
710
  g_warning("move_item_at %d i=%d j=%d\n", block, i, j);
 
711
 
 
712
  goo_canvas_item_get_bounds(item, &bounds);
 
713
 
 
714
  goo_canvas_item_animate(item,
 
715
                          i,
 
716
                          j,
 
717
                          1.0,
 
718
                          0,
 
719
                          TRUE,
 
720
                          animate_speed,
 
721
                          40,
 
722
                          GOO_CANVAS_ANIMATE_FREEZE);
 
723
 
 
724
}
 
725
 
 
726
/* ==================================== */
 
727
static void game_won()
 
728
{
 
729
  gcomprisBoard->sublevel++;
 
730
 
 
731
  if(gcomprisBoard->sublevel>gcomprisBoard->number_of_sublevel) {
 
732
    /* Try the next level */
 
733
    gcomprisBoard->sublevel=1;
 
734
    gcomprisBoard->level++;
 
735
    if(gcomprisBoard->level> gcomprisBoard->maxlevel) { // the current board is finished : bail out
 
736
      gcomprisBoard->level = gcomprisBoard->maxlevel;
 
737
      return;
 
738
    }
 
739
    gc_sound_play_ogg ("sounds/bonus.wav", NULL);
 
740
  }
 
741
  reversecount_next_level();
 
742
}
 
743
 
 
744
/* ==================================== */
 
745
/**
 
746
 * Increment the dices when they are clicked
 
747
 */
 
748
 
 
749
static gboolean
 
750
item_event (GooCanvasItem  *item,
 
751
            GooCanvasItem  *target,
 
752
            GdkEventButton *event,
 
753
            gint *dice_index)
 
754
{
 
755
  gchar *str;
 
756
  RsvgHandle *rsvg_handle;
 
757
  gint i = *dice_index;
 
758
 
 
759
  if(board_paused)
 
760
    return FALSE;
 
761
 
 
762
  switch(event->button)
 
763
    {
 
764
    case 1:
 
765
      if(dicevalue_array[i]++ >= max_dice_number)
 
766
        dicevalue_array[i] = (number_of_dices==1 ? 1 : 0);
 
767
      break;
 
768
    case 2:
 
769
    case 3:
 
770
      if(dicevalue_array[i]-- == (number_of_dices==1 ? 1 : 0))
 
771
        dicevalue_array[i] = max_dice_number;
 
772
      break;
 
773
    default:
 
774
      break;
 
775
    }
 
776
 
 
777
  str = g_strdup_printf("reversecount/dice%d.svgz", dicevalue_array[i]);
 
778
  rsvg_handle = gc_rsvg_load(str);
 
779
 
 
780
  g_object_set (item,
 
781
                "svg-handle", rsvg_handle,
 
782
                NULL);
 
783
  gc_item_focus_init(item, NULL);
 
784
  g_object_unref(rsvg_handle);
 
785
 
 
786
  g_free(str);
 
787
 
 
788
  return FALSE;
 
789
}
 
790
 
 
791
/*
 
792
 * Clock management
 
793
 */
 
794
static void create_clock(double x, double y, int value)
 
795
{
 
796
  GdkPixbuf   *pixmap = NULL;
 
797
  char        *str = NULL;
 
798
 
 
799
  if(value<0)
 
800
    return;
 
801
 
 
802
  str = g_strdup_printf("%s%d.png", "timers/clock",value);
 
803
 
 
804
  pixmap = gc_skin_pixmap_load(str);
 
805
 
 
806
  clock_image_item = goo_canvas_image_new (boardRootItem,
 
807
                                           pixmap,
 
808
                                           x,
 
809
                                           y,
 
810
                                           NULL);
 
811
 
 
812
  gdk_pixbuf_unref(pixmap);
 
813
  g_free(str);
 
814
}
 
815
 
 
816
static void update_clock(int value)
 
817
{
 
818
  GdkPixbuf   *pixmap = NULL;
 
819
  char        *str = NULL;
 
820
 
 
821
  if(value<0)
 
822
    return;
 
823
 
 
824
  str = g_strdup_printf("%s%d.png", "timers/clock",value);
 
825
 
 
826
  pixmap = gc_skin_pixmap_load(str);
 
827
 
 
828
  g_object_set (clock_image_item,
 
829
                "pixbuf", pixmap,
 
830
                NULL);
 
831
 
 
832
  gdk_pixbuf_unref(pixmap);
 
833
  g_free(str);
 
834
}
 
835
 
 
836
static gint animate_tux()
 
837
{
 
838
  // Move tux
 
839
  tux_index++;
 
840
 
 
841
  move_item_at(tuxRootItem, tux_index, tux_ratio);
 
842
 
 
843
  g_warning("=========== tux_index=%d tux_destination=%d fish_index=%d\n",
 
844
            tux_index, tux_destination, fish_index);
 
845
 
 
846
  // Wrapping
 
847
  if(tux_index >= number_of_item)
 
848
    tux_index = tux_index - (number_of_item);
 
849
 
 
850
  /* Calculate which tux should be displayed */
 
851
  if(tux_index<number_of_item_x-1)
 
852
    rotate_tux(tuxItem, EAST, tux_ratio);
 
853
  else if(tux_index<number_of_item_x+number_of_item_y-2)
 
854
    rotate_tux(tuxItem, SOUTH, tux_ratio);
 
855
  else if(tux_index<2*number_of_item_x+number_of_item_y-3)
 
856
    rotate_tux(tuxItem, WEST, tux_ratio);
 
857
  else
 
858
    rotate_tux(tuxItem, NORTH, tux_ratio);
 
859
 
 
860
  /* Rearm the timer to go to the next spot */
 
861
  if(tux_index != tux_destination)
 
862
    {
 
863
      animate_id = gtk_timeout_add (animate_speed,
 
864
                                    (GtkFunction) animate_tux, NULL);
 
865
    }
 
866
  else
 
867
    {
 
868
      animate_id = 0;
 
869
 
 
870
      if(tux_destination != fish_index)
 
871
        {
 
872
          process_error();
 
873
        }
 
874
      else
 
875
        {
 
876
          // Remove the fish
 
877
          if(fishItem!=NULL)
 
878
            goo_canvas_item_remove(fishItem);
 
879
 
 
880
          gc_sound_play_ogg ("sounds/gobble.wav", NULL);
 
881
 
 
882
          if(--number_of_fish == 0)
 
883
            {
 
884
              gamewon = TRUE;
 
885
              reversecount_destroy_all_items();
 
886
              gc_bonus_display(gamewon, GC_BONUS_SMILEY);
 
887
            }
 
888
          else
 
889
            {
 
890
              display_random_fish();
 
891
            }
 
892
        }
 
893
    }
 
894
 
 
895
  return(FALSE);
 
896
}
 
897
 
 
898
static void
 
899
rotate_tux(GooCanvasItem *tuxitem, gint direction,
 
900
           gdouble scale)
 
901
{
 
902
  gint rotation = 0;
 
903
  GooCanvasBounds bounds;
 
904
 
 
905
  /* Our svg image of tux is faced south */
 
906
  switch(direction)
 
907
    {
 
908
    case EAST:
 
909
      rotation = -90;
 
910
      break;
 
911
    case WEST:
 
912
      rotation = 90;
 
913
      break;
 
914
    case NORTH:
 
915
      rotation = 180;
 
916
      break;
 
917
    case SOUTH:
 
918
      rotation = 0;
 
919
      break;
 
920
    }
 
921
 
 
922
  goo_canvas_item_set_transform(tuxitem, NULL);
 
923
 
 
924
  goo_canvas_item_get_bounds(tuxitem, &bounds);
 
925
 
 
926
  goo_canvas_item_scale(tuxitem, scale, scale);
 
927
 
 
928
  goo_canvas_item_rotate(tuxitem, rotation,
 
929
                         (bounds.x2-bounds.x1)/2,
 
930
                         (bounds.y2-bounds.y1)/2);
 
931
 
 
932
}