[gnome-nibbles/wip/vala] Implement warp manager and warping



commit e437eaf884ede869893fb9bf1002f7d5cec20fac
Author: Iulian Radu <iulian radu67 gmail com>
Date:   Wed Aug 19 23:04:58 2015 +0300

    Implement warp manager and warping

 src/Makefile.am        |    1 +
 src/boni.vala          |    1 +
 src/gnome-nibbles.vala |    1 +
 src/nibbles-game.vala  |   30 ++++++-----
 src/nibbles-view.vala  |  134 ++++++++++++++++++++++++++++++++++++++++++++++-
 src/warp.vala          |  119 ++++++++++++++++++++++++++++++++++++++++++
 src/worm.vala          |   14 +++++-
 7 files changed, 282 insertions(+), 18 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 0392dc8..55b4d7e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -9,6 +9,7 @@ gnome_nibbles_SOURCES = \
        nibbles-game.vala \
        worm.vala \
        boni.vala \
+       warp.vala \
        $(BUILT_SOURCES)
 
 gnome_nibbles_CFLAGS = -w
diff --git a/src/boni.vala b/src/boni.vala
index e0332a3..9151891 100644
--- a/src/boni.vala
+++ b/src/boni.vala
@@ -22,6 +22,7 @@
 public class Boni : Object
 {
     public Gee.LinkedList<Bonus> bonuses;
+
     public int missed;
     public int numleft;
     public int numboni;
diff --git a/src/gnome-nibbles.vala b/src/gnome-nibbles.vala
index ef927ed..37c848f 100644
--- a/src/gnome-nibbles.vala
+++ b/src/gnome-nibbles.vala
@@ -267,6 +267,7 @@ public class Nibbles : Gtk.Application
 
             view.board_rescale (tile_size);
             view.boni_rescale (tile_size);
+            view.warps_rescale (tile_size);
             foreach (var worm in game.worms)
                 worm.rescaled (tile_size);
 
diff --git a/src/nibbles-game.vala b/src/nibbles-game.vala
index 8fbda88..1a9040d 100644
--- a/src/nibbles-game.vala
+++ b/src/nibbles-game.vala
@@ -21,19 +21,6 @@
 
 public class NibblesGame : Object
 {
-    private Boni _boni;
-    public Boni boni
-    {
-        get { return _boni; }
-        set
-        {
-            if (_boni != null)
-                SignalHandler.disconnect_matched (_boni, SignalMatchType.DATA, 0, 0, null, null, this);
-
-            _boni = value;
-        }
-    }
-
     public int tile_size;
     public int start_level;
 
@@ -53,6 +40,7 @@ public class NibblesGame : Object
 
     public const char EMPTYCHAR = 'a';
     public const char WORMCHAR = 'w';
+    public const char WARPCHAR = 'W';
 
     public const int MAX_LEVEL = 26;
 
@@ -61,11 +49,14 @@ public class NibblesGame : Object
 
     public Gee.LinkedList<Worm> worms;
 
+    public Boni boni;
+    public WarpManager warp_manager;
+
     public int numhumans;
     public int numai;
     public int numworms;
 
-    public int speed = 1;
+    public int speed = 4;
 
     public bool is_running = false;
     public bool is_paused { get; private set; }
@@ -87,6 +78,7 @@ public class NibblesGame : Object
     public NibblesGame (Settings settings)
     {
         boni = new Boni (numworms);
+        warp_manager = new WarpManager ();
         walls = new int[WIDTH, HEIGHT];
         worms = new Gee.LinkedList<Worm> ();
         worm_props = new Gee.HashMap<Worm, WormProperties?> ();
@@ -202,6 +194,7 @@ public class NibblesGame : Object
         {
             var worm = new Worm (i);
             worm.bonus_found.connect (bonus_found_cb);
+            worm.warp_found.connect (warp_found_cb);
             worm.is_human = (i < numhumans);
             worms.add (worm);
         }
@@ -477,6 +470,15 @@ public class NibblesGame : Object
         }
     }
 
+    public void warp_found_cb (Worm worm)
+    {
+        var warp = warp_manager.get_warp (worm.head.x, worm.head.y);
+        if (warp == null)
+            return;
+
+        worm.warp (walls, warp);
+    }
+
     public GameStatus? get_game_status ()
     {
         var worms_left = 0;
diff --git a/src/nibbles-view.vala b/src/nibbles-view.vala
index 3de0902..6e13f2b 100644
--- a/src/nibbles-view.vala
+++ b/src/nibbles-view.vala
@@ -34,6 +34,8 @@ public class NibblesView : GtkClutter.Embed
 
             _game.bonus_applied.connect (bonus_applied_cb);
 
+            _game.warp_manager.warp_added.connect (warp_added_cb);
+
             _game.animate_end_game.connect (animate_end_game_cb);
         }
     }
@@ -48,6 +50,7 @@ public class NibblesView : GtkClutter.Embed
 
     public Gee.HashMap<Worm, WormActor> worm_actors;
     public Gee.HashMap<Bonus, BonusTexture> bonus_actors;
+    public Gee.HashMap<Warp, WarpTexture> warp_actors;
 
     public const int NUM_COLORS = 6;
     public static string[] color_lookup =
@@ -75,6 +78,7 @@ public class NibblesView : GtkClutter.Embed
 
         worm_actors = new Gee.HashMap<Worm, WormActor> ();
         bonus_actors = new Gee.HashMap<Bonus, BonusTexture> ();
+        warp_actors = new Gee.HashMap<Warp, WarpTexture> ();
 
         load_pixmap ();
     }
@@ -110,6 +114,10 @@ public class NibblesView : GtkClutter.Embed
             actor.destroy ();
         bonus_actors.clear ();
 
+        foreach (var actor in warp_actors.values)
+            actor.destroy ();
+        warp_actors.clear ();
+
         game.boni.reset (game.numworms);
 
         for (int i = 0; i < NibblesGame.HEIGHT; i++)
@@ -169,6 +177,30 @@ public class NibblesView : GtkClutter.Embed
                             count++;
                         }
                         break;
+                    case 'Q':
+                    case 'R':
+                    case 'S':
+                    case 'T':
+                    case 'U':
+                    case 'V':
+                    case 'W':
+                    case 'X':
+                    case 'Y':
+                    case 'Z':
+                        game.warp_manager.add_warp (game.walls, j - 1, i - 1, -(game.walls[j, i]), 0);
+                        break;
+                    case 'r':
+                    case 's':
+                    case 't':
+                    case 'u':
+                    case 'v':
+                    case 'w':
+                    case 'x':
+                    case 'y':
+                    case 'z':
+                        game.warp_manager.add_warp (game.walls, -(game.walls[j, i] - 'a' + 'A'), 0, j, i);
+                        game.walls[j, i] = NibblesGame.EMPTYCHAR;
+                        break;
                     default:
                         break;
                 }
@@ -214,9 +246,6 @@ public class NibblesView : GtkClutter.Embed
             "questionmark.svg"
         };
 
-
-
-
         string[] small_files =
         {
             "wall-straight-up.svg",
@@ -476,6 +505,19 @@ public class NibblesView : GtkClutter.Embed
             actor.restore_easing_state ();
         }
 
+        foreach (var warp in game.warp_manager.warps)
+        {
+            var actor = warp_actors.get (warp);
+
+            actor.save_easing_state ();
+            actor.set_easing_mode (Clutter.AnimationMode.EASE_IN_QUAD);
+            actor.set_easing_duration (NibblesGame.GAMEDELAY * 15);
+            actor.set_scale (0.4f, 0.4f);
+            actor.set_pivot_point (0.5f, 0.5f);
+            actor.set_opacity (0);
+            actor.restore_easing_state ();
+        }
+
         level.save_easing_state ();
         level.set_easing_mode (Clutter.AnimationMode.EASE_IN_QUAD);
         level.set_easing_duration (NibblesGame.GAMEDELAY * 20);
@@ -485,6 +527,10 @@ public class NibblesView : GtkClutter.Embed
         level.restore_easing_state ();
     }
 
+    /*\
+    * * Worms drawing
+    \*/
+
     public void worm_added_cb (Worm worm)
     {
         var actor = new GtkClutter.Texture ();
@@ -632,6 +678,10 @@ public class NibblesView : GtkClutter.Embed
         }
     }
 
+    /*\
+    * * Bonuses drawing
+    \*/
+
     public void bonus_added_cb ()
     {
         /* Last bonus added to the list is the one that needs a texture */
@@ -652,6 +702,7 @@ public class NibblesView : GtkClutter.Embed
             error (_("Nibbles failed to set texture: %s"), e.message);
         }
 
+        actor.set_size (2 * game.tile_size, 2 * game.tile_size);
         actor.set_position (bonus.x * game.tile_size, bonus.y * game.tile_size);
 
         level.add_child (actor);
@@ -732,6 +783,64 @@ public class NibblesView : GtkClutter.Embed
         }
     }
 
+    /*\
+    * * Warps drawing
+    \*/
+    public void warp_added_cb (Warp warp)
+    {
+        var actor = new WarpTexture ();
+        try
+        {
+            actor.set_from_pixbuf (boni_pixmaps[BonusType.WARP]);
+        }
+        catch (Clutter.TextureError e)
+        {
+            /* Fatal console error when a texture could not be set. */
+            error (_("Nibbles failed to set texture: %s"), e.message);
+        }
+        catch (Error e)
+        {
+            /* Fatal console error when a texture could not be set. */
+            error (_("Nibbles failed to set texture: %s"), e.message);
+        }
+
+        actor.set_size (2 * game.tile_size, 2 * game.tile_size);
+        actor.set_position (warp.x * game.tile_size, warp.y * game.tile_size);
+
+        stage.add_child (actor);
+
+        warp_actors.set (warp, actor);
+    }
+
+    public void warps_rescale (int tile_size)
+    {
+        float x_pos, y_pos;
+
+        foreach (var warp in game.warp_manager.warps)
+        {
+            var actor = warp_actors.get (warp);
+            actor.get_position (out x_pos, out y_pos);
+            actor.set_position ((x_pos / game.tile_size) * tile_size,
+                                (y_pos / game.tile_size) * tile_size);
+
+            try
+            {
+                actor.set_from_pixbuf (boni_pixmaps[BonusType.WARP]);
+            }
+            catch (Clutter.TextureError e)
+            {
+                /* Fatal console error when a texture could not be set. */
+                error (_("Nibbles failed to set texture: %s"), e.message);
+            }
+            catch (Error e)
+            {
+                /* Fatal console error when a texture could not be set. */
+                error (_("Nibbles failed to set texture: %s"), e.message);
+            }
+        }
+    }
+
+
     private void play_sound (string name)
     {
         if (is_muted)
@@ -799,3 +908,22 @@ public class BonusTexture : GtkClutter.Texture
         restore_easing_state ();
     }
 }
+
+public class WarpTexture: GtkClutter.Texture
+{
+    public override void show ()
+    {
+        base.show ();
+
+        set_opacity (0);
+        set_scale (2.0, 2.0);
+
+        save_easing_state ();
+        set_easing_mode (Clutter.AnimationMode.EASE_OUT_CIRC);
+        set_easing_duration (NibblesGame.GAMEDELAY * 15);
+        set_scale (1.0, 1.0);
+        set_pivot_point (0.5f, 0.5f);
+        set_opacity (0xff);
+        restore_easing_state ();
+    }
+}
diff --git a/src/warp.vala b/src/warp.vala
new file mode 100644
index 0000000..a626c7b
--- /dev/null
+++ b/src/warp.vala
@@ -0,0 +1,119 @@
+/* -*- Mode: vala; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * Gnome Nibbles: Gnome Worm Game
+ * Copyright (C) 2015 Iulian-Gabriel Radu <iulian radu67 gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// This is a fairly literal translation of the LGPLv2+ original by
+// Sean MacIsaac, Ian Peters, Guillaume BĂ©land.
+
+public class Warp : Object
+{
+    public int x;
+    public int y;
+
+    public int wx;
+    public int wy;
+
+    public Warp (int x, int y, int wx, int wy)
+    {
+        this.x = x;
+        this.y = y;
+
+        this.wx = wx;
+        this.wy = wy;
+    }
+}
+
+public class WarpManager: Object
+{
+    private const int MAX_WARPS = 200;
+
+    public Gee.LinkedList<Warp> warps;
+
+    public signal void warp_added (Warp warp);
+
+    public WarpManager ()
+    {
+        warps = new Gee.LinkedList<Warp> ();
+    }
+
+    public void add_warp (int[,] walls, int x, int y, int wx, int wy)
+    {
+        bool add = true;
+
+        if (x < 0)
+        {
+            foreach (var warp in warps)
+            {
+                if (warp.wx == x)
+                {
+                    warp.wx = wx;
+                    warp.wy = wy;
+                    return;
+                }
+            }
+
+            if (warps.size == MAX_WARPS)
+                return;
+
+            warps.add (new Warp (x, y, wx, wy));
+        }
+        else
+        {
+            foreach (var warp in warps)
+            {
+                if (warp.x == wx)
+                {
+                    warp.x = x;
+                    warp.y = y;
+                    add = false;
+
+                    warp_added (warp);
+                }
+            }
+
+            if (add)
+            {
+                if (warps.size == MAX_WARPS)
+                    return;
+
+                var warp = new Warp (x, y, wx, wy);
+                warps.add (warp);
+
+                warp_added (warp);
+            }
+
+            walls[x, y] = NibblesGame.WARPCHAR;
+            walls[x + 1, y] = NibblesGame.WARPCHAR;
+            walls[x, y + 1] = NibblesGame.WARPCHAR;
+            walls[x + 1, y + 1] = NibblesGame.WARPCHAR;
+        }
+    }
+
+    public Warp? get_warp (int x, int y)
+    {
+        foreach (var warp in warps)
+        {
+            if ((x == warp.x && y == warp.y)
+             || (x == warp.x + 1 && y == warp.y)
+             || (x == warp.x && y == warp.y + 1)
+             || (x == warp.x + 1 && y == warp.y + 1))
+                return warp;
+        }
+
+        return null;
+    }
+}
diff --git a/src/worm.vala b/src/worm.vala
index ffe6d6a..879468a 100644
--- a/src/worm.vala
+++ b/src/worm.vala
@@ -50,7 +50,10 @@ public class Worm : Object
             Position head = list.first ();
             return head;
         }
-        set {}
+        private set
+        {
+            list.set (0, value);
+        }
     }
 
     public WormDirection direction;
@@ -69,6 +72,7 @@ public class Worm : Object
     public signal void reversed ();
 
     public signal void bonus_found ();
+    public signal void warp_found ();
 
     public Worm (int id)
     {
@@ -132,6 +136,9 @@ public class Worm : Object
         /* Add a new body piece */
         list.offer_head (position);
 
+        if (walls[head.x, head.y] == NibblesGame.WARPCHAR)
+            warp_found ();
+
         if (change > 0)
         {
             change--;
@@ -189,6 +196,11 @@ public class Worm : Object
             direction = (list[0].y > list[1].y) ? WormDirection.DOWN : WormDirection.UP;
     }
 
+    public void warp (Warp warp)
+    {
+        head = Position () { x = warp.wx, y = warp.wy };
+    }
+
     public bool can_move_to (int[,] walls, int numworms)
     {
         var position = position_move ();


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