all repos — Legends-RPG @ 3bf8b0eba9dc6f70d6792f2a41121414df24a7ca

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