~ml-launchpad/ubuntu/natty/gcompris/fix-for-777349

« back to all changes in this revision

Viewing changes to src/boards/canal_lock.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 - canal_lock.c
2
 
 *
3
 
 * Copyright (C) 2001 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
 
#define ANIMATE_SPEED 30
24
 
 
25
 
#define CANAL_COLOR             0x0010FFFF
26
 
#define LOCK_COLOR              0x8cc679FF
27
 
#define LOCK_COLOR_H            0x71A65FFF
28
 
#define CANALLOCK_COLOR         0xd1cd0cFF
29
 
#define CANALLOCK_COLOR_H       0xf1ed1cFF
30
 
#define GROUND_COLOR            0x9b5f5aFF
31
 
#define BASE_LINE               400
32
 
#define LEFT_CANAL_HEIGHT       100
33
 
#define LEFT_CANAL_WIDTH        325
34
 
#define RIGHT_CANAL_HEIGHT      200
35
 
#define RIGHT_CANAL_WIDTH       325
36
 
#define MIDDLE_CANAL_WIDTH      (BOARDWIDTH - RIGHT_CANAL_WIDTH -  LEFT_CANAL_WIDTH)
37
 
 
38
 
#define LOCK_WIDTH              20
39
 
#define LOCK_HEIGHT_MAX         (RIGHT_CANAL_HEIGHT + 40)
40
 
#define LOCK_HEIGHT_MIN         60
41
 
 
42
 
#define SUBCANAL_BASE_LINE      (BASE_LINE + 80)
43
 
#define SUBCANAL_HEIGHT         40
44
 
 
45
 
#define CANALLOCK_WIDTH         30
46
 
#define CANALLOCK_HEIGHT_MAX    SUBCANAL_HEIGHT
47
 
#define CANALLOCK_HEIGHT_MIN    15
48
 
 
49
 
static GcomprisBoard *gcomprisBoard = NULL;
50
 
static gboolean board_paused = TRUE;
51
 
 
52
 
static void      start_board (GcomprisBoard *agcomprisBoard);
53
 
static void      pause_board (gboolean pause);
54
 
static void      end_board (void);
55
 
static gboolean  is_our_board (GcomprisBoard *gcomprisBoard);
56
 
static void      set_level (guint level);
57
 
static int       gamewon;
58
 
static void      game_won(void);
59
 
 
60
 
static gint timer_id;
61
 
static gboolean animation;
62
 
 
63
 
static GnomeCanvasGroup *boardRootItem = NULL;
64
 
 
65
 
static GnomeCanvasItem  *lock_left_item         = NULL;
66
 
static GnomeCanvasItem  *lock_right_item        = NULL;
67
 
 
68
 
static GnomeCanvasItem  *canallock_left_item    = NULL;
69
 
static GnomeCanvasItem  *canallock_right_item   = NULL;
70
 
 
71
 
static GnomeCanvasItem  *canal_left_item        = NULL;
72
 
static GnomeCanvasItem  *canal_middle_item      = NULL;
73
 
static GnomeCanvasItem  *canal_right_item       = NULL;
74
 
 
75
 
static GnomeCanvasItem  *tuxboat_item           = NULL;
76
 
static double            tuxboat_width;
77
 
 
78
 
#define BOAT_POS_LEFT           1
79
 
#define BOAT_POS_MIDDLE         2
80
 
#define BOAT_POS_RIGHT          3
81
 
 
82
 
static guint boat_position;
83
 
static gboolean right_way;
84
 
static gboolean lock_left_up;
85
 
static gboolean lock_right_up;
86
 
static gboolean lock_water_low;
87
 
static gboolean canallock_left_up;
88
 
static gboolean canallock_right_up;
89
 
 
90
 
static double timer_item_x1, timer_item_y1, timer_item_x2, timer_item_y2;
91
 
static double timer_item_limit_y, timer_item_limit_x;
92
 
static GnomeCanvasItem *timer_item;
93
 
static gint timer_step_y1, timer_step_x1;
94
 
 
95
 
static GnomeCanvasItem  *canal_lock_create_item(GnomeCanvasGroup *parent);
96
 
static void              canal_lock_destroy_all_items(void);
97
 
static void              canal_lock_next_level(void);
98
 
static gint              item_event(GnomeCanvasItem *item, GdkEvent *event, gpointer data);
99
 
static gboolean          animate_step();
100
 
static void              update_water();
101
 
static void              toggle_lock(GnomeCanvasItem *item);
102
 
 
103
 
/* Description of this plugin */
104
 
static BoardPlugin menu_bp =
105
 
  {
106
 
    NULL,
107
 
    NULL,
108
 
    "Operate a canal lock",
109
 
    "Tux is in trouble in his ship. He needs to take it through a lock",
110
 
    "Bruno Coudoin <bruno.coudoin@free.fr>",
111
 
    NULL,
112
 
    NULL,
113
 
    NULL,
114
 
    NULL,
115
 
    start_board,
116
 
    pause_board,
117
 
    end_board,
118
 
    is_our_board,
119
 
    NULL,
120
 
    NULL,
121
 
    set_level,
122
 
    NULL,
123
 
    NULL,
124
 
    NULL,
125
 
    NULL
126
 
  };
127
 
 
128
 
/*
129
 
 * Main entry point mandatory for each Gcompris's game
130
 
 * ---------------------------------------------------
131
 
 *
132
 
 */
133
 
 
134
 
GET_BPLUGIN_INFO(canal_lock)
135
 
 
136
 
/*
137
 
 * in : boolean TRUE = PAUSE : FALSE = CONTINUE
138
 
 *
139
 
 */
140
 
static void pause_board (gboolean pause)
141
 
{
142
 
  if(gcomprisBoard==NULL)
143
 
    return;
144
 
 
145
 
  if(gamewon == TRUE && pause == FALSE) /* the game is won */
146
 
    {
147
 
      game_won();
148
 
    }
149
 
 
150
 
  board_paused = pause;
151
 
}
152
 
 
153
 
/*
154
 
 */
155
 
static void start_board (GcomprisBoard *agcomprisBoard)
156
 
{
157
 
 
158
 
  if(agcomprisBoard!=NULL)
159
 
    {
160
 
      gcomprisBoard=agcomprisBoard;
161
 
      gcomprisBoard->level=1;
162
 
      gcomprisBoard->maxlevel=2;
163
 
      gcomprisBoard->sublevel=1;
164
 
      gcomprisBoard->number_of_sublevel=1; /* Go to next level after this number of 'play' */
165
 
 
166
 
      canal_lock_next_level();
167
 
 
168
 
      gc_bar_set(0);
169
 
 
170
 
      animation = FALSE;
171
 
 
172
 
      gamewon = FALSE;
173
 
      pause_board(FALSE);
174
 
    }
175
 
}
176
 
/* ======================================= */
177
 
static void end_board ()
178
 
{
179
 
  // If we don't stop animation, there may be a segfault if leaving while the animation is running
180
 
  if (timer_id) {
181
 
    gtk_timeout_remove (timer_id);
182
 
    timer_id = 0;
183
 
  }
184
 
  animation = FALSE;
185
 
 
186
 
  if(gcomprisBoard!=NULL)
187
 
    {
188
 
      pause_board(TRUE);
189
 
      canal_lock_destroy_all_items();
190
 
    }
191
 
  gcomprisBoard = NULL;
192
 
}
193
 
 
194
 
/* ======================================= */
195
 
static void set_level (guint level)
196
 
{
197
 
 
198
 
  if(gcomprisBoard!=NULL)
199
 
    {
200
 
      gcomprisBoard->level=level;
201
 
      gcomprisBoard->sublevel=1;
202
 
      canal_lock_next_level();
203
 
    }
204
 
}
205
 
/* ======================================= */
206
 
static gboolean is_our_board (GcomprisBoard *gcomprisBoard)
207
 
{
208
 
  if (gcomprisBoard)
209
 
    {
210
 
      if(g_strcasecmp(gcomprisBoard->type, "canal_lock")==0)
211
 
        {
212
 
          /* Set the plugin entry */
213
 
          gcomprisBoard->plugin=&menu_bp;
214
 
 
215
 
          return TRUE;
216
 
        }
217
 
    }
218
 
  return FALSE;
219
 
}
220
 
 
221
 
/*-------------------------------------------------------------------------------*/
222
 
/*-------------------------------------------------------------------------------*/
223
 
/* set initial values for the next level */
224
 
static void canal_lock_next_level()
225
 
{
226
 
 
227
 
  gc_set_background(gnome_canvas_root(gcomprisBoard->canvas),
228
 
                          "canal_lock/canal_lock_bg.png");
229
 
 
230
 
  gc_bar_set_level(gcomprisBoard);
231
 
 
232
 
  canal_lock_destroy_all_items();
233
 
  gamewon = FALSE;
234
 
 
235
 
  /* Original state of the lock */
236
 
  boat_position = BOAT_POS_LEFT;
237
 
  right_way = TRUE;
238
 
  lock_left_up = TRUE;
239
 
  lock_right_up = TRUE;
240
 
  lock_water_low = TRUE;
241
 
  canallock_left_up = TRUE;
242
 
  canallock_right_up = TRUE;
243
 
 
244
 
  /* Try the next level */
245
 
  canal_lock_create_item(gnome_canvas_root(gcomprisBoard->canvas));
246
 
}
247
 
/* ==================================== */
248
 
/* Destroy all the items */
249
 
static void canal_lock_destroy_all_items()
250
 
{
251
 
  if(boardRootItem!=NULL)
252
 
    gtk_object_destroy (GTK_OBJECT(boardRootItem));
253
 
 
254
 
  boardRootItem = NULL;
255
 
}
256
 
/* ==================================== */
257
 
static GnomeCanvasItem *canal_lock_create_item(GnomeCanvasGroup *parent)
258
 
{
259
 
  GdkPixbuf *pixmap = NULL;
260
 
 
261
 
  boardRootItem = GNOME_CANVAS_GROUP(
262
 
                                     gnome_canvas_item_new (gnome_canvas_root(gcomprisBoard->canvas),
263
 
                                                            gnome_canvas_group_get_type (),
264
 
                                                            "x", (double) 0,
265
 
                                                            "y", (double) 0,
266
 
 
267
 
                                                            NULL));
268
 
 
269
 
  /* The boat */
270
 
  pixmap = gc_pixmap_load("gcompris/misc/tuxboat.png");
271
 
 
272
 
  tuxboat_item = gnome_canvas_item_new (boardRootItem,
273
 
                                        gnome_canvas_pixbuf_get_type (),
274
 
                                        "pixbuf",  pixmap,
275
 
                                        "x", (double) (LEFT_CANAL_WIDTH - gdk_pixbuf_get_width(pixmap)) / 2,
276
 
                                        "y", (double) BASE_LINE - LEFT_CANAL_HEIGHT - gdk_pixbuf_get_height(pixmap)*0.9,
277
 
                                        NULL);
278
 
  gtk_signal_connect(GTK_OBJECT(tuxboat_item), "event",
279
 
                     (GtkSignalFunc) item_event,
280
 
                     NULL);
281
 
  gtk_signal_connect(GTK_OBJECT(tuxboat_item), "event",
282
 
                     (GtkSignalFunc) gc_item_focus_event,
283
 
                     NULL);
284
 
  tuxboat_width = gdk_pixbuf_get_width(pixmap);
285
 
  gdk_pixbuf_unref(pixmap);
286
 
 
287
 
  /* This is the ground canal */
288
 
  gnome_canvas_item_new (boardRootItem,
289
 
                         gnome_canvas_rect_get_type (),
290
 
                         "x1", (double) 0,
291
 
                         "y1", (double) BASE_LINE,
292
 
                         "x2", (double) BOARDWIDTH,
293
 
                         "y2", (double) BOARDHEIGHT,
294
 
                         "fill_color_rgba", GROUND_COLOR,
295
 
                         "width_units", (double) 0,
296
 
                         NULL);
297
 
 
298
 
  /* This is the left canal */
299
 
  canal_left_item = gnome_canvas_item_new (boardRootItem,
300
 
                                            gnome_canvas_rect_get_type (),
301
 
                                            "x1", (double) 0,
302
 
                                            "y1", (double) BASE_LINE - LEFT_CANAL_HEIGHT,
303
 
                                            "x2", (double) LEFT_CANAL_WIDTH,
304
 
                                            "y2", (double) BASE_LINE,
305
 
                                            "fill_color_rgba", CANAL_COLOR,
306
 
                                            "width_units", (double) 0,
307
 
                                            NULL);
308
 
 
309
 
  /* This is the middle canal */
310
 
  canal_middle_item = gnome_canvas_item_new (boardRootItem,
311
 
                                             gnome_canvas_rect_get_type (),
312
 
                                             "x1", (double) LEFT_CANAL_WIDTH,
313
 
                                             "y1", (double) BASE_LINE - LEFT_CANAL_HEIGHT,
314
 
                                             "x2", (double) LEFT_CANAL_WIDTH + MIDDLE_CANAL_WIDTH,
315
 
                                             "y2", (double) BASE_LINE,
316
 
                                             "fill_color_rgba", CANAL_COLOR,
317
 
                                             "width_units", (double) 0,
318
 
                                             NULL);
319
 
 
320
 
  /* This is the right canal */
321
 
  canal_right_item = gnome_canvas_item_new (boardRootItem,
322
 
                                            gnome_canvas_rect_get_type (),
323
 
                                            "x1", (double) LEFT_CANAL_WIDTH + MIDDLE_CANAL_WIDTH,
324
 
                                            "y1", (double) BASE_LINE - RIGHT_CANAL_HEIGHT,
325
 
                                            "x2", (double) LEFT_CANAL_WIDTH + MIDDLE_CANAL_WIDTH + RIGHT_CANAL_WIDTH,
326
 
                                            "y2", (double) BASE_LINE,
327
 
                                            "fill_color_rgba", CANAL_COLOR,
328
 
                                            "width_units", (double) 0,
329
 
                                            NULL);
330
 
 
331
 
  /* This is the left lock */
332
 
  lock_left_item = gnome_canvas_item_new (boardRootItem,
333
 
                                          gnome_canvas_rect_get_type (),
334
 
                                          "x1", (double) LEFT_CANAL_WIDTH - LOCK_WIDTH / 2,
335
 
                                          "y1", (double) BASE_LINE - LOCK_HEIGHT_MAX,
336
 
                                          "x2", (double) LEFT_CANAL_WIDTH + LOCK_WIDTH / 2,
337
 
                                          "y2", (double) BASE_LINE,
338
 
                                          "fill_color_rgba", LOCK_COLOR,
339
 
                                          "width_units", (double) 0,
340
 
                                          NULL);
341
 
  gtk_signal_connect(GTK_OBJECT(lock_left_item), "event",
342
 
                     (GtkSignalFunc) item_event,
343
 
                     NULL);
344
 
 
345
 
  /* This is the right lock */
346
 
  lock_right_item = gnome_canvas_item_new (boardRootItem,
347
 
                                           gnome_canvas_rect_get_type (),
348
 
                                           "x1", (double) LEFT_CANAL_WIDTH + MIDDLE_CANAL_WIDTH - LOCK_WIDTH / 2,
349
 
                                           "y1", (double) BASE_LINE - LOCK_HEIGHT_MAX,
350
 
                                           "x2", (double) LEFT_CANAL_WIDTH + MIDDLE_CANAL_WIDTH + LOCK_WIDTH / 2,
351
 
                                           "y2", (double) BASE_LINE,
352
 
                                           "fill_color_rgba", LOCK_COLOR,
353
 
                                           "width_units", (double) 0,
354
 
                                           NULL);
355
 
  gtk_signal_connect(GTK_OBJECT(lock_right_item), "event",
356
 
                     (GtkSignalFunc) item_event,
357
 
                     NULL);
358
 
 
359
 
  /* This is the water conduit under the canal */
360
 
  gnome_canvas_item_new (boardRootItem,
361
 
                         gnome_canvas_rect_get_type (),
362
 
                         "x1", (double) LEFT_CANAL_WIDTH/2,
363
 
                         "y1", (double) SUBCANAL_BASE_LINE - SUBCANAL_HEIGHT,
364
 
                         "x2", (double) LEFT_CANAL_WIDTH + MIDDLE_CANAL_WIDTH + RIGHT_CANAL_WIDTH / 2 + SUBCANAL_HEIGHT,
365
 
                         "y2", (double) SUBCANAL_BASE_LINE,
366
 
                         "fill_color_rgba", CANAL_COLOR,
367
 
                         "width_units", (double) 0,
368
 
                         NULL);
369
 
 
370
 
  /* Left conduit */
371
 
  gnome_canvas_item_new (boardRootItem,
372
 
                         gnome_canvas_rect_get_type (),
373
 
                         "x1", (double) LEFT_CANAL_WIDTH/2,
374
 
                         "y1", (double) BASE_LINE,
375
 
                         "x2", (double) LEFT_CANAL_WIDTH/2 + SUBCANAL_HEIGHT,
376
 
                         "y2", (double) SUBCANAL_BASE_LINE,
377
 
                         "fill_color_rgba", CANAL_COLOR,
378
 
                         "width_units", (double) 0,
379
 
                         NULL);
380
 
 
381
 
  /* Middle conduit */
382
 
  gnome_canvas_item_new (boardRootItem,
383
 
                         gnome_canvas_rect_get_type (),
384
 
                         "x1", (double) LEFT_CANAL_WIDTH + MIDDLE_CANAL_WIDTH/2 - SUBCANAL_HEIGHT/2,
385
 
                         "y1", (double) BASE_LINE,
386
 
                         "x2", (double) LEFT_CANAL_WIDTH + MIDDLE_CANAL_WIDTH/2 + SUBCANAL_HEIGHT/2,
387
 
                         "y2", (double) SUBCANAL_BASE_LINE,
388
 
                         "fill_color_rgba", CANAL_COLOR,
389
 
                         "width_units", (double) 0,
390
 
                         NULL);
391
 
 
392
 
  /* Right conduit */
393
 
  gnome_canvas_item_new (boardRootItem,
394
 
                         gnome_canvas_rect_get_type (),
395
 
                         "x1", (double) LEFT_CANAL_WIDTH + MIDDLE_CANAL_WIDTH + RIGHT_CANAL_WIDTH/2,
396
 
                         "y1", (double) BASE_LINE,
397
 
                         "x2", (double) LEFT_CANAL_WIDTH + MIDDLE_CANAL_WIDTH + RIGHT_CANAL_WIDTH/2 + SUBCANAL_HEIGHT,
398
 
                         "y2", (double) SUBCANAL_BASE_LINE,
399
 
                         "fill_color_rgba", CANAL_COLOR,
400
 
                         "width_units", (double) 0,
401
 
                         NULL);
402
 
 
403
 
  /* And to finish, the 2 canal locks */
404
 
  canallock_left_item =
405
 
    gnome_canvas_item_new (boardRootItem,
406
 
                           gnome_canvas_rect_get_type (),
407
 
                           "x1", (double) LEFT_CANAL_WIDTH + MIDDLE_CANAL_WIDTH * 0.1,
408
 
                           "y1", (double) SUBCANAL_BASE_LINE - SUBCANAL_HEIGHT,
409
 
                           "x2", (double) LEFT_CANAL_WIDTH + MIDDLE_CANAL_WIDTH * 0.1 + LOCK_WIDTH / 2,
410
 
                           "y2", (double) SUBCANAL_BASE_LINE,
411
 
                           "fill_color_rgba", CANALLOCK_COLOR,
412
 
                           "width_units", (double) 0,
413
 
                           NULL);
414
 
  gtk_signal_connect(GTK_OBJECT(canallock_left_item), "event",
415
 
                     (GtkSignalFunc) item_event,
416
 
                     NULL);
417
 
 
418
 
  canallock_right_item =
419
 
    gnome_canvas_item_new (boardRootItem,
420
 
                           gnome_canvas_rect_get_type (),
421
 
                           "x1", (double) LEFT_CANAL_WIDTH + MIDDLE_CANAL_WIDTH * 0.9,
422
 
                           "y1", (double) SUBCANAL_BASE_LINE - SUBCANAL_HEIGHT,
423
 
                           "x2", (double) LEFT_CANAL_WIDTH + MIDDLE_CANAL_WIDTH * 0.9 + LOCK_WIDTH / 2,
424
 
                           "y2", (double) SUBCANAL_BASE_LINE,
425
 
                           "fill_color_rgba", CANALLOCK_COLOR,
426
 
                           "width_units", (double) 0,
427
 
                           NULL);
428
 
    gtk_signal_connect(GTK_OBJECT(canallock_right_item), "event",
429
 
                     (GtkSignalFunc) item_event,
430
 
                     NULL);
431
 
 
432
 
 
433
 
 
434
 
  return NULL;
435
 
}
436
 
/* ==================================== */
437
 
static void game_won()
438
 
{
439
 
  gcomprisBoard->sublevel++;
440
 
 
441
 
  if(gcomprisBoard->sublevel>gcomprisBoard->number_of_sublevel) {
442
 
    /* Try the next level */
443
 
    gcomprisBoard->sublevel=1;
444
 
    gcomprisBoard->level++;
445
 
    if(gcomprisBoard->level>gcomprisBoard->maxlevel) { // the current board is finished : bail out
446
 
      gc_bonus_end_display(GC_BOARD_FINISHED_RANDOM);
447
 
      return;
448
 
    }
449
 
    gc_sound_play_ogg ("sounds/bonus.wav", NULL);
450
 
  }
451
 
  canal_lock_next_level();
452
 
}
453
 
 
454
 
/* ==================================== */
455
 
/* Move the boat to the next possible position */
456
 
static void move_boat()
457
 
{
458
 
 
459
 
  /* If there is already an animation do nothing else set animation to avoid deadlock */
460
 
  if(animation)
461
 
    return;
462
 
  animation = TRUE;
463
 
 
464
 
  if(boat_position == BOAT_POS_LEFT && !lock_left_up)
465
 
    {
466
 
      boat_position = BOAT_POS_MIDDLE;
467
 
      timer_item_limit_x = LEFT_CANAL_WIDTH + (MIDDLE_CANAL_WIDTH - tuxboat_width)/2;
468
 
      timer_step_x1 = 2;
469
 
    }
470
 
  else if(boat_position == BOAT_POS_MIDDLE && !lock_left_up)
471
 
    {
472
 
      boat_position = BOAT_POS_LEFT;
473
 
      timer_item_limit_x = (LEFT_CANAL_WIDTH - tuxboat_width)/2;
474
 
      timer_step_x1 = -2;
475
 
    }
476
 
  else if(boat_position == BOAT_POS_MIDDLE && !lock_right_up)
477
 
    {
478
 
      boat_position = BOAT_POS_RIGHT;
479
 
      timer_item_limit_x = LEFT_CANAL_WIDTH + MIDDLE_CANAL_WIDTH + (RIGHT_CANAL_WIDTH - tuxboat_width)/2;
480
 
      timer_step_x1 = 2;
481
 
    }
482
 
  else if(boat_position == BOAT_POS_RIGHT && !lock_right_up)
483
 
    {
484
 
      boat_position = BOAT_POS_MIDDLE;
485
 
      timer_item_limit_x = LEFT_CANAL_WIDTH + (MIDDLE_CANAL_WIDTH - tuxboat_width)/2;
486
 
      timer_step_x1 = -2;
487
 
    }
488
 
  else
489
 
    {
490
 
      /* No possible move */
491
 
      gc_sound_play_ogg ("sounds/crash.ogg", NULL);
492
 
      animation = FALSE;
493
 
      return;
494
 
    }
495
 
 
496
 
  gc_sound_play_ogg ("sounds/eraser2.wav", NULL);
497
 
 
498
 
  gnome_canvas_item_get_bounds(tuxboat_item, &timer_item_x1, &timer_item_y1,
499
 
                               &timer_item_x2, &timer_item_y2);
500
 
 
501
 
  timer_item = tuxboat_item;
502
 
  timer_step_y1 = 0;
503
 
 
504
 
  timer_id = gtk_timeout_add (ANIMATE_SPEED, (GtkFunction) animate_step, NULL);
505
 
}
506
 
 
507
 
/* ==================================== */
508
 
/* Update the water level if necessary */
509
 
static void update_water()
510
 
{
511
 
  gboolean status = TRUE;
512
 
  double y1 = 0;
513
 
  gint min = LEFT_CANAL_HEIGHT;
514
 
 
515
 
  /* If there is already an animation do nothing else set animation to avoid deadlock */
516
 
  if(animation)
517
 
    return;
518
 
  animation = TRUE;
519
 
 
520
 
  if((!canallock_left_up && !lock_water_low) ||
521
 
     (!canallock_right_up && lock_water_low))
522
 
    {
523
 
      status = !lock_water_low;
524
 
      lock_water_low = !lock_water_low;
525
 
      y1 = BASE_LINE - RIGHT_CANAL_HEIGHT;
526
 
    }
527
 
  else
528
 
    {
529
 
      /* The water level is correct */
530
 
      animation = FALSE;
531
 
      return;
532
 
    }
533
 
 
534
 
  gnome_canvas_item_get_bounds(canal_middle_item, &timer_item_x1, &timer_item_y1,
535
 
                               &timer_item_x2, &timer_item_y2);
536
 
 
537
 
  timer_item = canal_middle_item;
538
 
  timer_item_limit_y = (status ? timer_item_y2 - min :
539
 
                        y1);
540
 
  timer_step_y1 = (status ? 2 : -2);
541
 
  timer_step_x1 = 0;
542
 
 
543
 
  timer_id = gtk_timeout_add (ANIMATE_SPEED, (GtkFunction) animate_step, NULL);
544
 
}
545
 
 
546
 
/* ==================================== */
547
 
/* Toggle the given lock */
548
 
static void toggle_lock(GnomeCanvasItem *item)
549
 
{
550
 
  gboolean status = TRUE;
551
 
  double y1 = 0;
552
 
  gint min = 0;
553
 
  guint animate_speed = 0;
554
 
 
555
 
  /* If there is already an animation do nothing else set animation to avoid deadlock */
556
 
  if(animation)
557
 
    return;
558
 
  animation = TRUE;
559
 
 
560
 
  gc_sound_play_ogg ("sounds/bleep.wav", NULL);
561
 
 
562
 
  gnome_canvas_item_get_bounds(item, &timer_item_x1, &timer_item_y1,
563
 
                               &timer_item_x2, &timer_item_y2);
564
 
 
565
 
  if(item == lock_left_item)
566
 
    {
567
 
      status = lock_left_up;
568
 
      lock_left_up = !lock_left_up;
569
 
      y1 = BASE_LINE - LOCK_HEIGHT_MAX;
570
 
      min = LOCK_HEIGHT_MIN;
571
 
      animate_speed = ANIMATE_SPEED;
572
 
    }
573
 
  else if(item == lock_right_item)
574
 
    {
575
 
      status = lock_right_up;
576
 
      lock_right_up = !lock_right_up;
577
 
      y1 = BASE_LINE - LOCK_HEIGHT_MAX;
578
 
      min = LOCK_HEIGHT_MIN;
579
 
      animate_speed = ANIMATE_SPEED;
580
 
    }
581
 
  else if(item == canallock_left_item)
582
 
    {
583
 
      status = canallock_left_up;
584
 
      canallock_left_up = !canallock_left_up;
585
 
      y1 = SUBCANAL_BASE_LINE - SUBCANAL_HEIGHT;
586
 
      min = CANALLOCK_HEIGHT_MIN;
587
 
      animate_speed = ANIMATE_SPEED;
588
 
    }
589
 
  else if(item == canallock_right_item)
590
 
    {
591
 
      status = canallock_right_up;
592
 
      canallock_right_up = !canallock_right_up;
593
 
      y1 = SUBCANAL_BASE_LINE - SUBCANAL_HEIGHT;
594
 
      min = CANALLOCK_HEIGHT_MIN;
595
 
      animate_speed = ANIMATE_SPEED;
596
 
    }
597
 
 
598
 
  timer_item = item;
599
 
  timer_item_limit_y = (status ? timer_item_y2 - min :
600
 
                        y1);
601
 
  timer_step_y1 = (status ? 2 : -2);
602
 
  timer_step_x1 = 0;
603
 
 
604
 
  timer_id = gtk_timeout_add (animate_speed, (GtkFunction) animate_step, NULL);
605
 
 
606
 
}
607
 
 
608
 
 
609
 
/* ==================================== */
610
 
static gboolean animate_step()
611
 
{
612
 
 
613
 
  if(!gcomprisBoard)
614
 
    return FALSE;
615
 
 
616
 
  timer_item_x1 += timer_step_x1;
617
 
  timer_item_y1 += timer_step_y1;
618
 
 
619
 
  if(GNOME_IS_CANVAS_PIXBUF(timer_item))
620
 
    gnome_canvas_item_set(timer_item,
621
 
                          "x", timer_item_x1,
622
 
                          "y", timer_item_y1,
623
 
                          NULL);
624
 
  else if(GNOME_IS_CANVAS_RECT(timer_item))
625
 
    gnome_canvas_item_set(timer_item,
626
 
                          "x1", timer_item_x1,
627
 
                          "y1", timer_item_y1,
628
 
                          NULL);
629
 
 
630
 
  /* Special case for raising/lowering the boat */
631
 
  if(boat_position==BOAT_POS_MIDDLE && timer_item==canal_middle_item)
632
 
    {
633
 
      double item_x1, item_y1, item_x2, item_y2;
634
 
 
635
 
      gnome_canvas_item_get_bounds(tuxboat_item, &item_x1, &item_y1,
636
 
                                   &item_x2, &item_y2);
637
 
 
638
 
      gnome_canvas_item_set(tuxboat_item,
639
 
                            "y", item_y1 + timer_step_y1,
640
 
                            NULL);
641
 
    }
642
 
 
643
 
  if((timer_item_y1 >= timer_item_limit_y && timer_step_y1 > 0) ||
644
 
     (timer_item_y1 <= timer_item_limit_y && timer_step_y1 < 0))
645
 
    {
646
 
      gtk_timeout_remove (timer_id);
647
 
      timer_id = 0;
648
 
      animation = FALSE;
649
 
      update_water();
650
 
    }
651
 
  else if((timer_item_x1 >= timer_item_limit_x && timer_step_x1 > 0) ||
652
 
     (timer_item_x1 <= timer_item_limit_x && timer_step_x1 < 0))
653
 
    {
654
 
      gtk_timeout_remove (timer_id);
655
 
      timer_id = 0;
656
 
      animation = FALSE;
657
 
      update_water();
658
 
    }
659
 
 
660
 
  gnome_canvas_update_now(gcomprisBoard->canvas);
661
 
 
662
 
  return TRUE;
663
 
}
664
 
 
665
 
/* ==================================== */
666
 
/* Highlight the given item */
667
 
static void hightlight(GnomeCanvasItem *item, gboolean status)
668
 
{
669
 
  guint color = 0;
670
 
 
671
 
  /* This is an image, not a rectangle */
672
 
  if(item == tuxboat_item)
673
 
    return;
674
 
 
675
 
  if(item == lock_left_item ||
676
 
     item == lock_right_item)
677
 
    {
678
 
      color   = (status ? LOCK_COLOR_H : LOCK_COLOR);
679
 
    }
680
 
  else if (item == canallock_left_item ||
681
 
           item == canallock_right_item)
682
 
    {
683
 
      color   = (status ? CANALLOCK_COLOR_H : CANALLOCK_COLOR);
684
 
    }
685
 
 
686
 
 
687
 
    gnome_canvas_item_set(item,
688
 
                          "fill_color_rgba", color,
689
 
                          NULL);
690
 
 
691
 
}
692
 
 
693
 
/* ==================================== */
694
 
static gint
695
 
item_event(GnomeCanvasItem *item, GdkEvent *event, gpointer data)
696
 
{
697
 
  double item_x, item_y;
698
 
  item_x = event->button.x;
699
 
  item_y = event->button.y;
700
 
  gnome_canvas_item_w2i(item->parent, &item_x, &item_y);
701
 
 
702
 
  if(board_paused)
703
 
    return FALSE;
704
 
 
705
 
  switch (event->type)
706
 
    {
707
 
    case GDK_ENTER_NOTIFY:
708
 
      hightlight(item, TRUE);
709
 
      break;
710
 
    case GDK_LEAVE_NOTIFY:
711
 
      hightlight(item, FALSE);
712
 
      break;
713
 
    case GDK_BUTTON_PRESS:
714
 
 
715
 
      /* If there is already an animation do nothing */
716
 
      if(animation)
717
 
        return FALSE;
718
 
 
719
 
      if(item == lock_left_item)
720
 
        {
721
 
          if(lock_water_low && canallock_right_up)
722
 
              toggle_lock(item);
723
 
          else
724
 
            gc_sound_play_ogg ("sounds/crash.ogg", NULL);
725
 
 
726
 
        }
727
 
      else if(item == lock_right_item)
728
 
        {
729
 
          if(!lock_water_low && canallock_left_up)
730
 
              toggle_lock(item);
731
 
          else
732
 
            gc_sound_play_ogg ("sounds/crash.ogg", NULL);
733
 
        }
734
 
      else if(item == canallock_left_item && canallock_right_up)
735
 
        {
736
 
          if(lock_right_up)
737
 
              toggle_lock(item);
738
 
          else
739
 
            gc_sound_play_ogg ("sounds/crash.ogg", NULL);
740
 
        }
741
 
      else if(item == canallock_right_item && canallock_left_up)
742
 
        {
743
 
          if(lock_left_up)
744
 
              toggle_lock(item);
745
 
          else
746
 
            gc_sound_play_ogg ("sounds/crash.ogg", NULL);
747
 
        }
748
 
      else if(item == tuxboat_item)
749
 
        {
750
 
          move_boat();
751
 
        }
752
 
      else
753
 
        {
754
 
          gc_sound_play_ogg ("sounds/crash.ogg", NULL);
755
 
        }
756
 
      break;
757
 
    default:
758
 
      break;
759
 
    }
760
 
  return FALSE;
761
 
 
762
 
 
763
 
  /*
764
 
    gamewon = TRUE;
765
 
    canal_lock_destroy_all_items();
766
 
    gc_bonus_display(gamewon, GC_BONUS_SMILEY);
767
 
  */
768
 
  return FALSE;
769
 
}
770