summaryrefslogtreecommitdiffstats
path: root/app/dialogs/lebl-dialog.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--app/dialogs/lebl-dialog.c869
1 files changed, 869 insertions, 0 deletions
diff --git a/app/dialogs/lebl-dialog.c b/app/dialogs/lebl-dialog.c
new file mode 100644
index 0000000..53bd492
--- /dev/null
+++ b/app/dialogs/lebl-dialog.c
@@ -0,0 +1,869 @@
+#include "config.h"
+
+#include <string.h>
+#include <math.h>
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "lebl-dialog.h"
+
+#include "gimp-intl.h"
+
+/* phish code */
+#define PHSHFRAMES 8
+#define PHSHORIGWIDTH 288
+#define PHSHORIGHEIGHT 22
+#define PHSHWIDTH (PHSHORIGWIDTH/PHSHFRAMES)
+#define PHSHHEIGHT PHSHORIGHEIGHT
+#define PHSHCHECKTIMEOUT (g_random_int()%120*1000)
+#define PHSHTIMEOUT 120
+#define PHSHHIDETIMEOUT 80
+#define PHSHXS 5
+#define PHSHYS ((g_random_int() % 2) + 1)
+#define PHSHXSHIDEFACTOR 2.5
+#define PHSHYSHIDEFACTOR 2.5
+#define PHSHPIXELSTOREMOVE(p) (p[3] < 55 || p[2] > 200)
+
+static void
+phsh_unsea(GdkPixbuf *gp)
+{
+ guchar *pixels = gdk_pixbuf_get_pixels (gp);
+ int rs = gdk_pixbuf_get_rowstride (gp);
+ int w = gdk_pixbuf_get_width (gp);
+ int h = gdk_pixbuf_get_height (gp);
+ int x, y;
+
+ for (y = 0; y < h; y++, pixels += rs) {
+ guchar *p = pixels;
+ for (x = 0; x < w; x++, p+=4) {
+ if (PHSHPIXELSTOREMOVE(p))
+ p[3] = 0;
+ }
+ }
+}
+
+static GdkPixbuf *
+get_phsh_frame (GdkPixbuf *pb, int frame)
+{
+ GdkPixbuf *newpb;
+
+ newpb = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
+ PHSHWIDTH, PHSHHEIGHT);
+ gdk_pixbuf_copy_area (pb, frame * PHSHWIDTH, 0,
+ PHSHWIDTH, PHSHHEIGHT, newpb, 0, 0);
+
+ return newpb;
+}
+
+typedef struct {
+ gboolean live;
+ int x, y;
+} InvGoat;
+
+typedef struct {
+ gboolean good;
+ int y;
+ int x;
+} InvShot;
+
+
+static GtkWidget *geginv = NULL;
+static GtkWidget *geginv_canvas = NULL;
+static GtkWidget *geginv_label = NULL;
+static GdkPixbuf *inv_goat1 = NULL;
+static GdkPixbuf *inv_goat2 = NULL;
+static GdkPixbuf *inv_phsh1 = NULL;
+static GdkPixbuf *inv_phsh2 = NULL;
+static int inv_phsh_state = 0;
+static int inv_goat_state = 0;
+static int inv_width = 0;
+static int inv_height = 0;
+static int inv_goat_width = 0;
+static int inv_goat_height = 0;
+static int inv_phsh_width = 0;
+static int inv_phsh_height = 0;
+#define INV_ROWS 3
+#define INV_COLS 5
+static InvGoat invs[INV_COLS][INV_ROWS] = { { { FALSE, 0, 0 } } };
+static int inv_num = INV_ROWS * INV_COLS;
+static double inv_factor = 1.0;
+static int inv_our_x = 0;
+static int inv_x = 0;
+static int inv_y = 0;
+static int inv_first_col = 0;
+static int inv_last_col = INV_COLS-1;
+static int inv_level = 0;
+static int inv_lives = 0;
+static gboolean inv_do_pause = FALSE;
+static gboolean inv_reverse = FALSE;
+static gboolean inv_game_over = FALSE;
+static gboolean inv_left_pressed = FALSE;
+static gboolean inv_right_pressed = FALSE;
+static gboolean inv_fire_pressed = FALSE;
+static gboolean inv_left_released = FALSE;
+static gboolean inv_right_released = FALSE;
+static gboolean inv_fire_released = FALSE;
+static gboolean inv_paused = FALSE;
+static GSList *inv_shots = NULL;
+static guint inv_draw_idle = 0;
+
+static void
+inv_show_status (void)
+{
+ gchar *s, *t, *u, *v, *w;
+ if (geginv == NULL)
+ return;
+
+ if (inv_game_over) {
+ t = g_strdup_printf (_("<b>GAME OVER</b> at level %d!"),
+ inv_level+1);
+ u = g_strdup_printf ("<big>%s</big>", t);
+ /* Translators: the first and third strings are similar to a
+ * title, and the second string is a small information text.
+ * The spaces are there only to separate all the strings, so
+ try to keep them as is. */
+ s = g_strdup_printf (_("%1$s %2$s %3$s"),
+ u, _("Press 'q' to quit"), u);
+ g_free (t);
+ g_free (u);
+
+ } else if (inv_paused) {
+ t = g_strdup_printf("<big><b>%s</b></big>", _("Paused"));
+ /* Translators: the first string is a title and the second
+ * string is a small information text. */
+ s = g_strdup_printf (_("%1$s\t%2$s"),
+ t, _("Press 'p' to unpause"));
+ g_free (t);
+
+ } else {
+ t = g_strdup_printf ("<b>%d</b>", inv_level+1);
+ u = g_strdup_printf ("<b>%d</b>", inv_lives);
+ v = g_strdup_printf (_("Level: %s, Lives: %s"), t, u);
+ w = g_strdup_printf ("<big>%s</big>", v);
+ /* Translators: the first string is a title and the second
+ * string is a small information text. */
+ s = g_strdup_printf (_("%1$s\t%2$s"), w,
+ _("Left/Right to move, Space to fire, 'p' to pause, 'q' to quit"));
+ g_free (t);
+ g_free (u);
+ g_free (v);
+ g_free (w);
+
+ }
+ gtk_label_set_markup (GTK_LABEL (geginv_label), s);
+
+ g_free (s);
+}
+
+static gboolean
+inv_draw (gpointer data)
+{
+ inv_draw_idle = 0;
+
+ if (geginv)
+ gtk_widget_queue_draw (data);
+
+ return FALSE;
+}
+
+static void
+inv_queue_draw (GtkWidget *window)
+{
+ if (inv_draw_idle == 0)
+ inv_draw_idle = g_idle_add (inv_draw, window);
+}
+
+static void
+inv_draw_explosion (int x, int y)
+{
+ cairo_t *cr;
+ int i;
+
+ if ( ! gtk_widget_is_drawable (geginv_canvas))
+ return;
+
+ cr = gdk_cairo_create ( gtk_widget_get_window (geginv_canvas));
+
+ cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);
+
+ for (i = 5; i < 100; i += 5) {
+ cairo_arc (cr, x, y, i, 0, 2 * G_PI);
+ cairo_fill (cr);
+ gdk_flush ();
+ g_usleep (50000);
+ }
+
+ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+
+ for (i = 5; i < 100; i += 5) {
+ cairo_arc (cr, x, y, i, 0, 2 * G_PI);
+ cairo_fill (cr);
+ gdk_flush ();
+ g_usleep (50000);
+ }
+
+ cairo_destroy (cr);
+
+ inv_queue_draw (geginv);
+}
+
+
+static void
+inv_do_game_over (void)
+{
+ GSList *li;
+
+ inv_game_over = TRUE;
+
+ for (li = inv_shots; li != NULL; li = li->next) {
+ InvShot *shot = li->data;
+ shot->good = FALSE;
+ }
+
+ inv_queue_draw (geginv);
+
+ inv_show_status ();
+}
+
+
+static GdkPixbuf *
+pb_scale (GdkPixbuf *pb, double scale)
+{
+ int w, h;
+
+ if (scale == 1.0)
+ return (GdkPixbuf *)g_object_ref ((GObject *)pb);
+
+ w = gdk_pixbuf_get_width (pb) * scale;
+ h = gdk_pixbuf_get_height (pb) * scale;
+
+ return gdk_pixbuf_scale_simple (pb, w, h,
+ GDK_INTERP_BILINEAR);
+}
+
+static void
+refind_first_and_last (void)
+{
+ int i, j;
+
+ for (i = 0; i < INV_COLS; i++) {
+ gboolean all_null = TRUE;
+ for (j = 0; j < INV_ROWS; j++) {
+ if (invs[i][j].live) {
+ all_null = FALSE;
+ break;
+ }
+ }
+ if ( ! all_null) {
+ inv_first_col = i;
+ break;
+ }
+ }
+
+ for (i = INV_COLS-1; i >= 0; i--) {
+ gboolean all_null = TRUE;
+ for (j = 0; j < INV_ROWS; j++) {
+ if (invs[i][j].live) {
+ all_null = FALSE;
+ break;
+ }
+ }
+ if ( ! all_null) {
+ inv_last_col = i;
+ break;
+ }
+ }
+}
+
+static void
+whack_gegl (int i, int j)
+{
+ if ( ! invs[i][j].live)
+ return;
+
+ invs[i][j].live = FALSE;
+ inv_num --;
+
+ if (inv_num > 0) {
+ refind_first_and_last ();
+ } else {
+ inv_x = 70;
+ inv_y = 70;
+ inv_first_col = 0;
+ inv_last_col = INV_COLS-1;
+ inv_reverse = FALSE;
+
+ g_slist_foreach (inv_shots, (GFunc)g_free, NULL);
+ g_slist_free (inv_shots);
+ inv_shots = NULL;
+
+ for (i = 0; i < INV_COLS; i++) {
+ for (j = 0; j < INV_ROWS; j++) {
+ invs[i][j].live = TRUE;
+ invs[i][j].x = 70 + i * 100;
+ invs[i][j].y = 70 + j * 80;
+ }
+ }
+ inv_num = INV_ROWS * INV_COLS;
+
+ inv_level ++;
+
+ inv_show_status ();
+ }
+
+ inv_queue_draw (geginv);
+}
+
+static gboolean
+geginv_timeout (gpointer data)
+{
+ int i, j;
+ int limitx1;
+ int limitx2;
+ int speed;
+ int shots;
+ int max_shots;
+
+ if (inv_paused)
+ return TRUE;
+
+ if (geginv != data ||
+ inv_num <= 0 ||
+ inv_y > 700)
+ return FALSE;
+
+ limitx1 = 70 - (inv_first_col * 100);
+ limitx2 = 800 - 70 - (inv_last_col * 100);
+
+ if (inv_game_over) {
+ inv_y += 30;
+ } else {
+ if (inv_num < (INV_COLS*INV_ROWS)/3)
+ speed = 45+2*inv_level;
+ else if (inv_num < (2*INV_COLS*INV_ROWS)/3)
+ speed = 30+2*inv_level;
+ else
+ speed = 15+2*inv_level;
+
+ if (inv_reverse) {
+ inv_x -= speed;
+ if (inv_x < limitx1) {
+ inv_reverse = FALSE;
+ inv_x = (limitx1 + (limitx1 - inv_x));
+ inv_y += 30+inv_level;
+ }
+ } else {
+ inv_x += speed;
+ if (inv_x > limitx2) {
+ inv_reverse = TRUE;
+ inv_x = (limitx2 - (inv_x - limitx2));
+ inv_y += 30+inv_level;
+ }
+ }
+ }
+
+ for (i = 0; i < INV_COLS; i++) {
+ for (j = 0; j < INV_ROWS; j++) {
+ if (invs[i][j].live) {
+ invs[i][j].x = inv_x + i * 100;
+ invs[i][j].y = inv_y + j * 80;
+
+ if ( ! inv_game_over &&
+ invs[i][j].y >= 570) {
+ inv_do_game_over ();
+ } else if ( ! inv_game_over &&
+ invs[i][j].y >= 530 &&
+ invs[i][j].x + 40 > inv_our_x - 25 &&
+ invs[i][j].x - 40 < inv_our_x + 25) {
+ whack_gegl (i,j);
+ inv_lives --;
+ inv_draw_explosion (inv_our_x, 550);
+ if (inv_lives <= 0) {
+ inv_do_game_over ();
+ } else {
+ g_slist_foreach (inv_shots, (GFunc)g_free, NULL);
+ g_slist_free (inv_shots);
+ inv_shots = NULL;
+ inv_our_x = 400;
+ inv_do_pause = TRUE;
+ inv_show_status ();
+ }
+ }
+ }
+ }
+ }
+
+ shots = 0;
+ max_shots = (g_random_int () >> 3) % (2+inv_level);
+ while ( ! inv_game_over && shots < MIN (max_shots, inv_num)) {
+ int i = (g_random_int () >> 3) % INV_COLS;
+ for (j = INV_ROWS-1; j >= 0; j--) {
+ if (invs[i][j].live) {
+ InvShot *shot = g_new0 (InvShot, 1);
+
+ shot->good = FALSE;
+ shot->x = invs[i][j].x + (g_random_int () % 6) - 3;
+ shot->y = invs[i][j].y + inv_goat_height/2 + (g_random_int () % 3);
+
+ inv_shots = g_slist_prepend (inv_shots, shot);
+ shots++;
+ break;
+ }
+ }
+ }
+
+ inv_goat_state = (inv_goat_state+1) % 2;
+
+ inv_queue_draw (geginv);
+
+ g_timeout_add (((inv_num/4)+1) * 100, geginv_timeout, geginv);
+
+ return FALSE;
+}
+
+static gboolean
+find_gegls (int x, int y)
+{
+ int i, j;
+
+ /* FIXME: this is stupid, we can do better */
+ for (i = 0; i < INV_COLS; i++) {
+ for (j = 0; j < INV_ROWS; j++) {
+ int ix = invs[i][j].x;
+ int iy = invs[i][j].y;
+
+ if ( ! invs[i][j].live)
+ continue;
+
+ if (y >= iy - 30 &&
+ y <= iy + 30 &&
+ x >= ix - 40 &&
+ x <= ix + 40) {
+ whack_gegl (i, j);
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+
+static gboolean
+geginv_move_timeout (gpointer data)
+{
+ GSList *li;
+ static int shot_inhibit = 0;
+
+ if (inv_paused)
+ return TRUE;
+
+ if (geginv != data ||
+ inv_num <= 0 ||
+ inv_y > 700)
+ return FALSE;
+
+ inv_phsh_state = (inv_phsh_state+1)%10;
+
+ /* we will be drawing something */
+ if (inv_shots != NULL)
+ inv_queue_draw (geginv);
+
+ li = inv_shots;
+ while (li != NULL) {
+ InvShot *shot = li->data;
+
+ if (shot->good) {
+ shot->y -= 30;
+ if (find_gegls (shot->x, shot->y) ||
+ shot->y <= 0) {
+ GSList *list = li;
+ /* we were restarted */
+ if (inv_shots == NULL)
+ return TRUE;
+ li = li->next;
+ g_free (shot);
+ inv_shots = g_slist_delete_link (inv_shots, list);
+ continue;
+ }
+ } else /* bad */ {
+ shot->y += 30;
+ if ( ! inv_game_over &&
+ shot->y >= 535 &&
+ shot->y <= 565 &&
+ shot->x >= inv_our_x - 25 &&
+ shot->x <= inv_our_x + 25) {
+ inv_lives --;
+ inv_draw_explosion (inv_our_x, 550);
+ if (inv_lives <= 0) {
+ inv_do_game_over ();
+ } else {
+ g_slist_foreach (inv_shots, (GFunc)g_free, NULL);
+ g_slist_free (inv_shots);
+ inv_shots = NULL;
+ inv_our_x = 400;
+ inv_do_pause = TRUE;
+ inv_show_status ();
+ return TRUE;
+ }
+ }
+
+ if (shot->y >= 600) {
+ GSList *list = li;
+ li = li->next;
+ g_free (shot);
+ inv_shots = g_slist_delete_link (inv_shots, list);
+ continue;
+ }
+ }
+
+ li = li->next;
+ }
+
+ if ( ! inv_game_over) {
+ if (inv_left_pressed && inv_our_x > 100) {
+ inv_our_x -= 20;
+ inv_queue_draw (geginv);
+ } else if (inv_right_pressed && inv_our_x < 700) {
+ inv_our_x += 20;
+ inv_queue_draw (geginv);
+ }
+ }
+
+ if (shot_inhibit > 0)
+ shot_inhibit--;
+
+ if ( ! inv_game_over && inv_fire_pressed && shot_inhibit == 0) {
+ InvShot *shot = g_new0 (InvShot, 1);
+
+ shot->good = TRUE;
+ shot->x = inv_our_x;
+ shot->y = 540;
+
+ inv_shots = g_slist_prepend (inv_shots, shot);
+
+ shot_inhibit = 5;
+
+ inv_queue_draw (geginv);
+ }
+
+ if (inv_left_released)
+ inv_left_pressed = FALSE;
+ if (inv_right_released)
+ inv_right_pressed = FALSE;
+ if (inv_fire_released)
+ inv_fire_pressed = FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+inv_key_press (GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+ switch (event->keyval) {
+ case GDK_KEY_Left:
+ case GDK_KEY_KP_Left:
+ case GDK_KEY_Pointer_Left:
+ inv_left_pressed = TRUE;
+ inv_left_released = FALSE;
+ return TRUE;
+ case GDK_KEY_Right:
+ case GDK_KEY_KP_Right:
+ case GDK_KEY_Pointer_Right:
+ inv_right_pressed = TRUE;
+ inv_right_released = FALSE;
+ return TRUE;
+ case GDK_KEY_space:
+ case GDK_KEY_KP_Space:
+ inv_fire_pressed = TRUE;
+ inv_fire_released = FALSE;
+ return TRUE;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+static gboolean
+inv_key_release (GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+ switch (event->keyval) {
+ case GDK_KEY_Left:
+ case GDK_KEY_KP_Left:
+ case GDK_KEY_Pointer_Left:
+ inv_left_released = TRUE;
+ return TRUE;
+ case GDK_KEY_Right:
+ case GDK_KEY_KP_Right:
+ case GDK_KEY_Pointer_Right:
+ inv_right_released = TRUE;
+ return TRUE;
+ case GDK_KEY_space:
+ case GDK_KEY_KP_Space:
+ inv_fire_released = TRUE;
+ return TRUE;
+ case GDK_KEY_q:
+ case GDK_KEY_Q:
+ gtk_widget_destroy (widget);
+ return TRUE;
+ case GDK_KEY_p:
+ case GDK_KEY_P:
+ inv_paused = ! inv_paused;
+ inv_show_status ();
+ return TRUE;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+static gboolean
+ensure_creatures (void)
+{
+ GdkPixbuf *pb, *pb1;
+
+ if (inv_goat1 != NULL)
+ return TRUE;
+
+ pb = gdk_pixbuf_new_from_resource ("/org/gimp/lebl-dialog/wanda.png",
+ NULL);
+ if (pb == NULL)
+ return FALSE;
+
+ pb1 = get_phsh_frame (pb, 1);
+ inv_phsh1 = pb_scale (pb1, inv_factor);
+ g_object_unref (G_OBJECT (pb1));
+ phsh_unsea (inv_phsh1);
+
+ pb1 = get_phsh_frame (pb, 2);
+ inv_phsh2 = pb_scale (pb1, inv_factor);
+ g_object_unref (G_OBJECT (pb1));
+ phsh_unsea (inv_phsh2);
+
+ g_object_unref (G_OBJECT (pb));
+
+ pb = gdk_pixbuf_new_from_resource ("/org/gimp/lebl-dialog/gegl-1.png",
+ NULL);
+ if (pb == NULL) {
+ g_object_unref (G_OBJECT (inv_phsh1));
+ g_object_unref (G_OBJECT (inv_phsh2));
+ return FALSE;
+ }
+
+ inv_goat1 = pb_scale (pb, inv_factor * 0.66);
+ g_object_unref (pb);
+
+ pb = gdk_pixbuf_new_from_resource ("/org/gimp/lebl-dialog/gegl-2.png",
+ NULL);
+ if (pb == NULL) {
+ g_object_unref (G_OBJECT (inv_goat1));
+ g_object_unref (G_OBJECT (inv_phsh1));
+ g_object_unref (G_OBJECT (inv_phsh2));
+ return FALSE;
+ }
+
+ inv_goat2 = pb_scale (pb, inv_factor * 0.66);
+ g_object_unref (pb);
+
+ inv_goat_width = gdk_pixbuf_get_width (inv_goat1);
+ inv_goat_height = gdk_pixbuf_get_height (inv_goat1);
+ inv_phsh_width = gdk_pixbuf_get_width (inv_phsh1);
+ inv_phsh_height = gdk_pixbuf_get_height (inv_phsh1);
+
+ return TRUE;
+}
+
+static void
+geginv_destroyed (GtkWidget *w, gpointer data)
+{
+ geginv = NULL;
+}
+
+static gboolean
+inv_expose (GtkWidget *widget, GdkEventExpose *event)
+{
+ cairo_t *cr;
+ GdkPixbuf *goat;
+ GSList *li;
+ int i, j;
+
+ if (geginv == NULL) {
+ inv_draw_idle = 0;
+ return TRUE;
+ }
+
+ if ( ! gtk_widget_is_drawable (geginv_canvas))
+ return TRUE;
+
+ cr = gdk_cairo_create (gtk_widget_get_window (geginv_canvas));
+
+ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+ cairo_paint (cr);
+
+ if (inv_goat_state == 0)
+ goat = inv_goat1;
+ else
+ goat = inv_goat2;
+
+ for (i = 0; i < INV_COLS; i++) {
+ for (j = 0; j < INV_ROWS; j++) {
+ int x, y;
+ if ( ! invs[i][j].live)
+ continue;
+
+ x = invs[i][j].x*inv_factor - inv_goat_width/2,
+ y = invs[i][j].y*inv_factor - inv_goat_height/2,
+
+ gdk_cairo_set_source_pixbuf (cr, goat, x, y);
+ cairo_rectangle (cr,
+ x, y,
+ inv_goat_width,
+ inv_goat_height);
+ cairo_fill (cr);
+ }
+ }
+
+ for (li = inv_shots; li != NULL; li = li->next) {
+ InvShot *shot = li->data;
+
+ cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
+ cairo_rectangle (cr,
+ (shot->x-1)*inv_factor,
+ (shot->y-4)*inv_factor,
+ 3, 8);
+ cairo_fill (cr);
+ }
+
+ if ( ! inv_game_over) {
+ GdkPixbuf *phsh;
+
+ if (inv_phsh_state < 5) {
+ phsh = inv_phsh1;
+ } else {
+ phsh = inv_phsh2;
+ }
+
+ gdk_cairo_set_source_pixbuf (cr, phsh,
+ inv_our_x*inv_factor - inv_phsh_width/2,
+ 550*inv_factor - inv_phsh_height/2);
+ cairo_rectangle (cr,
+ inv_our_x*inv_factor - inv_phsh_width/2,
+ 550*inv_factor - inv_phsh_height/2,
+ inv_phsh_width,
+ inv_phsh_height);
+ cairo_fill (cr);
+ }
+
+ cairo_destroy (cr);
+
+ gdk_flush ();
+
+ if (inv_do_pause) {
+ g_usleep (G_USEC_PER_SEC);
+ inv_do_pause = FALSE;
+ }
+
+ inv_draw_idle = 0;
+ return TRUE;
+}
+
+gboolean gimp_lebl_dialog (void);
+
+gboolean
+gimp_lebl_dialog (void)
+{
+ GtkWidget *vbox;
+ int i, j;
+
+ if (geginv != NULL) {
+ gtk_window_present (GTK_WINDOW (geginv));
+ return FALSE;
+ }
+
+ inv_width = 800;
+ inv_height = 600;
+
+ if (inv_width > gdk_screen_get_width (gdk_screen_get_default ()) * 0.9) {
+ inv_width = gdk_screen_get_width (gdk_screen_get_default ()) * 0.9;
+ inv_height = inv_width * (600.0/800.0);
+ }
+
+ if (inv_height > gdk_screen_get_height (gdk_screen_get_default ()) * 0.9) {
+ inv_height = gdk_screen_get_height (gdk_screen_get_default ()) * 0.9;
+ inv_width = inv_height * (800.0/600.0);
+ }
+
+ inv_factor = (double)inv_width / 800.0;
+
+ if ( ! ensure_creatures ())
+ return FALSE;
+
+ geginv = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_position (GTK_WINDOW (geginv), GTK_WIN_POS_CENTER);
+ gtk_window_set_title (GTK_WINDOW (geginv), _("Killer GEGLs from Outer Space"));
+ g_object_set (G_OBJECT (geginv), "resizable", FALSE, NULL);
+ g_signal_connect (G_OBJECT (geginv), "destroy",
+ G_CALLBACK (geginv_destroyed),
+ NULL);
+
+ geginv_canvas = gtk_drawing_area_new ();
+ gtk_widget_set_size_request (geginv_canvas, inv_width, inv_height);
+
+ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_container_add (GTK_CONTAINER (geginv), vbox);
+ gtk_box_pack_start (GTK_BOX (vbox), geginv_canvas, TRUE, TRUE, 0);
+
+ geginv_label = gtk_label_new ("");
+ gtk_box_pack_start (GTK_BOX (vbox), geginv_label, FALSE, FALSE, 0);
+
+ inv_our_x = 400;
+ inv_x = 70;
+ inv_y = 70;
+ inv_first_col = 0;
+ inv_level = 0;
+ inv_lives = 3;
+ inv_last_col = INV_COLS-1;
+ inv_reverse = FALSE;
+ inv_game_over = FALSE;
+ inv_left_pressed = FALSE;
+ inv_right_pressed = FALSE;
+ inv_fire_pressed = FALSE;
+ inv_left_released = FALSE;
+ inv_right_released = FALSE;
+ inv_fire_released = FALSE;
+ inv_paused = FALSE;
+
+ gtk_widget_add_events (geginv, GDK_KEY_RELEASE_MASK);
+
+ g_signal_connect (G_OBJECT (geginv), "key_press_event",
+ G_CALLBACK (inv_key_press), NULL);
+ g_signal_connect (G_OBJECT (geginv), "key_release_event",
+ G_CALLBACK (inv_key_release), NULL);
+ g_signal_connect (G_OBJECT (geginv_canvas), "expose_event",
+ G_CALLBACK (inv_expose), NULL);
+
+ g_slist_foreach (inv_shots, (GFunc)g_free, NULL);
+ g_slist_free (inv_shots);
+ inv_shots = NULL;
+
+ for (i = 0; i < INV_COLS; i++) {
+ for (j = 0; j < INV_ROWS; j++) {
+ invs[i][j].live = TRUE;
+ invs[i][j].x = 70 + i * 100;
+ invs[i][j].y = 70 + j * 80;
+ }
+ }
+ inv_num = INV_ROWS * INV_COLS;
+
+ g_timeout_add (((inv_num/4)+1) * 100, geginv_timeout, geginv);
+ g_timeout_add (90, geginv_move_timeout, geginv);
+
+ inv_show_status ();
+
+ gtk_widget_show_all (geginv);
+ return FALSE;
+}