16 self
.screen
= pygame
.display
.set_mode ((720, 512))
17 pygame
.display
.set_caption ("The Adventures of Butaba")
19 # initalize background graphics
20 self
.img_tileset
= pygame
.image
.load (os
.path
.join ("background", "tileset.png")).convert ()
22 self
.img_menu
= pygame
.image
.load (os
.path
.join ("background", "menu_screen.png")).convert ()
24 self
.img_inventory
= pygame
.image
.load (os
.path
.join ("background", "inventory.png")).convert ()
27 # initialize object graphics
28 self
.img_redpotion
= pygame
.image
.load (os
.path
.join ("objects", "red-potion.png")).convert ()
29 self
.img_redpotion
.set_colorkey (pygame
.Color (0, 255, 0))
30 self
.img_goldcoins
= pygame
.image
.load (os
.path
.join ("objects", "gold-coins.png")).convert ()
31 self
.img_goldcoins
.set_colorkey (pygame
.Color (0, 255, 0))
32 self
.img_wand
= pygame
.image
.load (os
.path
.join ("objects", "wand.png")).convert ()
33 self
.img_wand
.set_colorkey (pygame
.Color (0, 255, 0))
34 self
.img_bulb
= pygame
.image
.load (os
.path
.join ("objects", "bulb.png")).convert ()
35 self
.img_bulb
.set_colorkey (pygame
.Color (0, 255, 0))
36 self
.img_lightning
= pygame
.image
.load (os
.path
.join ("objects", "lightning.png")).convert ()
37 self
.img_lightning
.set_colorkey (pygame
.Color (0, 255, 0))
38 self
.img_key
= pygame
.image
.load (os
.path
.join ("objects", "key.png")).convert ()
39 self
.img_key
.set_colorkey (pygame
.Color (0, 255, 0))
40 self
.img_chest
= pygame
.image
.load (os
.path
.join ("objects", "chest.png")).convert ()
41 self
.img_chest
.set_colorkey (pygame
.Color (0, 255, 0))
43 # initialize player graphics
44 self
.img_butabafront
= pygame
.image
.load (os
.path
.join ("sprite", "butaba-front.png")).convert ()
45 self
.img_butabafront
.set_colorkey (pygame
.Color (0, 255, 0))
46 self
.img_butababack
= pygame
.image
.load (os
.path
.join ("sprite", "butaba-back.png")).convert ()
47 self
.img_butababack
.set_colorkey (pygame
.Color (0, 255, 0))
48 self
.img_butabaleft
= pygame
.image
.load (os
.path
.join ("sprite", "butaba-left.png")).convert ()
49 self
.img_butabaleft
.set_colorkey (pygame
.Color (0, 255, 0))
50 self
.img_butabaright
= pygame
.image
.load (os
.path
.join ("sprite", "butaba-right.png")).convert ()
51 self
.img_butabaright
.set_colorkey (pygame
.Color (0, 255, 0))
55 # set current level and position of our character
56 self
.currentlevel
= self
.level1
58 # set the status message
59 self
.status_message
= "Game started"
61 self
.butaba
= butaba
.Butaba (5,0, butaba
.Butaba
.RIGHT
, 75)
63 # set up the levels and their interactions
64 def setup_levels (self
):
66 self
.level1
= level
.Level (level
.LEVEL_1
)
67 self
.level1e
= level
.Level (level
.LEVEL_1E
,
68 objects
= [ gameobjects
.Key (4, 3, "a chest key", self
.img_key
, level
.KEY_CHEST1
),
69 gameobjects
.Key (4, 3, "a room key", self
.img_key
, level
.KEY_ROOM1
),
70 gameobjects
.HealthPotion (4, 2, self
.img_redpotion
),
71 gameobjects
.Chest (2, 5, "chest", self
.img_chest
, level
.KEY_CHEST1
, True)
74 self
.level1
.levelright
= self
.level1e
75 self
.level1e
.levelleft
= self
.level1
81 self
.screen
.fill (pygame
.Color (0,0,0))
83 self
.draw_level_background (self
.currentlevel
)
85 self
.draw_level_objects (self
.currentlevel
)
88 # display the character's inventory
89 self
.draw_inventory ()
90 # draw the status info
93 pygame
.display
.update ()
96 for event
in pygame
.event
.get ():
97 if event
.type == pygame
.QUIT
:
99 if event
.type == pygame
.KEYDOWN
:
100 if event
.key
== pygame
.K_UP
:
101 self
.move_butaba_up ()
102 elif event
.key
== pygame
.K_DOWN
:
103 self
.move_butaba_down ()
104 elif event
.key
== pygame
.K_LEFT
:
105 self
.move_butaba_left ()
106 elif event
.key
== pygame
.K_RIGHT
:
107 self
.move_butaba_right ()
109 def move_butaba_up (self
):
110 # clear any status messages
111 self
.status_message
= None
112 # first if butaba is not facing up, make him face up
113 if self
.butaba
.position
<> butaba
.Butaba
.BACK
:
114 self
.butaba
.position
= butaba
.Butaba
.BACK
117 # if butaba is trying to move off the top of the screen
118 if self
.butaba
.row
<= 0:
119 # if there is a level above set current level to that one
120 if self
.currentlevel
.leveltop
is not None:
121 lastrow
= len (self
.currentlevel
.leveltop
.background
) - 1
122 # if there is any object in that place interact with it
123 # if any object is a blocking object then avoid movement
124 if self
.interact_objects (self
.currentlevel
.leveltop
, lastrow
, self
.butaba
.col
) is False:
127 # make sure there is no obstacle
128 if self
.check_background_obstacle (self
.currentlevel
.leveltop
, lastrow
, self
.butaba
.col
) is False:
129 self
.currentlevel
= self
.currentlevel
.leveltop
130 self
.butaba
.row
= lastrow
131 # normal upward movement
133 # if there is any object in that place interact with it
134 # if any object is a blocking object then avoid movement
135 if self
.interact_objects (self
.currentlevel
, self
.butaba
.row
-1, self
.butaba
.col
) is False:
138 if self
.check_background_obstacle (self
.currentlevel
, self
.butaba
.row
-1, self
.butaba
.col
) is False:
141 def move_butaba_down (self
):
142 # clear any status messages
143 self
.status_message
= None
144 # first if butaba is not facing forward, make him face forward/down
145 if self
.butaba
.position
<> butaba
.Butaba
.FRONT
:
146 self
.butaba
.position
= butaba
.Butaba
.FRONT
149 # if butaba is trying to move off the bottom of the screen
150 if self
.butaba
.row
>= len (self
.currentlevel
.background
)-1:
151 # if there is a level below set current level to that one
152 if self
.currentlevel
.levelbottom
is not None:
153 # interact with objects if any
154 # if any object is a blocking object then avoid movement
155 if self
.interact_objects (self
.currentlevel
.levelbottom
, 0, self
.butaba
.col
) is False:
157 # make sure there is no obstacle at that position
158 if self
.check_background_obstacle (self
.currentlevel
.levelbottom
, 0, self
.butaba
.col
) is False:
159 self
.currentlevel
= self
.currentlevel
.levelbottom
161 # normal downward movement
163 # interact with objects if any
164 # if any object is a blocking object then avoid movement
165 if self
.interact_objects (self
.currentlevel
, self
.butaba
.row
+1, self
.butaba
.col
) is False:
167 if self
.check_background_obstacle (self
.currentlevel
, self
.butaba
.row
+1, self
.butaba
.col
) is False:
170 # check if a background tile is an obstacle
171 def check_background_obstacle (self
, level
, row
, col
):
172 if (level
.background
[row
][col
][2] == 1):
177 # get and interact with objects if present in a particular row/col
178 def interact_objects (self
, level
, row
, col
):
180 # get list of objects at current location
181 for obj
in level
.objects
:
182 if obj
.row
== row
and obj
.col
== col
:
185 # overall flag for blocking/non-blocking objects
187 # now perform interaction
189 # run the object interact function
190 if obj
.interact () is False:
192 # if object can be picked up ask
193 self
.pickup_object (obj
)
197 # picking up an object
198 def pickup_object (self
, obj
):
199 # only if object can be picked up, pick it up or use it
200 if obj
.can_pickup
is True:
201 ans
= utility
.ask_question (self
.screen
, "Found %s." % obj
.text
, ["Pick up", "Use", "Ignore"], self
.img_menu
)
202 # if the answer is "carry"
204 # check if the inventory is full
205 if len (self
.butaba
.inventory
) >= butaba
.Butaba
.MAXITEMS
:
206 self
.status_message
= "Failed. Inventory full"
208 # add item to inventory
209 self
.butaba
.inventory
.append (obj
)
210 self
.currentlevel
.objects
.remove (obj
)
212 self
.status_message
= "You picked up %s" % obj
.text
214 # use the object according to its type
215 self
.use_object (obj
)
216 # if it cannot be picked up, try to use it anyway
218 self
.use_object (obj
)
220 # this method uses the object first by calling the object use () method
221 # and then performing specific actions as necessary
222 def use_object (self
, obj
):
223 # if the object is a health potion
224 if isinstance (obj
, gameobjects
.HealthPotion
) is True:
225 obj
.use (self
.butaba
)
226 self
.currentlevel
.objects
.remove (obj
)
227 self
.status_message
= "You gained health"
228 # if the object is a chest
229 elif isinstance (obj
, gameobjects
.Chest
) is True:
230 # if chest is locked, try to open it
231 if obj
.locked
is True:
232 # try opening the chest with every item 9the use () function
233 # of the chest determines if item is a key anyway
235 for invobj
in self
.butaba
.inventory
:
236 fittedkey
= obj
.use (invobj
)
238 if fittedkey
is not None:
241 if fittedkey
is None:
242 self
.status_message
= "No key found to open %s" % obj
.text
243 # chest successfully unlocked
245 self
.status_message
= "You unlocked the %s" % obj
.text
246 # remove the key from inventory
247 self
.butaba
.inventory
.remove (fittedkey
)
248 # display the contents of the chest
252 def move_butaba_left (self
):
253 # clear any status messages
254 self
.status_message
= None
256 # first if Butaba is not facing left, make him face left
257 if self
.butaba
.position
<> butaba
.Butaba
.LEFT
:
258 self
.butaba
.position
= butaba
.Butaba
.LEFT
261 # if butaba is trying to move off the left edge
262 if self
.butaba
.col
<= 0:
263 # if there is a level to the right set current level to that one
264 if self
.currentlevel
.levelleft
is not None:
265 # get the last column of the previous level
266 lastcol
= len (self
.currentlevel
.levelleft
.background
[0]) - 1
267 # interact with objects if any
268 # if any object is a blocking object then avoid movement
269 if self
.interact_objects (self
.currentlevel
.levelleft
, self
.butaba
.row
, lastcol
) is False:
271 # make sure there is no obstacle at that position of movement
272 if self
.check_background_obstacle (self
.currentlevel
.levelleft
, self
.butaba
.row
, lastcol
) is False:
273 self
.currentlevel
= self
.currentlevel
.levelleft
274 self
.butaba
.col
= lastcol
275 # normal left movement
277 # interact with objects if any
278 # if any object is a blocking object then avoid movement
279 if self
.interact_objects (self
.currentlevel
, self
.butaba
.row
, self
.butaba
.col
-1) is False:
281 if self
.check_background_obstacle (self
.currentlevel
, self
.butaba
.row
, self
.butaba
.col
-1) is False:
284 def move_butaba_right (self
):
285 # clear any status messages
286 self
.status_message
= None
288 # First if Butaba is not facing right make him face right
289 if self
.butaba
.position
<> butaba
.Butaba
.RIGHT
:
290 self
.butaba
.position
= butaba
.Butaba
.RIGHT
293 # if butaba is trying to move off the right edge
294 if self
.butaba
.col
>= len (self
.currentlevel
.background
[0])-1:
295 # if there is a level to the right swap current level with that one
296 if self
.currentlevel
.levelright
is not None:
297 # interact with objects if any
298 # if any object is a blocking object then avoid movement
299 if self
.interact_objects (self
.currentlevel
.levelright
, self
.butaba
.row
, 0) is False:
302 # make sure there is no obstacle at that position of movement
303 # get the last column of the previous level
304 if self
.check_background_obstacle (self
.currentlevel
.levelright
, self
.butaba
.row
, 0) is False:
305 self
.currentlevel
= self
.currentlevel
.levelright
307 # normal right movement
309 # interact with objects if any
310 # if any object is a blocking object then avoid moving
311 if self
.interact_objects (self
.currentlevel
, self
.butaba
.row
, self
.butaba
.col
+ 1) is False:
313 if self
.check_background_obstacle (self
.currentlevel
, self
.butaba
.row
, self
.butaba
.col
+ 1) is False:
316 def draw_butaba (self
):
317 if self
.butaba
.position
== butaba
.Butaba
.FRONT
:
318 self
.screen
.blit (self
.img_butabafront
, (self
.butaba
.col
*48, self
.butaba
.row
*48))
319 elif self
.butaba
.position
== butaba
.Butaba
.BACK
:
320 self
.screen
.blit (self
.img_butababack
, (self
.butaba
.col
*48, self
.butaba
.row
*48))
321 elif self
.butaba
.position
== butaba
.Butaba
.LEFT
:
322 self
.screen
.blit (self
.img_butabaleft
, (self
.butaba
.col
*48, self
.butaba
.row
*48))
323 elif self
.butaba
.position
== butaba
.Butaba
.RIGHT
:
324 self
.screen
.blit (self
.img_butabaright
, (self
.butaba
.col
*48, self
.butaba
.row
*48))
327 # Draw the status infodisplay
328 def draw_status (self
):
329 self
.screen
.blit (self
.img_redpotion
, (485, 10))
330 utility
.put_text (self
.screen
, 550, 25, 24, (255, 0, 0), "%d" % self
.butaba
.health
)
332 self
.screen
.blit (self
.img_lightning
, (620, 10))
333 utility
.put_text (self
.screen
, 660, 20, 24, (255,255,255), "%d" % self
.butaba
.strength
)
335 self
.screen
.blit (self
.img_wand
, (485, 65))
336 utility
.put_text (self
.screen
, 550, 75, 24, (0, 0, 255), "%d" % self
.butaba
.magic
)
338 self
.screen
.blit (self
.img_bulb
, (620, 65))
339 utility
.put_text (self
.screen
, 660, 75, 24, (0, 255, 0), "%d" % self
.butaba
.experience
)
341 self
.screen
.blit (self
.img_goldcoins
, (485, 110))
342 utility
.put_text (self
.screen
, 550, 130, 24, (255, 255, 0), "%d" % self
.butaba
.gold
)
344 if self
.status_message
is not None:
345 utility
.put_text (self
.screen
, 10, 485, 18, (255,255, 0), "%s" % self
.status_message
)
347 # display the inventory of the player
348 def draw_inventory (self
):
349 # draw the inventory slots
352 utility
.put_text (self
.screen
, 490, 170, 22, (255,255 , 0), "Inventory")
353 for i
in range (butaba
.Butaba
.MAXITEMS
):
354 self
.screen
.blit (self
.img_inventory
, (440+c
*54, 150+r
*54))
363 for obj
in self
.butaba
.inventory
:
364 self
.screen
.blit (obj
.image
, (440+c
*54+2, 150+r
*54+2))
371 # Draw the level background tiles on surface
372 def draw_level_background (self
, level
):
374 for row
in level
.background
:
376 for tilerow
, tilecol
, is_solid
in row
:
379 self
.screen
.blit (self
.img_tileset
, (j
*48, i
*48), pygame
.Rect (tilex
, tiley
, 48, 48))
384 # Draw the level objects
385 def draw_level_objects (self
, level
):
386 for obj
in level
.objects
:
387 if obj
.image
is not None:
388 self
.screen
.blit (obj
.image
, (obj
.col
*48, obj
.row
*48))