基于pygame开发的口红挑战升级游戏

北慕城南 提交于 2020-04-06 10:16:15

游戏简介及操作

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()


四、运行并测试

鼠标点击口红命中中间旋转的西瓜,若命中重复位置的口红,则失败,成功即进入下一关

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!