温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Python中怎么用Pygame实现打砖块小游戏

发布时间:2022-02-21 14:48:10 来源:亿速云 阅读:131 作者:iii 栏目:开发技术

这篇文章主要介绍“Python中怎么用Pygame实现打砖块小游戏”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Python中怎么用Pygame实现打砖块小游戏”文章能帮助大家解决问题。

    一、准备中

    1)游戏规则:

    把所有砖块都清除后,还能继续进入下一轮挑战

    初始化每个玩家2次机会,打完所有砖块儿即可胜利,否则失败游戏不过关!

    (关卡素材、背景音乐等比较少也不展示了需要的主页源码基地见哈)

    2)环境安装

    本文用到的环境:Python3、Pycharm、Pygame模块以及部分自带。

    环境安装:pip install -i https://pypi.douban.com/simple/ +模块名

    二、开始敲代码

    1)配置文件

    import os
     
    '''游戏界面一些数值'''
    SCREENWIDTH = 640
    SCREENHEIGHT = 480
    BRICKWIDTH = 10
    BRICKHEIGHT = 10
    PADDLEWIDTH = 60
    PADDLEHEIGHT = 12
    BALLRADIUS = 8
    '''游戏素材路径'''
    FONTPATH = os.path.join(os.getcwd(), 'resources/font/font.TTF')
    HITSOUNDPATH = os.path.join(os.getcwd(), 'resources/audios/hit.wav')
    BGMPATH = os.path.join(os.getcwd(), 'resources/audios/bgm.mp3')
    LEVELROOTPATH = os.path.join(os.getcwd(), 'resources/levels')
    LEVELPATHS = [os.path.join(LEVELROOTPATH, '%s.level' % str(i+1)) for i in range(len(os.listdir(LEVELROOTPATH)))]
    '''一些颜色'''
    BLACK = (0, 0, 0)
    WHITE = (255, 255, 255)
    PINK = (212, 149, 174) 
    PURPLE = (168, 152, 191)
    YELLOW = (245, 237, 162)
    BLUE  = (51, 170, 230)
    AQUA = (182, 225, 225)

    2)定义一些类

    import random
    import pygame
     
     
    '''板子'''
    class Paddle(pygame.sprite.Sprite):
        def __init__(self, x, y, width, height, SCREENWIDTH, SCREENHEIGHT, **kwargs):
            pygame.sprite.Sprite.__init__(self)
            self.init_state = [x, y, width, height]
            self.rect = pygame.Rect(x, y, width, height)
            self.base_speed = 10
            self.SCREENWIDTH = SCREENWIDTH
            self.SCREENHEIGHT = SCREENHEIGHT
        '''移动板子'''
        def move(self, direction):
            if direction == 'left':
                self.rect.left = max(0, self.rect.left-self.base_speed)
            elif direction == 'right':
                self.rect.right = min(self.SCREENWIDTH, self.rect.right+self.base_speed)
            else:
                raise ValueError('Paddle.move.direction unsupport %s...' % direction)
            return True
        '''绑定到屏幕上'''
        def draw(self, screen, color):
            pygame.draw.rect(screen, color, self.rect)
            return True
        '''重置'''
        def reset(self):
            self.rect = pygame.Rect(self.init_state[0], self.init_state[1], self.init_state[2], self.init_state[3])
            return True
     
     
    '''球'''
    class Ball(pygame.sprite.Sprite):
        def __init__(self, x, y, radius, SCREENWIDTH, SCREENHEIGHT, **kwargs):
            pygame.sprite.Sprite.__init__(self)
            self.init_state = [x, y, radius*2, radius*2]
            self.rect = pygame.Rect(x, y, radius*2, radius*2)
            self.base_speed = [5, 5]
            self.direction = [random.choice([1, -1]), -1]
            self.radius = radius
            self.SCREENWIDTH = SCREENWIDTH
            self.SCREENHEIGHT = SCREENHEIGHT
        '''移动球'''
        def move(self):
            self.rect.left += self.direction[0] * self.base_speed[0]
            self.rect.top += self.direction[1] * self.base_speed[1]
            if self.rect.left <= 0:
                self.rect.left = 0
                self.direction[0] = -self.direction[0]
            elif self.rect.right >= self.SCREENWIDTH:
                self.rect.right = self.SCREENWIDTH
                self.direction[0] = -self.direction[0]
            if self.rect.top <= 0:
                self.rect.top = 0
                self.direction[1] = -self.direction[1]
            elif self.rect.bottom >= self.SCREENHEIGHT:
                return False
            return True
        '''改变运动速度和方向(与拍相撞时)'''
        def change(self):
            self.base_speed = [random.choice([4, 5, 6]), random.choice([4, 5, 6])]
            self.direction = [random.choice([1, -1]), -1]
            return True
        '''绑定到屏幕上'''
        def draw(self, screen, color):
            pygame.draw.circle(screen, color, (self.rect.left+self.radius, self.rect.top+self.radius), self.radius)
            return True
        '''重置'''
        def reset(self):
            self.rect = pygame.Rect(self.init_state[0], self.init_state[1], self.init_state[2], self.init_state[3])
            return True
     
     
    '''砖块'''
    class Brick(pygame.sprite.Sprite):
        def __init__(self, x, y, width, height, **kwargs):
            pygame.sprite.Sprite.__init__(self)
            self.init_state = [x, y, width, height]
            self.rect = pygame.Rect(x, y, width, height)
        '''绑定到屏幕上'''
        def draw(self, screen, color):
            pygame.draw.rect(screen, color, self.rect)
            return True
        '''重置'''
        def reset(self):
            self.rect = pygame.Rect(self.init_state[0], self.init_state[1], self.init_state[2], self.init_state[3])
            return True

    3)定义开始、结束界面

     '''开始界面'''
        def __startInterface(self):
            clock = pygame.time.Clock()
            while True:
                for event in pygame.event.get():
                    if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
                        pygame.quit()
                        sys.exit(-1)
                    if event.type == pygame.KEYDOWN and event.key == pygame.K_RETURN:
                        return
                self.screen.fill(self.cfg.AQUA)
                text1 = 'Press <Enter> to start the game'
                text2 = 'Press <Esc> to quit the game'
                text_render1 = self.font_big.render(text1, False, self.cfg.BLUE)
                text_render2 = self.font_big.render(text2, False, self.cfg.BLUE)
                self.screen.blit(text_render1, ((self.cfg.SCREENWIDTH-text_render1.get_rect().width)//2, (self.cfg.SCREENHEIGHT-text_render1.get_rect().height)//4))
                self.screen.blit(text_render2, ((self.cfg.SCREENWIDTH-text_render2.get_rect().width)//2, (self.cfg.SCREENHEIGHT-text_render2.get_rect().height)//2))
                pygame.display.flip()
                clock.tick(30)
        '''结束界面'''
        def __endInterface(self, is_win):
            if is_win:
                text1 = 'Congratulations! You win!'
            else:
                text1 = 'Game Over! You fail!'
            text2 = 'Press <R> to restart the game'
            text3 = 'Press <Esc> to quit the game.'
            clock = pygame.time.Clock()
            while True:
                for event in pygame.event.get():
                    if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
                        pygame.quit()
                        sys.exit(-1)
                    if event.type == pygame.KEYDOWN and event.key == pygame.K_r:
                        return
                self.screen.fill(self.cfg.AQUA)
                text_render1 = self.font_big.render(text1, False, self.cfg.BLUE)
                text_render2 = self.font_big.render(text2, False, self.cfg.BLUE)
                text_render3 = self.font_big.render(text3, False, self.cfg.BLUE)
                self.screen.blit(text_render1, ((self.cfg.SCREENWIDTH-text_render1.get_rect().width)//2, (self.cfg.SCREENHEIGHT-text_render1.get_rect().height)//4))
                self.screen.blit(text_render2, ((self.cfg.SCREENWIDTH-text_render2.get_rect().width)//2, (self.cfg.SCREENHEIGHT-text_render2.get_rect().height)//2))
                self.screen.blit(text_render3, ((self.cfg.SCREENWIDTH-text_render3.get_rect().width)//2, (self.cfg.SCREENHEIGHT-text_render2.get_rect().height)//1.5))
                pygame.display.flip()
                clock.tick(30)

    4)定义游戏

    '''打砖块游戏'''
    class breakoutClone():
        def __init__(self, cfg, **kwargs):
            pygame.init()
            pygame.display.set_caption('Breakout clone ')
            pygame.mixer.init()
            self.screen = pygame.display.set_mode((cfg.SCREENWIDTH, cfg.SCREENHEIGHT))
            self.font_small = pygame.font.Font(cfg.FONTPATH, 20)
            self.font_big = pygame.font.Font(cfg.FONTPATH, 30)
            self.hit_sound = pygame.mixer.Sound(cfg.HITSOUNDPATH)
            pygame.mixer.music.load(cfg.BGMPATH)
            pygame.mixer.music.play(-1, 0.0)
            self.cfg = cfg
        '''运行游戏'''
        def run(self):
            while True:
                self.__startInterface()
                for idx, levelpath in enumerate(self.cfg.LEVELPATHS):
                    state = self.__runLevel(levelpath)
                    if idx == len(self.cfg.LEVELPATHS)-1:
                        break
                    if state == 'win':
                        self.__nextLevel()
                    else:
                        break
                if state == 'fail':
                    self.__endInterface(False)
                else:
                    self.__endInterface(True)
        '''运行某关卡'''
        def __runLevel(self, levelpath):
            score = 0
            num_lives = 2
            # running: 游戏正在进行, fail: 游戏失败, win: 游戏成功.
            state = 'running'
            paddle = Paddle((self.cfg.SCREENWIDTH-self.cfg.PADDLEWIDTH)/2, self.cfg.SCREENHEIGHT-self.cfg.PADDLEHEIGHT-10, self.cfg.PADDLEWIDTH, self.cfg.PADDLEHEIGHT, self.cfg.SCREENWIDTH, self.cfg.SCREENHEIGHT)
            ball = Ball(paddle.rect.centerx-self.cfg.BALLRADIUS, paddle.rect.top-self.cfg.BALLRADIUS*2, self.cfg.BALLRADIUS, self.cfg.SCREENWIDTH, self.cfg.SCREENHEIGHT)
            brick_sprites = pygame.sprite.Group()
            brick_positions = loadLevel(levelpath)
            for bp in brick_positions:
                brick_sprites.add(Brick(bp[0]*self.cfg.BRICKWIDTH, bp[1]*self.cfg.BRICKHEIGHT, self.cfg.BRICKWIDTH, self.cfg.BRICKHEIGHT))
            clock = pygame.time.Clock()
            while True:
                if state != 'running':
                    return state
                for event in pygame.event.get():
                    if event.type == pygame.QUIT:
                        pygame.quit()
                        sys.exit(-1)
                keys_pressed = pygame.key.get_pressed()
                if keys_pressed[pygame.K_LEFT]:
                    paddle.move('left')
                elif keys_pressed[pygame.K_RIGHT]:
                    paddle.move('right')
                self.screen.fill(self.cfg.AQUA)
                is_alive = ball.move()
                # 判断有没有接住球
                if not is_alive:
                    ball.reset()
                    paddle.reset()
                    num_lives -= 1
                    if num_lives == 0:
                        state = 'fail'
                # 球和砖块碰撞检测
                num_bricks = pygame.sprite.spritecollide(ball, brick_sprites, True)
                score += len(num_bricks)
                # 球和拍碰撞检测
                if pygame.sprite.collide_rect(ball, paddle):
                    ball.change()
                # 判断砖块是否已经打完
                if len(brick_sprites) == 0:
                    state = 'win'
                # 将游戏精灵绑定到屏幕
                paddle.draw(self.screen, self.cfg.PURPLE)
                ball.draw(self.screen, self.cfg.WHITE)
                for brick in brick_sprites:
                    brick.draw(self.screen, self.cfg.YELLOW)
                text_render = self.font_small.render('SCORE: %s, LIVES: %s' % (score, num_lives), False, self.cfg.BLUE)
                self.screen.blit(text_render, (10, 10))
                pygame.display.flip()
                clock.tick(50)
        '''关卡切换'''
        def __nextLevel(self):
            clock = pygame.time.Clock()
            while True:
                for event in pygame.event.get():
                    if event.type == pygame.QUIT:
                        pygame.quit()
                        sys.exit(-1)
                    if event.type == pygame.KEYDOWN and event.key == pygame.K_RETURN:
                        return
                self.screen.fill(self.cfg.AQUA)
                text = 'Press <Enter> to enter the next level'
                text_render = self.font_big.render(text, False, self.cfg.BLUE)
                self.screen.blit(text_render, ((self.cfg.SCREENWIDTH-text_render.get_rect().width)//2, (self.cfg.SCREENHEIGHT-text_render.get_rect().height)//3))
                pygame.display.flip()
                clock.tick(30)

    5)主函数与运行界面

    import cfg
    from modules import breakoutClone
     
    '''主函数'''
    def main():
        game = breakoutClone(cfg)
        game.run()
     
    '''run'''
    if __name__ == '__main__':
        main()

    三、效果展示

    1)视频效果展示&mdash;&mdash;

    视频链接

    带你回忆经典:原生Python开发一款打砖块儿小游戏~

    2)截图效果展示&mdash;&mdash;

    游戏开始界面&mdash;&mdash;

    Python中怎么用Pygame实现打砖块小游戏

    运行界面&mdash;&mdash;

    Python中怎么用Pygame实现打砖块小游戏

    关于“Python中怎么用Pygame实现打砖块小游戏”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注亿速云行业资讯频道,小编每天都会为大家更新不同的知识点。

    向AI问一下细节

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

    AI