annotate mamba/widgets/level.py @ 555:c014f5023cd2

Test run replays
author Neil Muller <drnlmuller@gmail.com>
date Thu, 22 Sep 2011 17:32:38 +0200
parents b308ebaa96f3
children 03c0f1f5488c
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
21
f76c3f033772 Release early, release broken. Level stuff.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
1 from pygame.rect import Rect
172
dabf13abb3fd Add basic drawing to level editor
Neil Muller <drnlmuller@gmail.com>
parents: 120
diff changeset
2 from pygame.locals import MOUSEBUTTONDOWN, MOUSEBUTTONUP, MOUSEMOTION
551
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
3 from pygame.key import set_repeat
21
f76c3f033772 Release early, release broken. Level stuff.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
4
23
d0e8940df703 Widgets -> base
Stefano Rivera <stefano@rivera.za.net>
parents: 21
diff changeset
5 from mamba.widgets.base import Widget
172
dabf13abb3fd Add basic drawing to level editor
Neil Muller <drnlmuller@gmail.com>
parents: 120
diff changeset
6 from mamba.constants import TILE_SIZE
551
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
7 from mamba.snake import Snake
555
c014f5023cd2 Test run replays
Neil Muller <drnlmuller@gmail.com>
parents: 554
diff changeset
8 from mamba.engine import FlipArrowsEvent, ReplayEvent
21
f76c3f033772 Release early, release broken. Level stuff.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
9
f76c3f033772 Release early, release broken. Level stuff.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
10
120
6b1cdbdd34ca Rename LevelWidget
Neil Muller <drnlmuller@gmail.com>
parents: 119
diff changeset
11 class EditLevelWidget(Widget):
21
f76c3f033772 Release early, release broken. Level stuff.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
12 def __init__(self, level, offset=(0, 0)):
50
1b725035b8ef Levels that are visible.
Jeremy Thurgood <firxen@gmail.com>
parents: 24
diff changeset
13 self.level = level
21
f76c3f033772 Release early, release broken. Level stuff.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
14 level_rect = Rect(offset, level.get_size())
264
2c9cc902928f Right-click to erase in the level editor.
Jeremy Thurgood <firxen@gmail.com>
parents: 173
diff changeset
15 self.main_tool = None
172
dabf13abb3fd Add basic drawing to level editor
Neil Muller <drnlmuller@gmail.com>
parents: 120
diff changeset
16 self.tool = None
dabf13abb3fd Add basic drawing to level editor
Neil Muller <drnlmuller@gmail.com>
parents: 120
diff changeset
17 self.drawing = False
337
170d4a43c00e Don't edit the level when interacting with dialogs
Neil Muller <drnlmuller@gmail.com>
parents: 272
diff changeset
18 self.last_click_pos = None
170d4a43c00e Don't edit the level when interacting with dialogs
Neil Muller <drnlmuller@gmail.com>
parents: 272
diff changeset
19 self.tile_mode = True # Flag for sprite interactions
120
6b1cdbdd34ca Rename LevelWidget
Neil Muller <drnlmuller@gmail.com>
parents: 119
diff changeset
20 super(EditLevelWidget, self).__init__(level_rect)
337
170d4a43c00e Don't edit the level when interacting with dialogs
Neil Muller <drnlmuller@gmail.com>
parents: 272
diff changeset
21 self.add_callback(MOUSEBUTTONDOWN, self.place_tile)
170d4a43c00e Don't edit the level when interacting with dialogs
Neil Muller <drnlmuller@gmail.com>
parents: 272
diff changeset
22 self.add_callback(MOUSEBUTTONUP, self.end_draw)
170d4a43c00e Don't edit the level when interacting with dialogs
Neil Muller <drnlmuller@gmail.com>
parents: 272
diff changeset
23 self.add_callback(MOUSEMOTION, self.draw_tiles)
551
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
24 self.add_callback(FlipArrowsEvent, self.flip_arrows)
555
c014f5023cd2 Test run replays
Neil Muller <drnlmuller@gmail.com>
parents: 554
diff changeset
25 self.add_callback(ReplayEvent, self.handle_replay)
551
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
26 self.snake = None
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
27 self.snake_alive = False
555
c014f5023cd2 Test run replays
Neil Muller <drnlmuller@gmail.com>
parents: 554
diff changeset
28 self.replay_data = []
c014f5023cd2 Test run replays
Neil Muller <drnlmuller@gmail.com>
parents: 554
diff changeset
29 self.last_run = []
c014f5023cd2 Test run replays
Neil Muller <drnlmuller@gmail.com>
parents: 554
diff changeset
30 self.replay_pos = 0
c014f5023cd2 Test run replays
Neil Muller <drnlmuller@gmail.com>
parents: 554
diff changeset
31
c014f5023cd2 Test run replays
Neil Muller <drnlmuller@gmail.com>
parents: 554
diff changeset
32 def get_replay(self):
c014f5023cd2 Test run replays
Neil Muller <drnlmuller@gmail.com>
parents: 554
diff changeset
33 return self.replay_data[:]
c014f5023cd2 Test run replays
Neil Muller <drnlmuller@gmail.com>
parents: 554
diff changeset
34
c014f5023cd2 Test run replays
Neil Muller <drnlmuller@gmail.com>
parents: 554
diff changeset
35 def replay(self, run=None):
c014f5023cd2 Test run replays
Neil Muller <drnlmuller@gmail.com>
parents: 554
diff changeset
36 if run is None:
c014f5023cd2 Test run replays
Neil Muller <drnlmuller@gmail.com>
parents: 554
diff changeset
37 # We exclude the last couple of steps, so we don't redo
c014f5023cd2 Test run replays
Neil Muller <drnlmuller@gmail.com>
parents: 554
diff changeset
38 # the final crash in this run
c014f5023cd2 Test run replays
Neil Muller <drnlmuller@gmail.com>
parents: 554
diff changeset
39 run = self.last_run[:-4]
c014f5023cd2 Test run replays
Neil Muller <drnlmuller@gmail.com>
parents: 554
diff changeset
40 if len(run) > 0:
c014f5023cd2 Test run replays
Neil Muller <drnlmuller@gmail.com>
parents: 554
diff changeset
41 self.start_test()
c014f5023cd2 Test run replays
Neil Muller <drnlmuller@gmail.com>
parents: 554
diff changeset
42 ReplayEvent.post(run, 0)
c014f5023cd2 Test run replays
Neil Muller <drnlmuller@gmail.com>
parents: 554
diff changeset
43
c014f5023cd2 Test run replays
Neil Muller <drnlmuller@gmail.com>
parents: 554
diff changeset
44 def handle_replay(self, ev, widget):
c014f5023cd2 Test run replays
Neil Muller <drnlmuller@gmail.com>
parents: 554
diff changeset
45 self.apply_action(ev.run[ev.replay_pos])
c014f5023cd2 Test run replays
Neil Muller <drnlmuller@gmail.com>
parents: 554
diff changeset
46 if ev.replay_pos < len(ev.run) - 1:
c014f5023cd2 Test run replays
Neil Muller <drnlmuller@gmail.com>
parents: 554
diff changeset
47 ReplayEvent.post(ev.run, ev.replay_pos + 1)
551
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
48
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
49 def start_test(self):
554
b308ebaa96f3 Save tiles before starting test.
Simon Cross <hodgestar@gmail.com>
parents: 551
diff changeset
50 self.level.update_tiles_ascii()
555
c014f5023cd2 Test run replays
Neil Muller <drnlmuller@gmail.com>
parents: 554
diff changeset
51 self.last_run = self.replay_data
c014f5023cd2 Test run replays
Neil Muller <drnlmuller@gmail.com>
parents: 554
diff changeset
52 self.replay_data = []
551
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
53 self.level.restart()
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
54 tile_pos, orientation = self.level.get_entry()
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
55 self.snake = Snake(tile_pos, orientation)
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
56 set_repeat(40, 100)
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
57 self.snake_alive = True
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
58
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
59 def stop_test(self):
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
60 self.snake = None
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
61 self.snake_alive = False
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
62 self.level.restart()
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
63 set_repeat(0, 0)
21
f76c3f033772 Release early, release broken. Level stuff.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
64
24
30d4f3e62bcf Refactor widgets *again*, add container to Habitat
Stefano Rivera <stefano@rivera.za.net>
parents: 23
diff changeset
65 def draw(self, surface):
110
e6299eb296ce Draw the world!
Simon Cross <hodgestar@gmail.com>
parents: 81
diff changeset
66 self.level.draw(surface)
551
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
67 if self.snake:
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
68 self.snake.draw(surface)
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
69
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
70 def kill_snake(self):
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
71 """Prevent user interaction while snake is dead"""
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
72 self.snake_alive = False
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
73
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
74 def restart(self):
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
75 self.start_test()
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
76
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
77 def interact(self, segment):
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
78 if not self.snake or not self.snake_alive:
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
79 return
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
80 tiles = segment.filter_collisions(self.level.sprites)
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
81 for tile in tiles:
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
82 tile.interact(self, segment)
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
83
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
84 def get_sprite(self, sprite_id):
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
85 return self.level.extra_sprites[sprite_id]
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
86
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
87 def apply_action(self, orientation):
555
c014f5023cd2 Test run replays
Neil Muller <drnlmuller@gmail.com>
parents: 554
diff changeset
88 self.replay_data.append(orientation)
551
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
89 if not self.snake or not self.snake_alive:
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
90 return
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
91 # We choose numbers that are close to, but not exactly, move 0.5 tiles
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
92 # to avoid a couple of rounding corner cases in the snake code
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
93 if orientation is None or orientation == self.snake.orientation:
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
94 self.snake.update(9.99 / self.snake.speed, self)
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
95 else:
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
96 self.snake.send_new_direction(orientation)
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
97 self.snake.update(9.99 / self.snake.speed, self)
21
f76c3f033772 Release early, release broken. Level stuff.
Jeremy Thurgood <firxen@gmail.com>
parents:
diff changeset
98
172
dabf13abb3fd Add basic drawing to level editor
Neil Muller <drnlmuller@gmail.com>
parents: 120
diff changeset
99 def set_tool(self, new_tool):
264
2c9cc902928f Right-click to erase in the level editor.
Jeremy Thurgood <firxen@gmail.com>
parents: 173
diff changeset
100 self.main_tool = new_tool
172
dabf13abb3fd Add basic drawing to level editor
Neil Muller <drnlmuller@gmail.com>
parents: 120
diff changeset
101 self.tool = new_tool
dabf13abb3fd Add basic drawing to level editor
Neil Muller <drnlmuller@gmail.com>
parents: 120
diff changeset
102
337
170d4a43c00e Don't edit the level when interacting with dialogs
Neil Muller <drnlmuller@gmail.com>
parents: 272
diff changeset
103 def end_draw(self, event, widget):
170d4a43c00e Don't edit the level when interacting with dialogs
Neil Muller <drnlmuller@gmail.com>
parents: 272
diff changeset
104 self.drawing = False
170d4a43c00e Don't edit the level when interacting with dialogs
Neil Muller <drnlmuller@gmail.com>
parents: 272
diff changeset
105
170d4a43c00e Don't edit the level when interacting with dialogs
Neil Muller <drnlmuller@gmail.com>
parents: 272
diff changeset
106 def draw_tiles(self, event, widget):
170d4a43c00e Don't edit the level when interacting with dialogs
Neil Muller <drnlmuller@gmail.com>
parents: 272
diff changeset
107 if self.drawing and self.tool:
170d4a43c00e Don't edit the level when interacting with dialogs
Neil Muller <drnlmuller@gmail.com>
parents: 272
diff changeset
108 # FIXME: Need to consider leaving and re-entering the widget
170d4a43c00e Don't edit the level when interacting with dialogs
Neil Muller <drnlmuller@gmail.com>
parents: 272
diff changeset
109 self.update_tile(self.convert_pos(event.pos))
170d4a43c00e Don't edit the level when interacting with dialogs
Neil Muller <drnlmuller@gmail.com>
parents: 272
diff changeset
110
551
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
111 def flip_arrows(self, ev, widget):
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
112 self.level.flip_arrows()
9d3ed4d05f55 Hack in test level mode to editor
Neil Muller <drnlmuller@gmail.com>
parents: 337
diff changeset
113
337
170d4a43c00e Don't edit the level when interacting with dialogs
Neil Muller <drnlmuller@gmail.com>
parents: 272
diff changeset
114 def place_tile(self, event, widget):
170d4a43c00e Don't edit the level when interacting with dialogs
Neil Muller <drnlmuller@gmail.com>
parents: 272
diff changeset
115 if self.tile_mode:
264
2c9cc902928f Right-click to erase in the level editor.
Jeremy Thurgood <firxen@gmail.com>
parents: 173
diff changeset
116 if event.button == 1: # Left button
2c9cc902928f Right-click to erase in the level editor.
Jeremy Thurgood <firxen@gmail.com>
parents: 173
diff changeset
117 self.tool = self.main_tool
2c9cc902928f Right-click to erase in the level editor.
Jeremy Thurgood <firxen@gmail.com>
parents: 173
diff changeset
118 else:
2c9cc902928f Right-click to erase in the level editor.
Jeremy Thurgood <firxen@gmail.com>
parents: 173
diff changeset
119 self.tool = '.'
172
dabf13abb3fd Add basic drawing to level editor
Neil Muller <drnlmuller@gmail.com>
parents: 120
diff changeset
120 self.drawing = True
272
a061dd62127c Hook up load and new buttons
Neil Muller <drnlmuller@gmail.com>
parents: 264
diff changeset
121 if self.tool:
337
170d4a43c00e Don't edit the level when interacting with dialogs
Neil Muller <drnlmuller@gmail.com>
parents: 272
diff changeset
122 self.update_tile(self.convert_pos(event.pos))
170d4a43c00e Don't edit the level when interacting with dialogs
Neil Muller <drnlmuller@gmail.com>
parents: 272
diff changeset
123 else:
170d4a43c00e Don't edit the level when interacting with dialogs
Neil Muller <drnlmuller@gmail.com>
parents: 272
diff changeset
124 self.last_click_pos = self.convert_pos(event.pos)
172
dabf13abb3fd Add basic drawing to level editor
Neil Muller <drnlmuller@gmail.com>
parents: 120
diff changeset
125 self.drawing = False
337
170d4a43c00e Don't edit the level when interacting with dialogs
Neil Muller <drnlmuller@gmail.com>
parents: 272
diff changeset
126
170d4a43c00e Don't edit the level when interacting with dialogs
Neil Muller <drnlmuller@gmail.com>
parents: 272
diff changeset
127 def convert_pos(self, pos):
170d4a43c00e Don't edit the level when interacting with dialogs
Neil Muller <drnlmuller@gmail.com>
parents: 272
diff changeset
128 return (pos[0] / TILE_SIZE[0], pos[1] / TILE_SIZE[1])
172
dabf13abb3fd Add basic drawing to level editor
Neil Muller <drnlmuller@gmail.com>
parents: 120
diff changeset
129
337
170d4a43c00e Don't edit the level when interacting with dialogs
Neil Muller <drnlmuller@gmail.com>
parents: 272
diff changeset
130 def update_tile(self, tile_pos):
172
dabf13abb3fd Add basic drawing to level editor
Neil Muller <drnlmuller@gmail.com>
parents: 120
diff changeset
131 """Update the tile at the current mouse position"""
337
170d4a43c00e Don't edit the level when interacting with dialogs
Neil Muller <drnlmuller@gmail.com>
parents: 272
diff changeset
132 if self.check_paused():
170d4a43c00e Don't edit the level when interacting with dialogs
Neil Muller <drnlmuller@gmail.com>
parents: 272
diff changeset
133 return # Do nothing if dialogs showing
172
dabf13abb3fd Add basic drawing to level editor
Neil Muller <drnlmuller@gmail.com>
parents: 120
diff changeset
134 # We convert our current position into a tile position
dabf13abb3fd Add basic drawing to level editor
Neil Muller <drnlmuller@gmail.com>
parents: 120
diff changeset
135 # and replace the tile with the current tool
173
71911af9d42d Refactor drawing code. Correct tile variants when painting
Neil Muller <drnlmuller@gmail.com>
parents: 172
diff changeset
136 old_tile = self.level.get_tile(tile_pos)
172
dabf13abb3fd Add basic drawing to level editor
Neil Muller <drnlmuller@gmail.com>
parents: 120
diff changeset
137 if self.tool == '.' and old_tile is None:
dabf13abb3fd Add basic drawing to level editor
Neil Muller <drnlmuller@gmail.com>
parents: 120
diff changeset
138 return
dabf13abb3fd Add basic drawing to level editor
Neil Muller <drnlmuller@gmail.com>
parents: 120
diff changeset
139 elif old_tile is not None and old_tile.tile_char == self.tool:
dabf13abb3fd Add basic drawing to level editor
Neil Muller <drnlmuller@gmail.com>
parents: 120
diff changeset
140 return
173
71911af9d42d Refactor drawing code. Correct tile variants when painting
Neil Muller <drnlmuller@gmail.com>
parents: 172
diff changeset
141 self.level.replace_tile(tile_pos, self.tool)
337
170d4a43c00e Don't edit the level when interacting with dialogs
Neil Muller <drnlmuller@gmail.com>
parents: 272
diff changeset
142
170d4a43c00e Don't edit the level when interacting with dialogs
Neil Muller <drnlmuller@gmail.com>
parents: 272
diff changeset
143 def check_paused(self):
170d4a43c00e Don't edit the level when interacting with dialogs
Neil Muller <drnlmuller@gmail.com>
parents: 272
diff changeset
144 return hasattr(self.parent, 'paused') and self.parent.paused