99b903b84300d2e205e82f8568829e07b4e4a177
[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
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._infobar = InfoBar("day", battery=self._battery, scene=self)
33         self._mould = Boyd(gamestate, self._space)
34         self._turnips = []
35         for turnip_data in gamestate.turnips:
36             turnip = Turnip(space=self._space, **turnip_data)
37             self._turnips.append(turnip)
38         self._soil = loader.load_image(
39             "textures", "soil.png", transform=self.DARKNESS)
40         self._tools = self.create_tools(gamestate)
41         self._total_ticks = 0
42         self._do_ticks = True
43         self._paused = False
44         self._eaten_tonight = 0
45         self._night_over_text = []
46
47     def create_tools(self, gamestate):
48         tools = []
49         y = SCREEN_SIZE[1] - 40
50         tools.append(ImageButton(
51             '32', 'pause.png', name='pause play',
52             pos=(SCREEN_SIZE[0] - 150, y)))
53         tools.append(ImageButton(
54             '32', 'exit.png', name='exit', pos=(SCREEN_SIZE[0] - 50, y)))
55         return tools
56
57     @property
58     def turnip_count(self):
59         return len(self._turnips)
60
61     @property
62     def power_usage(self):
63         return int(self._lights.total_power_usage())
64
65     @debug_timer("night.render")
66     def render(self, surface, gamestate):
67         surface.blit(self._soil, (0, 0))
68
69         self._mould.render(surface)
70
71         for turnip in self._turnips[:]:
72             if turnip.eaten:
73                 self._turnips.remove(turnip)
74                 turnip.remove()
75                 gamestate.eaten += 1
76                 self._eaten_tonight += 1
77             else:
78                 turnip.render(surface)
79
80         self._lights.render_light(surface)
81         self._obstacles.render(surface)
82         self._lights.render_fittings(surface)
83         self._infobar.render(surface, gamestate)
84
85         for tool in self._tools:
86             tool.render(surface)
87
88         for text, text_pos in self._night_over_text:
89             surface.blit(text, text_pos, None)
90
91     def event(self, ev, gamestate):
92         if ev.type == pgl.KEYDOWN:
93             if not self._do_ticks:
94                 # Any keypress exits
95                 self._to_day()
96             if ev.key in (pgl.K_q, pgl.K_ESCAPE):
97                 from .menu import MenuScene
98                 SceneChangeEvent.post(scene=MenuScene())
99             elif ev.key == pgl.K_e and DEBUG:
100                 self._end_night()
101             elif ev.key == pgl.K_SPACE:
102                 self.toggle_pause()
103         elif ev.type == pgl.MOUSEBUTTONDOWN:
104             if not self._do_ticks:
105                 # Any mouse press exits
106                 self._to_day()
107             if ev.button == 1:
108                 self._lights.toggle_nearest(ev.pos, surfpos=True)
109                 print self._lights.lit_by(ev.pos, surfpos=True)
110
111                 # Check tools
112                 for tool in self._tools:
113                     if tool.pressed(ev):
114                         if tool.name == 'pause play':
115                             self.toggle_pause()
116                         elif tool.name == 'exit':
117                             from .menu import MenuScene
118                             SceneChangeEvent.post(scene=MenuScene())
119
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)
126
127     def _to_day(self):
128         # End the night
129         from .day import DayScene
130         SceneChangeEvent.post(scene=DayScene())
131
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),
149              (350, 240)))
150
151     @debug_timer("night.tick")
152     def tick(self, gamestate):
153         if self._do_ticks and not self._paused:
154             if self._total_ticks < NIGHT_LENGTH:
155                 self._mould.tick(gamestate, self._space, self._lights)
156                 self._lights.tick()
157                 print "Power usage: ", self._lights.total_power_usage()
158                 self._total_ticks += 1
159             else:
160                 self._end_night()
161             if not self._mould.alive():
162                 self._end_night()
163
164     def exit(self, gamestate):
165         turnip_data = [turnip.serialize() for turnip in self._turnips]
166         gamestate.turnips = turnip_data
167         # TODO: Move this into the end_night function
168         gamestate.days += 1
169         self._mould.update_resistances(gamestate)