Use count down bar.
[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, 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)
22
23
24 class NightScene(BaseScene):
25
26     DARKNESS = Overlay(colour=(0, 0, 0, 150))
27     HOURS_PER_TICK = float(NIGHT_LENGTH_HOURS) / NIGHT_LENGTH
28
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)
34         self.check_battery()
35         self._infobar = InfoBar("day", battery=self._battery, scene=self)
36         self._countdownbar = CountDownBar("h")
37         self._mould = Boyd(gamestate, self._space)
38         self._turnips = []
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)
45         self._total_ticks = 0
46         self._do_ticks = True
47         self._paused = False
48         self._eaten_tonight = 0
49         self._night_over_text = []
50
51     def create_tools(self, gamestate):
52         tools = []
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)))
59         return tools
60
61     @property
62     def turnip_count(self):
63         return len(self._turnips)
64
65     @property
66     def power_usage(self):
67         return int(self._lights.total_power_usage())
68
69     def remaining_hours(self):
70         return int(round(
71             (NIGHT_LENGTH - self._total_ticks) * self.HOURS_PER_TICK))
72
73     @debug_timer("night.render")
74     def render(self, surface, gamestate):
75         surface.blit(self._soil, (0, 0))
76
77         self._mould.render(surface)
78
79         for turnip in self._turnips[:]:
80             if turnip.eaten:
81                 self._turnips.remove(turnip)
82                 turnip.remove()
83                 gamestate.eaten += 1
84                 self._eaten_tonight += 1
85             else:
86                 turnip.render(surface)
87
88         self._lights.render_light(surface)
89         self._obstacles.render(surface)
90         self._lights.render_fittings(surface)
91         self._infobar.render(surface, gamestate)
92         self._countdownbar.render(surface, self.remaining_hours())
93
94         for tool in self._tools:
95             tool.render(surface)
96
97         for text, text_pos in self._night_over_text:
98             surface.blit(text, text_pos, None)
99
100     def event(self, ev, gamestate):
101         if ev.type == pgl.KEYDOWN:
102             if not self._do_ticks:
103                 # Any keypress exits
104                 self._to_day()
105             if ev.key in (pgl.K_q, pgl.K_ESCAPE):
106                 from .menu import MenuScene
107                 SceneChangeEvent.post(scene=MenuScene())
108             elif ev.key == pgl.K_e and DEBUG:
109                 self._end_night()
110             elif ev.key == pgl.K_SPACE:
111                 self.toggle_pause()
112         elif ev.type == pgl.MOUSEBUTTONDOWN:
113             if not self._do_ticks:
114                 # Any mouse press exits
115                 self._to_day()
116             if ev.button == 1:
117                 self._lights.toggle_nearest(ev.pos, surfpos=True)
118
119                 # Check tools
120                 for tool in self._tools:
121                     if tool.pressed(ev):
122                         if tool.name == 'pause play':
123                             self.toggle_pause()
124                         elif tool.name == 'exit':
125                             from .menu import MenuScene
126                             SceneChangeEvent.post(scene=MenuScene())
127
128     def toggle_pause(self):
129         self._paused = not self._paused
130         pause_img = "play.png" if self._paused else "pause.png"
131         for tool in self._tools:
132             if tool.name == 'pause play':
133                 tool.update_image("32", pause_img)
134
135     def _to_day(self):
136         # End the night
137         from .day import DayScene
138         SceneChangeEvent.post(scene=DayScene())
139
140     def _end_night(self):
141         self._do_ticks = False
142         self._night_over_text = []
143         overlay = pygame.surface.Surface(
144             (SCREEN_SIZE[0], 240), pgl.SWSURFACE).convert_alpha()
145         overlay.fill((0, 0, 0, 172))
146         self._night_over_text.append((overlay, (0, 40)))
147         self._night_over_text.append(
148             (shadowed_text("The Night is Over", FONTS["bold"], 48), (300, 50)))
149         self._night_over_text.append(
150             (shadowed_text("Turnips eaten tonight: %d" % self._eaten_tonight,
151                            FONTS["sans"], 32), (300, 130)))
152         self._night_over_text.append(
153             (shadowed_text("Surviving turnips: %d" % len(self._turnips),
154                            FONTS["sans"], 32), (300, 170)))
155         self._night_over_text.append(
156             (shadowed_text("Press any key to continue", FONTS["sans"], 24),
157              (350, 240)))
158
159     def check_battery(self):
160         if self._battery.current == 0:
161             self._lights.battery_dead()
162
163     @debug_timer("night.tick")
164     def tick(self, gamestate):
165         if self._do_ticks and not self._paused:
166             if self._total_ticks < NIGHT_LENGTH:
167                 self._mould.tick(gamestate, self._space, self._lights)
168                 self._lights.tick()
169                 if self._total_ticks % FPS == 0:
170                     self._battery.current -= int(
171                         self._lights.total_power_usage())
172                     self.check_battery()
173                 self._total_ticks += 1
174             else:
175                 self._end_night()
176             if not self._mould.alive():
177                 self._end_night()
178
179     def exit(self, gamestate):
180         turnip_data = [turnip.serialize() for turnip in self._turnips]
181         gamestate.turnips = turnip_data
182         # TODO: Move this into the end_night function
183         gamestate.days += 1
184         self._mould.update_resistances(gamestate)