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