Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoshua Minor <j@lux.vu>2008-01-22 01:29:32 (GMT)
committer Joshua Minor <j@lux.vu>2008-01-22 01:29:32 (GMT)
commit365c204dc7b94001b99c11ec767ec2b242cc5d7a (patch)
treee639f4ed763d53221182b79e61e1e5142be694ee
parent96783a2e6b24a9c6485dde166a35be12c147cae7 (diff)
Fixed dirty rect problem that caused the game to slow way down when the players were far apart in the maze.
-rw-r--r--Maze.activity/activity/activity.info2
-rw-r--r--Maze.activity/game.py59
-rw-r--r--Maze.activity/olpcgames/__init__.pycbin1336 -> 0 bytes
-rw-r--r--Maze.activity/olpcgames/canvas.pycbin4253 -> 0 bytes
-rw-r--r--Maze.activity/olpcgames/tubeconn.py107
-rw-r--r--docs/NOTES.txt5
6 files changed, 41 insertions, 132 deletions
diff --git a/Maze.activity/activity/activity.info b/Maze.activity/activity/activity.info
index 818c1fb..315f177 100644
--- a/Maze.activity/activity/activity.info
+++ b/Maze.activity/activity/activity.info
@@ -3,5 +3,5 @@ name = Maze
service_name = vu.lux.olpc.Maze
class = activity.MazeActivity
icon = activity-maze
-activity_version = 3
+activity_version = 4
show_launcher = yes
diff --git a/Maze.activity/game.py b/Maze.activity/game.py
index d4562f5..f1ac957 100644
--- a/Maze.activity/game.py
+++ b/Maze.activity/game.py
@@ -104,6 +104,7 @@ class MazeGame:
player.reset()
self.goal = (self.maze.width-2, self.maze.height-2)
self.dirtyRect = None
+ self.dirtyPoints = []
# clear and mark the whole screen as dirty
self.screen.fill((0,0,0))
@@ -120,8 +121,7 @@ class MazeGame:
def markPointDirty(self, pt):
"""Mark a single point that needs to be redrawn."""
- rect = pygame.Rect(pt[0], pt[1], 1, 1)
- self.markRectDirty(rect)
+ self.dirtyPoints.append(pt)
def processEvent(self, event):
"""Process a single pygame event. This includes keystrokes
@@ -287,6 +287,8 @@ class MazeGame:
for player in self.players.values():
oldposition = player.position
+ if oldposition == self.goal:
+ break
newposition = player.animate(self.maze)
if oldposition != newposition:
self.markPointDirty(oldposition)
@@ -296,7 +298,8 @@ class MazeGame:
if newposition == self.goal:
self.finish()
- if self.finish_time is not None and time.time() > self.finish_time+5:
+ finish_delay = min(2 * len(self.players), 6)
+ if self.finish_time is not None and time.time() > self.finish_time+finish_delay:
self.harder()
def finish(self):
@@ -308,7 +311,7 @@ class MazeGame:
def draw(self):
"""Draw the current state of the game.
This makes use of the dirty rectangle to reduce CPU load."""
- if self.dirtyRect is None:
+ if self.dirtyRect is None and len(self.dirtyPoints)==0:
return
# compute the size of the tiles given the screen size, etc.
@@ -317,27 +320,36 @@ class MazeGame:
self.offsetX = (size[0] - self.tileSize * self.maze.width)/2
self.offsetY = (size[1] - self.tileSize * self.maze.height)/2
self.outline = int(self.tileSize/5)
+
+ def drawPoint(x,y):
+ rect = pygame.Rect(self.offsetX + x*self.tileSize, self.offsetY + y*self.tileSize, self.tileSize, self.tileSize)
+ if self.maze.map[x][y] == self.maze.EMPTY:
+ pygame.draw.rect(self.screen, self.EMPTY_COLOR, rect, 0)
+ elif self.maze.map[x][y] == self.maze.SOLID:
+ pygame.draw.rect(self.screen, self.SOLID_COLOR, rect, 0)
+ elif self.maze.map[x][y] == self.maze.SEEN:
+ pygame.draw.rect(self.screen, self.EMPTY_COLOR, rect, 0)
+ dot = rect.inflate(-self.outline*2, -self.outline*2)
+ pygame.draw.ellipse(self.screen, self.TRAIL_COLOR, dot, 0)
+ else:
+ pygame.draw.rect(self.screen, (0xff, 0x00, 0xff), rect, 0)
+
+ # re-draw the dirty rectangle
+ if self.dirtyRect is not None:
+ # compute the area that needs to be redrawn
+ left = max(0, self.dirtyRect.left)
+ right = min(self.maze.width, self.dirtyRect.right)
+ top = max(0, self.dirtyRect.top)
+ bottom = min(self.maze.height, self.dirtyRect.bottom)
- # compute the area that needs to be redrawn
- left = max(0, self.dirtyRect.left)
- right = min(self.maze.width, self.dirtyRect.right)
- top = max(0, self.dirtyRect.top)
- bottom = min(self.maze.height, self.dirtyRect.bottom)
+ # loop over the dirty rect and draw
+ for x in range(left, right):
+ for y in range(top, bottom):
+ drawPoint(x,y)
- # loop over the dirty rect and draw
- for x in range(left, right):
- for y in range(top, bottom):
- rect = pygame.Rect(self.offsetX + x*self.tileSize, self.offsetY + y*self.tileSize, self.tileSize, self.tileSize)
- if self.maze.map[x][y] == self.maze.EMPTY:
- pygame.draw.rect(self.screen, self.EMPTY_COLOR, rect, 0)
- elif self.maze.map[x][y] == self.maze.SOLID:
- pygame.draw.rect(self.screen, self.SOLID_COLOR, rect, 0)
- elif self.maze.map[x][y] == self.maze.SEEN:
- pygame.draw.rect(self.screen, self.EMPTY_COLOR, rect, 0)
- dot = rect.inflate(-self.outline*2, -self.outline*2)
- pygame.draw.ellipse(self.screen, self.TRAIL_COLOR, dot, 0)
- else:
- pygame.draw.rect(self.screen, (0xff, 0x00, 0xff), rect, 0)
+ # re-draw the dirty points
+ for x,y in self.dirtyPoints:
+ drawPoint(x,y)
# draw the goal
rect = self.offsetX+self.goal[0]*self.tileSize, self.offsetY+self.goal[1]*self.tileSize, self.tileSize, self.tileSize
@@ -371,6 +383,7 @@ class MazeGame:
# clear the dirty rect so nothing will be drawn until there is a change
self.dirtyRect = None
+ self.dirtyPoints = []
def drawPlayer(self, player):
fg, bg = player.colors
diff --git a/Maze.activity/olpcgames/__init__.pyc b/Maze.activity/olpcgames/__init__.pyc
deleted file mode 100644
index 4f2a40c..0000000
--- a/Maze.activity/olpcgames/__init__.pyc
+++ /dev/null
Binary files differ
diff --git a/Maze.activity/olpcgames/canvas.pyc b/Maze.activity/olpcgames/canvas.pyc
deleted file mode 100644
index dc37e8c..0000000
--- a/Maze.activity/olpcgames/canvas.pyc
+++ /dev/null
Binary files differ
diff --git a/Maze.activity/olpcgames/tubeconn.py b/Maze.activity/olpcgames/tubeconn.py
deleted file mode 100644
index d1c1403..0000000
--- a/Maze.activity/olpcgames/tubeconn.py
+++ /dev/null
@@ -1,107 +0,0 @@
-# This should eventually land in telepathy-python, so has the same license:
-
-# Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published
-# by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-__all__ = ('TubeConnection',)
-__docformat__ = 'reStructuredText'
-
-
-import logging
-
-from dbus.connection import Connection
-
-
-logger = logging.getLogger('telepathy.tubeconn')
-
-
-class TubeConnection(Connection):
-
- def __new__(cls, conn, tubes_iface, tube_id, address=None,
- group_iface=None, mainloop=None):
- if address is None:
- address = tubes_iface.GetDBusServerAddress(tube_id)
- self = super(TubeConnection, cls).__new__(cls, address,
- mainloop=mainloop)
-
- self._tubes_iface = tubes_iface
- self.tube_id = tube_id
- self.participants = {}
- self.bus_name_to_handle = {}
- self._mapping_watches = []
-
- if group_iface is None:
- method = conn.GetSelfHandle
- else:
- method = group_iface.GetSelfHandle
- method(reply_handler=self._on_get_self_handle_reply,
- error_handler=self._on_get_self_handle_error)
-
- return self
-
- def _on_get_self_handle_reply(self, handle):
- self.self_handle = handle
- match = self._tubes_iface.connect_to_signal('DBusNamesChanged',
- self._on_dbus_names_changed)
- self._tubes_iface.GetDBusNames(self.tube_id,
- reply_handler=self._on_get_dbus_names_reply,
- error_handler=self._on_get_dbus_names_error)
- self._dbus_names_changed_match = match
-
- def _on_get_self_handle_error(self, e):
- logging.basicConfig()
- logger.error('GetSelfHandle failed: %s', e)
-
- def close(self):
- self._dbus_names_changed_match.remove()
- self._on_dbus_names_changed(self.tube_id, (), self.participants.keys())
- super(TubeConnection, self).close()
-
- def _on_get_dbus_names_reply(self, names):
- self._on_dbus_names_changed(self.tube_id, names, ())
-
- def _on_get_dbus_names_error(self, e):
- logging.basicConfig()
- logger.error('GetDBusNames failed: %s', e)
-
- def _on_dbus_names_changed(self, tube_id, added, removed):
- if tube_id == self.tube_id:
- for handle, bus_name in added:
- if handle == self.self_handle:
- # I've just joined - set my unique name
- self.set_unique_name(bus_name)
- self.participants[handle] = bus_name
- self.bus_name_to_handle[bus_name] = handle
-
- # call the callback while the removed people are still in
- # participants, so their bus names are available
- for callback in self._mapping_watches:
- callback(added, removed)
-
- for handle in removed:
- bus_name = self.participants.pop(handle, None)
- self.bus_name_to_handle.pop(bus_name, None)
-
- def watch_participants(self, callback):
- self._mapping_watches.append(callback)
- if self.participants:
- # GetDBusNames already returned: fake a participant add event
- # immediately
- added = []
- for k, v in self.participants.iteritems():
- added.append((k, v))
- callback(added, [])
diff --git a/docs/NOTES.txt b/docs/NOTES.txt
index 32f8981..610fa3b 100644
--- a/docs/NOTES.txt
+++ b/docs/NOTES.txt
@@ -10,9 +10,12 @@ Collaboration:
The first one to the goal "wins"
When one player reaches the end, all players jump to the next maze.
+Bugs:
+ [done] Support multiple dirty-rects to avoid performance hit when players are far apart.
+
Enhancements:
Show XO buddy icons instead of colored dots (only for easy mazes, when icons are large).
- Measure time-to-goal and rank players to formalize the winning condition.
+ [done] Measure time-to-goal and rank players to formalize the winning condition.
Separate easy/hard from small/large maze.
Easy mazes could have extra holes punched in them to make for multiple solutions.
Different maze-building algorithms