[lightsoff/wip/gtkview] Added basic mouse-playable version



commit 9246b114e99d87a4235466b4677b66193466f32b
Author: Robert Roth <robert roth off gmail com>
Date:   Fri Jun 29 23:26:50 2018 +0300

    Added basic mouse-playable version

 data/lightsoff.ui         |   2 +-
 src/game-view-gtk.vala    | 143 ++++++++++++++++++++++++++++++++++++++++++++++
 src/lightsoff-window.vala |  22 +++++--
 src/meson.build           |   1 +
 4 files changed, 163 insertions(+), 5 deletions(-)
---
diff --git a/data/lightsoff.ui b/data/lightsoff.ui
index dab0e53..0185eea 100644
--- a/data/lightsoff.ui
+++ b/data/lightsoff.ui
@@ -2,7 +2,7 @@
 <interface>
   <requires lib="gtk+" version="3.12"/>
   <template class="LightsoffWindow" parent="GtkApplicationWindow">
-    <property name="resizable">False</property>
+    <property name="resizable">True</property>
     <child type="titlebar">
       <object class="GtkHeaderBar" id="headerbar">
         <property name="visible">True</property>
diff --git a/src/game-view-gtk.vala b/src/game-view-gtk.vala
new file mode 100644
index 0000000..b372320
--- /dev/null
+++ b/src/game-view-gtk.vala
@@ -0,0 +1,143 @@
+public class GtkGameView : Gtk.Grid, GameView {
+
+    private Gtk.ToggleButton[,] lights;
+    private new const int SIZE = 5;
+    private PuzzleGenerator puzzle_generator;
+    private int current_level;
+    private int moves;
+
+    public void swap_board (int direction)
+    {
+        current_level += direction;
+        load_level (current_level);
+    }
+    public void hide_cursor ()
+    {
+    }
+    public void activate_cursor ()
+    {
+    }
+    public void move_cursor (int x, int y)
+    {
+    }
+    public void reset_game ()
+    {
+
+
+    }
+
+    public GtkGameView (int level)
+    {
+        puzzle_generator = new PuzzleGenerator (SIZE);
+                /* Clear level */
+        current_level = level;
+        lights = new Gtk.ToggleButton [SIZE, SIZE];
+        for (var x = 0; x < SIZE; x++)
+            for (var y = 0; y < SIZE; y++)
+            {
+                lights[x, y] = new Gtk.ToggleButton ();
+                lights[x, y].show ();
+                lights[x, y].toggled.connect (light_toggled_cb);
+                attach (lights[x, y], x, y, 1, 1);
+            }
+
+        set_size_request (SIZE * 64, SIZE * 64);
+        row_homogeneous = true;
+        column_homogeneous = true;
+        load_level (current_level);
+    }
+
+    private void find_light (Gtk.ToggleButton light, out int x, out int y)
+    {
+        x = y = 0;
+        for (x = 0; x < SIZE; x++)
+            for (y = 0; y < SIZE; y++)
+                if (lights[x, y] == light)
+                    return;
+    }
+
+    private bool is_completed ()
+    {
+        var cleared = true;
+        for (var x = 0; x < SIZE; x++)
+            for (var y = 0; y < SIZE; y++)
+                if (lights[x, y].active)
+                    cleared = false;
+
+        return cleared;
+    }
+
+    public void light_toggled_cb (Gtk.ToggleButton source)
+    {
+        int xl, yl;
+        find_light (source, out xl, out yl);
+
+        toggle_light (xl, yl, true);
+        moves_changed (++moves);
+        if (is_completed ()) {
+            load_level (++current_level);
+        }
+    }
+    // Pseudorandomly generates and sets the state of each light based on
+    // a level number; hopefully this is stable between machines, but that
+    // depends on GLib's PRNG stability. Also, provides some semblance of
+    // symmetry for some levels.
+
+     // Toggle a light and those in each cardinal direction around it.
+    private void toggle_light (int x, int y, bool clicked = false)
+    {
+        for (var xi = 0; xi < SIZE; xi++)
+            for (var yi = 0; yi < SIZE; yi++)
+                lights[xi, yi].toggled.disconnect (light_toggled_cb);
+
+        if (x>= SIZE || y >= SIZE || x < 0 || y < 0 )
+            return;
+        if ((int) x + 1 < SIZE)
+            lights[(int) x + 1, (int) y].set_active (!lights[(int) x + 1, (int) y].get_active ());
+        if ((int) x - 1 >= 0)
+            lights[(int) x - 1, (int) y].set_active (!lights[(int) x - 1, (int) y].get_active ());
+        if ((int) y + 1 < SIZE)
+            lights[(int) x, (int) y + 1].set_active (!lights[(int) x, (int) y + 1].get_active ());
+        if ((int) y - 1 >= 0)
+            lights[(int) x, (int) y - 1].set_active (!lights[(int) x, (int) y - 1].get_active ());
+
+        if (!clicked)
+            lights[(int) x, (int) y].set_active (!lights[(int) x, (int) y ].get_active ());
+
+        for (var xi = 0; xi < SIZE; xi++)
+            for (var yi = 0; yi < SIZE; yi++)
+                lights[xi, yi].toggled.connect (light_toggled_cb);
+    }
+
+    public void load_level (int level)
+    {
+        moves = 0;
+        moves_changed (moves);
+        level_changed (level);
+        /* We *must* not have level < 1, as the following assumes a nonzero, nonnegative number */
+        if (level < 1)
+            level = 1;
+
+        for (var xi = 0; xi < SIZE; xi++)
+            for (var yi = 0; yi < SIZE; yi++)
+                lights[xi, yi].toggled.disconnect (light_toggled_cb);
+
+        /* Clear level */
+        for (var x = 0; x < SIZE; x++)
+            for (var y = 0; y < SIZE; y++)
+                lights[x, y].active = false;
+
+        /* Use the same pseudo-random levels */
+        Random.set_seed (level);
+
+        /* Levels require more and more clicks to make */
+        var solution_length = (int) Math.floor (2 * Math.log (level) + 1);
+
+        /* Do the moves the player needs to */
+        var sol = puzzle_generator.minimal_solution (solution_length);
+        for (var x = 0; x < SIZE; x++)
+            for (var y = 0; y < SIZE; y++)
+                if (sol[x, y])
+                    toggle_light (x, y);
+    }
+}
diff --git a/src/lightsoff-window.vala b/src/lightsoff-window.vala
index 3204364..a392435 100644
--- a/src/lightsoff-window.vala
+++ b/src/lightsoff-window.vala
@@ -28,12 +28,12 @@ public class LightsoffWindow : ApplicationWindow
         { "next-level",     next_level_cb }
     };
 
-    public Gtk.Widget build_game_container (int level, out GameView out_game_view)
+    public Gtk.Widget build_clutter_game_container (int level, out GameView out_game_view)
     {
         var clutter_embed = new GtkClutter.Embed ();
         clutter_embed.show ();
         var stage = (Clutter.Stage) clutter_embed.get_stage ();
-        stage.key_release_event.connect (key_release_event_cb);
+        stage.key_release_event.connect (key_release_clutter_event_cb);
         stage.background_color = Clutter.Color.from_string ("#000000");
 
         ClutterGameView clutter_game_view = new ClutterGameView (level);
@@ -47,6 +47,20 @@ public class LightsoffWindow : ApplicationWindow
         return clutter_embed;
     }
 
+    public Gtk.Widget build_gtk_game_container (int level, out GameView out_game_view)
+    {
+        var aspect_frame = new Gtk.AspectFrame (null, 0.5f, 0.5f, 1.0f, false);
+        aspect_frame.show ();
+
+        GtkGameView gtk_game_view = new GtkGameView (level);
+        gtk_game_view.show ();
+
+        aspect_frame.add (gtk_game_view);
+
+        out_game_view = gtk_game_view;
+        return aspect_frame;
+    }
+
     public LightsoffWindow ()
     {
         settings = new GLib.Settings ("org.gnome.lightsoff");
@@ -57,7 +71,7 @@ public class LightsoffWindow : ApplicationWindow
         int level = settings.get_int ("level");
         level_changed_cb (level);
 
-        this.add (build_game_container (level, out game_view));
+        this.add (build_gtk_game_container (level, out game_view));
 
         game_view.level_changed.connect (level_changed_cb);
         game_view.moves_changed.connect (update_subtitle);
@@ -99,7 +113,7 @@ public class LightsoffWindow : ApplicationWindow
             settings.set_int ("level", level);
     }
 
-    private bool key_release_event_cb (Clutter.Actor actor, Clutter.KeyEvent event)
+    private bool key_release_clutter_event_cb (Clutter.Actor actor, Clutter.KeyEvent event)
     {
         switch (event.keyval)
         {
diff --git a/src/meson.build b/src/meson.build
index 33b94fd..e711372 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -5,6 +5,7 @@ lightsoff_vala_sources = [
   'puzzle-generator.vala',
   'game-view.vala',
   'game-view-clutter.vala',
+  'game-view-gtk.vala',
 ]
 
 lightsoff_resources_file = files('lightsoff.gresource.xml')


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