贪食蛇不是fps,没有那么高的效率,不可能更新窗口里面的全部内容,这样就需要一个算法来处理这个问题,
算法:假设小蛇由一个蛇头,n个蛇身组成,整个蛇的前进由蛇头控制,方向由用户控制。
每次刷新时,从蛇尾开始遍历,把(n-1)方块的位置赋给n方块,直到n为1,最后将蛇头的位置赋给0方块。
显示时不需更新窗口中每一个图片,如果蛇总共(n+1)个方块,则只需更新(n+2)个方块,(n+1)个蛇方块当然更新,还有一个就是这一次蛇腾出来的空间(即上一次蛇尾的位置)用土地本来的图片替换,这样整个蛇就会跟着蛇头跑不会留下痕迹。
实现了一个基本功能版,靠(wasd)控制方向,里面会随机出现蛋糕,吃掉蛋糕会得分,并且增长蛇身,碰到边界游戏结束
不到200行就搞定了,需要图片在附件
#-*- coding:utf-8 -*- ''' Created on 2011-3-23 经典游戏 --贪食蛇 @author: 123 ''' import wx import random,time #蛇身方块 class westiceSnakeBody(): def __init__(self): randnum=int(random.random()*4) imagename='snakeskin'+str(randnum)+'.jpg' img1=wx.Image(imagename,wx.BITMAP_TYPE_ANY) self.img1=img1.Scale(30,30)#2 缩小图像 self.x=-1 self.y=-1 #蛇体 class westiceSnake(): def __init__(self): self.bodys=[] self.headx=int(random.random()*(10))+5 self.heady=int(random.random()*(10))+5 self.direct=int(random.random()*4) self.img1=wx.Image('snakehead.jpg',wx.BITMAP_TYPE_ANY) self.headimg90=self.img1.Rotate90(True) self.headimg180=self.headimg90.Rotate90(True) self.headimg_90=self.img1.Rotate90(False) self.headimg1=self.img1 self.prev_snakex=self.headx self.prev_snakey=self.heady def update(self):#更新 #保存小蛇前一时刻最后一个位置 if len(self.bodys)!=0: self.prev_snakex=self.bodys[len(self.bodys)-1].x self.prev_snakey=self.bodys[len(self.bodys)-1].y else: self.prev_snakex=self.headx self.prev_snakey=self.heady if len(self.bodys)!=0: for index in range(len(self.bodys)-1,0,-1): self.bodys[index].x=self.bodys[index-1].x self.bodys[index].y=self.bodys[index-1].y self.bodys[0].x=self.headx self.bodys[0].y=self.heady #移动小蛇 if self.direct==0: self.headx+=1#向右 if self.direct==1: self.heady+=1#向下 if self.direct==2: self.headx-=1#向左 if self.direct==3: self.heady-=1#向上 #旋转一下蛇头 self.headimg1=self.img1 if self.direct==0: self.headimg1=self.headimg90 if self.direct==1: self.headimg1=self.headimg180 if self.direct==2: self.headimg1=self.headimg_90 self.headimg1=self.headimg1.Scale(30,30) #游戏主窗口 class MyFrame(wx.Frame): gridwidth=20 gridheight=20 landsqurelist=[] first=True def __init__(self): wx.Frame.__init__(self,None,-1,"My Frame",size=(800,700)) self.panel=wx.Panel(self,-1) self.score=0 self.scoretxt=wx.StaticText(self.panel,-1,'得分:'+str(self.score),pos=(630,300)) self.gamestatustxt=wx.StaticText(self.panel,-1,'游戏状态:正在运行',pos=(630,350)) fgs=wx.FlexGridSizer(cols=self.gridwidth,hgap=0,vgap=0) self.panel.Bind(wx.EVT_KEY_DOWN,self.OnKeyDown) self.panel.SetFocus() for col in range(self.gridwidth): random.seed(time.time()) for row in range(self.gridheight): #加载草地 randnum=int(random.random()*4) #随即加蛋糕 if random.random()<0.02: randnum=-1 imagename='land'+str(randnum)+'.jpg' img1=wx.Image(imagename,wx.BITMAP_TYPE_ANY) img1=img1.Scale(30,30)#2 缩小图像 sb1=wx.StaticBitmap(self.panel,-1,wx.BitmapFromImage(img1)) sb1.randnum=randnum #存入图片名 fgs.Add(sb1) self.landsqurelist.append(sb1) self.panel.SetSizerAndFit(fgs) #生成蛇,初始化位置, self.westicesnake=westiceSnake() #设定一个时钟 self.timer1=wx.Timer(self) self.Bind(wx.EVT_TIMER,self.frameUpdate,self.timer1) self.timer1.Start(500) #可在此设置速度 #键盘绑定 def OnKeyDown(self,event): if ord('A')==event.GetKeyCode()and self.westicesnake.direct!=0: #向左 self.westicesnake.direct=2 if ord('D')==event.GetKeyCode()and self.westicesnake.direct!=2: #向右 self.westicesnake.direct=0 if ord('S')==event.GetKeyCode()and self.westicesnake.direct!=3: #向下 self.westicesnake.direct=1 if ord('W')==event.GetKeyCode()and self.westicesnake.direct!=1: #向上 self.westicesnake.direct=3 #帧更新 def frameUpdate(self,event): #游戏算法实现处 if self.westicesnake.headx>=0and self.westicesnake.headx<self.gridwidth\ and self.westicesnake.heady>=0and self.westicesnake.heady<self.gridheight: tempindex=self.getIndex(self.westicesnake.headx,self.westicesnake.heady) #显示蛇头 self.landsqurelist[tempindex].SetBitmap(wx.BitmapFromImage(self.westicesnake.headimg1)) #显示小蛇身体 for body in self.westicesnake.bodys: tempindex=self.getIndex(body.x,body.y) self.landsqurelist[tempindex].SetBitmap(wx.BitmapFromImage(body.img1)) #显示上一次腾出的位置 if not self.first: tempindex=self.getIndex(self.westicesnake.prev_snakex,self.westicesnake.prev_snakey) tempimagenum=self.landsqurelist[tempindex].randnum tempimagename='land'+str(tempimagenum)+'.jpg' img1=wx.Image(tempimagename,wx.BITMAP_TYPE_ANY) img1=img1.Scale(30,30) self.landsqurelist[tempindex].SetBitmap(wx.BitmapFromImage(img1)) else: self.first=False #遇到蛋糕吃下,长蛇身,将蛋糕换成land if self.landsqurelist[tempindex].randnum==(-1): print '吃蛋糕' self.score+=1 self.scoretxt.SetLabel('得分:'+str(self.score)) self.landsqurelist[tempindex].randnum=int(random.random()*4) #加入一个body,设置好坐标,应该是加在上次腾出的地方 snakebody=westiceSnakeBody() snakebody.x=self.westicesnake.prev_snakex snakebody.y=self.westicesnake.prev_snakey self.westicesnake.bodys.append(snakebody) #在land中随机产生蛋糕 tempindex=int(random.random()*self.gridwidth*self.gridheight) if self.landsqurelist[tempindex].randnum==-1: randnum=int(random.random()*4) imagename='land'+str(randnum)+'.jpg' self.landsqurelist[tempindex].randnum=randnum else: imagename='land-1.jpg' self.landsqurelist[tempindex].randnum=-1 img1=wx.Image(imagename,wx.BITMAP_TYPE_ANY) img1=img1.Scale(30,30) self.landsqurelist[tempindex].SetBitmap(wx.BitmapFromImage(img1)) else: self.gamestatustxt.SetLabel('游戏状态:GameOver!') #移动小蛇 self.westicesnake.update() #得到图片的x,y坐标 def getX_Y(self,imageindex): x=imageindex%self.gridwidth y=imageindex/self.gridwidth return [x,y] def getIndex(self,x,y): return y*self.gridwidth+x #代码入口 if __name__=='__main__': app=wx.PySimpleApp() frame=MyFrame() frame.Show(True) app.MainLoop()