1 """ Roach management scene. """
3 from pygame.constants import BLEND_RGBA_MULT, BLEND_RGBA_SUB
4 from pgzero.constants import keys, mouse
5 from pgzero.actor import Actor
6 from pgzero.screen import Screen
7 from ..actors.buttons import ImageButton
8 from ..actors.surf import SurfActor
9 from ..constants import WIDTH, HEIGHT
10 from ..roaches import big_roaches, roach_by_name
11 from ..serums import big_serums, roach_is_serumless, SERUMS
12 from ..vehicles.base import Vehicle
13 from .base import Scene, ChangeSceneEvent, defer_to_update
14 from ..util import safepath
17 TOOLBAR_LEFT_X = WIDTH * 3 // 4
19 TOOLBAR_MID_Y = HEIGHT * 1 // 2
20 VEHICLE_MID_X = WIDTH * 3 // 8
21 VEHICLE_MID_Y = HEIGHT * 1 // 2
22 BUTTON_INSET = (20, 20)
23 SERUM_OFFSET = (0, 20)
24 ROACH_PAD_OFFSET = (0, 20)
27 def inset_button(pos, d):
29 pos[0] + d[0] * BUTTON_INSET[0],
30 pos[1] + d[1] * BUTTON_INSET[1])
33 class RoachesScene(Scene):
34 """ Roach management scene. """
36 def __init__(self, level_scene=None):
38 self._level_scene = level_scene
41 self._outside_roach = None
42 self._outside_roach_pos = 0
43 self._inventory_pos = 0
44 self._inventory_item = None
45 self._roach_layer = self.actors.add_layer("roaches", level=10)
46 self._inventory_layer = self.actors.add_layer("inventory", level=10)
47 self._pad_layer = self.actors.add_layer("pads", level=5)
48 self._seat_layer = self.actors.add_layer("seats", level=5)
49 self._button_layer = self.actors.add_layer("buttons", level=6)
54 def enter(self, world):
55 self._vehicle = Vehicle.current(world)
58 self._init_roaches(world)
59 self._update_inventory(world)
62 self.actors.default.clear()
63 overlay = self._vehicle.roach_management_overlay()
65 if self._level_scene is not None:
67 self._level_scene.draw(Screen(base))
69 base.fill((10, 10, 10))
70 base.blit(overlay, (0, 0))
71 frame = self._vehicle.roach_management_frame()
74 frame.fill((255, 255, 255, 8), None, BLEND_RGBA_MULT)
75 frame_rect = frame.get_rect()
77 VEHICLE_MID_X - frame_rect.w // 2,
78 VEHICLE_MID_Y - frame_rect.h // 2),
80 self.actors.default.add(SurfActor(base))
82 def _init_seats(self):
83 self._seat_layer.clear()
84 for seat in self._vehicle.seats:
85 seat_actor = self._seat_layer.add(seat.actor())
87 seat.vehicle_pos[0] + VEHICLE_MID_X,
88 seat.vehicle_pos[1] + VEHICLE_MID_Y)
89 self._seat_layer[self._seat_pos].selected = True
91 def _init_roaches(self, world):
92 self._roach_actors = {}
93 for roach in world.roaches:
94 self._roach_actors[roach.name] = big_roaches.assemble(roach)
96 def _init_serums(self):
97 self._serum_actors = {
98 serum: big_serums.assemble(serum) for serum in SERUMS}
100 def _update_inventory(self, world):
101 self._inventory_layer.clear()
102 serums = world.serums
105 self._inventory_pos %= len(serums)
106 serum_actor = self._serum_actors[serums[self._inventory_pos]]
107 inv_pad_centre = self._inventory_pad.center
109 inv_pad_centre[0] + SERUM_OFFSET[0],
110 inv_pad_centre[1] + SERUM_OFFSET[1])
111 self._inventory_layer.add(serum_actor)
113 def _update_roaches(self, world):
114 self._roach_layer.clear()
115 seating = self._vehicle.seating(world)
116 self._outside_roaches = []
117 for roach in world.roaches:
118 seat_pos = seating.get(roach.name)
119 if seat_pos is not None:
120 roach_actor = self._roach_actors[roach.name]
121 roach_actor.pos = self._seat_layer[seat_pos].pos
122 self._roach_layer.add(roach_actor)
124 self._outside_roaches.append(roach.name)
125 if self._outside_roaches:
126 self._outside_roach_pos %= len(self._outside_roaches)
127 roach_actor = self._roach_actors[
128 self._outside_roaches[self._outside_roach_pos]]
129 roach_pad_center = self._roach_pad.center
131 roach_pad_center[0] + ROACH_PAD_OFFSET[0],
132 roach_pad_center[1] + ROACH_PAD_OFFSET[1])
133 self._roach_layer.add(roach_actor)
135 self._outside_roach_pos = 0
137 def _init_pads(self):
138 self._roach_pad = self._pad_layer.add(
139 Actor(safepath("roach_management/roach_pad"), anchor=("left", "bottom")))
140 self._roach_pad.pos = (TOOLBAR_LEFT_X, TOOLBAR_MID_Y)
141 self._inventory_pad = self._pad_layer.add(
142 Actor(safepath("roach_management/inventory_pad"), anchor=("left", "top")))
143 self._inventory_pad.pos = (TOOLBAR_LEFT_X, TOOLBAR_MID_Y)
145 def _add_button(self, name, anchor, inset, pos, action):
146 button = self._button_layer.add(
147 ImageButton(name, anchor=anchor, action=action))
148 button.pos = inset_button(pos, inset)
151 def _init_buttons(self):
152 self._button_layer.clear()
154 safepath("roach_management/left_button"), ("left", "bottom"), (1, -1),
155 self._roach_pad.bottomleft, self._roach_left)
158 safepath("roach_management/right_button"), ("right", "bottom"), (-1, -1),
159 self._roach_pad.bottomright, self._roach_right)
162 safepath("roach_management/left_button"), ("left", "bottom"), (1, -1),
163 self._inventory_pad.bottomleft, self._inventory_left)
166 safepath("roach_management/right_button"), ("right", "bottom"), (-1, -1),
167 self._inventory_pad.bottomright, self._inventory_right)
170 safepath("roach_management/eject_button"), ("right", "top"), (-1, 1),
171 (TOOLBAR_LEFT_X, TOOLBAR_TOP_Y), self._eject_roach)
173 def _roach_left(self):
174 self._outside_roach_pos -= 1
176 def _roach_right(self):
177 self._outside_roach_pos += 1
179 def _inventory_left(self):
180 self._inventory_pos -= 1
182 def _inventory_right(self):
183 self._inventory_pos += 1
185 def _select_seat(self, seat_pos):
186 self._seat_layer[self._seat_pos].selected = False
187 self._seat_pos = seat_pos
188 self._seat_layer[self._seat_pos].selected = True
191 def _eject_roach(self, world):
192 self._vehicle.seat_roach(world, None, self._seat_pos)
195 def _click_roach_pad(self, world):
196 if self._outside_roaches:
197 roach = self._outside_roaches[self._outside_roach_pos]
198 self._vehicle.seat_roach(world, roach, self._seat_pos)
201 def _click_inventory_pad(self, world):
202 roach_name = self._vehicle.roach_at(world, self._seat_pos)
203 if roach_name is None:
205 roach = roach_by_name(world, roach_name)
208 serums = list(world.serums)
209 if self._inventory_pos >= len(serums):
211 serum = serums.pop(self._inventory_pos)
212 if roach_is_serumless(roach):
214 world.serums = serums
215 self._update_roach_actor(roach_name)
218 def _update_roach_actor(self, world, roach_name):
219 roach = roach_by_name(world, roach_name)
220 self._roach_actors[roach_name] = big_roaches.assemble(roach)
222 def update(self, world, engine, dt):
223 super().update(world, engine, dt)
224 events = world.pop_events()
225 self._update_inventory(world)
226 self._update_roaches(world)
229 def on_key_down(self, key, mod, unicode):
230 if key in (keys.ESCAPE, keys.Z):
231 if self._level_scene is None:
232 from .menu import MenuScene
233 return [ChangeSceneEvent(MenuScene())]
234 return [ChangeSceneEvent(self._level_scene)]
236 def on_mouse_down(self, pos, button):
237 if button == mouse.LEFT:
238 for actor in self.actors.buttons:
239 if actor.collidepoint(pos):
240 return actor.action()
241 for i, actor in enumerate(self.actors.seats):
242 if actor.collidepoint(pos):
243 return self._select_seat(i)
244 if self._roach_pad.collidepoint(pos):
245 return self._click_roach_pad()
246 if self._inventory_pad.collidepoint(pos):
247 return self._click_inventory_pad()