0c7688924e7ebd0d2e8e6fb245cab9fe1afabd8c
[tabakrolletjie.git] / tabakrolletjie / scenes / night.py
1 """ In the night, the mould attacks. """
2
3 import pygame.surface
4 import pygame.locals as pgl
5
6 import pymunk
7
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
21
22
23 class NightScene(BaseScene):
24
25     DARKNESS = Overlay(colour=(0, 0, 0, 150))
26
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)
32         self.check_battery()
33         self._infobar = InfoBar("day", battery=self._battery, scene=self)
34         self._mould = Boyd(gamestate, self._space)
35         self._turnips = []
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)
42         self._total_ticks = 0
43         self._do_ticks = True
44         self._paused = False
45         self._eaten_tonight = 0
46         self._night_over_text = []
47
48     def create_tools(self, gamestate):
49         tools = []
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)))
56         return tools
57
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)))
62
63     @property
64     def turnip_count(self):
65         return len(self._turnips)
66
67     @property
68     def power_usage(self):
69         return int(self._lights.total_power_usage())
70
71     @debug_timer("night.render")
72     def render(self, surface, gamestate):
73         surface.blit(self._soil, (0, 0))
74
75         self._mould.render(surface)
76
77         for turnip in self._turnips[:]:
78             if turnip.eaten:
79                 self._turnips.remove(turnip)
80                 turnip.remove()
81                 gamestate.eaten += 1
82                 self._eaten_tonight += 1
83             else:
84                 turnip.render(surface)
85
86         self._lights.render_light(surface)
87         self._obstacles.render(surface)
88         self._lights.render_fittings(surface)
89         self._infobar.render(surface, gamestate)
90
91         for tool in self._tools:
92             tool.render(surface)
93
94         for text, text_pos in self._night_over_text:
95             surface.blit(text, text_pos, None)
96
97     def event(self, ev, gamestate):
98         if ev.type == pgl.KEYDOWN:
99             if not self._do_ticks:
100                 # Any keypress exits
101                 self._to_day()
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:
106                 self._end_night()
107             elif ev.key == pgl.K_SPACE:
108                 self.toggle_pause()
109         elif ev.type == pgl.MOUSEBUTTONDOWN:
110             if not self._do_ticks:
111                 # Any mouse press exits
112                 self._to_day()
113             if ev.button == 1:
114                 self._lights.toggle_nearest(ev.pos, surfpos=True)
115
116                 # Check tools
117                 for tool in self._tools:
118                     if tool.pressed(ev):
119                         if tool.name == 'pause play':
120                             self.toggle_pause()
121                         elif tool.name == 'exit':
122                             from .menu import MenuScene
123                             SceneChangeEvent.post(scene=MenuScene())
124                         elif tool.name == 'day':
125                             self._to_day()
126
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)
133
134     def _to_day(self):
135         # End the night
136         from .day import DayScene
137         SceneChangeEvent.post(scene=DayScene())
138
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),
156              (350, 240)))
157
158     def check_battery(self):
159         if self._battery.current == 0:
160             self._lights.battery_dead()
161
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)
167                 self._lights.tick()
168                 if self._total_ticks % FPS == 0:
169                     self._battery.current -= int(
170                         self._lights.total_power_usage())
171                     self.check_battery()
172                 self._total_ticks += 1
173             else:
174                 self._end_night()
175             if not self._mould.alive():
176                 self._end_night()
177             if not self.turnip_count:
178                 self.add_day_button()
179                 
180
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
185         gamestate.days += 1
186         self._mould.update_resistances(gamestate)