comparison gamelib/gameboard.py @ 433:8643893635e7

Seperate toolbar and gameboard
author Neil Muller <drnlmuller@gmail.com>
date Sat, 21 Nov 2009 16:59:49 +0000
parents a356e57529ea
children f2a55e5e24db
comparison
equal deleted inserted replaced
432:d630465d7a84 433:8643893635e7
14 import sound 14 import sound
15 import cursors 15 import cursors
16 import sprite_cursor 16 import sprite_cursor
17 import misc 17 import misc
18 import engine 18 import engine
19 19 import toolbar
20 class OpaqueLabel(gui.Label):
21 def __init__(self, value, **params):
22 gui.Label.__init__(self, value, **params)
23 if 'width' in params:
24 self._width = params['width']
25 if 'height' in params:
26 self._height = params['height']
27 self._set_size()
28
29 def _set_size(self):
30 width, height = self.font.size(self.value)
31 width = getattr(self, '_width', width)
32 height = getattr(self, '_height', height)
33 self.style.width, self.style.height = width, height
34
35 def paint(self, s):
36 s.fill(self.style.background)
37 if self.style.align > 0:
38 r = s.get_rect()
39 w, _ = self.font.size(self.value)
40 s = s.subsurface(r.move((r.w-w, 0)).clip(r))
41 gui.Label.paint(self, s)
42
43 def update_value(self, value):
44 self.value = value
45 self._set_size()
46 self.repaint()
47
48 def mklabel(text="", **params):
49 params.setdefault('color', constants.FG_COLOR)
50 params.setdefault('width', GameBoard.TOOLBAR_WIDTH/2)
51 return OpaqueLabel(text, **params)
52
53 def mkcountupdate(counter):
54 def update_counter(self, value):
55 getattr(self, counter).update_value("%s " % value)
56 self.repaint()
57 return update_counter
58
59 class ToolBar(gui.Table):
60 def __init__(self, gameboard, level, **params):
61 gui.Table.__init__(self, **params)
62 self.group = gui.Group(name='toolbar', value=None)
63 self._next_tool_value = 0
64 self.gameboard = gameboard
65 self.cash_counter = mklabel(align=1)
66 self.wood_counter = mklabel(align=1)
67 self.chicken_counter = mklabel(align=1)
68 self.egg_counter = mklabel(align=1)
69 self.day_counter = mklabel(align=1)
70 self.killed_foxes = mklabel(align=1)
71
72 self.tr()
73 self.td(gui.Spacer(self.rect.w/2, 0))
74 self.td(gui.Spacer(self.rect.w/2, 0))
75 self.add_counter(mklabel("Day:"), self.day_counter)
76 self.add_counter(mklabel("Groats:"), self.cash_counter)
77 self.add_counter(mklabel("Planks:"), self.wood_counter)
78 self.add_counter(mklabel("Eggs:"), self.egg_counter)
79 self.add_counter(icons.CHKN_ICON, self.chicken_counter)
80 self.add_counter(icons.KILLED_FOX, self.killed_foxes)
81 self.add_spacer(5)
82
83 self.add_tool_button("Move Hen", constants.TOOL_PLACE_ANIMALS,
84 None, cursors.cursors['select'])
85 self.add_spacer(5)
86
87 self.add_heading("Sell ...")
88 self.add_tool_button("Chicken", constants.TOOL_SELL_CHICKEN,
89 level.sell_price_chicken, cursors.cursors['sell'])
90 self.add_tool_button("Egg", constants.TOOL_SELL_EGG,
91 level.sell_price_egg, cursors.cursors['sell'])
92 self.add_tool_button("Building", constants.TOOL_SELL_BUILDING,
93 None, cursors.cursors['sell'])
94 self.add_tool_button("Equipment", constants.TOOL_SELL_EQUIPMENT,
95 None, cursors.cursors['sell'])
96 self.add_spacer(5)
97
98 self.add_heading("Buy ...")
99
100 for building_cls in buildings.BUILDINGS:
101 self.add_tool_button(building_cls.NAME.title(), building_cls,
102 None, cursors.cursors.get('build', None))
103
104 for equipment_cls in equipment.EQUIPMENT:
105 self.add_tool_button(equipment_cls.NAME.title(),
106 equipment_cls,
107 equipment_cls.BUY_PRICE,
108 cursors.cursors.get('buy', None))
109
110 self.add_spacer(5)
111 self.add_tool_button("Repair", constants.TOOL_REPAIR_BUILDING, None, cursors.cursors['repair'])
112
113 self.add_spacer(5)
114 self.add_tool("Price Reference", self.show_prices)
115
116 self.fin_tool = self.add_tool("Finished Day", self.day_done)
117
118 self.anim_clear_tool = False # Flag to clear the tool on an anim loop
119 # pgu's tool widget fiddling happens after the tool action, so calling
120 # clear_tool in the tool's action doesn't work, so we punt it to
121 # the anim loop
122
123 def day_done(self):
124 if self.gameboard.day:
125 pygame.event.post(engine.START_NIGHT)
126 else:
127 self.anim_clear_tool = True
128 pygame.event.post(engine.FAST_FORWARD)
129
130 def update_fin_tool(self, day):
131 if day:
132 self.fin_tool.widget = gui.basic.Label('Finished Day')
133 self.fin_tool.resize()
134 else:
135 self.fin_tool.widget = gui.basic.Label('Fast Forward')
136 self.fin_tool.resize()
137
138 def show_prices(self):
139 """Popup dialog of prices"""
140 def make_box(text):
141 style = {
142 'border' : 1
143 }
144 word = gui.Label(text, style=style)
145 return word
146
147 def fix_widths(doc):
148 """Loop through all the widgets in the doc, and set the
149 width of the labels to max + 10"""
150 # We need to do this because of possible font issues
151 max_width = 0
152 for thing in doc.widgets:
153 if hasattr(thing, 'style'):
154 # A label
155 if thing.style.width > max_width:
156 max_width = thing.style.width
157 for thing in doc.widgets:
158 if hasattr(thing, 'style'):
159 thing.style.width = max_width + 10
160
161 tbl = gui.Table()
162 tbl.tr()
163 doc = gui.Document(width=510)
164 space = doc.style.font.size(" ")
165 for header in ['Item', 'Buy Price', 'Sell Price', 'Repair Price']:
166 doc.add(make_box(header))
167 doc.br(space[1])
168 for building in buildings.BUILDINGS:
169 doc.add(make_box(building.NAME))
170 doc.add(make_box('%d' % building.BUY_PRICE))
171 doc.add(make_box('%d' % building.SELL_PRICE))
172 if building.BREAKABLE:
173 doc.add(make_box('%d' % building.REPAIR_PRICE))
174 else:
175 doc.add(make_box('N/A'))
176 doc.br(space[1])
177 for equip in equipment.EQUIPMENT:
178 doc.add(make_box(equip.NAME))
179 doc.add(make_box('%d' % equip.BUY_PRICE))
180 doc.add(make_box('%d' % equip.SELL_PRICE))
181 doc.add(make_box('N/A'))
182 doc.br(space[1])
183
184 fix_widths(doc)
185 for word in "Damaged equipment or buildings will be sold for" \
186 " less than the sell price.".split():
187 doc.add(gui.Label(word))
188 doc.space(space)
189 close_button = gui.Button("Close")
190 tbl.td(doc)
191 tbl.tr()
192 tbl.td(close_button, align=1)
193 dialog = gui.Dialog(gui.Label('Price Reference'), tbl)
194 close_button.connect(gui.CLICK, dialog.close)
195 dialog.open()
196 self.anim_clear_tool = True
197
198 update_cash_counter = mkcountupdate('cash_counter')
199 update_wood_counter = mkcountupdate('wood_counter')
200 update_fox_counter = mkcountupdate('killed_foxes')
201 update_chicken_counter = mkcountupdate('chicken_counter')
202 update_egg_counter = mkcountupdate('egg_counter')
203 update_day_counter = mkcountupdate('day_counter')
204
205 def add_spacer(self, height):
206 self.tr()
207 self.td(gui.Spacer(0, height), colspan=2)
208
209 def add_heading(self, text):
210 self.tr()
211 self.td(mklabel(text), colspan=2)
212
213 def add_tool_button(self, text, tool, price=None, cursor=None):
214 if price is not None:
215 text = "%s (%s)" % (text, price)
216 self.add_tool(text, lambda: self.gameboard.set_selected_tool(tool,
217 cursor))
218
219 def add_tool(self, text, func):
220 label = gui.basic.Label(text)
221 value = self._next_tool_value
222 self._next_tool_value += 1
223 tool = gui.Tool(self.group, label, value, width=self.rect.w, style={"padding_left": 0})
224 tool.connect(gui.CLICK, func)
225 self.tr()
226 self.td(tool, align=-1, colspan=2)
227 return tool
228
229 def clear_tool(self):
230 self.group.value = None
231 for item in self.group.widgets:
232 item.pcls = ""
233 self.anim_clear_tool = False
234
235 def add_counter(self, icon, label):
236 self.tr()
237 self.td(icon, width=self.rect.w/2)
238 self.td(label, width=self.rect.w/2)
239
240 def resize(self, width=None, height=None):
241 width, height = gui.Table.resize(self, width, height)
242 width = GameBoard.TOOLBAR_WIDTH
243 return width, height
244
245 20
246 class VidWidget(gui.Widget): 21 class VidWidget(gui.Widget):
247 def __init__(self, gameboard, vid, **params): 22 def __init__(self, gameboard, vid, **params):
248 gui.Widget.__init__(self, **params) 23 gui.Widget.__init__(self, **params)
249 self.gameboard = gameboard 24 self.gameboard = gameboard
264 self.gameboard.use_tool(e) 39 self.gameboard.use_tool(e)
265 elif e.type == MOUSEMOTION and self.gameboard.sprite_cursor: 40 elif e.type == MOUSEMOTION and self.gameboard.sprite_cursor:
266 self.gameboard.update_sprite_cursor(e) 41 self.gameboard.update_sprite_cursor(e)
267 42
268 class GameBoard(object): 43 class GameBoard(object):
269 TILE_DIMENSIONS = (20, 20)
270 TOOLBAR_WIDTH = 140
271 44
272 GRASSLAND = tiles.REVERSE_TILE_MAP['grassland'] 45 GRASSLAND = tiles.REVERSE_TILE_MAP['grassland']
273 FENCE = tiles.REVERSE_TILE_MAP['fence'] 46 FENCE = tiles.REVERSE_TILE_MAP['fence']
274 WOODLAND = tiles.REVERSE_TILE_MAP['woodland'] 47 WOODLAND = tiles.REVERSE_TILE_MAP['woodland']
275 BROKEN_FENCE = tiles.REVERSE_TILE_MAP['broken fence'] 48 BROKEN_FENCE = tiles.REVERSE_TILE_MAP['broken fence']
316 89
317 def create_display(self): 90 def create_display(self):
318 width, height = self.disp.rect.w, self.disp.rect.h 91 width, height = self.disp.rect.w, self.disp.rect.h
319 tbl = gui.Table() 92 tbl = gui.Table()
320 tbl.tr() 93 tbl.tr()
321 self.toolbar = ToolBar(self, self.level, width=self.TOOLBAR_WIDTH) 94 self.toolbar = toolbar.ToolBar(self, self.level, width=constants.TOOLBAR_WIDTH)
322 tbl.td(self.toolbar, valign=-1) 95 tbl.td(self.toolbar, valign=-1)
323 self.tvw = VidWidget(self, self.tv, width=width-self.TOOLBAR_WIDTH, height=height) 96 self.tvw = VidWidget(self, self.tv, width=width-constants.TOOLBAR_WIDTH, height=height)
324 tbl.td(self.tvw) 97 tbl.td(self.tvw)
325 self.top_widget = tbl 98 self.top_widget = tbl
326 99
327 def update(self): 100 def update(self):
328 self.tvw.reupdate() 101 self.tvw.reupdate()
761 dialog = self.open_dialog(tbl, x=x, y=y) 534 dialog = self.open_dialog(tbl, x=x, y=y)
762 535
763 def event(self, e): 536 def event(self, e):
764 if e.type == KEYDOWN and e.key in [K_UP, K_DOWN, K_LEFT, K_RIGHT]: 537 if e.type == KEYDOWN and e.key in [K_UP, K_DOWN, K_LEFT, K_RIGHT]:
765 if e.key == K_UP: 538 if e.key == K_UP:
766 self.tvw.move_view(0, -self.TILE_DIMENSIONS[1]) 539 self.tvw.move_view(0, -constants.TILE_DIMENSIONS[1])
767 if e.key == K_DOWN: 540 if e.key == K_DOWN:
768 self.tvw.move_view(0, self.TILE_DIMENSIONS[1]) 541 self.tvw.move_view(0, constants.TILE_DIMENSIONS[1])
769 if e.key == K_LEFT: 542 if e.key == K_LEFT:
770 self.tvw.move_view(-self.TILE_DIMENSIONS[0], 0) 543 self.tvw.move_view(-constants.TILE_DIMENSIONS[0], 0)
771 if e.key == K_RIGHT: 544 if e.key == K_RIGHT:
772 self.tvw.move_view(self.TILE_DIMENSIONS[0], 0) 545 self.tvw.move_view(constants.TILE_DIMENSIONS[0], 0)
773 return True 546 return True
774 return False 547 return False
775 548
776 def advance_day(self): 549 def advance_day(self):
777 self.days += 1 550 self.days += 1