Here is a sample script to compile a pygame app to a standalone windows application. It includes a hack to include pygame default font into executable file.
Just edit value in BuildExe.__init__ to fit you needs. This will only work for GUI apps, change "windows =" to "console =" in setup command would do the job.
To have a zipfile with libraries, just specify a zip file name. If you don't specify an icon file name, pygame icon will be used.
Changes by arit:
For this script to work I *had* to modify my font call in my game fromFont = pygame.font.SysFont(None,16) # the created .exe does not runtoFont = pygame.font.Font("freesansbold.ttf", 16)and additionally copy freesansbold.ttf into the same directory as the created .exeI also needed to add sdl_ttf.dll to the check for include files (see comment in source code bellow)(This has been suggested by http://stackoverflow.com/questions/6376194/font-module-error-when-using-py2exe)Then I saved the script bellow as game2exe.py in the same directory as my MyApps.py file.From the command promt inside this very directory I then executed the script by writingpython game2exe.pyThen I had to manually copy freesansbold.ttf into the subfolder "dist" where the MyApps.exe is created.Windows7 64bit Enterprise, Python 2.7.2, pygame-1.9.2a0.win32-py2.7
# This will create a dist directory containing the executable file, all the data# directories. All Libraries will be bundled in executable file.## Run the build process by entering 'pygame2exe.py' or# 'python pygame2exe.py' in a console prompt.## To build exe, python, pygame, and py2exe have to be installed. After# building exe none of this libraries are needed.#Please Note have a backup file in a different directory as if it crashes you#will loose it all!(I lost 6 months of work because I did not do this)try:fromdistutils.coreimport setupimportpy2exe,pygamefrommodulefinderimport Moduleimportglob,fnmatchimportsys,os,shutilimportoperatorexceptImportError, message:raiseSystemExit,"Unable to load module.%s"% message#hack which fixes the pygame mixer and pygame fontorigIsSystemDLL= py2exe.build_exe.isSystemDLL# save the orginal before we edit itdefisSystemDLL(pathname):# checks if the freetype and ogg dll files are being includedif os.path.basename(pathname).lower()in ("libfreetype-6.dll","libogg-0.dll","sdl_ttf.dll"):# "sdl_ttf.dll" added by arit.return0return origIsSystemDLL(pathname)# return the orginal functionpy2exe.build_exe.isSystemDLL= isSystemDLL# override the default function with this oneclasspygame2exe(py2exe.build_exe.py2exe):#This hack make sure that pygame default font is copied: no need to modify code for specifying default fontdefcopy_extensions(self, extensions):#Get pygame default font pygamedir= os.path.split(pygame.base.__file__)[0] pygame_default_font= os.path.join(pygamedir, pygame.font.get_default_font())#Add font to list of extension to be copied extensions.append(Module("pygame.font", pygame_default_font)) py2exe.build_exe.py2exe.copy_extensions(self, extensions)classBuildExe:def__init__(self):#Name of starting .pyself.script="MyApps.py"#Name of programself.project_name="MyApps"#Project urlself.project_url="about:none"#Version of programself.project_version="0.0"#License of the programself.license="MyApps License"#Auhor of programself.author_name="Me"self.author_email="example@example.com"self.copyright="Copyright (c) 2009 Me."#Descriptionself.project_description="MyApps Description"#Icon file (None will use pygame default icon)self.icon_file=None#Extra files/dirs copied to gameself.extra_datas= []#Extra/excludes python modulesself.extra_modules= []self.exclude_modules= []#DLL Excludesself.exclude_dll= ['']#python scripts (strings) to be included, seperated by a commaself.extra_scripts= []#Zip file name (None will bundle files in exe instead of zip file)self.zipfile_name=None#Dist directoryself.dist_dir='dist'## Code from DistUtils tutorial at http://wiki.python.org/moin/Distutils/Tutorial## Originally borrowed from wxPython's setup and config filesdefopj(self,*args): path= os.path.join(*args)return os.path.normpath(path)deffind_data_files(self, srcdir,*wildcards,**kw):# get a list of all files under the srcdir matching wildcards,# returned in a format to be used for install_datadefwalk_helper(arg, dirname, files):if'.svn'in dirname:return names= [] lst, wildcards= argfor wcin wildcards: wc_name=self.opj(dirname, wc)for fin files: filename=self.opj(dirname, f)if fnmatch.fnmatch(filename, wc_name)andnot os.path.isdir(filename): names.append(filename)if names: lst.append( (dirname, names ) ) file_list= [] recursive= kw.get('recursive',True)if recursive: os.path.walk(srcdir, walk_helper, (file_list, wildcards))else: walk_helper((file_list, wildcards), srcdir, [os.path.basename(f)for fin glob.glob(self.opj(srcdir,'*'))])return file_listdefrun(self):if os.path.isdir(self.dist_dir):#Erase previous destination dir shutil.rmtree(self.dist_dir)#Use the default pygame icon, if none givenifself.icon_file==None: path= os.path.split(pygame.__file__)[0]self.icon_file= os.path.join(path,'pygame.ico')#List all data files to add extra_datas= []for datainself.extra_datas:if os.path.isdir(data): extra_datas.extend(self.find_data_files(data,'*'))else: extra_datas.append(('.', [data])) setup( cmdclass= {'py2exe': pygame2exe}, version=self.project_version, description=self.project_description, name=self.project_name, url=self.project_url, author=self.author_name, author_email=self.author_email, license=self.license,# targets to build windows= [{'script':self.script,'icon_resources': [(0,self.icon_file)],'copyright':self.copyright }], options= {'py2exe': {'optimize':2,'bundle_files':1,'compressed':True, \'excludes':self.exclude_modules,'packages':self.extra_modules, \'dll_excludes':self.exclude_dll,'includes':self.extra_scripts} }, zipfile=self.zipfile_name, data_files= extra_datas, dist_dir=self.dist_dir )if os.path.isdir('build'):#Clean up build dir shutil.rmtree('build')if__name__=='__main__':if operator.lt(len(sys.argv),2): sys.argv.append('py2exe') BuildExe().run()#Run generation raw_input("Press any key to continue")#Pause to let user see that things ends