17 self
.screen
= pygame
.display
.set_mode ((720, 512))
18 pygame
.display
.set_caption ("The Adventures of Butaba")
20 # initalize background graphics
21 self
.img_tileset
= pygame
.image
.load (os
.path
.join ("background", "tileset.png")).convert ()
23 self
.img_menu
= pygame
.image
.load (os
.path
.join ("background", "menu_screen.png")).convert ()
25 self
.img_inventory
= pygame
.image
.load (os
.path
.join ("background", "inventory.png")).convert ()
28 # initialize object graphics
29 self
.img_redpotion
= pygame
.image
.load (os
.path
.join ("objects", "red-potion.png")).convert ()
30 self
.img_redpotion
.set_colorkey (pygame
.Color (0, 255, 0))
31 self
.img_goldcoins
= pygame
.image
.load (os
.path
.join ("objects", "gold-coins.png")).convert ()
32 self
.img_goldcoins
.set_colorkey (pygame
.Color (0, 255, 0))
33 self
.img_wand
= pygame
.image
.load (os
.path
.join ("objects", "wand.png")).convert ()
34 self
.img_wand
.set_colorkey (pygame
.Color (0, 255, 0))
35 self
.img_bulb
= pygame
.image
.load (os
.path
.join ("objects", "bulb.png")).convert ()
36 self
.img_bulb
.set_colorkey (pygame
.Color (0, 255, 0))
37 self
.img_lightning
= pygame
.image
.load (os
.path
.join ("objects", "lightning.png")).convert ()
38 self
.img_lightning
.set_colorkey (pygame
.Color (0, 255, 0))
39 self
.img_key
= pygame
.image
.load (os
.path
.join ("objects", "key.png")).convert ()
40 self
.img_key
.set_colorkey (pygame
.Color (0, 255, 0))
41 self
.img_key2
= pygame
.image
.load (os
.path
.join ("objects", "key2.png")).convert ()
42 self
.img_key2
.set_colorkey (pygame
.Color (0, 255, 0))
43 self
.img_chest
= pygame
.image
.load (os
.path
.join ("objects", "chest.png")).convert ()
44 self
.img_chest
.set_colorkey (pygame
.Color (0, 255, 0))
46 # initialize player graphics
47 self
.img_butabafront
= pygame
.image
.load (os
.path
.join ("sprite", "butaba-front.png")).convert ()
48 self
.img_butabafront
.set_colorkey (pygame
.Color (0, 255, 0))
49 self
.img_butababack
= pygame
.image
.load (os
.path
.join ("sprite", "butaba-back.png")).convert ()
50 self
.img_butababack
.set_colorkey (pygame
.Color (0, 255, 0))
51 self
.img_butabaleft
= pygame
.image
.load (os
.path
.join ("sprite", "butaba-left.png")).convert ()
52 self
.img_butabaleft
.set_colorkey (pygame
.Color (0, 255, 0))
53 self
.img_butabaright
= pygame
.image
.load (os
.path
.join ("sprite", "butaba-right.png")).convert ()
54 self
.img_butabaright
.set_colorkey (pygame
.Color (0, 255, 0))
58 # set current level and position of our character
59 self
.currentlevel
= self
.level1
61 # set the status message
62 self
.status_message
= "Game started"
64 self
.butaba
= butaba
.Butaba (5,0, butaba
.Butaba
.RIGHT
, 75)
66 # set up the levels and their interactions
67 def setup_levels (self
):
69 self
.level1
= level
.Level (cPickle
.load (file ("levels/level1.dat")))
70 self
.level1w
= level
.Level (cPickle
.load (file ("levels/level1w.dat")))
71 self
.level1e
= level
.Level (cPickle
.load (file ("levels/level1e.dat")),
72 objects
= [ gameobjects
.Key (5, 3, "a chest key", self
.img_key2
, level
.KEY_CHEST1
),
73 gameobjects
.Key (5, 3, "a room key", self
.img_key
, level
.KEY_ROOM1
),
74 gameobjects
.HealthPotion (5, 2, self
.img_redpotion
),
75 gameobjects
.Chest (2, 5, "chest", self
.img_chest
, level
.KEY_CHEST1
, True),
76 gameobjects
.GoldCoins (6, 2, self
.img_goldcoins
, 50)
79 self
.level1
.levelright
= self
.level1e
80 self
.level1
.levelleft
= self
.level1w
82 self
.level1e
.levelleft
= self
.level1
84 self
.level1w
.levelright
= self
.level1
90 self
.screen
.fill (pygame
.Color (0,0,0))
92 self
.draw_level_background (self
.currentlevel
)
94 self
.draw_level_objects (self
.currentlevel
)
97 # display the character's inventory
98 self
.draw_inventory ()
99 # draw the status info
102 pygame
.display
.update ()
104 # get keyboard events
105 for event
in pygame
.event
.get ():
106 if event
.type == pygame
.QUIT
:
109 if event
.type == pygame
.KEYDOWN
:
110 if event
.key
== pygame
.K_UP
:
111 self
.move_butaba_up ()
112 elif event
.key
== pygame
.K_DOWN
:
113 self
.move_butaba_down ()
114 elif event
.key
== pygame
.K_LEFT
:
115 self
.move_butaba_left ()
116 elif event
.key
== pygame
.K_RIGHT
:
117 self
.move_butaba_right ()
118 # drinking health potion in inventory
119 elif event
.key
== ord ("h") or event
.key
== ord ("H"):
120 self
.inventory_drink_health_potion ()
122 elif event
.key
== ord ("q") or event
.key
== ord ("Q"):
125 # drink a health potion if it is in the player's inventory
126 def inventory_drink_health_potion (self
):
127 # if health is maxed out then ignore
128 if self
.butaba
.health
== butaba
.Butaba
.MAXHEALTH
:
129 self
.status_message
= "You already have maximum health."
131 # look for a health potion
132 for item
in self
.butaba
.inventory
:
133 if isinstance (item
, gameobjects
.HealthPotion
) is True:
134 self
.use_object (item
)
137 def move_butaba_up (self
):
138 # clear any status messages
139 self
.status_message
= None
140 # first if butaba is not facing up, make him face up
141 if self
.butaba
.position
<> butaba
.Butaba
.BACK
:
142 self
.butaba
.position
= butaba
.Butaba
.BACK
145 # if butaba is trying to move off the top of the screen
146 if self
.butaba
.row
<= 0:
147 # if there is a level above set current level to that one
148 if self
.currentlevel
.leveltop
is not None:
149 lastrow
= len (self
.currentlevel
.leveltop
.background
) - 1
150 # if there is any object in that place interact with it
151 # if any object is a blocking object then avoid movement
152 if self
.interact_objects (self
.currentlevel
.leveltop
, lastrow
, self
.butaba
.col
) is False:
155 # make sure there is no obstacle
156 if self
.check_background_obstacle (self
.currentlevel
.leveltop
, lastrow
, self
.butaba
.col
) is False:
157 self
.currentlevel
= self
.currentlevel
.leveltop
158 self
.butaba
.row
= lastrow
159 # normal upward movement
161 # if there is any object in that place interact with it
162 # if any object is a blocking object then avoid movement
163 if self
.interact_objects (self
.currentlevel
, self
.butaba
.row
-1, self
.butaba
.col
) is False:
166 if self
.check_background_obstacle (self
.currentlevel
, self
.butaba
.row
-1, self
.butaba
.col
) is False:
169 def move_butaba_down (self
):
170 # clear any status messages
171 self
.status_message
= None
172 # first if butaba is not facing forward, make him face forward/down
173 if self
.butaba
.position
<> butaba
.Butaba
.FRONT
:
174 self
.butaba
.position
= butaba
.Butaba
.FRONT
177 # if butaba is trying to move off the bottom of the screen
178 if self
.butaba
.row
>= len (self
.currentlevel
.background
)-1:
179 # if there is a level below set current level to that one
180 if self
.currentlevel
.levelbottom
is not None:
181 # interact with objects if any
182 # if any object is a blocking object then avoid movement
183 if self
.interact_objects (self
.currentlevel
.levelbottom
, 0, self
.butaba
.col
) is False:
185 # make sure there is no obstacle at that position
186 if self
.check_background_obstacle (self
.currentlevel
.levelbottom
, 0, self
.butaba
.col
) is False:
187 self
.currentlevel
= self
.currentlevel
.levelbottom
189 # normal downward movement
191 # interact with objects if any
192 # if any object is a blocking object then avoid movement
193 if self
.interact_objects (self
.currentlevel
, self
.butaba
.row
+1, self
.butaba
.col
) is False:
195 if self
.check_background_obstacle (self
.currentlevel
, self
.butaba
.row
+1, self
.butaba
.col
) is False:
198 # check if a background tile is an obstacle
199 def check_background_obstacle (self
, level
, row
, col
):
200 if (level
.background
[row
][col
][2] == 1):
205 # get and interact with objects if present in a particular row/col
206 def interact_objects (self
, level
, row
, col
):
208 # get list of objects at current location
209 for obj
in level
.objects
:
210 if obj
.row
== row
and obj
.col
== col
:
213 # overall flag for blocking/non-blocking objects
215 # now perform interaction
217 # run the object interact function
218 if obj
.interact () is False:
220 # if object can be picked up ask
221 self
.pickup_object (obj
)
225 # picking up an object
226 def pickup_object (self
, obj
):
227 # only if object can be picked up, pick it up or use it
228 if obj
.can_pickup
is True:
229 ans
= utility
.ask_question (self
.screen
, "Found %s." % obj
.text
, ["Pick up", "Use", "Ignore"], self
.img_menu
)
230 # if the answer is "carry"
232 # check if the inventory is full
233 if len (self
.butaba
.inventory
) >= butaba
.Butaba
.MAXITEMS
:
234 self
.status_message
= "Failed. Inventory full"
236 # add item to inventory
237 self
.butaba
.inventory
.append (obj
)
238 self
.currentlevel
.objects
.remove (obj
)
240 self
.status_message
= "You picked up %s" % obj
.text
242 # use the object according to its type
243 self
.use_object (obj
)
244 # if it cannot be picked up, try to use it anyway
246 self
.use_object (obj
)
248 # this method uses the object first by calling the object use () method
249 # and then performing specific actions as necessary
250 def use_object (self
, obj
):
251 # if the object is a health potion
252 if isinstance (obj
, gameobjects
.HealthPotion
) is True:
253 obj
.use (self
.butaba
)
254 if obj
in self
.currentlevel
.objects
:
255 self
.currentlevel
.objects
.remove (obj
)
256 elif obj
in self
.butaba
.inventory
:
257 self
.butaba
.inventory
.remove (obj
)
258 self
.status_message
= "You gained health"
259 # if the object is a chest
260 elif isinstance (obj
, gameobjects
.Chest
) is True:
261 # if chest is locked, try to open it
262 if obj
.locked
is True:
263 # try opening the chest with every item 9the use () function
264 # of the chest determines if item is a key anyway
266 for invobj
in self
.butaba
.inventory
:
267 fittedkey
= obj
.use (invobj
)
269 if fittedkey
is not None:
272 if fittedkey
is None:
273 self
.status_message
= "No key found to open %s" % obj
.text
274 # chest successfully unlocked
276 self
.status_message
= "You unlocked the %s" % obj
.text
277 # remove the key from inventory
278 self
.butaba
.inventory
.remove (fittedkey
)
279 # display the contents of the chest
282 # if the object is gold coins
283 elif isinstance (obj
, gameobjects
.GoldCoins
) is True:
284 obj
.use (self
.butaba
)
285 self
.status_message
= "You picked up %d gold." % obj
.value
286 # remove the gold coins after adding it to Butaba's gold
287 if obj
in self
.currentlevel
.objects
:
288 self
.currentlevel
.objects
.remove (obj
)
289 elif obj
in self
.butaba
.inventory
:
290 self
.butaba
.inventory
.remove (obj
)
292 def move_butaba_left (self
):
293 # clear any status messages
294 self
.status_message
= None
296 # first if Butaba is not facing left, make him face left
297 if self
.butaba
.position
<> butaba
.Butaba
.LEFT
:
298 self
.butaba
.position
= butaba
.Butaba
.LEFT
301 # if butaba is trying to move off the left edge
302 if self
.butaba
.col
<= 0:
303 # if there is a level to the right set current level to that one
304 if self
.currentlevel
.levelleft
is not None:
305 # get the last column of the previous level
306 lastcol
= len (self
.currentlevel
.levelleft
.background
[0]) - 1
307 # interact with objects if any
308 # if any object is a blocking object then avoid movement
309 if self
.interact_objects (self
.currentlevel
.levelleft
, self
.butaba
.row
, lastcol
) is False:
311 # make sure there is no obstacle at that position of movement
312 if self
.check_background_obstacle (self
.currentlevel
.levelleft
, self
.butaba
.row
, lastcol
) is False:
313 self
.currentlevel
= self
.currentlevel
.levelleft
314 self
.butaba
.col
= lastcol
315 # normal left movement
317 # interact with objects if any
318 # if any object is a blocking object then avoid movement
319 if self
.interact_objects (self
.currentlevel
, self
.butaba
.row
, self
.butaba
.col
-1) is False:
321 if self
.check_background_obstacle (self
.currentlevel
, self
.butaba
.row
, self
.butaba
.col
-1) is False:
324 def move_butaba_right (self
):
325 # clear any status messages
326 self
.status_message
= None
328 # First if Butaba is not facing right make him face right
329 if self
.butaba
.position
<> butaba
.Butaba
.RIGHT
:
330 self
.butaba
.position
= butaba
.Butaba
.RIGHT
333 # if butaba is trying to move off the right edge
334 if self
.butaba
.col
>= len (self
.currentlevel
.background
[0])-1:
335 # if there is a level to the right swap current level with that one
336 if self
.currentlevel
.levelright
is not None:
337 # interact with objects if any
338 # if any object is a blocking object then avoid movement
339 if self
.interact_objects (self
.currentlevel
.levelright
, self
.butaba
.row
, 0) is False:
342 # make sure there is no obstacle at that position of movement
343 # get the last column of the previous level
344 if self
.check_background_obstacle (self
.currentlevel
.levelright
, self
.butaba
.row
, 0) is False:
345 self
.currentlevel
= self
.currentlevel
.levelright
347 # normal right movement
349 # interact with objects if any
350 # if any object is a blocking object then avoid moving
351 if self
.interact_objects (self
.currentlevel
, self
.butaba
.row
, self
.butaba
.col
+ 1) is False:
353 if self
.check_background_obstacle (self
.currentlevel
, self
.butaba
.row
, self
.butaba
.col
+ 1) is False:
356 def draw_butaba (self
):
357 if self
.butaba
.position
== butaba
.Butaba
.FRONT
:
358 self
.screen
.blit (self
.img_butabafront
, (self
.butaba
.col
*48, self
.butaba
.row
*48))
359 elif self
.butaba
.position
== butaba
.Butaba
.BACK
:
360 self
.screen
.blit (self
.img_butababack
, (self
.butaba
.col
*48, self
.butaba
.row
*48))
361 elif self
.butaba
.position
== butaba
.Butaba
.LEFT
:
362 self
.screen
.blit (self
.img_butabaleft
, (self
.butaba
.col
*48, self
.butaba
.row
*48))
363 elif self
.butaba
.position
== butaba
.Butaba
.RIGHT
:
364 self
.screen
.blit (self
.img_butabaright
, (self
.butaba
.col
*48, self
.butaba
.row
*48))
367 # Draw the status infodisplay
368 def draw_status (self
):
369 self
.screen
.blit (self
.img_redpotion
, (485, 10))
370 utility
.put_text (self
.screen
, 550, 25, 20, (255, 0, 0), "%d" % self
.butaba
.health
)
372 self
.screen
.blit (self
.img_lightning
, (620, 10))
373 utility
.put_text (self
.screen
, 660, 25, 20, (255,255,255), "%d" % self
.butaba
.strength
)
375 self
.screen
.blit (self
.img_wand
, (485, 65))
376 utility
.put_text (self
.screen
, 550, 75, 20, (0, 0, 255), "%d" % self
.butaba
.magic
)
378 self
.screen
.blit (self
.img_bulb
, (620, 65))
379 utility
.put_text (self
.screen
, 660, 75, 20, (0, 255, 0), "%d" % self
.butaba
.experience
)
381 self
.screen
.blit (self
.img_goldcoins
, (485, 110))
382 utility
.put_text (self
.screen
, 550, 130, 20, (255, 255, 0), "%d" % self
.butaba
.gold
)
384 if self
.status_message
is not None:
385 utility
.put_text (self
.screen
, 10, 485, 16, (255,255, 0), "%s" % self
.status_message
)
387 # display the inventory of the player
388 def draw_inventory (self
):
389 # draw the inventory slots
392 utility
.put_text (self
.screen
, 490, 170, 16, (255,255 , 0), "Inventory")
393 for i
in range (butaba
.Butaba
.MAXITEMS
):
394 self
.screen
.blit (self
.img_inventory
, (440+c
*54, 150+r
*54))
403 for obj
in self
.butaba
.inventory
:
404 self
.screen
.blit (obj
.image
, (440+c
*54+2, 150+r
*54+2))
411 # Draw the level background tiles on surface
412 def draw_level_background (self
, level
):
414 for row
in level
.background
:
416 for tilerow
, tilecol
, is_solid
in row
:
419 self
.screen
.blit (self
.img_tileset
, (j
*48, i
*48), pygame
.Rect (tilex
, tiley
, 48, 48))
424 # Draw the level objects
425 def draw_level_objects (self
, level
):
426 for obj
in level
.objects
:
427 if obj
.image
is not None:
428 self
.screen
.blit (obj
.image
, (obj
.col
*48, obj
.row
*48))