[gnome-nibbles] Rearrange and refactor code



commit fb38a653cf855a51534228f3b2d484c667a606a5
Author: Iulian Radu <iulian radu67 gmail com>
Date:   Mon Aug 3 19:44:47 2015 +0300

    Rearrange and refactor code

 src/gnome-nibbles.vala |  121 ++++++++++++++------
 src/nibbles-game.vala  |  296 +++++++++++++++++++++++++----------------------
 src/nibbles-view.vala  |   21 ++--
 src/worm.vala          |    4 +-
 4 files changed, 254 insertions(+), 188 deletions(-)
---
diff --git a/src/gnome-nibbles.vala b/src/gnome-nibbles.vala
index fd79eda..c56419c 100644
--- a/src/gnome-nibbles.vala
+++ b/src/gnome-nibbles.vala
@@ -45,7 +45,7 @@ public class Nibbles : Gtk.Application
     private NibblesView? view;
     private NibblesGame? game = null;
 
-    private const int COUNTDOWN_TIME = 3;
+    private const int COUNTDOWN_TIME = 0;
 
     private const ActionEntry action_entries[] =
     {
@@ -102,7 +102,7 @@ public class Nibbles : Gtk.Application
 
         settings = new Settings ("org.gnome.nibbles");
         worm_settings = new Gee.ArrayList<Settings> ();
-        for (int i = 0; i < NibblesGame.NUMWORMS; i++)
+        for (int i = 0; i < NibblesGame.NUMHUMANS; i++)
         {
             var name = "org.gnome.nibbles.worm%d".printf(i);
             worm_settings.add (new Settings (name));
@@ -125,7 +125,7 @@ public class Nibbles : Gtk.Application
         statusbar_stack = (Gtk.Stack) builder.get_object ("statusbar_stack");
         countdown = (Gtk.Label) builder.get_object ("countdown");
         number_of_players_buttons = new Gee.LinkedList<Gtk.ToggleButton> ();
-        for (int i = 0; i < 2; i++)
+        for (int i = 0; i < NibblesGame.NUMHUMANS; i++)
         {
             var button = (Gtk.ToggleButton) builder.get_object ("players%d".printf (i + 1));
             button.toggled.connect (change_number_of_players_cb);
@@ -137,13 +137,14 @@ public class Nibbles : Gtk.Application
 
         add_window (window);
 
-        /* Load game */
+        /* Create game */
         game = new NibblesGame (settings);
         game.log_score.connect (log_score_cb);
         game.restart_game.connect (restart_game_cb);
+        game.level_completed.connect (level_completed_cb);
 
         view = new NibblesView (game);
-        view.show ();
+        view.configure_event.connect (configure_event_cb);
 
         frame = new Games.GridFrame (NibblesGame.WIDTH, NibblesGame.HEIGHT);
         game_box.pack_start (frame);
@@ -162,6 +163,7 @@ public class Nibbles : Gtk.Application
             show_first_run_screen ();
         else
             show_new_game_screen_cb ();
+            // start_game_cb ();
 
         window.show_all ();
 
@@ -170,18 +172,19 @@ public class Nibbles : Gtk.Application
 
     protected override void activate ()
     {
-        stderr.printf("[Debug] Activate\n");
         base.activate ();
+
+        window.present ();
     }
 
     protected override void shutdown ()
     {
+        base.shutdown ();
+
         settings.set_int ("window-width", window_width);
         settings.set_int ("window-height", window_height);
         settings.set_boolean ("window-is-maximized", is_maximized);
         game.save_properties (settings);
-
-        base.shutdown ();
     }
 
     /*\
@@ -243,26 +246,24 @@ public class Nibbles : Gtk.Application
     {
         settings.set_boolean ("first-run", false);
 
-        /* TODO Fix problem and remove this call
-         * For some reason tile_size gets set to 0 after calling
-         * frame.add (view). start_level stays the same
-         */
-        game.load_properties (settings);
         game.current_level = game.start_level;
-        game.loop_started.connect (scoreboard.update);
+        game.create_worms ();
+        game.load_worm_properties (worm_settings);
+
         view.new_level (game.current_level);
-        view.configure_event.connect (configure_event_cb);
+        view.connect_worm_signals ();
 
-        game.load_worm_properties (worm_settings);
         foreach (var worm in game.worms)
         {
             var color = game.worm_props.get (worm).color;
             scoreboard.register (worm, NibblesView.colorval_name (color), scoreboard_life);
+            worm.notify["lives"].connect (scoreboard.update);
+            worm.notify["score"].connect (scoreboard.update);
 
             var actors = view.worm_actors.get (worm);
-            if (actors.get_stage () == null) {
+            if (actors.get_stage () == null)
                 view.stage.add_child (actors);
-            }
+
             actors.show ();
         }
         game.add_worms ();
@@ -281,6 +282,7 @@ public class Nibbles : Gtk.Application
             if (seconds == 0)
             {
                 statusbar_stack.set_visible_child_name ("scoreboard");
+                countdown.set_label (COUNTDOWN_TIME.to_string ());
                 game.start ();
                 return Source.REMOVE;
             }
@@ -324,7 +326,7 @@ public class Nibbles : Gtk.Application
             if (button.get_active ())
             {
                 var label = button.get_label ();
-                game.numworms = int.parse (label);
+                game.numhumans = int.parse (label);
             }
         }
 
@@ -434,22 +436,16 @@ public class Nibbles : Gtk.Application
 
         try
         {
-            scores_context.add_score (score, get_scores_category (game.speed, game.fakes));
+            if (scores_context.add_score (score, get_scores_category (game.speed, game.fakes)))
+                scores_context.run_dialog ();
+            else
+                game_over_cb ();
         }
         catch (GLib.Error e)
         {
             // Translators: This warning is displayed when adding a score fails
             // just before displaying the score dialog
-            warning ("Failed to add score: %s", e.message);
-        }
-
-        try
-        {
-            scores_context.run_dialog ();
-        }
-        catch (GLib.Error e)
-        {
-            warning ("Failed to run scores dialog: %s", e.message);
+            warning (_("Failed to add score: %s"), e.message);
         }
     }
 
@@ -462,10 +458,52 @@ public class Nibbles : Gtk.Application
         catch (GLib.Error e)
         {
             // Translators: This error is displayed when the scores dialog fails to load
-            error ("Failed to run scores dialog: %s", e.message);
+            error (_("Failed to run scores dialog: %s"), e.message);
         }
     }
 
+    public void level_completed_cb ()
+    {
+        // TODO: Fix extremely big title bar
+        var dialog = new Gtk.MessageDialog (window,
+                                            Gtk.DialogFlags.MODAL,
+                                            Gtk.MessageType.INFO,
+                                            Gtk.ButtonsType.NONE,
+                                            _("Level %d Completed!").printf (game.current_level));
+
+        dialog.add_button (_("Next level"), Gtk.ResponseType.OK);
+        dialog.response.connect ((response_id) => {
+            if (response_id == Gtk.ResponseType.OK)
+                restart_game_cb ();
+
+            dialog.destroy ();
+        });
+
+        dialog.show ();
+    }
+
+    public void game_over_cb ()
+    {
+        var dialog = new Gtk.MessageDialog (window,
+                                            Gtk.DialogFlags.MODAL,
+                                            Gtk.MessageType.INFO,
+                                            Gtk.ButtonsType.NONE,
+                                            _("Game Over!").printf (game.current_level));
+
+        dialog.add_button (_("_Quit"), Gtk.ResponseType.CLOSE);
+        dialog.add_button (_("_Play Again"), Gtk.ResponseType.OK);
+        dialog.response.connect ((response_id) => {
+            if (response_id == Gtk.ResponseType.OK)
+                show_new_game_screen_cb ();
+            if (response_id == Gtk.ResponseType.CLOSE)
+                quit ();
+
+            dialog.destroy ();
+        });
+
+        dialog.show ();
+    }
+
     public static int main (string[] args)
     {
         var context = new OptionContext ("");
@@ -485,6 +523,8 @@ public class Nibbles : Gtk.Application
 
         Environment.set_application_name (_("Nibbles"));
 
+        Gtk.Window.set_default_icon_name ("gnome-nibbles");
+
         try
         {
             GtkClutter.init_with_args (ref args, "", new OptionEntry[0], null);
@@ -572,21 +612,26 @@ public class PlayerScoreBox : Gtk.Box
 
     public void update_score (int score)
     {
-        if (score_label.get_label () == score.to_string ())
-            return;
-
         score_label.set_label (score.to_string ());
     }
 
     public void update_lives (int lives_left)
     {
-        if (life_images.size == lives_left)
-            return;
-
-        for (int i = 0; i < life_images.size - lives_left; i++)
+        /* Remove lost lives - if any */
+        for (int i = life_images.size; i > lives_left; i--)
         {
             var life = life_images.poll ();
             life.hide ();
         }
+
+        /* Add new lives - if any */
+        for (int i = life_images.size; i < lives_left; i++)
+        {
+            var life = new Gtk.Image.from_pixbuf (life_images.first ().get_pixbuf ());
+            life.show ();
+
+            life_images.add (life);
+            lives_grid.attach (life, i % 6, i/6);
+        }
     }
 }
diff --git a/src/nibbles-game.vala b/src/nibbles-game.vala
index 8552ba4..8adbf98 100644
--- a/src/nibbles-game.vala
+++ b/src/nibbles-game.vala
@@ -42,7 +42,7 @@ public class NibblesGame : Object
     public const int GAMEDELAY = 35;
     public const int BONUSDELAY = 100;
 
-    public const int NUMHUMANS = 1;
+    public const int NUMHUMANS = 2;
     public const int NUMAI = 0;
     public const int NUMWORMS = NUMHUMANS + NUMAI;
 
@@ -72,10 +72,10 @@ public class NibblesGame : Object
 
     public signal void worm_moved (Worm worm);
     public signal void bonus_applied (Worm worm);
-    public signal void loop_started ();
     public signal void log_score (int score);
     public signal void animate_end_game ();
     public signal void restart_game ();
+    public signal void level_completed ();
 
     public Gee.HashMap<Worm, WormProperties?> worm_props;
 
@@ -84,17 +84,16 @@ public class NibblesGame : Object
         boni = new Boni (numworms);
         walls = new int[WIDTH, HEIGHT];
         worms = new Gee.LinkedList<Worm> ();
-        for (int i = 0; i < numworms; i++)
-        {
-            var worm = new Worm (i);
-            worms.add (worm);
-        }
         worm_props = new Gee.HashMap<Worm, WormProperties?> ();
 
         Random.set_seed ((uint32) time_t ());
         load_properties (settings);
     }
 
+    /*\
+    * * Game controls
+    \*/
+
     public void start ()
     {
         stderr.printf("[Debug] Game started\n");
@@ -122,15 +121,154 @@ public class NibblesGame : Object
         }
     }
 
+    private void end ()
+    {
+        stop ();
+        animate_end_game ();
+    }
+
+    public bool main_loop_cb ()
+    {
+        var status = get_game_status ();
+
+        if (status == GameStatus.GAMEOVER)
+        {
+            end ();
+
+            log_score (worms.first ().score);
+
+            return Source.REMOVE;
+        }
+        else if (status == GameStatus.VICTORY)
+        {
+            end ();
+            var winner = get_winner ();
+
+            if (winner == null)
+                return Source.REMOVE;
+
+            log_score (winner.score);
+
+            return Source.REMOVE;
+        }
+        else if (status == GameStatus.NEWROUND)
+        {
+            stop ();
+
+            animate_end_game ();
+            level_completed ();
+
+            if (current_level < MAX_LEVEL)
+                current_level++;
+
+            return Source.REMOVE;
+        }
+        move_worms ();
+
+        return Source.CONTINUE;
+    }
+
+    /*\
+    * * Handling worms
+    \*/
+
+    public void create_worms ()
+    {
+        numworms = numai + numhumans;
+        stderr.printf("[Debug] Numw %d\n", numworms);
+        for (int i = 0; i < numworms; i++)
+        {
+            var worm = new Worm (i);
+            worm.bonus_found.connect (bonus_found_cb);
+            worms.add (worm);
+        }
+    }
+
     public void add_worms ()
     {
         foreach (var worm in worms)
-        {
             worm.spawn (walls);
-            worm.bonus_found.connect (bonus_found_cb);
+    }
+
+    public void move_worms ()
+    {
+        if (boni.missed > Boni.MAX_MISSED)
+        {
+            foreach (var worm in worms)
+            {
+                if (worm.score > 0)
+                    worm.score--;
+            }
+        }
+
+        // FIXME 1/3: Use an iterator instead of a second list and remove
+        // from the boni.bonuses list inside boni.remove_bonus ()
+        var found = new Gee.LinkedList<Bonus> ();
+        foreach (var bonus in boni.bonuses)
+        {
+            if (bonus.countdown-- == 0)
+            {
+                if (bonus.type == BonusType.REGULAR && !bonus.fake)
+                {
+                    found.add (bonus);
+                    boni.remove_bonus (walls, bonus);
+                    boni.missed++;
+
+                    add_bonus (true);
+                }
+                else
+                {
+                    found.add (bonus);
+                    boni.remove_bonus (walls, bonus);
+                }
+            }
+        }
+        boni.bonuses.remove_all (found);
+        // END FIXME
+
+        var dead_worms = new Gee.LinkedList<Worm> ();
+        foreach (var worm in worms)
+        {
+            if (worm.is_stopped)
+                continue;
+
+            foreach (var other_worm in worms)
+            {
+                if (worm.will_collide_with_head (other_worm)
+                    && worm != other_worm
+                    && !other_worm.is_stopped)
+                    {
+                        if (!dead_worms.contains (worm))
+                            dead_worms.add (worm);
+                        if (!dead_worms.contains (worm))
+                            dead_worms.add (other_worm);
+                        continue;
+                    }
+            }
+
+            if (!worm.can_move_to (walls, numworms))
+            {
+                dead_worms.add (worm);
+                continue;
+            }
+
+            worm.move (walls);
+        }
+
+        foreach (var worm in dead_worms)
+        {
+            if (numworms > 1)
+                worm.score = worm.score * 7 / 10;
+
+            if (worm.lives > 0)
+                worm.reset (walls);
         }
     }
 
+    /*\
+    * * Handling bonuses
+    \*/
+
     public void add_bonus (bool regular)
     {
         bool good = false;
@@ -227,88 +365,6 @@ public class NibblesGame : Object
         }
     }
 
-    public bool add_bonus_cb ()
-    {
-        add_bonus (false);
-
-        return Source.CONTINUE;
-    }
-
-    public void move_worms ()
-    {
-        if (boni.missed > Boni.MAX_MISSED)
-        {
-            foreach (var worm in worms)
-            {
-                if (worm.score > 0)
-                    worm.score--;
-            }
-        }
-
-        // FIXME 1/3: Use an iterator instead of a second list and remove
-        // from the boni.bonuses list inside boni.remove_bonus ()
-        var found = new Gee.LinkedList<Bonus> ();
-        foreach (var bonus in boni.bonuses)
-        {
-            if (bonus.countdown-- == 0)
-            {
-                if (bonus.type == BonusType.REGULAR && !bonus.fake)
-                {
-                    found.add (bonus);
-                    boni.remove_bonus (walls, bonus);
-                    boni.missed++;
-
-                    add_bonus (true);
-                }
-                else
-                {
-                    found.add (bonus);
-                    boni.remove_bonus (walls, bonus);
-                }
-            }
-        }
-        boni.bonuses.remove_all (found);
-        // END FIXME
-
-        var dead_worms = new Gee.LinkedList<Worm> ();
-        foreach (var worm in worms)
-        {
-            if (worm.is_stopped)
-                continue;
-
-            foreach (var other_worm in worms)
-            {
-                if (worm.will_collide_with_head (other_worm)
-                    && worm != other_worm
-                    && !other_worm.is_stopped)
-                    {
-                        if (!dead_worms.contains (worm))
-                            dead_worms.add (worm);
-                        if (!dead_worms.contains (worm))
-                            dead_worms.add (other_worm);
-                        continue;
-                    }
-            }
-
-            if (!worm.can_move_to (walls, numworms))
-            {
-                dead_worms.add (worm);
-                continue;
-            }
-
-            worm.move (walls);
-        }
-
-        foreach (var worm in dead_worms)
-        {
-            if (numworms > 1)
-                worm.score = worm.score * 7 / 10;
-
-            if (worm.lives > 0)
-                worm.reset (walls);
-        }
-    }
-
     public void apply_bonus (Bonus bonus, Worm worm)
     {
         if (bonus.fake)
@@ -345,6 +401,13 @@ public class NibblesGame : Object
         }
     }
 
+    public bool add_bonus_cb ()
+    {
+        add_bonus (false);
+
+        return Source.CONTINUE;
+    }
+
     public void bonus_found_cb (Worm worm)
     {
         var bonus = boni.get_bonus (walls, worm.head ().x, worm.head ().y);
@@ -371,49 +434,6 @@ public class NibblesGame : Object
         }
     }
 
-    public bool main_loop_cb ()
-    {
-        var status = get_game_status ();
-        loop_started ();
-
-        if (status == GameStatus.GAMEOVER)
-        {
-            end_game ();
-
-            log_score (worms.first ().score);
-
-            return Source.REMOVE;
-        }
-        else if (status == GameStatus.VICTORY)
-        {
-            end_game ();
-            var winner = get_winner ();
-
-            if (winner == null)
-                return Source.REMOVE;
-
-            log_score (winner.score);
-
-            return Source.REMOVE;
-        }
-        else if (status == GameStatus.NEWROUND)
-        {
-            stop ();
-
-            if (current_level < MAX_LEVEL)
-                current_level++;
-
-            animate_end_game ();
-
-            restart_game ();
-
-            return Source.REMOVE;
-        }
-        move_worms ();
-
-        return Source.CONTINUE;
-    }
-
     public GameStatus? get_game_status ()
     {
         var worms_left = 0;
@@ -453,11 +473,9 @@ public class NibblesGame : Object
         return null;
     }
 
-    private void end_game ()
-    {
-        stop ();
-        animate_end_game ();
-    }
+    /*\
+    * * Saving / Loading properties
+    \*/
 
     public void load_properties (Settings settings)
     {
diff --git a/src/nibbles-view.vala b/src/nibbles-view.vala
index 8d3a3ba..a451219 100644
--- a/src/nibbles-view.vala
+++ b/src/nibbles-view.vala
@@ -35,15 +35,6 @@ public class NibblesView : GtkClutter.Embed
             _game.bonus_applied.connect (bonus_applied_cb);
 
             _game.animate_end_game.connect (animate_end_game_cb);
-
-            foreach (var worm in _game.worms)
-            {
-                worm.added.connect (worm_added_cb);
-                worm.moved.connect (worm_moved_cb);
-                worm.rescaled.connect (worm_rescaled_cb);
-                worm.died.connect (worm_died_cb);
-                worm.tail_reduced.connect (worm_tail_reduced_cb);
-            }
         }
     }
 
@@ -359,6 +350,18 @@ public class NibblesView : GtkClutter.Embed
         level.restore_easing_state ();
     }
 
+    public void connect_worm_signals ()
+    {
+        foreach (var worm in game.worms)
+        {
+            worm.added.connect (worm_added_cb);
+            worm.moved.connect (worm_moved_cb);
+            worm.rescaled.connect (worm_rescaled_cb);
+            worm.died.connect (worm_died_cb);
+            worm.tail_reduced.connect (worm_tail_reduced_cb);
+        }
+    }
+
     public void board_rescale (int tile_size)
     {
         int board_width, board_height;
diff --git a/src/worm.vala b/src/worm.vala
index 2de6349..b5533f7 100644
--- a/src/worm.vala
+++ b/src/worm.vala
@@ -33,9 +33,9 @@ public class Worm : Object
     public bool keypress = false;
     public bool is_stopped = false;
 
-    public int lives;
+    public int lives { get; set; }
     public int change;
-    public int score;
+    public int score { get; set; }
 
     public int length
     {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]