22 self
.clock
= pygame
.time
.Clock ()
23 self
.screen
= pygame
.display
.set_mode ((720, 512))
24 pygame
.display
.set_caption ("The Adventures of Butaba")
26 # initalize background graphics
27 self
.img_tileset
= pygame
.image
.load (os
.path
.join ("background", "tileset.png")).convert ()
29 self
.img_menu
= pygame
.image
.load (os
.path
.join ("background", "menu_screen.png")).convert ()
31 self
.img_inventory
= pygame
.image
.load (os
.path
.join ("background", "inventory.png")).convert ()
33 self
.img_chestbg
= pygame
.image
.load (os
.path
.join ("background", "chestcontent.png")).convert ()
35 self
.img_dialogue
= pygame
.image
.load (os
.path
.join ("background", "dialog_screen.png")).convert ()
36 self
.img_dialogue
.set_colorkey (pygame
.Color (0, 255, 0))
39 # initialize object graphics
40 self
.img_redpotion
= pygame
.image
.load (os
.path
.join ("objects", "red-potion.png")).convert ()
41 self
.img_redpotion
.set_colorkey (pygame
.Color (0, 255, 0))
42 self
.img_goldcoins
= pygame
.image
.load (os
.path
.join ("objects", "gold-coins.png")).convert ()
43 self
.img_goldcoins
.set_colorkey (pygame
.Color (0, 255, 0))
44 self
.img_wand
= pygame
.image
.load (os
.path
.join ("objects", "wand.png")).convert ()
45 self
.img_wand
.set_colorkey (pygame
.Color (0, 255, 0))
46 self
.img_bulb
= pygame
.image
.load (os
.path
.join ("objects", "bulb.png")).convert ()
47 self
.img_bulb
.set_colorkey (pygame
.Color (0, 255, 0))
48 self
.img_lightning
= pygame
.image
.load (os
.path
.join ("objects", "lightning.png")).convert ()
49 self
.img_lightning
.set_colorkey (pygame
.Color (0, 255, 0))
50 self
.img_key
= pygame
.image
.load (os
.path
.join ("objects", "key.png")).convert ()
51 self
.img_key
.set_colorkey (pygame
.Color (0, 255, 0))
52 self
.img_key2
= pygame
.image
.load (os
.path
.join ("objects", "key2.png")).convert ()
53 self
.img_key2
.set_colorkey (pygame
.Color (0, 255, 0))
54 self
.img_chest
= pygame
.image
.load (os
.path
.join ("objects", "chest.png")).convert ()
55 self
.img_chest
.set_colorkey (pygame
.Color (0, 255, 0))
56 self
.img_bucket
= pygame
.image
.load (os
.path
.join ("objects", "bucket.png")).convert ()
57 self
.img_bucket
.set_colorkey (pygame
.Color (0, 255, 0))
59 # initialize player graphics
60 self
.img_butabafront
= pygame
.image
.load (os
.path
.join ("sprite", "butaba-front.png")).convert ()
61 self
.img_butabafront
.set_colorkey (pygame
.Color (0, 255, 0))
62 self
.img_butababack
= pygame
.image
.load (os
.path
.join ("sprite", "butaba-back.png")).convert ()
63 self
.img_butababack
.set_colorkey (pygame
.Color (0, 255, 0))
64 self
.img_butabaleft
= pygame
.image
.load (os
.path
.join ("sprite", "butaba-left.png")).convert ()
65 self
.img_butabaleft
.set_colorkey (pygame
.Color (0, 255, 0))
66 self
.img_butabaright
= pygame
.image
.load (os
.path
.join ("sprite", "butaba-right.png")).convert ()
67 self
.img_butabaright
.set_colorkey (pygame
.Color (0, 255, 0))
69 # initialize NPC graphics
70 self
.img_bulisafront
= pygame
.image
.load (os
.path
.join ("sprite", "bulisa-front.png")).convert ()
71 self
.img_bulisafront
.set_colorkey (pygame
.Color (0, 255, 0))
73 self
.img_bulisaback
= pygame
.image
.load (os
.path
.join ("sprite", "bulisa-back.png")).convert ()
74 self
.img_bulisaback
.set_colorkey (pygame
.Color (0, 255, 0))
76 self
.img_bulisaleft
= pygame
.image
.load (os
.path
.join ("sprite", "bulisa-left.png")).convert ()
77 self
.img_bulisaleft
.set_colorkey (pygame
.Color (0, 255, 0))
79 self
.img_bulisaright
= pygame
.image
.load (os
.path
.join ("sprite", "bulisa-right.png")).convert ()
80 self
.img_bulisaright
.set_colorkey (pygame
.Color (0, 255, 0))
82 self
.img_mayorfront
= pygame
.image
.load (os
.path
.join ("sprite", "mayor-front.png")).convert ()
83 self
.img_mayorfront
.set_colorkey (pygame
.Color (0, 255, 0))
85 self
.img_mayorback
= pygame
.image
.load (os
.path
.join ("sprite", "mayor-back.png")).convert ()
86 self
.img_mayorback
.set_colorkey (pygame
.Color (0, 255, 0))
88 self
.img_mayorleft
= pygame
.image
.load (os
.path
.join ("sprite", "mayor-left.png")).convert ()
89 self
.img_mayorleft
.set_colorkey (pygame
.Color (0, 255, 0))
91 self
.img_mayorright
= pygame
.image
.load (os
.path
.join ("sprite", "mayor-right.png")).convert ()
92 self
.img_mayorright
.set_colorkey (pygame
.Color (0, 255, 0))
94 # initialize portraits
95 self
.img_butaba_portrait
= pygame
.image
.load (os
.path
.join ("portraits", "butaba.png")).convert ()
96 self
.img_bulisa_portrait
= pygame
.image
.load (os
.path
.join ("portraits", "bulisa.png")).convert ()
97 self
.img_mayor_portrait
= pygame
.image
.load (os
.path
.join ("portraits", "mayor.png")).convert ()
101 # set current level and position of our character
102 self
.currentlevel
= self
.level1
104 # set the status message
105 self
.status_message
= "Game started"
107 self
.butaba
= butaba
.Butaba (5,0, self
.img_butabaleft
,
108 self
.img_butabaright
, self
.img_butabafront
,
109 self
.img_butababack
, self
.img_butaba_portrait
, constants
.RIGHT
)
111 # set up the levels and their interactions
112 def setup_levels (self
):
113 # set up the objects first
114 chest1
= gameobjects
.Chest (2, 6, "chest", self
.img_chest
, constants
.KEY_CHEST1
, True)
115 chest2
= gameobjects
.Chest (6, 6, "chest", self
.img_chest
, constants
.KEY_CHEST2
, True)
116 key2
= gameobjects
.Key (5, 3, "a chest key", self
.img_key
, constants
.KEY_CHEST2
)
117 potion
= gameobjects
.HealthPotion (5, 2, self
.img_redpotion
)
118 gold50
= gameobjects
.GoldCoins (6, 2, self
.img_goldcoins
, 50)
119 gold25
= gameobjects
.GoldCoins (6, 2, self
.img_goldcoins
, 25)
120 gold10
= gameobjects
.GoldCoins (6, 2, self
.img_goldcoins
, 10)
121 bucket
= gameobjects
.Bucket (6, 3, self
.img_bucket
)
123 well1
= gameobjects
.Well (4, 7)
124 well2
= gameobjects
.Well (5, 7)
125 well3
= gameobjects
.Well (4, 8)
126 well4
= gameobjects
.Well (5, 8)
128 npc_bulisa
= npcs
.Bulisa (4, 3, self
.img_bulisaleft
, self
.img_bulisaright
,
129 self
.img_bulisafront
, self
.img_bulisaback
,
130 self
.img_bulisa_portrait
, constants
.FRONT
,
132 [ os
.path
.join ("dialogues", "bulisa1.dlg"),
133 os
.path
.join ("dialogues", "bulisa2.dlg"),
134 os
.path
.join ("dialogues", "bulisa3.dlg"),
135 os
.path
.join ("dialogues", "bulisa4.dlg"),
136 os
.path
.join ("dialogues", "bulisa5.dlg"),
137 os
.path
.join ("dialogues", "bulisa6.dlg"),
138 os
.path
.join ("dialogues", "bulisa7.dlg") ] )
140 npc_mayor
= npcs
.Mayor (5, 4, self
.img_mayorleft
, self
.img_mayorright
,
141 self
.img_mayorfront
, self
.img_mayorback
,
142 self
.img_mayor_portrait
, constants
.FRONT
,
144 [ os
.path
.join ("dialogues", "mayor1.dlg"),
145 os
.path
.join ("dialogues", "mayor2.dlg"),
146 os
.path
.join ("dialogues", "mayor3.dlg") ])
148 chest1
.objects
= [ gold50
, gold25
, key2
, gold10
]
151 self
.level1
= level
.Level (cPickle
.load (file (os
.path
.join ("levels", "level1.dat"))),
152 objects
= [ chest1
] )
154 self
.level1w
= level
.Level (cPickle
.load (file (os
.path
.join ("levels", "level1w.dat"))))
156 self
.level1e
= level
.Level (cPickle
.load (file (os
.path
.join ("levels", "level1e.dat"))),
157 objects
= [ potion
, chest2
], npcs
= [ npc_bulisa
])
159 self
.level1ee
= level
.Level (cPickle
.load (file (os
.path
.join ("levels", "level1ee.dat"))),
160 objects
= [ well1
, well2
, well3
, well4
])
162 self
.level1n
= level
.Level (cPickle
.load (file (os
.path
.join ("levels", "level1n.dat"))),
163 objects
= [ bucket
])
165 self
.level1nw
= level
.Level (cPickle
.load (file (os
.path
.join ("levels", "level1nw.dat"))))
167 self
.level1ne
= level
.Level (cPickle
.load (file (os
.path
.join ("levels", "level1ne.dat"))))
169 self
.level1nee
= level
.Level (cPickle
.load (file (os
.path
.join ("levels", "level1nee.dat"))))
171 self
.level1sw
= level
.Level (cPickle
.load (file (os
.path
.join ("levels", "level1sw.dat"))))
173 self
.level1sww
= level
.Level (cPickle
.load (file (os
.path
.join ("levels", "level1sww.dat"))))
175 self
.level1ww
= level
.Level (cPickle
.load (file (os
.path
.join ("levels", "level1ww.dat"))),
176 npcs
= [ npc_mayor
])
178 # set up the interaction between levels (level exits)
179 self
.level1
.levelright
= self
.level1e
180 self
.level1
.levelleft
= self
.level1w
181 self
.level1e
.levelleft
= self
.level1
182 self
.level1e
.levelright
= self
.level1ee
183 self
.level1ee
.levelleft
= self
.level1e
184 self
.level1w
.levelright
= self
.level1
185 self
.level1
.leveltop
= self
.level1n
186 self
.level1n
.levelbottom
= self
.level1
187 self
.level1n
.levelleft
= self
.level1nw
188 self
.level1w
.leveltop
= self
.level1nw
189 self
.level1nw
.levelright
= self
.level1n
190 self
.level1nw
.levelbottom
= self
.level1w
191 self
.level1n
.levelright
= self
.level1ne
192 self
.level1e
.leveltop
= self
.level1ne
193 self
.level1ne
.levelleft
= self
.level1n
194 self
.level1ne
.levelbottom
= self
.level1e
195 self
.level1ne
.levelright
= self
.level1nee
196 self
.level1ee
.leveltop
= self
.level1nee
197 self
.level1nee
.levelleft
= self
.level1ne
198 self
.level1nee
.levelbottom
= self
.level1ee
199 self
.level1sw
.leveltop
= self
.level1w
200 self
.level1w
.levelbottom
= self
.level1sw
201 self
.level1sww
.levelright
= self
.level1sw
202 self
.level1sw
.levelleft
= self
.level1sww
203 self
.level1ww
.levelright
= self
.level1w
204 self
.level1ww
.levelbottom
= self
.level1sww
205 self
.level1sww
.leveltop
= self
.level1ww
206 self
.level1w
.levelleft
= self
.level1ww
208 def main_loop (self
):
213 self
.screen
.fill (pygame
.Color (0,0,0))
215 self
.draw_level_background (self
.currentlevel
)
217 self
.draw_level_objects (self
.currentlevel
)
218 # draw the NPCs in the level
219 self
.draw_level_npcs (self
.currentlevel
)
222 # display the character's inventory
223 self
.draw_inventory ()
224 # draw the status info
227 pygame
.display
.update ()
229 # get keyboard events
230 for event
in pygame
.event
.get ():
231 if event
.type == pygame
.QUIT
:
234 if event
.type == pygame
.KEYDOWN
:
235 if event
.key
== pygame
.K_UP
:
236 self
.move_butaba_up ()
237 elif event
.key
== pygame
.K_DOWN
:
238 self
.move_butaba_down ()
239 elif event
.key
== pygame
.K_LEFT
:
240 self
.move_butaba_left ()
241 elif event
.key
== pygame
.K_RIGHT
:
242 self
.move_butaba_right ()
243 # drinking health potion in inventory
244 elif event
.key
== ord ("h") or event
.key
== ord ("H"):
245 self
.inventory_drink_health_potion ()
247 elif event
.key
== ord ("q") or event
.key
== ord ("Q"):
250 # drink a health potion if it is in the player's inventory
251 def inventory_drink_health_potion (self
):
252 # look for a health potion
253 for item
in self
.butaba
.objects
:
254 if isinstance (item
, gameobjects
.HealthPotion
) is True:
255 self
.use_object (self
.butaba
, item
)
258 def move_butaba_up (self
):
259 # clear any status messages
260 self
.status_message
= None
261 # first if butaba is not facing up, make him face up
262 if self
.butaba
.position
<> constants
.BACK
:
263 self
.butaba
.position
= constants
.BACK
266 # if butaba is trying to move off the top of the screen
267 if self
.butaba
.row
<= 0:
268 # if there is a level above set current level to that one
269 if self
.currentlevel
.leveltop
is not None:
270 lastrow
= len (self
.currentlevel
.leveltop
.background
) - 1
271 # interact with objects
272 if self
.level_interact (self
.currentlevel
.leveltop
, lastrow
, self
.butaba
.col
) is False:
275 # make sure there is no obstacle
276 if self
.check_background_obstacle (self
.currentlevel
.leveltop
, lastrow
, self
.butaba
.col
) is False:
277 self
.currentlevel
= self
.currentlevel
.leveltop
278 self
.butaba
.row
= lastrow
279 # normal upward movement
281 # if there is any object in that place interact with it
282 # if any object is a blocking object then avoid movement
283 if self
.level_interact (self
.currentlevel
, self
.butaba
.row
-1, self
.butaba
.col
) is False:
286 if self
.check_background_obstacle (self
.currentlevel
, self
.butaba
.row
-1, self
.butaba
.col
) is False:
289 def move_butaba_down (self
):
290 # clear any status messages
291 self
.status_message
= None
292 # first if butaba is not facing forward, make him face forward/down
293 if self
.butaba
.position
<> constants
.FRONT
:
294 self
.butaba
.position
= constants
.FRONT
297 # if butaba is trying to move off the bottom of the screen
298 if self
.butaba
.row
>= len (self
.currentlevel
.background
)-1:
299 # if there is a level below set current level to that one
300 if self
.currentlevel
.levelbottom
is not None:
301 # interact with objects if any
302 # if any object is a blocking object then avoid movement
303 if self
.level_interact (self
.currentlevel
.levelbottom
, 0, self
.butaba
.col
) is False:
305 # make sure there is no obstacle at that position
306 if self
.check_background_obstacle (self
.currentlevel
.levelbottom
, 0, self
.butaba
.col
) is False:
307 self
.currentlevel
= self
.currentlevel
.levelbottom
309 # normal downward movement
311 # interact with objects if any
312 # if any object is a blocking object then avoid movement
313 if self
.level_interact (self
.currentlevel
, self
.butaba
.row
+1, self
.butaba
.col
) is False:
315 if self
.check_background_obstacle (self
.currentlevel
, self
.butaba
.row
+1, self
.butaba
.col
) is False:
318 # check if a background tile is an obstacle
319 def check_background_obstacle (self
, level
, row
, col
):
320 if (level
.background
[row
][col
][2] == 1):
325 # get and interact with objects and characters if present in a particular row/col
326 def level_interact (self
, level
, row
, col
):
328 # get list of objects at current location
329 for obj
in level
.objects
:
330 if obj
.row
== row
and obj
.col
== col
:
333 notblock
= self
.interact_objects (level
, objs
)
335 # get npc at current location
337 for npc
in level
.npcs
:
338 if npc
.row
== row
and npc
.col
== col
:
342 # npcs always block the tile. So return false if there is an NPC
344 if current_npc
is not None:
345 self
.interact_npc (current_npc
)
350 # interaction with npcs
351 def interact_npc (self
, npc
):
352 # interact with NPC and get the response ID
353 # if the NPC is Bulisa
355 # if the NPC is dead cannot talk with the NPC
356 if npc
.is_dead
is True:
357 self
.status_message
= "%s is dead! RIP..." % npc
.charname
360 if isinstance (npc
, npcs
.Bulisa
):
361 # interact with Bulisa
362 self
.interact_npc_bulisa (npc
)
363 elif isinstance (npc
, npcs
.Mayor
):
364 # interact with the Mayor
365 self
.interact_npc_mayor (npc
)
367 # interact with the mayor
368 def interact_npc_mayor (self
, npc
):
371 if gamestate
.flag
["mission_charity_money"] is True:
372 npc
.currentdialog
= 2
373 resp_id
= utility
.dialogue_play (self
.screen
, self
.img_dialogue
, npc
, self
.butaba
.portrait
, 0, 90)
374 elif gamestate
.flag
["mission_charity_informed_mayor"] is True:
375 npc
.currentdialog
= 1
376 resp_id
= utility
.dialogue_play (self
.screen
, self
.img_dialogue
, npc
, self
.butaba
.portrait
, 0, 90)
378 npc
.currentdialog
= 0
379 resp_id
= utility
.dialogue_play (self
.screen
, self
.img_dialogue
, npc
, self
.butaba
.portrait
, 0, 90)
382 # deal with the respnses
383 if resp_id
== "missioncharityaccepted":
384 gamestate
.flag
["mission_charity_money"] = True
385 # response ID is none
386 elif resp_id
is None:
387 self
.status_message
= "You cannot initiate a conversation with %s" % npc
.charname
389 # interact with NPC Bulisa
390 def interact_npc_bulisa (self
, npc
):
391 # set initial response ID to none
394 # check for global game states (starting from later flags to earlier ones
396 # whether butaba is doing the mayor charity mission
397 if gamestate
.flag
["mission_charity_money"] is True:
398 npc
.currentdialog
= 6
399 resp_id
= utility
.dialogue_play (self
.screen
, self
.img_dialogue
, npc
, self
.butaba
.portrait
, 0, 90)
400 # whether the drawing water from well mission completed
401 elif gamestate
.flag
["mission_charity_informed"] is True:
402 npc
.currentdialog
= 5
403 resp_id
= utility
.dialogue_play (self
.screen
, self
.img_dialogue
, npc
, self
.butaba
.portrait
, 0, 90)
404 elif gamestate
.flag
['mission_bulisa_water_from_well_complete'] is True:
405 npc
.currentdialog
= 4
406 resp_id
= utility
.dialogue_play (self
.screen
, self
.img_dialogue
, npc
, self
.butaba
.portrait
, 0, 90)
407 # whether the drawing water from well mission refused
408 elif gamestate
.flag
['mission_bulisa_water_from_well_refused'] is True:
409 npc
.currentdialog
= 2
410 resp_id
= utility
.dialogue_play (self
.screen
, self
.img_dialogue
, npc
, self
.butaba
.portrait
, 0, 90)
411 # whether the drawing water from well mission is accepted
412 elif gamestate
.flag
['mission_bulisa_water_from_well'] is True:
413 # check if butaba has a bucket full of water
414 for invobj
in self
.butaba
.objects
:
415 if isinstance (invobj
, gameobjects
.Bucket
) is True:
416 # if yes, then mission is completed accordingly
417 if invobj
.liquid
== "water":
418 gamestate
.flag
["mission_bulisa_water_from_well_complete"] = True
419 self
.butaba
.objects
.remove (invobj
)
420 key1
= gameobjects
.Key (5, 3, "a chest key", self
.img_key2
, constants
.KEY_CHEST1
)
421 self
.butaba
.objects
.append (key1
)
423 # water mission is not completed yet
424 if gamestate
.flag
["mission_bulisa_water_from_well_complete"] is False:
425 npc
.currentdialog
= 1
427 npc
.currentdialog
= 3
428 # get the response ID
429 resp_id
= utility
.dialogue_play (self
.screen
, self
.img_dialogue
, npc
, self
.butaba
.portrait
, 0, 90)
430 # Butaba hasn't been told about the initial mission yet, so tell him now
432 npc
.currentdialog
= 0
433 # get the response ID
434 resp_id
= utility
.dialogue_play (self
.screen
, self
.img_dialogue
, npc
, self
.butaba
.portrait
, 0, 90)
437 # Check each response
439 # Drawing water from well mission is refused
440 if resp_id
== "refusedwatermission":
441 gamestate
.flag
["mission_bulisa_water_from_well_refused"] = True
442 # Drawing water from well mission begins
443 elif resp_id
== "acceptedwatermission":
444 gamestate
.flag
["mission_bulisa_water_from_well"] = True
445 gamestate
.flag
["mission_bulisa_water_from_well_refused"] = False
446 # Butaba is informed about the mayor's charity
447 elif resp_id
== "informedcharitymission":
448 gamestate
.flag
["mission_charity_informed"] = True
449 # if mayor has been told about Butaba
450 elif resp_id
== "mayortoldaboutbutaba":
451 gamestate
.flag
["mission_charity_informed_mayor"] = True
452 # if response ID is none
453 elif resp_id
is None:
454 self
.status_message
= "You cannot initiate a conversation with %s" % npc
.charname
456 # interaction with objects
457 def interact_objects (self
, container
, objs
):
458 # overall flag for blocking/non-blocking objects
461 # now perform interaction
463 # run the object interact function
464 if obj
.interact () is False:
466 # if object can be picked up ask
467 if obj
.can_pickup
is True:
468 ans
= utility
.ask_question (self
.screen
, "Found %s." % obj
.text
, ["Pick up", obj
.use_str
, "Ignore"], self
.img_menu
)
469 # if the answer is "pick up"
471 self
.pickup_object (container
, obj
)
473 # use the object according to its type
474 self
.use_object (container
, obj
)
475 # if it cannot be picked up, try to use it anyway
477 ans
= utility
.ask_question (self
.screen
, "Found %s." % obj
.text
, [obj
.use_str
, "Ignore"], self
.img_menu
)
479 self
.use_object (container
, obj
)
483 # transfer an object from one container to another
484 # container must have an objects list
485 def transfer_object (self
, source
, obj
, dest
):
486 # remove object from source
487 source
.objects
.remove (obj
)
488 # add object to destination
489 dest
.objects
.append (obj
)
491 # picking up an object
492 def pickup_object (self
, container
, obj
):
493 # only if object can be picked up, pick it up or use it
494 if obj
.can_pickup
is True:
495 # check if the inventory is full
496 if len (self
.butaba
.objects
) >= constants
.MAXITEMS
:
497 self
.status_message
= "Cannot pick up item. Inventory full"
499 # add item to inventory
500 self
.transfer_object (container
, obj
, self
.butaba
)
502 self
.status_message
= "You picked up %s" % obj
.text
504 # this method uses the object first by calling the object use () method
505 # and then performing specific actions as necessary
506 def use_object (self
, container
, obj
):
507 # if the object is a health potion
508 if isinstance (obj
, gameobjects
.HealthPotion
) is True:
509 if self
.butaba
.health
< constants
.MAXHEALTH
:
510 obj
.use (self
.butaba
)
511 container
.objects
.remove (obj
)
512 self
.status_message
= "You gained health"
514 self
.status_message
= "You already have maximum health!"
515 # if the object is a chest
516 elif isinstance (obj
, gameobjects
.Chest
) is True:
517 # if chest is locked, try to open it
518 if obj
.locked
is True:
519 # try opening the chest with every item 9the use () function
520 # of the chest determines if item is a key anyway
522 for invobj
in self
.butaba
.objects
:
523 fittedkey
= obj
.use (invobj
)
525 if fittedkey
is not None:
528 if fittedkey
is None:
529 self
.status_message
= "No key found to open %s" % obj
.text
530 # chest successfully unlocked
532 self
.status_message
= "You unlocked the %s" % obj
.text
533 # remove the key from Butaba
534 self
.butaba
.objects
.remove (fittedkey
)
535 # add an experience point for unlocking chest subject
536 # to a limit of KNOWLEDGEMAX_CHEST_UNLOCK
537 if self
.butaba
.experience
< constants
.KNOWLEDGEMAX_CHEST_UNLOCK
:
538 self
.butaba
.experience
+= 1
539 self
.status_message
+= " and gained experience!"
540 # display the contents of the chest
542 item
= utility
.get_container_object (self
.screen
, obj
, self
.img_chestbg
, 30)
544 self
.interact_objects (obj
, [ item
, ])
546 # if the object is gold coins
547 elif isinstance (obj
, gameobjects
.GoldCoins
) is True:
548 obj
.use (self
.butaba
)
549 self
.status_message
= "You picked up %d gold." % obj
.value
550 # remove the gold coins after adding it to Butaba's gold
551 container
.objects
.remove (obj
)
552 # using a bucket means emptying it
553 elif isinstance (obj
, gameobjects
.Bucket
) is True:
554 if obj
.liquid
is not None:
555 self
.status_message
= "You emptied the bucket of %s" % obj
.liquid
556 obj
.use (self
.butaba
)
558 self
.status_message
= "Bucket is already empty."
560 elif isinstance (obj
, gameobjects
.Well
) is True:
561 # if the well is not dry, i.e. it has some liquid
562 if obj
.liquid
is not None:
563 # search butaba inventory for an empty bucket
564 for invobj
in self
.butaba
.objects
:
565 # bucket found, now check if it is empty
566 if isinstance (invobj
, gameobjects
.Bucket
) is True:
568 if invobj
.liquid
is None:
570 self
.status_message
= "You successfully filled the %s with %s" % (invobj
.text
, obj
.liquid
)
571 if self
.butaba
.strength
< constants
.STRENGTHMAX_DRAW_WELL_WATER
:
572 self
.butaba
.strength
+= 2
573 self
.status_message
+= " and gained strength!"
575 self
.status_message
= "You have no empty bucket to draw %s with!" % obj
.liquid
577 self
.status_message
= "%s appears to be dry!" % obj
.text
579 def move_butaba_left (self
):
580 # clear any status messages
581 self
.status_message
= None
583 # first if Butaba is not facing left, make him face left
584 if self
.butaba
.position
<> constants
.LEFT
:
585 self
.butaba
.position
= constants
.LEFT
588 # if butaba is trying to move off the left edge
589 if self
.butaba
.col
<= 0:
590 # if there is a level to the right set current level to that one
591 if self
.currentlevel
.levelleft
is not None:
592 # get the last column of the previous level
593 lastcol
= len (self
.currentlevel
.levelleft
.background
[0]) - 1
594 # interact with objects if any
595 # if any object is a blocking object then avoid movement
596 if self
.level_interact (self
.currentlevel
.levelleft
, self
.butaba
.row
, lastcol
) is False:
598 # make sure there is no obstacle at that position of movement
599 if self
.check_background_obstacle (self
.currentlevel
.levelleft
, self
.butaba
.row
, lastcol
) is False:
600 self
.currentlevel
= self
.currentlevel
.levelleft
601 self
.butaba
.col
= lastcol
602 # normal left movement
604 # interact with objects if any
605 # if any object is a blocking object then avoid movement
606 if self
.level_interact (self
.currentlevel
, self
.butaba
.row
, self
.butaba
.col
-1) is False:
608 if self
.check_background_obstacle (self
.currentlevel
, self
.butaba
.row
, self
.butaba
.col
-1) is False:
611 def move_butaba_right (self
):
612 # clear any status messages
613 self
.status_message
= None
615 # First if Butaba is not facing right make him face right
616 if self
.butaba
.position
<> constants
.RIGHT
:
617 self
.butaba
.position
= constants
.RIGHT
620 # if butaba is trying to move off the right edge
621 if self
.butaba
.col
>= len (self
.currentlevel
.background
[0])-1:
622 # if there is a level to the right swap current level with that one
623 if self
.currentlevel
.levelright
is not None:
624 # interact with objects if any
625 # if any object is a blocking object then avoid movement
626 if self
.level_interact (self
.currentlevel
.levelright
, self
.butaba
.row
, 0) is False:
629 # make sure there is no obstacle at that position of movement
630 # get the last column of the previous level
631 if self
.check_background_obstacle (self
.currentlevel
.levelright
, self
.butaba
.row
, 0) is False:
632 self
.currentlevel
= self
.currentlevel
.levelright
634 # normal right movement
636 # interact with objects if any
637 # if any object is a blocking object then avoid moving
638 if self
.level_interact (self
.currentlevel
, self
.butaba
.row
, self
.butaba
.col
+ 1) is False:
640 if self
.check_background_obstacle (self
.currentlevel
, self
.butaba
.row
, self
.butaba
.col
+ 1) is False:
643 def draw_butaba (self
):
644 if self
.butaba
.position
== constants
.FRONT
:
645 self
.screen
.blit (self
.butaba
.imagefront
, (self
.butaba
.col
*48, self
.butaba
.row
*48))
646 elif self
.butaba
.position
== constants
.BACK
:
647 self
.screen
.blit (self
.butaba
.imageback
, (self
.butaba
.col
*48, self
.butaba
.row
*48))
648 elif self
.butaba
.position
== constants
.LEFT
:
649 self
.screen
.blit (self
.butaba
.imageleft
, (self
.butaba
.col
*48, self
.butaba
.row
*48))
650 elif self
.butaba
.position
== constants
.RIGHT
:
651 self
.screen
.blit (self
.butaba
.imageright
, (self
.butaba
.col
*48, self
.butaba
.row
*48))
654 # Draw the status infodisplay
655 def draw_status (self
):
656 self
.screen
.blit (self
.img_redpotion
, (485, 10))
657 utility
.put_text (self
.screen
, 550, 25, 20, (255, 0, 0), "%d" % self
.butaba
.health
)
659 self
.screen
.blit (self
.img_lightning
, (620, 10))
660 utility
.put_text (self
.screen
, 660, 25, 20, (255,255,255), "%d" % self
.butaba
.strength
)
662 self
.screen
.blit (self
.img_wand
, (485, 65))
663 utility
.put_text (self
.screen
, 550, 75, 20, (0, 0, 255), "%d" % self
.butaba
.magic
)
665 self
.screen
.blit (self
.img_bulb
, (620, 65))
666 utility
.put_text (self
.screen
, 660, 75, 20, (0, 255, 0), "%d" % self
.butaba
.experience
)
668 self
.screen
.blit (self
.img_goldcoins
, (485, 110))
669 utility
.put_text (self
.screen
, 550, 130, 20, (255, 255, 0), "%d" % self
.butaba
.gold
)
671 if self
.status_message
is not None:
672 utility
.put_text (self
.screen
, 10, 485, 10, (255,255, 0), "%s" % self
.status_message
)
674 # display the inventory of the player
675 def draw_inventory (self
):
676 # draw the inventory slots
679 utility
.put_text (self
.screen
, 490, 170, 16, (255,255 , 0), "Inventory")
680 for i
in range (constants
.MAXITEMS
):
681 self
.screen
.blit (self
.img_inventory
, (440+c
*54, 150+r
*54))
690 for obj
in self
.butaba
.objects
:
691 self
.screen
.blit (obj
.image
, (440+c
*54+2, 150+r
*54+2))
698 # Draw the level background tiles on surface
699 def draw_level_background (self
, level
):
701 for row
in level
.background
:
703 for tilerow
, tilecol
, is_solid
in row
:
706 self
.screen
.blit (self
.img_tileset
, (j
*48, i
*48), pygame
.Rect (tilex
, tiley
, 48, 48))
711 # Draw the level objects
712 def draw_level_objects (self
, level
):
713 for obj
in level
.objects
:
714 if obj
.image
is not None:
715 self
.screen
.blit (obj
.image
, (obj
.col
*48, obj
.row
*48))
718 # Draw the NPCs in the level
719 def draw_level_npcs (self
, level
):
720 for npc
in level
.npcs
:
721 # if npc is not dead then move the NPC randomly depending on their
723 if npc
.is_dead
is False:
725 if random
.randint (1, 500) < npc
.movement_speed
:
726 # whether to change direction?
727 if random
.randint (1, 100) < 25:
728 npc
.position
= random
.randint (0, 3)
731 if npc
.position
== constants
.LEFT
:
732 # cannot move beyond level and cannot move beyond the
734 if npc
.col
> 0 and npc
.col
> npc
.initcol
- npc
.leftlimit
:
735 # check if there is any background obstacle
736 if self
.check_background_obstacle (level
, npc
.row
, npc
.col
- 1) is False:
737 # check if there are any objects
740 for lobj
in level
.objects
:
741 if lobj
.row
== npc
.row
and lobj
.col
== npc
.col
- 1:
744 # check if there any any npcs blocking
745 for lnpc
in level
.npcs
:
746 if lnpc
.row
== npc
.row
and lnpc
.col
== npc
.col
- 1:
749 if objblock
is False and npcblock
is False:
750 # if butaba is not blocking
751 if self
.butaba
.row
<> npc
.row
or self
.butaba
.col
<> npc
.col
- 1:
753 elif npc
.position
== constants
.RIGHT
:
754 # cannot move beyond level and cannot move beyond the
756 if npc
.col
< 9 and npc
.col
< npc
.initcol
+ npc
.rightlimit
:
757 # check if there is any background obstacle
758 if self
.check_background_obstacle (level
, npc
.row
, npc
.col
+ 1) is False:
759 # check if there are any objects
762 for lobj
in level
.objects
:
763 if lobj
.row
== npc
.row
and lobj
.col
== npc
.col
+ 1:
766 # check if there any any npcs blocking
767 for lnpc
in level
.npcs
:
768 if lnpc
.row
== npc
.row
and lnpc
.col
== npc
.col
+ 1:
771 if objblock
is False and npcblock
is False:
772 # if butaba is not blocking
773 if self
.butaba
.row
<> npc
.row
or self
.butaba
.col
<> npc
.col
+ 1:
775 elif npc
.position
== constants
.FRONT
:
776 # cannot move beyond level and cannot move beyond the
777 # lower bottom limit area
778 if npc
.row
< 9 and npc
.row
< npc
.initrow
+ npc
.bottomlimit
:
779 # check if there is any background obstacle
780 if self
.check_background_obstacle (level
, npc
.row
+ 1, npc
.col
) is False:
781 # check if there are any objects
784 for lobj
in level
.objects
:
785 if lobj
.row
== npc
.row
+ 1 and lobj
.col
== npc
.col
:
788 # check if there any any npcs blocking
789 for lnpc
in level
.npcs
:
790 if lnpc
.row
== npc
.row
+ 1 and lnpc
.col
== npc
.col
:
793 if objblock
is False and npcblock
is False:
794 # if butaba is not blocking
795 if self
.butaba
.row
<> npc
.row
+ 1 or self
.butaba
.col
<> npc
.col
:
797 elif npc
.position
== constants
.BACK
:
798 # cannot move beyond level and cannot move beyond the
799 # top upper limit area
800 if npc
.row
> 0 and npc
.row
> npc
.initrow
- npc
.toplimit
:
801 # check if there is any background obstacle
802 if self
.check_background_obstacle (level
, npc
.row
- 1, npc
.col
) is False:
803 # check if there are any objects
806 for lobj
in level
.objects
:
807 if lobj
.row
== npc
.row
- 1 and lobj
.col
== npc
.col
:
810 # check if there any any npcs blocking
811 for lnpc
in level
.npcs
:
812 if lnpc
.row
== npc
.row
- 1 and lnpc
.col
== npc
.col
:
815 # if no object is blocking
816 if objblock
is False and npcblock
is False:
817 # if butaba is not blocking
818 if self
.butaba
.row
<> npc
.row
- 1 or self
.butaba
.col
<> npc
.col
:
821 if npc
.position
== constants
.FRONT
:
823 elif npc
.position
== constants
.BACK
:
825 elif npc
.position
== constants
.LEFT
:
830 self
.screen
.blit (img
, (npc
.col
*48, npc
.row
*48))