Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBruno Coudoin <bcoudoin@src.gnome.org>2006-11-04 11:37:40 (GMT)
committer Bruno Coudoin <bcoudoin@src.gnome.org>2006-11-04 11:37:40 (GMT)
commitedcc5c384b2acc0d2bb5a47a11ffa4176259fee3 (patch)
tree9869d00f46b07157f67f6c8f397f8f2d3ad40abf
parent10ec7199e8a2c1ecc09ec5ff147ca67450e32ea9 (diff)
Improved clickgame by Joshua N.Pritikin /jpritikin on pobox point com/
* src/boards/clickgame.c: (clickgame_pause), (fish_reverse_direction), (fish_gobble), (canvas_event), (item_event), (clickgame_start), (clickgame_end), (clickgame_is_our_board), (clickgame_next_level), (clickgame_animate_item), (clickgame_move_item), (clickgame_destroy_item), (clickgame_destroy_all_items), (clickgame_move_items), (load_random_fish), (clickgame_create_item), (clickgame_drop_items): Improved clickgame by Joshua N.Pritikin /jpritikin on pobox point com/ Return images from load_random_pixmap instead of via global imagelist. Split the fish list into smallish and biggish. Rename some globals for clarity. Keep both normal and mirror'd fish in anticipation of direction reversal. Clean up background setup code. Add frighten and stun behaviors. Trivial cleanups. Put some fish on the screen immediately after starting. * src/gcompris/config.c: (item_event_ok): * src/gcompris/soundutil.c: (gc_sound_init), (scheduler_bgnd), (gc_sound_play_ogg): Improved the management of the sound: - shuffle the background musics on startup - really close the audio device when sounds are deactivated in the config panel - reopen the audio devide when sounds are activated in tha config panel
-rw-r--r--ChangeLog29
-rw-r--r--src/boards/clickgame.c764
-rw-r--r--src/gcompris/config.c6
-rw-r--r--src/gcompris/soundutil.c103
4 files changed, 516 insertions, 386 deletions
diff --git a/ChangeLog b/ChangeLog
index d6fb490..d81b30f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2006-11-04 Bruno coudoin <bruno.coudoin@free.fr>
+
+
+ * src/boards/clickgame.c: (clickgame_pause),
+ (fish_reverse_direction), (fish_gobble), (canvas_event),
+ (item_event), (clickgame_start), (clickgame_end),
+ (clickgame_is_our_board), (clickgame_next_level),
+ (clickgame_animate_item), (clickgame_move_item),
+ (clickgame_destroy_item), (clickgame_destroy_all_items),
+ (clickgame_move_items), (load_random_fish),
+ (clickgame_create_item), (clickgame_drop_items):
+
+ Improved clickgame by Joshua N.Pritikin /jpritikin on pobox point com/
+ Return images from load_random_pixmap instead of via global imagelist.
+ Split the fish list into smallish and biggish.
+ Rename some globals for clarity.
+ Keep both normal and mirror'd fish in anticipation of direction reversal.
+ Clean up background setup code.
+ Add frighten and stun behaviors.
+ Trivial cleanups.
+ Put some fish on the screen immediately after starting.
+
+ * src/gcompris/config.c: (item_event_ok):
+ * src/gcompris/soundutil.c: (gc_sound_init), (scheduler_bgnd),
+ (gc_sound_play_ogg): Improved the management of the sound:
+ - shuffle the background musics on startup
+ - really close the audio device when sounds are deactivated in the config panel
+ - reopen the audio devide when sounds are activated in tha config panel
+
2006-11-03 Bruno coudoin <bruno.coudoin@free.fr>
- Patch from Miguel that:
diff --git a/src/boards/clickgame.c b/src/boards/clickgame.c
index efa8a3a..a82a648 100644
--- a/src/boards/clickgame.c
+++ b/src/boards/clickgame.c
@@ -33,22 +33,25 @@
static gboolean board_paused = TRUE;
-static GList *item_list = NULL;
+static GList *item_list = NULL; // onscreen fish
static GList *item2del_list = NULL;
static GcomprisBoard *gcomprisBoard = NULL;
-static gint dummy_id = 0;
+static gulong event_handle_id;
+static gint move_items_id = 0;
static gint animate_id = 0;
static gint drop_items_id = 0;
-static GList *imagelist = NULL;
-
typedef struct {
double speed;
+ gint fright;
+ gint stun;
gint currentItem;
GnomeCanvasItem *rootitem;
- GList *item_list;
+ GSList *fwd_frames;
+ GSList *rev_frames;
+ GSList *cur_frames; // points to fwd_frames or rev_frames
} FishItem;
static void clickgame_start (GcomprisBoard *agcomprisBoard);
@@ -58,57 +61,65 @@ static gboolean clickgame_is_our_board (GcomprisBoard *gcomprisBoard);
static void clickgame_set_level (guint level);
static void clickgame_config(void);
-static FishItem *clickgame_create_item(GnomeCanvasGroup *parent);
+static FishItem *clickgame_create_item();
static gint clickgame_drop_items (GtkWidget *widget, gpointer data);
static gint clickgame_move_items (GtkWidget *widget, gpointer data);
static gint clickgame_animate_items (GtkWidget *widget, gpointer data);
static void clickgame_destroy_item(FishItem *fishitem);
static void clickgame_destroy_items(void);
static void clickgame_destroy_all_items(void);
-static void setup_item(FishItem *fishitem);
-static void load_random_pixmap(void);
static void clickgame_next_level(void);
static int gamewon;
static void game_won(void);
static guint32 fallSpeed = 0;
-static double speed = 0.0;
+static double moveSpeed = 0.0;
static double imageZoom = 0.0;
-// List of images to use in the game
-static gchar *pixmapList[] =
+
+static const gchar *smallFish[] =
+ {
+ "%s/cichlid1_%d.png",
+ "%s/cichlid4_%d.png",
+ "%s/collaris_%d.png",
+ "%s/discus3_%d.png",
+ "%s/eel_%d.png",
+ "%s/teeth_%d.png",
+ "%s/f02_%d.png",
+ };
+#define NUM_SMALLFISH G_N_ELEMENTS(smallFish)
+
+static const gchar *medFish[] =
{
- "fishes/blueking2_%d.png",
- "fishes/butfish_%d.png",
- "fishes/cichlid1_%d.png",
- "fishes/cichlid4_%d.png",
- "fishes/collaris_%d.png",
- "fishes/discus2_%d.png",
- "fishes/discus3_%d.png",
- "fishes/eel_%d.png",
- "fishes/f00_%d.png",
- "fishes/f01_%d.png",
- "fishes/f02_%d.png",
- "fishes/f03_%d.png",
- "fishes/f04_%d.png",
- "fishes/f05_%d.png",
- "fishes/f06_%d.png",
- "fishes/f07_%d.png",
- "fishes/f08_%d.png",
- "fishes/f09_%d.png",
- "fishes/f10_%d.png",
- "fishes/f11_%d.png",
- "fishes/f12_%d.png",
- "fishes/f13_%d.png",
- "fishes/manta_%d.png",
- "fishes/newf1_%d.png",
- "fishes/QueenAngel_%d.png",
- "fishes/shark1_%d.png",
- "fishes/six_barred_%d.png",
- "fishes/teeth_%d.png",
+ "%s/f00_%d.png",
+ "%s/f01_%d.png",
+ "%s/f03_%d.png",
+ "%s/f04_%d.png",
+ "%s/f05_%d.png",
+ "%s/f06_%d.png",
+ "%s/f11_%d.png",
+ "%s/f12_%d.png",
+ "%s/f13_%d.png",
+ "%s/QueenAngel_%d.png",
+ "%s/six_barred_%d.png",
+ "%s/shark1_%d.png",
};
-#define NUMBER_OF_IMAGES G_N_ELEMENTS(pixmapList)
+#define NUM_MEDFISH G_N_ELEMENTS(medFish)
+
+static const gchar *bigFish[] =
+ {
+ "%s/blueking2_%d.png",
+ "%s/butfish_%d.png",
+ "%s/discus2_%d.png",
+ "%s/f07_%d.png",
+ "%s/f08_%d.png",
+ "%s/f09_%d.png",
+ "%s/f10_%d.png",
+ "%s/manta_%d.png",
+ "%s/newf1_%d.png",
+ };
+#define NUM_BIGFISH G_N_ELEMENTS(bigFish)
/* Description of this plugin */
static BoardPlugin menu_bp =
@@ -116,7 +127,7 @@ static BoardPlugin menu_bp =
NULL,
NULL,
"Click On Me",
- "Left-Click with the mouse on all swimming fish before they leave the fishtank",
+ "Click with the mouse on all swimming fish before they leave the fishtank",
"Bruno Coudoin <bruno.coudoin@free.fr>",
NULL,
NULL,
@@ -159,9 +170,9 @@ static void clickgame_pause (gboolean pause)
if(pause)
{
- if (dummy_id) {
- gtk_timeout_remove (dummy_id);
- dummy_id = 0;
+ if (move_items_id) {
+ gtk_timeout_remove (move_items_id);
+ move_items_id = 0;
}
if (animate_id) {
gtk_timeout_remove (animate_id);
@@ -178,8 +189,8 @@ static void clickgame_pause (gboolean pause)
drop_items_id = gtk_timeout_add (200,
(GtkFunction) clickgame_drop_items, NULL);
}
- if(!dummy_id) {
- dummy_id = gtk_timeout_add (200, (GtkFunction) clickgame_move_items, NULL);
+ if(!move_items_id) {
+ move_items_id = gtk_timeout_add (200, (GtkFunction) clickgame_move_items, NULL);
}
if(!animate_id) {
animate_id = gtk_timeout_add (200, (GtkFunction) clickgame_animate_items, NULL);
@@ -189,30 +200,239 @@ static void clickgame_pause (gboolean pause)
board_paused = pause;
}
+static void
+fish_reverse_direction (FishItem *fish)
+{
+ fish->speed = -fish->speed;
+
+ gnome_canvas_item_hide(g_slist_nth_data(fish->cur_frames,
+ fish->currentItem));
+
+ fish->cur_frames =
+ fish->speed<0? fish->rev_frames : fish->fwd_frames;
+
+ gnome_canvas_item_show(g_slist_nth_data(fish->cur_frames,
+ fish->currentItem));
+}
+
+static void
+fish_gobble (FishItem *fishitem)
+{
+ clickgame_destroy_item(fishitem);
+ gc_sound_play_ogg ("sounds/gobble.ogg", NULL);
+
+ gcomprisBoard->sublevel++;
+ gc_score_set(gcomprisBoard->sublevel);
+
+ if(gcomprisBoard->sublevel>=gcomprisBoard->number_of_sublevel) {
+ gamewon = TRUE;
+ clickgame_destroy_all_items();
+ gc_bonus_display(gamewon, BONUS_FLOWER);
+ return;
+ }
+ /* Drop a new item now to speed up the game */
+ if(g_list_length(item_list)==0)
+ {
+ /* Remove any pending new item creation to sync the falls */
+ if (drop_items_id)
+ gtk_timeout_remove (drop_items_id);
+ drop_items_id =
+ gtk_timeout_add (0, (GtkFunction) clickgame_drop_items, NULL);
+ }
+}
+
+static gint
+canvas_event(GnomeCanvas *canvas, GdkEvent *event)
+{
+ FishItem *fish;
+ double mouse_x = event->button.x;
+ double mouse_y = event->button.y;
+ int ii;
+
+ switch (event->type)
+ {
+ case GDK_BUTTON_PRESS:
+ switch(event->button.button)
+ {
+ case 1:
+ case 2:
+ case 3:
+ if (gcomprisBoard->level >= 3 &&
+ !(event->button.state & GDK_SHIFT_MASK)) {
+ for (ii=0; (fish=g_list_nth_data(item_list, ii)); ii++) {
+ double dx, dy, near;
+ double x1,x2,y1,y2;
+ int react;
+ gnome_canvas_item_get_bounds (fish->rootitem, &x1, &y1, &x2, &y2);
+ //printf("fish %d\n", ii);
+
+ dy = (mouse_y - (y1 + (y2 - y1) / 2)) / ((y2 - y1) / 2);
+ //printf("dy = %.2f\n", dy);
+ if (fabs(dy) > 2) continue;
+
+ dx = (mouse_x - (x1 + (x2 - x1) / 2)) / ((x2 - x1) / 2);
+ //printf("dx = %.2f\n", dx);
+ if (fabs(dx) > 2) continue;
+
+ // 0 to .9
+ near = (2.83 - sqrt(dx*dx + dy*dy)) / 3.15;
+ //printf("near = %.2f\n", near);
+
+ react = ((rand() % 1000 < near * 1000) +
+ (rand() % 1000 < near * 1000));
+ if (react) {
+ if (gnome_canvas_get_item_at (canvas, mouse_x, mouse_y) !=
+ g_slist_nth_data (fish->cur_frames, fish->currentItem) &&
+ (dx > 0) ^ (fish->speed < 0))
+ fish_reverse_direction (fish);
+ else
+ react += 1;
+ }
+ if (react >= 2)
+ fish->fright +=
+ (1000 + rand() % (int)(near * 2000)) / moveSpeed;
+ }
+ }
+ break;
+ default: break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+static gint
+item_event(GnomeCanvasItem *item, GdkEvent *event, FishItem *fishitem)
+{
+ static double x, y;
+ double new_x, new_y;
+ GdkCursor *fleur;
+ static int dragging;
+ double item_x, item_y;
+
+ if(!gcomprisBoard)
+ return FALSE;
+
+ if(board_paused)
+ return FALSE;
+
+ item_x = event->button.x;
+ item_y = event->button.y;
+ gnome_canvas_item_w2i(item->parent, &item_x, &item_y);
+
+ switch (event->type)
+ {
+ case GDK_BUTTON_PRESS:
+ switch(event->button.button)
+ {
+ case 1:
+ case 2:
+ case 3:
+ if (event->button.state & GDK_SHIFT_MASK)
+ {
+ x = item_x;
+ y = item_y;
+
+ fleur = gdk_cursor_new(GDK_FLEUR);
+ gc_canvas_item_grab(item,
+ GDK_POINTER_MOTION_MASK |
+ GDK_BUTTON_RELEASE_MASK,
+ fleur,
+ event->button.time);
+ gdk_cursor_destroy(fleur);
+ dragging = TRUE;
+ }
+ else
+ {
+ if (gcomprisBoard->level >= 5 && !fishitem->stun) {
+ fishitem->stun = 500 * (1 + gcomprisBoard->maxlevel - gcomprisBoard->level) / moveSpeed;
+ fishitem->fright += 500 / moveSpeed;
+ } else {
+ fish_gobble (fishitem);
+ }
+ }
+ break;
+
+ case 4:
+ /* fish up */
+ gnome_canvas_item_move(item, 0.0, -3.0);
+ break;
+
+ case 5:
+ /* fish down */
+ gnome_canvas_item_move(item, 0.0, 3.0);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case GDK_MOTION_NOTIFY:
+ if (dragging && (event->motion.state & GDK_BUTTON1_MASK))
+ {
+ new_x = item_x;
+ new_y = item_y;
+
+ gnome_canvas_item_move(item, new_x - x, new_y - y);
+ x = new_x;
+ y = new_y;
+ }
+ break;
+
+ case GDK_BUTTON_RELEASE:
+ if(dragging)
+ {
+ gc_canvas_item_ungrab(item, event->button.time);
+ dragging = FALSE;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return FALSE;
+ }
+
/*
*/
static void clickgame_start (GcomprisBoard *agcomprisBoard)
{
- if(agcomprisBoard!=NULL)
- {
- gcomprisBoard = agcomprisBoard;
-
- /* set initial values for this level */
- gcomprisBoard->level = 1;
- gcomprisBoard->maxlevel=6;
- gcomprisBoard->number_of_sublevel=10; /* Go to next level after this number of 'play' */
- gc_score_start(SCORESTYLE_NOTE,
- gcomprisBoard->width - 220,
- gcomprisBoard->height - 50,
- gcomprisBoard->number_of_sublevel);
- gc_bar_set(GC_BAR_LEVEL);
-
- clickgame_next_level();
+ if (!agcomprisBoard)
+ return;
- clickgame_pause(FALSE);
+ gcomprisBoard = agcomprisBoard;
+
+ /* set initial values for this level */
+ gcomprisBoard->level = 1;
+ gcomprisBoard->maxlevel=6;
+ gcomprisBoard->number_of_sublevel=10; /* Go to next level after this number of 'play' */
+ gc_score_start(SCORESTYLE_NOTE,
+ gcomprisBoard->width - 220,
+ gcomprisBoard->height - 50,
+ gcomprisBoard->number_of_sublevel);
+ gc_bar_set(GC_BAR_LEVEL);
+
+ event_handle_id =
+ gtk_signal_connect(GTK_OBJECT(gcomprisBoard->canvas), "event",
+ (GtkSignalFunc) canvas_event, 0);
+ clickgame_next_level();
+ {
+ int ii;
+ for (ii=0; ii < 3; ii++) {
+ FishItem *fish = clickgame_create_item();
+ if (!fish) continue;
+ gnome_canvas_item_move(fish->rootitem,
+ fish->speed * (rand() % 200), 0.0);
}
+ }
+ clickgame_pause(FALSE);
}
static void
@@ -223,6 +443,8 @@ clickgame_end ()
clickgame_pause(TRUE);
gc_score_end();
clickgame_destroy_all_items();
+ gtk_signal_disconnect(GTK_OBJECT(gcomprisBoard->canvas),
+ event_handle_id);
gcomprisBoard->level = 1; // Restart this game to zero
}
gcomprisBoard = NULL;
@@ -240,14 +462,14 @@ clickgame_set_level (guint level)
}
static gboolean
-clickgame_is_our_board (GcomprisBoard *gcomprisBoard)
+clickgame_is_our_board (GcomprisBoard *board)
{
- if (gcomprisBoard)
+ if (board)
{
- if(g_strcasecmp(gcomprisBoard->type, "clickgame")==0)
+ if(g_strcasecmp(board->type, "clickgame")==0)
{
/* Set the plugin entry */
- gcomprisBoard->plugin=&menu_bp;
+ board->plugin=&menu_bp;
return TRUE;
}
@@ -272,41 +494,29 @@ clickgame_config ()
/* set initial values for the next level */
static void clickgame_next_level()
{
-
- switch(gcomprisBoard->level)
+ static /*const*/ gchar *bglist[] =
{
- case 1:
- gc_set_background(gnome_canvas_root(gcomprisBoard->canvas),
- "clickgame/nur00523.jpg");
- break;
- case 2:
- gc_set_background(gnome_canvas_root(gcomprisBoard->canvas),
- "clickgame/nur03006.jpg");
- break;
- case 3:
- gc_set_background(gnome_canvas_root(gcomprisBoard->canvas),
- "clickgame/nur03011.jpg");
- break;
- case 4:
- gc_set_background(gnome_canvas_root(gcomprisBoard->canvas),
- "clickgame/nur03010.jpg");
- break;
- case 5:
- gc_set_background(gnome_canvas_root(gcomprisBoard->canvas),
- "clickgame/nur03013.jpg");
- break;
- default:
- gc_set_background(gnome_canvas_root(gcomprisBoard->canvas),
- "clickgame/nur03505.jpg");
- }
+ "clickgame/nur00523.jpg",
+ "clickgame/nur03006.jpg",
+ "clickgame/nur03011.jpg",
+ "clickgame/nur03010.jpg",
+ "clickgame/nur03013.jpg",
+ "clickgame/nur03505.jpg"
+ };
+
+ int bgx = gcomprisBoard->level - 1;
+
+ if (bgx < 0 || G_N_ELEMENTS(bglist) <= bgx)
+ bgx = G_N_ELEMENTS(bglist) - 1;
+
+ gc_set_background(gnome_canvas_root(gcomprisBoard->canvas), bglist[bgx]);
gc_bar_set_level(gcomprisBoard);
/* Try the next level */
- speed=100+(40/(gcomprisBoard->level));
+ moveSpeed=100+(40/(gcomprisBoard->level));
fallSpeed=5000-gcomprisBoard->level*200;
- /* Make the images tend to 0.5 ratio */
- imageZoom=0.5+(0.5/(gcomprisBoard->level));
+ imageZoom = 0.75 + 0.25 * ((gcomprisBoard->maxlevel - gcomprisBoard->level + 1) / gcomprisBoard->maxlevel);
gcomprisBoard->sublevel=0;
gc_score_set(gcomprisBoard->sublevel);
@@ -320,23 +530,31 @@ static void clickgame_animate_item(FishItem *fishitem)
/* Manage the animation */
currentItem = fishitem->currentItem;
fishitem->currentItem++;
- if(fishitem->currentItem >= g_list_length(fishitem->item_list))
+ if(fishitem->currentItem >= g_slist_length(fishitem->cur_frames))
fishitem->currentItem=0;
- gnome_canvas_item_show((GnomeCanvasItem *)g_list_nth_data(fishitem->item_list,
- fishitem->currentItem));
+ gnome_canvas_item_show((GnomeCanvasItem *)g_slist_nth_data(fishitem->cur_frames,
+ fishitem->currentItem));
- gnome_canvas_item_hide((GnomeCanvasItem *)g_list_nth_data(fishitem->item_list,
- currentItem));
+ gnome_canvas_item_hide((GnomeCanvasItem *)g_slist_nth_data(fishitem->cur_frames,
+ currentItem));
}
static void clickgame_move_item(FishItem *fishitem)
{
+ double sp = fishitem->speed;
double x1, y1, x2, y2;
GnomeCanvasItem *item = fishitem->rootitem;
- gnome_canvas_item_move(item, fishitem->speed, 0.0);
+ if (fishitem->stun) {
+ --fishitem->stun;
+ sp *= .1 + (rand() % 100) / 1000.0;
+ } else if (fishitem->fright) {
+ --fishitem->fright;
+ sp *= 3 + (rand() % 3000) / 1000.0;
+ }
+ gnome_canvas_item_move(item, sp, 0.0);
gnome_canvas_item_get_bounds (item,
@@ -370,7 +588,8 @@ static void clickgame_destroy_item(FishItem *fishitem)
item2del_list = g_list_remove (item2del_list, fishitem);
gtk_object_destroy (GTK_OBJECT(item));
- g_list_free(fishitem->item_list);
+ g_slist_free (fishitem->fwd_frames);
+ g_slist_free (fishitem->rev_frames);
g_free(fishitem);
}
@@ -389,22 +608,11 @@ static void clickgame_destroy_items()
/* Destroy all the items */
static void clickgame_destroy_all_items()
{
- FishItem *fishitem;
-
- while(g_list_length(item_list)>0)
+ while(item_list)
{
- fishitem = g_list_nth_data(item_list, 0);
+ FishItem *fishitem = g_list_nth_data(item_list, 0);
clickgame_destroy_item(fishitem);
}
- if(item_list) {
- g_list_free(item_list);
- item_list = NULL;
- }
-
- if(imagelist) {
- g_list_free(imagelist);
- imagelist = NULL;
- }
}
/*
@@ -418,8 +626,8 @@ static gint clickgame_move_items (GtkWidget *widget, gpointer data)
/* Destroy items that falls out of the canvas */
clickgame_destroy_items();
- dummy_id = gtk_timeout_add (speed,
- (GtkFunction) clickgame_move_items, NULL);
+ move_items_id = gtk_timeout_add (moveSpeed,
+ (GtkFunction) clickgame_move_items, NULL);
return(FALSE);
}
@@ -438,27 +646,85 @@ static gint clickgame_animate_items (GtkWidget *widget, gpointer data)
return(FALSE);
}
-static FishItem *clickgame_create_item(GnomeCanvasGroup *parent)
+static GSList *load_random_fish(gboolean smallish)
+{
+ int fish;
+ const gchar **extraFish;
+ const gchar **surpriseFish;
+ int num_extra;
+ int num_surprise;
+
+ if (smallish) {
+ extraFish = smallFish;
+ num_extra = NUM_SMALLFISH;
+ surpriseFish = bigFish;
+ num_surprise = NUM_BIGFISH;
+ } else {
+ extraFish = bigFish;
+ num_extra = NUM_BIGFISH;
+ surpriseFish = smallFish;
+ num_surprise = NUM_SMALLFISH;
+ }
+
+ fish = rand() % (NUM_MEDFISH + num_extra + 2);
+
+ const gchar *path;
+ if (fish < NUM_MEDFISH) {
+ path = medFish[fish];
+ } else if (fish < NUM_MEDFISH + num_extra) {
+ path = extraFish[fish - NUM_MEDFISH];
+ } else {
+ fish = rand() % num_surprise;
+ path = surpriseFish[fish];
+ }
+
+ int frame = 0;
+ GSList *ilist = 0;
+ while(1)
+ {
+ if (frame) {
+ gchar *exists = gc_file_find_absolute (path, "fishes", frame);
+ g_free (exists);
+ if (!exists) break;
+ }
+
+ GdkPixbuf *pixmap = gc_pixmap_load (path, "fishes", frame);
+ if (!pixmap) break;
+
+ ilist = g_slist_prepend (ilist, pixmap);
+ ++frame;
+ }
+ return g_slist_reverse (ilist);
+}
+
+static FishItem *
+clickgame_create_item()
{
+ GnomeCanvasGroup *parent = gnome_canvas_root(gcomprisBoard->canvas);
GdkPixbuf *pixmap = NULL;
GdkPixbuf *pixmap2 = NULL;
- GnomeCanvasItem *rootitem, *item;
+ GnomeCanvasItem *rootitem;
FishItem *fishitem;
double x;
gint i, length;
+ GSList *ilist;
/* Avoid to have too much items displayed */
if(g_list_length(item_list)>5)
return NULL;
- load_random_pixmap();
+ // select smallish fish on even levels, also see imageZoom
+ ilist = load_random_fish (!(gcomprisBoard->level & 1));
fishitem = g_malloc(sizeof(FishItem));
fishitem->currentItem = 0;
fishitem->speed = (double)(rand()%(60))/10 - 3;
- fishitem->item_list = NULL;
+ fishitem->fright = 0;
+ fishitem->stun = 0;
+ fishitem->fwd_frames = NULL;
+ fishitem->rev_frames = NULL;
- pixmap = (GdkPixbuf *)g_list_nth_data(imagelist, 0);
+ pixmap = (GdkPixbuf *)g_slist_nth_data(ilist, 0);
if(pixmap==NULL)
return NULL;
@@ -483,60 +749,72 @@ static FishItem *clickgame_create_item(GnomeCanvasGroup *parent)
imageZoom))),
NULL);
+ gtk_signal_connect(GTK_OBJECT(rootitem), "event",
+ (GtkSignalFunc) item_event, fishitem);
fishitem->rootitem = rootitem;
- length = g_list_length(imagelist);
+ length = g_slist_length(ilist);
for(i=0; i<length; i++)
{
- pixmap = (GdkPixbuf *)g_list_nth_data(imagelist, i);
-
- pixmap2 = pixbuf_copy_mirror(pixmap, (fishitem->speed<0?TRUE:FALSE), FALSE);
-
+ GnomeCanvasItem *fwd, *rev;
+
+ pixmap = (GdkPixbuf *)g_slist_nth_data(ilist, i);
+ pixmap2 = pixbuf_copy_mirror(pixmap, TRUE, FALSE);
+
+ fwd = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
+ gnome_canvas_pixbuf_get_type (),
+ "pixbuf", pixmap,
+ "x", 0.0,
+ "y", 0.0,
+ "width", (double) gdk_pixbuf_get_width(pixmap)*imageZoom,
+ "height", (double) gdk_pixbuf_get_height(pixmap)*imageZoom,
+ "width_set", TRUE,
+ "height_set", TRUE,
+ NULL);
+ rev = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
+ gnome_canvas_pixbuf_get_type (),
+ "pixbuf", pixmap2,
+ "x", 0.0,
+ "y", 0.0,
+ "width", (double) gdk_pixbuf_get_width(pixmap2)*imageZoom,
+ "height", (double) gdk_pixbuf_get_height(pixmap2)*imageZoom,
+ "width_set", TRUE,
+ "height_set", TRUE,
+ NULL);
gdk_pixbuf_unref(pixmap);
-
- item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
- gnome_canvas_pixbuf_get_type (),
- "pixbuf", pixmap2,
- "x", 0.0,
- "y", 0.0,
- "width", (double) gdk_pixbuf_get_width(pixmap)*imageZoom,
- "height", (double) gdk_pixbuf_get_height(pixmap)*imageZoom,
- "width_set", TRUE,
- "height_set", TRUE,
- NULL);
gdk_pixbuf_unref(pixmap2);
- if(i==fishitem->currentItem)
- gnome_canvas_item_show(item);
- else
- gnome_canvas_item_hide(item);
+ fishitem->fwd_frames = g_slist_prepend (fishitem->fwd_frames, fwd);
+ fishitem->rev_frames = g_slist_prepend (fishitem->rev_frames, rev);
- fishitem->item_list = g_list_append (fishitem->item_list, item);
+ gnome_canvas_item_hide (fwd);
+ gnome_canvas_item_hide (rev);
}
- for(i=0; i<length; i++)
- {
- pixmap = (GdkPixbuf *)g_list_nth_data(imagelist, 0);
- imagelist = g_list_remove(imagelist, pixmap);
- }
+ g_slist_free (ilist);
+
+ fishitem->fwd_frames = g_slist_reverse (fishitem->fwd_frames);
+ fishitem->rev_frames = g_slist_reverse (fishitem->rev_frames);
+
+ fishitem->cur_frames =
+ fishitem->speed<0? fishitem->rev_frames : fishitem->fwd_frames;
+
+ gnome_canvas_item_show(g_slist_nth_data(fishitem->cur_frames,
+ fishitem->currentItem));
+
item_list = g_list_append (item_list, fishitem);
return (fishitem);
}
-static void clickgame_add_new_item()
-{
- setup_item (clickgame_create_item(gnome_canvas_root(gcomprisBoard->canvas)));
-}
-
/*
* This is called on a low frequency and is used to drop new items
*
*/
static gint clickgame_drop_items (GtkWidget *widget, gpointer data)
{
- clickgame_add_new_item();
+ clickgame_create_item();
drop_items_id = gtk_timeout_add (fallSpeed,
(GtkFunction) clickgame_drop_items, NULL);
@@ -561,181 +839,3 @@ static void game_won()
clickgame_next_level();
}
-static gint
-item_event(GnomeCanvasItem *item, GdkEvent *event, FishItem *fishitem)
-{
- static double x, y;
- double new_x, new_y;
- GdkCursor *fleur;
- static int dragging;
- double item_x, item_y;
-
- if(!gcomprisBoard)
- return FALSE;
-
- if(board_paused)
- return FALSE;
-
- item_x = event->button.x;
- item_y = event->button.y;
- gnome_canvas_item_w2i(item->parent, &item_x, &item_y);
-
- switch (event->type)
- {
- case GDK_BUTTON_PRESS:
- switch(event->button.button)
- {
- case 1:
- if (event->button.state & GDK_SHIFT_MASK)
- {
- x = item_x;
- y = item_y;
-
- fleur = gdk_cursor_new(GDK_FLEUR);
- gc_canvas_item_grab(item,
- GDK_POINTER_MOTION_MASK |
- GDK_BUTTON_RELEASE_MASK,
- fleur,
- event->button.time);
- gdk_cursor_destroy(fleur);
- dragging = TRUE;
- }
- else
- {
- clickgame_destroy_item(fishitem);
- gc_sound_play_ogg ("sounds/gobble.ogg", NULL);
-
- gcomprisBoard->sublevel++;
- gc_score_set(gcomprisBoard->sublevel);
-
- if(gcomprisBoard->sublevel>=gcomprisBoard->number_of_sublevel) {
- gamewon = TRUE;
- clickgame_destroy_all_items();
- gc_bonus_display(gamewon, BONUS_FLOWER);
- return FALSE;
- }
- /* Drop a new item now to speed up the game */
- if(g_list_length(item_list)==0)
- {
- if (drop_items_id) {
- /* Remove pending new item creation to sync the falls */
- gtk_timeout_remove (drop_items_id);
- drop_items_id = 0;
- }
- if(!drop_items_id) {
- drop_items_id = gtk_timeout_add (0,
- (GtkFunction) clickgame_drop_items,
- NULL);
- }
- }
- }
- break;
-
- case 3:
- /* Speed up the fish */
- if(fishitem->speed>0)
- fishitem->speed = MAX(fishitem->speed+1 , 5);
- else
- fishitem->speed = MIN(fishitem->speed-1, -5);
- break;
-
- case 2:
- /* Slow the fish */
- if(fishitem->speed>0)
- fishitem->speed = MAX(fishitem->speed-1, 1);
- else
- fishitem->speed = MIN(fishitem->speed+1, -1);
- break;
-
- case 4:
- /* fish up */
- gnome_canvas_item_move(item, 0.0, -3.0);
- break;
-
- case 5:
- /* fish down */
- gnome_canvas_item_move(item, 0.0, 3.0);
- break;
-
- default:
- break;
- }
- break;
-
- case GDK_MOTION_NOTIFY:
- if (dragging && (event->motion.state & GDK_BUTTON1_MASK))
- {
- new_x = item_x;
- new_y = item_y;
-
- gnome_canvas_item_move(item, new_x - x, new_y - y);
- x = new_x;
- y = new_y;
- }
- break;
-
- case GDK_BUTTON_RELEASE:
- if(dragging)
- {
- gc_canvas_item_ungrab(item, event->button.time);
- dragging = FALSE;
- }
- break;
-
- default:
- break;
- }
-
- return FALSE;
- }
-
-static void
-setup_item(FishItem *fishitem)
-{
- if(fishitem)
- gtk_signal_connect(GTK_OBJECT(fishitem->rootitem), "event",
- (GtkSignalFunc) item_event,
- fishitem);
-}
-
-/*
- * Return the list of pixmap in the global
- * imagelist
- */
-static void load_random_pixmap()
-{
- GdkPixbuf *pixmap;
- int i, j;
- gchar *str = NULL;
- gboolean cont = TRUE;
-
- i=rand()%(NUMBER_OF_IMAGES);
-
- /* First image */
- j=0;
-
- while(cont)
- {
- gchar *url;
- str = g_strdup(pixmapList[i]);
-
- url = gc_file_find_absolute(str, j++);
-
- if(!url)
- {
- cont = FALSE;
- }
- else
- {
- pixmap = gc_pixmap_load (str, j-1);
-
- if(pixmap) {
- imagelist = g_list_append (imagelist, pixmap);
- } else {
- cont = FALSE;
- }
- }
- g_free(str);
- }
-
-}
diff --git a/src/gcompris/config.c b/src/gcompris/config.c
index 0d29395..b10138d 100644
--- a/src/gcompris/config.c
+++ b/src/gcompris/config.c
@@ -736,9 +736,11 @@ item_event_ok(GnomeCanvasItem *item, GdkEvent *event, gpointer data)
gc_skin_load(properties->skin);
gc_config_stop();
- if(properties->music || properties->fx) {
+ if(properties->music || properties->fx)
gc_sound_init();
- }
+
+ if(!properties->music && !properties->fx)
+ gc_sound_close();
gc_prop_save(properties);
}
diff --git a/src/gcompris/soundutil.c b/src/gcompris/soundutil.c
index 9892e03..033bb05 100644
--- a/src/gcompris/soundutil.c
+++ b/src/gcompris/soundutil.c
@@ -18,7 +18,6 @@
*/
#include "string.h"
-#include <unistd.h> /* sleep */
#ifdef __APPLE__
# include <sys/types.h>
@@ -34,7 +33,6 @@ static gboolean sound_closed = FALSE;
/* mutex */
GMutex *lock = NULL;
-GMutex *lock_bg = NULL;
GCond *cond = NULL;
/* Singleton */
@@ -61,6 +59,16 @@ void
gc_sound_init()
{
+ /* Check to run the init once only */
+ if(sound_init == 1)
+ {
+ if(sound_closed == TRUE)
+ gc_sound_reopen();
+
+ return;
+ }
+ sound_init = 1;
+
gc_sound_controller = g_object_new (GCOMPRIS_SOUND_TYPE, NULL);
g_signal_connect( gc_sound_controller,
@@ -70,17 +78,10 @@ gc_sound_init()
g_assert( gc_sound_controller != NULL );
- /* Check to run the init once only */
- if(sound_init == 1) {
- return;
- }
- sound_init = 1;
-
/* Initialize the thread system */
if (!g_thread_supported ()) g_thread_init (NULL);
lock = g_mutex_new ();
- lock_bg = g_mutex_new ();
cond = g_cond_new ();
sound_policy = PLAY_AFTER_CURRENT;
@@ -102,35 +103,37 @@ gc_sound_init()
perror("create failed for scheduler background");
}
+
void
gc_sound_close()
{
- if ( ! ( sound_closed || ( ( gc_prop_get()->music == 0 )
- && ( gc_prop_get()->fx == 0) ) ) ){
- g_mutex_lock(lock);
- g_mutex_lock(lock_bg);
- sdlplayer_close();
- sound_closed = TRUE;
- }
+ if ( !sound_closed )
+ {
+ g_mutex_lock(lock);
+ sdlplayer_close();
+ sound_closed = TRUE;
+ }
}
void
gc_sound_reopen()
{
- if (sound_closed){
- sdlplayer_reopen();
- g_mutex_unlock(lock);
- g_mutex_unlock(lock_bg);
- sound_closed = FALSE;
- }
+ if (sound_closed)
+ {
+ sdlplayer_reopen();
+ g_mutex_unlock(lock);
+ sound_closed = FALSE;
+ }
}
void
-gc_sound_pause(){
+gc_sound_pause()
+{
sdlplayer_pause();
}
void
-gc_sound_resume(){
+gc_sound_resume()
+{
sdlplayer_resume();
}
@@ -168,16 +171,12 @@ scheduler_bgnd (gpointer user_data)
gint i;
gchar *str;
gchar *music_dir;
- GList *musiclist = NULL;
+ GSList *musiclist = NULL;
GDir *dir;
const gchar *one_dirent;
/* Sleep to let gcompris intialisation and intro music to complete */
-#if defined WIN32
- sleep(25000);
-#else
- sleep(25);
-#endif
+ g_usleep(25000000);
/* Load the Music directory file names */
music_dir = g_strconcat(properties->package_data_dir, "/music/background", NULL);
@@ -191,18 +190,18 @@ scheduler_bgnd (gpointer user_data)
}
/* Fill up the music list */
- while((one_dirent = g_dir_read_name(dir)) != NULL) {
-
- if (strcmp(one_dirent, "COPYRIGHT")) {
- str = g_strdup_printf("%s/%s", music_dir, one_dirent);
-
- musiclist = g_list_append (musiclist, str);
+ while((one_dirent = g_dir_read_name(dir)) != NULL)
+ {
+ if (g_str_has_suffix(one_dirent, ".ogg"))
+ {
+ str = g_strdup_printf("%s/%s", music_dir, one_dirent);
+ musiclist = g_slist_insert (musiclist, str, RAND(0, g_slist_length(musiclist)));
+ }
}
- }
g_dir_close(dir);
/* No music no play */
- if(g_list_length(musiclist)==0)
+ if(g_slist_length(musiclist)==0)
{
g_free(music_dir);
return NULL;
@@ -211,27 +210,27 @@ scheduler_bgnd (gpointer user_data)
/* Now loop over all our music files */
while (TRUE)
{
- /* Music can be disabled at any time */
- if ( !gc_prop_get()->music )
- return NULL;
-
- for(i=0; i<g_list_length(musiclist); i++)
+ for(i=0; i<g_slist_length(musiclist); i++)
{
+ /* Music can be disabled at any time */
+ if ( !gc_prop_get()->music )
+ {
+ g_usleep(5000000);
+ continue;
+ }
+
/* WARNING Displaying stuff in a thread seems to make gcompris unstable */
/* display_ogg_file_credits((char *)g_list_nth_data(musiclist, i)); */
// if(decode_ogg_file((char *)g_list_nth_data(musiclist, i))!=0)
- if(sdlplayer_bg((char *)g_list_nth_data(musiclist, i), 128)!=0){
- g_warning("Stopping music, sdlplayer_bg failed");
- goto exit;
+ if(sdlplayer_bg((char *)g_slist_nth_data(musiclist, i), 128)!=0){
+ g_warning("Stopping music, sdlplayer_bg failed, try again in 5 seconds");
+ g_usleep(5000000);
}
- g_mutex_lock( lock_bg );
- g_mutex_unlock( lock_bg );
}
}
-
- exit:
- g_list_free(musiclist);
+ /* Never happen */
+ g_slist_free(musiclist);
g_warning( "The background thread music is stopped now. "\
"The files in %s are not ogg vorbis OR the sound output failed",
music_dir);
@@ -355,7 +354,7 @@ gc_sound_play_ogg(const gchar *sound, ...)
char* tmp = NULL;
GList* list = NULL;
- if(!sound)
+ if(!sound || !gc_prop_get()->fx)
return;
list = g_list_append(list, (gpointer)sound);