Angry Doctor(愤怒的医生小游戏)

目录

一、背景介绍:

二、整体流程:

 三、游戏的主要设计:

四、效果展示

五、代码部分 

1.游戏整体部分

2.设计关卡

3.碰撞检测(核心)


项目描述:为落实抗击疫情的精神设计了一款类似于愤怒的小鸟模型的一款小游戏,基于pygame开发。

一、背景介绍:

  1. 疯狂的小鸟作为被大众熟知的一款游戏,在当年许多单机游戏中也是脱颖而出。又正值如今疫情严峻,为了缓解大家一个多月的疫情封寝带来的焦虑以及感受防疫工作者面对新冠病毒的勇敢果决,我们在这一款游戏之上做了一些改编和拓展,做出了一款关于防疫医生与新冠病毒的游戏。游戏的主要流程是通过控制医生实现对病毒的精确打击,要求便是将病毒全部消灭。如果成功消灭会显示相应分数,作为向医生的鼓励以及增加我们防疫的信心

二、整体流程:

Angry Doctor(愤怒的医生小游戏)_第1张图片

 三、游戏的主要设计:

Angry Doctor(愤怒的医生小游戏)_第2张图片

四、效果展示

Angry Doctor(愤怒的医生小游戏)_第3张图片 游戏开始界面

                   

Angry Doctor(愤怒的医生小游戏)_第4张图片 游戏界面
Angry Doctor(愤怒的医生小游戏)_第5张图片 游戏关卡切换界面(体现分数)

Angry Doctor(愤怒的医生小游戏)_第6张图片 游戏失败界面
Angry Doctor(愤怒的医生小游戏)_第7张图片 游戏暂停界面

五、代码部分 

1.游戏整体部分

def start(self):
        # 导入所有游戏精灵
        game_sprites = self.loadlevelmap()  # 载入地图返回游戏精灵内容(字典类型)
        doctors, covids, blocks, walls = game_sprites['doctors'], game_sprites['covids'], game_sprites['blocks'], game_sprites[
            'walls']  # 得到游戏内容
        slingshot = Slingshot(self.screen, 200, self.screen_size[1] - 200, 30, 200)
        doctors[0].load(slingshot)
        score_label = Label(self.screen, 50, 10, 100, 50)
        score_label.addtext(f'SCORE: {self.score}', 25, self.cfg.FONTPATH['Comic_Kings'], (236, 240, 241))
        doctors_remaining_label = Label(self.screen, 120, 50, 100, 50)
        doctors_remaining_label.addtext(f"Doctor REMAINING: {len(doctors)}", 25, self.cfg.FONTPATH['Comic_Kings'],
                                      (236, 240, 241))
        covids_remaining_label = Label(self.screen, 110, 90, 100, 50)
        covids_remaining_label.addtext(f"COVIDs REMAINING: {len(covids)}", 25, self.cfg.FONTPATH['Comic_Kings'],
                                     (236, 240, 241))
        charles_label = Label(self.screen, self.screen_size[0] - 450, self.screen_size[1] - 20, 300, 100)
        charles_label.addtext('Against The Epidemic', 60, self.cfg.FONTPATH['arfmoochikncheez'], (113, 125, 126))
        # 游戏主循环
        clock = pygame.time.Clock()
        blocks_to_remove, covids_to_remove = [], []
        while True:
            # --按键检测
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.quitgame()
                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_q:
                        self.quitgame()
                    elif event.key == pygame.K_r:
                        self.start()
                    elif event.key == pygame.K_p or event.key == pygame.K_ESCAPE:
                        self.pauseinterface()
                elif event.type == pygame.MOUSEBUTTONDOWN:
                    if doctors[0].selected():
                        doctors[0].is_selected = True
                elif event.type == pygame.MOUSEBUTTONUP:
                    if doctors[0].is_selected:
                        doctors[0].is_selected = False
                        doctors[0].start_flying = True

            # --背景颜色填充,绘制四色条的背景
            color = self.cfg.BACKGROUND_COLOR
            for i in range(3):
                color = (color[0] + 5, color[1] + 5, color[2] + 5)
                pygame.draw.rect(self.screen, color, (0, i * 300, self.screen_size[0], 300))
            pygame.draw.rect(self.screen, (77, 86, 86), (0, self.screen_size[1], self.screen_size[0], 50))
            # --判断游戏是否结束,若没有则导入新的医生
            if (not doctors[0].is_loaded) and self.still(covids + doctors + blocks):
                doctors.pop(0)
                if self.status(covids, doctors) == 2:  # 游戏胜利
                    self.score += len(doctors) * 100  # 剩余医生越多,得分越高
                    self.switchlevelinterface()
                elif self.status(covids, doctors) == 1:
                    self.failureinterface()
                doctors[0].load(slingshot)
                doctors[0].start_flying = False
            # --重置医生的位置
            if doctors[0].is_selected:
                doctors[0].reposition(slingshot)
            if hasattr(doctors[0], 'start_flying') and doctors[0].start_flying: #start_flying为后添加属性,得用hasatter判断是否存在属性
                doctors[0].is_loaded = False
            # --弹弓
            slingshot.draw(doctors[0])
            # --判断病毒是否撞上木桩
            for i in range(len(covids)):
                for j in range(len(blocks)):
                    covid_magnitude_1, block_magnitude_1 = covids[i].velocity.magnitude, blocks[j].velocity.magnitude
                    covids[i], blocks[j], is_collision = self.collision(covids[i], blocks[j])
                    covid_magnitude_2, block_magnitude_2 = covids[i].velocity.magnitude, blocks[j].velocity.magnitude
                    if is_collision:
                        if abs(covid_magnitude_2 - covid_magnitude_1) > 2:
                            blocks_to_remove.append(blocks[j])
                            blocks[j].setdestroy()
                        if abs(block_magnitude_2 - block_magnitude_1) > 2:
                            covids_to_remove.append(covids[i])
                            covids[i].setdead()
            # --判断医生是否撞上木桩
            for i in range(len(doctors)):
                if not (doctors[i].is_loaded or doctors[i].velocity.magnitude == 0):
                    for j in range(len(blocks)):
                        doctor_magnitude_1, block_magnitude_1 = doctors[i].velocity.magnitude, blocks[j].velocity.magnitude
                        doctors[i], blocks[j], is_collision = self.collision(doctors[i], blocks[j])
                        doctor_magnitude_2, block_magnitude_2 = doctors[i].velocity.magnitude, blocks[j].velocity.magnitude
                        if is_collision:
                            if abs(doctor_magnitude_1 - doctor_magnitude_2) > 2:
                                if blocks[j] not in blocks_to_remove: #木桩和医生病毒同时相撞避免重复破坏木桩
                                    blocks_to_remove.append(blocks[j])
                                    blocks[j].setdestroy()
            # --判断病毒是否撞上病毒或者病毒撞墙
            for i in range(len(covids)):
                covids[i].move()
                for j in range(i + 1, len(covids)):
                    covid1_magnitude_1, covid2_magnitude_1 = covids[i].velocity.magnitude, covids[j].velocity.magnitude
                    covids[i], covids[j], is_collision = self.collision(covids[i], covids[j])
                    covid1_magnitude_2, covid2_magnitude_2 = covids[i].velocity.magnitude, covids[j].velocity.magnitude
                    if abs(covid1_magnitude_1 - covid1_magnitude_2) > 2:
                        if covids[j] not in covids_to_remove:
                            covids_to_remove.append(covids[j])
                            covids[j].setdead()
                    if abs(covid2_magnitude_1 - covid2_magnitude_2) > 2:
                        if covids[i] not in covids_to_remove:
                            covids_to_remove.append(covids[i])
                            covids[i].setdead()
                for wall in walls: covids[i] = self.collision(covids[i], wall)[0]
                covids[i].draw()
            # --判断医生是否撞到病毒或者医生是否撞到墙
            for i in range(len(doctors)):
                if (not doctors[i].is_loaded) and (doctors[i].velocity.magnitude):
                    doctors[i].move()
                    for j in range(len(covids)):
                        doctor_magnitude_1, covid_magnitude_1 = doctors[i].velocity.magnitude, covids[j].velocity.magnitude
                        doctors[i], covids[j], is_collision = self.collision(doctors[i], covids[j])
                        doctor_magnitude_2, covid_magnitude_2 = doctors[i].velocity.magnitude, covids[j].velocity.magnitude
                        if is_collision:
                            if abs(doctor_magnitude_2 - doctor_magnitude_1) > 2:
                                if covids[j] not in covids_to_remove:
                                    covids_to_remove.append(covids[j])
                                    covids[j].setdead()
                if doctors[i].is_loaded: doctors[i].projectpath()
                for wall in walls: doctors[i] = self.collision(doctors[i], wall)[0]
                doctors[i].draw()
            # --判断木桩是否撞到了木桩或者木桩撞到墙
            for i in range(len(blocks)):
                for j in range(i + 1, len(blocks)):
                    block1_magnitude_1, block2_magnitude_1 = blocks[i].velocity.magnitude, blocks[j].velocity.magnitude
                    blocks[i], blocks[j], is_collision = self.collision(blocks[i], blocks[j])
                    block1_magnitude_2, block2_magnitude_2 = blocks[i].velocity.magnitude, blocks[j].velocity.magnitude
                    if is_collision:
                        if abs(block1_magnitude_2 - block1_magnitude_1) > 2:
                            if blocks[j] not in blocks_to_remove:
                                blocks_to_remove.append(blocks[j])
                                blocks[j].setdestroy()
                        if abs(block2_magnitude_2 - block2_magnitude_1) > 2:
                            if blocks[i] not in blocks_to_remove:
                                blocks_to_remove.append(blocks[i])
                                blocks[i].setdestroy()
                blocks[i].move()
                for wall in walls: blocks[i] = self.collision(blocks[i], wall)[0]
                blocks[i].draw()
            # --墙
            for wall in walls: wall.draw()
            # --显示文字
            score_label.addtext(f'SCORE: {self.score}', 25, self.cfg.FONTPATH['Comic_Kings'], (236, 240, 241))
            score_label.draw()
            doctors_remaining_label.addtext(f"DOCTORS REMAINING: {len(doctors)}", 25, self.cfg.FONTPATH['Comic_Kings'],
                                          (236, 240, 241))
            doctors_remaining_label.draw()
            covids_remaining_label.addtext(f"COVID REMAINING: {len(covids)}", 25, self.cfg.FONTPATH['Comic_Kings'],
                                         (236, 240, 241))
            covids_remaining_label.draw()
            charles_label.draw()
            # --画面刷新
            pygame.display.update()
            clock.tick(self.cfg.FPS)
            # --删除无效的元素
            if self.still(doctors + covids + blocks):
                for covid in covids_to_remove:
                    if covid in covids:
                        covids.remove(covid)
                        self.score += 100
                for block in blocks_to_remove:
                    if block in blocks:
                        blocks.remove(block)
                        self.score += 50
                covids_to_remove = []
                blocks_to_remove = []

另外,游戏的开始游戏界面、游戏的失败界面、游戏暂停界面、游戏关卡切换界面与这里游戏界面中的部分也大同小异,主要包括相关按钮,标题的载入以及对事件(主要是按钮触发)的检测 

2.设计关卡

for i in range(3):
            doctors.append(
                Doctor(screen=self.screen, imagepaths=self.cfg.IMAGEPATHS['doctor'],
                     loc_info=(45 * i, self.screen_size[1] - 40, 20))
            )
        if self.level_pointer == 1:
            covids.append(
                COVID(screen=self.screen, imagepaths=self.cfg.IMAGEPATHS['covid'],
                    loc_info=(1100, self.screen_size[1] - 60, 25))
            )
            covids.append(
                COVID(screen=self.screen, imagepaths=self.cfg.IMAGEPATHS['covid'],
                    loc_info=(1200, self.screen_size[1] - 60, 25))
            )
            walls.append(
                Slab(screen=self.screen, imagepaths=self.cfg.IMAGEPATHS['wall'], x=700, y=250, width=30,
                     height=self.screen_size[1] - 250)
            )

主要通过添加相关元素(包括医生,病毒,障碍[通过木块体现],墙),设置其位置来体现关卡特点,其余关卡也是大同小异

3.碰撞检测(核心)

通过检测物体之间(主要是医生与病毒,医生与障碍,医生与墙,病毒与病毒,病毒与墙,病毒与障碍)图像是否发生重叠来体现是否发生碰撞,若发生碰撞则修改碰撞物体的速度大小与方向,这里体现了病毒医生之间的碰撞,其余碰撞的产生也能通过类似功能实现

 def collision(self, sprite1, sprite2):
        is_collision = False
        elasticity, block_elasticity = 0.8, 0.7
        if sprite1.type in ['covid', 'doctor'] and sprite2.type in ['covid', 'doctor']:   #病毒医生之间的碰撞
            dx, dy = sprite1.loc_info[0] - sprite2.loc_info[0], sprite1.loc_info[1] - sprite2.loc_info[1]
            dist = math.hypot(dx, dy)
            if dist < sprite1.loc_info[2] + sprite2.loc_info[2]:
                tangent = math.atan2(dy, dx)
                angle = 0.5 * math.pi + tangent
                angle1, angle2 = 2 * tangent - sprite1.velocity.angle, 2 * tangent - sprite2.velocity.angle
                magnitude1, magnitude2 = sprite2.velocity.magnitude, sprite1.velocity.magnitude
                sprite1.velocity, sprite2.velocity = VelocityVector(magnitude1, angle1), VelocityVector(magnitude2,
                                                                                                        angle2)
                sprite1.velocity.magnitude *= elasticity
                sprite2.velocity.magnitude *= elasticity
                overlap = 0.5 * (sprite1.loc_info[2] + sprite2.loc_info[2] - dist + 1)
                sprite1.loc_info[0] += math.sin(angle) * overlap
                sprite1.loc_info[1] -= math.cos(angle) * overlap
                sprite2.loc_info[0] -= math.sin(angle) * overlap
                sprite2.loc_info[1] += math.cos(angle) * overlap
                is_collision = True

你可能感兴趣的:(pygame,python,游戏程序)