pygame学习日记——贪吃猪(蛇)
作者:互联网
新手向——pygame实现贪吃蛇小游戏
猪头图片由一只可爱的灵魂画家提供
贪吃蛇主要逻辑是蛇的头部带动身体移动,所以移动操作时,只需要更新头部的位置信息,而蛇身的每一块位置则更替为前一块的位置。使用列表存储蛇(蛇的头部和身体块分别由一对坐标表示),列表的第一个元素即为蛇头,对于每一次移动,采用生成新的位置坐标插入到列表的首位充当新的头部,并将列表的最后一个元素丢弃,实现蛇身每一块的前移。完整代码如下:
详细注释源码
import pygame
import sys
import random
#定义用来表示移动方向的常量(Python中并没有提供定义常量的保留字)
UP = 'move_up'
DOWN = 'move_down'
LEFT = 'move_left'
RIGHT = 'move_right'
#初始化pygame 关于init()函数相关信息见https://blog.csdn.net/Enderman_xiaohei/article/details/88655432
pygame.init()
#加载头部,身体和食物的图片
image_head = pygame.image.load("src/head.png")
image_body = pygame.image.load("src/body.png")
image_food = pygame.image.load("src/food.png")
#设置格子单位,后面的移动操作都是以此最单位进行
unit = image_body.get_width()
#设置游戏窗体尺寸
frame_size = width, height = 40,20
#生成游戏窗口
screen = pygame.display.set_mode((frame_size[0]*unit, frame_size[1]*unit))
#设置窗体标题
pygame.display.set_caption("贪吃猪")
#设置游戏图标
pygame.display.set_icon(image_head)
#加载字体
font_score = pygame.font.Font("src/font.ttf",24)
font_start = pygame.font.Font("C:/Windows/Fonts/HGCY_CNKI.TTF",48)
#用于设置游戏画面刷新帧数
clock = pygame.time.Clock()
#食物生成函数,需要传入蛇
def gen(snack):
while True:
#随机生成食物的坐标
x = random.randrange(1, frame_size[0] - 1) * unit
y = random.randrange(1, frame_size[1] - 1) * unit
#用来标志生成的食物是否于蛇重叠
repeat = False
for each in snack:
#判断是否重叠,如果重叠就将repeat标识设置为True,重新生成食物
if x == each[0] and y == each[1]:
repeat = True
#不重叠就返回食物坐标
if not repeat:
return [x, y]
#移动函数,需要传入移动方向和蛇
def move(direction,snack):
newhead = []
#声明unit是全局变量
global unit
#生成新的头部
newhead.append(snack[0][0])
newhead.append(snack[0][1])
#根据传入的方向设置新头部的移动
if direction == UP:
newhead[1] -= unit
elif direction == DOWN:
newhead[1] += unit
elif direction == RIGHT:
newhead[0] += unit
elif direction == LEFT:
newhead[0] -= unit
#将新的头部插到列表的首位,并移除snake列表的最后一个元素,实现蛇的整体移动
#移动的本质时头部带动身体,每一块身体移动到前一块身体的位置
snack.insert(0,newhead)
snack.pop()
#返回移动过的蛇
return snack
#游戏开始界面,随便写的,可以忽略
def gamestart():
global unit,frame_size
speed_start = [1, 1]
speed_exit = [1, 1]
text_start = font_start.render("开始游戏", True, (255, 0, 0))
text_start_rect = text_start.get_rect()
text_exit = font_start.render("退出游戏", True, (255, 0, 0))
text_exit_rect = text_exit.get_rect()
text_exit_rect.left = frame_size[0]*unit - text_exit_rect.width
while True:
for event in pygame.event.get():
#设置退出
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.pos[0] > text_start_rect.left \
and event.pos[0] < text_start_rect.right \
and event.pos[1] > text_start_rect.top \
and event.pos[1] < text_start_rect.bottom:
return True
elif event.pos[0] > text_exit_rect.left \
and event.pos[0] < text_exit_rect.right \
and event.pos[1] > text_exit_rect.top \
and event.pos[1] < text_exit_rect.bottom:
pygame.quit()
sys.exit()
text_start_rect = text_start_rect.move(speed_start[0], speed_start[1])
text_exit_rect = text_exit_rect.move(speed_exit[0], speed_exit[1])
if text_start_rect.left < 0 or text_start_rect.right > frame_size[0] * unit:
speed_start[0] = - speed_start[0]
if text_start_rect.top < 0 or text_start_rect.bottom > frame_size[1] * unit:
speed_start[1] = - speed_start[1]
if text_exit_rect.left < 0 or text_exit_rect.right > frame_size[0] * unit:
speed_exit[0] = - speed_exit[0]
if text_exit_rect.top < 0 or text_exit_rect.bottom > frame_size[1] * unit:
speed_exit[1] = - speed_exit[1]
screen.fill((255, 255, 255))
screen.blit(text_start, text_start_rect)
screen.blit(text_exit,text_exit_rect)
pygame.display.update()
clock.tick(300)
#游戏主体函数
def maingame():
global unit
# 游戏开始时生成蛇的头部(游戏中的头部,身体和食物均以坐标元组(x,y)表示
head = [5 * unit, 5 * unit]
# 使用列表来表示整条蛇,游戏开始时只有头部和两节身体
snack = [head, [4 * unit, 5 * unit], [3 * unit, 5 * unit]]
#用于检测头部是否触碰身体
collision = False
# 设置蛇默认的移动方向
direction = RIGHT
# 用于判断画面中是否已经存在食物,如果不存在(被吃掉)就重新生成食物
food_exist = False
# 用来保存食物的位置
food_site = (0, 0)
# 用于控制移动频率
delay = 0
while True:
for event in pygame.event.get():
#设置退出
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
#设置按钮操作监听
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
#按下上建如果当前方向不是向下,则设置方向向上,并移动一次
if direction != DOWN:
direction = UP
#重置delay,防止移动后立即再次移动
delay = 0
snack = move(direction, snack)
elif event.key == pygame.K_DOWN:
if direction != UP:
direction = DOWN
delay = 0
snack = move(direction, snack)
elif event.key == pygame.K_RIGHT:
if direction != LEFT:
direction = RIGHT
delay = 0
snack = move(direction, snack)
elif event.key == pygame.K_LEFT:
if direction != RIGHT:
direction = LEFT
delay = 0
snack = move(direction, snack)
#当不存在食物时,创建食物
if not food_exist:
food_site = gen(snack)
food_exist = not food_exist
#填充窗体背景为白色
screen.fill((255, 255, 255))
delay = (delay + 1) % 90
#如果头部和食物坐标相同,代表食物被吃,重新生成食物,身体加一
if snack[0][0] == food_site[0] and snack[0][1] == food_site[1]:
food_exist = False
#在身体的第一块设置新的身体,便于检测头部与身体的碰撞
snack.append(snack[1])
#画面没刷新30此执行一次移动
if not delay%30:
snack = move(direction, snack)
#绘制得分,得分为snack的长度减3
text = font_score.render("Your Score: {}".format(len(snack)-3), True, (255, 0, 0))
screen.blit(text,(30,30))
#绘制蛇
for each in snack:
screen.blit(image_body, (each[0], each[1]))
#重新绘制头部
screen.blit(image_head,(snack[0][0], snack[0][1]))
#绘制食物
screen.blit(image_food,(food_site[0],food_site[1]))
#检测头部是否与身体碰撞
for each in snack[1:]:
if each[0] == snack[0][0] and each[1] == snack[0][1]:
collision = True
#如果头部碰墙,则游戏结束,绘制游戏结束画面
if snack[0][0] < 0 or snack[0][1] < 0 \
or snack[0][0] + unit > frame_size[0]*unit \
or snack[0][1] + unit > frame_size[1]*unit\
or collision:
screen.fill((255,255,255))
text_again = font_start.render("GameOver", True, (255, 0, 0))
screen.blit(text_again, (450, 100))
text_score = font_score.render("Your Score: {}".format(len(snack)-3), True, (255, 0, 0))
screen.blit(text_score, (510, 200))
text_again = font_start.render("重新开始", True, (255, 0, 0))
screen.blit(text_again, (480, 300))
text_exit = font_start.render("退出游戏", True, (255, 0, 0))
screen.blit(text_exit, (480, 400))
pygame.display.update()
while True:
for event in pygame.event.get():
# 设置退出
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
#点击重新开始
if event.pos[0] > 480\
and event.pos[0] < 480 + text_again.get_rect().width\
and event.pos[1] > 300\
and event.pos[1] < 300 + text_again.get_rect().height:
return True
#点击退出游戏
elif event.pos[0] > 480\
and event.pos[0] < 480 + text_exit.get_rect().width\
and event.pos[1] > 400\
and event.pos[1] < 400 + text_exit.get_rect().height:
pygame.quit()
sys.exit()
#设置刷新帧率
clock.tick(50)
#更新画面
pygame.display.update()
if __name__ == '__main__':
#控制界面显示
Start = False
while True:
if Start:
Start = maingame()
else:
Start = gamestart()
游戏界面
标签:snack,text,event,exit,pygame,日记,rect,贪吃 来源: https://blog.csdn.net/qq_36947570/article/details/105667732