贪食蛇不是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()