2073
Comment:
|
4016
good
|
Deletions are marked like this. | Additions are marked like this. |
Line 1: | Line 1: |
= Game Programming With Python = | # Copyright (c) 2005 Nokia Corporation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. |
Line 3: | Line 15: |
You can write whole games in Python using [http://www.pygame.org/ PyGame]. | import appuifw from graphics import * import e32 from key_codes import * |
Line 5: | Line 20: |
If you have an existing game and want to add a scripting engine to make it more flexible, Python is also a very good choice. But you'll have to learn about IntegratingPythonWithOtherLanguages. | class Keyboard(object): def __init__(self,onevent=lambda:None): self._keyboard_state={} self._downs={} self._onevent=onevent def handle_event(self,event): if event['type'] == appuifw.EEventKeyDown: code=event['scancode'] if not self.is_down(code): self._downs[code]=self._downs.get(code,0)+1 self._keyboard_state[code]=1 elif event['type'] == appuifw.EEventKeyUp: self._keyboard_state[event['scancode']]=0 self._onevent() def is_down(self,scancode): return self._keyboard_state.get(scancode,0) def pressed(self,scancode): if self._downs.get(scancode,0): self._downs[scancode]-=1 return True return False keyboard=Keyboard() |
Line 7: | Line 43: |
Read [http://www.onlamp.com/pub/a/python/2002/07/11/pythonnews.html Humongous Python] for a case study. | appuifw.app.screen='full' img=None def handle_redraw(rect): if img: canvas.blit(img) appuifw.app.body=canvas=appuifw.Canvas( event_callback=keyboard.handle_event, redraw_callback=handle_redraw) img=Image.new(canvas.size) |
Line 9: | Line 53: |
Another library is [http://www.alobbs.com/pykyra PyKyra]: PyKyra is a fast game development framework for Python. It is based in SDL and the Kyra engine. In addition to the standard features of Kyra, PyKyra also supports MPEG video, sound (MP3, Ogg Vorbis, Wav and Multichannel module files), direct images reading and much more. -- InTheirOwnWords |
running=1 def quit(): global running running=0 appuifw.app.exit_key_handler=quit |
Line 14: | Line 59: |
== Testimony == | location=[img.size[0]/2,img.size[1]/2] speed=[0.,0.] blobsize=16 xs,ys=img.size[0]-blobsize,img.size[1]-blobsize gravity=0.03 acceleration=0.05 |
Line 16: | Line 66: |
I tried porting [http://taoriver.net/eouwiki/ Escape of the Unicorn] to Python/PySDL, but the game dropped from 30 fps to 6 fps. | import time start_time=time.clock() n_frames=0 # To speed things up, we prerender the text. labeltext=u'Use arrows to move ball' textrect=img.measure_text(labeltext, font='normal')[0] text_img=Image.new((textrect[2]-textrect[0],textrect[3]-textrect[1])) text_img.clear(0) text_img.text((-textrect[0],-textrect[1]),labeltext,fill=0xffffff,font='normal') |
Line 18: | Line 76: |
After a lot of profiling and unrolling screen draw code, I was able to reach 8 frames a second. | while running: img.clear(0) img.blit(text_img, (0,0)) img.point((location[0]+blobsize/2,location[1]+blobsize/2), 0x00ff00,width=blobsize) handle_redraw(()) e32.ao_yield() speed[0]*=0.999 speed[1]*=0.999 speed[1]+=gravity location[0]+=speed[0] location[1]+=speed[1] if location[0]>xs: location[0]=xs-(location[0]-xs) speed[0]=-0.80*speed[0] speed[1]=0.90*speed[1] if location[0]<0: location[0]=-location[0] speed[0]=-0.80*speed[0] speed[1]=0.90*speed[1] if location[1]>ys: location[1]=ys-(location[1]-ys) speed[0]=0.90*speed[0] speed[1]=-0.80*speed[1] if location[1]<0: location[1]=-location[1] speed[0]=0.90*speed[0] speed[1]=-0.80*speed[1] if keyboard.is_down(EScancodeLeftArrow): speed[0] -= acceleration if keyboard.is_down(EScancodeRightArrow): speed[0] += acceleration if keyboard.is_down(EScancodeDownArrow): speed[1] += acceleration if keyboard.is_down(EScancodeUpArrow): speed[1] -= acceleration if keyboard.pressed(EScancodeHash): filename=u'e:\\screenshot.png' canvas.text((0,32),u'Saving screenshot to:',fill=0xffff00) canvas.text((0,48),filename,fill=0xffff00) img.save(filename) |
Line 20: | Line 115: |
If you look at PyGame and PySDL games, you'll notice that they aren't action or arcade games. | n_frames+=1 end_time=time.clock() total=end_time-start_time |
Line 22: | Line 119: |
I have only heard of few efforts that succeeded in embedding Python in C++, and I have forgotten them. For the most part, people (including Humongous, as described in [http://www.onlamp.com/pub/a/python/2002/07/11/pythonnews.html the case study described]) extend Python with C++. If you are going to mix Python and C++, I think it is best to extend Python- that is the intended direction. I consider this a failing of Python. If you want to embed a scripting system because you already have a huge system, embed something like Guile. I think it is an inferior solution, but that it will result in a lot less heartbreak. I suspect I'll try to rewrite Escape of the Unicorn as a C++/Python mixture some day, and pay careful attention to how I cut the C++/Python lines. I think only a few things need to be given to C++, such as display loops, animation management, and collision detection. -- LionKimbro [[DateTime(2002-07-19T10:45:57)]] |
print "%d frames, %f seconds, %f FPS, %f ms/frame."%(n_frames,total, n_frames/total, total/n_frames*1000.) |
# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.
import appuifw from graphics import * import e32 from key_codes import *
class Keyboard(object):
def init(self,onevent=lambda:None):
- self._keyboard_state={} self._downs={} self._onevent=onevent
- if event['type'] == appuifw.EEventKeyDown:
- code=event['scancode'] if not self.is_down(code):
- self._downs[code]=self._downs.get(code,0)+1
- self._keyboard_state[event['scancode']]=0
- code=event['scancode'] if not self.is_down(code):
- return self._keyboard_state.get(scancode,0)
- if self._downs.get(scancode,0):
- self._downs[scancode]-=1 return True
keyboard=Keyboard()
appuifw.app.screen='full' img=None def handle_redraw(rect):
- if img:
- canvas.blit(img)
appuifw.app.body=canvas=appuifw.Canvas(
- event_callback=keyboard.handle_event, redraw_callback=handle_redraw)
img=Image.new(canvas.size)
running=1 def quit():
- global running running=0
appuifw.app.exit_key_handler=quit
location=[img.size[0]/2,img.size[1]/2] speed=[0.,0.] blobsize=16 xs,ys=img.size[0]-blobsize,img.size[1]-blobsize gravity=0.03 acceleration=0.05
import time start_time=time.clock() n_frames=0 # To speed things up, we prerender the text. labeltext=u'Use arrows to move ball' textrect=img.measure_text(labeltext, font='normal')[0] text_img=Image.new((textrect[2]-textrect[0],textrect[3]-textrect[1])) text_img.clear(0) text_img.text((-textrect[0],-textrect[1]),labeltext,fill=0xffffff,font='normal')
while running:
- img.clear(0) img.blit(text_img, (0,0)) img.point((location[0]+blobsize/2,location[1]+blobsize/2),
- 0x00ff00,width=blobsize)
if location[0]>xs:
- location[0]=xs-(location[0]-xs) speed[0]=-0.80*speed[0] speed[1]=0.90*speed[1]
if location[0]<0:
- location[0]=-location[0] speed[0]=-0.80*speed[0] speed[1]=0.90*speed[1]
if location[1]>ys:
- location[1]=ys-(location[1]-ys) speed[0]=0.90*speed[0] speed[1]=-0.80*speed[1]
if location[1]<0:
- location[1]=-location[1] speed[0]=0.90*speed[0] speed[1]=-0.80*speed[1]
- filename=u'e:\\screenshot.png' canvas.text((0,32),u'Saving screenshot to:',fill=0xffff00) canvas.text((0,48),filename,fill=0xffff00) img.save(filename)
end_time=time.clock() total=end_time-start_time
print "%d frames, %f seconds, %f FPS, %f ms/frame."%(n_frames,total,
- n_frames/total, total/n_frames*1000.)