要离职了,忙着写项目交接文档,真心累。明年去南京工作,还不知道能不能找着东家,苦逼以后就不能去北高峰爬山啦,这个礼拜最后再去看次妹纸撒
今天用wxPython做了个贪吃蛇,当是对wxPythonGDI的巩固。
关于如何在屏幕上绘画,请参见wxPython In Action的第六章1.1在屏幕上绘画
贪吃蛇源码下载不要积分
贪吃蛇源码及py2exe打包结果下载骗一个积分
突然发现一个bug,buffer的实际面积比窗口显示的要大,也就是说,当snakeHead的X是600的时候,snake已经超出右边界了,此时游戏还未失败- -晚上用sizer修改一下。
资源中的代码与最终代码不同,请参考贪吃蛇全部代码
来画一条蛇吧
贪吃蛇首先得要有一条蛇才行,蛇细细长长的,就是一条线,那么怎么画一条线呢?以下代码就是如何画一条线,这与贪吃蛇无关,仅仅只是先初步了解怎么画。请注意OnPaint中的
dc = wx.BufferedPaintDC(self, self.buffer)可以注释掉试试
# -*- coding:utf-8 -*-
'''
Created on 2013-1-16
@author: jincheng
'''
import wx
class SnakeWindow(wx.Window):
'''
贪吃蛇
'''
def __init__(self,parent):
wx.Window.__init__(self,parent,-1)
self.snakeColor='black'
self.SetBackgroundColour('green')
self.snakeThickness = 10
self.snake = [(100,100),(100,200)]
self.pen = wx.Pen(self.snakeColor, self.snakeThickness, wx.SOLID)
self.buffer = wx.EmptyBitmap(800,600)
dc = wx.BufferedDC(wx.ClientDC(self),self.buffer)
dc.SetPen(self.pen)
dc.DrawLine(100,200,300,400)
self.Bind(wx.EVT_PAINT, self.OnPaint)
#self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
def OnPaint(self, event):
dc = wx.BufferedPaintDC(self, self.buffer)#处理一个paint(描绘)请求
print 'onpaint'
def OnLeftUp(self, event):
dc = wx.BufferedDC(wx.ClientDC(self),self.buffer)
dc.SetPen(self.pen)
pos = event.GetPositionTuple()
dc.DrawPoint(*pos)
print 'drawpoint'
class SnakeFrame(wx.Frame):
def __init__(self,parent):
wx.Frame.__init__(self,parent,-1,'title',size=(800,600))
self.sketch = SnakeWindow(self)
if __name__ == '__main__':
app = wx.PySimpleApp()
frame = SnakeFrame(None)
frame.Show(True)
app.MainLoop()
让蛇动起来
现在我知道了怎么画一条线,但是线不会动啊,不会动的蛇是死蛇而不是贪吃蛇,下面要让蛇动起来。
蛇应该怎么动?鼠标点一下动一下呢还是键盘按一下动一下?方向键不动的时候蛇也应该会动才对,不然的话该叫懒蛇。
这里需要用到wx.Timer,添加一个timer事件。
self.runtime = wx.Timer(self)SnakeMove顾名思义是贪吃蛇开始移动了。
self.runtime.Start(100)#100毫秒动一下
self.Bind(wx.EVT_TIMER, self.OnTimer)
#每一百毫秒做一件事
def OnTimer(self,event):
self.SnakeMove()
此时我们需要考虑两件事:1、蛇往哪个方向移动;2、蛇每次移动多少距离。当然这条蛇只会或垂直方向或水平方向移动
蛇默认是向下移动的,设一个属性self.snakeDire = 317。为什么设317呢?
我们知道,按方向键是可以控制蛇的前进方向的,所以我们要加一个键盘事件。可以打出keycode看看,注意贪吃蛇不能向尾巴方向倒车,不知道两头蛇行不行。
self.Bind(wx.EVT_KEY_UP,self.OnKeyUp)获得了蛇行动的方向,就可以开始Move了
def OnKeyUp(self,event):
code = event.GetKeyCode()
if code >= 314 and code <=317 and code != self.snakeDire - 2 and code != self.snakeDire + 2:
self.snakeDire = code
def SnakeMove(self):接着将画蛇的代码整理到一个方法里
length = len(self.snake)
self.snake.pop(length-1)#shift
space = self.snakeSpace
x = 0
y = 0
if self.snakeDire == 317:
y = space
elif self.snakeDire == 316:
x = space
elif self.snakeDire == 315:
y = -space
elif self.snakeDire == 314:
x = -space
newhead = (self.snakeHead[0] + x,self.snakeHead[1] + y)
self.snake.insert(0,newhead)
self.snakeHead = newhead
dc = wx.BufferedDC(wx.ClientDC(self),self.buffer)
dc.SetPen(self.pen)
print self.snake
def SnakeInstantiate(self,dc):
'''
画出蛇
'''
last = self.snake[0]
length = len(self.snake)
for s in self.snake[1:length]:
line = last + s
dc.DrawLine(*line)
last = s
此阶段全部代码
# -*- coding:utf-8 -*-
'''
Created on 2013-1-16
@author: jincheng
'''
import wx
class SnakeWindow(wx.Window):
'''
贪吃蛇
'''
def __init__(self,parent):
wx.Window.__init__(self,parent,-1)
self.snakeColor='black'
self.SetBackgroundColour('green')
self.snakeThickness = 10
self.snake = [(100,100),(100,200),(100,300)]
self.snakeHead = (100,300)
self.snakeSpace = 10
self.pen = wx.Pen("red", 10, wx.SOLID)
self.winsize = self.GetClientSize()
self.buffer = wx.EmptyBitmap(800,600)
self.snakeDire = 317#蛇头向下
self.runtime = wx.Timer(self)
self.runtime.Start(100)#100毫秒动一下
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_KEY_UP,self.OnKeyUp)
self.Bind(wx.EVT_TIMER, self.OnTimer)
#self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
def SnakeMove(self):
length = len(self.snake)
self.snake.pop(length-1)#shift
space = self.snakeSpace
x = 0
y = 0
if self.snakeDire == 317:
y = space
elif self.snakeDire == 316:
x = space
elif self.snakeDire == 315:
y = -space
elif self.snakeDire == 314:
x = -space
newhead = (self.snakeHead[0] + x,self.snakeHead[1] + y)
self.snake.insert(0,newhead)
self.snakeHead = newhead
dc = wx.BufferedDC(wx.ClientDC(self),self.buffer)
dc.SetPen(self.pen)
#dc.Clear()
print self.snake
self.SnakeInstantiate(dc)
def SnakeInstantiate(self,dc):
'''
画出蛇
'''
last = self.snake[0]
length = len(self.snake)
for s in self.snake[1:length]:
line = last + s
dc.DrawLine(*line)
last = s
def OnTimer(self,event):
self.SnakeMove()
def OnKeyUp(self,event):
code = event.GetKeyCode()
if code >= 314 and code <=317 and code != self.snakeDire - 2 and code != self.snakeDire + 2:
self.snakeDire = code
def OnPaint(self, event):
dc = wx.BufferedPaintDC(self, self.buffer)#13 处理一个paint(描绘)请求
print 'onpaint'
def OnLeftUp(self, event):
dc = wx.BufferedDC(wx.ClientDC(self),self.buffer)
dc.SetPen(self.pen)
pos = event.GetPositionTuple()
dc.DrawPoint(*pos)
print 'drawpoint'
class SnakeFrame(wx.Frame):
def __init__(self,parent):
wx.Frame.__init__(self,parent,-1,'title',size=(800,600))
self.sketch = SnakeWindow(self)
if __name__ == '__main__':
app = wx.PySimpleApp()
frame = SnakeFrame(None)
frame.Show(True)
app.MainLoop()
运行一下试试?
为什么蛇明明什么都没吃,却越来越长?打印结果也依然娇小啊
请注意,在画新的图案前,一定要clear一下旧的图案 ,凡游过,不留下痕迹。放开dc.Clear()那行代码!!!
食物在哪里
光有蛇没有食物是玩不了贪吃蛇的,食物怎么画?1、食物得出现在某个坐标上(x,y);2、食物得有一定的体积a*b,哪怕是1*1。
我们可以认为食物是一个(x,y,x+a,y+b)的线段,当然,也可以认为是一个长a宽b左上角坐标是(x,y)的矩形。在这里,我使用dc.DrawRectangle
self.foodLoc = ()
self.foodWidth = 5
#生产食物
self.FoodManufacture()
def FoodManufacture(self):
x = random.randint(0,800)
y = random.randint(0,600)
self.foodLoc = (x,y)
def foodInstantiate(self,dc):
'''
画出食物
'''
food = self.foodLoc + (self.foodWidth,self.foodWidth)
dc.DrawRectangle(*food)
此阶段全部代码
# -*- coding:utf-8 -*-
'''
Created on 2013-1-16
@author: jincheng
'''
import wx
import random
class SnakeWindow(wx.Window):
'''
贪吃蛇
'''
def __init__(self,parent):
wx.Window.__init__(self,parent,-1)
self.snakeColor='black'
self.SetBackgroundColour('green')
self.snakeThickness = 10
self.snake = [(100,100),(100,200),(100,300)]
self.snakeHead = (100,300)
self.snakeSpace = 10
self.foodLoc = ()
self.foodWidth = 5
self.FoodManufacture()
self.pen = wx.Pen("red", 10, wx.SOLID)
self.winsize = self.GetClientSize()
self.buffer = wx.EmptyBitmap(800,600)
self.snakeDire = 317#蛇头向下
#self.foodInstantiate()
self.runtime = wx.Timer(self)
self.runtime.Start(100)#100毫秒动一下
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_KEY_UP,self.OnKeyUp)
self.Bind(wx.EVT_TIMER, self.OnTimer)
#self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
def FoodManufacture(self):
x = random.randint(0,800)
y = random.randint(0,600)
self.foodLoc = (x,y)
def foodInstantiate(self,dc):
food = self.foodLoc + (self.foodWidth,self.foodWidth)
dc.DrawRectangle(*food)
def SnakeMove(self):
length = len(self.snake)
self.snake.pop(length-1)#shift
space = self.snakeSpace
x = 0
y = 0
if self.snakeDire == 317:
y = space
elif self.snakeDire == 316:
x = space
elif self.snakeDire == 315:
y = -space
elif self.snakeDire == 314:
x = -space
newhead = (self.snakeHead[0] + x,self.snakeHead[1] + y)
self.snake.insert(0,newhead)
self.snakeHead = newhead
dc = wx.BufferedDC(wx.ClientDC(self),self.buffer)
dc.SetPen(self.pen)
dc.Clear()
print self.snake
self.SnakeInstantiate(dc)
def SnakeInstantiate(self,dc):
'''
画出蛇与食物
'''
self.foodInstantiate(dc)
last = self.snake[0]
length = len(self.snake)
for s in self.snake[1:length]:
line = last + s
dc.DrawLine(*line)
last = s
def OnTimer(self,event):
self.SnakeMove()
def OnKeyUp(self,event):
code = event.GetKeyCode()
if code >= 314 and code <=317 and code != self.snakeDire - 2 and code != self.snakeDire + 2:
self.snakeDire = code
def OnPaint(self, event):
dc = wx.BufferedPaintDC(self, self.buffer)#13 处理一个paint(描绘)请求
print 'onpaint'
def OnLeftUp(self, event):
dc = wx.BufferedDC(wx.ClientDC(self),self.buffer)
dc.SetPen(self.pen)
pos = event.GetPositionTuple()
pos = pos + (10,10)
dc.Clear()
dc.DrawRectangle(*pos)
print 'drawpoint'
class SnakeFrame(wx.Frame):
def __init__(self,parent):
wx.Frame.__init__(self,parent,-1,'title',size=(800,600))
self.sketch = SnakeWindow(self)
if __name__ == '__main__':
app = wx.PySimpleApp()
frame = SnakeFrame(None)
frame.Show(True)
app.MainLoop()
吃到食物
吃到食物很好理解,蛇的头snakeHead碰到食物的位置foodLoc,就算吃到了,蛇也长大一节,随后重新投放食物
此阶段全部代码
# -*- coding:utf-8 -*-到此贪吃蛇的基本功能就实现了,还剩下判断游戏失败。
'''
Created on 2013-1-16
@author: jincheng
'''
import wx
import random
class SnakeWindow(wx.Window):
'''
贪吃蛇
'''
def __init__(self,parent):
wx.Window.__init__(self,parent,-1)
self.snakeColor='black'
self.SetBackgroundColour('green')
self.snakeThickness = 10
self.snake = [(100,100),(100,200),(100,300)]
self.snakeHead = (100,300)
self.snakeSpace = 10
self.foodLoc = ()
self.foodWidth = 1
self.FoodManufacture()
self.pen = wx.Pen(self.snakeColor, self.snakeThickness, wx.SOLID)
self.winsize = self.GetClientSize()
self.buffer = wx.EmptyBitmap(800,600)
self.snakeDire = 317#蛇头向下
#self.foodInstantiate()
self.runtime = wx.Timer(self)
self.runtime.Start(100)#100毫秒动一下
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_KEY_UP,self.OnKeyUp)
self.Bind(wx.EVT_TIMER, self.OnTimer)
#self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
def FoodManufacture(self):
x = random.randint(0,80)
y = random.randint(0,60)
self.foodLoc = (x*10,y*10)
def foodInstantiate(self,dc):
food = self.foodLoc + (self.foodWidth,self.foodWidth)
dc.DrawRectangle(*food)
def SnakeMove(self):
length = len(self.snake)
self.snake.pop(length-1)#shift
space = self.snakeSpace
x = 0
y = 0
if self.snakeDire == 317:
y = space
elif self.snakeDire == 316:
x = space
elif self.snakeDire == 315:
y = -space
elif self.snakeDire == 314:
x = -space
newhead = (self.snakeHead[0] + x,self.snakeHead[1] + y)
self.snake.insert(0,newhead)
self.snakeHead = newhead
dc = wx.BufferedDC(wx.ClientDC(self),self.buffer)
dc.SetPen(self.pen)
dc.Clear()
self.SnakeInstantiate(dc)
def SnakeInstantiate(self,dc):
'''
画出蛇与食物
'''
self.foodInstantiate(dc)
last = self.snake[0]
length = len(self.snake)
for s in self.snake[1:length]:
line = last + s
dc.DrawLine(*line)
last = s
if self.Eat():
pass
def Eat(self):
print self.snakeHead,self.foodLoc
if self.snakeHead == self.foodLoc:
self.snake.insert(0, self.foodLoc)
self.FoodManufacture()
#print self.snake
return True
else :
return False
def OnTimer(self,event):
self.SnakeMove()
def OnKeyUp(self,event):
code = event.GetKeyCode()
if code >= 314 and code <=317 and code != self.snakeDire - 2 and code != self.snakeDire + 2:
self.snakeDire = code
#self.SnakeMove()
def OnPaint(self, event):
dc = wx.BufferedPaintDC(self, self.buffer)#13 处理一个paint(描绘)请求
print 'onpaint'
def OnLeftUp(self, event):
dc = wx.BufferedDC(wx.ClientDC(self),self.buffer)
dc.SetPen(self.pen)
pos = event.GetPositionTuple()
pos = pos + (10,10)
dc.Clear()
dc.DrawRectangle(*pos)
print 'drawpoint'
class SnakeFrame(wx.Frame):
def __init__(self,parent):
wx.Frame.__init__(self,parent,-1,'title',size=(800,600))
self.sketch = SnakeWindow(self)
if __name__ == '__main__':
app = wx.PySimpleApp()
frame = SnakeFrame(None)
frame.Show(True)
app.MainLoop()
恭喜,GAME OVER
怎么判断游戏失败:1、蛇头超出窗口;2、蛇咬到自己(snakeHead in snake)
def GameOver(self,newhead):
if newhead in self.snake:
self.runtime.Stop()
print 'autotomy'
return True
elif self.snakeHead[0] < 0 or self.snakeHead[0] > 800 or self.snakeHead[1] <1 or self.snakeHead[1] >600:
self.runtime.Stop()
print 'out'
return True
else :
return False
贪吃蛇全部代码
最新代码,已修正边界坐标 2013.1.18
# -*- coding:utf-8 -*-一个最最最最简单的贪吃蛇游戏就是这样的啦
'''
Created on 2013-1-16
@author: jincheng
'''
import wx
import random
class SnakeWindow(wx.Window):
'''
贪吃蛇
'''
def __init__(self,parent,size,offset):
wx.Window.__init__(self,parent,-1,size=size)
print self.GetBorder(wx.BOTTOM)
self.area = (size[0]-offset,size[1]-offset)
self.snakeColor='black'
self.SetBackgroundColour('green')
self.snakeThickness = 10
self.snake = [(100,100),(100,110),(100,120)]
self.snakeHead = (100,120)
self.snakeSpace = 10
self.snakeDebris = []
self.foodLoc = ()
self.foodWidth = 1
self.FoodManufacture()
self.pen = wx.Pen(self.snakeColor, self.snakeThickness, wx.SOLID)
self.winsize = self.GetClientSize()
self.buffer = wx.EmptyBitmap(*self.area)
self.snakeDire = 317#蛇头向下
#self.foodInstantiate()
self.runtime = wx.Timer(self)
self.runtime.Start(100)#100毫秒动一下
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_KEY_UP,self.OnKeyUp)
self.Bind(wx.EVT_TIMER, self.OnTimer)
#self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
def __RandPoint(self):
x = random.randint(1,self.area[0]/10)*10
y = random.randint(1,self.area[1]/10)*10
return (x,y)
def FoodManufacture(self):
self.foodLoc = self.__RandPoint()
def foodInstantiate(self,dc):
food = self.foodLoc + (self.foodWidth,self.foodWidth)
dc.DrawRectangle(*food)
def __Fission(self):
'''
抛洒尸骸
'''
point = self.__RandPoint()
if point in self.snakeDebris or point == self.foodLoc:
self.__Fission()
else:
return point
def SnakeFission(self):
'''
蛇断尾
'''
length = len(self.snake)/2
while length > 0:
index = len(self.snake) - 1
self.snake.pop(index)#删除末位
point = self.__Fission()
self.snakeDebris.append(point)
length -= 1
def SnakeFissionInstantiate(self,dc):
for debris in self.snakeDebris:
d = debris + (self.foodWidth,self.foodWidth)
dc.DrawRectangle(*d)
def SnakeMove(self):
length = len(self.snake)
self.snake.pop(length-1)#shift
space = self.snakeSpace
x = 0
y = 0
if self.snakeDire == 317:
y = space
elif self.snakeDire == 316:
x = space
elif self.snakeDire == 315:
y = -space
elif self.snakeDire == 314:
x = -space
newhead = (self.snakeHead[0] + x,self.snakeHead[1] + y)
self.GameOver(newhead)
self.snake.insert(0,newhead)
self.snakeHead = newhead
dc = wx.BufferedDC(wx.ClientDC(self),self.buffer)
dc.SetPen(self.pen)
dc.Clear()
self.SnakeInstantiate(dc)
def SnakeInstantiate(self,dc):
'''
画出蛇与食物
'''
self.foodInstantiate(dc)
last = self.snake[0]
length = len(self.snake)
for s in self.snake[1:length]:
line = last + s
dc.DrawLine(*line)
last = s
if self.Eat():
if len(self.snake) > 5:
self.SnakeFission()
pen = wx.Pen('red',self.snakeThickness,wx.SOLID)
dc.SetPen(pen)
self.SnakeFissionInstantiate(dc)
def Eat(self):
if self.snakeHead == self.foodLoc:
self.snake.insert(0, self.foodLoc)
self.FoodManufacture()
return True
else :
return False
def GameOver(self,newhead):
print newhead
if newhead in self.snake or newhead in self.snakeDebris:
self.runtime.Stop()
print 'autotomy'
return True
elif newhead[0] < 0 or newhead[0] > self.area[0] or newhead[1] < 0 or newhead[1] > self.area[1]:
self.runtime.Stop()
print 'out'
return True
else :
return False
def OnTimer(self,event):
self.SnakeMove()
def OnKeyUp(self,event):
code = event.GetKeyCode()
if code >= 314 and code <=317 and code != self.snakeDire - 2 and code != self.snakeDire + 2:
self.snakeDire = code
#self.SnakeMove()
def OnPaint(self, event):
dc = wx.BufferedPaintDC(self, self.buffer)#13 处理一个paint(描绘)请求
def OnLeftUp(self, event):
dc = wx.BufferedDC(wx.ClientDC(self),self.buffer)
dc.SetPen(self.pen)
pos = event.GetPositionTuple()
pos = pos + (10,10)
dc.Clear()
dc.DrawRectangle(*pos)
print 'drawpoint'
class SnakeFrame(wx.Frame):
def __init__(self,parent):
wx.Frame.__init__(self,parent,-1,'title',size=(800,600))
size = self.__AreaSize(self.GetClientSize())
panel = wx.Panel(self)
panel.SetBackgroundColour('#4f5049')
border = 10
self.sketch = SnakeWindow(panel,size,2*border)
box = wx.BoxSizer(wx.VERTICAL)
box.Add(self.sketch,1,wx.ALIGN_TOP|wx.ALL,border)
panel.SetSizer(box)
def __AreaSize(self,size):
width = self.__AreaMath(size[0])
height = self.__AreaMath(size[1])
return (width,height)
def __AreaMath(self,intparam):
if intparam%10 < 5:
return intparam/10 * 10
else:
return (intparam/10 + 1)*10
if __name__ == '__main__':
app = wx.PySimpleApp()
frame = SnakeFrame(None)
frame.Show(True)
app.MainLoop()