all repos — Legends-RPG @ 2ded5c74f1c07582e76cc562f5d3027c49637745

A fantasy mini-RPG built with Python and Pygame.

data/components/textbox.py (view raw)

  1__author__ = 'justinarmstrong'
  2import copy
  3import pygame as pg
  4from .. import setup
  5from .. import constants as c
  6
  7
  8
  9class NextArrow(pg.sprite.Sprite):
 10    """Flashing arrow indicating more dialogue"""
 11    def __init__(self):
 12        super(NextArrow, self).__init__()
 13        self.image = setup.GFX['fancyarrow']
 14        self.rect = self.image.get_rect(right=780,
 15                                        bottom=135)
 16
 17
 18class DialogueBox(object):
 19    """Text box used for dialogue"""
 20    def __init__(self, dialogue, index=0, image_key='dialoguebox', item=None):
 21        self.item = item
 22        self.bground = setup.GFX[image_key]
 23        self.rect = self.bground.get_rect(centerx=400)
 24        self.arrow_timer = 0.0
 25        self.font = pg.font.Font(setup.FONTS[c.MAIN_FONT], 22)
 26        self.dialogue_list = dialogue
 27        self.index = index
 28        self.image = self.make_dialogue_box_image()
 29        self.arrow = NextArrow()
 30        self.check_to_draw_arrow()
 31        self.done = False
 32        self.allow_input = False
 33        self.name = image_key
 34
 35
 36    def make_dialogue_box_image(self):
 37        """Make the image of the dialogue box"""
 38        image = pg.Surface(self.rect.size)
 39        image.set_colorkey(c.BLACK)
 40        image.blit(self.bground, (0, 0))
 41
 42        dialogue_image = self.font.render(self.dialogue_list[self.index],
 43                                          True,
 44                                          c.NEAR_BLACK)
 45        dialogue_rect = dialogue_image.get_rect(left=50, top=50)
 46        image.blit(dialogue_image, dialogue_rect)
 47
 48        return image
 49
 50    def update(self, keys, current_time):
 51        """Updates scrolling text"""
 52        self.current_time = current_time
 53        self.draw_box(current_time)
 54        self.terminate_check(keys)
 55
 56    def draw_box(self, current_time, x=400):
 57        """Reveal dialogue on textbox"""
 58        self.image = self.make_dialogue_box_image()
 59        self.check_to_draw_arrow()
 60
 61    def terminate_check(self, keys):
 62        """Remove textbox from sprite group after 2 seconds"""
 63        if keys[pg.K_SPACE] and self.allow_input:
 64            self.done = True
 65
 66        if not keys[pg.K_SPACE]:
 67            self.allow_input = True
 68
 69    def check_to_draw_arrow(self):
 70        """Blink arrow if more text needs to be read"""
 71        if self.index < len(self.dialogue_list) - 1:
 72            self.image.blit(self.arrow.image, self.arrow.rect)
 73        else:
 74            pass
 75
 76
 77class ItemBox(DialogueBox):
 78    """Text box for information like obtaining new items"""
 79    def __init__(self, dialogue, item=None):
 80        super(ItemBox, self).__init__(None, 0, 'infobox', item)
 81
 82    def make_dialogue_box_image(self):
 83        """Make the image of the dialogue box"""
 84        image = pg.Surface(self.rect.size)
 85        image.set_colorkey(c.BLACK)
 86        image.blit(self.bground, (0, 0))
 87
 88        if self.item:
 89            type = 'Healing Potion'
 90            total = str(1)
 91            dialogue = 'You received ' + total + ' ' + type + '.'
 92            self.dialogue_list = [dialogue]
 93            self.item = None
 94
 95        dialogue_image = self.font.render(self.dialogue_list[self.index],
 96                                          False,
 97                                          c.NEAR_BLACK)
 98        dialogue_rect = dialogue_image.get_rect(left=50, top=50)
 99        image.blit(dialogue_image, dialogue_rect)
100
101        return image
102
103
104class TextHandler(object):
105    """Handles interaction between sprites to create dialogue boxes"""
106
107    def __init__(self, level):
108        self.player = level.player
109        self.sprites = level.sprites
110        self.talking_sprite = None
111        self.textbox = None
112        self.allow_input = False
113        self.level = level
114        self.last_textbox_timer = 0.0
115        self.game_data = level.game_data
116
117    def update(self, keys, current_time):
118        """Checks for the creation of Dialogue boxes"""
119        if keys[pg.K_SPACE] and not self.textbox and self.allow_input:
120            for sprite in self.sprites:
121                if (current_time - self.last_textbox_timer) > 300:
122                    if self.player.state == 'resting':
123                        self.allow_input = False
124                        self.check_for_dialogue(sprite)
125
126        if self.textbox:
127            if self.talking_sprite.name == 'treasurechest':
128                self.open_chest(self.talking_sprite)
129
130            self.textbox.update(keys, current_time)
131
132            if self.textbox.done:
133
134                if self.textbox.index < (len(self.textbox.dialogue_list) - 1):
135                    index = self.textbox.index + 1
136                    dialogue = self.textbox.dialogue_list
137                    if self.textbox.name == 'dialoguebox':
138                        self.textbox = DialogueBox(dialogue, index)
139                    elif self.textbox.name == 'infobox':
140                        self.textbox = ItemBox(dialogue, index)
141                elif self.talking_sprite.item:
142                    self.check_for_item()
143                elif self.talking_sprite.battle:
144                    self.game_data['battle type'] = self.talking_sprite.battle
145                    self.end_dialogue(current_time)
146                    self.level.switch_to_battle = True
147                elif self.talking_sprite.name == 'oldmanbrother' and \
148                        self.game_data['talked to sick brother'] and \
149                        not self.game_data['has brother elixir']:
150                    self.talking_sprite.item = 'ELIXIR'
151                    self.game_data['has brother elixir'] = True
152                    self.check_for_item()
153                    dialogue = ['Hurry! There is precious little time.']
154                    self.talking_sprite.dialogue = dialogue
155                elif self.talking_sprite.name == 'oldman':
156                    if self.game_data['has brother elixir'] and \
157                            not self.game_data['elixir received']:
158                        del self.game_data['player inventory']['ELIXIR']
159                        self.game_data['elixir received'] = True
160                        dialogue = ['My good health is thanks to you.',
161                                    'I will be forever in your debt.']
162                        self.talking_sprite.dialogue = dialogue
163                    elif not self.game_data['talked to sick brother']:
164                        self.game_data['talked to sick brother'] = True
165                         
166                        dialogue = ['Hurry to the NorthEast Shores!',
167                                    'I do not have much time left.']
168                        self.talking_sprite.dialogue = dialogue
169                    else:
170                        self.end_dialogue(current_time)
171                elif self.talking_sprite.name == 'king':
172                     
173                    if (self.game_data['crown quest'] 
174                            and not self.game_data['delivered crown']):
175                        retrieved_crown_dialogue = ['My crown! You recovered my stolen crown!!!',
176                                                   'I can not believe what I see before my eyes.',
177                                                   'You are truly a brave and noble warrior.',
178                                                   'Henceforth, I name thee Grand Protector of this Town!',
179                                                   'Go forth and be recognized.',
180                                                   'You are the greatest warrior this world has ever known.']
181                        self.talking_sprite.dialogue = retrieved_crown_dialogue
182                        self.game_data['delivered crown'] = True
183                        self.end_dialogue(current_time)
184                    elif self.game_data['delivered crown']:
185                        thank_you_dialogue = ['Thank you for retrieving my crown.',
186                                              'My kingdom is forever in your debt.']
187                        self.talking_sprite.dialogue = thank_you_dialogue
188                        self.end_dialogue(current_time)
189                    else:
190                        self.end_dialogue(current_time)
191                else:
192                    self.end_dialogue(current_time)
193
194
195        if not keys[pg.K_SPACE]:
196            self.allow_input = True
197
198    def end_dialogue(self, current_time):
199        """
200        End dialogue state for level.
201        """
202        self.talking_sprite = None
203        self.level.state = 'normal'
204        self.textbox = None
205        self.last_textbox_timer = current_time
206        self.reset_sprite_direction()
207
208    def check_for_dialogue(self, sprite):
209        """Checks if a sprite is in the correct location to give dialogue"""
210        player = self.player
211        tile_x, tile_y = player.location
212
213        if player.direction == 'up':
214            if sprite.location == [tile_x, tile_y - 1]:
215                self.textbox = DialogueBox(sprite.dialogue)
216                sprite.direction = 'down'
217                self.talking_sprite = sprite
218        elif player.direction == 'down':
219            if sprite.location == [tile_x, tile_y + 1]:
220                self.textbox = DialogueBox(sprite.dialogue)
221                sprite.direction = 'up'
222                self.talking_sprite = sprite
223        elif player.direction == 'left':
224            if sprite.location == [tile_x - 1, tile_y]:
225                self.textbox = DialogueBox(sprite.dialogue)
226                sprite.direction = 'right'
227                self.talking_sprite = sprite
228        elif player.direction == 'right':
229            if sprite.location == [tile_x + 1, tile_y]:
230                self.textbox = DialogueBox(sprite.dialogue)
231                sprite.direction = 'left'
232                self.talking_sprite = sprite
233
234    def check_for_item(self):
235        """Checks if sprite has an item to give to the player"""
236        item = self.talking_sprite.item
237
238        if item:
239            if item in self.game_data['player inventory']:
240                if 'quantity' in self.game_data['player inventory'][item]:
241                    self.game_data['player inventory'][item]['quantity'] += 1
242            else:
243                self.add_new_item_to_inventory(item)
244
245            self.update_game_items_info(self.talking_sprite)
246            self.talking_sprite.item = None
247
248            if self.talking_sprite.name == 'treasurechest':
249                self.talking_sprite.dialogue = ['Empty.']
250
251            if item == 'ELIXIR':
252                self.game_data['has brother elixir'] = True
253                self.game_data['old man gift'] = 'Fire Blast'
254                dialogue = ['Hurry! There is precious little time.']
255                self.level.reset_dialogue = self.talking_sprite, dialogue
256
257    def add_new_item_to_inventory(self, item):
258        inventory = self.game_data['player inventory']
259        potions = ['Healing Potion', 'Ether Potion']
260        if item in potions:
261            inventory[item] = dict([('quantity',1),
262                                    ('value',15)])
263        elif item == 'ELIXIR':
264            inventory[item] = dict([('quantity',1)])
265        elif item == 'Fire Blast':
266            inventory[item] = dict([('magic points', 25),
267                                    ('power', 10)])
268        else:
269            pass
270
271    def update_game_items_info(self, sprite):
272        if sprite.name == 'treasurechest':
273            self.game_data['treasure{}'.format(sprite.id)] = False
274        elif sprite.name == 'oldmanbrother':
275            self.game_data['brother elixir'] = False
276
277    def reset_sprite_direction(self):
278        """Reset sprite to default direction"""
279        for sprite in self.sprites:
280            if sprite.state == 'resting':
281                sprite.direction = sprite.default_direction
282
283
284    def draw(self, surface):
285        """Draws textbox to surface"""
286        if self.textbox:
287            surface.blit(self.textbox.image, self.textbox.rect)
288
289
290    def make_textbox(self, name, dialogue, item=None):
291        """Make textbox on demand"""
292        if name == 'itembox':
293            textbox = ItemBox(dialogue, item)
294        elif name == 'dialoguebox':
295            textbox = DialogueBox(dialogue)
296        else:
297            textbox = None
298
299        return textbox
300
301    def open_chest(self, sprite):
302        if sprite.name == 'treasurechest':
303            sprite.index = 1
304