今天怕p8架构师用154行写个冒险岛,小白都看得懂的语言描述
Posted 编程界的小胖子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了今天怕p8架构师用154行写个冒险岛,小白都看得懂的语言描述相关的知识,希望对你有一定的参考价值。
今天这篇文章可能会有点长,一定要耐心看完,超级有意思的用python只需158行代码就能写成
相比大家小时候玩过一个fc游戏叫冒险岛,不知道大家有没有玩过,还是挺有趣的,有好几个代,本文试着用154行写个简版的冒险岛。
1. 初始化
import pygame
复制代码
初始化
pygame.init()
复制代码
设置宽高
screen = pygame.display.set_mode((800,400))
复制代码
设置标题
pygame.display.set_caption('Runner')
复制代码
设置时钟
clock = pygame.time.Clock()
复制代码
填充颜色
screen.fill((94,129,162))
复制代码
渲染
while True:
# 更新
pygame.display.update()
# 时间开始走,60帧
clock.tick(60)
复制代码
python3 island.py
打开测试下
出现了个问题,鼠标点击会卡死,我们添加事件捕捉
for event in pygame.event.get():
# 这边先pass代码
pass
复制代码
现在执行python3 island.py,点击鼠标就不会卡死
代码整理如下:
import pygame
# 初始化
pygame.init()
# 设置宽高
screen = pygame.display.set_mode((800,400))
# 设置标题
pygame.display.set_caption('Runner')
clock = pygame.time.Clock()
# 填充颜色
screen.fill((94,129,162))
while True:
for event in pygame.event.get():
# 这边先pass代码
pass
# 显示更新
pygame.display.update()
# 时间开始走,60帧
clock.tick(60)
复制代码
2. 主界面
刚才的代码执行了下,发现无法关闭,只能关闭脚本,检测下关闭事件
while True:
for event in pygame.event.get():
# 检测退出
if event.type == pygame.QUIT:
pygame.quit()
exit()
# 显示更新
pygame.display.update()
# 时间开始走,60帧
clock.tick(60)
复制代码
现在可以正常关闭了
我们来添加初始页面,添加游戏状态,默认未启动
game_active = False
复制代码
引入玩家图片
player_stand = pygame.image.load('graphics/player/player_stand.png').convert_alpha()
复制代码
设置放置位置
player_stand_rect = player_stand.get_rect(center = (400,200))
复制代码
渲染出来看下效果
好像缺点啥,加个提示,自定义字体,这边选择的是像素字体
test_font = pygame.font.Font('font/Pixeltype.ttf', 50)
game_message = test_font.render('Press space to run',False,(111,196,169))
game_message_rect = game_message.get_rect(center = (400,330))
复制代码
显示出来
在加个标题
game_name = test_font.render('Huamiao Runner',False,(111,196,169))
game_name_rect = game_name.get_rect(center = (400,80))
复制代码
显示出来
代码整理如下:
import pygame
# 初始化
pygame.init()
# 设置宽高
screen = pygame.display.set_mode((800,400))
# 设置标题
pygame.display.set_caption('Runner')
clock = pygame.time.Clock()
# 舞台填充颜色
screen.fill((94,129,162))
# 游戏状态
game_active = False
# 玩家图标
player_stand = pygame.image.load('graphics/player/player_stand.png').convert_alpha()
player_stand_rect = player_stand.get_rect(center = (400,200))
# 引入像素字体
test_font = pygame.font.Font('font/Pixeltype.ttf', 50)
# 游戏提示
game_message = test_font.render('Press space to run',False,(111,196,169))
game_message_rect = game_message.get_rect(center = (400,330))
# 游戏标题
game_name = test_font.render('Huamiao Runner',False,(111,196,169))
game_name_rect = game_name.get_rect(center = (400,80))
while True:
# 监听事件
for event in pygame.event.get():
# 检测退出
if event.type == pygame.QUIT:
pygame.quit()
exit()
if game_active:
pass
else:
# 显示玩家
screen.blit(player_stand,player_stand_rect)
# 显示游戏提示信息
screen.blit(game_message,game_message_rect)
# 显示游戏名称
screen.blit(game_name,game_name_rect)
# 显示更新
pygame.display.update()
# 时间开始走,60帧
clock.tick(60)
复制代码
3. 开始游戏
实现按空格开始游戏,添加监听
if ~game_active:
# 按下空格开始
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
game_active = True
复制代码
添加开始信息文字
# 游戏开始提示
game_start_message = test_font.render('Game start',False,(111,196,169))
game_start_message_rect = game_start_message.get_rect(center = (400,330))
复制代码
显示开始游戏信息
if game_active:
screen.fill((94,129,162))
screen.blit(game_start_message,game_start_message_rect)
else:
# 显示玩家
screen.blit(player_stand,player_stand_rect)
# 显示游戏提示信息
screen.blit(game_message,game_message_rect)
# 显示游戏名称
screen.blit(game_name,game_name_rect)
# 显示更新
pygame.display.update()
# 时间开始走,60帧
clock.tick(60)
复制代码
执行脚本,python3 island.py
按下空格
这个界面只是测试,我们改为正常的游戏画面,需要有天空和地面,我们来添加下:
# 加载天空图片
sky_surface = pygame.image.load('graphics/Sky.png').convert()
# 加载地面图片
ground_surface = pygame.image.load('graphics/ground.png').convert()
复制代码
把刚才的测试信息改下:
if game_active:
# 绘制天空
screen.blit(sky_surface,(0,0))
# 绘制地面
screen.blit(ground_surface,(0,300))
复制代码
执行脚本,按下空格
gif截图软件小问题,颜色稍微失真,看个效果:
4. 添加玩家
# 玩家
player = pygame.sprite.GroupSingle()
player.add(Player())
复制代码
创建Player类,丰富这个类
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
# 加载两张走路的图片,让走路动起来
player_walk_1 = pygame.image.load('graphics/player/player_walk_1.png').convert_alpha()
player_walk_2 = pygame.image.load('graphics/player/player_walk_2.png').convert_alpha()
# 放在list里面,使用索引切换
self.player_walk = [player_walk_1,player_walk_2]
# 初始化索引
self.player_index = 0
# 玩家走路初始帧
self.image = self.player_walk[self.player_index]
# 设置玩家初始位置,左下角地面上
self.rect = self.image.get_rect(midbottom = (80,300))
复制代码
绘制玩家
# 游戏开始
if game_active:
# code ……
# 绘制玩家
player.draw(screen)
复制代码
看下效果
人物出来了,我们要弄个走路的动画效果,我们需要个监听器:
# 绘制玩家
player.draw(screen)
# 玩家监听器
player.update()
复制代码
在Player类添加动画
def animation_state(self):
self.player_index += 0.1
if self.player_index >= len(self.player_walk):self.player_index = 0
self.image = self.player_walk[int(self.player_index)]
# 监听器
def update(self):
self.animation_state()
复制代码
看下效果
5. 玩家事件监听
监听玩家按了空格,跳起来,并为动作添加音效
# Player类
# 跳跃音效,音量
self.jump_sound = pygame.mixer.Sound('audio/jump.mp3')
self.jump_sound.set_volume(0.5)
# 玩家事件监听
def player_input(self):
keys = pygame.key.get_pressed()
# 玩家按下空格且不是跳跃状态
if keys[pygame.K_SPACE] and self.rect.bottom >= 300:
# 播放跳跃音效
self.jump_sound.play()
复制代码
添加重力计算方法,并监听
# 重力计算
def apply_gravity(self):
self.gravity += 1
self.rect.y += self.gravity
if self.rect.bottom >= 300:
self.rect.bottom = 300
复制代码
动画状态需要改下
# 动画状态
def animation_state(self):
if self.rect.bottom < 300:
self.image = self.player_jump
else:
self.player_index += 0.1
if self.player_index >= len(self.player_walk):self.player_index = 0
self.image = self.player_walk[int(self.player_index)]
复制代码
监听器
# 监听器
def update(self):
self.animation_state()
self.player_input()
self.apply_gravity()
复制代码
看下效果
代码整理如下:
import pygame
# 初始化
pygame.init()
# 设置宽高
screen = pygame.display.set_mode((800,400))
# 设置标题
pygame.display.set_caption('Runner')
clock = pygame.time.Clock()
# 舞台填充颜色
screen.fill((94,129,162))
# 游戏状态
game_active = False
# 玩家图标
player_stand = pygame.image.load('graphics/player/player_stand.png').convert_alpha()
player_stand_rect = player_stand.get_rect(center = (400,200))
# 引入像素字体
test_font = pygame.font.Font('font/Pixeltype.ttf', 50)
# 游戏提示
game_message = test_font.render('Press space to run',False,(111,196,169))
game_message_rect = game_message.get_rect(center = (400,330))
# 游戏标题
game_name = test_font.render('Huamiao Runner',False,(111,196,169))
game_name_rect = game_name.get_rect(center = (400,80))
# 游戏结束提示
game_over_message = test_font.render('Game over',False,(111,196,169))
game_over_message_rect = game_over_message.get_rect(center = (400,330))
# 游戏开始提示
game_start_message = test_font.render('Game start',False,(111,196,169))
game_start_message_rect = game_start_message.get_rect(center = (400,330))
# 加载天空图片
sky_surface = pygame.image.load('graphics/Sky.png').convert()
# 加载地面图片
ground_surface = pygame.image.load('graphics/ground.png').convert()
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
# 加载两张走路的图片,让走路动起来
player_walk_1 = pygame.image.load('graphics/player/player_walk_1.png').convert_alpha()
player_walk_2 = pygame.image.load('graphics/player/player_walk_2.png').convert_alpha()
# 放在list里面
self.player_walk = [player_walk_1,player_walk_2]
self.player_index = 0
# 加载跳起来的图片
self.player_jump = pygame.image.load('graphics/player/jump.png').convert_alpha()
# 玩家走路初始位帧
self.image = self.player_walk[self.player_index]
# 设置初始位置
self.rect = self.image.get_rect(midbottom = (80,300))
# 跳跃音效,音量
self.jump_sound = pygame.mixer.Sound('audio/jump.mp3')
self.jump_sound.set_volume(0.5)
# 玩家事件监听
def player_input(self):
keys = pygame.key.get_pressed()
# 玩家按下空格且不是跳跃状态
if keys[pygame.K_SPACE] and self.rect.bottom >= 300:
# 设置重力
self.gravity = -20
# 播放跳跃音效
self.jump_sound.play()
# 重力计算
def apply_gravity(self):
self.gravity += 1
self.rect.y += self.gravity
if self.rect.bottom >= 300:
self.rect.bottom = 300
# 动画状态
def animation_state(self):
if self.rect.bottom < 300:
self.image = self.player_jump
else:
self.player_index += 0.1
if self.player_index >= len(self.player_walk):self.player_index = 0
self.image = self.player_walk[int(self.player_index)]
# 监听器
def update(self):
self.animation_state()
self.player_input()
self.apply_gravity()
# 玩家
player = pygame.sprite.GroupSingle()
player.add(Player())
while True:
# 监听事件
for event in pygame.event.get():
# 检测退出
if event.type == pygame.QUIT:
pygame.quit()
exit()
if ~game_active:
# 按下空格开始
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
game_active = True
# 游戏开始
if game_active:
# 绘制天空
screen.blit(sky_surface,(0,0))
# 绘制地面
screen.blit(ground_surface,(0,300))
# 绘制玩家
player.draw(screen)
# 玩家监听器
player.update()
else:
# 显示玩家
screen.blit(player_stand,player_stand_rect)
# 显示游戏提示信息
screen.blit(game_message,game_message_rect)
# 显示游戏名称
screen.blit(game_name,game_name_rect)
# 显示更新
pygame.display.update()
# 时间开始走,60帧
clock.tick(60)
复制代码
6. 添加时间及分数
添加全局显示时间方法,这边我们根据玩家能完多久来计算分数,如下:
# 开始时间
start_time = 0
# 显示分数
def display_score():
current_time = int(pygame.time.get_ticks() / 1000) - start_time
score_surf = test_font.render(f'Score: {current_time}',False,(64,64,64))
score_rect = score_surf.get_rect(center = (400,50))
screen.blit(score_surf,score_rect)
return current_time
复制代码
在开始游戏后显示分数
# 分数
score = display_score()
复制代码
分数已经可以正常计算来
改下之前的一个bug,不使用~
while True:
# 监听事件
for event in pygame.event.get():
# 检测退出
if event.type == pygame.QUIT:
pygame.quit()
exit()
if game_active:
pass
else:
# 按下空格开始
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
game_active = True
复制代码
7. 添加障碍物
添加障碍物组
obstacle_group = pygame.sprite.Group()
复制代码
添加障碍物事件
obstacle_timer = pygame.USEREVENT + 1
pygame.time.set_timer(obstacle_timer,1500)
复制代码
添加个蜗牛
# 来只蜗牛,两张图片动起来
snail_frame_1 = pygame.image.load('graphics/snail/snail1.png').convert_alpha()
snail_frame_2 = pygame.image.load('graphics/snail/snail2.png').convert_alpha()
snail_frames = [snail_frame_1, snail_frame_2]
snail_frame_index = 0
# 定义当前帧的图片
snail_surf = snail_frames[snail_frame_index]
复制代码
添加蜗牛事件
snail_animation_timer = pygame.USEREVENT + 2
pygame.time.set_timer(snail_animation_timer,500)
复制代码
添加障碍物类,我们预留个类型,后面会添加不同类型的障碍物
# 障碍物类
class Obstacle(pygame.sprite.Sprite):
def __init__(self,type):
super().__init__()
# 蜗牛的动画
snail_1 = pygame.image.load('graphics/snail/snail1.png').convert_alpha()
snail_2 = pygame.image.load('graphics/snail/snail2.png').convert_alpha()
self.frames = [snail_1,snail_2]
# 高度
y_pos = 300
self.animation_index = 0
self.image = self.frames[self.animation_index]
# 在右侧屏幕生成障碍物
self.rect = self.image.get_rect(midbottom = (randint(900,1100),y_pos))
复制代码
添加障碍物动画
# 动画状态
def animation_state(self):
self.animation_index += 0.1
if self.animation_index >= len(self.frames): self.animation_index = 0
self.image = self.frames[int(self.animation_index)]
复制代码
监听障碍物
# 监听
def update(self):
self.animation_state()
self.rect.x -= 6
self.destroy()
复制代码
销毁障碍物
# 销毁
def destroy(self):
if self.rect.x <= -100:
self.kill()
复制代码
障碍物事件添加到循环中
while True:
# 监听事件
for event in pygame.event.get():
# 检测退出
if event.type == pygame.QUIT:
pygame.quit()
exit()
if game_active:
# 障碍物事件
if event.type == obstacle_timer:
# 设置障碍物概率,蜗牛和苍蝇3:1
obstacle_group.add(Obstacle(choice(['snail'])))
# 蜗牛事件
if event.type == snail_animation_timer:
if snail_frame_index == 0: snail_frame_index = 1
else: snail_frame_index = 0
snail_surf = snail_frames[snail_frame_index]
复制代码
游戏开始的地方添加障碍物渲染
# 游戏开始
if game_active:
# 绘制天空
screen.blit(sky_surface,(0,0))
# 绘制地面
screen.blit(ground_surface,(0,300))
# 分数
score = display_score()
# 绘制玩家
player.draw(screen)
# 玩家监听器
player.update()
# 绘制障碍物
obstacle_group.draw(screen)
obstacle_group.update()
复制代码
看下效果
8. 添加额外的障碍物
# 来只苍蝇,同上
fly_frame1 = pygame.image.load('graphics/fly/fly1.png').convert_alpha()
fly_frame2 = pygame.image.load('graphics/fly/fly2.png').convert_alpha()
fly_frames = [fly_frame1, fly_frame2]
fly_frame_index = 0
fly_surf = fly_frames[fly_frame_index]
复制代码
添加苍蝇事件
# 苍蝇事件
fly_animation_timer = pygame.USEREVENT + 3
pygame.time.set_timer(fly_animation_timer,200)
复制代码
障碍物类改下
# 障碍物类
class Obstacle(pygame.sprite.Sprite):
def __init__(self,type):
super().__init__()
if type == 'fly':
# 苍蝇的动画
fly_1 = pygame.image.load('graphics/fly/fly1.png').convert_alpha()
fly_2 = pygame.image.load('graphics/fly/fly2.png').convert_alpha()
self.frames = [fly_1,fly_2]
# 高度
y_pos = 210
else:
# 蜗牛的动画
snail_1 = pygame.image.load('graphics/snail/snail1.png').convert_alpha()
snail_2 = pygame.image.load('graphics/snail/snail2.png').convert_alpha()
self.frames = [snail_1,snail_2]
# 高度
y_pos = 300
复制代码
在障碍物生成的事件中添加苍蝇,由于我们之前预留了一个chioce
while True:
# 监听事件
for event in pygame.event.get():
# 检测退出
if event.type == pygame.QUIT:
pygame.quit()
exit()
if game_active:
# 障碍物事件
if event.type == obstacle_timer:
# 设置障碍物概率,蜗牛和苍蝇3:1
obstacle_group.add(Obstacle(choice(['snail', 'fly'])))
复制代码
看下效果
代码整理如下:
import pygame
from random import randint,choice
# 初始化
pygame.init()
# 设置宽高
screen = pygame.display.set_mode((800,400))
# 设置标题
pygame.display.set_caption('Runner')
clock = pygame.time.Clock()
# 舞台填充颜色
screen.fill((94,129,162))
# 游戏状态
game_active = False
# 玩家图标
player_stand = pygame.image.load('graphics/player/player_stand.png').convert_alpha()
player_stand_rect = player_stand.get_rect(center = (400,200))
# 引入像素字体
test_font = pygame.font.Font('font/Pixeltype.ttf', 50)
# 游戏提示
game_message = test_font.render('Press space to run',False,(111,196,169))
game_message_rect = game_message.get_rect(center = (400,330))
# 游戏标题
game_name = test_font.render('Huamiao Runner',False,(111,196,169))
game_name_rect = game_name.get_rect(center = (400,80))
# 游戏结束提示
game_over_message = test_font.render('Game over',False,(111,196,169))
game_over_message_rect = game_over_message.get_rect(center = (400,330))
# 游戏开始提示
game_start_message = test_font.render('Game start',False,(111,196,169))
game_start_message_rect = game_start_message.get_rect(center = (400,330))
# 加载天空图片
sky_surface = pygame.image.load('graphics/Sky.png').convert()
# 加载地面图片
ground_surface = pygame.image.load('graphics/ground.png').convert()
# 开始时间
start_time = 0
# 显示分数
def display_score():
current_time = int(pygame.time.get_ticks() / 1000) - start_time
score_surf = test_font.render(f'Score: {current_time}',False,(64,64,64))
score_rect = score_surf.get_rect(center = (400,50))
screen.blit(score_surf,score_rect)
return current_time
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
# 加载两张走路的图片,让走路动起来
player_walk_1 = pygame.image.load('graphics/player/player_walk_1.png').convert_alpha()
player_walk_2 = pygame.image.load('graphics/player/player_walk_2.png').convert_alpha()
# 放在list里面
self.player_walk = [player_walk_1,player_walk_2]
self.player_index = 0
# 加载跳起来的图片
self.player_jump = pygame.image.load('graphics/player/jump.png').convert_alpha()
# 玩家走路初始位帧
self.image = self.player_walk[self.player_index]
# 设置初始位置
self.rect = self.image.get_rect(midbottom = (80,300))
# 跳跃音效,音量
self.jump_sound = pygame.mixer.Sound('audio/jump.mp3')
self.jump_sound.set_volume(0.5)
# 玩家事件监听
def player_input(self):
keys = pygame.key.get_pressed()
# 玩家按下空格且不是跳跃状态
if keys[pygame.K_SPACE] and self.rect.bottom >= 300:
# 设置重力
self.gravity = -20
# 播放跳跃音效
self.jump_sound.play()
# 重力计算
def apply_gravity(self):
self.gravity += 1
self.rect.y += self.gravity
if self.rect.bottom >= 300:
self.rect.bottom = 300
# 动画状态
def animation_state(self):
if self.rect.bottom < 300:
self.image = self.player_jump
else:
self.player_index += 0.1
if self.player_index >= len(self.player_walk):self.player_index = 0
self.image = self.player_walk[int(self.player_index)]
# 监听器
def update(self):
self.animation_state()
self.player_input()
self.apply_gravity()
# 玩家
player = pygame.sprite.GroupSingle()
player.add(Player())
# 障碍物组
obstacle_group = pygame.sprite.Group()
# 障碍物事件
obstacle_timer = pygame.USEREVENT + 1
pygame.time.set_timer(obstacle_timer,1500)
# 蜗牛事件
snail_animation_timer = pygame.USEREVENT + 2
pygame.time.set_timer(snail_animation_timer,500)
# 来只蜗牛,两张图片动起来
snail_frame_1 = pygame.image.load('graphics/snail/snail1.png').convert_alpha()
snail_frame_2 = pygame.image.load('graphics/snail/snail2.png').convert_alpha()
snail_frames = [snail_frame_1, snail_frame_2]
snail_frame_index = 0
# 定义当前帧的图片
snail_surf = snail_frames[snail_frame_index]
# 苍蝇事件
# fly_animation_timer = pygame.USEREVENT + 3
# pygame.time.set_timer(fly_animation_timer,200)
# 障碍物类
class Obstacle(pygame.sprite.Sprite):
def __init__(self,type):
super().__init__()
if type == 'fly':
# 苍蝇的动画
fly_1 = pygame.image.load('graphics/fly/fly1.png').convert_alpha()
fly_2 = pygame.image.load('graphics/fly/fly2.png').convert_alpha()
self.frames = [fly_1,fly_2]
# 高度
y_pos = 210
else:
# 蜗牛的动画
snail_1 = pygame.image.load('graphics/snail/snail1.png').convert_alpha()
snail_2 = pygame.image.load('graphics/snail/snail2.png').convert_alpha()
self.frames = [snail_1,snail_2]
# 高度
y_pos = 300
self.animation_index = 0
self.image = self.frames[self.animation_index]
# 在右侧屏幕生成障碍物
self.rect = self.image.get_rect(midbottom = (randint(900,1100),y_pos))
# 动画状态
def animation_state(self):
self.animation_index += 0.1
if self.animation_index >= len(self.frames): self.animation_index = 0
self.image = self.frames[int(self.animation_index)]
# 监听
def update(self):
self.animation_state()
self.rect.x -= 6
self.destroy()
# 销毁
def destroy(self):
if self.rect.x <= -100:
self.kill()
# 来只苍蝇,同上
fly_frame1 = pygame.image.load('graphics/fly/fly1.png').convert_alpha()
fly_frame2 = pygame.image.load('graphics/fly/fly2.png').convert_alpha()
fly_frames = [fly_frame1, fly_frame2]
fly_frame_index = 0
fly_surf = fly_frames[fly_frame_index]
# 苍蝇事件
fly_animation_timer = pygame.USEREVENT + 3
pygame.time.set_timer(fly_animation_timer,200)
while True:
# 监听事件
for event in pygame.event.get():
# 检测退出
if event.type == pygame.QUIT:
pygame.quit()
exit()
if game_active:
# 障碍物事件
if event.type == obstacle_timer:
# 设置障碍物概率,蜗牛和苍蝇3:1
obstacle_group.add(Obstacle(choice(['snail', 'fly'])))
# 蜗牛事件
if event.type == snail_animation_timer:
if snail_frame_index == 0: snail_frame_index = 1
else: snail_frame_index = 0
snail_surf = snail_frames[snail_frame_index]
# 苍蝇事件
if event.type == fly_animation_timer:
if fly_frame_index == 0: fly_frame_index = 1
else: fly_frame_index = 0
fly_surf = fly_frames[fly_frame_index]
else:
# 按下空格开始
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
game_active = True
# 游戏开始
if game_active:
# 绘制天空
screen.blit(sky_surface,(0,0))
# 绘制地面
screen.blit(ground_surface,(0,300))
# 分数
score = display_score()
# 绘制玩家
player.draw(screen)
# 玩家监听器
player.update()
# 绘制障碍物
obstacle_group.draw(screen)
obstacle_group.update()
else:
# 显示玩家
screen.blit(player_stand,player_stand_rect)
# 显示游戏提示信息
screen.blit(game_message,game_message_rect)
# 显示游戏名称
screen.blit(game_name,game_name_rect)
# 显示更新
pygame.display.update()
# 时间开始走,60帧
clock.tick(60)
复制代码
9. 碰撞检测
添加全局碰撞检测方法
def collision_sprite():
if pygame.sprite.spritecollide(player.sprite,obstacle_group,False):
obstacle_group.empty()
return False
else: return True
复制代码
到开始游戏中注册
# 游戏开始
if game_active:
# 绘制天空
screen.blit(sky_surface,(0,0))
# 绘制地面
screen.blit(ground_surface,(0,300))
# 分数
score = display_score()
# 绘制玩家
player.draw(screen)
# 玩家监听器
player.update()
# 绘制障碍物
obstacle_group.draw(screen)
obstacle_group.update()
# 碰撞检测
game_active = collision_sprite()
复制代码
试试
发现死掉了展示的不符合我们的要求
9. 优化细节
之前我们在这里设置背景
# 初始化
pygame.init()
# 设置宽高
screen = pygame.display.set_mode((800,400))
# 设置标题
pygame.display.set_caption('Runner')
clock = pygame.time.Clock()
# 舞台填充颜色
screen.fill((94,129,162))
复制代码
我们改下,这边去掉,改到:
# 游戏开始
if game_active:
# 绘制天空
screen.blit(sky_surface,(0,0))
# 绘制地面
screen.blit(ground_surface,(0,300))
# 分数
score = display_score()
# 绘制玩家
player.draw(screen)
# 玩家监听器
player.update()
# 绘制障碍物
obstacle_group.draw(screen)
obstacle_group.update()
# 碰撞检测
game_active = collision_sprite()
else:
# 在这里粉刷背景
screen.fill((94,129,162))
# 显示玩家
screen.blit(player_stand,player_stand_rect)
复制代码
再试试
死掉是这个界面,跟初始界面一样,我们要提示分数
全局设置分数
score = 0
复制代码
初始化显示初始界面,死了显示分数
# 游戏开始
if game_active:
# 绘制天空
screen.blit(sky_surface,(0,0))
# 绘制地面
screen.blit(ground_surface,(0,300))
# 分数
score = display_score()
# 绘制玩家
player.draw(screen)
# 玩家监听器
player.update()
# 绘制障碍物
obstacle_group.draw(screen)
obstacle_group.update()
# 碰撞检测
game_active = collision_sprite()
else:
# 在这里粉刷背景
screen.fill((94,129,162))
# 显示玩家
screen.blit(player_stand,player_stand_rect)
# 显示游戏提示信息
# screen.blit(game_message,game_message_rect)
# 显示游戏名称
screen.blit(game_name,game_name_rect)
# 显示分数
score_message = test_font.render(f'Your score: {score}',False,(111,196,169))
score_message_rect = score_message.get_rect(center = (400,330))
screen.blit(game_name,game_name_rect)
# 根据分值显示不同提示语
if score == 0: screen.blit(game_message,game_message_rect)
else: screen.blit(score_message,score_message_rect)
复制代码
试试,死了是预期的界面
又活捉个bug,死了再开始分数没有重新计算
判断按下空格开始的时候,重置下计时,我们的分数会自动设置为0,因为我们的分数是基于时间计算的:
# 按下空格开始
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
game_active = True
start_time = int(pygame.time.get_ticks() / 1000)
复制代码
顺便加个游戏背景音乐
# 加载背景音乐
bg_music = pygame.mixer.Sound('audio/music.wav')
# 背景音乐播放,无限循环播放
bg_music.play(loops = -1)
复制代码
最后试试
有背景音乐还是挺带劲的
完美,收工。
所有代码如下:
import pygame
from random import randint,choice
# 初始化
pygame.init()
# 设置宽高
screen = pygame.display.set_mode((800,400))
# 设置标题
pygame.display.set_caption('Runner')
clock = pygame.time.Clock()
# 舞台填充颜色
# screen.fill((94,129,162))
# 游戏状态
game_active = False
# 玩家图标
player_stand = pygame.image.load('graphics/player/player_stand.png').convert_alpha()
player_stand_rect = player_stand.get_rect(center = (400,200))
# 引入像素字体
test_font = pygame.font.Font('font/Pixeltype.ttf', 50)
# 游戏提示
game_message = test_font.render('Press space to run',False,(111,196,169))
game_message_rect = game_message.get_rect(center = (400,330))
# 游戏标题
game_name = test_font.render('Huamiao Runner',False,(111,196,169))
game_name_rect = game_name.get_rect(center = (400,80))
# 游戏结束提示
game_over_message = test_font.render('Game over',False,(111,196,169))
game_over_message_rect = game_over_message.get_rect(center = (400,330))
# 游戏开始提示
game_start_message = test_font.render('Game start',False,(111,196,169))
game_start_message_rect = game_start_message.get_rect(center = (400,330))
# 加载天空图片
sky_surface = pygame.image.load('graphics/Sky.png').convert()
# 加载地面图片
ground_surface = pygame.image.load('graphics/ground.png').convert()
# 开始时间
start_time = 0
# 显示分数
def display_score():
current_time = int(pygame.time.get_ticks() / 1000) - start_time
score_surf = test_font.render(f'Score: {current_time}',False,(64,64,64))
score_rect = score_surf.get_rect(center = (400,50))
screen.blit(score_surf,score_rect)
return current_time
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
# 加载两张走路的图片,让走路动起来
player_walk_1 = pygame.image.load('graphics/player/player_walk_1.png').convert_alpha()
player_walk_2 = pygame.image.load('graphics/player/player_walk_2.png').convert_alpha()
# 放在list里面
self.player_walk = [player_walk_1,player_walk_2]
self.player_index = 0
# 加载跳起来的图片
self.player_jump = pygame.image.load('graphics/player/jump.png').convert_alpha()
# 玩家走路初始位帧
self.image = self.player_walk[self.player_index]
# 设置初始位置
self.rect = self.image.get_rect(midbottom = (80,300))
# 跳跃音效,音量
self.jump_sound = pygame.mixer.Sound('audio/jump.mp3')
self.jump_sound.set_volume(0.5)
# 玩家事件监听
def player_input(self):
keys = pygame.key.get_pressed()
# 玩家按下空格且不是跳跃状态
if keys[pygame.K_SPACE] and self.rect.bottom >= 300:
# 设置重力
self.gravity = -20
# 播放跳跃音效
self.jump_sound.play()
# 重力计算
def apply_gravity(self):
self.gravity += 1
self.rect.y += self.gravity
if self.rect.bottom >= 300:
self.rect.bottom = 300
# 动画状态
def animation_state(self):
if self.rect.bottom < 300:
self.image = self.player_jump
else:
self.player_index += 0.1
if self.player_index >= len(self.player_walk):self.player_index = 0
self.image = self.player_walk[int(self.player_index)]
# 监听器
def update(self):
self.animation_state()
self.player_input()
self.apply_gravity()
# 玩家
player = pygame.sprite.GroupSingle()
player.add(Player())
# 障碍物组
obstacle_group = pygame.sprite.Group()
# 障碍物事件
obstacle_timer = pygame.USEREVENT + 1
pygame.time.set_timer(obstacle_timer,1500)
# 蜗牛事件
snail_animation_timer = pygame.USEREVENT + 2
pygame.time.set_timer(snail_animation_timer,500)
# 来只蜗牛,两张图片动起来
snail_frame_1 = pygame.image.load('graphics/snail/snail1.png').convert_alpha()
snail_frame_2 = pygame.image.load('graphics/snail/snail2.png').convert_alpha()
snail_frames = [snail_frame_1, snail_frame_2]
snail_frame_index = 0
# 定义当前帧的图片
snail_surf = snail_frames[snail_frame_index]
# 障碍物类
class Obstacle(pygame.sprite.Sprite):
def __init__(self,type):
super().__init__()
if type == 'fly':
# 苍蝇的动画
fly_1 = pygame.image.load('graphics/fly/fly1.png').convert_alpha()
fly_2 = pygame.image.load('graphics/fly/fly2.png').convert_alpha()
self.frames = [fly_1,fly_2]
# 高度
y_pos = 210
else:
# 蜗牛的动画
snail_1 = pygame.image.load('graphics/snail/snail1.png').convert_alpha()
snail_2 = pygame.image.load('graphics/snail/snail2.png').convert_alpha()
self.frames = [snail_1,snail_2]
# 高度
y_pos = 300
self.animation_index = 0
self.image = self.frames[self.animation_index]
# 在右侧屏幕生成障碍物
self.rect = self.image.get_rect(midbottom = (randint(900,1100),y_pos))
# 动画状态
def animation_state(self):
self.animation_index += 0.1
if self.animation_index >= len(self.frames): self.animation_index = 0
self.image = self.frames[int(self.animation_index)]
# 监听
def update(self):
self.animation_state()
self.rect.x -= 6
self.destroy()
# 销毁
def destroy(self):
if self.rect.x <= -100:
self.kill()
# 来只苍蝇,同上
fly_frame1 = pygame.image.load('graphics/fly/fly1.png').convert_alpha()
fly_frame2 = pygame.image.load('graphics/fly/fly2.png').convert_alpha()
fly_frames = [fly_frame1, fly_frame2]
fly_frame_index = 0
fly_surf = fly_frames[fly_frame_index]
# 苍蝇事件
fly_animation_timer = pygame.USEREVENT + 3
pygame.time.set_timer(fly_animation_timer,200)
def collision_sprite():
if pygame.sprite.spritecollide(player.sprite,obstacle_group,False):
obstacle_group.empty()
return False
else: return True
score = 0
# 加载背景音乐
bg_music = pygame.mixer.Sound('audio/music.wav')
# 背景音乐播放,无限循环播放
bg_music.play(loops = -1)
while True:
# 监听事件
for event in pygame.event.get():
# 检测退出
if event.type == pygame.QUIT:
pygame.quit()
exit()
if game_active:
# 障碍物事件
if event.type == obstacle_timer:
# 设置障碍物概率,蜗牛和苍蝇3:1
obstacle_group.add(Obstacle(choice(['snail', 'fly'])))
# 蜗牛事件
if event.type == snail_animation_timer:
if snail_frame_index == 0: snail_frame_index = 1
else: snail_frame_index = 0
snail_surf = snail_frames[snail_frame_index]
# 苍蝇事件
if event.type == fly_animation_timer:
if fly_frame_index == 0: fly_frame_index = 1
else: fly_frame_index = 0
fly_surf = fly_frames[fly_frame_index]
else:
# 按下空格开始
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
game_active = True
start_time = int(pygame.time.get_ticks() / 1000)
# 游戏开始
if game_active:
# 绘制天空
screen.blit(sky_surface,(0,0))
# 绘制地面
screen.blit(ground_surface,(0,300))
# 分数
score = display_score()
# 绘制玩家
player.draw(screen)
# 玩家监听器
player.update()
# 绘制障碍物
obstacle_group.draw(screen)
obstacle_group.update()
# 碰撞检测
game_active = collision_sprite()
else:
# 在这里粉刷背景
screen.fill((94,129,162))
# 显示玩家
screen.blit(player_stand,player_stand_rect)
# 显示游戏提示信息
# screen.blit(game_message,game_message_rect)
# 显示游戏名称
screen.blit(game_name,game_name_rect)
# 显示分数
score_message = test_font.render(f'Your score: {score}',False,(111,196,169))
score_message_rect = score_message.get_rect(center = (400,330))
screen.blit(game_name,game_name_rect)
# 根据分值显示不同提示语
if score == 0: screen.blit(game_message,game_message_rect)
else: screen.blit(score_message,score_message_rect)
# 显示更新
pygame.display.update()
# 时间开始走,60帧
clock.tick(60)
复制代码
删除注释以及空行,完整代码如下,总共154行:
import pygame
from random import randint,choice
pygame.init()
screen = pygame.display.set_mode((800,400))
pygame.display.set_caption('Runner')
clock = pygame.time.Clock()
game_active = False
player_stand = pygame.image.load('graphics/player/player_stand.png').convert_alpha()
player_stand_rect = player_stand.get_rect(center = (400,200))
test_font = pygame.font.Font('font/Pixeltype.ttf', 50)
game_message = test_font.render('Press space to run',False,(111,196,169))
game_message_rect = game_message.get_rect(center = (400,330))
game_name = test_font.render('Huamiao Runner',False,(111,196,169))
game_name_rect = game_name.get_rect(center = (400,80))
game_over_message = test_font.render('Game over',False,(111,196,169))
game_over_message_rect = game_over_message.get_rect(center = (400,330))
game_start_message = test_font.render('Game start',False,(111,196,169))
game_start_message_rect = game_start_message.get_rect(center = (400,330))
sky_surface = pygame.image.load('graphics/Sky.png').convert()
ground_surface = pygame.image.load('graphics/ground.png').convert()
start_time = 0
def display_score():
current_time = int(pygame.time.get_ticks() / 1000) - start_time
score_surf = test_font.render(f'Score: {current_time}',False,(64,64,64))
score_rect = score_surf.get_rect(center = (400,50))
screen.blit(score_surf,score_rect)
return current_time
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
player_walk_1 = pygame.image.load('graphics/player/player_walk_1.png').convert_alpha()
player_walk_2 = pygame.image.load('graphics/player/player_walk_2.png').convert_alpha()
self.player_walk = [player_walk_1,player_walk_2]
self.player_index = 0
self.player_jump = pygame.image.load('graphics/player/jump.png').convert_alpha()
self.image = self.player_walk[self.player_index]
self.rect = self.image.get_rect(midbottom = (80,300))
self.jump_sound = pygame.mixer.Sound('audio/jump.mp3')
self.jump_sound.set_volume(0.5)
def player_input(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE] and self.rect.bottom >= 300:
self.gravity = -20
self.jump_sound.play()
def apply_gravity(self):
self.gravity += 1
self.rect.y += self.gravity
if self.rect.bottom >= 300:
self.rect.bottom = 300
def animation_state(self):
if self.rect.bottom < 300:
self.image = self.player_jump
else:
self.player_index += 0.1
if self.player_index >= len(self.player_walk):self.player_index = 0
self.image = self.player_walk[int(self.player_index)]
def update(self):
self.animation_state()
self.player_input()
self.apply_gravity()
player = pygame.sprite.GroupSingle()
player.add(Player())
obstacle_group = pygame.sprite.Group()
obstacle_timer = pygame.USEREVENT + 1
pygame.time.set_timer(obstacle_timer,1500)
snail_animation_timer = pygame.USEREVENT + 2
pygame.time.set_timer(snail_animation_timer,500)
snail_frame_1 = pygame.image.load('graphics/snail/snail1.png').convert_alpha()
snail_frame_2 = pygame.image.load('graphics/snail/snail2.png').convert_alpha()
snail_frames = [snail_frame_1, snail_frame_2]
snail_frame_index = 0
snail_surf = snail_frames[snail_frame_index]
class Obstacle(pygame.sprite.Sprite):
def __init__(self,type):
super().__init__()
if type == 'fly':
fly_1 = pygame.image.load('graphics/fly/fly1.png').convert_alpha()
fly_2 = pygame.image.load('graphics/fly/fly2.png').convert_alpha()
self.frames = [fly_1,fly_2]
y_pos = 210
else:
snail_1 = pygame.image.load('graphics/snail/snail1.png').convert_alpha()
snail_2 = pygame.image.load('graphics/snail/snail2.png').convert_alpha()
self.frames = [snail_1,snail_2]
y_pos = 300
self.animation_index = 0
self.image = self.frames[self.animation_index]
self.rect = self.image.get_rect(midbottom = (randint(900,1100),y_pos))
def animation_state(self):
self.animation_index += 0.1
if self.animation_index >= len(self.frames): self.animation_index = 0
self.image = self.frames[int(self.animation_index)]
def update(self):
self.animation_state()
self.rect.x -= 6
self.destroy()
def destroy(self):
if self.rect.x <= -100:
self.kill()
fly_frame1 = pygame.image.load('graphics/fly/fly1.png').convert_alpha()
fly_frame2 = pygame.image.load('graphics/fly/fly2.png').convert_alpha()
fly_frames = [fly_frame1, fly_frame2]
fly_frame_index = 0
fly_surf = fly_frames[fly_frame_index]
fly_animation_timer = pygame.USEREVENT + 3
pygame.time.set_timer(fly_animation_timer,200)
def collision_sprite():
if pygame.sprite.spritecollide(player.sprite,obstacle_group,False):
obstacle_group.empty()
return False
else: return True
score = 0
bg_music = pygame.mixer.Sound('audio/music.wav')
bg_music.play(loops = -1)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if game_active:
if event.type == obstacle_timer:
obstacle_group.add(Obstacle(choice(['snail', 'fly'])))
if event.type == snail_animation_timer:
if snail_frame_index == 0: snail_frame_index = 1
else: snail_frame_index = 0
snail_surf = snail_frames[snail_frame_index]
if event.type == fly_animation_timer:
if fly_frame_index == 0: fly_frame_index = 1
else: fly_frame_index = 0
fly_surf = fly_frames[fly_frame_index]
else:
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
game_active = True
start_time = int(pygame.time.get_ticks() / 1000)
if game_active:
screen.blit(sky_surface,(0,0))
screen.blit(ground_surface,(0,300))
score = display_score()
player.draw(screen)
player.update()
obstacle_group.draw(screen)
obstacle_group.update()
game_active = collision_sprite()
else:
screen.fill((94,129,162))
screen.blit(player_stand,player_stand_rect)
screen.blit(game_name,game_name_rect)
score_message = test_font.render(f'Your score: {score}',False,(111,196,169))
score_message_rect = score_message.get_rect(center = (400,330))
screen.blit(game_name,game_name_rect)
if score == 0: screen.blit(game_message,game_message_rect)
else: screen.blit(score_message,score_message_rect)
pygame.display.update()
clock.tick(60)
喜欢小胖子的记得三连哦~
今天这篇文章可能有点长但是会让你们受益匪浅的哦~
以上是关于今天怕p8架构师用154行写个冒险岛,小白都看得懂的语言描述的主要内容,如果未能解决你的问题,请参考以下文章
hdu 1024 Max Sum Plus Plus 小白都可以看得懂的解析