Python_Weekend_14 贪吃蛇

本文主要是写的一个贪吃蛇小游戏
目前还没有计分效果

from abc import ABCMeta,abstractmethod
from random import randint

import pygame

GREEN_COLOR =(0,0,255)


UP = 0
RIGHT = 1
DOWN = 2
LEFT = 3
#  顺时针顺序设置

class  Gameobject(object,metaclass=ABCMeta):
    def __init__(self,x=0,y=0,color =(0, 0, 0) ):
        self._x = x
        self._y = y
        self._color = color

    @property
    def x(self):
        return self._x

    @property
    def y(self):
        return self._y

    @abstractmethod
    def draw(self,screen):
        pass

class Wall(Gameobject):

    def __init__(self,x,y,hight,width,color =(0,0,0)):    # pos 元组 一个点
        super().__init__(x, y, color)
        self._hight = hight
        self._width = width
                       # 默认颜色为黑色
        # 初始化
    @property
    def width(self):
        return self._width

    @property
    def hight(self):
        return self._hight

    def draw(self,screen):              #  1 画围墙   4 是像素
        pygame.draw.rect(screen,self._color,
                         (self._x,self._y,self._width,self._hight),4)


class Food(Gameobject):


    def __init__(self,x,y,size,color=(255,189,0)):
         super().__init__(x,y,color)
         self._size =size
         self._hidden = False



    def draw(self,screen):
        if not self._hidden:   # 闪烁
            pygame.draw.circle(screen,self._color,
                               (self._x+self._size//2,self._y + self._size//2 ),self._size//2,0)
                                                    # x y是起点位置 size是半径
        self._hidden = not self._hidden   # 闪烁

class SnakeNode(Gameobject):

    def __init__(self,x,y,size,color=GREEN_COLOR):
        super().__init__(x,y,color)
        self._size = size

    @property
    def size(self):
        return self._size

    def draw(self,screen):    # 画矩形
        pygame.draw.rect(screen,self._color,(self._x,self._y,self._size,self._size),0)
        pygame.draw.rect(screen, (0,0,0), (self._x, self._y, self._size, self._size), 1)

class Snake(Gameobject):
##  如果能使用强关联关系,就不要考虑继承关系
    def __init__(self):
        super().__init__()
        self._dir = LEFT             # 蛇的方向
        self._nodes = []
        self._alive = True
        for index in range(5):
            node = SnakeNode(290 + index * 20 ,290,20)   # 蛇的第一个节点 方向
            self._nodes.append(node)  # 容器

    @property
    def dir(self):
        return self._dir

    @property
    def alive(self):
        return self._alive

    @property
    def head(self):
        return self._nodes[0]

    def change_dir(self,new_dir):   # 蛇跑的方向转变
        if (self._dir + new_dir) % 2 != 0:
            self._dir = new_dir

    def move(self):
        if self._alive:
            snake_dir = self._dir
                                          # 蛇的移动
            x,y,size = self.head.x,self.head.y,self.head.size
            if snake_dir == UP:
                y -= size            # 往上跑
            elif snake_dir == RIGHT:
                x += size            # 往右跑
            elif snake_dir == DOWN:
                y += size
            else :
                x -= size
            new_head = SnakeNode(x,y,size)
            self._nodes.insert(0,new_head)
            self._nodes.pop()      # 删除最后一节

    def collide(self,wall):             # 判断撞墙
        """

        :param wall: 围墙
        :return:  撞到围墙返回真 否则返回假
        """
        head = self.head
        if head.x < wall.x or head.x + head.size > wall.x + wall.width or head.y < wall.y\
               or head.y + head.size > wall.y + wall.hight:
            self._alive =False

    def eat_food(self,food):        ## 吃食物
        if self.head.x == food.x and self.head.y == food.y:
            tail = self._nodes[-1]
            self._nodes.append(tail)
            return True
        return False

                            # 增加一个记分功能
    def eat_me(self):      # 咬到自己
        pass

    def draw(self,screen):
        for node in self._nodes:
            node.draw(screen)


def main():

    def refresh():      ## 函数里面在定义函数 (嵌套)
        """刷新游戏窗口"""
        screen.fill((242, 242, 242))
        wall.draw(screen)  # 3传个消息 在屏幕是画
        food.draw(screen)
        snake.draw(screen)
        pygame.display.flip()


    def handle_key_event(key_event):
        """处理按键事件"""
        key = key_event.key
        if key == pygame.K_F2:
            reset_game()
        else:
            if snake.alive:
                new_dir =snake.dir
                if key == pygame.K_w:
                    new_dir = UP
                elif key == pygame.K_d:
                    new_dir = RIGHT
                elif key == pygame.K_s:
                    new_dir = DOWN
                elif key == pygame.K_a:
                    new_dir = LEFT
                if new_dir != snake.dir:
                    snake.change_dir(new_dir)


    def create_food():   ##随机生成一个食物点
        row = randint(0,29)
        col = randint(0,29)
        return Food(10 + 20 * col ,10 + 20 * row ,20)

    def reset_game():
        nonlocal food,snake   ## 作用域 有这个才能F2 重新刷新
        food = create_food()
        snake = Snake()


    wall = Wall(10,10,600,600)    # 2创建围墙对象
    food =create_food()
    snake = Snake()
    pygame.init()
    screen = pygame.display.set_mode((620, 620))   # 窗口大小 620个像素(620个点)
    pygame.display.set_caption('贪吃蛇')
    screen.fill((242,242,242))                     # 必须两个括号 里面 放元组 或列表的意思
    pygame.display.flip()
    clock = pygame.time.Clock()
    running = True
    while running:                        # 循环 把窗口保留着  发生键盘鼠标事件就进行处理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.KEYDOWN:
                handle_key_event(event)
        if snake.alive:
            refresh()  # 4刷新界面
        clock.tick(6)                 # 20帧/1s
        if snake.alive:
            snake.move()
            snake.collide(wall)
            if snake.eat_food(food):
                food = create_food()

    pygame.quit()


if __name__ == '__main__':
    main()

猜你喜欢

转载自blog.csdn.net/weixin_41782332/article/details/79573972