all repos — Legends-RPG @ 3680331e18c35231e06b60e40f5431de762dbf63

A fantasy mini-RPG built with Python and Pygame.

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