1
/* gcompris - planegame.c
3
* Copyright (C) 2000, 2008 Bruno Coudoin
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.
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.
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/>.
19
#include "gcompris/gcompris.h"
21
#define SOUNDLISTFILE PACKAGE
23
static GcomprisBoard *gcomprisBoard = NULL;
25
static gint planemove_id = 0;
26
static gint drop_items_id = 0;
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;
36
/* These are the index for managing the game rule */
37
static gint plane_target, plane_last_target;
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);
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);
52
static guint32 fallSpeed = 0;
53
static double speed = 0.0;
54
static double imageZoom = 0.0;
56
/* Description of this plugin */
57
static BoardPlugin menu_bp =
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>",
82
* Main entry point mandatory for each Gcompris's game
83
* ---------------------------------------------------
87
GET_BPLUGIN_INFO(planegame)
90
* in : boolean TRUE = PAUSE : FALSE = CONTINUE
93
static void pause_board (gboolean pause)
95
if(gcomprisBoard==NULL)
101
g_source_remove (planemove_id);
105
g_source_remove (drop_items_id);
112
drop_items_id = g_timeout_add (1000,
113
(GtkFunction) planegame_drop_items,
117
planemove_id = g_timeout_add (1000,
118
(GtkFunction) planegame_move_items,
126
static void start_board (GcomprisBoard *agcomprisBoard)
129
if(agcomprisBoard!=NULL)
131
gcomprisBoard=agcomprisBoard;
133
/* disable im_context */
134
gcomprisBoard->disable_im_context = TRUE;
136
gc_set_background(goo_canvas_get_root_item(gcomprisBoard->canvas),
137
"planegame/scenery3_background.png");
140
/* set initial values for this level */
141
gcomprisBoard->level = 1;
142
gcomprisBoard->maxlevel = 2;
143
gc_bar_set(GC_BAR_LEVEL);
145
planegame_next_level();
157
if(gcomprisBoard!=NULL)
161
planegame_destroy_all_items();
162
gcomprisBoard->level = 1; // Restart this game to zero
164
gcomprisBoard = NULL;
168
set_level (guint level)
171
if(gcomprisBoard!=NULL)
173
gcomprisBoard->level=level;
174
planegame_next_level();
178
static gint key_press(guint keyval, gchar *commit_str, gchar *preedit_str)
184
/* Add some filter for control and shift key */
187
/* Avoid all this keys to be interpreted by this game */
208
if(planespeed_x < MAXSPEED)
212
if(planespeed_x > -MAXSPEED)
216
if(planespeed_y > -MAXSPEED)
220
if(planespeed_y < MAXSPEED)
228
is_our_board (GcomprisBoard *gcomprisBoard)
232
if(g_strcasecmp(gcomprisBoard->type, "planegame")==0)
234
/* Set the plugin entry */
235
gcomprisBoard->plugin=&menu_bp;
244
/*-------------------------------------------------------------------------------*/
245
/*-------------------------------------------------------------------------------*/
246
/*-------------------------------------------------------------------------------*/
247
/*-------------------------------------------------------------------------------*/
249
/* set initial values for the next level */
250
static void planegame_next_level()
252
RsvgHandle *svg_handle = NULL;
255
gc_bar_set_level(gcomprisBoard);
257
planegame_destroy_all_items();
259
rootitem = goo_canvas_group_new (goo_canvas_get_root_item(gcomprisBoard->canvas),
262
clouds_rootitem = goo_canvas_group_new (rootitem, NULL);
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));
270
/* Setup and Display the plane */
273
svg_handle = gc_rsvg_load("planegame/tuxhelico.svgz");
277
planeitem = goo_canvas_group_new (rootitem,
280
goo_canvas_item_translate(planeitem, plane_x, plane_y);
282
item = goo_canvas_svg_new (planeitem,
286
goo_canvas_item_scale(item,
290
g_object_unref(svg_handle);
294
plane_last_target = 10;
296
gcomprisBoard->number_of_sublevel=plane_last_target;
298
gcomprisBoard->sublevel=plane_target;
300
if(gcomprisBoard->level>1)
302
/* No scoring after level 1 */
307
gc_score_start(SCORESTYLE_NOTE,
310
gcomprisBoard->number_of_sublevel);
311
gc_score_set(gcomprisBoard->sublevel);
316
#define ISIN(x1, y1, px1, py1, px2, py2) \
317
(x1>px1 && x1<px2 && y1>py1 && y1<py2 ? TRUE : FALSE)
319
static void planegame_cloud_colision(GooCanvasItem *item)
321
GooCanvasBounds ib, pb;
323
goo_canvas_item_get_bounds(planeitem, &pb);
324
goo_canvas_item_get_bounds(item, &ib);
328
goo_canvas_item_remove(item);
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)
339
gint number = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item),
342
if(plane_target == number)
344
gc_sound_play_ogg ("sounds/gobble.wav", NULL);
347
goo_canvas_item_remove(item);
349
if(gcomprisBoard->level==1)
350
gc_score_set(plane_target);
352
if(plane_target == plane_last_target)
354
/* Try the next level */
355
gcomprisBoard->level++;
356
if(gcomprisBoard->level>gcomprisBoard->maxlevel)
357
gcomprisBoard->level = gcomprisBoard->maxlevel;
359
planegame_next_level();
360
gc_sound_play_ogg ("sounds/bonus.wav", NULL);
367
static void planegame_move_plane(GooCanvasItem *item)
369
GooCanvasBounds bounds;
371
goo_canvas_item_get_bounds(item, &bounds);
373
if(plane_x > BOARDWIDTH - (bounds.x2 - bounds.x1)
377
if(plane_x < 0 && planespeed_x < 0)
380
if(plane_y > BOARDHEIGHT - (bounds.y2 - bounds.y1)
384
if(plane_y < 0 && planespeed_y < 0)
387
goo_canvas_item_translate(item,
390
plane_x += planespeed_x;
391
plane_y += planespeed_y;
394
/* Destroy all the items */
395
static void planegame_destroy_all_items()
398
goo_canvas_item_remove(rootitem);
404
* This does the moves of the game items on the play canvas
407
static gint planegame_move_items (GtkWidget *widget, gpointer data)
411
/* Check collision with each cloud */
413
i < goo_canvas_item_get_n_children(clouds_rootitem);
415
planegame_cloud_colision(goo_canvas_item_get_child(clouds_rootitem,
419
planegame_move_plane(planeitem);
420
planemove_id = g_timeout_add (speed,
421
(GtkFunction) planegame_move_items, NULL);
426
static GooCanvasItem *planegame_create_item(GooCanvasItem *parent)
428
RsvgHandle *svg_handle;
429
RsvgDimensionData dimension;
430
GooCanvasItem *itemgroup;
436
/* Random cloud number */
437
if(g_random_int()%2==0)
444
min = MAX(1, plane_target - 1);
445
i = min + g_random_int()%(plane_target - min + 3);
447
number = g_strdup_printf("%d", i);
449
itemgroup = goo_canvas_group_new (parent, NULL);
451
g_object_set_data (G_OBJECT (itemgroup),
452
"cloud_number", GINT_TO_POINTER (i));
454
svg_handle = gc_rsvg_load("planegame/cloud.svgz");
455
rsvg_handle_get_dimensions(svg_handle, &dimension);
457
y = (g_random_int()%(BOARDHEIGHT -
458
(guint)(dimension.height * imageZoom)));
460
goo_canvas_item_translate(itemgroup,
464
item = goo_canvas_svg_new (itemgroup,
467
goo_canvas_item_scale(item, imageZoom, imageZoom);
469
g_object_unref(svg_handle);
471
g_object_set_data (G_OBJECT (item),
472
"cloud_number", GINT_TO_POINTER (i));
474
item = goo_canvas_text_new (itemgroup,
476
dimension.width*imageZoom/2,
477
dimension.height*imageZoom/2,
480
"font", gc_skin_font_board_big,
484
g_object_set_data (G_OBJECT (item),
485
"cloud_number", GINT_TO_POINTER (i));
487
goo_canvas_item_animate(itemgroup,
488
-dimension.width*imageZoom,
495
GOO_CANVAS_ANIMATE_FREEZE);
497
/* The plane is always on top */
498
goo_canvas_item_raise(itemgroup, NULL);
499
goo_canvas_item_raise(planeitem, NULL);
506
static void planegame_add_new_item()
508
planegame_create_item(clouds_rootitem);
512
* This is called on a low frequency and is used to drop new items
515
static gint planegame_drop_items (GtkWidget *widget, gpointer data)
517
planegame_add_new_item();
519
drop_items_id = g_timeout_add (fallSpeed,
520
(GtkFunction) planegame_drop_items, NULL);