游戏简介及操作:
1.游戏分为五关,每关限时60秒。
2.游戏每关难度递增。
3.口红命中一个,增加10分。
4.口红命中重复位置即为失败。
开发工具:Pycharm
游戏截图:
游戏制作步骤
一、准备素材
搜集素材以及字体
二、游戏初始设置
1.设置游戏屏幕大小,游戏界面标题
SCREEN_WIDTH = 480
SCREEN_HEIGHT = 800
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
# 游戏界面标题
pygame.display.set_caption('口红挑战')
image_dir = 'image/lipstick/'
ttf_dir = 'ttf/'
index_background = pygame.image.load(image_dir+'index_background.jpg')
index_background = pygame.transform.scale(index_background, (SCREEN_WIDTH, SCREEN_HEIGHT))
lipstick_head = pygame.image.load(image_dir+'lipstick_head.png')
lipstick_head = pygame.transform.scale(lipstick_head, (400, 100))
game_begin = pygame.image.load(image_dir+'game_begin.png')
game_begin = pygame.transform.scale(game_begin, (400, 200))
process_background = pygame.image.load(image_dir+'process_background.jpg')
process_background = pygame.transform.scale(process_background, (SCREEN_WIDTH, SCREEN_HEIGHT))
fail_image = pygame.image.load(image_dir+'fail.png')
fail_image = pygame.transform.scale(fail_image, (400, 164))
success_image = pygame.image.load(image_dir+'success.png')
success_image = pygame.transform.scale(success_image, (400, 164))
man_image = pygame.image.load(image_dir+'manImg.jpg')
man_image = pygame.transform.scale(man_image, (65, 65))
2.60 个 0-59,绘制圆的图片
# 60 个 0-59
circle_img = pygame.image.load(image_dir+'circle.png')
circle_pos = [120, 200]
# 圆的图片
circle_rect = pygame.Rect(0, 0, 240, 240)
# 口红
lipstick_img = pygame.image.load(image_dir + 'lipstick_zhijia.png')
# 下一关
next_game_img = pygame.image.load(image_dir + '下一关.png')
# 剩余口红
lipstick_remain = pygame.transform.scale(lipstick_img, (lipstick_img.get_width()//2, lipstick_img.get_height()//2))
lipstick_remain = pygame.transform.rotate(lipstick_remain, -140)
lipstick_pos = [220, 660]
lipstick_group = pygame.sprite.Group()
lipstick_hit_group =pygame.sprite.Group()
3.游戏循环帧率设置,旋转速度 度数越大,旋转的却快
# 游戏循环帧率设置
clock = pygame.time.Clock()
# 旋转速度 度数越大,旋转的却快
ROLL_SPEED = 6
4.设置口红数量,当前关
# 口红数量
LIPSTICK_COUNT = 6
# 当前关
CURRENT_INDEX = 1
5.创建口红类
class Lipstick(pygame.sprite.Sprite):
def __init__(self, init_img, init_pos):
pygame.sprite.Sprite.__init__(self)
self.image = init_img
self.rect = self.image.get_rect()
self.rect.topleft = init_pos
self.rect.top = self.rect.top-140
self.speed = 30
self.degrees = 0
self.roll_speed = ROLL_SPEED
self.is_hit = False
self.is_rotate = True
def move(self):
self.rect.top -= self.speed
if self.rect.top < circle.rect.bottom:
self.rect.top = circle.rect.bottom-55
def auto_move(self):
self.degrees = self.degrees + self.roll_speed
if self.degrees >= 360:
self.degrees = 0
angle_ = 360 - self.degrees # 旋转角度
x = CENTER[0] + (RADIUS + 35) * math.cos(math.pi * (angle_ - 90) / 180) # 圆上一点横坐标
y = CENTER[1] - (RADIUS + 35) * math.sin(math.pi * (angle_ - 90) / 180) # 圆上一点纵坐标
center = (x, y)
self.rect = pygame.transform.rotate(self.image, angle_).get_rect()
self.rect.center = center
screen.blit(pygame.transform.rotate(self.image, angle_), self.rect)
6.创建转盘类
class Circle(pygame.sprite.Sprite):
def __init__(self, init_img, init_rect, init_pos):
pygame.sprite.Sprite.__init__(self)
self.image = init_img # 图片
self.rect = init_rect # 初始化图片所在的矩形
self.rect.topleft = init_pos # 初始化矩形的左上角坐标
self.speed = ROLL_SPEED # 初始化速度,这里是一个确定的值
self.is_hit = False # 玩家是否被击中
self.degrees = 0
def roll(self):
self.degrees = self.degrees+self.speed
if self.degrees >= 180:
self.degrees = 0
angle_ = 180 - self.degrees # 旋转角度
self.rect = pygame.transform.rotate(self.image, angle_).get_rect()
self.rect.center = (240, 320)
screen.blit(pygame.transform.rotate(self.image, angle_), self.rect)
7.创建按钮类
class Button(object):
def __init__(self, image, position):
self.image = image
self.position = position
def is_click(self):
point_x, point_y = pygame.mouse.get_pos()
x, y = self.position
w, h = self.image.get_size()
in_x = x < point_x < x + w
in_y = y < point_y < y + h
return in_x and in_y
def render(self):
return self.is_click()
begin_button = Button(game_begin, (55, 500))
lipstick_button = Button(lipstick_img, (220, 640))
next_game_button = Button(next_game_img, (140, SCREEN_HEIGHT//2))
is_index = True
is_begin = False
8.定义游戏得分、游戏时间,自定义计时事件
# 定义游戏得分
score = 0
# 定义游戏时间
game_time = 60
# 自定义计时事件
COUNT = pygame.USEREVENT + 1
CLICK = pygame.USEREVENT + 2
circle = None
9.判断游戏循环退出的参数,是否生成支架,是否挑战成功
# 判断游戏循环退出的参数
running = True
# 是否生成支架
is_produce = False
produce_count = 0
direction = pygame.math.Vector2(0, 1)
CENTER = (240, 320)
RADIUS = 120
# 是否挑战成功
is_success = False
is_next_game = False
10.定义下一关,口红数量和时间
def draw_next_game():
screen.blit(process_background, (0, 0))
screen.blit(man_image, (50, 30))
screen.blit(success_image, (40, 80))
score_font = pygame.font.Font(ttf_dir + '楷体GB2312.ttf', 36)
score_text = score_font.render('得分:' + str(score), True, (128, 128, 128))
score_text_rect = score_text.get_rect()
score_text_rect.topleft = [180, 320]
screen.blit(score_text, score_text_rect)
screen.blit(next_game_button.image, next_game_button.position)
pygame.display.update()
# 绘制口红数量
def draw_lipstick_count():
score_font = pygame.font.Font(ttf_dir + '楷体GB2312.ttf', 25)
score_text = score_font.render('数量:' + str(LIPSTICK_COUNT-len(lipstick_hit_group)), True, (255, 0, 0))
score_text_rect = score_text.get_rect()
score_text_rect.topleft = [SCREEN_WIDTH//10+50, SCREEN_HEIGHT*2//3+30]
screen.blit(score_text, score_text_rect)
screen.blit(lipstick_remain, [SCREEN_WIDTH//10, SCREEN_HEIGHT*2//3])
# 绘制时间
def draw_time():
time_font = pygame.font.Font(ttf_dir + '楷体GB2312.ttf', 36)
time_text = time_font.render(str('时间:') + str(game_time), True, (128, 128, 128))
current_font = pygame.font.Font(ttf_dir + '楷体GB2312.ttf', 30)
current_text = current_font.render(str('第') + str(CURRENT_INDEX)+'关', True, (0, 0, 255))
time_text_rect = time_text.get_rect()
time_text_rect.topleft = [190, 30]
current_text_rect = current_text.get_rect()
current_text_rect.topleft = [360, 32]
screen.blit(time_text, time_text_rect)
screen.blit(current_text, current_text_rect)
三、设置游戏主循环
1.控制游戏最大帧率为60,首页展示, 绘制背景,中心点坐标,屏幕填充,绘制背景和头像,时间
while running:
# 控制游戏最大帧率为60
clock.tick(60)
# 首页展示
if is_index:
# 绘制背景
screen.blit(index_background, (0, 0))
screen.blit(lipstick_head, (40, 50))
screen.blit(game_begin, (55, 500))
pygame.display.flip()
# 游戏开始
if is_begin:
direction.rotate_ip(6) # By 4 degrees.
# 中心点坐标
ball_pos = [int(i) for i in CENTER + direction * (RADIUS + 50)]
# 屏幕填充
screen.fill((0, 0, 0))
# 绘制背景和头像
screen.blit(process_background, (0, 0))
screen.blit(man_image, (25, 15))
# 绘制时间
draw_time()
2.口红按钮,击中的位置集
# 口红按钮
screen.blit(lipstick_button.image, lipstick_button.position)
# 击中的位置集
degrees_list = []
for lip in lipstick_hit_group:
degrees_list.append(lip.degrees)
3.支架,显示口红列表
# 支架
for lip in lipstick_group:
# 支架移动
lip.move()
# # 是否击中
if pygame.sprite.collide_rect(lip, circle):
# 移除生成group
lipstick_group.remove(lip)
lip.is_hit = True
# 判断是不是击中点是否重复
if 0 in degrees_list:
running = False
break
else:
score += 10
# 添加到击中group
lipstick_hit_group.add(lip)
# 显示口红列表
lipstick_group.draw(screen)
for lip in lipstick_hit_group:
lip.auto_move()
4.绘制得分、口红数量
# 绘制得分
score_font = pygame.font.Font(None, 36)
score_text = score_font.render(str(score), True, (128, 128, 128))
score_text_rect = score_text.get_rect()
score_text_rect.topleft = [100, 40]
screen.blit(score_text, score_text_rect)
# 绘制口红数量 放在这里有讲究
draw_lipstick_count()
# 圆
if circle is None:
circle = Circle(circle_img, circle_rect, circle_pos)
5.更换图片索引使有动画效果
circle.roll()
roll_frequency += 2
if roll_frequency >= 60:
roll_frequency = 0
pygame.display.update()
6.检测 KEYDOWN 事件: KEYDOWN 是 pygame.locals 中定义的常量,pygame.locals文件开始已经导入
(如果按下 Esc 那么主循环终止
检测 QUIT : 如果 QUIT, 终止主循环
每隔1秒发送一次自定义事件
重新设定时间
设置速度 是之前的1.5倍)
for event in pygame.event.get():
# 检测 KEYDOWN 事件: KEYDOWN 是 pygame.locals 中定义的常量,pygame.locals文件开始已经导入
if event.type == pygame.KEYDOWN:
# 如果按下 Esc 那么主循环终止
if event.key == pygame.K_ESCAPE:
running = False
# 检测 QUIT : 如果 QUIT, 终止主循环
elif event.type == pygame.QUIT:
running = False
pygame.quit()
exit()
elif event.type == pygame.MOUSEBUTTONDOWN and is_index:
point_x, point_y = pygame.mouse.get_pos()
is_begin = begin_button.render()
if is_begin:
is_index = False
# 每隔1秒发送一次自定义事件
pygame.time.set_timer(COUNT, 1000)
elif event.type == pygame.MOUSEBUTTONDOWN:
if lipstick_button.render() and is_begin:
lipstick = Lipstick(lipstick_img, lipstick_pos)
lipstick_group.add(lipstick)
if is_next_game and next_game_button.render():
is_begin = True
# 重新设定时间
game_time = 60
# 设置速度 是之前的1.5倍
ROLL_SPEED = ROLL_SPEED * 1.5
CURRENT_INDEX += 1
LIPSTICK_COUNT += 2
circle = None
elif event.type == COUNT:
if game_time > 0:
game_time -= 1
7.时间到游戏结束,判断是否挑战成功、口红数量是否全部点击完成
if game_time <= 0:
# 时间到游戏结束
running = False
# 判断是否挑战成功
if CURRENT_INDEX == 3 and len(lipstick_hit_group) == LIPSTICK_COUNT:
# 稍微停顿一下
time.sleep(0.3)
is_success = True
running = False
# 判断口红数量是否全部点击完成
if len(lipstick_hit_group) == LIPSTICK_COUNT:
# 稍微停顿一下
time.sleep(0.3)
is_begin = False
is_next_game = True
draw_next_game()
for lip in lipstick_hit_group:
lipstick_hit_group.remove(lip)
print('-----over------')
# screen.fill((0, 0, 0))
screen.blit(process_background, (0, 0))
screen.blit(man_image, (50, 30))
if is_success:
screen.blit(success_image, (40, 80))
else:
screen.blit(fail_image, (40, 80))
8.绘制得分,显示得分并处理游戏退出
score_font = pygame.font.Font(ttf_dir+'楷体GB2312.ttf', 36)
score_text = score_font.render('得分:'+str(score), True, (128, 128, 128))
score_text_rect = score_text.get_rect()
score_text_rect.topleft = [180, 320]
screen.blit(score_text, score_text_rect)
# 显示得分并处理游戏退出
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
pygame.display.update()
四、运行并测试
鼠标点击口红命中中间旋转的西瓜,若命中重复位置的口红,则失败,成功即进入下一关
来源:oschina
链接:https://my.oschina.net/u/4460615/blog/3221432