data/states/level_state.py (view raw)
1__author__ = 'justinarmstrong'
2"""
3This is the base class all level states (i.e. states
4where the player can move around the screen) inherit
5from. This class inherits from the generic state class
6found in the tools.py module.
7"""
8
9import copy
10import pygame as pg
11from .. import tools, collision
12from .. import tilemap as tm
13from .. components import person, textbox
14from . import player_menu
15
16
17class LevelState(tools._State):
18 def __init__(self):
19 super(LevelState, self).__init__()
20 self.name = None
21 self.map_width = None
22 self.map_height = None
23
24
25
26 def startup(self, current_time, game_data):
27 """Called when the State object is created"""
28 self.game_data = game_data
29 self.current_time = current_time
30 self.state = 'normal'
31 self.allow_input = False
32 self.background = tm.create_map_layer1(self.name,
33 self.map_width,
34 self.map_height)
35 self.foreground = tm.create_map_layer2(self.name,
36 self.map_width,
37 self.map_height)
38 self.viewport = tm.create_viewport(self.background)
39 self.blockers = tm.create_blockers(self.name)
40 self.level_surface = tm.make_level_surface(self.background)
41 self.level_rect = self.level_surface.get_rect()
42 self.player = person.Player(game_data['last direction'])
43 self.sprites = pg.sprite.Group()
44 self.start_positions = tm.set_sprite_positions(self.player,
45 self.sprites,
46 self.name,
47 self.game_data)
48 self.set_sprite_dialogue()
49 self.collision_handler = collision.CollisionHandler(self.player,
50 self.blockers,
51 self.sprites)
52 self.dialogue_handler = textbox.TextHandler(self)
53 self.state_dict = self.make_state_dict()
54 self.portals = tm.make_level_portals(self.name)
55 self.menu_screen = player_menu.Player_Menu(game_data, self)
56
57
58 def set_sprite_dialogue(self):
59 """Sets unique dialogue for each sprite"""
60 raise NotImplementedError
61
62
63 def make_state_dict(self):
64 """Make a dictionary of states the level can be in"""
65 state_dict = {'normal': self.running_normally,
66 'dialogue': self.handling_dialogue,
67 'menu': self.goto_menu}
68
69 return state_dict
70
71
72 def running_normally(self, surface, keys, current_time):
73 """Update level normally"""
74 self.check_for_dialogue()
75 self.check_for_portals()
76 self.player.update(keys, current_time)
77 self.sprites.update(current_time)
78 self.collision_handler.update(keys, current_time)
79 self.dialogue_handler.update(keys, current_time)
80 self.check_for_menu(keys)
81 self.viewport_update()
82
83 self.draw_level(surface)
84
85
86 def check_for_portals(self):
87 """Check if the player walks into a door, requiring a level change"""
88 portal = pg.sprite.spritecollideany(self.player, self.portals)
89
90 if portal and self.player.state == 'resting':
91 self.player.location = self.player.get_tile_location()
92 self.next = portal.name
93 self.update_game_data()
94 self.done = True
95
96
97 def check_for_menu(self, keys):
98 """Check if player hits enter to go to menu"""
99 if keys[pg.K_RETURN] and self.allow_input:
100 if self.player.state == 'resting':
101 self.state = 'menu'
102 self.allow_input = False
103
104
105 if not keys[pg.K_RETURN]:
106 self.allow_input = True
107
108
109 def update_game_data(self):
110 """Update the persistant game data dictionary"""
111 self.game_data['last location'] = self.player.location
112 self.game_data['last direction'] = self.player.direction
113 self.game_data['last state'] = self.name
114
115 self.set_new_start_pos()
116
117
118 def set_new_start_pos(self):
119 """Set new start position based on previous state"""
120 location = copy.deepcopy(self.game_data['last location'])
121 direction = self.game_data['last direction']
122 state = self.game_data['last state']
123
124 if self.next == 'player menu':
125 pass
126 elif direction == 'up':
127 location[1] += 1
128 elif direction == 'down':
129 location[1] -= 1
130 elif direction == 'left':
131 location[0] += 1
132 elif direction == 'right':
133 location[0] -= 1
134
135 self.game_data[state + ' start pos'] = location
136
137
138 def handling_dialogue(self, surface, keys, current_time):
139 """Update only dialogue boxes"""
140 self.dialogue_handler.update(keys, current_time)
141 self.draw_level(surface)
142
143
144 def goto_menu(self, surface, keys, *args):
145 """Go to menu screen"""
146 self.menu_screen.update(surface, keys)
147 self.menu_screen.draw(surface)
148
149
150 def check_for_dialogue(self):
151 """Check if the level needs to freeze"""
152 if self.dialogue_handler.textbox:
153 self.state = 'dialogue'
154
155
156 def update(self, surface, keys, current_time):
157 """Updates state"""
158 state_function = self.state_dict[self.state]
159 state_function(surface, keys, current_time)
160
161
162 def viewport_update(self):
163 """Viewport stays centered on character, unless at edge of map"""
164 self.viewport.center = self.player.rect.center
165 self.viewport.clamp_ip(self.level_rect)
166
167
168 def draw_level(self, surface):
169 """Blits all images to screen"""
170 self.level_surface.blit(self.background, self.viewport, self.viewport)
171 self.level_surface.blit(self.player.image, self.player.rect)
172 self.sprites.draw(self.level_surface)
173 self.level_surface.blit(self.foreground, self.viewport, self.viewport)
174
175
176 surface.blit(self.level_surface, (0, 0), self.viewport)
177 self.dialogue_handler.draw(surface)
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192