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
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 NIGHT_LENGTH, DEBUG, FONTS, SCREEN_SIZE, FPS
23 class NightScene(BaseScene):
25 DARKNESS = Overlay(colour=(0, 0, 0, 150))
27 def enter(self, gamestate):
28 self._space = pymunk.Space()
29 self._obstacles = ObstacleManager(self._space, gamestate)
30 self._lights = LightManager(self._space, gamestate)
31 self._battery = BatteryManager(gamestate)
33 self._infobar = InfoBar("day", battery=self._battery, scene=self)
34 self._mould = Boyd(gamestate, self._space)
36 for turnip_data in gamestate.turnips:
37 turnip = Turnip(space=self._space, **turnip_data)
38 self._turnips.append(turnip)
39 self._soil = loader.load_image(
40 "textures", "soil.png", transform=self.DARKNESS)
41 self._tools = self.create_tools(gamestate)
45 self._eaten_tonight = 0
46 self._night_over_text = []
48 def create_tools(self, gamestate):
50 y = SCREEN_SIZE[1] - 40
51 tools.append(ImageButton(
52 '32', 'pause.png', name='pause play',
53 pos=(SCREEN_SIZE[0] - 150, y)))
54 tools.append(ImageButton(
55 '32', 'exit.png', name='exit', pos=(SCREEN_SIZE[0] - 50, y)))
58 def add_day_button(self):
59 y = SCREEN_SIZE[1] - 40
60 self._tools.append(ImageButton(
61 '32', 'day.png', name='day', pos=(SCREEN_SIZE[0] - 200, y)))
64 def turnip_count(self):
65 return len(self._turnips)
68 def power_usage(self):
69 return int(self._lights.total_power_usage())
71 @debug_timer("night.render")
72 def render(self, surface, gamestate):
73 surface.blit(self._soil, (0, 0))
75 self._mould.render(surface)
77 for turnip in self._turnips[:]:
79 self._turnips.remove(turnip)
82 self._eaten_tonight += 1
84 turnip.render(surface)
86 self._lights.render_light(surface)
87 self._obstacles.render(surface)
88 self._lights.render_fittings(surface)
89 self._infobar.render(surface, gamestate)
91 for tool in self._tools:
94 for text, text_pos in self._night_over_text:
95 surface.blit(text, text_pos, None)
97 def event(self, ev, gamestate):
98 if ev.type == pgl.KEYDOWN:
99 if not self._do_ticks:
102 if ev.key in (pgl.K_q, pgl.K_ESCAPE):
103 from .menu import MenuScene
104 SceneChangeEvent.post(scene=MenuScene())
105 elif ev.key == pgl.K_e and DEBUG:
107 elif ev.key == pgl.K_SPACE:
109 elif ev.type == pgl.MOUSEBUTTONDOWN:
110 if not self._do_ticks:
111 # Any mouse press exits
114 self._lights.toggle_nearest(ev.pos, surfpos=True)
117 for tool in self._tools:
119 if tool.name == 'pause play':
121 elif tool.name == 'exit':
122 from .menu import MenuScene
123 SceneChangeEvent.post(scene=MenuScene())
124 elif tool.name == 'day':
127 def toggle_pause(self):
128 self._paused = not self._paused
129 pause_img = "play.png" if self._paused else "pause.png"
130 for tool in self._tools:
131 if tool.name == 'pause play':
132 tool.update_image("32", pause_img)
136 from .day import DayScene
137 SceneChangeEvent.post(scene=DayScene())
139 def _end_night(self):
140 self._do_ticks = False
141 self._night_over_text = []
142 overlay = pygame.surface.Surface(
143 (SCREEN_SIZE[0], 240), pgl.SWSURFACE).convert_alpha()
144 overlay.fill((0, 0, 0, 172))
145 self._night_over_text.append((overlay, (0, 40)))
146 self._night_over_text.append(
147 (shadowed_text("The Night is Over", FONTS["bold"], 48), (300, 50)))
148 self._night_over_text.append(
149 (shadowed_text("Turnips eaten tonight: %d" % self._eaten_tonight,
150 FONTS["sans"], 32), (300, 130)))
151 self._night_over_text.append(
152 (shadowed_text("Surviving turnips: %d" % len(self._turnips),
153 FONTS["sans"], 32), (300, 170)))
154 self._night_over_text.append(
155 (shadowed_text("Press any key to continue", FONTS["sans"], 24),
158 def check_battery(self):
159 if self._battery.current == 0:
160 self._lights.battery_dead()
162 @debug_timer("night.tick")
163 def tick(self, gamestate):
164 if self._do_ticks and not self._paused:
165 if self._total_ticks < NIGHT_LENGTH:
166 self._mould.tick(gamestate, self._space, self._lights)
168 if self._total_ticks % FPS == 0:
169 self._battery.current -= int(
170 self._lights.total_power_usage())
172 self._total_ticks += 1
175 if not self._mould.alive():
177 if not self.turnip_count:
178 self.add_day_button()
181 def exit(self, gamestate):
182 turnip_data = [turnip.serialize() for turnip in self._turnips]
183 gamestate.turnips = turnip_data
184 # TODO: Move this into the end_night function
186 self._mould.update_resistances(gamestate)