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

« back to all changes in this revision

Viewing changes to src/boards/planegame.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 - planegame.c
2
 
 *
3
 
 * Copyright (C) 2000 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 GList *item_list = NULL;
24
 
static GList *item2del_list = NULL;
25
 
 
26
 
static gboolean board_paused = TRUE;
27
 
static GcomprisBoard *gcomprisBoard = NULL;
28
 
 
29
 
static gint dummy_id = 0;
30
 
static gint drop_items_id = 0;
31
 
 
32
 
static GnomeCanvasItem *planeitem = NULL;
33
 
static gint plane_x, plane_y;
34
 
static gint planespeed_x, planespeed_y;
35
 
 
36
 
#define MAXSPEED 7
37
 
 
38
 
/* These are the index for managing the game rule */
39
 
static gint plane_target, plane_last_target;
40
 
 
41
 
typedef struct {
42
 
  gint number;
43
 
  GnomeCanvasItem *rootitem;
44
 
} CloudItem;
45
 
 
46
 
 
47
 
static void start_board (GcomprisBoard *agcomprisBoard);
48
 
static void pause_board (gboolean pause);
49
 
static void end_board (void);
50
 
static gboolean is_our_board (GcomprisBoard *gcomprisBoard);
51
 
static void set_level (guint level);
52
 
static gint key_press(guint keyval, gchar *commit_str, gchar *preedit_str);
53
 
 
54
 
static GnomeCanvasItem *planegame_create_item(GnomeCanvasGroup *parent);
55
 
static gint planegame_drop_items (GtkWidget *widget, gpointer data);
56
 
static gint planegame_move_items (GtkWidget *widget, gpointer data);
57
 
static void planegame_destroy_item(CloudItem *clouditem);
58
 
static void planegame_destroy_items(void);
59
 
static void planegame_destroy_all_items(void);
60
 
static void setup_item(GnomeCanvasItem *item);
61
 
static void planegame_next_level(void);
62
 
 
63
 
static  guint32              fallSpeed = 0;
64
 
static  double               speed = 0.0;
65
 
static  double               imageZoom = 0.0;
66
 
 
67
 
/* Description of this plugin */
68
 
static BoardPlugin menu_bp =
69
 
{
70
 
   NULL,
71
 
   NULL,
72
 
   N_("Numbers in Order"),
73
 
   N_("Move the plane to catch the clouds in the correct order"),
74
 
   "Bruno Coudoin <bruno.coudoin@free.fr>",
75
 
   NULL,
76
 
   NULL,
77
 
   NULL,
78
 
   NULL,
79
 
   start_board,
80
 
   pause_board,
81
 
   end_board,
82
 
   is_our_board,
83
 
   key_press,
84
 
   NULL,
85
 
   set_level,
86
 
   NULL,
87
 
   NULL,
88
 
   NULL,
89
 
   NULL
90
 
};
91
 
 
92
 
/*
93
 
 * Main entry point mandatory for each Gcompris's game
94
 
 * ---------------------------------------------------
95
 
 *
96
 
 */
97
 
 
98
 
GET_BPLUGIN_INFO(planegame)
99
 
 
100
 
/*
101
 
 * in : boolean TRUE = PAUSE : FALSE = CONTINUE
102
 
 *
103
 
 */
104
 
static void pause_board (gboolean pause)
105
 
{
106
 
  if(gcomprisBoard==NULL)
107
 
    return;
108
 
 
109
 
  if(pause)
110
 
    {
111
 
      if (dummy_id) {
112
 
        gtk_timeout_remove (dummy_id);
113
 
        dummy_id = 0;
114
 
      }
115
 
      if (drop_items_id) {
116
 
        gtk_timeout_remove (drop_items_id);
117
 
        drop_items_id = 0;
118
 
      }
119
 
    }
120
 
  else
121
 
    {
122
 
      if(!drop_items_id) {
123
 
        drop_items_id = gtk_timeout_add (1000,
124
 
                                         (GtkFunction) planegame_drop_items, NULL);
125
 
      }
126
 
      if(!dummy_id) {
127
 
        dummy_id = gtk_timeout_add (1000, (GtkFunction) planegame_move_items, NULL);
128
 
      }
129
 
    }
130
 
  board_paused = pause;
131
 
}
132
 
 
133
 
/*
134
 
 */
135
 
static void start_board (GcomprisBoard *agcomprisBoard)
136
 
{
137
 
 
138
 
  if(agcomprisBoard!=NULL)
139
 
    {
140
 
      gcomprisBoard=agcomprisBoard;
141
 
 
142
 
      /* disable im_context */
143
 
      gcomprisBoard->disable_im_context = TRUE;
144
 
 
145
 
      gc_set_background(gnome_canvas_root(gcomprisBoard->canvas), "opt/scenery3_background.png");
146
 
 
147
 
 
148
 
      /* set initial values for this level */
149
 
      gcomprisBoard->level = 1;
150
 
      gcomprisBoard->maxlevel = 2;
151
 
      gc_bar_set(GC_BAR_LEVEL);
152
 
 
153
 
      planegame_next_level();
154
 
 
155
 
      pause_board(FALSE);
156
 
 
157
 
    }
158
 
 
159
 
}
160
 
 
161
 
static void
162
 
end_board ()
163
 
{
164
 
 
165
 
  if(gcomprisBoard!=NULL)
166
 
    {
167
 
      pause_board(TRUE);
168
 
      gc_score_end();
169
 
      planegame_destroy_all_items();
170
 
      gcomprisBoard->level = 1;       // Restart this game to zero
171
 
    }
172
 
  gcomprisBoard = NULL;
173
 
}
174
 
 
175
 
static void
176
 
set_level (guint level)
177
 
{
178
 
 
179
 
  if(gcomprisBoard!=NULL)
180
 
    {
181
 
      gcomprisBoard->level=level;
182
 
      planegame_next_level();
183
 
    }
184
 
}
185
 
 
186
 
static gint key_press(guint keyval, gchar *commit_str, gchar *preedit_str)
187
 
{
188
 
 
189
 
  if(board_paused || !gcomprisBoard)
190
 
    return FALSE;
191
 
 
192
 
  /* Add some filter for control and shift key */
193
 
  switch (keyval)
194
 
    {
195
 
      /* Avoid all this keys to be interpreted by this game */
196
 
    case GDK_Shift_L:
197
 
    case GDK_Shift_R:
198
 
    case GDK_Control_L:
199
 
    case GDK_Control_R:
200
 
    case GDK_Caps_Lock:
201
 
    case GDK_Shift_Lock:
202
 
    case GDK_Meta_L:
203
 
    case GDK_Meta_R:
204
 
    case GDK_Alt_L:
205
 
    case GDK_Alt_R:
206
 
    case GDK_Super_L:
207
 
    case GDK_Super_R:
208
 
    case GDK_Hyper_L:
209
 
    case GDK_Hyper_R:
210
 
    case GDK_Num_Lock:
211
 
      return FALSE;
212
 
    case GDK_KP_Enter:
213
 
    case GDK_Return:
214
 
      return TRUE;
215
 
    case GDK_Right:
216
 
      if(planespeed_x < MAXSPEED)
217
 
        planespeed_x++;
218
 
      return TRUE;
219
 
    case GDK_Left:
220
 
      if(planespeed_x > -MAXSPEED)
221
 
        planespeed_x--;
222
 
      return TRUE;
223
 
    case GDK_Up:
224
 
      if(planespeed_y > -MAXSPEED)
225
 
      planespeed_y--;
226
 
      return TRUE;
227
 
    case GDK_Down:
228
 
      if(planespeed_y < MAXSPEED)
229
 
      planespeed_y++;
230
 
      return TRUE;
231
 
    }
232
 
  return TRUE;
233
 
}
234
 
 
235
 
gboolean
236
 
is_our_board (GcomprisBoard *gcomprisBoard)
237
 
{
238
 
  if (gcomprisBoard)
239
 
    {
240
 
      if(g_strcasecmp(gcomprisBoard->type, "planegame")==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
 
/*-------------------------------------------------------------------------------*/
253
 
/*-------------------------------------------------------------------------------*/
254
 
/*-------------------------------------------------------------------------------*/
255
 
/*-------------------------------------------------------------------------------*/
256
 
 
257
 
/* set initial values for the next level */
258
 
static void planegame_next_level()
259
 
{
260
 
  GdkPixbuf *pixmap = NULL;
261
 
 
262
 
  gc_bar_set_level(gcomprisBoard);
263
 
 
264
 
  planegame_destroy_all_items();
265
 
 
266
 
  /* Try the next level */
267
 
  speed=100+(40/(gcomprisBoard->level));
268
 
  fallSpeed=10000-gcomprisBoard->level*200;
269
 
  /* Make the images tend to 0.5 ratio */
270
 
  imageZoom=0.3+(0.5/(gcomprisBoard->level));
271
 
 
272
 
  /* Setup and Display the plane */
273
 
  planespeed_y = 0;
274
 
  planespeed_x = 0;
275
 
  pixmap = gc_pixmap_load("gcompris/misc/tuxhelico.png");
276
 
  plane_x = 50;
277
 
  plane_y = 300;
278
 
  planeitem = gnome_canvas_item_new (gnome_canvas_root(gcomprisBoard->canvas),
279
 
                                     gnome_canvas_pixbuf_get_type (),
280
 
                                     "pixbuf", pixmap,
281
 
                                     "x", (double) plane_x,
282
 
                                     "y", (double) plane_y,
283
 
                                     "width", (double) gdk_pixbuf_get_width(pixmap)*imageZoom,
284
 
                                     "height", (double) gdk_pixbuf_get_height(pixmap)*imageZoom,
285
 
                                     "width_set", TRUE,
286
 
                                     "height_set", TRUE,
287
 
                                     NULL);
288
 
  gdk_pixbuf_unref(pixmap);
289
 
 
290
 
  /* Game rules */
291
 
  plane_target = 1;
292
 
  plane_last_target = 10;
293
 
 
294
 
  gcomprisBoard->number_of_sublevel=plane_last_target;
295
 
 
296
 
  gcomprisBoard->sublevel=plane_target;
297
 
 
298
 
  if(gcomprisBoard->level>1)
299
 
    {
300
 
      /* No scoring after level 1 */
301
 
      gc_score_end();
302
 
    }
303
 
  else
304
 
    {
305
 
      gc_score_start(SCORESTYLE_NOTE,
306
 
                           gcomprisBoard->width - 220,
307
 
                           gcomprisBoard->height - 50,
308
 
                           gcomprisBoard->number_of_sublevel);
309
 
      gc_score_set(gcomprisBoard->sublevel);
310
 
    }
311
 
}
312
 
 
313
 
#define ISIN(x1, y1, px1, py1, px2, py2) (x1>px1 && x1<px2 && y1>py1 && y2<py2 ? TRUE : FALSE)
314
 
 
315
 
static void planegame_cloud_colision(CloudItem *clouditem)
316
 
{
317
 
  double px1, px2, py1, py2;
318
 
  double x1, x2, y1, y2;
319
 
  GnomeCanvasItem *item;
320
 
 
321
 
  if(clouditem==NULL)
322
 
    return;
323
 
 
324
 
  item = clouditem->rootitem;
325
 
 
326
 
  gnome_canvas_item_get_bounds(planeitem,  &px1, &py1, &px2, &py2);
327
 
  gnome_canvas_item_get_bounds(item,  &x1, &y1, &x2, &y2);
328
 
 
329
 
  if(
330
 
     ISIN(x1, y1, px1, py1, px2, py2) ||
331
 
     ISIN(x2, y1, px1, py1, px2, py2) ||
332
 
     ISIN(x1, y2, px1, py1, px2, py2) ||
333
 
     ISIN(x2, y2, px1, py1, px2, py2)
334
 
     )
335
 
    {
336
 
      if(plane_target == clouditem->number)
337
 
        {
338
 
          gc_sound_play_ogg ("sounds/gobble.wav", NULL);
339
 
          item2del_list = g_list_append (item2del_list, clouditem);
340
 
          plane_target++;
341
 
 
342
 
          if(gcomprisBoard->level==1)
343
 
            {
344
 
              gc_score_set(plane_target);
345
 
            }
346
 
 
347
 
          if(plane_target==plane_last_target)
348
 
            {
349
 
              /* Try the next level */
350
 
              gcomprisBoard->level++;
351
 
              if(gcomprisBoard->level>gcomprisBoard->maxlevel) { // the current board is finished : bail out
352
 
                gc_bonus_end_display(GC_BOARD_FINISHED_RANDOM);
353
 
                return;
354
 
              }
355
 
              planegame_next_level();
356
 
              gc_sound_play_ogg ("sounds/bonus.wav", NULL);
357
 
            }
358
 
        }
359
 
    }
360
 
}
361
 
 
362
 
/* Move the plane */
363
 
static void planegame_move_plane(GnomeCanvasItem *item)
364
 
{
365
 
  if(plane_x>gcomprisBoard->width-150 && planespeed_x>0)
366
 
    planespeed_x=0;
367
 
 
368
 
  if(plane_x<0 && planespeed_x<0)
369
 
    planespeed_x=0;
370
 
 
371
 
  if(plane_y>gcomprisBoard->height-50 && planespeed_y>0)
372
 
    planespeed_y=0;
373
 
 
374
 
  if(plane_y<10 && planespeed_y<0)
375
 
    planespeed_y=0;
376
 
 
377
 
  gnome_canvas_item_move(item, (double)planespeed_x, (double)planespeed_y);
378
 
  plane_x+=planespeed_x;
379
 
  plane_y+=planespeed_y;
380
 
}
381
 
 
382
 
static void planegame_move_item(CloudItem *clouditem)
383
 
{
384
 
  double x1, y1, x2, y2;
385
 
  GnomeCanvasItem *item = clouditem->rootitem;
386
 
 
387
 
  gnome_canvas_item_move(item, -2.0, 0.0);
388
 
 
389
 
  gnome_canvas_item_get_bounds    (item,
390
 
                                   &x1,
391
 
                                   &y1,
392
 
                                   &x2,
393
 
                                   &y2);
394
 
 
395
 
  if(x2<0) {
396
 
    item2del_list = g_list_append (item2del_list, clouditem);
397
 
  }
398
 
 
399
 
}
400
 
 
401
 
static void planegame_destroy_item(CloudItem *clouditem)
402
 
{
403
 
  GnomeCanvasItem *item = clouditem->rootitem;
404
 
 
405
 
  item_list = g_list_remove (item_list, clouditem);
406
 
  item2del_list = g_list_remove (item2del_list, clouditem);
407
 
  gtk_object_destroy (GTK_OBJECT(item));
408
 
 
409
 
  g_free(clouditem);
410
 
}
411
 
 
412
 
/* Destroy items that falls out of the canvas */
413
 
static void planegame_destroy_items()
414
 
{
415
 
  CloudItem *clouditem;
416
 
 
417
 
  while(g_list_length(item2del_list)>0)
418
 
    {
419
 
      clouditem = g_list_nth_data(item2del_list, 0);
420
 
      planegame_destroy_item(clouditem);
421
 
    }
422
 
}
423
 
 
424
 
/* Destroy all the items */
425
 
static void planegame_destroy_all_items()
426
 
{
427
 
  CloudItem *clouditem;
428
 
 
429
 
  while(g_list_length(item_list)>0)
430
 
    {
431
 
      clouditem = g_list_nth_data(item_list, 0);
432
 
      planegame_destroy_item(clouditem);
433
 
    }
434
 
 
435
 
  if(planeitem)
436
 
    {
437
 
      gtk_object_destroy (GTK_OBJECT(planeitem));
438
 
      planeitem = NULL;
439
 
    }
440
 
}
441
 
 
442
 
/*
443
 
 * This does the moves of the game items on the play canvas
444
 
 *
445
 
 */
446
 
static gint planegame_move_items (GtkWidget *widget, gpointer data)
447
 
{
448
 
  g_list_foreach (item_list, (GFunc) planegame_move_item, NULL);
449
 
  g_list_foreach (item_list, (GFunc) planegame_cloud_colision, NULL);
450
 
 
451
 
  /* Destroy items that falls out of the canvas */
452
 
  planegame_destroy_items();
453
 
 
454
 
  /* move the plane */
455
 
  planegame_move_plane(planeitem);
456
 
  dummy_id = gtk_timeout_add (speed,
457
 
                              (GtkFunction) planegame_move_items, NULL);
458
 
 
459
 
  return(FALSE);
460
 
}
461
 
 
462
 
static GnomeCanvasItem *planegame_create_item(GnomeCanvasGroup *parent)
463
 
{
464
 
  GdkPixbuf *pixmap = NULL;
465
 
  GnomeCanvasItem *itemgroup;
466
 
  char *number = NULL;
467
 
  int i, min;
468
 
  CloudItem *clouditem;
469
 
 
470
 
  /* Random cloud number */
471
 
  if(g_random_int()%2==0)
472
 
    {
473
 
      /* Put the target */
474
 
      i = plane_target;
475
 
    }
476
 
  else
477
 
    {
478
 
      min = MAX(1, plane_target - 1);
479
 
      i   = min + g_random_int()%(plane_target - min + 3);
480
 
    }
481
 
  number = g_strdup_printf("%d", i);
482
 
 
483
 
  pixmap = gc_pixmap_load("gcompris/misc/cloud.png");
484
 
 
485
 
  itemgroup = \
486
 
    gnome_canvas_item_new (parent,
487
 
                           gnome_canvas_group_get_type (),
488
 
                           "x", (double) gcomprisBoard->width,
489
 
                           "y", (double)(g_random_int()%(gcomprisBoard->height-
490
 
                                                 (guint)(gdk_pixbuf_get_height(pixmap)*
491
 
                                                         imageZoom))),
492
 
                           NULL);
493
 
 
494
 
 
495
 
  gnome_canvas_item_new (GNOME_CANVAS_GROUP(itemgroup),
496
 
                         gnome_canvas_pixbuf_get_type (),
497
 
                         "pixbuf", pixmap,
498
 
                         "x", (double) -gdk_pixbuf_get_width(pixmap)*imageZoom/2,
499
 
                         "y", (double) -gdk_pixbuf_get_height(pixmap)*imageZoom/2,
500
 
                         "width", (double) gdk_pixbuf_get_width(pixmap)*imageZoom,
501
 
                         "height", (double) gdk_pixbuf_get_height(pixmap)*imageZoom,
502
 
                         "width_set", TRUE,
503
 
                         "height_set", TRUE,
504
 
                         NULL);
505
 
  gdk_pixbuf_unref(pixmap);
506
 
 
507
 
 
508
 
  gnome_canvas_item_new (GNOME_CANVAS_GROUP(itemgroup),
509
 
                         gnome_canvas_text_get_type (),
510
 
                         "text", number,
511
 
                         "font", gc_skin_font_board_big,
512
 
                         "x", (double) 0,
513
 
                         "y", (double) 0,
514
 
                         "fill_color", "red",
515
 
                         NULL);
516
 
 
517
 
  /* The plane is always on top */
518
 
  gnome_canvas_item_raise_to_top(planeitem);
519
 
 
520
 
  clouditem = g_malloc(sizeof(CloudItem));
521
 
  clouditem->rootitem = itemgroup;
522
 
  clouditem->number   = i;
523
 
 
524
 
  item_list = g_list_append (item_list, clouditem);
525
 
 
526
 
  g_free (number);
527
 
 
528
 
  return (itemgroup);
529
 
}
530
 
 
531
 
static void planegame_add_new_item()
532
 
{
533
 
  setup_item (planegame_create_item(gnome_canvas_root(gcomprisBoard->canvas)));
534
 
}
535
 
 
536
 
/*
537
 
 * This is called on a low frequency and is used to drop new items
538
 
 *
539
 
 */
540
 
static gint planegame_drop_items (GtkWidget *widget, gpointer data)
541
 
{
542
 
  planegame_add_new_item();
543
 
 
544
 
  drop_items_id = gtk_timeout_add (fallSpeed,
545
 
                                   (GtkFunction) planegame_drop_items, NULL);
546
 
  return (FALSE);
547
 
}
548
 
 
549
 
static gint
550
 
item_event(GnomeCanvasItem *item, GdkEvent *event, gpointer data)
551
 
{
552
 
   static double x, y;
553
 
   double new_x, new_y;
554
 
   GdkCursor *fleur;
555
 
   static int dragging;
556
 
   double item_x, item_y;
557
 
 
558
 
  if(!gcomprisBoard)
559
 
    return FALSE;
560
 
 
561
 
   item_x = event->button.x;
562
 
   item_y = event->button.y;
563
 
   gnome_canvas_item_w2i(item->parent, &item_x, &item_y);
564
 
 
565
 
   switch (event->type)
566
 
     {
567
 
     case GDK_BUTTON_PRESS:
568
 
       switch(event->button.button)
569
 
         {
570
 
         case 1:
571
 
           if (event->button.state & GDK_SHIFT_MASK)
572
 
             {
573
 
               x = item_x;
574
 
               y = item_y;
575
 
 
576
 
               fleur = gdk_cursor_new(GDK_FLEUR);
577
 
               gc_canvas_item_grab(item,
578
 
                                      GDK_POINTER_MOTION_MASK |
579
 
                                      GDK_BUTTON_RELEASE_MASK,
580
 
                                      fleur,
581
 
                                      event->button.time);
582
 
               gdk_cursor_destroy(fleur);
583
 
               dragging = TRUE;
584
 
             }
585
 
           break;
586
 
 
587
 
         default:
588
 
           break;
589
 
         }
590
 
       break;
591
 
 
592
 
     case GDK_MOTION_NOTIFY:
593
 
       if (dragging && (event->motion.state & GDK_BUTTON1_MASK))
594
 
         {
595
 
           new_x = item_x;
596
 
           new_y = item_y;
597
 
 
598
 
           gnome_canvas_item_move(item, new_x - x, new_y - y);
599
 
           x = new_x;
600
 
           y = new_y;
601
 
         }
602
 
       break;
603
 
 
604
 
     case GDK_BUTTON_RELEASE:
605
 
       if(dragging)
606
 
         {
607
 
           gc_canvas_item_ungrab(item, event->button.time);
608
 
           dragging = FALSE;
609
 
         }
610
 
       break;
611
 
 
612
 
     default:
613
 
       break;
614
 
     }
615
 
 
616
 
   return FALSE;
617
 
 }
618
 
 
619
 
static void
620
 
setup_item(GnomeCanvasItem *item)
621
 
{
622
 
  gtk_signal_connect(GTK_OBJECT(item), "event",
623
 
                     (GtkSignalFunc) item_event,
624
 
                     NULL);
625
 
}