comparison gamelib/loadlevel.py @ 532:0667189a5973

New load level dialog.
author Simon Cross <hodgestar@gmail.com>
date Fri, 27 Nov 2009 21:28:20 +0000
parents 3a8a64bbe2d8
children
comparison
equal deleted inserted replaced
531:452cde9af2a2 532:0667189a5973
2 2
3 from pgu import gui 3 from pgu import gui
4 import os 4 import os
5 import pygame 5 import pygame
6 import level 6 import level
7 import engine
8 import data 7 import data
9 import imagecache
10 import gameboard 8 import gameboard
11 import constants 9 import constants
12 10
13 def make_load_screen(level):
14 """Create a screen for selecting the levels"""
15 load_screen = LoadScreen(level, width=600)
16 11
17 c = LoadContainer(align=0, valign=0) 12 class LoadLevelDialog(gui.Dialog):
18 c.add(load_screen, 0, 0) 13 """Load level dialog."""
19 14
20 return c, load_screen 15 def __init__(self, curr_level, load_func, cls="dialog"):
16 self.value = None
17 self.levels = self._populate_levels()
21 18
22 class LoadContainer(gui.Container): 19 self.main_style = {
23 def paint(self, s): 20 'width': 300, 'height': 350
24 pygame.display.set_caption('Load Level') 21 }
25 splash = imagecache.load_image("images/splash.png", ["lighten_most"])
26 pygame.display.get_surface().blit(splash, (0, 0))
27 gui.Container.paint(self, s)
28 22
29 class LoadScreen(gui.Document): 23 td_style = {
30 def __init__(self, start_level, **params): 24 'padding_left': 4,
31 gui.Document.__init__(self, **params) 25 'padding_right': 4,
26 'padding_top': 2,
27 'padding_bottom': 2,
28 }
32 29
33 self.levels = [] 30 self.level_list = gui.List(**self.main_style)
34 self.cur_level = None 31 level_names = self.levels.keys()
32 level_names.sort()
33 for name in level_names:
34 self.level_list.add(name, value=name)
35 self.level_list.set_vertical_scroll(0)
36 self.level_list.connect(gui.CHANGE, self._level_list_change)
37
38 self.image_container = gui.Container()
39
40 button_ok = gui.Button("Load Level")
41 button_ok.connect(gui.CLICK, self._click_ok)
42
43 button_cancel = gui.Button("Cancel")
44 button_cancel.connect(gui.CLICK, self._click_cancel)
45
46 body = gui.Table()
47 body.tr()
48 list_style = dict(self.main_style)
49 list_style.update(td_style)
50 body.td(self.level_list, style=list_style, valign=-1, rowspan=2)
51 body.td(self.image_container, style=td_style, colspan=2)
52 body.tr()
53 # putting in the extra spacer squashes the ok and cancel button
54 # up nicely
55 body.td(gui.Spacer(0, 0), style=td_style)
56 body.td(button_ok, style=td_style, align=1)
57 body.td(button_cancel, style=td_style, align=1)
58
59 title = gui.Label("Load Level ...", cls=cls + ".title.label")
60 gui.Dialog.__init__(self, title, body)
61
62 if curr_level.level_name in self.levels:
63 self.level_list.group.value = curr_level.level_name
64 elif level_names:
65 self.level_list.group.value = level_names[0]
66
67 self.connect(gui.CHANGE, self._load_level, load_func)
68
69 def _populate_levels(self):
70 """Read list of levels from disk."""
71 levels = {}
35 for name in os.listdir(data.filepath('levels/')): 72 for name in os.listdir(data.filepath('levels/')):
36 if name.endswith('.conf'): 73 if not name.endswith('.conf'):
37 try: 74 continue
38 this_level = level.Level(name) 75 try:
39 except RuntimeError: 76 this_level = level.Level(name)
40 continue # Skip levels that fail to load 77 except RuntimeError:
41 if os.path.exists(this_level.map): 78 # Skip levels that fail to load
42 # Skip level if we can't see the map 79 continue
43 self.levels.append(this_level) 80 if not os.path.exists(this_level.map):
44 if this_level.level_name == start_level.level_name: 81 # Skip level if we can't see the map
45 self.cur_level = this_level 82 continue
83 levels[this_level.level_name] = (this_level, None)
84 return levels
46 85
47 if not self.cur_level: 86 def _create_image_widget(self, curr_level):
48 self.cur_level = self.levels[0] 87 """Create an image showing the contents of level file."""
49 88 board = gameboard.GameBoard(None, curr_level)
50
51 def done_pressed():
52 pygame.event.post(engine.DO_LOAD_LEVEL)
53
54 def cancel_pressed():
55 pygame.event.post(engine.GO_MAIN_MENU)
56
57 def next_pressed():
58 self.next_level()
59
60 def prev_pressed():
61 self.prev_level()
62
63 self.next_button = gui.Button("Next Level >>")
64 self.next_button.connect(gui.CLICK, next_pressed)
65
66 self.prev_button = gui.Button("<< Prev Level")
67 self.prev_button.connect(gui.CLICK, prev_pressed)
68
69 self.cancel_button = gui.Button("Cancel")
70 self.cancel_button.connect(gui.CLICK, cancel_pressed)
71
72 self.done_button = gui.Button("Load This Level")
73 self.done_button.connect(gui.CLICK, done_pressed)
74
75 self.render_level()
76
77
78 def next_level(self):
79 pos = self.levels.index(self.cur_level) + 1
80 if pos == len(self.levels):
81 pos = 0
82 self.cur_level = self.levels[pos]
83 self.render_level()
84
85 def prev_level(self):
86 pos = self.levels.index(self.cur_level) - 1
87 if pos == -1:
88 pos = len(self.levels) - 1
89 self.cur_level = self.levels[pos]
90 self.render_level()
91
92 def render_level(self):
93 self.clear()
94 self.repaint()
95
96 board = gameboard.GameBoard(None, self.cur_level)
97
98 space = self.style.font.size(" ")
99 w, h = board.tv.size 89 w, h = board.tv.size
100 90
101 map_image = pygame.Surface((constants.TILE_DIMENSIONS[0] * w, 91 map_image = pygame.Surface((constants.TILE_DIMENSIONS[0] * w,
102 constants.TILE_DIMENSIONS[1] * h)) 92 constants.TILE_DIMENSIONS[1] * h))
103 board.tv.loop() 93 board.tv.loop()
104 board.tv.paint(map_image) 94 board.tv.paint(map_image)
105 95
106 style = { 96 style = {
107 'width' : min(300, 7*w), 97 'width' : min(300, 7*w),
108 'height' : min(300, 7*h), 98 'height' : min(300, 7*h),
109 } 99 }
110 100
111 image = gui.Image(map_image, style=style) 101 doc = gui.Document(style=self.main_style)
102 space = doc.style.font.size(" ")
112 103
113 self.block(align=0) 104 doc.block(align=0)
114 self.add(image) 105 doc.add(gui.Image(map_image, style=style))
115 106
116 self.block(align=-1) 107 doc.block(align=0)
117 self.add(gui.Label(self.cur_level.level_name)) 108 doc.add(gui.Label(curr_level.level_name, style={
118 self.block(align=-1) 109 'border_bottom': 1,
119 for word in self.cur_level.goal.split(): 110 'margin_bottom': 5,
120 self.add(gui.Label(word)) 111 'margin_top': 5,
121 self.space(space) 112 }))
122 113
123 self.block(align=0) 114 doc.block(align=0)
124 # NB: pgu 's layout engine is sensitive to ordering here 115 for word in curr_level.goal.split():
125 self.add(self.prev_button, align=-1) 116 doc.add(gui.Label(word))
126 self.add(self.next_button, align=1) 117 doc.space(space)
127 self.add(self.done_button)
128 self.add(self.cancel_button)
129 118
130 def clear(self): 119 return doc
131 """Clear the document""" 120
132 for widget in self.widgets[:]: 121 def _level_list_change(self):
133 self.remove(widget) 122 for w in self.image_container.widgets:
134 self.layout._widgets = [] 123 self.image_container.remove(w)
135 self.layout.init() 124
125 name = self.level_list.value
126 curr_level, widget = self.levels[name]
127 if widget is None:
128 widget = self._create_image_widget(curr_level)
129 self.levels[name] = (curr_level, widget)
130
131 self.image_container.add(widget, 0, 0)
132
133 def _click_ok(self):
134 self.value = self.level_list.value
135 if self.value:
136 self.send(gui.CHANGE)
137 self.close()
138
139 def _click_cancel(self):
140 self.value = None
141 self.send(gui.CHANGE)
142 self.close()
143
144 def _load_level(self, load_func):
145 level = self.get_level()
146 if level is not None:
147 load_func(level)
148
149 def get_level(self):
150 if self.value is None:
151 return None
152 return self.levels[self.value][0]
136 153
137 154
138 155