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 if (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.talking_sprite.dialogue = retrieved_crown_dialogue
167 self.game_data['delivered crown'] = True
168 self.end_dialogue(current_time)
169 elif self.game_data['delivered crown']:
170 thank_you_dialogue = ['Thank you for retrieving my crown.',
171 'My kingdom is forever in your debt.']
172 self.talking_sprite.dialogue = thank_you_dialogue
173 self.end_dialogue(current_time)
174 else:
175 self.end_dialogue(current_time)
176 else:
177 self.end_dialogue(current_time)
178
179
180 if not keys[pg.K_SPACE]:
181 self.allow_input = True
182
183 def end_dialogue(self, current_time):
184 """
185 End dialogue state for level.
186 """
187 self.talking_sprite = None
188 self.level.state = 'normal'
189 self.textbox = None
190 self.last_textbox_timer = current_time
191 self.reset_sprite_direction()
192 self.notify(self, c.CLICK)
193
194 def check_for_dialogue(self, sprite):
195 """Checks if a sprite is in the correct location to give dialogue"""
196 player = self.player
197 tile_x, tile_y = player.location
198
199 if player.direction == 'up':
200 if sprite.location == [tile_x, tile_y - 1]:
201 self.textbox = DialogueBox(sprite.dialogue)
202 sprite.direction = 'down'
203 self.talking_sprite = sprite
204 elif player.direction == 'down':
205 if sprite.location == [tile_x, tile_y + 1]:
206 self.textbox = DialogueBox(sprite.dialogue)
207 sprite.direction = 'up'
208 self.talking_sprite = sprite
209 elif player.direction == 'left':
210 if sprite.location == [tile_x - 1, tile_y]:
211 self.textbox = DialogueBox(sprite.dialogue)
212 sprite.direction = 'right'
213 self.talking_sprite = sprite
214 elif player.direction == 'right':
215 if sprite.location == [tile_x + 1, tile_y]:
216 self.textbox = DialogueBox(sprite.dialogue)
217 sprite.direction = 'left'
218 self.talking_sprite = sprite
219
220 def check_for_item(self):
221 """Checks if sprite has an item to give to the player"""
222 item = self.talking_sprite.item
223
224 if item:
225 if item in self.game_data['player inventory']:
226 if 'quantity' in self.game_data['player inventory'][item]:
227 if item == 'GOLD':
228 self.game_data['player inventory'][item]['quantity'] += 100
229 else:
230 self.game_data['player inventory'][item]['quantity'] += 1
231 else:
232 self.add_new_item_to_inventory(item)
233
234 self.update_game_items_info(self.talking_sprite)
235 self.talking_sprite.item = None
236
237 if self.talking_sprite.name == 'treasurechest':
238 self.talking_sprite.dialogue = ['Empty.']
239
240 if item == 'ELIXIR':
241 self.game_data['has brother elixir'] = True
242 self.game_data['old man gift'] = 'Fire Blast'
243 dialogue = ['Hurry! There is precious little time.']
244 self.level.reset_dialogue = self.talking_sprite, dialogue
245
246 def add_new_item_to_inventory(self, item):
247 inventory = self.game_data['player inventory']
248 potions = ['Healing Potion', 'Ether Potion']
249 if item in potions:
250 inventory[item] = dict([('quantity',1),
251 ('value',15)])
252 elif item == 'ELIXIR':
253 inventory[item] = dict([('quantity',1)])
254 elif item == 'Fire Blast':
255 inventory[item] = dict([('magic points', 40),
256 ('power', 15)])
257 else:
258 pass
259
260 def update_game_items_info(self, sprite):
261 if sprite.name == 'treasurechest':
262 self.game_data['treasure{}'.format(sprite.id)] = False
263 elif sprite.name == 'oldmanbrother':
264 self.game_data['brother elixir'] = False
265
266 def reset_sprite_direction(self):
267 """Reset sprite to default direction"""
268 for sprite in self.sprites:
269 if sprite.state == 'resting':
270 sprite.direction = sprite.default_direction
271
272
273 def draw(self, surface):
274 """Draws textbox to surface"""
275 if self.textbox:
276 surface.blit(self.textbox.image, self.textbox.rect)
277
278
279 def make_textbox(self, name, dialogue, item=None):
280 """Make textbox on demand"""
281 if name == 'itembox':
282 textbox = ItemBox(dialogue, item)
283 elif name == 'dialoguebox':
284 textbox = DialogueBox(dialogue)
285 else:
286 textbox = None
287
288 return textbox
289
290 def open_chest(self, sprite):
291 if sprite.name == 'treasurechest':
292 sprite.index = 1
293