1 """ In the night, the mould attacks. """
4 import pygame.locals as pgl
8 from .base import BaseScene
9 from ..battery import BatteryManager
10 from ..lights import LightManager
11 from ..infobar import InfoBar, CountDownBar
12 from ..obstacles import ObstacleManager
13 from ..enemies import Boyd
14 from ..events import SceneChangeEvent
15 from ..utils import debug_timer, shadowed_text
16 from ..loader import loader
17 from ..transforms import Overlay
18 from ..turnip import Turnip
19 from ..widgets import ImageButton
20 from ..constants import (
21 NIGHT_LENGTH, NIGHT_HOURS_PER_TICK, DEBUG, FONTS,
25 class NightScene(BaseScene):
27 DARKNESS = Overlay(colour=(0, 0, 0, 150))
29 def enter(self, gamestate):
30 self._space = pymunk.Space()
31 self._obstacles = ObstacleManager(self._space, gamestate)
32 self._lights = LightManager(self._space, gamestate)
33 self._battery = BatteryManager(gamestate)
35 self._infobar = InfoBar("day", battery=self._battery, scene=self)
36 self._countdownbar = CountDownBar("h")
37 self._mould = Boyd(gamestate, self._space)
39 for turnip_data in gamestate.turnips:
40 turnip = Turnip(space=self._space, **turnip_data)
41 self._turnips.append(turnip)
42 self._soil = loader.load_image(
43 "textures", "soil.png", transform=self.DARKNESS)
44 self._tools = self.create_tools(gamestate)
48 self._eaten_tonight = 0
49 self._night_over_text = []
51 def create_tools(self, gamestate):
53 y = SCREEN_SIZE[1] - 40
54 tools.append(ImageButton(
55 '32', 'pause.png', name='pause play',
56 pos=(SCREEN_SIZE[0] - 150, y)))
57 tools.append(ImageButton(
58 '32', 'exit.png', name='exit', pos=(SCREEN_SIZE[0] - 50, y)))
61 def add_day_button(self):
62 y = SCREEN_SIZE[1] - 40
63 self._tools.append(ImageButton(
64 '32', 'day.png', name='day', pos=(SCREEN_SIZE[0] - 200, y)))
67 def turnip_count(self):
68 return len(self._turnips)
71 def power_usage(self):
72 power = self._lights.total_power_usage()
73 power = power / (FPS * NIGHT_HOURS_PER_TICK)
74 return int(round(power))
76 def remaining_hours(self):
78 (NIGHT_LENGTH - self._total_ticks) * NIGHT_HOURS_PER_TICK))
80 @debug_timer("night.render")
81 def render(self, surface, gamestate):
82 surface.blit(self._soil, (0, 0))
84 self._mould.render(surface)
86 for turnip in self._turnips[:]:
88 self._turnips.remove(turnip)
91 self._eaten_tonight += 1
93 turnip.render(surface)
95 self._lights.render_light(surface)
96 self._obstacles.render(surface)
97 self._lights.render_fittings(surface)
98 self._infobar.render(surface, gamestate)
99 self._countdownbar.render(surface, self.remaining_hours())
101 for tool in self._tools:
104 for text, text_pos in self._night_over_text:
105 surface.blit(text, text_pos, None)
107 def event(self, ev, gamestate):
108 if ev.type == pgl.KEYDOWN:
109 if not self._do_ticks:
111 self._to_day(gamestate)
112 if ev.key in (pgl.K_q, pgl.K_ESCAPE):
113 from .menu import MenuScene
114 SceneChangeEvent.post(scene=MenuScene())
115 elif ev.key == pgl.K_e and DEBUG:
117 elif ev.key == pgl.K_SPACE:
119 elif ev.type == pgl.MOUSEBUTTONDOWN:
120 if not self._do_ticks:
121 # Any mouse press exits
122 self._to_day(gamestate)
124 self._lights.toggle_nearest(ev.pos, surfpos=True)
127 for tool in self._tools:
129 if tool.name == 'pause play':
131 elif tool.name == 'exit':
132 from .menu import MenuScene
133 SceneChangeEvent.post(scene=MenuScene())
134 elif tool.name == 'day':
135 self._to_day(gamestate)
137 def toggle_pause(self):
138 self._paused = not self._paused
139 pause_img = "play.png" if self._paused else "pause.png"
140 for tool in self._tools:
141 if tool.name == 'pause play':
142 tool.update_image("32", pause_img)
144 def _to_day(self, gamestate):
146 gamestate.update_lights(self._lights)
147 from .day import DayScene
148 SceneChangeEvent.post(scene=DayScene())
150 def _end_night(self):
151 self._do_ticks = False
152 self._night_over_text = []
153 overlay = pygame.surface.Surface(
154 (SCREEN_SIZE[0], 240), pgl.SWSURFACE).convert_alpha()
155 overlay.fill((0, 0, 0, 172))
156 self._night_over_text.append((overlay, (0, 40)))
157 self._night_over_text.append(
158 (shadowed_text("The Night is Over", FONTS["bold"], 48), (300, 50)))
159 self._night_over_text.append(
160 (shadowed_text("Turnips eaten tonight: %d" % self._eaten_tonight,
161 FONTS["sans"], 32), (300, 130)))
162 self._night_over_text.append(
163 (shadowed_text("Surviving turnips: %d" % len(self._turnips),
164 FONTS["sans"], 32), (300, 170)))
165 self._night_over_text.append(
166 (shadowed_text("Press any key to continue", FONTS["sans"], 24),
169 def check_battery(self):
170 if self._battery.current == 0:
171 self._lights.battery_dead()
173 @debug_timer("night.tick")
174 def tick(self, gamestate):
175 if self._do_ticks and not self._paused:
176 if self._total_ticks < NIGHT_LENGTH:
177 self._mould.tick(gamestate, self._space, self._lights)
179 if self._total_ticks % FPS == 0:
180 self._battery.current -= int(
181 self._lights.total_power_usage())
183 self._total_ticks += 1
186 if not self._mould.alive():
188 if not self.turnip_count:
189 self.add_day_button()
190 if not self.turnip_count and not self._battery.current:
193 def exit(self, gamestate):
194 turnip_data = [turnip.serialize() for turnip in self._turnips]
195 gamestate.turnips = turnip_data
196 # TODO: Move this into the end_night function
198 self._mould.update_resistances(gamestate)