The beautiful interface effect of python elimination music [complete source code + detailed process]

The effect is like this ↓ ↓ ↓

1. Environmental requirements

windows system, python3.6+ pip21+

Development environment build address

Let's learn pygame together. 30 cases of game development (opening words)-environment construction + game effect display

安装游戏依赖模块 pip install pygame

2. Introduction to the game

Everyone should have played it or watched it. This fancy little game

It is very simple to implement with python's pygame.

Today, I will take you all to implement this fancy little game with Python.

Three, complete development process

1. The main structure of the project

First of all, first organize the main structure of the project. In fact, if you look at the main structure, it is basically clear.

modules:相关定义的Python类位置——game.py:主模块 res:存放引用到的图片、音频等等——audios:音频资源——imgs:图片资源——fonts:字体 cfg.py:为主配置文件 xxls.py:主程序文件 requirements.txt:需要引入的python依赖包

2. Detailed configuration

cfg.py

In the configuration file, you need to introduce the os module and configure the screen size to open the game.

'''主配置文件'''import os '''屏幕设置大小'''SCREENSIZE = (700, 700)'''元素尺寸'''NUMGRID = 8GRIDSIZE = 64XMARGIN = (SCREENSIZE[0] - GRIDSIZE * NUMGRID) // 2YMARGIN = (SCREENSIZE[1] - GRIDSIZE * NUMGRID) // 2'''获取根目录'''ROOTDIR = os.getcwd()'''FPS'''FPS = 30

3. Load all the graphics

game.py: part one

Put the whole project under a whole game.py module, and disassemble this code file for interpretation.

Puzzle sprite class: First obtain the path of the square sprite from the configuration file and load it into the game.

Define the function of move() to move the module. This move is relatively simple. Between the modules, only the adjacent ones can move with each other.

'''Function:    主游戏'''import sysimport timeimport randomimport pygame  '''拼图精灵类'''class pacerSprite(pygame.sprite.Sprite):    def __init__(self, img_path, size, position, downlen, **kwargs):        pygame.sprite.Sprite.__init__(self)        self.image = pygame.image.load(img_path)        self.image = pygame.transform.smoothscale(self.image, size)        self.rect = self.image.get_rect()        self.rect.left, self.rect.top = position        self.downlen = downlen        self.target_x = position[0]        self.target_y = position[1] + downlen        self.type = img_path.split('/')[-1].split('.')[0]        self.fixed = False        self.speed_x = 9        self.speed_y = 9        self.direction = 'down'    def move(self):                #下移        if self.direction == 'down':            self.rect.top = min(self.target_y, self.rect.top+self.speed_y)            if self.target_y == self.rect.top:                self.fixed = True                #上移        elif self.direction == 'up':            self.rect.top = max(self.target_y, self.rect.top-self.speed_y)            if self.target_y == self.rect.top:                self.fixed = True                #左移        elif self.direction == 'left':            self.rect.left = max(self.target_x, self.rect.left-self.speed_x)            if self.target_x == self.rect.left:                self.fixed = True                #右移        elif self.direction == 'right':            self.rect.left = min(self.target_x, self.rect.left+self.speed_x)            if self.target_x == self.rect.left:                self.fixed = True    '''获取当前坐标'''    def getPosition(self):        return self.rect.left, self.rect.top    '''设置星星坐标'''    def setPosition(self, position):        self.rect.left, self.rect.top = position

4. Randomly generate initial layout, adjacent elimination, automatic fall

game.py part 2

Set the title of the main window of the game, and set the main method of starting the game.

'''主游戏类'''class pacerGame():    def __init__(self, screen, sounds, font, pacer_imgs, cfg, **kwargs):        self.info = 'pacer'        self.screen = screen        self.sounds = sounds        self.font = font        self.pacer_imgs = pacer_imgs        self.cfg = cfg        self.reset()    '''开始游戏'''    def start(self):        clock = pygame.time.Clock()        # 遍历整个游戏界面更新位置        overall_moving = True        # 指定某些对象个体更新位置        individual_moving = False        # 定义一些必要的变量        pacer_selected_xy = None        pacer_selected_xy2 = None        swap_again = False        add_score = 0        add_score_showtimes = 10        time_pre = int(time.time())        # 游戏主循环        while True:            for event in pygame.event.get():                if event.type == pygame.QUIT or (event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE):                    pygame.quit()                    sys.exit()                elif event.type == pygame.MOUSEBUTTONUP:                    if (not overall_moving) and (not individual_moving) and (not add_score):                        position = pygame.mouse.get_pos()                        if pacer_selected_xy is None:                            pacer_selected_xy = self.checkSelected(position)                        else:                            pacer_selected_xy2 = self.checkSelected(position)                            if pacer_selected_xy2:                                if self.swappacer(pacer_selected_xy, pacer_selected_xy2):                                    individual_moving = True                                    swap_again = False                                else:                                    pacer_selected_xy = None            if overall_moving:                overall_moving = not self.droppacers(0, 0)                # 移动一次可能可以拼出多个3连块                if not overall_moving:                    res_match = self.isMatch()                    add_score = self.removeMatched(res_match)                    if add_score > 0:                        overall_moving = True            if individual_moving:                pacer1 = self.getpacerByPos(*pacer_selected_xy)                pacer2 = self.getpacerByPos(*pacer_selected_xy2)                pacer1.move()                pacer2.move()                if pacer1.fixed and pacer2.fixed:                    res_match = self.isMatch()                    if res_match[0] == 0 and not swap_again:                        swap_again = True                        self.swappacer(pacer_selected_xy, pacer_selected_xy2)                        self.sounds['mismatch'].play()                    else:                        add_score = self.removeMatched(res_match)                        overall_moving = True                        individual_moving = False                        pacer_selected_xy = None                        pacer_selected_xy2 = None            self.screen.fill((135, 206, 235))            self.drawGrids()            self.pacers_group.draw(self.screen)            if pacer_selected_xy:                self.drawBlock(self.getpacerByPos(*pacer_selected_xy).rect)            if add_score:                if add_score_showtimes == 10:                    random.choice(self.sounds['match']).play()                self.drawAddScore(add_score)                add_score_showtimes -= 1                if add_score_showtimes < 1:                    add_score_showtimes = 10                    add_score = 0            self.remaining_time -= (int(time.time()) - time_pre)            time_pre = int(time.time())            self.showRemainingTime()            self.drawScore()            if self.remaining_time <= 0:                return self.score            pygame.display.update()            clock.tick(self.cfg.FPS)

5. Randomly initialize the content of the main picture of Xiaoxiaole.

game.py part three

Detailed comments are written in the code. Everyone must watch it again, don’t run, just ignore it.

    '''初始化'''    def reset(self):        # 随机生成各个块(即初始化游戏地图各个元素)        while True:            self.all_pacers = []            self.pacers_group = pygame.sprite.Group()            for x in range(self.cfg.NUMGRID):                self.all_pacers.append([])                for y in range(self.cfg.NUMGRID):                    pacer = pacerSprite(img_path=random.choice(self.pacer_imgs), size=(self.cfg.GRIDSIZE, self.cfg.GRIDSIZE), position=[self.cfg.XMARGIN+x*self.cfg.GRIDSIZE, self.cfg.YMARGIN+y*self.cfg.GRIDSIZE-self.cfg.NUMGRID*self.cfg.GRIDSIZE], downlen=self.cfg.NUMGRID*self.cfg.GRIDSIZE)                    self.all_pacers[x].append(pacer)                    self.pacers_group.add(pacer)            if self.isMatch()[0] == 0:                break        # 得分        self.score = 0        # 拼出一个的奖励        self.reward = 10        # 时间        self.remaining_time = 300    '''显示剩余时间'''    def showRemainingTime(self):        remaining_time_render = self.font.render('CountDown: %ss' % str(self.remaining_time), 1, (85, 65, 0))        rect = remaining_time_render.get_rect()        rect.left, rect.top = (self.cfg.SCREENSIZE[0]-201, 6)        self.screen.blit(remaining_time_render, rect)    '''显示得分'''    def drawScore(self):        score_render = self.font.render('SCORE:'+str(self.score), 1, (85, 65, 0))        rect = score_render.get_rect()        rect.left, rect.top = (10, 6)        self.screen.blit(score_render, rect)    '''显示加分'''    def drawAddScore(self, add_score):        score_render = self.font.render('+'+str(add_score), 1, (255, 100, 100))        rect = score_render.get_rect()        rect.left, rect.top = (250, 250)        self.screen.blit(score_render, rect)    '''生成新的拼图块'''    def generateNewpacers(self, res_match):        if res_match[0] == 1:            start = res_match[2]            while start > -2:                for each in [res_match[1], res_match[1]+1, res_match[1]+2]:                    pacer = self.getpacerByPos(*[each, start])                    if start == res_match[2]:                        self.pacers_group.remove(pacer)                        self.all_pacers[each][start] = None                    elif start >= 0:                        pacer.target_y += self.cfg.GRIDSIZE                        pacer.fixed = False                        pacer.direction = 'down'                        self.all_pacers[each][start+1] = pacer                    else:                        pacer = pacerSprite(img_path=random.choice(self.pacer_imgs), size=(self.cfg.GRIDSIZE, self.cfg.GRIDSIZE), position=[self.cfg.XMARGIN+each*self.cfg.GRIDSIZE, self.cfg.YMARGIN-self.cfg.GRIDSIZE], downlen=self.cfg.GRIDSIZE)                        self.pacers_group.add(pacer)                        self.all_pacers[each][start+1] = pacer                start -= 1        elif res_match[0] == 2:            start = res_match[2]            while start > -4:                if start == res_match[2]:                    for each in range(0, 3):                        pacer = self.getpacerByPos(*[res_match[1], start+each])                        self.pacers_group.remove(pacer)                        self.all_pacers[res_match[1]][start+each] = None                elif start >= 0:                    pacer = self.getpacerByPos(*[res_match[1], start])                    pacer.target_y += self.cfg.GRIDSIZE * 3                    pacer.fixed = False                    pacer.direction = 'down'                    self.all_pacers[res_match[1]][start+3] = pacer                else:                    pacer = pacerSprite(img_path=random.choice(self.pacer_imgs), size=(self.cfg.GRIDSIZE, self.cfg.GRIDSIZE), position=[self.cfg.XMARGIN+res_match[1]*self.cfg.GRIDSIZE, self.cfg.YMARGIN+start*self.cfg.GRIDSIZE], downlen=self.cfg.GRIDSIZE*3)                    self.pacers_group.add(pacer)                    self.all_pacers[res_match[1]][start+3] = pacer                start -= 1    '''移除匹配的pacer'''    def removeMatched(self, res_match):        if res_match[0] > 0:            self.generateNewpacers(res_match)            self.score += self.reward            return self.reward        return 0    '''游戏界面的网格绘制'''    def drawGrids(self):        for x in range(self.cfg.NUMGRID):            for y in range(self.cfg.NUMGRID):                rect = pygame.Rect((self.cfg.XMARGIN+x*self.cfg.GRIDSIZE, self.cfg.YMARGIN+y*self.cfg.GRIDSIZE, self.cfg.GRIDSIZE, self.cfg.GRIDSIZE))                self.drawBlock(rect, color=(0, 0, 255), size=1)    '''画矩形block框'''    def drawBlock(self, block, color=(255, 0, 255), size=4):        pygame.draw.rect(self.screen, color, block, size)    '''下落特效'''    def droppacers(self, x, y):        if not self.getpacerByPos(x, y).fixed:            self.getpacerByPos(x, y).move()        if x < self.cfg.NUMGRID - 1:            x += 1            return self.droppacers(x, y)        elif y < self.cfg.NUMGRID - 1:            x = 0            y += 1            return self.droppacers(x, y)        else:            return self.isFull()    '''是否每个位置都有拼图块了'''    def isFull(self):        for x in range(self.cfg.NUMGRID):            for y in range(self.cfg.NUMGRID):                if not self.getpacerByPos(x, y).fixed:                    return False        return True    '''检查有无拼图块被选中'''    def checkSelected(self, position):        for x in range(self.cfg.NUMGRID):            for y in range(self.cfg.NUMGRID):                if self.getpacerByPos(x, y).rect.collidepoint(*position):                    return [x, y]        return None    '''是否有连续一样的三个块(无--返回0/水平--返回1/竖直--返回2)'''    def isMatch(self):        for x in range(self.cfg.NUMGRID):            for y in range(self.cfg.NUMGRID):                if x + 2 < self.cfg.NUMGRID:                    if self.getpacerByPos(x, y).type == self.getpacerByPos(x+1, y).type == self.getpacerByPos(x+2, y).type:                        return [1, x, y]                if y + 2 < self.cfg.NUMGRID:                    if self.getpacerByPos(x, y).type == self.getpacerByPos(x, y+1).type == self.getpacerByPos(x, y+2).type:                        return [2, x, y]        return [0, x, y]    '''根据坐标获取对应位置的拼图对象'''    def getpacerByPos(self, x, y):        return self.all_pacers[x][y]    '''交换拼图'''    def swappacer(self, pacer1_pos, pacer2_pos):        margin = pacer1_pos[0] - pacer2_pos[0] + pacer1_pos[1] - pacer2_pos[1]        if abs(margin) != 1:            return False        pacer1 = self.getpacerByPos(*pacer1_pos)        pacer2 = self.getpacerByPos(*pacer2_pos)        if pacer1_pos[0] - pacer2_pos[0] == 1:            pacer1.direction = 'left'            pacer2.direction = 'right'        elif pacer1_pos[0] - pacer2_pos[0] == -1:            pacer2.direction = 'left'            pacer1.direction = 'right'        elif pacer1_pos[1] - pacer2_pos[1] == 1:            pacer1.direction = 'up'            pacer2.direction = 'down'        elif pacer1_pos[1] - pacer2_pos[1] == -1:            pacer2.direction = 'up'            pacer1.direction = 'down'        pacer1.target_x = pacer2.rect.left        pacer1.target_y = pacer2.rect.top        pacer1.fixed = False        pacer2.target_x = pacer1.rect.left        pacer2.target_y = pacer1.rect.top        pacer2.fixed = False        self.all_pacers[pacer2_pos[0]][pacer2_pos[1]] = pacer1        self.all_pacers[pacer1_pos[0]][pacer1_pos[1]] = pacer2        return True    '''信息显示'''    def __repr__(self):        return self.info

Including game background audio, pictures and font design

res main resource directory
audios: Load game background music
fonts: Scoreboard related fonts
imgs: Here are the graphics of our various small stars, which is the key. If this fails to load,
There will be no graphics in our Xiaoxiaole

6. Start the main program

xxls.py

In the main program, by reading the configuration file, import project resources: including pictures, audio, etc., and import all our modules from our modules.

'''Function:    消消乐'''import osimport sysimport cfgimport pygamefrom modules import *  '''主程序'''def main():    pygame.init()    screen = pygame.display.set_mode(cfg.SCREENSIZE)    pygame.display.set_caption('hacklex')    # 加载背景音乐    pygame.mixer.init()    pygame.mixer.music.load(os.path.join(cfg.ROOTDIR, "res/audios/bg.mp3"))    pygame.mixer.music.set_volume(0.6)    pygame.mixer.music.play(-1)    # 加载音效    sounds = {}    sounds['mismatch'] = pygame.mixer.Sound(os.path.join(cfg.ROOTDIR, 'res/audios/badswap.wav'))    sounds['match'] = []    for i in range(6):        sounds['match'].append(pygame.mixer.Sound(os.path.join(cfg.ROOTDIR, 'res/audios/match%s.wav' % i)))     # 字体显示    font = pygame.font.Font(os.path.join(cfg.ROOTDIR, 'res/font/font.TTF'), 25)    # 星星    pacer_imgs = []    for i in range(1, 8):        pacer_imgs.append(os.path.join(cfg.ROOTDIR, 'res/imgs/pacer%s.png' % i))    # 循环    game = pacerGame(screen, sounds, font, pacer_imgs, cfg)    while True:        score = game.start()        flag = False        # 给出选择,玩家选择重玩或者退出        while True:            for event in pygame.event.get():                if event.type == pygame.QUIT or (event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE):                    pygame.quit()                    sys.exit()                elif event.type == pygame.KEYUP and event.key == pygame.K_r:                    flag = True            if flag:                break            screen.fill((136, 207, 236))            text0 = 'Final score: %s' % score            text1 = 'Press <R> to restart the game.'            text2 = 'Press <Esc> to quit the game.'            y = 150            for idx, text in enumerate([text0, text1, text2]):                text_render = font.render(text, 1, (85, 65, 0))                rect = text_render.get_rect()                if idx == 0:                    rect.left, rect.top = (223, y)                elif idx == 1:                    rect.left, rect.top = (133.5, y)                else:                    rect.left, rect.top = (126.5, y)                y += 99                screen.blit(text_render, rect)            pygame.display.update()        game.reset()  '''游戏运行'''if __name__ == '__main__':    main()

4. How to start the game?

1. Use the development tool IDE to start

If the environment of the development tool IDE

For example: VScode, sublimeText, notepad+

What is pycharm configured for the Python environment

You can run the game directly in the tool.

2. Command line start

As shown below

Python actual combat

[Python actual combat] ex-girlfriend’s wedding, python cracked the WIFI at the wedding site and changed the name to

[Python actual combat] The encrypted "520 Happy.pdf" sent by my ex-girlfriend, after I cracked it with python, I found

[Python actual combat] Last night, I used python to take a selfie with my sister P next door, and then found ...

[Python actual combat] Girlfriend works overtime in the middle of the night and sends a selfie. Python boyfriend discovers the amazing secret with 30 lines of code

[Python actual combat] python you TM is too skinny-only 30 lines of code can record every move of the keyboard

[ Python actual combat] Forgot the password of the goddess album, I only wrote 20 lines of code in Python~~~

pygame series articles [subscribe to the column, get the complete source code]

Let's learn pygame together. 30 cases of game development (2)-tower defense game

Let’s learn pygame together. 30 cases of game development (4)-Tetris game

Penetration testing practical column

Windows AD/Exchange Management Column

Linux high-performance server construction

PowerShell Automation Column

CSDN official learning recommendation ↓ ↓ ↓

The Python full-stack knowledge graph produced by CSDN is too strong, and I recommend it to everyone!