[gnome-nibbles/wip/vala: 7/16] Add worms
- From: Michael Catanzaro <mcatanzaro src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-nibbles/wip/vala: 7/16] Add worms
- Date: Sat, 27 Jun 2015 17:03:14 +0000 (UTC)
commit a772615c80fa23661e033bc4f10bf17d6f5126bc
Author: Iulian Radu <iulian radu67 gmail com>
Date: Fri Jun 26 21:17:12 2015 +0300
Add worms
configure.ac | 2 +-
data/org.gnome.nibbles.gschema.xml | 81 ++++++++++
src/Makefile.am | 3 +-
src/gnome-nibbles.vala | 40 ++++-
src/nibbles-game.vala | 96 ++++++++++-
src/nibbles-view.vala | 305 ++++++++++++++++++++++++++++-------
src/worm.vala | 282 +++++++++++++++++++++++++++++++++
7 files changed, 730 insertions(+), 79 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 0b1226f..78b9ddd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -9,7 +9,7 @@ GNOME_MAINTAINER_MODE_DEFINES
AC_PROG_CC
AC_PROG_CXX
-AM_PROG_VALAC([0.26.0.91])
+AM_PROG_VALAC([0.28.0])
AM_PROG_CC_C_O
GLIB_GSETTINGS
diff --git a/data/org.gnome.nibbles.gschema.xml b/data/org.gnome.nibbles.gschema.xml
index 406dc85..7be2d8c 100644
--- a/data/org.gnome.nibbles.gschema.xml
+++ b/data/org.gnome.nibbles.gschema.xml
@@ -28,4 +28,85 @@
<description>Game level to start on.</description>
</key>
</schema>
+ <schema id="org.gnome.nibbles.worm0" path="/org/gnome/nibbles/worm0/">
+ <key name="color" type="s">
+ <default>'red'</default>
+ <summary>Color to use for worm</summary>
+ <description>Color to use for worm.</description>
+ </key>
+ <key name="key-up" type="i">
+ <default>65362</default>
+ <summary>Move up</summary>
+ <description>Key to use for motion up.</description>
+ </key>
+ <key name="key-down" type="i">
+ <default>65364</default>
+ <summary>Move down</summary>
+ <description>Key to use for motion down.</description>
+ </key>
+ <key name="key-left" type="i">
+ <default>65361</default>
+ <summary>Move left</summary>
+ <description>Key to use for motion left.</description>
+ </key>
+ <key name="key-right" type="i">
+ <default>65363</default>
+ <summary>Move right</summary>
+ <description>Key to use for motion right.</description>
+ </key>
+ </schema>
+ <schema id="org.gnome.nibbles.worm1" path="/org/gnome/nibbles/worm1/">
+ <key name="color" type="s">
+ <default>'green'</default>
+ <summary>Color to use for worm</summary>
+ <description>Color to use for worm.</description>
+ </key>
+ <key name="key-up" type="i">
+ <default>65362</default>
+ <summary>Move up</summary>
+ <description>Key to use for motion up.</description>
+ </key>
+ <key name="key-down" type="i">
+ <default>65364</default>
+ <summary>Move down</summary>
+ <description>Key to use for motion down.</description>
+ </key>
+ <key name="key-left" type="i">
+ <default>65361</default>
+ <summary>Move left</summary>
+ <description>Key to use for motion left.</description>
+ </key>
+ <key name="key-right" type="i">
+ <default>65363</default>
+ <summary>Move right</summary>
+ <description>Key to use for motion right.</description>
+ </key>
+ </schema>
+ <schema id="org.gnome.nibbles.worm2" path="/org/gnome/nibbles/worm2/">
+ <key name="color" type="s">
+ <default>'blue'</default>
+ <summary>Color to use for worm</summary>
+ <description>Color to use for worm.</description>
+ </key>
+ <key name="key-up" type="i">
+ <default>65362</default>
+ <summary>Move up</summary>
+ <description>Key to use for motion up.</description>
+ </key>
+ <key name="key-down" type="i">
+ <default>65364</default>
+ <summary>Move down</summary>
+ <description>Key to use for motion down.</description>
+ </key>
+ <key name="key-left" type="i">
+ <default>65361</default>
+ <summary>Move left</summary>
+ <description>Key to use for motion left.</description>
+ </key>
+ <key name="key-right" type="i">
+ <default>65363</default>
+ <summary>Move right</summary>
+ <description>Key to use for motion right.</description>
+ </key>
+ </schema>
</schemalist>
diff --git a/src/Makefile.am b/src/Makefile.am
index 78ed01d..07183d3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -9,9 +9,10 @@ gnome_nibbles_SOURCES = \
nibbles-game.vala \
games-gridframe.h \
games-gridframe.c \
+ worm.vala \
$(BUILT_SOURCES)
-gnome_nibbles_CFLAGS = -w `pkg-config --cflags glib-2.0` `pkg-config --cflags gtk+-3.0` `pkg-config --libs
glib-2.0` `pkg-config --libs gtk+-3.0` `pkg-config --cflags clutter-1.0` `pkg-config --cflags
clutter-gtk-1.0` `pkg-config --libs clutter-1.0` `pkg-config --libs clutter-gtk-1.0`
+gnome_nibbles_CFLAGS = -w `pkg-config --cflags glib-2.0` `pkg-config --cflags gtk+-3.0` `pkg-config --libs
glib-2.0` `pkg-config --libs gtk+-3.0` `pkg-config --cflags clutter-1.0` `pkg-config --cflags
clutter-gtk-1.0` `pkg-config --libs clutter-1.0` `pkg-config --libs clutter-gtk-1.0` `pkg-config --cflags
gee-0.8` `pkg-config --libs gee-0.8`
gnome_nibbles_CPPFLAGS = \
-DVERSION=\"$(VERSION)\" \
diff --git a/src/gnome-nibbles.vala b/src/gnome-nibbles.vala
index 5ef82f2..7c461dd 100644
--- a/src/gnome-nibbles.vala
+++ b/src/gnome-nibbles.vala
@@ -3,6 +3,7 @@ using Gtk;
public class Nibbles : Gtk.Application
{
private GLib.Settings settings;
+ private Gee.ArrayList<GLib.Settings> worm_settings;
private bool is_maximized;
private bool is_tiled;
@@ -58,6 +59,12 @@ public class Nibbles : Gtk.Application
add_action_entries (action_entries, this);
settings = new GLib.Settings ("org.gnome.nibbles");
+ worm_settings = new Gee.ArrayList<GLib.Settings> ();
+ for (int i = 0; i < NibblesGame.NUMWORMS; i++)
+ {
+ var name = "org.gnome.nibbles.worm%d".printf(i);
+ worm_settings.add (new GLib.Settings (name));
+ }
set_accels_for_action ("app.quit", {"<Primary>q"});
@@ -120,20 +127,21 @@ public class Nibbles : Gtk.Application
/* Compute the new tile size based on the size of the
* drawing area, rounded down.
*/
- ts_x = event.width / game.width;
- ts_y = event.height / game.height;
- if (ts_x * game.width > event.width)
+ ts_x = event.width / NibblesGame.WIDTH;
+ ts_y = event.height / NibblesGame.HEIGHT;
+ if (ts_x * NibblesGame.WIDTH > event.width)
ts_x--;
- if (ts_y * game.height > event.height)
+ if (ts_y * NibblesGame.HEIGHT > event.height)
ts_y--;
tile_size = int.min (ts_x, ts_y);
if (game.tile_size != tile_size)
{
-
- view.stage.set_size (tile_size * game.width, tile_size * game.height);
+ view.stage.set_size (tile_size * NibblesGame.WIDTH, tile_size * NibblesGame.HEIGHT);
view.board_rescale (tile_size);
+ foreach (var worm in game.worms)
+ worm.rescaled (tile_size);
game.tile_size = tile_size;
}
@@ -168,16 +176,34 @@ public class Nibbles : Gtk.Application
view = new NibblesView (game);
view.configure_event.connect (configure_event_cb);
- frame = new GamesGridFrame (game.width, game.height);
+ frame = new GamesGridFrame (NibblesGame.WIDTH, NibblesGame.HEIGHT);
main_stack.add_named (frame, "frame");
frame.add (view);
frame.show_all ();
+ /* 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;
view.new_level (game.current_level);
+
+ foreach (var worm in game.worms)
+ {
+ var actors = view.worm_actors.lookup (worm);
+ if (actors.get_stage () == null) {
+ view.stage.add_child (actors);
+ }
+ actors.show ();
+ }
+ game.load_worm_properties (worm_settings);
+
+ stderr.printf("[Debug] Showing game view\n");
show_game_view ();
+
+ game.start ();
}
public static int main (string[] args)
diff --git a/src/nibbles-game.vala b/src/nibbles-game.vala
index 31e0c0f..81c907f 100644
--- a/src/nibbles-game.vala
+++ b/src/nibbles-game.vala
@@ -3,26 +3,80 @@ public class NibblesGame : Object
public int tile_size;
public int start_level;
- public int DEFAULTGAMEDELAY = 35;
- public int GAMEDELAY = 35;
- public int NETDELAY = 2;
- public int BONUSDELAY = 100;
+ public const int MINIMUM_TILE_SIZE = 7;
- public int width = 92;
- public int height = 66;
+ public const int DEFAULTGAMEDELAY = 35;
+ public const int GAMEDELAY = 35;
+ public const int NETDELAY = 2;
+ public const int BONUSDELAY = 100;
- public char EMPTYCHAR = 'a';
- public char WORMCHAR = 'w';
+ public const int NUMWORMS = 1;
+
+ public const int WIDTH = 92;
+ public const int HEIGHT = 66;
+
+ public const char EMPTYCHAR = 'a';
+ public const char WORMCHAR = 'w';
public int current_level;
public int[,] walls;
+ public Gee.LinkedList<Worm> worms;
+
+ public int numworms = NUMWORMS;
+
+ public int game_speed = 4;
+
+ public signal void worm_moved (Worm worm);
+
+ public HashTable<Worm, WormProperties?> worm_props;
+
public NibblesGame (Settings settings)
{
- walls = new int[width, height];
+ walls = new int[WIDTH, HEIGHT];
+ worms = new Gee.LinkedList<Worm> ();
+ worm_props = new HashTable<Worm, WormProperties?> (direct_hash, direct_equal);
load_properties (settings);
}
+ public void start ()
+ {
+ add_worms ();
+ Timeout.add (game_speed * (GAMEDELAY + NETDELAY), main_loop_cb);
+ }
+
+ public void add_worms ()
+ {
+ stderr.printf("[Debug] Loading worms\n");
+ stderr.printf("[Debug] worms: %d\n", worms.size);
+ foreach (var worm in worms) {
+ stderr.printf("[Debug] worm size %d\n", worm.list.size);
+ worm.spawn (walls);
+ }
+ }
+
+ public void move_worms ()
+ {
+ foreach (var worm in worms)
+ {
+ if (worm.stop)
+ continue;
+ if (!worm.can_move_to (walls, numworms)) {
+ stderr.printf("[Debug] died\n");
+ worm.die (walls);
+ continue;
+ }
+
+ worm.move (walls, true);
+ }
+ }
+
+ public bool main_loop_cb ()
+ {
+ move_worms ();
+ return Source.CONTINUE;
+ }
+
public void load_properties (Settings settings)
{
tile_size = settings.get_int ("tile-size");
@@ -34,4 +88,28 @@ public class NibblesGame : Object
tile_size = settings.get_int ("tile-size");
start_level = settings.get_int ("start-level");
}
+
+ public void load_worm_properties (Gee.ArrayList<Settings> worm_settings)
+ {
+ foreach (var worm in worms)
+ {
+ var properties = WormProperties ();
+ properties.up = worm_settings[worm.id].get_int ("key-up");
+ properties.down = worm_settings[worm.id].get_int ("key-down");
+ properties.left = worm_settings[worm.id].get_int ("key-left");
+ properties.right = worm_settings[worm.id].get_int ("key-right");
+
+ worm_props.insert (worm, properties);
+ }
+ }
+
+ public bool handle_keypress (uint keyval)
+ {
+ foreach (var worm in worms)
+ if (worm.human)
+ if (worm.handle_keypress (keyval, worm_props))
+ return true;
+
+ return false;
+ }
}
diff --git a/src/nibbles-view.vala b/src/nibbles-view.vala
index 841e5da..f451570 100644
--- a/src/nibbles-view.vala
+++ b/src/nibbles-view.vala
@@ -1,22 +1,28 @@
public class NibblesView : GtkClutter.Embed
{
/* Game being played */
- public NibblesGame game { get; private set; }
+ private NibblesGame? _game = null;
+ public NibblesGame? game
+ {
+ get { return _game; }
+ set
+ {
+ if (_game != null)
+ SignalHandler.disconnect_matched (_game, SignalMatchType.DATA, 0, 0, null, null, this);
+ _game = value;
+ }
+ }
- public GtkClutter.Texture surface;
- public Clutter.Stage stage;
+ public Clutter.Stage stage { get; private set; }
+ private GtkClutter.Texture surface;
private Clutter.Actor level;
- Gdk.Pixbuf[] wall_pixmaps = { null, null, null, null, null,
- null, null, null, null, null,
- null
- };
- Gdk.Pixbuf[] worm_pixmaps = { null, null, null, null, null,
- null, null
- };
- Gdk.Pixbuf[] boni_pixmaps = { null, null, null, null, null,
- null, null, null, null
- };
+ private Gdk.Pixbuf wall_pixmaps[11];
+ public Gdk.Pixbuf worm_pixmaps[7];
+ private Gdk.Pixbuf boni_pixmaps[9];
+
+ // public Gee.ArrayList<GtkClutter.Actor> worm_actors;
+ public HashTable<Worm, WormActor> worm_actors;
public NibblesView (NibblesGame game)
{
@@ -26,7 +32,8 @@ public class NibblesView : GtkClutter.Embed
Clutter.Color stage_color = { 0x00, 0x00, 0x00, 0xff };
stage.set_background_color (stage_color);
- set_size_request (7 * game.width, 7 * game.height);
+ set_size_request (NibblesGame.MINIMUM_TILE_SIZE * NibblesGame.WIDTH,
+ NibblesGame.MINIMUM_TILE_SIZE * NibblesGame.HEIGHT);
try
{
@@ -42,7 +49,6 @@ public class NibblesView : GtkClutter.Embed
surface.set_property ("repeat-y", val);
surface.set_position (0, 0);
- surface.show ();
}
catch (Clutter.TextureError e)
{
@@ -53,18 +59,24 @@ public class NibblesView : GtkClutter.Embed
error ("Failed to load textures: %s", e.message);
}
+ worm_actors = new HashTable<Worm, WormActor> (direct_hash, direct_equal);
load_pixmap ();
stage.add_child (surface);
}
+ public override bool key_press_event (Gdk.EventKey event)
+ {
+ return game.handle_keypress (event.keyval);
+ }
+
public void new_level (int level)
{
string level_name;
string filename;
string tmpboard;
+ int count = 0;
- warning("%d\n", game.tile_size);
level_name = "level%03d.gnl".printf (level);
filename = Path.build_filename (PKGDATADIR, "levels", level_name, null);
@@ -74,7 +86,9 @@ public class NibblesView : GtkClutter.Embed
error (_("Nibbles couldn't find pixmap file: %s"), filename);
}
- for (int i = 0; i < game.height; i++)
+
+ stderr.printf("[Debug] %d\n", game.tile_size);
+ for (int i = 0; i < NibblesGame.HEIGHT; i++)
{
if ((tmpboard = file.read_line ()) == null)
{
@@ -82,22 +96,74 @@ public class NibblesView : GtkClutter.Embed
error (_("Level file appears to be damaged: %s"), filename);
}
- for (int j = 0; j < game.width; j++)
+ for (int j = 0; j < NibblesGame.WIDTH; j++)
{
game.walls[j, i] = tmpboard get(j);
switch (game.walls[j, i])
{
case 'm':
- game.walls[j, i] = game.EMPTYCHAR;
+ game.walls[j, i] = NibblesGame.EMPTYCHAR;
+ if (count < game.numworms)
+ {
+ var worm = new Worm (count++, WormDirection.UP);
+ 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.set_start (j, i);
+ game.worms.add (worm);
+
+ var actors = new WormActor ();
+ worm_actors.insert (worm, actors);
+ }
break;
case 'n':
- game.walls[j, i] = game.EMPTYCHAR;
+ game.walls[j, i] = NibblesGame.EMPTYCHAR;
+ if (count < game.numworms)
+ {
+ var worm = new Worm (count++, WormDirection.DOWN);
+ 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.set_start (j, i);
+ game.worms.add (worm);
+
+ var actors = new WormActor ();
+ worm_actors.insert (worm, actors);
+ }
break;
case 'o':
- game.walls[j, i] = game.EMPTYCHAR;
+ game.walls[j, i] = NibblesGame.EMPTYCHAR;
+ if (count < game.numworms)
+ {
+ var worm = new Worm (count++, WormDirection.LEFT);
+ 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.set_start (j, i);
+ game.worms.add (worm);
+
+ var actors = new WormActor ();
+ worm_actors.insert (worm, actors);
+ }
break;
case 'p':
- game.walls[j, i] = game.EMPTYCHAR;
+ game.walls[j, i] = NibblesGame.EMPTYCHAR;
+ if (count < game.numworms)
+ {
+ var worm = new Worm (count++, WormDirection.RIGHT);
+ 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.set_start (j, i);
+ game.worms.add (worm);
+
+ var actors = new WormActor ();
+ worm_actors.insert (worm, actors);
+ }
break;
default:
break;
@@ -105,6 +171,8 @@ public class NibblesView : GtkClutter.Embed
}
}
+ stderr.printf("[Debug] %d\n", game.tile_size);
+ stderr.printf("[Debug] Loading level\n");
load_level ();
}
@@ -167,41 +235,34 @@ public class NibblesView : GtkClutter.Embed
"snake-grey.svg"
};
- int tile_size = game.tile_size;
for (int i = 0; i < 8; i++) {
boni_pixmaps[i] = load_pixmap_file (bonus_files[i],
- 2 * tile_size, 2 * tile_size);
+ 2 * game.tile_size, 2 * game.tile_size);
}
for (int i = 0; i < 11; i++) {
wall_pixmaps[i] = load_pixmap_file (small_files[i],
- 2 * tile_size, 2 * tile_size);
+ 2 * game.tile_size, 2 * game.tile_size);
}
for (int i = 0; i < 7; i++) {
worm_pixmaps[i] = load_pixmap_file (worm_files[i],
- tile_size, tile_size);
+ game.tile_size, game.tile_size);
}
}
void load_level ()
{
int x_pos, y_pos;
- Clutter.Actor tmp = null;
+ GtkClutter.Texture tmp = null;
bool is_wall = true;
level = new Clutter.Actor ();
- // if (level != null)
- // {
- // warning("here");
- // level.remove_all_children ();
- // stage.remove_child (level);
- // }
/* Load wall_pixmaps onto the surface */
- for (int i = 0; i < game.height; i++)
+ for (int i = 0; i < NibblesGame.HEIGHT; i++)
{
y_pos = i * game.tile_size;
- for (int j = 0; j < game.width; j++)
+ for (int j = 0; j < NibblesGame.WIDTH; j++)
{
is_wall = true;
try
@@ -213,56 +274,56 @@ public class NibblesView : GtkClutter.Embed
break;
case 'b': // straight up
tmp = new GtkClutter.Texture ();
- ((GtkClutter.Texture) tmp).set_from_pixbuf (wall_pixmaps[0]);
+ tmp.set_from_pixbuf (wall_pixmaps[0]);
break;
case 'c': // straight side
tmp = new GtkClutter.Texture ();
- ((GtkClutter.Texture) tmp).set_from_pixbuf (wall_pixmaps[1]);
+ tmp.set_from_pixbuf (wall_pixmaps[1]);
break;
case 'd': // corner bottom left
tmp = new GtkClutter.Texture ();
- ((GtkClutter.Texture) tmp).set_from_pixbuf (wall_pixmaps[2]);
+ tmp.set_from_pixbuf (wall_pixmaps[2]);
break;
case 'e': // corner bottom right
tmp = new GtkClutter.Texture ();
- ((GtkClutter.Texture) tmp).set_from_pixbuf (wall_pixmaps[3]);
+ tmp.set_from_pixbuf (wall_pixmaps[3]);
break;
case 'f': // corner up left
tmp = new GtkClutter.Texture ();
- ((GtkClutter.Texture) tmp).set_from_pixbuf (wall_pixmaps[4]);
+ tmp.set_from_pixbuf (wall_pixmaps[4]);
break;
case 'g': // corner up right
tmp = new GtkClutter.Texture ();
- ((GtkClutter.Texture) tmp).set_from_pixbuf (wall_pixmaps[5]);
+ tmp.set_from_pixbuf (wall_pixmaps[5]);
break;
case 'h': // tee up
tmp = new GtkClutter.Texture ();
- ((GtkClutter.Texture) tmp).set_from_pixbuf (wall_pixmaps[6]);
+ tmp.set_from_pixbuf (wall_pixmaps[6]);
break;
case 'i': // tee right
tmp = new GtkClutter.Texture ();
- ((GtkClutter.Texture) tmp).set_from_pixbuf (wall_pixmaps[7]);
+ tmp.set_from_pixbuf (wall_pixmaps[7]);
break;
case 'j': // tee left
tmp = new GtkClutter.Texture ();
- ((GtkClutter.Texture) tmp).set_from_pixbuf (wall_pixmaps[8]);
+ tmp.set_from_pixbuf (wall_pixmaps[8]);
break;
case 'k': // tee down
tmp = new GtkClutter.Texture ();
- ((GtkClutter.Texture) tmp).set_from_pixbuf (wall_pixmaps[9]);
+ tmp.set_from_pixbuf (wall_pixmaps[9]);
break;
case 'l': // tee cross
tmp = new GtkClutter.Texture ();
- ((GtkClutter.Texture) tmp).set_from_pixbuf (wall_pixmaps[10]);
+ tmp.set_from_pixbuf (wall_pixmaps[10]);
break;
default:
is_wall = false;
break;
}
}
- catch (GLib.Error e)
+ catch (Error e)
{
-
+ error (e.message);
}
if (is_wall)
@@ -272,7 +333,6 @@ public class NibblesView : GtkClutter.Embed
((Clutter.Actor) tmp).set_size (game.tile_size,
game.tile_size);
((Clutter.Actor) tmp).set_position (x_pos, y_pos);
- ((Clutter.Actor) tmp).show ();
level.add_child ((Clutter.Actor) tmp);
}
}
@@ -285,7 +345,7 @@ public class NibblesView : GtkClutter.Embed
level.save_easing_state ();
level.set_easing_mode (Clutter.AnimationMode.EASE_OUT_BOUNCE);
- level.set_easing_duration (game.GAMEDELAY * game.GAMEDELAY);
+ level.set_easing_duration (NibblesGame.GAMEDELAY * NibblesGame.GAMEDELAY);
level.set_scale (1.0, 1.0);
level.set_pivot_point (0.5f, 0.5f);
level.set_opacity (0xff);
@@ -294,30 +354,153 @@ public class NibblesView : GtkClutter.Embed
public void board_rescale (int tile_size)
{
- int count;
int board_width, board_height;
float x_pos, y_pos;
- Clutter.Actor tmp;
if (level == null)
return;
if (surface == null)
return;
- board_width = game.width * tile_size;
- board_height = game.height * tile_size;
+ board_width = NibblesGame.WIDTH * tile_size;
+ board_height = NibblesGame.HEIGHT * tile_size;
surface.set_size (board_width, board_height);
- count = level.get_n_children ();
+ foreach (var actor in level.get_children ())
+ {
+ 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);
+ actor.set_size (tile_size, tile_size);
+ }
+ }
+
+ public void worm_added_cb (Worm worm)
+ {
+ var actor = new GtkClutter.Texture ();
+ try
+ {
+ actor.set_from_pixbuf (worm_pixmaps[0]);
+ }
+ catch (Clutter.TextureError e)
+ {
+ error ("Failed to set texture: %s", e.message);
+ }
+ catch (GLib.Error e)
+ {
+ error ("Failed to set texture: %s", e.message);
+ }
+
+ actor.set_size (game.tile_size, game.tile_size);
+ actor.set_position (worm.list.first ().x * game.tile_size, worm.list.first ().y * game.tile_size);
+
+ var actors = worm_actors.lookup (worm);
+ actors.add_child (actor);
+
+ for (int i = 0; i < 13; i++) {
+ for (int j = 0; j < 20; j++)
+ stderr.printf("%c ", game.walls[j, i]);
+ stderr.printf("\n");
+ }
+ stderr.printf("\n");
+ }
+
+ public void worm_moved_cb (Worm worm)
+ {
+ var actors = worm_actors.lookup (worm);
+
+ /* Make the worms last actor (the tail) the new head. Then remove it
+ * and add it again so the head is always the last child added */
+ var tail_actor = actors.first_child;
+ tail_actor.set_position (worm.list.first ().x * game.tile_size, worm.list.first ().y *
game.tile_size);
+ actors.remove_child (tail_actor);
+ actors.add_child (tail_actor);
+
+ for (int i = 0; i < 13; i++) {
+ for (int j = 0; j < 20; j++)
+ stderr.printf("%c ", game.walls[j, i]);
+ stderr.printf("\n");
+ }
+ stderr.printf("\n");
+ }
+
+ public void worm_rescaled_cb (Worm worm, int tile_size)
+ {
+ float x_pos, y_pos;
+ var actors = worm_actors.lookup (worm);
+ if (actors == null)
+ return;
- for (int i = 0; i < count; i++)
+ foreach (var actor in actors.get_children ())
{
- tmp = level.get_child_at_index (i);
- ((Clutter.Actor) tmp).get_position (out x_pos, out y_pos);
- ((Clutter.Actor) tmp).set_position ((x_pos / game.tile_size) * tile_size,
- (y_pos / game.tile_size) * tile_size);
- ((Clutter.Actor) tmp).set_size (tile_size, tile_size);
+ 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);
+ actor.set_size (tile_size, tile_size);
}
}
+
+ public void worm_died_cb (Worm worm)
+ {
+ float x, y;
+ var group = new Clutter.Actor ();
+ var actors = worm_actors.lookup (worm);
+ foreach (var actor in actors.get_children ())
+ {
+ stderr.printf("[Debug] Before\n");
+ GtkClutter.Texture tmp = new GtkClutter.Texture ();
+ var color = game.worm_props.lookup (worm).color;
+ try
+ {
+ tmp.set_from_pixbuf (worm_pixmaps[color]);
+ }
+ catch (Clutter.TextureError e)
+ {
+ error ("Failed to set texture: %s", e.message);
+ }
+ catch (GLib.Error e)
+ {
+ error ("Failed to set texture: %s", e.message);
+ }
+
+ actor.get_position (out x, out y);
+
+ tmp.set_position (x, y);
+ tmp.set_size (game.tile_size, game.tile_size);
+ group.add_child (tmp);
+ stderr.printf("[Debug] After\n");
+ }
+
+ actors.remove_all_children ();
+
+ stage.add_child (group);
+
+ group.save_easing_state ();
+ group.set_easing_mode (Clutter.AnimationMode.EASE_OUT_QUAD);
+ group.set_easing_duration (NibblesGame.GAMEDELAY * 9);
+ group.set_scale (2.0f, 2.0f);
+ group.set_pivot_point (5f, 0.5f);
+ group.set_opacity (0);
+ group.restore_easing_state ();
+ }
+}
+
+public class WormActor : Clutter.Actor
+{
+ public override void show ()
+ {
+ base.show ();
+
+ set_opacity (0);
+ set_scale (3.0, 3.0);
+
+ save_easing_state ();
+ set_easing_mode (Clutter.AnimationMode.EASE_OUT_CIRC);
+ set_easing_duration (NibblesGame.GAMEDELAY * 26);
+ set_scale (1.0, 1.0);
+ set_pivot_point (0.5f, 0.5f);
+ set_opacity (0xff);
+ restore_easing_state ();
+ }
}
diff --git a/src/worm.vala b/src/worm.vala
new file mode 100644
index 0000000..453406d
--- /dev/null
+++ b/src/worm.vala
@@ -0,0 +1,282 @@
+public struct Position
+{
+ int x;
+ int y;
+}
+
+public enum WormDirection
+{
+ UP,
+ DOWN,
+ LEFT,
+ RIGHT
+}
+
+public struct WormProperties
+{
+ int color;
+ uint left;
+ uint right;
+ uint up;
+ uint down;
+}
+
+public class Worm : Object
+{
+ public const int STARTING_LENGTH = 5;
+ private const int STARTING_LIVES = 6;
+
+ public Position starting_position { get; private set; }
+
+ public int id { get; private set; }
+
+ public bool human;
+ public bool keypress = false;
+ public bool stop = false;
+
+ public int lives { get; private set; }
+ private WormDirection _direction;
+ public WormDirection direction
+ {
+ get { return _direction; }
+ set
+ {
+ if (keypress)
+ {
+ queue_keypress (value);
+ return;
+ }
+
+ _direction = value;
+ keypress = true;
+ }
+ }
+
+ public WormDirection starting_direction;
+
+ private Gee.ArrayQueue<WormDirection> key_queue;
+
+ public Gee.LinkedList<Position?> list { get; private set; }
+
+ public signal void added ();
+ public signal void moved ();
+ public signal void rescaled (int tile_size);
+ public signal void died ();
+
+ public Worm (int id, WormDirection direction)
+ {
+ this.id = id;
+ human = true;
+ starting_direction = direction;
+ lives = STARTING_LIVES;
+ list = new Gee.LinkedList<Position?> ();
+ key_queue = new Gee.ArrayQueue<WormDirection> ();
+ }
+
+ public Position head ()
+ {
+ return list.first ();
+ }
+
+ public void set_start (int xhead, int yhead)
+ {
+ starting_position = Position () {
+ x = xhead,
+ y = yhead
+ };
+
+ list.add (starting_position);
+
+ this.direction = starting_direction;
+ }
+
+ public void move (int[,] walls, bool remove)
+ {
+ if (human)
+ keypress = false;
+
+ var position = head ();
+ switch (direction)
+ {
+ case WormDirection.UP:
+ position.y = --head ().y;
+ if (position.y < 0)
+ position.y = NibblesGame.HEIGHT - 1;
+ break;
+ case WormDirection.DOWN:
+ position.y = ++head ().y;
+ if (position.y >= NibblesGame.HEIGHT)
+ position.y = 0;
+ break;
+ case WormDirection.LEFT:
+ position.x = --head ().x;
+ if (position.x < 0)
+ position.x = NibblesGame.WIDTH - 1;
+ break;
+ case WormDirection.RIGHT:
+ position.x = ++head ().x;
+ if (position.x >= NibblesGame.WIDTH)
+ position.x = 0;
+ break;
+ default:
+ break;
+ }
+
+ stderr.printf("[Debug] x %d y %d\n", position.x, position.y);
+ /* Add a new body piece */
+ list.offer_head (position);
+ /* Mark the tile as occupied by the worm's body */
+ walls[head ().x, head ().y] = NibblesGame.WORMCHAR + id;
+
+ if (remove)
+ {
+ walls[list.last ().x, list.last ().y] = NibblesGame.EMPTYCHAR;
+ list.poll_tail ();
+ moved ();
+ }
+ else
+ added ();
+
+ if (!key_queue.is_empty)
+ dequeue_keypress ();
+ }
+
+ public bool can_move_to (int[,] walls, int numworms)
+ {
+ Position position = position_move ();
+
+ if (walls[position.x, position.y] > NibblesGame.EMPTYCHAR &&
+ walls[position.x, position.y] < 'z' + numworms)
+ return false;
+
+ return true;
+ }
+
+ public void spawn (int[,] walls)
+ {
+ for (int i = 0; i < STARTING_LENGTH; i++)
+ move (walls, false);
+ }
+
+ public void lose_life ()
+ {
+ lives--;
+ }
+
+ public void die (int[,] walls)
+ {
+ stop = true;
+ lose_life ();
+
+ died ();
+ foreach (var pos in list)
+ walls[pos.x, pos.y] = NibblesGame.EMPTYCHAR;
+
+ list.clear ();
+ list.add (starting_position);
+ direction = starting_direction;
+ spawn (walls);
+
+ key_queue.clear ();
+
+ stop = false;
+ }
+
+ private Position position_move ()
+ {
+ Position position = head ();
+
+ switch (direction)
+ {
+ case WormDirection.UP:
+ position.y = --head ().y;
+ if (position.y < 0)
+ position.y = NibblesGame.HEIGHT - 1;
+ break;
+ case WormDirection.DOWN:
+ position.y = ++head ().y;
+ if (position.y >= NibblesGame.HEIGHT)
+ position.y = 0;
+ break;
+ case WormDirection.LEFT:
+ position.x = --head ().x;
+ if (position.x < 0)
+ position.x = NibblesGame.WIDTH - 1;
+ break;
+ case WormDirection.RIGHT:
+ position.x = ++head ().x;
+ if (position.x >= NibblesGame.WIDTH)
+ position.x = 0;
+ break;
+ default:
+ break;
+ }
+
+ return position;
+ }
+
+ public bool handle_keypress (uint keyval, HashTable<Worm, WormProperties?> worm_props)
+ {
+ WormProperties properties;
+ uint propsUp, propsDown, propsLeft, propsRight, keyvalUpper;
+
+ if (lives <= 0)
+ return false;
+
+ properties = worm_props.lookup (this);
+ propsUp = upper_key (properties.up);
+ propsLeft = upper_key (properties.left);
+ propsDown = upper_key (properties.down);
+ propsRight = upper_key (properties.right);
+ keyvalUpper = upper_key (keyval);
+
+ if ((keyvalUpper == propsUp) && (direction != WormDirection.DOWN))
+ {
+ handle_direction (WormDirection.UP);
+ return true;
+ }
+ if ((keyvalUpper == propsDown) && (direction != WormDirection.UP)) {
+ handle_direction (WormDirection.DOWN);
+ return true;
+ }
+ if ((keyvalUpper == propsRight) && (direction != WormDirection.LEFT)) {
+ handle_direction (WormDirection.RIGHT);
+ return true;
+ }
+ if ((keyvalUpper == propsLeft) && (direction != WormDirection.RIGHT)) {
+ handle_direction (WormDirection.LEFT);
+ return true;
+ }
+
+ return false;
+ }
+
+ private uint upper_key (uint keyval)
+ {
+ if (keyval > 255)
+ return keyval;
+ return ((char) keyval).toupper ();
+ }
+
+ public void handle_direction (WormDirection dir)
+ {
+ direction = dir;
+ }
+
+ public void queue_keypress (WormDirection dir)
+ requires (!key_queue.is_empty)
+ {
+ /* Ignore duplicates in normal movement mode. This resolves the key
+ * repeat issue
+ */
+ if (!key_queue.is_empty && dir == key_queue.peek ())
+ return;
+
+ key_queue.add (dir);
+ }
+
+ public void dequeue_keypress ()
+ {
+ direction = key_queue.poll ();
+ }
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]