python贪吃蛇简单演示
程序员文章站
2022-07-14 14:52:43
...
一、 脚本环境
我的环境:
- Python 3.6.8
- pygame 1.9.6
- 操作系统 win10
也可以用其他操作系统、python版本及其适应的pygame模块。
二、思路
总的来说,把pygame窗口设为800x400,将蛇身体的每一方块大小设为20,窗口大小要为20的整数倍才好展开代码。蛇每一次移动一个蛇方块距离即20。为了设置随机出现的“豆子”且方便蛇吞下后长大一个蛇方块,将800x400大小的pygame窗口划分为一个个20x20的方块,保存于ground变量中。
- 设置窗口。
- 在窗口上绘制蛇、豆子、计分板等图形元素。
- 接收键盘有关按键的输入信号,控制“蛇头”方向。
- 移动蛇位置。
- 判断蛇是否死亡,如撞墙、吃到自己。如果是其中之一则绘制“Game Over”字样,重新开始游戏。
由于把蛇分割成一个个20x20大小的方块,所以每一部分都是独立的,而且接收键盘信号从而改变方向只能是“蛇头”这个20x20的方块,为了实现“蛇身”们沿着“蛇头“的运行轨迹而运行,需要将整条蛇以列表加字典的形式在代码中展现,而且还需要将”dir“键值从“蛇尾”开始依次将上一个“dir”键值覆盖。形如。
蛇的表示:snakes=[{'rect':pg.Rect(100,100,20,20),'dir':down},
{'rect':pg.Rect(100,80,20,20),'dir':down},
{'rect':pg.Rect(100,60,20,20),'dir':down}]
覆盖写法:for i in range(len(snakes)-1,0,-1):
snakes[i]['dir']=snakes[i-1]['dir']
其中“rect”键值表示蛇在窗口中的位置和大小,“dir”键值表示蛇的每一部分在下一移动中的朝向。
三、 代码展示
#python3
import pygame as pg
from pygame.locals import *
import random
#---------------------
#Get Bean point Func in random
def Bean():
global bean
bp=random.choice(ground)
bean=[{'rect':pg.Rect(bp[0],bp[1],20,20)}]
#----------------------
#Draw snakes white strike
def Boundary():
global snakes,info
point=[(snake['rect'].left,snake['rect'].top) for snake in snakes]
for p in point:
pg.draw.line(screen,info['strike'],(p[0],p[1]),(p[0],p[1]+20),1)
pg.draw.line(screen,info['strike'],(p[0],p[1]),(p[0]+20,p[1]),1)
pg.draw.line(screen,info['strike'],(p[0]+20,p[1]),(p[0]+20,p[1]+20),1)
pg.draw.line(screen,info['strike'],(p[0],p[1]+20),(p[0]+20,p[1]+20),1)
#----------------------
#Main draw func including score word,snake,bean,
def Draw():
global info
#-----------------
#score record element
font2=pg.font.SysFont(None,1)
text2=font.render("length: {}".format(len(snakes)),True,BLACK,WHITE)
point2=pg.Rect(0,0,60,20)
screen.fill(info['bg'])
screen.blit(text2,point2)
#------------------
#draw bean and snake in window
for b in bean:
pg.draw.rect(screen,info['apple'],b['rect'])
for snake in snakes:
pg.draw.rect(screen,info['snake'],snake['rect'])
#-----------------
#give snake make up
Boundary()
pg.display.update()
clock.tick(8)
#-----------------------
#Control snake to move in direct and distance func
def Move():
for i in range(len(snakes)):
if snakes[i]['dir']==down:
snakes[i]['rect'].top+=20
if snakes[i]['dir']==up:
snakes[i]['rect'].top-=20
if snakes[i]['dir']==left:
snakes[i]['rect'].left-=20
if snakes[i]['dir']==right:
snakes[i]['rect'].left+=20
Draw()
#----------------------
#move the rest body exclude head
#the snake part that you only can crab is its head,the reat of part will follow its up one part
for i in range(len(snakes)-1,0,-1):
snakes[i]['dir']=snakes[i-1]['dir']
#-----------------------
#Judge if game over or get bean,to eat itself,to touch wall... func
def Crush():
global down,up,left,right,info
#---------------------
#touch wall with your snake head GG... :(
ww=info['width']
hh=info['heigth']
headR=snakes[0]['rect'].right
headL=snakes[0]['rect'].left
headT=snakes[0]['rect'].top
headB=snakes[0]['rect'].bottom
if headR>ww or headL<0 or headT<0 or headB>hh:
GameOver()
#---------------------
#I get you my body GG... :(
body=[[i['rect'].left,i['rect'].top] for i in snakes[1:]]
location=[headL,headT]
if location in body:
GameOver()
#---------------------
#bean location in window
beanR=bean[0]['rect'].right
beanL=bean[0]['rect'].left
beanT=bean[0]['rect'].top
beanB=bean[0]['rect'].bottom
#----------------------
#mom I am growing,can I eat that blue thing again.Nice!! :p
if headL==beanL and headT==beanT:
tailL,tailT=snakes[-1]['rect'].left,snakes[-1]['rect'].top
tailR,tailB=snakes[-1]['rect'].right,snakes[-1]['rect'].bottom
tailDir=snakes[-1]['dir']
if tailDir==down:
snakes.append({'rect':pg.Rect(tailL,tailT-20,20,20),'dir':down})
bean.remove(bean[0])
Bean()
elif tailDir==up:
snakes.append({'rect':pg.Rect(tailL,tailT+20,20,20),'dir':up})
bean.remove(bean[0])
Bean()
elif tailDir==left:
snakes.append({'rect':pg.Rect(tailR,tailT,20,20),'dir':left})
bean.remove(bean[0])
Bean()
elif tailDir==right:
snakes.append({'rect':pg.Rect(tailL-20,tailT,20,20),'dir':right})
bean.remove(bean[0])
Bean()
#-----------------------
#Draw "Game over"
def GameOver():
global info,text
screen.fill(info['bg'])
screen.blit(text,point)
pg.display.update()
clock.tick(1)
Main()
#-----------------------
#main func
def Main():
global snakes,down,up,left,right
#--------------------
#as you see your snake is a list be taked apart into 20 size
snakes=[{'rect':pg.Rect(100,100,20,20),'dir':down},
{'rect':pg.Rect(100,80,20,20),'dir':down},
{'rect':pg.Rect(100,60,20,20),'dir':down}]
#--------------------
#Emerge bean in window
Bean()
#--------------------
#take sinal from keyboard,like exit and "w" "a" "s" "d" equal "up" "left" "down" "right"
while True:
for event in pg.event.get():
if event.type==12:
pg.quit()
exit()
#-------------------
#crub head
if event.type==KEYDOWN:
head=snakes[0]['dir']
if event.unicode==right and head!=left:
snakes[0]['dir']=right
if event.unicode==left and head!=right:
snakes[0]['dir']=left
if event.unicode==up and head!=down:
snakes[0]['dir']=up
if event.unicode==down and head!=up:
snakes[0]['dir']=down
#-------------------
#move your snake
Move()
#-------------------
#judge if your snake die?
Crush()
if __name__=="__main__":
#--------------------
#set some color var
BLACK=(0,0,0)
RED=(255,0,0)
WHITE=(255,255,255)
BLUE=(0, 0, 255)
#--------------------
#combine color var and window size var into info dict var
info={'bg':WHITE,
'snake':BLACK,
'apple':BLUE,
'font':BLACK,
'width':800,
'heigth':400,
'strike':WHITE,}
#--------------------
#define direct var、clock var and window size
w,h=info['width'],info['heigth']
clock = pg.time.Clock()
up='w'
down='s'
left='a'
right='d'
#---------------------
#pygame common start configure
pg.init()
screen=pg.display.set_mode((w,h),0,32)
#---------------------
#game over font
font=pg.font.SysFont(None,48)
text=font.render("Game Over",True,RED,WHITE)
point=pg.Rect(300,150,100,40)
#---------------------
#pygame window point in every 20
ground=[[x,y] for x in range(0,w,20) for y in range(100,h-100,20)]
#---------------------
#game start
Main()
四、操作演示
谢谢各位