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") ] )
139 npc_mayor
= npcs
.Mayor (5, 4, self
.img_mayorleft
, self
.img_mayorright
,
140 self
.img_mayorfront
, self
.img_mayorback
,
141 self
.img_mayor_portrait
, constants
.FRONT
,
144 chest1
.objects
= [ gold50
, gold25
, key2
, gold10
]
147 self
.level1
= level
.Level (cPickle
.load (file (os
.path
.join ("levels", "level1.dat"))),
148 objects
= [ chest1
] )
150 self
.level1w
= level
.Level (cPickle
.load (file (os
.path
.join ("levels", "level1w.dat"))))
152 self
.level1e
= level
.Level (cPickle
.load (file (os
.path
.join ("levels", "level1e.dat"))),
153 objects
= [ potion
, chest2
], npcs
= [ npc_bulisa
])
155 self
.level1ee
= level
.Level (cPickle
.load (file (os
.path
.join ("levels", "level1ee.dat"))),
156 objects
= [ well1
, well2
, well3
, well4
])
158 self
.level1n
= level
.Level (cPickle
.load (file (os
.path
.join ("levels", "level1n.dat"))),
159 objects
= [ bucket
])
161 self
.level1nw
= level
.Level (cPickle
.load (file (os
.path
.join ("levels", "level1nw.dat"))))
163 self
.level1ne
= level
.Level (cPickle
.load (file (os
.path
.join ("levels", "level1ne.dat"))))
165 self
.level1nee
= level
.Level (cPickle
.load (file (os
.path
.join ("levels", "level1nee.dat"))))
167 self
.level1sw
= level
.Level (cPickle
.load (file (os
.path
.join ("levels", "level1sw.dat"))))
169 self
.level1sww
= level
.Level (cPickle
.load (file (os
.path
.join ("levels", "level1sww.dat"))))
171 self
.level1ww
= level
.Level (cPickle
.load (file (os
.path
.join ("levels", "level1ww.dat"))),
172 npcs
= [ npc_mayor
])
174 # set up the interaction between levels (level exits)
175 self
.level1
.levelright
= self
.level1e
176 self
.level1
.levelleft
= self
.level1w
177 self
.level1e
.levelleft
= self
.level1
178 self
.level1e
.levelright
= self
.level1ee
179 self
.level1ee
.levelleft
= self
.level1e
180 self
.level1w
.levelright
= self
.level1
181 self
.level1
.leveltop
= self
.level1n
182 self
.level1n
.levelbottom
= self
.level1
183 self
.level1n
.levelleft
= self
.level1nw
184 self
.level1w
.leveltop
= self
.level1nw
185 self
.level1nw
.levelright
= self
.level1n
186 self
.level1nw
.levelbottom
= self
.level1w
187 self
.level1n
.levelright
= self
.level1ne
188 self
.level1e
.leveltop
= self
.level1ne
189 self
.level1ne
.levelleft
= self
.level1n
190 self
.level1ne
.levelbottom
= self
.level1e
191 self
.level1ne
.levelright
= self
.level1nee
192 self
.level1ee
.leveltop
= self
.level1nee
193 self
.level1nee
.levelleft
= self
.level1ne
194 self
.level1nee
.levelbottom
= self
.level1ee
195 self
.level1sw
.leveltop
= self
.level1w
196 self
.level1w
.levelbottom
= self
.level1sw
197 self
.level1sww
.levelright
= self
.level1sw
198 self
.level1sw
.levelleft
= self
.level1sww
199 self
.level1ww
.levelright
= self
.level1w
200 self
.level1ww
.levelbottom
= self
.level1sww
201 self
.level1sww
.leveltop
= self
.level1ww
202 self
.level1w
.levelleft
= self
.level1ww
204 def main_loop (self
):
209 self
.screen
.fill (pygame
.Color (0,0,0))
211 self
.draw_level_background (self
.currentlevel
)
213 self
.draw_level_objects (self
.currentlevel
)
214 # draw the NPCs in the level
215 self
.draw_level_npcs (self
.currentlevel
)
218 # display the character's inventory
219 self
.draw_inventory ()
220 # draw the status info
223 pygame
.display
.update ()
225 # get keyboard events
226 for event
in pygame
.event
.get ():
227 if event
.type == pygame
.QUIT
:
230 if event
.type == pygame
.KEYDOWN
:
231 if event
.key
== pygame
.K_UP
:
232 self
.move_butaba_up ()
233 elif event
.key
== pygame
.K_DOWN
:
234 self
.move_butaba_down ()
235 elif event
.key
== pygame
.K_LEFT
:
236 self
.move_butaba_left ()
237 elif event
.key
== pygame
.K_RIGHT
:
238 self
.move_butaba_right ()
239 # drinking health potion in inventory
240 elif event
.key
== ord ("h") or event
.key
== ord ("H"):
241 self
.inventory_drink_health_potion ()
243 elif event
.key
== ord ("q") or event
.key
== ord ("Q"):
246 # drink a health potion if it is in the player's inventory
247 def inventory_drink_health_potion (self
):
248 # look for a health potion
249 for item
in self
.butaba
.objects
:
250 if isinstance (item
, gameobjects
.HealthPotion
) is True:
251 self
.use_object (self
.butaba
, item
)
254 def move_butaba_up (self
):
255 # clear any status messages
256 self
.status_message
= None
257 # first if butaba is not facing up, make him face up
258 if self
.butaba
.position
<> constants
.BACK
:
259 self
.butaba
.position
= constants
.BACK
262 # if butaba is trying to move off the top of the screen
263 if self
.butaba
.row
<= 0:
264 # if there is a level above set current level to that one
265 if self
.currentlevel
.leveltop
is not None:
266 lastrow
= len (self
.currentlevel
.leveltop
.background
) - 1
267 # interact with objects
268 if self
.level_interact (self
.currentlevel
.leveltop
, lastrow
, self
.butaba
.col
) is False:
271 # make sure there is no obstacle
272 if self
.check_background_obstacle (self
.currentlevel
.leveltop
, lastrow
, self
.butaba
.col
) is False:
273 self
.currentlevel
= self
.currentlevel
.leveltop
274 self
.butaba
.row
= lastrow
275 # normal upward movement
277 # if there is any object in that place interact with it
278 # if any object is a blocking object then avoid movement
279 if self
.level_interact (self
.currentlevel
, self
.butaba
.row
-1, self
.butaba
.col
) is False:
282 if self
.check_background_obstacle (self
.currentlevel
, self
.butaba
.row
-1, self
.butaba
.col
) is False:
285 def move_butaba_down (self
):
286 # clear any status messages
287 self
.status_message
= None
288 # first if butaba is not facing forward, make him face forward/down
289 if self
.butaba
.position
<> constants
.FRONT
:
290 self
.butaba
.position
= constants
.FRONT
293 # if butaba is trying to move off the bottom of the screen
294 if self
.butaba
.row
>= len (self
.currentlevel
.background
)-1:
295 # if there is a level below set current level to that one
296 if self
.currentlevel
.levelbottom
is not None:
297 # interact with objects if any
298 # if any object is a blocking object then avoid movement
299 if self
.level_interact (self
.currentlevel
.levelbottom
, 0, self
.butaba
.col
) is False:
301 # make sure there is no obstacle at that position
302 if self
.check_background_obstacle (self
.currentlevel
.levelbottom
, 0, self
.butaba
.col
) is False:
303 self
.currentlevel
= self
.currentlevel
.levelbottom
305 # normal downward movement
307 # interact with objects if any
308 # if any object is a blocking object then avoid movement
309 if self
.level_interact (self
.currentlevel
, self
.butaba
.row
+1, self
.butaba
.col
) is False:
311 if self
.check_background_obstacle (self
.currentlevel
, self
.butaba
.row
+1, self
.butaba
.col
) is False:
314 # check if a background tile is an obstacle
315 def check_background_obstacle (self
, level
, row
, col
):
316 if (level
.background
[row
][col
][2] == 1):
321 # get and interact with objects and characters if present in a particular row/col
322 def level_interact (self
, level
, row
, col
):
324 # get list of objects at current location
325 for obj
in level
.objects
:
326 if obj
.row
== row
and obj
.col
== col
:
329 notblock
= self
.interact_objects (level
, objs
)
331 # get npc at current location
333 for npc
in level
.npcs
:
334 if npc
.row
== row
and npc
.col
== col
:
338 # npcs always block the tile. So return false if there is an NPC
340 if current_npc
is not None:
341 self
.interact_npc (current_npc
)
346 # interaction with npcs
347 def interact_npc (self
, npc
):
348 # interact with NPC and get the response ID
349 # if the NPC is Bulisa
351 # if the NPC is dead cannot talk with the NPC
352 if npc
.is_dead
is True:
353 self
.status_message
= "%s is dead! RIP..." % npc
.charname
356 if isinstance (npc
, npcs
.Bulisa
):
357 # interact with Bulisa
358 self
.interact_npc_bulisa (npc
)
360 # interact with NPC Bulisa
361 def interact_npc_bulisa (self
, npc
):
362 # set initial response ID to none
365 # check for global game states (starting from later flags to earlier ones
367 # whether the drawing water from well mission completed
368 if gamestate
.flag
["mission_charity_informed"] is True:
369 npc
.currentdialog
= 5
370 resp_id
= utility
.dialogue_play (self
.screen
, self
.img_dialogue
, npc
, self
.butaba
.portrait
, 0, 90)
371 elif gamestate
.flag
['mission_bulisa_water_from_well_complete'] is True:
372 npc
.currentdialog
= 4
373 resp_id
= utility
.dialogue_play (self
.screen
, self
.img_dialogue
, npc
, self
.butaba
.portrait
, 0, 90)
374 # whether the drawing water from well mission refused
375 elif gamestate
.flag
['mission_bulisa_water_from_well_refused'] is True:
376 npc
.currentdialog
= 2
377 resp_id
= utility
.dialogue_play (self
.screen
, self
.img_dialogue
, npc
, self
.butaba
.portrait
, 0, 90)
378 # whether the drawing water from well mission is accepted
379 elif gamestate
.flag
['mission_bulisa_water_from_well'] is True:
380 # check if butaba has a bucket full of water
381 for invobj
in self
.butaba
.objects
:
382 if isinstance (invobj
, gameobjects
.Bucket
) is True:
383 # if yes, then mission is completed accordingly
384 if invobj
.liquid
== "water":
385 gamestate
.flag
["mission_bulisa_water_from_well_complete"] = True
386 self
.butaba
.objects
.remove (invobj
)
387 key1
= gameobjects
.Key (5, 3, "a chest key", self
.img_key2
, constants
.KEY_CHEST1
)
388 self
.butaba
.objects
.append (key1
)
390 # water mission is not completed yet
391 if gamestate
.flag
["mission_bulisa_water_from_well_complete"] is False:
392 npc
.currentdialog
= 1
394 npc
.currentdialog
= 3
395 # get the response ID
396 resp_id
= utility
.dialogue_play (self
.screen
, self
.img_dialogue
, npc
, self
.butaba
.portrait
, 0, 90)
397 # Butaba hasn't been told about the initial mission yet, so tell him now
399 npc
.currentdialog
= 0
400 # get the response ID
401 resp_id
= utility
.dialogue_play (self
.screen
, self
.img_dialogue
, npc
, self
.butaba
.portrait
, 0, 90)
404 # Check each response
406 # Drawing water from well mission is refused
407 if resp_id
== "refusedwatermission":
408 gamestate
.flag
["mission_bulisa_water_from_well_refused"] = True
409 # Drawing water from well mission begins
410 elif resp_id
== "acceptedwatermission":
411 gamestate
.flag
["mission_bulisa_water_from_well"] = True
412 gamestate
.flag
["mission_bulisa_water_from_well_refused"] = False
413 # Butaba is informed about the mayor's charity
414 elif resp_id
== "informedcharitymission":
415 gamestate
.flag
["mission_charity_informed"] = True
416 # if response ID is none
417 elif resp_id
is None:
418 self
.status_message
= "You cannot initiate a conversation with %s" % npc
.charname
420 # interaction with objects
421 def interact_objects (self
, container
, objs
):
422 # overall flag for blocking/non-blocking objects
425 # now perform interaction
427 # run the object interact function
428 if obj
.interact () is False:
430 # if object can be picked up ask
431 if obj
.can_pickup
is True:
432 ans
= utility
.ask_question (self
.screen
, "Found %s." % obj
.text
, ["Pick up", obj
.use_str
, "Ignore"], self
.img_menu
)
433 # if the answer is "pick up"
435 self
.pickup_object (container
, obj
)
437 # use the object according to its type
438 self
.use_object (container
, obj
)
439 # if it cannot be picked up, try to use it anyway
441 ans
= utility
.ask_question (self
.screen
, "Found %s." % obj
.text
, [obj
.use_str
, "Ignore"], self
.img_menu
)
443 self
.use_object (container
, obj
)
447 # transfer an object from one container to another
448 # container must have an objects list
449 def transfer_object (self
, source
, obj
, dest
):
450 # remove object from source
451 source
.objects
.remove (obj
)
452 # add object to destination
453 dest
.objects
.append (obj
)
455 # picking up an object
456 def pickup_object (self
, container
, obj
):
457 # only if object can be picked up, pick it up or use it
458 if obj
.can_pickup
is True:
459 # check if the inventory is full
460 if len (self
.butaba
.objects
) >= constants
.MAXITEMS
:
461 self
.status_message
= "Cannot pick up item. Inventory full"
463 # add item to inventory
464 self
.transfer_object (container
, obj
, self
.butaba
)
466 self
.status_message
= "You picked up %s" % obj
.text
468 # this method uses the object first by calling the object use () method
469 # and then performing specific actions as necessary
470 def use_object (self
, container
, obj
):
471 # if the object is a health potion
472 if isinstance (obj
, gameobjects
.HealthPotion
) is True:
473 if self
.butaba
.health
< constants
.MAXHEALTH
:
474 obj
.use (self
.butaba
)
475 container
.objects
.remove (obj
)
476 self
.status_message
= "You gained health"
478 self
.status_message
= "You already have maximum health!"
479 # if the object is a chest
480 elif isinstance (obj
, gameobjects
.Chest
) is True:
481 # if chest is locked, try to open it
482 if obj
.locked
is True:
483 # try opening the chest with every item 9the use () function
484 # of the chest determines if item is a key anyway
486 for invobj
in self
.butaba
.objects
:
487 fittedkey
= obj
.use (invobj
)
489 if fittedkey
is not None:
492 if fittedkey
is None:
493 self
.status_message
= "No key found to open %s" % obj
.text
494 # chest successfully unlocked
496 self
.status_message
= "You unlocked the %s" % obj
.text
497 # remove the key from Butaba
498 self
.butaba
.objects
.remove (fittedkey
)
499 # add an experience point for unlocking chest subject
500 # to a limit of KNOWLEDGEMAX_CHEST_UNLOCK
501 if self
.butaba
.experience
< constants
.KNOWLEDGEMAX_CHEST_UNLOCK
:
502 self
.butaba
.experience
+= 1
503 self
.status_message
+= " and gained experience!"
504 # display the contents of the chest
506 item
= utility
.get_container_object (self
.screen
, obj
, self
.img_chestbg
, 30)
508 self
.interact_objects (obj
, [ item
, ])
510 # if the object is gold coins
511 elif isinstance (obj
, gameobjects
.GoldCoins
) is True:
512 obj
.use (self
.butaba
)
513 self
.status_message
= "You picked up %d gold." % obj
.value
514 # remove the gold coins after adding it to Butaba's gold
515 container
.objects
.remove (obj
)
516 # using a bucket means emptying it
517 elif isinstance (obj
, gameobjects
.Bucket
) is True:
518 if obj
.liquid
is not None:
519 self
.status_message
= "You emptied the bucket of %s" % obj
.liquid
520 obj
.use (self
.butaba
)
522 self
.status_message
= "Bucket is already empty."
524 elif isinstance (obj
, gameobjects
.Well
) is True:
525 # if the well is not dry, i.e. it has some liquid
526 if obj
.liquid
is not None:
527 # search butaba inventory for an empty bucket
528 for invobj
in self
.butaba
.objects
:
529 # bucket found, now check if it is empty
530 if isinstance (invobj
, gameobjects
.Bucket
) is True:
532 if invobj
.liquid
is None:
534 self
.status_message
= "You successfully filled the %s with %s" % (invobj
.text
, obj
.liquid
)
535 if self
.butaba
.strength
< constants
.STRENGTHMAX_DRAW_WELL_WATER
:
536 self
.butaba
.strength
+= 2
537 self
.status_message
+= " and gained strength!"
539 self
.status_message
= "You have no empty bucket to draw %s with!" % obj
.liquid
541 self
.status_message
= "%s appears to be dry!" % obj
.text
543 def move_butaba_left (self
):
544 # clear any status messages
545 self
.status_message
= None
547 # first if Butaba is not facing left, make him face left
548 if self
.butaba
.position
<> constants
.LEFT
:
549 self
.butaba
.position
= constants
.LEFT
552 # if butaba is trying to move off the left edge
553 if self
.butaba
.col
<= 0:
554 # if there is a level to the right set current level to that one
555 if self
.currentlevel
.levelleft
is not None:
556 # get the last column of the previous level
557 lastcol
= len (self
.currentlevel
.levelleft
.background
[0]) - 1
558 # interact with objects if any
559 # if any object is a blocking object then avoid movement
560 if self
.level_interact (self
.currentlevel
.levelleft
, self
.butaba
.row
, lastcol
) is False:
562 # make sure there is no obstacle at that position of movement
563 if self
.check_background_obstacle (self
.currentlevel
.levelleft
, self
.butaba
.row
, lastcol
) is False:
564 self
.currentlevel
= self
.currentlevel
.levelleft
565 self
.butaba
.col
= lastcol
566 # normal left movement
568 # interact with objects if any
569 # if any object is a blocking object then avoid movement
570 if self
.level_interact (self
.currentlevel
, self
.butaba
.row
, self
.butaba
.col
-1) is False:
572 if self
.check_background_obstacle (self
.currentlevel
, self
.butaba
.row
, self
.butaba
.col
-1) is False:
575 def move_butaba_right (self
):
576 # clear any status messages
577 self
.status_message
= None
579 # First if Butaba is not facing right make him face right
580 if self
.butaba
.position
<> constants
.RIGHT
:
581 self
.butaba
.position
= constants
.RIGHT
584 # if butaba is trying to move off the right edge
585 if self
.butaba
.col
>= len (self
.currentlevel
.background
[0])-1:
586 # if there is a level to the right swap current level with that one
587 if self
.currentlevel
.levelright
is not None:
588 # interact with objects if any
589 # if any object is a blocking object then avoid movement
590 if self
.level_interact (self
.currentlevel
.levelright
, self
.butaba
.row
, 0) is False:
593 # make sure there is no obstacle at that position of movement
594 # get the last column of the previous level
595 if self
.check_background_obstacle (self
.currentlevel
.levelright
, self
.butaba
.row
, 0) is False:
596 self
.currentlevel
= self
.currentlevel
.levelright
598 # normal right movement
600 # interact with objects if any
601 # if any object is a blocking object then avoid moving
602 if self
.level_interact (self
.currentlevel
, self
.butaba
.row
, self
.butaba
.col
+ 1) is False:
604 if self
.check_background_obstacle (self
.currentlevel
, self
.butaba
.row
, self
.butaba
.col
+ 1) is False:
607 def draw_butaba (self
):
608 if self
.butaba
.position
== constants
.FRONT
:
609 self
.screen
.blit (self
.butaba
.imagefront
, (self
.butaba
.col
*48, self
.butaba
.row
*48))
610 elif self
.butaba
.position
== constants
.BACK
:
611 self
.screen
.blit (self
.butaba
.imageback
, (self
.butaba
.col
*48, self
.butaba
.row
*48))
612 elif self
.butaba
.position
== constants
.LEFT
:
613 self
.screen
.blit (self
.butaba
.imageleft
, (self
.butaba
.col
*48, self
.butaba
.row
*48))
614 elif self
.butaba
.position
== constants
.RIGHT
:
615 self
.screen
.blit (self
.butaba
.imageright
, (self
.butaba
.col
*48, self
.butaba
.row
*48))
618 # Draw the status infodisplay
619 def draw_status (self
):
620 self
.screen
.blit (self
.img_redpotion
, (485, 10))
621 utility
.put_text (self
.screen
, 550, 25, 20, (255, 0, 0), "%d" % self
.butaba
.health
)
623 self
.screen
.blit (self
.img_lightning
, (620, 10))
624 utility
.put_text (self
.screen
, 660, 25, 20, (255,255,255), "%d" % self
.butaba
.strength
)
626 self
.screen
.blit (self
.img_wand
, (485, 65))
627 utility
.put_text (self
.screen
, 550, 75, 20, (0, 0, 255), "%d" % self
.butaba
.magic
)
629 self
.screen
.blit (self
.img_bulb
, (620, 65))
630 utility
.put_text (self
.screen
, 660, 75, 20, (0, 255, 0), "%d" % self
.butaba
.experience
)
632 self
.screen
.blit (self
.img_goldcoins
, (485, 110))
633 utility
.put_text (self
.screen
, 550, 130, 20, (255, 255, 0), "%d" % self
.butaba
.gold
)
635 if self
.status_message
is not None:
636 utility
.put_text (self
.screen
, 10, 485, 10, (255,255, 0), "%s" % self
.status_message
)
638 # display the inventory of the player
639 def draw_inventory (self
):
640 # draw the inventory slots
643 utility
.put_text (self
.screen
, 490, 170, 16, (255,255 , 0), "Inventory")
644 for i
in range (constants
.MAXITEMS
):
645 self
.screen
.blit (self
.img_inventory
, (440+c
*54, 150+r
*54))
654 for obj
in self
.butaba
.objects
:
655 self
.screen
.blit (obj
.image
, (440+c
*54+2, 150+r
*54+2))
662 # Draw the level background tiles on surface
663 def draw_level_background (self
, level
):
665 for row
in level
.background
:
667 for tilerow
, tilecol
, is_solid
in row
:
670 self
.screen
.blit (self
.img_tileset
, (j
*48, i
*48), pygame
.Rect (tilex
, tiley
, 48, 48))
675 # Draw the level objects
676 def draw_level_objects (self
, level
):
677 for obj
in level
.objects
:
678 if obj
.image
is not None:
679 self
.screen
.blit (obj
.image
, (obj
.col
*48, obj
.row
*48))
682 # Draw the NPCs in the level
683 def draw_level_npcs (self
, level
):
684 for npc
in level
.npcs
:
685 # if npc is not dead then move the NPC randomly depending on their
687 if npc
.is_dead
is False:
689 if random
.randint (1, 500) < npc
.movement_speed
:
690 # whether to change direction?
691 if random
.randint (1, 100) < 25:
692 npc
.position
= random
.randint (0, 3)
695 if npc
.position
== constants
.LEFT
:
696 # cannot move beyond level and cannot move beyond the
698 if npc
.col
> 0 and npc
.col
> npc
.initcol
- npc
.leftlimit
:
699 # check if there is any background obstacle
700 if self
.check_background_obstacle (level
, npc
.row
, npc
.col
- 1) is False:
701 # check if there are any objects
704 for lobj
in level
.objects
:
705 if lobj
.row
== npc
.row
and lobj
.col
== npc
.col
- 1:
708 # check if there any any npcs blocking
709 for lnpc
in level
.npcs
:
710 if lnpc
.row
== npc
.row
and lnpc
.col
== npc
.col
- 1:
713 if objblock
is False and npcblock
is False:
714 # if butaba is not blocking
715 if self
.butaba
.row
<> npc
.row
or self
.butaba
.col
<> npc
.col
- 1:
717 elif npc
.position
== constants
.RIGHT
:
718 # cannot move beyond level and cannot move beyond the
720 if npc
.col
< 9 and npc
.col
< npc
.initcol
+ npc
.rightlimit
:
721 # check if there is any background obstacle
722 if self
.check_background_obstacle (level
, npc
.row
, npc
.col
+ 1) is False:
723 # check if there are any objects
726 for lobj
in level
.objects
:
727 if lobj
.row
== npc
.row
and lobj
.col
== npc
.col
+ 1:
730 # check if there any any npcs blocking
731 for lnpc
in level
.npcs
:
732 if lnpc
.row
== npc
.row
and lnpc
.col
== npc
.col
+ 1:
735 if objblock
is False and npcblock
is False:
736 # if butaba is not blocking
737 if self
.butaba
.row
<> npc
.row
or self
.butaba
.col
<> npc
.col
+ 1:
739 elif npc
.position
== constants
.FRONT
:
740 # cannot move beyond level and cannot move beyond the
741 # lower bottom limit area
742 if npc
.row
< 9 and npc
.row
< npc
.initrow
+ npc
.bottomlimit
:
743 # check if there is any background obstacle
744 if self
.check_background_obstacle (level
, npc
.row
+ 1, npc
.col
) is False:
745 # check if there are any objects
748 for lobj
in level
.objects
:
749 if lobj
.row
== npc
.row
+ 1 and lobj
.col
== npc
.col
:
752 # check if there any any npcs blocking
753 for lnpc
in level
.npcs
:
754 if lnpc
.row
== npc
.row
+ 1 and lnpc
.col
== npc
.col
:
757 if objblock
is False and npcblock
is False:
758 # if butaba is not blocking
759 if self
.butaba
.row
<> npc
.row
+ 1 or self
.butaba
.col
<> npc
.col
:
761 elif npc
.position
== constants
.BACK
:
762 # cannot move beyond level and cannot move beyond the
763 # top upper limit area
764 if npc
.row
> 0 and npc
.row
> npc
.initrow
- npc
.toplimit
:
765 # check if there is any background obstacle
766 if self
.check_background_obstacle (level
, npc
.row
- 1, npc
.col
) is False:
767 # check if there are any objects
770 for lobj
in level
.objects
:
771 if lobj
.row
== npc
.row
- 1 and lobj
.col
== npc
.col
:
774 # check if there any any npcs blocking
775 for lnpc
in level
.npcs
:
776 if lnpc
.row
== npc
.row
- 1 and lnpc
.col
== npc
.col
:
779 # if no object is blocking
780 if objblock
is False and npcblock
is False:
781 # if butaba is not blocking
782 if self
.butaba
.row
<> npc
.row
- 1 or self
.butaba
.col
<> npc
.col
:
785 if npc
.position
== constants
.FRONT
:
787 elif npc
.position
== constants
.BACK
:
789 elif npc
.position
== constants
.LEFT
:
794 self
.screen
.blit (img
, (npc
.col
*48, npc
.row
*48))