all repos — Legends-RPG @ 2927a342d54f5d95eda1568b0d7d7b31caa4a63b

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