1 """Provides high level functionality for accessing media from files"""
2 import os
3 import pygame
4 import pyzzle
5 import urlparse, urllib2
6
8 """Loads and stores data from files.
9
10 A pattern often emerges when handling files for video games:
11 check to see if a file exists in a group of folders organized by content type,
12 load the file if it exists, display a place-holder file if something goes wrong,
13 and most importantly, store the data in the event we want to reach it again.
14
15 The Library class handles this pattern. Libraries are used throughout
16 Pyzzle to lazily initialize persistant content in a Pythonic fashion.
17 Content from files can be loaded by either the load() method
18 (e.g. images.load('foobar.jpg')) or as a dictionary (e.g. images['foobar.jpg'] ).
19
20 In addition, a URL can be specified from which files will download in the
21 event they are not found on the local machine. This frees you from restrictions
22 imposed on the size of your distributable - a game from a 10 MB installer file
23 could access thousands of MB in content. """
24 - def __init__(self, folder, load, default=None, download=None):
25 """Creates a Library.
26 @param folder: The relative folder path from which content from this library
27 may be accessed.
28 @param load: The load function that runs upon requesting to load a file
29 for the first time. Accepts the name of the file and returns
30 the data contained within the file.
31 @param default: The default data that will be presented in the event
32 something goes wrong when loading the file.
33 @param download: The name of the URL from which to download content,
34 in the event content is not on the local machine.
35 """
36 self.folder=folder
37 self.default=default
38 self.download=download
39 self._load=load
40 self.loaded={}
45 - def load(self, file, **param):
46 """Loads the file from self.folder.
47 Retrieves existing data in the event the file has been previously loaded,
48 downloads content from the internet in the event of an error
49 (if url is specified), and displays self.default if all else fails
50 (if default content is specified). Throws an exception if an error occurs
51 that is not resolved from a download or default content.
52 """
53 if file in self.loaded:
54 return self.loaded[file]
55 else:
56 path=os.path.join(self.folder, file)
57 if os.path.exists(path):
58 data=self._load(path, **param)
59 self.loaded[file]=data
60 elif file==self.default:
61 raise 'Could not load default file: '+str(self.default)
62 elif not self.default:
63 raise 'Could not load file: '+str(file)
64 elif self.download:
65 base=self.download
66 base2 = urlparse.urljoin(base, self.folder)+'/'
67 url = urlparse.urljoin(base2, file)
68 url = url.replace(' ', '%20')
69 url = url.replace('\\', '/')
70 request = urllib2.Request(url)
71 try:
72 print('downloading from '+url)
73 downloader = urllib2.urlopen(request)
74 download = open(path, "wb")
75 download.write(downloader.read())
76 download.close()
77 data=self._load(path, **param)
78 self.loaded[file]=data
79 except urllib2.HTTPError, ex:
80 print(str(ex.code)+' Could not find file: '+str(url))
81 data=self.load(self.default)
82 else:
83 print('Could not load file: '+str(file))
84 data=self.load(self.default)
85 return data
87 """Deletes data loaded from the file, if present.
88 Implementing behavior that uses this function may be more
89 trouble than its worth. Only consider this if You're game slows
90 down considerably as more and more content is loaded. Even on
91 a large (1000+ slide) project, this shouldn't happen when
92 using reasonable slide resolutions.
93 """
94 if file in self.loaded:
95 del self.loaded[file]
96
98 -def loadFont(path, fontSize=16):return pygame.font.Font(path, fontSize)
99 -def loadSound(path): return pygame.mixer.Sound(path)
101 images=Library('pictures', loadImage, default='default.gif')
102 movies=Library('Movies', loadMovie)
103 cursors=Library('cursors', loadImage, default='arrow.png')
104 fonts =Library('fonts', loadFont)
105 sounds=Library('sounds/effects', loadSound, default='../default.wav')
106 voices=Library('sounds/voices', loadSound, default='../default.wav')
107