效果图~新鲜出炉
- 开始界面
- 游戏中
- 结束界面
一、pygame模块概览
模块名称 | 功能 |
pygame.cdrom | 访问光驱 |
pygame.cursors | 加载光标 |
pygame.display | 访问显示设备 |
pygame.draw | 绘制形状、线和点 |
pygame.event | 管理事件 |
pygame.font | 使用字体 |
pygame.image | 加载和存储图片 |
pygame.joystick | 使用游戏手柄或类似的东西 |
pygame.key | 读取键盘按键 |
pygame.mixer | 声音 |
pygame.mouse | 鼠标 |
pygame.movie | 播放视频 |
pygame.music | 播放音频 |
pygame.overlay | 访问高级视频叠加 |
pygame | 目前学习的 |
pygame.rect | 管理矩形区域 |
pygame.sndarray | 操作声音数据 |
pygame.sprite | 操作移动图像 |
pygame.surface | 管理图像和屏幕 |
pygame.surfarray | 管理点阵图像数据 |
pygame.time | 管理时间和帧信息 |
pygame.transform | 缩放和移动图像 |
二、核心代码
思路
- 首页面:会涉及图片和文字提示的显示,进入(任意键)或退出(ESC)游戏;
- 游戏页面:主要涉及食物的创建绘制,蛇的移动和显示,蛇是否吃到食物或者是否撞到边界或自身,再者就是音效的实现(背景音乐+gameover音效);
- 结束页面:会涉及图片和文字提示的显示,重来(任意键)或退出(ESC)游戏。
核心代码
- 主函数
def main():
pygame.init()
# 创建Pygame时钟对象,控制每个循环多长时间运行一次。
# 例如:snake_speed_clock(60)代表每秒内循环要运行的 60 次
# 每秒60个循环(或帧)时,每个循环需要1000/60=16.66ms(大约17ms)如果循环中的代码运行时间超过17ms,
# 在clock指出下一次循环时当前循环将无法完成。
snake_speed_clock = pygame.time.Clock()
screen = pygame.display.set_mode((windows_width, windows_height))
screen.fill(white)
pygame.display.set_caption("贪吃蛇~")
show_start_info(screen)
while True:
music()
running_game(screen, snake_speed_clock)
show_end_info(screen)
- 游戏运行代码
def running_game(screen,snake_speed_clock):
start_x = random.randint(3, map_width - 8) #开始位置
start_y = random.randint(3, map_height - 8)
snake_coords = [{'x': start_x, 'y': start_y}, #初始贪吃蛇
{'x': start_x - 1, 'y': start_y},
{'x': start_x - 2, 'y': start_y}]
direction = RIGHT # 开始时向右移动
food = get_random_location() #实物随机位置
while True:
for event in pygame.event.get():
if event.type == QUIT:
terminate()
elif event.type == KEYDOWN:
if (event.key == K_LEFT or event.key == K_a) and direction != RIGHT:
direction = LEFT
elif (event.key == K_RIGHT or event.key == K_d) and direction != LEFT:
direction = RIGHT
elif (event.key == K_UP or event.key == K_w) and direction != DOWN:
direction = UP
elif (event.key == K_DOWN or event.key == K_s) and direction != UP:
direction = DOWN
elif event.key == K_ESCAPE:
terminate()
move_snake(direction, snake_coords) #移动蛇
ret = snake_is_alive(snake_coords)
if not ret:
gameover_music()
break #蛇死了. 游戏结束
snake_is_eat_food(snake_coords, food) #判断蛇是否吃到食物
screen.fill(BG_COLOR)
draw_snake(screen, snake_coords)
draw_food(screen, food)
show_score(screen, len(snake_coords) - 3)
pygame.display.update()
snake_speed_clock.tick(snake_speed) #控制fps
- 食物绘制
def draw_food(screen, food):
x = food['x'] * cell_size
y = food['y'] * cell_size
appleRect = pygame.Rect(x, y, cell_size, cell_size)
pygame.draw.rect(screen, red, appleRect)
- 贪吃蛇绘制
def draw_snake(screen, snake_coords):
for coord in snake_coords:
x = coord['x'] * cell_size
y = coord['y'] * cell_size
wormSegmentRect = pygame.Rect(x,y,cell_size,cell_size)
pygame.draw.rect(screen, dark_blue, wormSegmentRect)
wormInnerSegmentRect = pygame.Rect(x+4,y+4,cell_size - 8, cell_size - 8)
pygame.draw.rect(screen, blue, wormInnerSegmentRect)
- 移动贪吃蛇
def move_snake(direction, snake_coords):
if direction == UP:
newHead = {'x':snake_coords[HEAD]['x'], 'y':snake_coords[HEAD]['y'] - 1}
elif direction == DOWN:
newHead = {'x':snake_coords[HEAD]['x'], 'y':snake_coords[HEAD]['y'] + 1}
elif direction == LEFT:
newHead = {'x':snake_coords[HEAD]['x'] - 1, 'y':snake_coords[HEAD]['y']}
elif direction == RIGHT:
newHead = {'x':snake_coords[HEAD]['x'] + 1, 'y':snake_coords[HEAD]['y']}
snake_coords.insert(0, newHead)
- 判断蛇死没有死
def snake_is_alive(snake_coords):
tag = True
# 头坐标超出地图范围
if(snake_coords[HEAD]['x'] == -1 \
or snake_coords[HEAD]['x'] == map_width \
or snake_coords[HEAD]['y'] == -1 \
or snake_coords[HEAD]['y'] == map_height):
tag = False
# 头坐标等于身体某节坐标
for snake_body in snake_coords[1:]:
if snake_body['x'] == snake_coords[HEAD]['x'] and snake_body['y'] == snake_coords[HEAD]['y']:
tag = False
return tag
- 判断蛇是否吃到食物
def snake_is_eat_food(snake_coords, food):
if(snake_coords[HEAD]['x'] == food['x'] and snake_coords[HEAD]['y'] == food['y']):
## 重新生成食物
food['x'] = random.randint(0, map_width - 1)
food['y'] = random.randint(0, map_height - 1)
else:
# 如果没有吃到实物, 就向前移动, 那么尾部一格删掉
del snake_coords[-1]
- 随机生成食物
def get_random_location():
return {'x':random.randint(0, map_width - 1),'y':random.randint(0, map_height - 1)}
- 开始信息显示
def show_start_info(screen):
# 创建Font字体对象,使用render方法写字
font = pygame.font.Font("simsun.ttc", 40)
tip = font.render('按任意键开始游戏', True,(65,105,255))
# 加载图片
gamestart = pygame.image.load('startlogo.jpg').convert()
# 通过blit方法输出在屏幕上
screen.blit(gamestart,(140, 30))
screen.blit(tip,(240, 550))
## 刷新屏幕
pygame.display.update()
while True: # 监听键盘
for event in pygame.event.get():
if event.type == QUIT:
terminate()
elif event.type == KEYDOWN: # 任意键按下
return
if (event.key == K_ESCAPE): # 若为ESC,则终止程序
terminate()
else:
return
- 声音设置
def music():
pygame.mixer.init()
pygame.mixer.music.load('111.mp3')
pygame.mixer.music.play(1, 0)
def gameover_music():
pygame.mixer.init()
pygame.mixer.music.load('gameover.mp3')
pygame.mixer.music.play(1,0)
- 结束信息显示
def show_end_info(screen):
font = pygame.font.Font("simsun.ttc", 40)
tip = font.render("按ESC退出游戏,按任意键重新开始游戏",True,(65,105,255))
# gamestart = pygame.image.load('gameover.png')
# screen.blit(gamestart,(60, 0))
screen.blit(tip,(80, 300))
pygame.display.update()
while True:
for event in pygame.event.get():
if event.type == QUIT:
terminate()
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
terminate()
else:
return
- 成绩信息显示
def show_score(screen, score):
font = pygame.font.Font("simsun.ttc", 30)
scoreSurf = font.render("得分:%s" % score, True, green)
scoreRect = scoreSurf.get_rect()
scoreRect.topleft = (windows_width - 120, 10)
screen.blit(scoreSurf,scoreRect)
- 程序终止
def terminate():
pygame.quit()
sys.exit()