diff options
author | Gonzalo Odiard <godiard@gmail.com> | 2012-02-06 00:53:00 (GMT) |
---|---|---|
committer | Gonzalo Odiard <godiard@gmail.com> | 2012-02-06 00:53:00 (GMT) |
commit | 952583926af90301cfee57c19cf72f4de9954598 (patch) | |
tree | ad6c0203329b8ff64144e8a6e2bee52a4be42e26 /mapnav.py | |
parent | f38aa41dc7e7553b7cd3d5c2b0ce744dd1262e77 (diff) |
Add a class to test basic navigation in the map
Signed-off-by: Gonzalo Odiard <gonzalo@laptop.org>
Diffstat (limited to 'mapnav.py')
-rw-r--r-- | mapnav.py | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/mapnav.py b/mapnav.py new file mode 100644 index 0000000..7324230 --- /dev/null +++ b/mapnav.py @@ -0,0 +1,208 @@ +#!/usr/bin/env python +# Copyright (C) 2012, One Laptop Per Child +# Author, Gonzalo Odiard +# License: LGPLv2 +# +# The class MapNavView draw a map from the top + +import gtk +import gobject +import cairo +import logging + +from game_map import GameMap +from mapview import TopMapView + + +class MapNavView(gtk.DrawingArea): + + __gsignals__ = {'position-changed': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, + ([gobject.TYPE_INT, gobject.TYPE_INT, + gobject.TYPE_STRING]))} + + def __init__(self, game_map): + self._game_map = game_map + self.x = 0 + self.y = 0 + self.direction = 'S' + self.cache_info = {} + + super(MapNavView, self).__init__() + self.set_can_focus(True) + self.add_events(gtk.gdk.KEY_PRESS_MASK) + self.connect('expose_event', self.expose) + self.connect('key-press-event', self._key_press_event_cb) + + def _key_press_event_cb(self, widget, event): + keyname = gtk.gdk.keyval_name(event.keyval) + if keyname not in ('Up', 'KP_Up', 'Down', 'KP_Down', 'Left', 'KP_Left', + 'Right', 'KP_Right'): + return False + + x, y = self.x, self.y + info_walls = self.get_information_walls(x, y, self.direction) + + new_x, new_y, new_direction = self.x, self.y, self.direction + if keyname == 'Up' or keyname == 'KP_Up': + new_x, new_y, new_direction = \ + self._game_map.cross_door(x, y, self.direction) + + elif keyname == 'Down' or keyname == 'KP_Down': + reversed_direction = \ + self._game_map.get_reversed_direction(self.direction) + wall_info = self._game_map.get_wall_info(x, y, reversed_direction) + if wall_info is None or self._game_map.have_door(wall_info): + new_x, new_y, new_direction = \ + self._game_map.cross_door(x, y, reversed_direction) + new_direction = self.direction + if self._game_map.get_wall_info(new_x, new_y, new_direction) \ + is None: + new_x, new_y, new_direction = \ + self._game_map.go_forward(new_x, new_y, new_direction) + + elif keyname == 'Right' or keyname == 'KP_Right': + new_x, new_y, new_direction = \ + self._game_map.go_right(self.x, self.y, self.direction) + + elif keyname == 'Left' or keyname == 'KP_Left': + new_x, new_y, new_direction = \ + self._game_map.go_left(self.x, self.y, self.direction) + if (new_x, new_y, new_direction) != (self.x, self.y, self.direction): + self.x, self.y, self.direction = new_x, new_y, new_direction + self.emit('position-changed', self.x, self.y, self.direction) + self.queue_draw() + return True + + def calculate_sizes(self, width, height): + self._width = width + self._height = height + # used as unity 1/10 of the height + self._grid_size = self._height / 10 + # the door is 3 units width and 8 unit shight + self._door_width = self._grid_size * 3 + self._door_height = self._grid_size * 8 + + def expose(self, widget, event): + rect = self.get_allocation() + self.calculate_sizes(rect.width, rect.height) + ctx = widget.window.cairo_create() + # set a clip region for the expose event + ctx.rectangle(event.area.x, event.area.y, event.area.width, + event.area.height) + ctx.clip() + self.draw(ctx) + return False + + def get_information_walls(self, x, y, direction): + key = str(x) + direction + str(y) + if key in self.cache_info: + return self.cache_info[key] + else: + # have door? + wall_info = self._game_map.get_wall_info(x, y, direction) + have_door = self._game_map.have_door(wall_info) + # there are a page at cw direction? + cw_direction = self._game_map.get_direction_cw(direction) + wall_cw = self._game_map.get_wall_info(x, y, cw_direction) is \ + not None + # there are a page at ccw direction? + ccw_direction = self._game_map.get_direction_ccw(direction) + wall_ccw = self._game_map.get_wall_info(x, y, ccw_direction) is \ + not None + info = {'have_door': have_door, 'wall_cw': wall_cw, + 'wall_ccw': wall_ccw} + self.cache_info[key] = info + return info + + def draw(self, ctx): + x, y = self.x, self.y + info_walls = self.get_information_walls(x, y, self.direction) + # draw back wall + ctx.rectangle(0, 0, self._width, self._height - self._grid_size) + fill = (1, 1, 1) + stroke = (0, 0, 0) + ctx.set_source_rgb(*fill) + ctx.fill_preserve() + ctx.set_source_rgb(*stroke) + ctx.stroke() + + # draw floor + + ctx.rectangle(0, self._height - self._grid_size, self._width, + self._grid_size) + fill = (0, 0, 0) + stroke = (1, 1, 1) + ctx.set_source_rgb(*fill) + ctx.fill_preserve() + ctx.set_source_rgb(*stroke) + ctx.stroke() + + if info_walls['have_door']: + if self.direction in ('N', 'W'): + # door is at rigth of the wall + x = self._width - self._grid_size * 5 + else: + x = self._grid_size * 2 + + ctx.rectangle(x, self._grid_size * 3, self._grid_size * 3, + self._grid_size * 6) + fill = (0, 0, 0) + stroke = (0, 0, 0) + ctx.set_source_rgb(*fill) + ctx.fill_preserve() + ctx.set_source_rgb(*stroke) + ctx.stroke() + + if info_walls['wall_cw']: + ctx.move_to(self._width - self._grid_size, 0) + ctx.line_to(self._width, 0) + ctx.line_to(self._width, self._height) + ctx.line_to(self._width - self._grid_size, + self._height - self._grid_size) + ctx.close_path() + fill = (1, 1, 1) + stroke = (0, 0, 0) + ctx.set_source_rgb(*fill) + ctx.fill_preserve() + ctx.set_source_rgb(*stroke) + ctx.stroke() + + if info_walls['wall_ccw']: + ctx.move_to(0, 0) + ctx.line_to(self._grid_size, 0) + ctx.line_to(self._grid_size, + self._height - self._grid_size) + ctx.line_to(0, self._height) + ctx.close_path() + fill = (1, 1, 1) + stroke = (0, 0, 0) + ctx.set_source_rgb(*fill) + ctx.fill_preserve() + ctx.set_source_rgb(*stroke) + ctx.stroke() + + +def show_position(nav_view, x, y, direction, top_view): + top_view.show_position(x, y, direction) + + +def main(): + window = gtk.Window() + game_map = GameMap() + nav_view = MapNavView(game_map) + top_view = TopMapView(game_map, 200, 200) + top_view.show_position(nav_view.x, nav_view.y, nav_view.direction) + nav_view.connect('position-changed', show_position, top_view) + hbox = gtk.HBox() + hbox.pack_start(nav_view, True, True) + hbox.pack_start(top_view, False, False) + window.add(hbox) + nav_view.grab_focus() + window.connect("destroy", gtk.main_quit) + window.set_default_size(800, 600) + window.show_all() + gtk.main() + +if __name__ == "__main__": + main() |