f115374cfa0381c6fe50947cf70859910b5c9cc1
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 scrwidth
= screen
.get_width ()
20 scrheight
= screen
.get_height ()
21 bgwidth
= bgscreen
.get_width ()
22 bgheight
= bgscreen
.get_height ()
23 leftedge
= scrwidth
/2 - bgwidth
/2
24 topedge
= scrheight
/2 - bgheight
/2
26 # now initiate the conversation
29 current_resp
= convtree
[dlg_id
][1][0][1]
32 screen
.blit (bgscreen
, (leftedge
, topedge
))
34 # a dialgoue ID of 0 always exits the conversation
35 # return the unique response ID
40 if reply_mode
is False:
41 if npc
.portrait
is not None:
42 screen
.blit (npc
.portrait
, (leftedge
, topedge
))
44 # get the lines to display wrapped using textwrap module
46 textnpc
= textwrap
.wrap (convtree
[dlg_id
][0], 40)
48 lines
.append ((10, 0, 0, 0, text
))
50 put_lines (screen
, lines
,
51 pygame
.Rect(leftedge
+marginleft
, topedge
+margintop
,
52 bgwidth
-marginleft
-marginright
, bgheight
-margintop
-marginbottom
))
53 pygame
.display
.update ()
55 for event
in pygame
.event
.get ():
56 if event
.type == pygame
.QUIT
:
58 elif event
.type == pygame
.KEYDOWN
:
59 # now continue the dialog
60 if event
.key
== pygame
.K_RETURN
or event
.key
== pygame
.K_SPACE
:
62 current_resp
= convtree
[dlg_id
][1][0][1]
66 if responder_portrait
is not None:
67 screen
.blit (responder_portrait
, (leftedge
, topedge
))
70 for resptext
, respid
, nextdlgid
in convtree
[dlg_id
][1]:
71 if respid
== current_resp
:
72 lines
.append ((10, 255, 0, 0, resptext
))
74 lines
.append ((10, 0, 0, 0, resptext
))
76 put_lines (screen
, lines
,
77 pygame
.Rect (leftedge
+marginleft
, topedge
+margintop
,
78 bgwidth
-marginleft
-marginright
, bgheight
-margintop
-marginbottom
))
80 pygame
.display
.update ()
81 for event
in pygame
.event
.get ():
82 if event
.type == pygame
.QUIT
:
84 elif event
.type == pygame
.KEYDOWN
:
85 if event
.key
== pygame
.K_UP
or event
.key
== pygame
.K_LEFT
:
89 current_resp
= convtree
[dlg_id
][1][sel
][1]
90 elif event
.key
== pygame
.K_DOWN
or event
.key
== pygame
.K_RIGHT
:
92 if sel
>= len (convtree
[dlg_id
][1]):
93 sel
= len(convtree
[dlg_id
][1]) - 1
94 current_resp
= convtree
[dlg_id
][1][sel
][1]
96 elif event
.key
== pygame
.K_RETURN
or event
.key
== pygame
.K_SPACE
:
97 dlg_id
= convtree
[dlg_id
][1][sel
][2]
100 # function to parse a conversation XML into a python dictionary
101 def xml_to_dict (file):
102 # parse the dialogue XML file
103 dlgtree
= ET
.parse (file)
104 # get the root element
105 conversation
= dlgtree
.getroot ()
107 # build the conversation tree as a dictionary
109 for dlg
in conversation
.findall ("dialogue"):
111 speech
= dlg
.find ("speech").text
113 for resp
in dlg
.findall ("response"):
114 responses
.append ((resp
.text
, resp
.get ("id"), resp
.get ("nextdialogue")))
116 convtree
[id] = (speech
, responses
)
122 # function to draw text on surface
123 def put_text (surface
, x
, y
, size
, (r
,g
,b
), text
):
124 harisfont
= os
.path
.join ("font", "harisgamefont.ttf")
125 textsurf
= pygame
.font
.Font (harisfont
, size
).render (text
, True, pygame
.Color (r
,g
,b
))
126 surface
.blit (textsurf
, (x
, y
))
128 # function to draw several lines of text, centered horizontally and vertically on screen
129 # or drawn centered on a rectangle
130 def put_lines (surface
, text_lines
, rect
=None):
133 harisfont
= os
.path
.join ("font", "harisgamefont.ttf")
135 for size
, r
, g
, b
, text
in text_lines
:
136 s
= pygame
.font
.Font (harisfont
, size
).render (text
, True, pygame
.Color (r
,g
,b
))
138 height
= height
+ s
.get_height()*1.5
142 # if no rectangle specified, center in screen
144 scrwidth
= surface
.get_width ()
145 scrheight
= surface
.get_height ()
148 surface
.blit (s
, (scrwidth
/2 - s
.get_width()/2, scrheight
/2 - height
/2+ i
* (s
.get_height()*1.5)))
150 # center on specified rectangular region
152 midx
= (rect
.left
+ rect
.right
)/2
153 midy
= (rect
.top
+ rect
.bottom
)/2
154 num
= len (textsurfs
) / 2
156 surface
.blit (s
, (midx
- s
.get_width()/2, midy
- (num
-i
) * s
.get_height() * 3/2))
159 # function to ask a question and return answer
160 def ask_question (surface
, question
, answers
, bgscreen
):
165 textarray
= [ [ 10, 128, 0, 0, question
] ]
168 for answer
in answers
:
173 textarray
.append ( [10, r
, g
, b
, answer
] )
177 surface
.blit (bgscreen
, (surface
.get_width()/2 - bgscreen
.get_width()/2,
178 surface
.get_height()/2 - bgscreen
.get_height()/2))
179 put_lines (surface
, textarray
, pygame
.Rect (surface
.get_width()/2 - bgscreen
.get_width()/2,
180 surface
.get_height()/2 - bgscreen
.get_height()/2,
181 bgscreen
.get_width(), bgscreen
.get_height()))
183 pygame
.display
.update ()
185 for event
in pygame
.event
.get ():
186 if event
.type == pygame
.QUIT
:
188 elif event
.type == pygame
.KEYDOWN
:
189 if event
.key
== pygame
.K_UP
:
193 elif event
.key
== pygame
.K_DOWN
:
195 if sel_answer
> len(answers
):
196 sel_answer
= len(answers
)
197 elif event
.key
== pygame
.K_RETURN
:
200 # function displaying the contents of a container. Object must contain
202 # edgewidth - container edges to avoid drawing items in
203 def get_container_object (surface
, obj
, bgimage
, edgewidth
=0):
205 # get the number of items
206 numitems
= len (obj
.objects
)
208 num_rows
= (bgimage
.get_height () - edgewidth
*2) / 48
210 num_cols
= (bgimage
.get_width () - edgewidth
*2) / 48
212 objposx
= surface
.get_width()/2 - bgimage
.get_width()/2
213 objposy
= surface
.get_height()/2 - bgimage
.get_height()/2
220 # display the background for the container
221 surface
.blit (bgimage
, (objposx
, objposy
))
223 # display each item in the container
227 # display all the items in container
228 for item
in obj
.objects
:
229 surface
.blit (item
.image
, (objposx
+ edgewidth
+ j
*48, objposy
+ edgewidth
+ i
*48))
234 # only draw selector if there is at least one item
236 pygame
.draw
.rect (surface
, pygame
.Color (255,255,255),
237 pygame
.Rect(objposx
+ edgewidth
+ selcol
*48, objposy
+ edgewidth
+ selrow
*48, 48, 48), 1)
239 pygame
.display
.update ()
242 for event
in pygame
.event
.get ():
243 if event
.type == pygame
.QUIT
:
245 elif event
.type == pygame
.KEYDOWN
:
246 if event
.key
== pygame
.K_ESCAPE
:
248 elif event
.key
== pygame
.K_RETURN
:
249 if numitems
> 0 and selitem
>= 0 and selitem
< numitems
:
250 return obj
.objects
[selitem
]
253 elif event
.key
== pygame
.K_UP
or event
.key
== pygame
.K_LEFT
:
254 # go to the prev item
257 selitem
= numitems
- 1
258 selrow
= selitem
/ num_cols
259 selcol
= selitem
% num_cols
261 elif event
.key
== pygame
.K_DOWN
or event
.key
== pygame
.K_RIGHT
:
262 # go to the next item
264 if selitem
> numitems
- 1:
266 selrow
= selitem
/ num_cols
267 selcol
= selitem
% num_cols