看了www.pygame.org,感觉挺好玩的,看看pygame的手册,参考其它贪吃蛇写法,产生如下代码:
有注释,有详细代码,有真相!
#!/usr/bin/python
#-*-coding:utf8-*-
#
import pygame
import random
import os
main_dir = os.path.split(os.path.abspath(__file__))[0]
print main_dir
# 屏幕大小
SCREENSIZE = (640,480)
SCREENRECT = pygame.Rect(0, 0, SCREENSIZE[0], SCREENSIZE[1])
CAPTION = "first Snake"
# 帧
FPS = 30
# 起始蛇长
START_SEGMENT = 5
#起始地点
START_POS = (20,20)
# 移动速率
MOVE_RATE = 2
MOVE_THRESHOLD = 5
#蛇头,食物大小
FOODSIZE = (12,12)
SNAKE_HEAD_SIZE = (12,12)
SNAKE_SEG_SIZE = (12,12)
# 障碍物宽度
BLOCK_WIDE = 5
# food, snanke_segment只能在这范围内产生
SCREEN_SEGMENT = ((SCREENSIZE[0]) / SNAKE_SEG_SIZE[0] -1, (SCREENSIZE[1]) / \
SNAKE_SEG_SIZE[1] - 1)
#颜色
BACKGROUND_COLOR = (255, 255, 255)
FOOD_COLOR = (0, 0, 0)
SNAKE_HEAD_COLOR = (0, 255, 0)
SNAKE_SEG_COLOR = (0, 0, 255)
BLOCK_COLOR = (255, 0, 0)
#GAME OVER
GAME_OVER_COLOR = (255, 0, 0)
#方向
#关键地方
moveRight = 1
moveLeft = 2
moveUp = 3
moveDown = 4
MOVE_VECTOR = {moveLeft : (-1, 0),
moveRight: (1, 0),
moveUp : (0, -1),
moveDown : (0, 1)
}
MOVE_VECTOR_PIXS = {moveLeft : (-SNAKE_SEG_SIZE[0], 0),
moveRight: (SNAKE_SEG_SIZE[0], 0),
moveUp : (0, -SNAKE_SEG_SIZE[1]),
moveDown : (0, SNAKE_SEG_SIZE[1])
}
#分数
SCORE = 0
# 蛇身
class Snake_Segment(pygame.sprite.Sprite):
def __init__(self, spos, segment_groups, color = SNAKE_SEG_COLOR):
pygame.sprite.Sprite.__init__(self)
# 创建方块
self.image = pygame.Surface(SNAKE_SEG_SIZE).convert()
self.image.fill(color)
# 初始位置
self.spos = spos
# 设置image在初始位置出现
self.rect = self.image.get_rect()
self.rect.topleft = (spos[0] * SNAKE_SEG_SIZE[0], spos[1] * SNAKE_SEG_SIZE[1])
# 蛇身属于一个或多个组,做碰撞检测
self.segment_groups = segment_groups
for group in segment_groups:
group.add(self)
# 紧跟到一个蛇身
self.behind_segment = None
# 初始化相左移动
self.movedir = moveLeft
def add_segment(self):
"""在当前后面增加一个新的蛇身,蛇长长"""
seg = self
# 循环到尾部增加
while True:
if seg.behind_segment == None:
x = seg.spos[0]
y = seg.spos[1]
if seg.movedir == moveLeft:
x += 1 # 如果当前方向相左移动,则需要向右边加一个,其它方向类似
elif seg.movedir == moveRight:
x -= 1
elif seg.movedir == moveUp:
y += 1
elif seg.movedir == moveDown:
y -= 1
seg.behind_segment = Snake_Segment((x, y), seg.segment_groups)
seg.behind_segment.movedir = seg.movedir
break
else:
seg = seg.behind_segment #向后查找
def update(self):
"""移动的动作在头部中"""
pass
def move(self):
"""根据方向移动到不同位置上"""
#self.spos = (self.spos[0] + MOVE_VECTOR[self.movedir][0], self.spos[0] + MOVE_VECTOR[self.movedir][1])
x = self.spos[0] + MOVE_VECTOR[self.movedir][0]
y = self.spos[1] + MOVE_VECTOR[self.movedir][1]
if x < 0:
x = SCREEN_SEGMENT[0]
elif y < 0:
y = SCREEN_SEGMENT[1]
elif x > SCREEN_SEGMENT[0]:
x = 0
elif y > SCREEN_SEGMENT[1]:
y = 0
self.spos = (x, y)
self.rect.topleft = (x * SNAKE_SEG_SIZE[0], y * SNAKE_SEG_SIZE[1])
# 同时移动后面的蛇身
if self.behind_segment != None:
self.behind_segment.move()
self.behind_segment.movedir = self.movedir
class Snake_Head(Snake_Segment):
"""蛇头, 主要属性是方向"""
def __init__(self, spos, movedir, segment_groups):
Snake_Segment.__init__(self, spos, segment_groups, color = SNAKE_HEAD_COLOR)
self.movedir = movedir
self.movecount = 0
def update(self):
self.movecount += MOVE_RATE
if self.movecount > MOVE_THRESHOLD:
self.move()
self.movecount = 0
class Food(pygame.sprite.Sprite):
def __init__(self, takeupgroup):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface(FOODSIZE).convert()
self.image.fill((250,250,250))
# 两个food不能出现在同一个或相交的位置
self.rect = self.image.get_rect()
while True:
self.rect.topleft = (random.randint(0,SCREEN_SEGMENT[0]) * SNAKE_SEG_SIZE[0],\
random.randint(0,SCREEN_SEGMENT[1]) * SNAKE_SEG_SIZE[1])
for sprt in takeupgroup:
if self.rect.colliderect(sprt):
continue #随机生成的与前一个位置相交,则继续生成位置
break
class Block(pygame.sprite.Sprite):
def __init__(self, rect):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((rect[2], rect[3])).convert()
self.image.fill(BLOCK_COLOR)
self.rect = self.image.get_rect()
self.rect.topleft = (rect[0], rect[1])
class Score(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.font = pygame.font.Font(None, 20)
self.font.set_italic(1)
self.color = pygame.Color('white')
self.lastscore = -1
self.update()
self.rect = self.image.get_rect().move(10,450)
def update(self):
if SCORE != self.lastscore:
self.lastscore = SCORE
msg = "Score: %d" % SCORE
self.image = self.font.render(msg, 0, self.color)
class ResourceLoad:
def __init__(self):
self.datapath = os.path.join(main_dir,'data')
def load_image(self,file):
"加载图片"
try:
self.file = os.path.join(self.datapath, file)
surface = pygame.image.load(self.file)
except pygame.error:
raise SystemExit('Could not load image "%s" %s' %(self.file,\
pygame.get_error))
return surface.convert()
def load_images(self, *files):
imgs = []
for file in files:
imgs.append(load_image(file))
return imgs
# 默认声音类
class dummysound:
def play(self):pass
def load_sound(file):
if not pygame.mixer: return dummysound()
self.file = os.path.join(self.datapath, file)
try:
sound = pygame.mixer.Sound(self.file)
return sound
except pygame.error:
print 'Warning, unable to load , %s' % self.file
return dummysound()
def main():
# initialize everything
pygame.init()
screen = pygame.display.set_mode(SCREENSIZE)
pygame.display.set_caption('Snake')
pygame.mouse.set_visible(0)
# background
#background = pygame.Surface(screen.get_size())
#background = background.convert()
#background.fill((0,0,0))
# 加载图片,代替黑屏背景
res = ResourceLoad()
background = res.load_image('background2.jpg')
# display the background
screen.blit(background, (0,0))
pygame.display.flip()
# prepare Snake
clock = pygame.time.Clock()
# groups
snakegroup = pygame.sprite.Group()
snakeheadgroup = pygame.sprite.Group()
foodgroup = pygame.sprite.Group()
takeupgroup = pygame.sprite.Group()
blockgroup = pygame.sprite.Group()
allsprites = pygame.sprite.RenderUpdates()
# 创建一条蛇
snake = Snake_Head(START_POS, moveRight, [snakegroup, allsprites, takeupgroup])
snakeheadgroup.add(snake)
for i in range(START_SEGMENT):
snake.add_segment()
#创建障碍物
#blocktop = Block((0, 0, SCREENSIZE[0], BLOCK_WIDE))
#blockgroup.add(blocktop)
#blockleft = Block((0, 0, BLOCK_WIDE, SCREENSIZE[1]))
#blockgroup.add(blockleft)
#blockright = Block((SCREENSIZE[0]-BLOCK_WIDE, 0, BLOCK_WIDE, SCREENSIZE[1]))
#blockgroup.add(blockright)
#blockbottom = Block((0, SCREENSIZE[1]-BLOCK_WIDE, SCREENSIZE[0], BLOCK_WIDE))
#blockgroup.add(blockbottom)
#for block in blockgroup:
# allsprites.add(block)
global socre
if pygame.font:
allsprites.add(Score())
global SCORE
curfood = None
# 初始化方向
movedir = snake.movedir
donotmovedir = moveRight
lose = False
quit = False
while not quit:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
print "exit, good bye!"
quit = True
return
keystate = pygame.key.get_pressed()
# 相左不能向右,反之亦然,
# 向上不能向下, 反之亦然
curMovdir = snake.movedir
if keystate[pygame.K_RIGHT] == 1:
movedir = moveRight
donotmovedir = moveLeft
elif keystate[pygame.K_LEFT] == 1:
movedir = moveLeft
donotmovedir = moveRight
elif keystate[pygame.K_UP] == 1:
movedir = moveUp
donotmovedir = moveDown
elif keystate[pygame.K_DOWN] == 1:
movedir = moveDown
donotmovedir = moveUp
if not curMovdir == donotmovedir:
snake.movedir = movedir
allsprites.clear(screen, background)
allsprites.update()
# 产生一个食物,以后会一次产生一个或多个食物
if curfood == None:
curfood = Food(takeupgroup)
foodgroup.add(curfood)
takeupgroup.add(curfood)
allsprites.add(curfood)
# 检测碰撞
# snake -> snake
col = pygame.sprite.groupcollide(snakeheadgroup, snakegroup,\
False,False)
for head in col:
for tail in col[head]:
if not tail is snake:
print "snake crash"
quit = True
lose = True
# snake -> food
col = pygame.sprite.groupcollide(snakeheadgroup, foodgroup,\
False,True)
for head in col:
for tail in col[head]:
curfood = None
snake.add_segment()
SCORE += 1
# snake -> block
#col = pygame.sprite.groupcollide(snakeheadgroup,blockgroup,\
# True, False)
#for head in col:
# for block in col[head]:
# quit = True
# lose = True
# 重绘制所有元素
screen.blit(background,(0,0))
allsprites.draw(screen)
pygame.display.flip()
if lose == True:
f = pygame.font.Font(None, 100)
failmsg = f.render('Game Over', True, GAME_OVER_COLOR)
failmsgrect = failmsg.get_rect()
failmsgrect.center = SCREENRECT.center
screen.blit(failmsg, failmsgrect)
pygame.display.flip()
pygame.time.wait(2000)
pygame.quit()
if __name__ == '__main__': main()