美文网首页
Python游戏练习之贪吃蛇示例

Python游戏练习之贪吃蛇示例

作者: 极客匠 | 来源:发表于2020-02-01 17:09 被阅读0次

    这篇文章主要介绍了python实现贪吃蛇小游戏,由键盘控制snake方向,吃食物功能。游戏基于pygame框架制作的

    基础知识

    • 基于python面向对象编程思想
    • pygame知识了解
    • python数组操作

    需求描述

    1. 游戏界面分辨率是640x480,蛇和食物都是由1个或多个20x20像素的正方形块儿(为了方便,下文用点表示20x20像素的正方形块儿)组成,这样共有32x24个点,使用pygame.draw.rect来绘制每一个点。
    2. 初始化时蛇的长度是3,食物是1个点,蛇初始的移动的方向是右,用一个数组代表蛇,数组的每个元素是蛇每个点的坐标,因此数组的第一个坐标是蛇尾,最后一个坐标是蛇头。
    3. 游戏开始后,根据蛇的当前移动方向,将蛇运动方向的前方的那个点append到蛇数组的末位,再把蛇尾去掉,蛇的坐标数组就相当于往前挪了一位。
    4. 如果蛇吃到了食物,即蛇头的坐标等于食物的坐标,那么在第2点中蛇尾就不用去掉,就产生了蛇长度增加的效果;食物被吃掉后,随机在空的位置(不能与蛇的身体重合)再生成一个
    5. 通过PyGame的event监控按键,改变蛇的方向,例如当蛇向右时,下一次改变方向只能向上或者向下。
    6. 当蛇撞上自身或墙壁,游戏结束,蛇头装上自身,那么蛇坐标数组里就有和舌头坐标重复的数据,撞上墙壁则是蛇头坐标超过了边界,都很好判断。
    7. 其他细节:做了个开始的欢迎界面;食物的颜色随机生成。

    代码示例

    import pygame
    import sys, os
    from time import sleep
    from random import choice
    from itertools import product
    from pygame.locals import QUIT, KEYDOWN
    
    
    class Snake(object):
        def __init__(self):
            self.map = {(x, y): 0 for x in range(32) for y in range(24)}
            self.body = [[100, 100], [120, 100], [140, 100]]
            self.head = [140, 100]
            self.moving_direction = 'right'
            self.speed = 10
            self.game_started = False
    
        def check_game_status(self):
            if self.body.count(self.head) > 1:
                return True
            if self.head[0] < 0 or self.head[0] > 620 or self.head[1] < 0 or self.head[1] > 460:
                return True
            return False
    
        def move_head(self):
            moves = {
                'right': (20, 0),
                'up': (0, -20),
                'down': (0, 20),
                'left': (-20, 0)
            }
            step = moves[self.moving_direction]
            self.head[0] += step[0]
            self.head[1] += step[1]
    
    
    class Food(object):
        def __init__(self, pos, colors):
            self.colors = colors
            self.food_postion = [pos[0], pos[1]]
    
    class GameSnake(object):
        def __init__(self, snake):
            self.snake = snake
            self.generate_food()
    
        def generate_food(self):
            self.snake.speed = len(self.snake.body) // 16 if len(self.snake.body) // 16 > 4 else self.snake.speed
            for seg in self.snake.body:
                x, y = seg
                self.snake.map[x // 20, y // 20] = 1
            empty_pos = [pos for pos in self.snake.map.keys() if not self.snake.map[pos]]
            result = choice(empty_pos)
            self.food = Food(([result[0] * 20, result[1] * 20]), list(choice(list(product([0, 64, 128, 192, 255], repeat=3))[1:-1])))
    
        def direction_check(self, moving_direction, change_direction):
            directions = [['up', 'down'], ['left', 'right']]
            if moving_direction in directions[0] and change_direction in directions[1]:
                return change_direction
            elif moving_direction in directions[1] and change_direction in directions[0]:
                return change_direction
            return moving_direction
    
        def run(self):
            key_direction_dict = {
                119: 'up',  # W
                115: 'down',  # S
                97: 'left',  # A
                100: 'right',  # D
                273: 'up',  # UP
                274: 'down',  # DOWN
                276: 'left',  # LEFT
                275: 'right',  # RIGHT
            }
            fps_clock = pygame.time.Clock()
            pygame.init()
            pygame.mixer.init()
            title_font = pygame.font.SysFont('arial', 32)
            welcome_words = title_font.render('Welcome to My Snake', True, (0, 0, 0), (255, 255, 255))
            tips_font = pygame.font.SysFont('arial', 24)
            start_game_words = tips_font.render('Click to Start Game', True, (0, 0, 0), (255, 255, 255))
            close_game_words = tips_font.render('Press ESC to Close', True, (0, 0, 0), (255, 255, 255))
            gameover_words = title_font.render('GAME OVER', True, (205, 92, 92), (255, 255, 255))
            win_words = title_font.render('THE SNAKE IS LONG ENOUGH AND YOU WIN!', True, (0, 0, 205), (255, 255, 255))
            screen = pygame.display.set_mode((640, 480), 0, 32)
            pygame.display.set_caption('My Snake')
            new_direction = self.snake.moving_direction
            while 1:
                for event in pygame.event.get():
                    if event.type == QUIT:
                        exit()
                    elif event.type == KEYDOWN:
                        if event.key == 27:
                            exit()
                        if self.snake.game_started and event.key in key_direction_dict:
                            direction = key_direction_dict[event.key]
                            new_direction = self.direction_check(self.snake.moving_direction, direction)
                    elif (not self.snake.game_started) and event.type == pygame.MOUSEBUTTONDOWN:
                        x, y = pygame.mouse.get_pos()
                        if 213 <= x <= 422 and 304 <= y <= 342:
                            self.snake.game_started = True
                screen.fill((255, 255, 255))
                if self.snake.game_started:
                    self.snake.moving_direction = new_direction  # 在这里赋值,而不是在event事件的循环中赋值,避免按键太快
                    self.snake.move_head()
                    self.snake.body.append(self.snake.head[:])
                    if self.snake.head == self.food.food_postion:
                        self.generate_food()
                    else:
                        self.snake.body.pop(0)
                    for seg in self.snake.body:
                        pygame.draw.rect(screen, [0, 0, 0], [seg[0], seg[1], 20, 20], 0)
                    pygame.draw.rect(screen, self.food.colors, [self.food.food_postion[0], self.food.food_postion[1], 20, 20], 0)
                    if self.snake.check_game_status():
                        screen.blit(gameover_words, (241, 310))
                        pygame.display.update()
                        self.snake = Snake()
                        new_direction = self.snake.moving_direction
                        sleep(3)
                    elif len(self.snake.body) == 512:
                        screen.blit(win_words, (33, 210))
                        pygame.display.update()
                        self.snake = Snake()
                        new_direction = self.snake.moving_direction
                        sleep(3)
                else:
                    screen.blit(welcome_words, (188, 100))
                    screen.blit(start_game_words, (236, 310))
                    screen.blit(close_game_words, (233, 350))
                pygame.display.update()
                fps_clock.tick(self.snake.speed)
    
    
    if __name__ == '__main__':
        gameSanke = GameSnake(Snake())
        gameSanke.run()
    
    

    代码链接:https://github.com/trk-huang/Game-snake.git

    总结:练习python数组操作,pygame的api,训练基于python面向对象编程思想。

    每天多努力那么一点点,积少成多

    相关文章

      网友评论

          本文标题:Python游戏练习之贪吃蛇示例

          本文链接:https://www.haomeiwen.com/subject/mzjxxhtx.html