pygame实现贪吃蛇小游戏
程序员文章站
2024-03-19 08:21:04
...
pygame实现贪吃蛇小游戏
由于这段时间实在是太聊了,没什么事做,游戏也玩腻了,所以玩起来pygame。pygame是真的容易上手,但用来做游戏也有很大的局限性,做一些小游戏还是没什么问题的。
首先,制作游戏最大的问题我认为是确定要制作的游戏的玩法,具体的细节都确定清楚之后再去实现还是很容易的。所以开发游戏最大的问题可能是需要一个好的创意,没有好的创意都没法开始。贪吃蛇相信没有人没玩过了,玩法也很简单,没吃一个方块可以使蛇的身体变长,头部碰到墙壁或者头部碰到自己身体就game over了。然后也需要一个计分板记录分数。由于只是一个简单的小游戏,不用一个具体的步骤了,就自己码代码的时候不断完善代码还是很容易完成的。
初步的版本,实现了蛇的移动和吃方块身体变长,但还没有检测导致game over 的时间。自己想到了不少事情,如可以记录游戏分数并保存到本地文件,记录最高分,但毕竟只是个小游戏,只要保证游戏的完整性就算过关了,再怎么追求完美也不过是用pygame开发的,其价值始终只在于自娱自乐。之后将这个版本完善一下就算完成了。
import pygame,sys,numpy as nu,random as ra
from pygame.sprite import Sprite,Group
class setting():
def __init__(self,w,h):
self.w1=0.1*w
self.w2=0.7*w
self.w3=0.75*w
self.w4=0.95*w
self.h1=0.1*h
self.h2=0.7*h
self.length=0.05*self.w1
self.speed=self.length
self.wall_length=0.1*self.length
self.wall_color=(0,0,0)
self.snake_color=(0,0,230)
self.head_color=(230,0,0)
class block(Sprite):
def __init__(self,screen,rect,test,color):
super().__init__()
self.screen=screen
self.rect=rect #pygame.Rect(0,0,10,10)
self.test=test
self.color=color
def update(self):
self.rect=self.test(self.rect)
def draw_bullet(self):
pygame.draw.rect(self.screen,self.color,self.rect)
class textBlock(Sprite):
def __init__(self,screen,rect,color,text,text_color):
super().__init__()
self.screen=screen
self.rect=rect #pygame.Rect(0,0,10,10)
self.color=color
self.text_color=text_color
self.font=pygame.font.SysFont(None,68)
self.image=self.font.render(text,True,self.text_color,self.color)
self.image_rect=self.image.get_rect()
self.image_rect.left=rect.left-200
self.image_rect.top=rect.top-200
def update(self):
pass
def changeText(self,text):
self.image=self.font.render(text,True,self.text_color,self.color)
def draw_bullet(self):
self.screen.blit(self.image,self.image_rect)
#pygame.draw.rect(self.screen, self.color, self.rect)
def run_game():
pygame.init()
w,h=1200,800
screen=pygame.display.set_mode((w,h))
pygame.display.set_caption("pygame1")
bg_color=(230,230,230)
settings=setting(w,h)
g,gg=Group(),Group()
a = block(screen, pygame.Rect((settings.w1+settings.w2)/2, (settings.h1+settings.h2)/2,
settings.length, settings.length),lambda r:r,settings.head_color)
aa = block(screen, pygame.Rect((settings.w1 + settings.w2) / 2, (settings.h1 + settings.h2) / 2,
settings.length, settings.length), lambda r: r, settings.snake_color)
g.add(a)
#墙壁
wall=Group()
w1=block(screen, pygame.Rect(settings.w1, settings.h1, settings.wall_length, settings.h2-settings.h1),
lambda r:r,settings.wall_color)
w2 = block(screen, pygame.Rect(settings.w1, settings.h1, settings.w2-settings.w1, settings.wall_length),
lambda r: r,settings.wall_color)
w3 = block(screen, pygame.Rect(settings.w2, settings.h1, settings.wall_length, settings.h2-settings.h1),
lambda r: r,settings.wall_color)
w4 = block(screen, pygame.Rect(settings.w1, settings.h2, settings.w2-settings.w1, settings.wall_length),
lambda r: r,settings.wall_color)
wall.add(w1);wall.add(w2);wall.add(w3);wall.add(w4)
w5 = block(screen, pygame.Rect(settings.w3, settings.h1, settings.wall_length, settings.h2 - settings.h1),
lambda r: r, settings.wall_color)
w6 = block(screen, pygame.Rect(settings.w3, settings.h1, settings.w4 - settings.w3, settings.wall_length),
lambda r: r, settings.wall_color)
w7 = block(screen, pygame.Rect(settings.w4, settings.h1, settings.wall_length, settings.h2 - settings.h1),
lambda r: r, settings.wall_color)
w8 = block(screen, pygame.Rect(settings.w3, settings.h2, settings.w4 - settings.w3, settings.wall_length),
lambda r: r, settings.wall_color)
wall.add(w5)
wall.add(w6)
wall.add(w7)
wall.add(w8)
timesec = textBlock(screen, pygame.Rect(settings.w3+200, settings.h1+200, 50,50), (230, 230, 230),
"time:"+str(pygame.time.get_ticks()), (200, 0, 20))
leng=1
snakeLength = textBlock(screen, pygame.Rect(settings.w3 + 200, settings.h1 + 400, 50, 50), (230, 230, 230),
"length:" + str(leng), (200, 0, 20))
start=textBlock(screen,pygame.Rect(w/2,h/2,50,50),(230,230,230),"Gluttonous Snake",(0,200,200))
start_1 = textBlock(screen, pygame.Rect(w / 2+50, h / 2+100, 50, 50), (230, 230, 230),
"Start game",(200,20,20))
start_2 = textBlock(screen, pygame.Rect(w / 2 + 50, h / 2 + 200, 50, 50), (230, 230, 230),
"exit", (200, 20, 20))
block_=block(screen, pygame.Rect(w / 2-170, h / 2-85, 10, 10),
lambda r:r,settings.wall_color)
kw,ks,ka,kd=False,False,False,False
start_game,exit_game,generator=False,False,False
timeStart=0
ls=[start_game,kw,ks,ka,kd,exit_game,timeStart,generator,leng]
lx,ly,la=[],[],[]
def check_event(ls,lx,ly,la):
for event in pygame.event.get():
if event.type==pygame.QUIT:
sys.exit()
elif event.type==pygame.KEYDOWN and ls[0]:
if event.key==pygame.K_w:
ls[1:5]=[True,False,False,False]
elif event.key==pygame.K_a:
ls[1:5]=[False,False,True,False]
elif event.key==pygame.K_s:
ls[1:5]=[False,True,False,False]
elif event.key==pygame.K_d:
ls[1:5]=[False,False,False,True]
elif event.type==pygame.KEYDOWN:
if event.key==pygame.K_SPACE :
if(ls[5]):
sys.exit()
else:
ls[0],ls[2],ls[7]=True,True,True
ls[6]=pygame.time.get_ticks()
elif event.key==pygame.K_w or event.key==pygame.K_s:
if(ls[5]):
block_.rect.y-=100
else:
block_.rect.y+=100
ls[5]=not ls[5]
if(ls[0]):#start game
if(ls[7]):
aa.rect.x,aa.rect.y=ra.randint(settings.w1+20,settings.w2-20),\
ra.randint(settings.h1+20,settings.h2-20)
ls[7]=False
if(pygame.time.get_ticks()%30==1):
if(ls[1] and a.rect.y>settings.h1):
a.rect.y-=settings.speed
lx.append(0)
ly.append(-settings.speed)
elif(ls[2] and a.rect.y<settings.h2-settings.length):
a.rect.y+=settings.speed
lx.append(0)
ly.append(settings.speed)
elif(ls[3] and a.rect.x>settings.w1):
a.rect.x-=settings.speed
lx.append(-settings.speed)
ly.append(0)
elif(ls[4] and a.rect.x<settings.w2-settings.length):
a.rect.x+=settings.speed
lx.append(settings.speed)
ly.append(0)
dir=-2
for als in la:
als.rect.x+=lx[dir]
als.rect.y+=ly[dir]
dir-=1
a.draw_bullet()
g.update()
aa.draw_bullet()
for all in gg:
all.draw_bullet()
for walls in wall:
walls.draw_bullet()
timesec.changeText("time:"+str((pygame.time.get_ticks()-ls[6])//1000))
timesec.draw_bullet()
snakeLength.draw_bullet()
if (pygame.sprite.spritecollideany(aa, g)):
print("collide")
ls[7]=True
ls[8]+=1
snakeLength.changeText("length:" + str(ls[8]))
if(len(la)==0):
aaa = block(screen, pygame.Rect(a.rect.x,a.rect.y,
settings.length, settings.length), lambda r: r, settings.snake_color)
else:
aaa = block(screen, pygame.Rect(a.rect.x, a.rect.y,
settings.length, settings.length), lambda r: r,
settings.snake_color)
for x in range(len(la)+1):
aaa.rect.x-=lx[-x-1]
aaa.rect.y-=ly[-x-1]
gg.add(aaa)
la.append(aaa)
else:
start.draw_bullet()
start_1.draw_bullet()
start_2.draw_bullet()
block_.draw_bullet()
while True:
screen.fill(bg_color)
check_event(ls,lx,ly,la)
pygame.display.flip()
run_game()
最终完成版本:
import pygame,sys,numpy as nu,random as ra
from pygame.sprite import Sprite,Group
class setting():
def __init__(self,w,h):
self.w1=0.1*w
self.w2=0.7*w
self.w3=0.75*w
self.w4=0.95*w
self.h1=0.1*h
self.h2=0.7*h
self.length=0.05*self.w1
self.speed=self.length
self.wall_length=0.1*self.length
self.wall_color=(0,0,0)
self.snake_color=(0,0,230)
self.head_color=(230,0,0)
class block(Sprite):
def __init__(self,screen,rect,test,color):
super().__init__()
self.screen=screen
self.rect=rect #pygame.Rect(0,0,10,10)
self.test=test
self.color=color
def update(self):
self.rect=self.test(self.rect)
def draw_bullet(self):
pygame.draw.rect(self.screen,self.color,self.rect)
class textBlock(Sprite):
def __init__(self,screen,rect,color,text,text_color):
super().__init__()
self.screen=screen
self.rect=rect #pygame.Rect(0,0,10,10)
self.color=color
self.text_color=text_color
self.font=pygame.font.SysFont(None,68)
self.image=self.font.render(text,True,self.text_color,self.color)
self.image_rect=self.image.get_rect()
self.image_rect.left=rect.left-200
self.image_rect.top=rect.top-200
def update(self):
pass
def changeText(self,text):
self.image=self.font.render(text,True,self.text_color,self.color)
def draw_bullet(self):
self.screen.blit(self.image,self.image_rect)
#pygame.draw.rect(self.screen, self.color, self.rect)
def run_game():
pygame.init()
w,h=1200,800
screen=pygame.display.set_mode((w,h))
pygame.display.set_caption("pygame1")
bg_color=(230,230,230)
settings=setting(w,h)
g,gg=Group(),Group()
a = block(screen, pygame.Rect((settings.w1+settings.w2)/2, (settings.h1+settings.h2)/2,
settings.length, settings.length),lambda r:r,settings.head_color)
aa = block(screen, pygame.Rect((settings.w1 + settings.w2) / 2, (settings.h1 + settings.h2) / 2,
settings.length, settings.length), lambda r: r, settings.snake_color)
g.add(a)
#墙壁
wall=Group()
w1=block(screen, pygame.Rect(settings.w1, settings.h1, settings.wall_length, settings.h2-settings.h1),
lambda r:r,settings.wall_color)
w2 = block(screen, pygame.Rect(settings.w1, settings.h1, settings.w2-settings.w1, settings.wall_length),
lambda r: r,settings.wall_color)
w3 = block(screen, pygame.Rect(settings.w2, settings.h1, settings.wall_length, settings.h2-settings.h1),
lambda r: r,settings.wall_color)
w4 = block(screen, pygame.Rect(settings.w1, settings.h2, settings.w2-settings.w1, settings.wall_length),
lambda r: r,settings.wall_color)
wall.add(w1);wall.add(w2);wall.add(w3);wall.add(w4)
w5 = block(screen, pygame.Rect(settings.w3, settings.h1, settings.wall_length, settings.h2 - settings.h1),
lambda r: r, settings.wall_color)
w6 = block(screen, pygame.Rect(settings.w3, settings.h1, settings.w4 - settings.w3, settings.wall_length),
lambda r: r, settings.wall_color)
w7 = block(screen, pygame.Rect(settings.w4, settings.h1, settings.wall_length, settings.h2 - settings.h1),
lambda r: r, settings.wall_color)
w8 = block(screen, pygame.Rect(settings.w3, settings.h2, settings.w4 - settings.w3, settings.wall_length),
lambda r: r, settings.wall_color)
wall.add(w5)
wall.add(w6)
wall.add(w7)
wall.add(w8)
timesec = textBlock(screen, pygame.Rect(settings.w3+200, settings.h1+200, 50,50), (230, 230, 230),
"time:"+str(pygame.time.get_ticks()), (200, 0, 20))
leng=1
snakeLength = textBlock(screen, pygame.Rect(settings.w3 + 200, settings.h1 + 400, 50, 50), (230, 230, 230),
"length:" + str(leng), (200, 0, 20))
start=textBlock(screen,pygame.Rect(w/2,h/2,50,50),(230,230,230),"Gluttonous Snake",(0,200,200))
start_1 = textBlock(screen, pygame.Rect(w / 2+50, h / 2+100, 50, 50), (230, 230, 230),
"Start game",(200,20,20))
start_2 = textBlock(screen, pygame.Rect(w / 2 + 50, h / 2 + 200, 50, 50), (230, 230, 230),
"exit", (200, 20, 20))
block_=block(screen, pygame.Rect(w / 2-170, h / 2-85, 10, 10),
lambda r:r,settings.wall_color)
kw,ks,ka,kd=False,False,False,False
start_game,exit_game,generator,gameOver=False,False,False,False
timeStart=0
ls=[start_game,kw,ks,ka,kd,exit_game,timeStart,generator,leng,gameOver]
lx,ly=[],[]
def check_event(ls,lx,ly,gg):
for event in pygame.event.get():
if event.type==pygame.QUIT:
sys.exit()
elif event.type==pygame.KEYDOWN and ls[0] and not ls[9]:
if event.key==pygame.K_w:
ls[1:5]=[True,False,False,False]
elif event.key==pygame.K_a:
ls[1:5]=[False,False,True,False]
elif event.key==pygame.K_s:
ls[1:5]=[False,True,False,False]
elif event.key==pygame.K_d:
ls[1:5]=[False,False,False,True]
elif event.type==pygame.KEYDOWN and not ls[9]:
if event.key==pygame.K_SPACE :
if(ls[5]):
sys.exit()
else:
ls[0],ls[2],ls[7]=True,True,True
ls[6]=pygame.time.get_ticks()
elif event.key==pygame.K_w or event.key==pygame.K_s:
if(ls[5]):
block_.rect.y-=100
else:
block_.rect.y+=100
ls[5]=not ls[5]
elif event.type==pygame.KEYDOWN:
if event.key==pygame.K_SPACE :
if(ls[5]):
sys.exit()
else:
ls[0],ls[2],ls[7],ls[9],ls[8]=True,True,True,False,1
la ,lx,ly= [],[],[]
snakeLength.changeText("length:" + str(ls[8]))
gg.empty()
ls[6]=pygame.time.get_ticks()
a.rect.x,a.rect.y=(settings.w1+settings.w2)/2, (settings.h1+settings.h2)/2
elif event.key==pygame.K_w or event.key==pygame.K_s:
if(ls[5]):
block_.rect.y-=100
else:
block_.rect.y+=100
ls[5]=not ls[5]
if(ls[0] and not ls[9]):#start game
if(ls[7]):
aa.rect.x,aa.rect.y=ra.randint(settings.w1+20,settings.w2-20),\
ra.randint(settings.h1+20,settings.h2-20)
ls[7]=False
if(pygame.time.get_ticks()%30==1):
if(ls[1] and a.rect.y>=settings.h1):
a.rect.y-=settings.speed
lx.append(0)
ly.append(-settings.speed)
elif(ls[2] and a.rect.y<=settings.h2-settings.length):
a.rect.y+=settings.speed
lx.append(0)
ly.append(settings.speed)
elif(ls[3] and a.rect.x>=settings.w1):
a.rect.x-=settings.speed
lx.append(-settings.speed)
ly.append(0)
elif(ls[4] and a.rect.x<=settings.w2-settings.length):
a.rect.x+=settings.speed
lx.append(settings.speed)
ly.append(0)
dir=-2
for als in gg:
als.rect.x+=lx[dir]
als.rect.y+=ly[dir]
dir-=1
a.draw_bullet()
g.update()
aa.draw_bullet()
for all in gg:
all.draw_bullet()
for walls in wall:
walls.draw_bullet()
timesec.changeText("time:"+str((pygame.time.get_ticks()-ls[6])//1000))
timesec.draw_bullet()
snakeLength.draw_bullet()
if (pygame.sprite.spritecollideany(aa, g)):
print("collide")
ls[7]=True
ls[8]+=1
snakeLength.changeText("length:" + str(ls[8]))
aaa = block(screen, pygame.Rect(a.rect.x, a.rect.y,
settings.length, settings.length), lambda r: r,
settings.snake_color)
for x in range(len(gg)+1):
aaa.rect.x-=lx[-x-1]
aaa.rect.y-=ly[-x-1]
gg.add(aaa)
if pygame.sprite.spritecollideany(a,wall) or pygame.sprite.spritecollideany(a,gg):
ls[9],ls[1],ls[2],ls[3],ls[4]=True,False,False,False,False
print("game over")
if a.rect.x==settings.w1-settings.length or a.rect.x==settings.w2 \
or a.rect.y==settings.h1-settings.length or a.rect.y==settings.h2:
ls[9], ls[1], ls[2], ls[3], ls[4] = True, False, False, False, False
print("game over")
else:
if ls[9]:
start.changeText("again or exit")
start_1.changeText("again")
start.draw_bullet()
start_1.draw_bullet()
start_2.draw_bullet()
block_.draw_bullet()
while True:
screen.fill(bg_color)
check_event(ls,lx,ly,gg)
pygame.display.flip()
run_game()
虽然可能还有不足之处,但玩起来感觉还不错。