Professional Documents
Culture Documents
Jones Rapid Game Dev
Jones Rapid Game Dev
RapidGameDevelopmentInPython
Author:RichardJones
Howdoyoumakeagame?
Gamesconsistlargelyofuserinput,gameoutputandsomesortofworldsimulation.Themostinteresting gamesaretheonesthatdosomethingdifferentornewinthesimulation.Pythonisareallynicelanguagefor writinggamesimulationsin.Fortunately,otherpeoplehavedoneareallyexcellentjobofprovidingPython librariesforuserinputandgameoutput.
Pythonhas...
Python Possiblythebestlanguageforwritinggameworldsimulationsin.It'scleartoreadandwrite,easyto learn,handlesalotofprogramminghousekeepingandisreasonablyfast. PyGame Providesuserinputhandling(mouse,keyboard,joystick)andgameoutputviascreen(shapedrawing, imageblitting,fontrendering)andspeakers(effectsandmusic).Strictly2dgraphics. PyOpenGL GivesPythonthepowerofOpenGLforveryhighperformance3dgraphics. (Soya3d,PGU,...) Additionallibrariesoverthetopoftheabovethatprovideasolidbasisforyourworldsimulation, gamemapdrawingcode,modelloading,eventmanagement,etc.
Managingthescreenthebasics
Basicscreeninitialisationlookslike:
>>>frompygame.localsimport* >>>screen=pygame.display.set_mode((1024,768)) >>>screen=pygame.display.set_mode((1024,768),FULLSCREEN)
You can call set_mode duringyourgameto switchfromwindowed(thedefault) tofullscreen.Other displaymodeflags(youjust|themtogether): DOUBLEBUF mustbeusedforsmoothanimation OPENGL letsyoudraw3dsceneswithPyOpenGL,butwon'tletyouperformmostpygamedrawingfunctions. Thereisanoptionalbitdepthflag,butit'salmostalwaysbettertonotincludeitandgowithwhatever platformdefaultisavailable. Ifyou'reusingDOUBLEBUFthenyou'llneedtoflipthescreenafteryou'verenderedit.Thisisassimpleas:
>>>pygame.display.flip()
Drawingacar
We'regoingtodrawacaronscreen.Wedothisusingoneofthemostimportantdrawingprimitives,the BLIT(BlockImageTransfer).Itcopiesanimagefromoneplace(eg.yoursourceimage)toanotherplace (eg.thescreenatX=50,Y=100): 84OpenSourceDevelopers'Conference2005
RapidGameDevelopmentInPython
>>>car=pygame.image.load('car.png') >>>screen.blit(car,(50,100)) >>>pygame.display.flip()
Animatingthecar
Animatinganythingonscreeninvolvesdrawingascene,clearingitanddrawingitagainslightlydifferently:
>>>foriinrange(100): ...screen.fill((0,0,0)) ...screen.blit(car,(i,0))
Inputhandling
There'sanumberofwaystogetusereventsinPyGame,themostcommonofwhichare:
>>>importpygame >>>pygame.event.wait() >>>pygame.event.poll() >>>pygame.event.get()
waitwillsitandblockfurthergameexecutionuntilaneventcomesalong.Thisisnotgenerallyveryuseful forgames,asyouwanttobeanimatingthingsatthesametime.pollwillseewhetherthereareanyevents
Bringingtogethersomeelements
Thefollowingcodewillanimateourlittlecaraccordingtousercontrols.Itconsistsbroadlyoffoursections (initialisation,userinput,animationandrendering):
#INTIALISATION importpygame,math,sys frompygame.localsimport* screen=pygame.display.set_mode((1024,768)) car=pygame.image.load('car.png') clock=pygame.time.Clock() k_up=k_down=k_left=k_right=0 speed=direction=0 position=(100,100) TURN_SPEED=5 ACCELERATION=2 MAX_FORWARD_SPEED=10 MAX_REVERSE_SPEED=5 BLACK=(0,0,0) while1: #USERINPUT clock.tick(30) foreventinpygame.event.get(): ifnothasattr(event,'key'):continue down=event.type==KEYDOWN#keydownorup? ifevent.key==K_RIGHT:k_right=down*5 elifevent.key==K_LEFT:k_left=down*5 elifevent.key==K_UP:k_up=down*2 elifevent.key==K_DOWN:k_down=down*2 elifevent.key==K_ESCAPE:sys.exit(0)#quitthegame screen.fill(BLACK) #SIMULATION #..newspeedanddirectionbasedonaccelerationandturn speed+=(k_up+k_down) ifspeed>MAX_FORWARD_SPEED:speed=MAX_FORWARD_SPEED ifspeed<MAX_REVERSE_SPEED:speed=MAX_REVERSE_SPEED direction+=(k_right+k_left) #..newpositionbasedoncurrentposition,speedanddirection x,y=position rad=direction*math.pi/180 x+=speed*math.sin(rad) y+=speed*math.cos(rad) position=(x,y) #RENDERING #..rotatethecarimagefordirection rotated=pygame.transform.rotate(car,direction) #..positionthecaronscreen rect=rotated.get_rect() rect.center=position #..renderthecartoscreen screen.blit(rotated,rect) pygame.display.flip()
Morestructure
Sotheabovecodeisalittleadhoc.Mostgameswillwanttoorganisethingstobeabletobettercontrol 86OpenSourceDevelopers'Conference2005
OpenSourceDevelopers'Conference200587
Sonowwehaveacar,runningaroundonthescreen,controlledbytheplayerandwecandetectwhenthecar hitsotherthingsonthescreen.
Addingobjectives
It'dbeniceifwecoulddeterminewhetherthecarhasmadea"lap"ofthe"circuit"we'veconstructed.We'll keepinformationindicatingwhichorderthepadsmustbevisited:
classPadSprite(pygame.sprite.Sprite): normal=pygame.image.load('pad_normal.png') hit=pygame.image.load('pad_hit.png') def__init__(self,number,position): pygame.sprite.Sprite.__init__(self) self.number=number self.rect=pygame.Rect(self.normal.get_rect()) self.rect.center=position self.image=self.normal pads=[ PadSprite(1,(200,200)), PadSprite(2,(800,200)), PadSprite(3,(200,600)), PadSprite(4,(800,600)), ] current_pad_number=0
Nowwereplacethepadcollisionfromabovewithcodethatmakessurewehittheminthecorrectorder:
pads=pygame.sprite.spritecollide(car,pad_group,False) ifpads: pad=pads[0] ifpad.number==current_pad_number+1: pad.image=pad.hit current_pad_number+=1 elifcurrent_pad_number==4:
88OpenSourceDevelopers'Conference2005
RapidGameDevelopmentInPython
forpadinpad_group.sprites():pad.image=pad.normal current_pad_number=0
Thelastpartofthattext,resettingthecurrent_pad_numberiswherewe'dflagthattheplayerhasruna lap.
Addingabackground
Currentlywe'reclearingthescreenoneveryframebeforerendering (screen.fill((0,0,0))).Thisis quiteslow(thoughyoumightnotnotice)andiseasilyimprovedupon.Firstlyoutsidetheanimationloopwe loadupabackgroundimageanddrawittothescreen:
background=pygame.image.load('track.png') screen.blit(self.background,(0,0))
Nowinsidetheloop,butbeforeweupdate(move)thecar,weaskthecar'sspritetoclearitselffromthe screen.Wedothiswiththepadstoo:
pad_group.clear(screen,background) car_group.clear(screen,background)
Phil'sPyGameUtilities(PGU)
pguisanextensionforPyGamewhichincludesseveraltoolsandlibraries. tools gui thetoolsareatileeditorandaleveleditor(tile,isometric,hexagonal). fullfeaturedgui,htmlrendering,documentlayout,andtextrendering. gamelibs thelibrariesincludeaspriteandtileengine(tile,isometric,hexagonal),astateengine,atimer,anda highscoresystem.
Soya3d
Soya3Disahighlevel3DengineforPython;itaimsatbeingto3DwhatPythonistoprogramming:easy andpowerful.Itisdesignedwithgamesinmind,focusingbothonperformanceandeaseofuse.Itrelieson OpenGL,SDLandCal3D. Soya3DisavailableundertheGPLandcurrentlyrunsonGNU/Linux,thoughportstootherOSareplanned (MacOSX,Windows,...)sinceitusesonlyportablelibraries. Featuresincludes:
RapidGameDevelopmentInPython
PyWeekOne
ThefirstPythonGameProgrammingChallenge(PyWeek)washeldoverthelastweekinAugust/firstweek ofSeptember,2005.ThePyWeekchallengegoalswere: 1. Mustbechallengingandfun, 2. Entriesmustbedevelopedduringthechallenge,andmustincorporatesomethemedecidedatthestart ofthechallenge, 3. Willhopefullyincreasethepublicbodyofpythongametools,codeandexpertise, 4. Willletalotofpeopleactuallyfinishagame,and 5. Mayinspirenewprojects(withreadymadeteams!) Whathappened:
Theadditionalgoalsofrunoffbenefits(points3and5)havecometofruitionaswell,withanumberofthe projectscontinuingtobedevelopedafterthechallenge,andanumberoftheframeworksbeingimprovedasa resultofthechallenge. The feedback from the competitors was almost universally positive (the only gripes from people who unfortunatelygotdraggedawayfromthechallengepartwaythrough). ThenextchallengewillberunsomewherearoundFebruarytoApril2006.
References
Pythonhttp://www.python.org PyGamehttp://www.pygame.org PyOpenGLhttp://pyopengl.sf.net Soya3dhttp://home.gna.org/oomadness PGUhttp://www.imitationpickles.org/pgu PyWeekhttp://www.mechanicalcat.net/tech/PyWeek GameProgrammingInPythonBookbySeanRileyavailablepublishedbyCharlesRiverMedia
90OpenSourceDevelopers'Conference2005