[gnome-games/gsoc-seed-games] [lightsoff] Implement keyboard-based play (use arrow keys/enter)
- From: Tim Horton <hortont src gnome org>
- To: svn-commits-list gnome org
- Subject: [gnome-games/gsoc-seed-games] [lightsoff] Implement keyboard-based play (use arrow keys/enter)
- Date: Sat, 27 Jun 2009 05:41:13 +0000 (UTC)
commit a7f47db4d95f94edba69b5cfeface958ee0774f0
Author: Tim Horton <hortont424 gmail com>
Date: Sat Jun 27 01:39:12 2009 -0400
[lightsoff] Implement keyboard-based play (use arrow keys/enter)
lightsoff/Board.js | 77 +++++++++++++++------------
lightsoff/Game.js | 69 +++++++++++++++++++++++
lightsoff/main.js.in | 2 +
lightsoff/themes/tango/Makefile.am | 2 +
lightsoff/themes/tango/highlight.svg | 99 ++++++++++++++++++++++++++++++++++
lightsoff/themes/tango/theme.js.in | 3 +
lightsoff/themes/up/Makefile.am | 2 +
lightsoff/themes/up/highlight.svg | 99 ++++++++++++++++++++++++++++++++++
lightsoff/themes/up/theme.js.in | 3 +
9 files changed, 322 insertions(+), 34 deletions(-)
---
diff --git a/lightsoff/Board.js b/lightsoff/Board.js
index a5e4f33..5363969 100644
--- a/lightsoff/Board.js
+++ b/lightsoff/Board.js
@@ -9,7 +9,7 @@ BoardView = new GType({
parent: Clutter.Group.type,
name: "BoardView",
signals: [{name: "game_won"}],
- init: function()
+ init: function(self)
{
// Private
var self = this;
@@ -28,7 +28,8 @@ BoardView = new GType({
for(var y = 0; y < tiles; y++)
{
var l = new Light.LightView();
- l.set_position((x + 0.5) * l.width, (y + 0.5) * l.height);
+ var loc = self.position_for_light(x, y);
+ l.set_position(loc.x, loc.y);
l.signal.button_release_event.connect(light_clicked, {"x":x, "y":y});
lights[x][y] = l;
@@ -39,8 +40,39 @@ BoardView = new GType({
}
}
+ // Check if the game was won; if so, emit the game_won signal
+ // in order to notify the Game controller.
+
+ var check_won = function()
+ {
+ if(cleared())
+ self.signal.game_won.emit();
+ }
+
+ // Callback for button_release_event from each light; user_data
+ // is an object containing the coordinates of the clicked light.
+ var light_clicked = function(light, event, coords)
+ {
+ self.light_toggle(coords.x, coords.y);
+
+ return false;
+ }
+
+ // Returns whether or not the board is entirely 'off' (i.e. game is won)
+ var cleared = function()
+ {
+ for(var x = 0; x < tiles; x++)
+ for(var y = 0; y < tiles; y++)
+ if(lights[x][y].get_state())
+ return false;
+
+ return true;
+ }
+
+ // Public
+
// Toggle a light and those in each cardinal direction around it.
- var light_toggle = function(x, y)
+ this.light_toggle = function(x, y)
{
if(!playable)
return;
@@ -68,37 +100,14 @@ BoardView = new GType({
timeline.start();
}
- // Check if the game was won; if so, emit the game_won signal
- // in order to notify the Game controller.
-
- var check_won = function()
- {
- if(cleared())
- self.signal.game_won.emit();
- }
-
- // Callback for button_release_event from each light; user_data
- // is an object containing the coordinates of the clicked light.
- var light_clicked = function(light, event, coords)
- {
- light_toggle(coords.x, coords.y);
-
- return false;
- }
-
- // Returns whether or not the board is entirely 'off' (i.e. game is won)
- var cleared = function()
+ this.position_for_light = function(x, y)
{
- for(var x = 0; x < tiles; x++)
- for(var y = 0; y < tiles; y++)
- if(lights[x][y].get_state())
- return false;
+ var p_l = {x: (x + 0.5) * Settings.theme.light[0].width,
+ y: (y + 0.5) * Settings.theme.light[0].height};
- return true;
+ return p_l;
}
- // Public
-
// 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
@@ -124,18 +133,18 @@ BoardView = new GType({
i = Math.round((tiles - 1) * GLib.random_double());
j = Math.round((tiles - 1) * GLib.random_double());
- light_toggle(i, j);
+ self.light_toggle(i, j);
// Ensure some level of "symmetry"
var x_sym = Math.abs(i - (tiles - 1));
var y_sym = Math.abs(j - (tiles - 1));
if(sym == 0)
- light_toggle(x_sym, j);
+ self.light_toggle(x_sym, j);
else if(sym == 1)
- light_toggle(x_sym, y_sym);
+ self.light_toggle(x_sym, y_sym);
else
- light_toggle(i, y_sym);
+ self.light_toggle(i, y_sym);
}
}
while(cleared());
diff --git a/lightsoff/Game.js b/lightsoff/Game.js
index bb3d5c8..ccf7485 100644
--- a/lightsoff/Game.js
+++ b/lightsoff/Game.js
@@ -20,8 +20,10 @@ GameView = new GType({
var backing_view = new Clutter.Clone({source:Settings.theme.backing});
var left_arrow = new Arrow.ArrowView();
var right_arrow = new Arrow.ArrowView();
+ var keycursor_view = new Clutter.Clone({source:Settings.theme.highlight});
var new_board_view = null;
var timeline;
+ var keycursor = {x:0, y:0, ready: false};
// Set up a new board.
var create_next_board = function()
@@ -41,6 +43,7 @@ GameView = new GType({
self.remove_actor(board_view);
board_view = new_board_view;
board_view.set_playable(true);
+ keycursor_view.raise_top();
timeline = 0;
}
@@ -171,6 +174,68 @@ GameView = new GType({
return false;
}
+ // Change the currently selected tile with the keyboard
+ this.update_keyboard_selection = function (actor, event, ud)
+ {
+ // TODO: this is wrong. but, they're defines...
+ var kUp = 65362, kDown = 65364, kLeft = 65361, kRight = 65363, kEnter = 65293, kEsc = 65307;
+
+ if(event.key.keyval == kEsc)
+ {
+ keycursor_view.animate(Clutter.AnimationMode.EASE_OUT_SINE, 250,
+ {
+ opacity: 0
+ });
+
+ keycursor.ready = false;
+ }
+
+ if(keycursor.ready)
+ {
+ if(event.key.keyval == kUp && keycursor.y > 0)
+ keycursor.y--;
+ else if(event.key.keyval == kDown && keycursor.y < 4)
+ keycursor.y++;
+ else if(event.key.keyval == kLeft && keycursor.x > 0)
+ keycursor.x--;
+ else if(event.key.keyval == kRight && keycursor.x < 4)
+ keycursor.x++;
+ else if(event.key.keyval == kEnter)
+ board_view.light_toggle(keycursor.x, keycursor.y);
+ }
+
+ if(event.key.keyval != kDown &&
+ event.key.keyval != kUp &&
+ event.key.keyval != kLeft &&
+ event.key.keyval != kRight)
+ return false;
+
+ var loc = board_view.position_for_light(keycursor.x, keycursor.y);
+
+ if(keycursor.ready)
+ {
+ keycursor_view.animate(Clutter.AnimationMode.EASE_OUT_SINE, 250,
+ {
+ x: loc.x,
+ y: loc.y
+ });
+ }
+ else
+ {
+ keycursor_view.opacity = 0;
+ keycursor_view.set_position(loc.x, loc.y);
+
+ keycursor_view.animate(Clutter.AnimationMode.EASE_OUT_SINE, 250,
+ {
+ opacity: 255
+ });
+ }
+
+ keycursor.ready = true;
+
+ return false;
+ }
+
// Implementation
score_view.set_width(5);
@@ -204,6 +269,10 @@ GameView = new GType({
right_arrow.signal.button_release_event.connect(swap_board, {direction: 1});
this.set_size(board_view.width, score_view.y + score_view.height);
+
+ keycursor_view.set_position(-100, -100);
+ keycursor_view.anchor_gravity = Clutter.Gravity.CENTER;
+ this.add_actor(keycursor_view);
Settings.Watcher.signal.theme_changed.connect(theme_changed);
}
diff --git a/lightsoff/main.js.in b/lightsoff/main.js.in
index 8bd2100..fff7d9d 100755
--- a/lightsoff/main.js.in
+++ b/lightsoff/main.js.in
@@ -54,6 +54,8 @@ stage.add_actor(game);
stage.set_size(game.width, game.height);
clutter_embed.set_size_request(stage.width, stage.height);
+stage.signal.key_release_event.connect(game.update_keyboard_selection);
+
stage.show_all();
window.show_all();
diff --git a/lightsoff/themes/tango/Makefile.am b/lightsoff/themes/tango/Makefile.am
index 9d2f4c1..cde0d38 100644
--- a/lightsoff/themes/tango/Makefile.am
+++ b/lightsoff/themes/tango/Makefile.am
@@ -5,6 +5,7 @@ theme_DATA = \
led-back.svg \
off.svg \
on.svg \
+ highlight.svg \
theme.js
EXTRA_DIST = \
@@ -13,4 +14,5 @@ EXTRA_DIST = \
led-back.svg \
off.svg \
on.svg \
+ highlight.svg \
theme.js.in
diff --git a/lightsoff/themes/tango/highlight.svg b/lightsoff/themes/tango/highlight.svg
new file mode 100644
index 0000000..a830854
--- /dev/null
+++ b/lightsoff/themes/tango/highlight.svg
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="75"
+ height="75"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docname="highlight.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ version="1.0">
+ <defs
+ id="defs4">
+ <linearGradient
+ id="linearGradient3179">
+ <stop
+ style="stop-color:#35669b;stop-opacity:0.96078432;"
+ offset="0"
+ id="stop3181" />
+ <stop
+ style="stop-color:#5e92c8;stop-opacity:0.96078432;"
+ offset="1"
+ id="stop3183" />
+ </linearGradient>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ <filter
+ inkscape:collect="always"
+ id="filter3393"
+ x="-0.43563023"
+ width="1.8712605"
+ y="-0.43563023"
+ height="1.8712605">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="5.5324044"
+ id="feGaussianBlur3395" />
+ </filter>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#000000"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="1"
+ inkscape:pageshadow="2"
+ inkscape:zoom="8.76"
+ inkscape:cx="17.522831"
+ inkscape:cy="37.5"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1438"
+ inkscape:window-height="882"
+ inkscape:window-x="0"
+ inkscape:window-y="16" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-164.71428,-194.21933)">
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.64102568;fill:#ffffff;fill-opacity:1;stroke:none;stroke-opacity:1;filter:url(#filter3393)"
+ id="path3183"
+ sodipodi:cx="22.888128"
+ sodipodi:cy="25.285389"
+ sodipodi:rx="15.239726"
+ sodipodi:ry="15.239726"
+ d="M 38.127854,25.285389 A 15.239726,15.239726 0 1 1 7.6484022,25.285389 A 15.239726,15.239726 0 1 1 38.127854,25.285389 z"
+ transform="matrix(1.247191,0,0,1.247191,173.66841,200.18362)" />
+ </g>
+</svg>
diff --git a/lightsoff/themes/tango/theme.js.in b/lightsoff/themes/tango/theme.js.in
index d6cb044..0922369 100644
--- a/lightsoff/themes/tango/theme.js.in
+++ b/lightsoff/themes/tango/theme.js.in
@@ -8,6 +8,7 @@ var light = [ load_svg("off.svg"), load_svg("on.svg") ];
var arrow = load_svg("arrow.svg");
var backing = load_svg("backing.svg");
var led_back = load_svg("led-back.svg");
+var highlight = load_svg("highlight.svg");
// TODO: figure out how to fix this new offscreen cloning thing. this is a hack.
@@ -22,6 +23,7 @@ function map_stuff(a)
a.add_actor(arrow);
a.add_actor(backing);
a.add_actor(led_back);
+ a.add_actor(highlight);
a.show_all();
light[0].set_position(-500, -500);
@@ -29,6 +31,7 @@ function map_stuff(a)
arrow.set_position(-500, -500);
backing.set_position(-500, -500);
led_back.set_position(-500, -500);
+ highlight.set_position(-500, -500);
}
// helper functions should be put somewhere global
diff --git a/lightsoff/themes/up/Makefile.am b/lightsoff/themes/up/Makefile.am
index 831465f..605c997 100644
--- a/lightsoff/themes/up/Makefile.am
+++ b/lightsoff/themes/up/Makefile.am
@@ -5,6 +5,7 @@ theme_DATA = \
led-back.svg \
off.svg \
on.svg \
+ highlight.svg \
theme.js
EXTRA_DIST = \
@@ -13,4 +14,5 @@ EXTRA_DIST = \
led-back.svg \
off.svg \
on.svg \
+ highlight.svg \
theme.js.in
diff --git a/lightsoff/themes/up/highlight.svg b/lightsoff/themes/up/highlight.svg
new file mode 100644
index 0000000..a830854
--- /dev/null
+++ b/lightsoff/themes/up/highlight.svg
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="75"
+ height="75"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docname="highlight.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ version="1.0">
+ <defs
+ id="defs4">
+ <linearGradient
+ id="linearGradient3179">
+ <stop
+ style="stop-color:#35669b;stop-opacity:0.96078432;"
+ offset="0"
+ id="stop3181" />
+ <stop
+ style="stop-color:#5e92c8;stop-opacity:0.96078432;"
+ offset="1"
+ id="stop3183" />
+ </linearGradient>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ <filter
+ inkscape:collect="always"
+ id="filter3393"
+ x="-0.43563023"
+ width="1.8712605"
+ y="-0.43563023"
+ height="1.8712605">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="5.5324044"
+ id="feGaussianBlur3395" />
+ </filter>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#000000"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="1"
+ inkscape:pageshadow="2"
+ inkscape:zoom="8.76"
+ inkscape:cx="17.522831"
+ inkscape:cy="37.5"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1438"
+ inkscape:window-height="882"
+ inkscape:window-x="0"
+ inkscape:window-y="16" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-164.71428,-194.21933)">
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.64102568;fill:#ffffff;fill-opacity:1;stroke:none;stroke-opacity:1;filter:url(#filter3393)"
+ id="path3183"
+ sodipodi:cx="22.888128"
+ sodipodi:cy="25.285389"
+ sodipodi:rx="15.239726"
+ sodipodi:ry="15.239726"
+ d="M 38.127854,25.285389 A 15.239726,15.239726 0 1 1 7.6484022,25.285389 A 15.239726,15.239726 0 1 1 38.127854,25.285389 z"
+ transform="matrix(1.247191,0,0,1.247191,173.66841,200.18362)" />
+ </g>
+</svg>
diff --git a/lightsoff/themes/up/theme.js.in b/lightsoff/themes/up/theme.js.in
index efc097e..63ea95f 100644
--- a/lightsoff/themes/up/theme.js.in
+++ b/lightsoff/themes/up/theme.js.in
@@ -8,6 +8,7 @@ var light = [ load_svg("off.svg"), load_svg("on.svg") ];
var arrow = load_svg("arrow.svg");
var backing = load_svg("backing.svg");
var led_back = load_svg("led-back.svg");
+var highlight = load_svg("highlight.svg");
// TODO: figure out how to fix this new offscreen cloning thing. this is a hack.
@@ -22,6 +23,7 @@ function map_stuff(a)
a.add_actor(arrow);
a.add_actor(backing);
a.add_actor(led_back);
+ a.add_actor(highlight);
a.show_all();
light[0].set_position(-500, -500);
@@ -29,6 +31,7 @@ function map_stuff(a)
arrow.set_position(-500, -500);
backing.set_position(-500, -500);
led_back.set_position(-500, -500);
+ highlight.set_position(-500, -500);
}
// helper functions should be put somewhere global
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]