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_LENGTH_HOURS, DEBUG, FONTS, SCREEN_SIZE, FPS)
24 class NightScene(BaseScene):
26 DARKNESS = Overlay(colour=(0, 0, 0, 150))
27 HOURS_PER_TICK = float(NIGHT_LENGTH_HOURS) / NIGHT_LENGTH
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 return int(self._lights.total_power_usage())
74 def remaining_hours(self):
76 (NIGHT_LENGTH - self._total_ticks) * self.HOURS_PER_TICK))
78 @debug_timer("night.render")
79 def render(self, surface, gamestate):
80 surface.blit(self._soil, (0, 0))
82 self._mould.render(surface)
84 for turnip in self._turnips[:]:
86 self._turnips.remove(turnip)
89 self._eaten_tonight += 1
91 turnip.render(surface)
93 self._lights.render_light(surface)
94 self._obstacles.render(surface)
95 self._lights.render_fittings(surface)
96 self._infobar.render(surface, gamestate)
97 self._countdownbar.render(surface, self.remaining_hours())
99 for tool in self._tools:
102 for text, text_pos in self._night_over_text:
103 surface.blit(text, text_pos, None)
105 def event(self, ev, gamestate):
106 if ev.type == pgl.KEYDOWN:
107 if not self._do_ticks:
110 if ev.key in (pgl.K_q, pgl.K_ESCAPE):
111 from .menu import MenuScene
112 SceneChangeEvent.post(scene=MenuScene())
113 elif ev.key == pgl.K_e and DEBUG:
115 elif ev.key == pgl.K_SPACE:
117 elif ev.type == pgl.MOUSEBUTTONDOWN:
118 if not self._do_ticks:
119 # Any mouse press exits
122 self._lights.toggle_nearest(ev.pos, surfpos=True)
125 for tool in self._tools:
127 if tool.name == 'pause play':
129 elif tool.name == 'exit':
130 from .menu import MenuScene
131 SceneChangeEvent.post(scene=MenuScene())
132 elif tool.name == 'day':
135 def toggle_pause(self):
136 self._paused = not self._paused
137 pause_img = "play.png" if self._paused else "pause.png"
138 for tool in self._tools:
139 if tool.name == 'pause play':
140 tool.update_image("32", pause_img)
144 from .day import DayScene
145 SceneChangeEvent.post(scene=DayScene())
147 def _end_night(self):
148 self._do_ticks = False
149 self._night_over_text = []
150 overlay = pygame.surface.Surface(
151 (SCREEN_SIZE[0], 240), pgl.SWSURFACE).convert_alpha()
152 overlay.fill((0, 0, 0, 172))
153 self._night_over_text.append((overlay, (0, 40)))
154 self._night_over_text.append(
155 (shadowed_text("The Night is Over", FONTS["bold"], 48), (300, 50)))
156 self._night_over_text.append(
157 (shadowed_text("Turnips eaten tonight: %d" % self._eaten_tonight,
158 FONTS["sans"], 32), (300, 130)))
159 self._night_over_text.append(
160 (shadowed_text("Surviving turnips: %d" % len(self._turnips),
161 FONTS["sans"], 32), (300, 170)))
162 self._night_over_text.append(
163 (shadowed_text("Press any key to continue", FONTS["sans"], 24),
166 def check_battery(self):
167 if self._battery.current == 0:
168 self._lights.battery_dead()
170 @debug_timer("night.tick")
171 def tick(self, gamestate):
172 if self._do_ticks and not self._paused:
173 if self._total_ticks < NIGHT_LENGTH:
174 self._mould.tick(gamestate, self._space, self._lights)
176 if self._total_ticks % FPS == 0:
177 self._battery.current -= int(
178 self._lights.total_power_usage())
180 self._total_ticks += 1
183 if not self._mould.alive():
185 if not self.turnip_count:
186 self.add_day_button()
187 if not self.turnip_count and not self._battery.current:
190 def exit(self, gamestate):
191 turnip_data = [turnip.serialize() for turnip in self._turnips]
192 gamestate.turnips = turnip_data
193 # TODO: Move this into the end_night function
195 self._mould.update_resistances(gamestate)