游戏效果图:
1、贪吃蛇模块
游戏中的蛇本质是由一个列表组成的,利用列表可以添加和修改的特性,完成小蛇的移动和成长。我们先定义一个蛇的初始列表self.item=[(20,15),(20,16)]。
那么如何画出一条蛇呢,首先我们需要画出蛇头,蛇头是一个圆形,这时便可以用到模块pygame中画圆形的功能:
pygame.draw.circle(screen,color,position,radius,width)
其中:screen代表游戏图框的大小,color代表颜色,如color=(0,255,0)即代表绿色,position则代表圆心的位置,radius代表圆的半径,width代表线宽,需要注意的是width不能超过radius的数值,否者便会报错。这样一个蛇头便画出来了,同理,蛇的身体也是相同的原理。蛇头与蛇身,共同组成了一个蛇的列表。为了让贪吃蛇动起来,我们就需要对position这个参数下手了,首先需要定义一个蛇头朝向的函数,蛇头是朝左还是朝右运动,便是由此参数所决定的,我们先定义一个蛇头的基础朝向:self.X=1,self.Y=0,那么位置参数可以令为:
head=(self.item[0][0]+self.x,self.item[0][1]+self.y)`
self.item.insert(0,head)
这样,通过改变self.X,self.y的值,就可以改变蛇头的方向。在蛇没有吃到食物的情况下,需要加一句:self.item.pop()否者小蛇便要无限的长大了。本贪吃蛇游戏采用键盘控制的方式,那么,我们便需要将蛇头的朝向和键盘的按键对应起来:
def press(self,keys):
global score
if keys[K_w] or keys[K_UP]:
self.toward(0, -1)
elif keys[K_s] or keys[K_DOWN]:
self.toward(0, 1)
elif keys[K_a] or keys[K_LEFT]:
self.toward(-1, 0)
elif keys[K_d] or keys[K_RIGHT]:
self.toward(1, 0)
不过我们仍然要解决一个问题,即蛇头仅能90°的转向,而不能180°的转向,这需要增加一个判断来解决这个问题:
def toward(self,x,y):
if self.x*x>=0 and self.y*y>=0:
self.x=x
self.y=y
2、食物模块
与贪吃蛇模块相同,食物同样是一个列表,同样通过pygame.draw画出形状,不同的是,食物模块再被吃掉后,需要重新在游戏框内更新食物的位置,这便要用到np.random.randint来随机生成食物的位置坐标,即:
seld.item[0]=random.randint(1,BOARDWIDTH-2),np.random.randint(1,BOARDHEIGHT-2)
同时,如果生成的食物坐标在贪吃蛇上,则需要重新生产坐标,代码如下:
while self.item in snack.item:
self.item[0]=np.random.randint(1, BOARDWIDTH - 2), np.random.randint(1, BOARDHEIGHT - 2)
3、其他模块
定义贪吃蛇与食物模块对于一个贪吃蛇游戏还是远远不够的,游戏界面,记分牌,游戏的结束等,都需要定义对应的函数。
游戏的界面:pygame.init是对pygame模块进行初始化,如果没有这个模块则程序便会报错。pygame.display.set_mode用来设置游戏界面的大小。pygame.display.set_caption用来显示游戏标题。
def game_init():
pygame.init()
screen=pygame.display.set_mode((BOARDWIDTH*20 , BOARDHEIGHT*20 ))
pygame.display.set_caption("snack")
return screen
记分牌:每当贪吃蛇吃到食物时,记分牌则增加100,首先需要判断贪食蛇吃到食物的状态,即蛇头和食物的坐标重合的状态,一个判断即可搞定:
snack_x,snack_y=snack.item[0]
food_x,food_y=attak_chichken.item[0]
if(snack_x==food_x)and(snack_y==food_y):
score+=100
return 1
那么如何让记分牌的分数显示在游戏界面上呢:定义text = u"score: {} ch".format(score),使记分牌的数值与score保持一致。同时定义一个print_text函数,使得输出的数值到指定的位置上去:
def print_text(screen,font,x,y,text,color=(255,0,0)):
imgText = font.render(text, True, color)
screen.blit(imgText, (x, y))
然后再主函数中输入:print_text(screen, font, 0, 0, text)则在游戏界面的左上角生成了记分牌。
游戏的结束:当贪吃蛇头碰到自己的身体或者游戏的边界,则游戏结束。
def game_over(snack):
broad_x,broad_y=snack.get_head()
flag=0
old=len(snack.item)
new=len(set(snack.item))
if new<old:
flag=1
if broad_x==0 or broad_x==BOARDWIDTH-1:
flag=1
if broad_y==0 or broad_y==BOARDHEIGHT-1:
flag=1
if flag:
return True
else:
return False
最后是运行游戏的主函数,贪吃蛇游戏便可以顺利运行:
def game(screen):
snack=Snack()
food=attak_chichken()
font=pygame.font.SysFont('simHei',20)
is_fail=0
while True:
for event in pygame.event.get():
if event.type == QUIT:
exit()
screen.fill((65, 240, 75))
init_board(screen=screen)
keys = pygame.key.get_pressed()
snack.press(keys)
if is_fail:
font2 = pygame.font.Font('E:\ freesansbold.ttf', 40)
print_text(screen, font, 0, 0, text)
print_text(screen, font2, 400, 200, "GAME OVER")
if not is_fail:
enlarge = snack.eat_food(food)
text = u"score: {} ch".format(score)
print_text(screen, font, 0, 0, text)
food.update(screen, enlarge, snack)
food.chicken_move()
snack.move(enlarge)
is_fail = game_over(snack=snack)
snack.draw(screen)
pygame.display.update()
time.sleep(0.10)