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

« back to all changes in this revision

Viewing changes to src/planegame-activity/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, 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
 
 
25
static gint planemove_id = 0;
 
26
static gint drop_items_id = 0;
 
27
 
 
28
static GooCanvasItem *rootitem = NULL;
 
29
static GooCanvasItem *planeitem;
 
30
static GooCanvasItem *clouds_rootitem;
 
31
static gint plane_x, plane_y;
 
32
static gint planespeed_x, planespeed_y;
 
33
 
 
34
#define MAXSPEED 7
 
35
 
 
36
/* These are the index for managing the game rule */
 
37
static gint plane_target, plane_last_target;
 
38
 
 
39
static void start_board (GcomprisBoard *agcomprisBoard);
 
40
static void pause_board (gboolean pause);
 
41
static void end_board (void);
 
42
static gboolean is_our_board (GcomprisBoard *gcomprisBoard);
 
43
static void set_level (guint level);
 
44
static gint key_press(guint keyval, gchar *commit_str, gchar *preedit_str);
 
45
 
 
46
static GooCanvasItem *planegame_create_item(GooCanvasItem *parent);
 
47
static gint planegame_drop_items (GtkWidget *widget, gpointer data);
 
48
static gint planegame_move_items (GtkWidget *widget, gpointer data);
 
49
static void planegame_destroy_all_items(void);
 
50
static void planegame_next_level(void);
 
51
 
 
52
static  guint32              fallSpeed = 0;
 
53
static  double               speed = 0.0;
 
54
static  double               imageZoom = 0.0;
 
55
 
 
56
/* Description of this plugin */
 
57
static BoardPlugin menu_bp =
 
58
{
 
59
   NULL,
 
60
   NULL,
 
61
   N_("Numbers in Order"),
 
62
   N_("Move the plane to catch the clouds in the correct order"),
 
63
   "Bruno Coudoin <bruno.coudoin@free.fr>",
 
64
   NULL,
 
65
   NULL,
 
66
   NULL,
 
67
   NULL,
 
68
   start_board,
 
69
   pause_board,
 
70
   end_board,
 
71
   is_our_board,
 
72
   key_press,
 
73
   NULL,
 
74
   set_level,
 
75
   NULL,
 
76
   NULL,
 
77
   NULL,
 
78
   NULL
 
79
};
 
80
 
 
81
/*
 
82
 * Main entry point mandatory for each Gcompris's game
 
83
 * ---------------------------------------------------
 
84
 *
 
85
 */
 
86
 
 
87
GET_BPLUGIN_INFO(planegame)
 
88
 
 
89
/*
 
90
 * in : boolean TRUE = PAUSE : FALSE = CONTINUE
 
91
 *
 
92
 */
 
93
static void pause_board (gboolean pause)
 
94
{
 
95
  if(gcomprisBoard==NULL)
 
96
    return;
 
97
 
 
98
  if(pause)
 
99
    {
 
100
      if (planemove_id) {
 
101
        g_source_remove (planemove_id);
 
102
        planemove_id = 0;
 
103
      }
 
104
      if (drop_items_id) {
 
105
        g_source_remove (drop_items_id);
 
106
        drop_items_id = 0;
 
107
      }
 
108
    }
 
109
  else
 
110
    {
 
111
      if(!drop_items_id) {
 
112
        drop_items_id = g_timeout_add (1000,
 
113
                                       (GtkFunction) planegame_drop_items,
 
114
                                       NULL);
 
115
      }
 
116
      if(!planemove_id) {
 
117
        planemove_id = g_timeout_add (1000,
 
118
                                      (GtkFunction) planegame_move_items,
 
119
                                      NULL);
 
120
      }
 
121
    }
 
122
}
 
123
 
 
124
/*
 
125
 */
 
126
static void start_board (GcomprisBoard *agcomprisBoard)
 
127
{
 
128
 
 
129
  if(agcomprisBoard!=NULL)
 
130
    {
 
131
      gcomprisBoard=agcomprisBoard;
 
132
 
 
133
      /* disable im_context */
 
134
      gcomprisBoard->disable_im_context = TRUE;
 
135
 
 
136
      gc_set_background(goo_canvas_get_root_item(gcomprisBoard->canvas),
 
137
                        "planegame/scenery3_background.png");
 
138
 
 
139
 
 
140
      /* set initial values for this level */
 
141
      gcomprisBoard->level = 1;
 
142
      gcomprisBoard->maxlevel = 2;
 
143
      gc_bar_set(GC_BAR_LEVEL);
 
144
 
 
145
      planegame_next_level();
 
146
 
 
147
      pause_board(FALSE);
 
148
 
 
149
    }
 
150
 
 
151
}
 
152
 
 
153
static void
 
154
end_board ()
 
155
{
 
156
 
 
157
  if(gcomprisBoard!=NULL)
 
158
    {
 
159
      pause_board(TRUE);
 
160
      gc_score_end();
 
161
      planegame_destroy_all_items();
 
162
      gcomprisBoard->level = 1;       // Restart this game to zero
 
163
    }
 
164
  gcomprisBoard = NULL;
 
165
}
 
166
 
 
167
static void
 
168
set_level (guint level)
 
169
{
 
170
 
 
171
  if(gcomprisBoard!=NULL)
 
172
    {
 
173
      gcomprisBoard->level=level;
 
174
      planegame_next_level();
 
175
    }
 
176
}
 
177
 
 
178
static gint key_press(guint keyval, gchar *commit_str, gchar *preedit_str)
 
179
{
 
180
 
 
181
  if(!gcomprisBoard)
 
182
    return FALSE;
 
183
 
 
184
  /* Add some filter for control and shift key */
 
185
  switch (keyval)
 
186
    {
 
187
      /* Avoid all this keys to be interpreted by this game */
 
188
    case GDK_Shift_L:
 
189
    case GDK_Shift_R:
 
190
    case GDK_Control_L:
 
191
    case GDK_Control_R:
 
192
    case GDK_Caps_Lock:
 
193
    case GDK_Shift_Lock:
 
194
    case GDK_Meta_L:
 
195
    case GDK_Meta_R:
 
196
    case GDK_Alt_L:
 
197
    case GDK_Alt_R:
 
198
    case GDK_Super_L:
 
199
    case GDK_Super_R:
 
200
    case GDK_Hyper_L:
 
201
    case GDK_Hyper_R:
 
202
    case GDK_Num_Lock:
 
203
      return FALSE;
 
204
    case GDK_KP_Enter:
 
205
    case GDK_Return:
 
206
      return TRUE;
 
207
    case GDK_Right:
 
208
      if(planespeed_x < MAXSPEED)
 
209
        planespeed_x++;
 
210
      return TRUE;
 
211
    case GDK_Left:
 
212
      if(planespeed_x > -MAXSPEED)
 
213
        planespeed_x--;
 
214
      return TRUE;
 
215
    case GDK_Up:
 
216
      if(planespeed_y > -MAXSPEED)
 
217
      planespeed_y--;
 
218
      return TRUE;
 
219
    case GDK_Down:
 
220
      if(planespeed_y < MAXSPEED)
 
221
      planespeed_y++;
 
222
      return TRUE;
 
223
    }
 
224
  return TRUE;
 
225
}
 
226
 
 
227
gboolean
 
228
is_our_board (GcomprisBoard *gcomprisBoard)
 
229
{
 
230
  if (gcomprisBoard)
 
231
    {
 
232
      if(g_strcasecmp(gcomprisBoard->type, "planegame")==0)
 
233
        {
 
234
          /* Set the plugin entry */
 
235
          gcomprisBoard->plugin=&menu_bp;
 
236
 
 
237
          return TRUE;
 
238
        }
 
239
    }
 
240
  return FALSE;
 
241
}
 
242
 
 
243
 
 
244
/*-------------------------------------------------------------------------------*/
 
245
/*-------------------------------------------------------------------------------*/
 
246
/*-------------------------------------------------------------------------------*/
 
247
/*-------------------------------------------------------------------------------*/
 
248
 
 
249
/* set initial values for the next level */
 
250
static void planegame_next_level()
 
251
{
 
252
  RsvgHandle *svg_handle = NULL;
 
253
  GooCanvasItem *item;
 
254
 
 
255
  gc_bar_set_level(gcomprisBoard);
 
256
 
 
257
  planegame_destroy_all_items();
 
258
 
 
259
  rootitem = goo_canvas_group_new (goo_canvas_get_root_item(gcomprisBoard->canvas),
 
260
                                   NULL);
 
261
 
 
262
  clouds_rootitem = goo_canvas_group_new (rootitem, NULL);
 
263
 
 
264
  /* Try the next level */
 
265
  speed=100+(40/(gcomprisBoard->level));
 
266
  fallSpeed=10000-gcomprisBoard->level*200;
 
267
  /* Make the images tend to 0.5 ratio */
 
268
  imageZoom=0.3+(0.5/(gcomprisBoard->level));
 
269
 
 
270
  /* Setup and Display the plane */
 
271
  planespeed_y = 0;
 
272
  planespeed_x = 0;
 
273
  svg_handle = gc_rsvg_load("planegame/tuxhelico.svgz");
 
274
  plane_x = 50;
 
275
  plane_y = 300;
 
276
 
 
277
  planeitem = goo_canvas_group_new (rootitem,
 
278
                                   NULL);
 
279
 
 
280
  goo_canvas_item_translate(planeitem, plane_x, plane_y);
 
281
 
 
282
  item = goo_canvas_svg_new (planeitem,
 
283
                           svg_handle,
 
284
                           NULL);
 
285
 
 
286
  goo_canvas_item_scale(item,
 
287
                        0.4 * imageZoom,
 
288
                        0.4 * imageZoom);
 
289
 
 
290
  g_object_unref(svg_handle);
 
291
 
 
292
  /* Game rules */
 
293
  plane_target = 1;
 
294
  plane_last_target = 10;
 
295
 
 
296
  gcomprisBoard->number_of_sublevel=plane_last_target;
 
297
 
 
298
  gcomprisBoard->sublevel=plane_target;
 
299
 
 
300
  if(gcomprisBoard->level>1)
 
301
    {
 
302
      /* No scoring after level 1 */
 
303
      gc_score_end();
 
304
    }
 
305
  else
 
306
    {
 
307
      gc_score_start(SCORESTYLE_NOTE,
 
308
                           BOARDWIDTH - 195,
 
309
                           BOARDHEIGHT - 30,
 
310
                           gcomprisBoard->number_of_sublevel);
 
311
      gc_score_set(gcomprisBoard->sublevel);
 
312
    }
 
313
 
 
314
}
 
315
 
 
316
#define ISIN(x1, y1, px1, py1, px2, py2) \
 
317
  (x1>px1 && x1<px2 && y1>py1 && y1<py2 ? TRUE : FALSE)
 
318
 
 
319
static void planegame_cloud_colision(GooCanvasItem *item)
 
320
{
 
321
  GooCanvasBounds ib, pb;
 
322
 
 
323
  goo_canvas_item_get_bounds(planeitem,  &pb);
 
324
  goo_canvas_item_get_bounds(item, &ib);
 
325
 
 
326
  if(ib.x2<0)
 
327
    {
 
328
      goo_canvas_item_remove(item);
 
329
      return;
 
330
    }
 
331
 
 
332
  if(
 
333
     ISIN(ib.x1, ib.y1, pb.x1, pb.y1, pb.x2, pb.y2) ||
 
334
     ISIN(ib.x2, ib.y1, pb.x1, pb.y1, pb.x2, pb.y2) ||
 
335
     ISIN(ib.x1, ib.y2, pb.x1, pb.y1, pb.x2, pb.y2) ||
 
336
     ISIN(ib.x2, ib.y2, pb.x1, pb.y1, pb.x2, pb.y2)
 
337
     )
 
338
    {
 
339
      gint number = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item),
 
340
                                                        "cloud_number"));
 
341
 
 
342
      if(plane_target == number)
 
343
        {
 
344
          gc_sound_play_ogg ("sounds/gobble.wav", NULL);
 
345
          plane_target++;
 
346
 
 
347
          goo_canvas_item_remove(item);
 
348
 
 
349
          if(gcomprisBoard->level==1)
 
350
            gc_score_set(plane_target);
 
351
 
 
352
          if(plane_target == plane_last_target)
 
353
            {
 
354
              /* Try the next level */
 
355
              gcomprisBoard->level++;
 
356
              if(gcomprisBoard->level>gcomprisBoard->maxlevel)
 
357
                gcomprisBoard->level = gcomprisBoard->maxlevel;
 
358
 
 
359
              planegame_next_level();
 
360
              gc_sound_play_ogg ("sounds/bonus.wav", NULL);
 
361
            }
 
362
        }
 
363
    }
 
364
}
 
365
 
 
366
/* Move the plane */
 
367
static void planegame_move_plane(GooCanvasItem *item)
 
368
{
 
369
  GooCanvasBounds bounds;
 
370
 
 
371
  goo_canvas_item_get_bounds(item, &bounds);
 
372
 
 
373
  if(plane_x > BOARDWIDTH - (bounds.x2 - bounds.x1)
 
374
     && planespeed_x > 0)
 
375
    planespeed_x=0;
 
376
 
 
377
  if(plane_x < 0 && planespeed_x < 0)
 
378
    planespeed_x = 0;
 
379
 
 
380
  if(plane_y > BOARDHEIGHT - (bounds.y2 - bounds.y1)
 
381
     && planespeed_y > 0)
 
382
    planespeed_y = 0;
 
383
 
 
384
  if(plane_y < 0 && planespeed_y < 0)
 
385
    planespeed_y=0;
 
386
 
 
387
  goo_canvas_item_translate(item,
 
388
                            planespeed_x,
 
389
                            planespeed_y);
 
390
  plane_x += planespeed_x;
 
391
  plane_y += planespeed_y;
 
392
}
 
393
 
 
394
/* Destroy all the items */
 
395
static void planegame_destroy_all_items()
 
396
{
 
397
  if(rootitem)
 
398
    goo_canvas_item_remove(rootitem);
 
399
 
 
400
  rootitem = NULL;
 
401
}
 
402
 
 
403
/*
 
404
 * This does the moves of the game items on the play canvas
 
405
 *
 
406
 */
 
407
static gint planegame_move_items (GtkWidget *widget, gpointer data)
 
408
{
 
409
  int i;
 
410
 
 
411
  /* Check collision with each cloud */
 
412
  for(i = 0;
 
413
      i < goo_canvas_item_get_n_children(clouds_rootitem);
 
414
      i++)
 
415
    planegame_cloud_colision(goo_canvas_item_get_child(clouds_rootitem,
 
416
                                                         i));
 
417
 
 
418
  /* move the plane */
 
419
  planegame_move_plane(planeitem);
 
420
  planemove_id = g_timeout_add (speed,
 
421
                                (GtkFunction) planegame_move_items, NULL);
 
422
 
 
423
  return(FALSE);
 
424
}
 
425
 
 
426
static GooCanvasItem *planegame_create_item(GooCanvasItem *parent)
 
427
{
 
428
  RsvgHandle *svg_handle;
 
429
  RsvgDimensionData dimension;
 
430
  GooCanvasItem *itemgroup;
 
431
  GooCanvasItem *item;
 
432
  char *number = NULL;
 
433
  int i, min;
 
434
  guint y;
 
435
 
 
436
  /* Random cloud number */
 
437
  if(g_random_int()%2==0)
 
438
    {
 
439
      /* Put the target */
 
440
      i = plane_target;
 
441
    }
 
442
  else
 
443
    {
 
444
      min = MAX(1, plane_target - 1);
 
445
      i   = min + g_random_int()%(plane_target - min + 3);
 
446
    }
 
447
  number = g_strdup_printf("%d", i);
 
448
 
 
449
  itemgroup = goo_canvas_group_new (parent, NULL);
 
450
 
 
451
  g_object_set_data (G_OBJECT (itemgroup),
 
452
                     "cloud_number", GINT_TO_POINTER (i));
 
453
 
 
454
  svg_handle = gc_rsvg_load("planegame/cloud.svgz");
 
455
  rsvg_handle_get_dimensions(svg_handle, &dimension);
 
456
 
 
457
  y = (g_random_int()%(BOARDHEIGHT -
 
458
                       (guint)(dimension.height * imageZoom)));
 
459
 
 
460
  goo_canvas_item_translate(itemgroup,
 
461
                            BOARDWIDTH,
 
462
                            y);
 
463
 
 
464
  item = goo_canvas_svg_new (itemgroup,
 
465
                           svg_handle,
 
466
                           NULL);
 
467
  goo_canvas_item_scale(item, imageZoom, imageZoom);
 
468
 
 
469
  g_object_unref(svg_handle);
 
470
 
 
471
  g_object_set_data (G_OBJECT (item),
 
472
                     "cloud_number", GINT_TO_POINTER (i));
 
473
 
 
474
  item = goo_canvas_text_new (itemgroup,
 
475
                              number,
 
476
                              dimension.width*imageZoom/2,
 
477
                              dimension.height*imageZoom/2,
 
478
                              -1,
 
479
                              GTK_ANCHOR_CENTER,
 
480
                              "font", gc_skin_font_board_big,
 
481
                              "fill-color", "red",
 
482
                              NULL);
 
483
 
 
484
  g_object_set_data (G_OBJECT (item),
 
485
                     "cloud_number", GINT_TO_POINTER (i));
 
486
 
 
487
  goo_canvas_item_animate(itemgroup,
 
488
                          -dimension.width*imageZoom,
 
489
                          y,
 
490
                          1.0,
 
491
                          0,
 
492
                          TRUE,
 
493
                          40*BOARDWIDTH,
 
494
                          40,
 
495
                          GOO_CANVAS_ANIMATE_FREEZE);
 
496
 
 
497
  /* The plane is always on top */
 
498
  goo_canvas_item_raise(itemgroup, NULL);
 
499
  goo_canvas_item_raise(planeitem, NULL);
 
500
 
 
501
  g_free (number);
 
502
 
 
503
  return (itemgroup);
 
504
}
 
505
 
 
506
static void planegame_add_new_item()
 
507
{
 
508
  planegame_create_item(clouds_rootitem);
 
509
}
 
510
 
 
511
/*
 
512
 * This is called on a low frequency and is used to drop new items
 
513
 *
 
514
 */
 
515
static gint planegame_drop_items (GtkWidget *widget, gpointer data)
 
516
{
 
517
  planegame_add_new_item();
 
518
 
 
519
  drop_items_id = g_timeout_add (fallSpeed,
 
520
                                 (GtkFunction) planegame_drop_items, NULL);
 
521
  return (FALSE);
 
522
}
 
523