f452e7ff31a2e03a3f3246a5a067465114e3c032
1 # utility functions for the game
5 import xml
.etree
.cElementTree
as ET
8 # function to run through an interactive dialogue and return the response ID
9 def dialogue_play (screen
, bgscreen
, npc
, responder_portrait
=None,
10 marginleft
=0, margintop
=0, marginright
=0, marginbottom
=0):
12 # first check if NPC has a dialogue at all
13 if len (npc
.dialogues
) == 0 or npc
.currentdialog
>= len (npc
.dialogues
):
16 # get the conversation as a dictionary
17 convtree
= xml_to_dict (npc
.dialogues
[npc
.currentdialog
])
19 pprint
.pprint (convtree
)
21 scrwidth
= screen
.get_width ()
22 scrheight
= screen
.get_height ()
23 bgwidth
= bgscreen
.get_width ()
24 bgheight
= bgscreen
.get_height ()
25 leftedge
= scrwidth
/2 - bgwidth
/2
26 topedge
= scrheight
/2 - bgheight
/2
28 # now initiate the conversation
31 current_resp
= convtree
[dlg_id
][1][0][1]
34 screen
.blit (bgscreen
, (leftedge
, topedge
))
36 # a dialgoue ID of 0 always exits the conversation
37 # return the unique response ID
43 if reply_mode
is False:
44 if npc
.portrait
is not None:
45 screen
.blit (npc
.portrait
, (leftedge
, topedge
))
47 # get the lines to display wrapped using textwrap module
49 textnpc
= textwrap
.wrap (convtree
[dlg_id
][0], 40)
51 lines
.append ((10, 0, 0, 0, text
))
53 put_lines (screen
, lines
,
54 pygame
.Rect(leftedge
+marginleft
, topedge
+margintop
,
55 bgwidth
-marginleft
-marginright
, bgheight
-margintop
-marginbottom
))
56 pygame
.display
.update ()
58 for event
in pygame
.event
.get ():
59 if event
.type == pygame
.QUIT
:
61 elif event
.type == pygame
.KEYDOWN
:
62 # now continue the dialog
63 if event
.key
== pygame
.K_RETURN
or event
.key
== pygame
.K_SPACE
:
65 current_resp
= convtree
[dlg_id
][1][0][1]
69 if responder_portrait
is not None:
70 screen
.blit (responder_portrait
, (leftedge
, topedge
))
73 for resptext
, respid
, nextdlgid
in convtree
[dlg_id
][1]:
74 if respid
== current_resp
:
75 lines
.append ((10, 255, 0, 0, resptext
))
77 lines
.append ((10, 0, 0, 0, resptext
))
79 put_lines (screen
, lines
,
80 pygame
.Rect (leftedge
+marginleft
, topedge
+margintop
,
81 bgwidth
-marginleft
-marginright
, bgheight
-margintop
-marginbottom
))
83 pygame
.display
.update ()
84 for event
in pygame
.event
.get ():
85 if event
.type == pygame
.QUIT
:
87 elif event
.type == pygame
.KEYDOWN
:
88 if event
.key
== pygame
.K_UP
or event
.key
== pygame
.K_LEFT
:
92 current_resp
= convtree
[dlg_id
][1][sel
][1]
93 elif event
.key
== pygame
.K_DOWN
or event
.key
== pygame
.K_RIGHT
:
95 if sel
>= len (convtree
[dlg_id
][1]):
96 sel
= len(convtree
[dlg_id
][1]) - 1
97 current_resp
= convtree
[dlg_id
][1][sel
][1]
99 elif event
.key
== pygame
.K_RETURN
or event
.key
== pygame
.K_SPACE
:
100 dlg_id
= convtree
[dlg_id
][1][sel
][2]
103 # function to parse a conversation XML into a python dictionary
104 def xml_to_dict (file):
105 # parse the dialogue XML file
106 dlgtree
= ET
.parse (file)
107 # get the root element
108 conversation
= dlgtree
.getroot ()
110 # build the conversation tree as a dictionary
112 for dlg
in conversation
.findall ("dialogue"):
114 speech
= dlg
.find ("speech").text
116 for resp
in dlg
.findall ("response"):
117 responses
.append ((resp
.text
, resp
.get ("id"), resp
.get ("nextdialogue")))
119 convtree
[id] = (speech
, responses
)
125 # function to draw text on surface
126 def put_text (surface
, x
, y
, size
, (r
,g
,b
), text
):
127 harisfont
= os
.path
.join ("font", "harisgamefont.ttf")
128 textsurf
= pygame
.font
.Font (harisfont
, size
).render (text
, True, pygame
.Color (r
,g
,b
))
129 surface
.blit (textsurf
, (x
, y
))
131 # function to draw several lines of text, centered horizontally and vertically on screen
132 # or drawn centered on a rectangle
133 def put_lines (surface
, text_lines
, rect
=None):
136 harisfont
= os
.path
.join ("font", "harisgamefont.ttf")
138 for size
, r
, g
, b
, text
in text_lines
:
139 s
= pygame
.font
.Font (harisfont
, size
).render (text
, True, pygame
.Color (r
,g
,b
))
141 height
= height
+ s
.get_height()*1.5
145 # if no rectangle specified, center in screen
147 scrwidth
= surface
.get_width ()
148 scrheight
= surface
.get_height ()
151 surface
.blit (s
, (scrwidth
/2 - s
.get_width()/2, scrheight
/2 - height
/2+ i
* (s
.get_height()*1.5)))
153 # center on specified rectangular region
155 midx
= (rect
.left
+ rect
.right
)/2
156 midy
= (rect
.top
+ rect
.bottom
)/2
157 num
= len (textsurfs
) / 2
159 surface
.blit (s
, (midx
- s
.get_width()/2, midy
- (num
-i
) * s
.get_height() * 3/2))
162 # function to ask a question and return answer
163 def ask_question (surface
, question
, answers
, bgscreen
):
168 textarray
= [ [ 10, 128, 0, 0, question
] ]
171 for answer
in answers
:
176 textarray
.append ( [10, r
, g
, b
, answer
] )
180 surface
.blit (bgscreen
, (surface
.get_width()/2 - bgscreen
.get_width()/2,
181 surface
.get_height()/2 - bgscreen
.get_height()/2))
182 put_lines (surface
, textarray
, pygame
.Rect (surface
.get_width()/2 - bgscreen
.get_width()/2,
183 surface
.get_height()/2 - bgscreen
.get_height()/2,
184 bgscreen
.get_width(), bgscreen
.get_height()))
186 pygame
.display
.update ()
188 for event
in pygame
.event
.get ():
189 if event
.type == pygame
.QUIT
:
191 elif event
.type == pygame
.KEYDOWN
:
192 if event
.key
== pygame
.K_UP
:
196 elif event
.key
== pygame
.K_DOWN
:
198 if sel_answer
> len(answers
):
199 sel_answer
= len(answers
)
200 elif event
.key
== pygame
.K_RETURN
:
203 # function displaying the contents of a container. Object must contain
205 # edgewidth - container edges to avoid drawing items in
206 def get_container_object (surface
, obj
, bgimage
, edgewidth
=0):
208 # get the number of items
209 numitems
= len (obj
.objects
)
211 num_rows
= (bgimage
.get_height () - edgewidth
*2) / 48
213 num_cols
= (bgimage
.get_width () - edgewidth
*2) / 48
215 objposx
= surface
.get_width()/2 - bgimage
.get_width()/2
216 objposy
= surface
.get_height()/2 - bgimage
.get_height()/2
223 # display the background for the container
224 surface
.blit (bgimage
, (objposx
, objposy
))
226 # display each item in the container
230 # display all the items in container
231 for item
in obj
.objects
:
232 surface
.blit (item
.image
, (objposx
+ edgewidth
+ j
*48, objposy
+ edgewidth
+ i
*48))
237 # only draw selector if there is at least one item
239 pygame
.draw
.rect (surface
, pygame
.Color (255,255,255),
240 pygame
.Rect(objposx
+ edgewidth
+ selcol
*48, objposy
+ edgewidth
+ selrow
*48, 48, 48), 1)
242 pygame
.display
.update ()
245 for event
in pygame
.event
.get ():
246 if event
.type == pygame
.QUIT
:
248 elif event
.type == pygame
.KEYDOWN
:
249 if event
.key
== pygame
.K_ESCAPE
:
251 elif event
.key
== pygame
.K_RETURN
:
252 if numitems
> 0 and selitem
>= 0 and selitem
< numitems
:
253 return obj
.objects
[selitem
]
256 elif event
.key
== pygame
.K_UP
or event
.key
== pygame
.K_LEFT
:
257 # go to the prev item
260 selitem
= numitems
- 1
261 selrow
= selitem
/ num_cols
262 selcol
= selitem
% num_cols
264 elif event
.key
== pygame
.K_DOWN
or event
.key
== pygame
.K_RIGHT
:
265 # go to the next item
267 if selitem
> numitems
- 1:
269 selrow
= selitem
/ num_cols
270 selcol
= selitem
% num_cols