diff options
author | Gonzalo Odiard <godiard@gmail.com> | 2012-05-02 04:31:23 (GMT) |
---|---|---|
committer | Gonzalo Odiard <godiard@gmail.com> | 2012-05-02 04:31:23 (GMT) |
commit | 6d9cbdc157e0b7d0a0fdf807ec8dfb2d510f2edb (patch) | |
tree | 68d50bd790e210614e222c234811edf7ce997623 | |
parent | 86a0f2454fa3a9b255cabdcd3f7ab362746925d0 (diff) |
Start movement of character in play mode
Now the character does not walk all time left and right,
but wait to a click, and go to the place,
if the click is over a lateral wall or over a door, the character walk and later
the map change to the new selected vision.
Is not working all right now. When the character go to the left
the svg is not rendered. A posible solution using to ImageSurfaces
to cache te rendering is commented in character.py
Signed-off-by: Gonzalo Odiard <gonzalo@laptop.org>
-rw-r--r-- | character.py | 59 | ||||
-rw-r--r-- | mapnav.py | 96 | ||||
-rw-r--r-- | stateview.py | 3 |
3 files changed, 122 insertions, 36 deletions
diff --git a/character.py b/character.py index cf3c2ce..a4daa5c 100644 --- a/character.py +++ b/character.py @@ -1,3 +1,5 @@ +import logging + import gtk from gtk import gdk import gobject @@ -10,7 +12,7 @@ class Sprite(object): self.svg_file = svg_file self.cel_width, self.cel_height = cel_width, cel_height self.current_animation = None - self.flip_x = None + self.direction = 1 self._animation_data = animation_data self._current_data = None @@ -20,13 +22,30 @@ class Sprite(object): def load_svg(self): self._svg = rsvg.Handle(file=self.svg_file) - - def change_animation(self, animation_name, flip_x=1): + self._svg_width = self._svg.props.width + """ + # create a cache with the image rendered + self.cache = cairo.ImageSurface(cairo.FORMAT_ARGB32, + self._svg.props.width, self._svg.props.height) + self.cache_context = cairo.Context(self.cache) + self._svg.render_cairo(self.cache_context) + self.cache.flush() + + # and another with a flipped render + self.cache_inv = cairo.ImageSurface(cairo.FORMAT_ARGB32, + self._svg.props.width, self._svg.props.height) + self.cache_inv_context = cairo.Context(self.cache_inv) + self.cache_inv_context.scale(-1, 1) + self._svg.render_cairo(self.cache_inv_context) + self.cache_inv.flush() + """ + + def change_animation(self, animation_name, direction=1): self.current_animation = animation_name self._current_data = self._animation_data[animation_name] self._animation_index = 0 - self.flip_x = flip_x - if flip_x == -1: + #self.direction = direction + if self.direction == -1: self._current_data = list(reversed(self._current_data)) def next_frame(self): @@ -37,18 +56,22 @@ class Sprite(object): def draw(self, context, dx, dy): cel_x, cel_y = self._current_data[self._animation_index] - context.scale(self.flip_x, 1) - + context.scale(self.direction, 1) + #if self.direction == 1: + # context.set_source_surface(self.cache) + #else: + # context.set_source_surface(self.cache_inv) context.translate(dx, dy) - context.translate(-cel_x * self.cel_width * self.flip_x, + context.translate(-cel_x * self.cel_width * self.direction, -cel_y * self.cel_height) - context.rectangle(cel_x * self.cel_width * self.flip_x, + context.rectangle(cel_x * self.cel_width * self.direction, cel_y * self.cel_height, self.cel_width, self.cel_height) - if self.flip_x == -1: - context.translate(-900, 0) + if self.direction == -1: + context.translate(-self._svg_width, 0) context.clip() + #context.paint() self._svg.render_cairo(context) @@ -67,11 +90,12 @@ class Character(object): self.sprite.change_animation('walk') self.pos = [0, 0] - self.direction = -1 # -1 for left, 1 for right + self.direction = 1 # -1 for left, 1 for right def update(self): + self.sprite.direction = self.direction self.sprite.next_frame() - + """ if self.direction == 1 and self.pos[0] > 600: self.pos[0] += self.sprite.cel_width self.direction = -1 @@ -81,18 +105,19 @@ class Character(object): self.direction = 1 self.sprite.change_animation('walk') else: - self.pos[0] += self.speed * self.direction + """ + self.pos[0] += self.speed * self.direction return (self.pos[0], self.pos[1] - self.sprite.cel_height + 10, self.sprite.cel_width, self.sprite.cel_height) def draw(self, context): # draw char - dx, dy = self.pos[0], \ - self.pos[1] - self.sprite.cel_height + 10 + dx, dy = self.pos[0], self.pos[1] - self.sprite.cel_height + 10 # for debug write a rectangle around - context.rectangle(dx, dy, self.sprite.cel_width, self.sprite.cel_height) + context.rectangle(dx, dy, self.sprite.cel_width, + self.sprite.cel_height) stroke = (0, 0, 0) context.set_source_rgb(*stroke) context.stroke() @@ -70,12 +70,15 @@ class MapNavView(gtk.DrawingArea): self.connect('button_release_event', self.__button_release_event_cb) self._character = Character(self) + self._is_walking = False def size_allocate_cb(widget, allocation): self.calculate_sizes(allocation.width, allocation.height) if self.view_mode == self.MODE_PLAY: character_y = allocation.height - self._grid_size self._character.pos = [0, character_y] + self._character.direction = 1 + self._character.change_animation('stand', flip_x=1) self.disconnect(self._setup_handle) self._setup_handle = self.connect('size_allocate', @@ -85,13 +88,6 @@ class MapNavView(gtk.DrawingArea): if self.view_mode == self.MODE_PLAY: cell = style.GRID_CELL_SIZE / 2 self._state_view = StateView(self._model, cell, cell, cell) - gobject.timeout_add(100, self._update_timer) - - def _update_timer(self): - if self.is_drawable(): - rect = self._character.update() - self.queue_draw_area(*rect) - return True def clear_cache(self): self.cache_info = {} @@ -176,11 +172,70 @@ class MapNavView(gtk.DrawingArea): self.selected.y = event.y self.update_wall_info(self.x, self.y, self.direction) - if self.view_mode == self.MODE_EDIT: + if self.view_mode == self.MODE_PLAY and not self._is_walking: # verify doors + if info_walls['have_door'] != []: + door_x = self._get_door_x() + door_y = self._get_door_y() + door_width = self._grid_size * self._door_width + door_height = self._grid_size * self._door_height + if door_x < event.x < door_x + door_width and \ + door_y < event.y < door_y + door_height: + logging.error('Door clicked') + new_x, new_y, new_direction = self._game_map.cross_door( + self.x, self.y, self.direction) + self._move_character(door_x + door_width / 2, new_x, + new_y, new_direction) + # verify lateral walls + if event.x < self._grid_size: + logging.error('Left wall clicked') + new_x, new_y, new_direction = self._game_map.go_left(self.x, + self.y, self.direction) + self._move_character(0, new_x, new_y, new_direction) + + elif event.x > self._width - self._grid_size: + logging.error('Right wall clicked') + new_x, new_y, new_direction = self._game_map.go_right(self.x, + self.y, self.direction) + self._move_character(self._width, new_x, new_y, + new_direction) + else: + self._move_character(event.x, self.x, self.y, self.direction) + + def _move_character(self, character_destination, new_map_x, new_map_y, + new_map_direction): + """ + Move the character to the next position, + if needed, because the character is going to another wall or + to a door, change the map view position + """ + character_pos = self._character.pos[0] + if character_destination < character_pos: + self._character.direction = -1 + else: + self._character.direction = 1 + self._character_destination = character_destination + self._new_map_position = (new_map_x, new_map_y, new_map_direction) + gobject.timeout_add(100, self._update_timer) - # verify lateral doors - pass + def _update_timer(self): + self._is_walking = True + if self.is_drawable(): + rect = self._character.update() + self.queue_draw_area(*rect) + finish = abs(self._character_destination - self._character.pos[0]) < \ + self._character.speed + if finish: + self._is_walking = False + if (self.x, self.y, self.direction) != self._new_map_position: + self.x, self.y, self.direction = self._new_map_position + self.emit('position-changed', self.x, self.y, self.direction) + if self._character.pos[0] >= self._width - self._grid_size: + self._character.pos[0] = self._grid_size + elif self._character.pos[0] < self._grid_size: + self._character.pos[0] = self._width - self._grid_size + self.queue_draw() + return not finish def __motion_notify_event_cb(self, widget, event): if self.view_mode == self.MODE_EDIT: @@ -345,13 +400,8 @@ class MapNavView(gtk.DrawingArea): 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 * (self._door_width + 2) - else: - x = self._grid_size * 2 - - self.draw_door(ctx, x, info_walls['have_door']) + x_door = self._get_door_x() + self.draw_door(ctx, x_door, info_walls['have_door']) if info_walls['wall_cw']: ctx.move_to(self._width - self._grid_size, 0) @@ -446,8 +496,18 @@ class MapNavView(gtk.DrawingArea): RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE) ctx.stroke() + def _get_door_x(self): + if self.direction in ('N', 'W'): + # door is at rigth of the wall + return self._width - self._grid_size * (self._door_width + 2) + else: + return self._grid_size * 2 + + def _get_door_y(self): + return self._height - self._grid_size * (self._door_height + 1) + def draw_door(self, ctx, x, doors): - y = self._height - self._grid_size * (self._door_height + 1) + y = self._get_door_y() ctx.rectangle(x, y, self._grid_size * self._door_width, self._grid_size * self._door_height) fill = (style.Color('#8B6914').get_rgba()) diff --git a/stateview.py b/stateview.py index 931ea3f..3a6624b 100644 --- a/stateview.py +++ b/stateview.py @@ -11,6 +11,7 @@ import cairo import rsvg import model import math +import logging class StateView(): @@ -38,7 +39,7 @@ class StateView(): replied_questions = len(state['replied_questions']) scale = float(self._svg_width) / float(self._cell_size) - print "scale", scale + logging.error('draw stateview scale %s', scale) ctx.save() ctx.translate(self._x, self._y) for n in range(cant_questions): |