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)))
59 def turnip_count(self):
60 return len(self._turnips)
63 def power_usage(self):
64 return int(self._lights.total_power_usage())
66 @debug_timer("night.render")
67 def render(self, surface, gamestate):
68 surface.blit(self._soil, (0, 0))
70 self._mould.render(surface)
72 for turnip in self._turnips[:]:
74 self._turnips.remove(turnip)
77 self._eaten_tonight += 1
79 turnip.render(surface)
81 self._lights.render_light(surface)
82 self._obstacles.render(surface)
83 self._lights.render_fittings(surface)
84 self._infobar.render(surface, gamestate)
86 for tool in self._tools:
89 for text, text_pos in self._night_over_text:
90 surface.blit(text, text_pos, None)
92 def event(self, ev, gamestate):
93 if ev.type == pgl.KEYDOWN:
94 if not self._do_ticks:
97 if ev.key in (pgl.K_q, pgl.K_ESCAPE):
98 from .menu import MenuScene
99 SceneChangeEvent.post(scene=MenuScene())
100 elif ev.key == pgl.K_e and DEBUG:
102 elif ev.key == pgl.K_SPACE:
104 elif ev.type == pgl.MOUSEBUTTONDOWN:
105 if not self._do_ticks:
106 # Any mouse press exits
109 self._lights.toggle_nearest(ev.pos, surfpos=True)
112 for tool in self._tools:
114 if tool.name == 'pause play':
116 elif tool.name == 'exit':
117 from .menu import MenuScene
118 SceneChangeEvent.post(scene=MenuScene())
120 def toggle_pause(self):
121 self._paused = not self._paused
122 pause_img = "play.png" if self._paused else "pause.png"
123 for tool in self._tools:
124 if tool.name == 'pause play':
125 tool.update_image("32", pause_img)
129 from .day import DayScene
130 SceneChangeEvent.post(scene=DayScene())
132 def _end_night(self):
133 self._do_ticks = False
134 self._night_over_text = []
135 overlay = pygame.surface.Surface(
136 (SCREEN_SIZE[0], 240), pgl.SWSURFACE).convert_alpha()
137 overlay.fill((0, 0, 0, 172))
138 self._night_over_text.append((overlay, (0, 40)))
139 self._night_over_text.append(
140 (shadowed_text("The Night is Over", FONTS["bold"], 48), (300, 50)))
141 self._night_over_text.append(
142 (shadowed_text("Turnips eaten tonight: %d" % self._eaten_tonight,
143 FONTS["sans"], 32), (300, 130)))
144 self._night_over_text.append(
145 (shadowed_text("Surviving turnips: %d" % len(self._turnips),
146 FONTS["sans"], 32), (300, 170)))
147 self._night_over_text.append(
148 (shadowed_text("Press any key to continue", FONTS["sans"], 24),
151 def check_battery(self):
152 if self._battery.current == 0:
153 self._lights.battery_dead()
155 @debug_timer("night.tick")
156 def tick(self, gamestate):
157 if self._do_ticks and not self._paused:
158 if self._total_ticks < NIGHT_LENGTH:
159 self._mould.tick(gamestate, self._space, self._lights)
161 if self._total_ticks % FPS == 0:
162 self._battery.current -= int(
163 self._lights.total_power_usage())
165 self._total_ticks += 1
168 if not self._mould.alive():
171 def exit(self, gamestate):
172 turnip_data = [turnip.serialize() for turnip in self._turnips]
173 gamestate.turnips = turnip_data
174 # TODO: Move this into the end_night function
176 self._mould.update_resistances(gamestate)