pygame制作贪吃蛇游戏教程(二)

接下来先让蛇动起来,有两种思路:
1、全局更新:隔一段时间全部重画。这样写比较简单,但是比较消耗内存,可能运行不顺畅
2、局部更新:擦掉头和尾巴的一小部分重画
考虑到后期蛇比较长的时候,如果每次运行都重新画,画面肯定是不流畅的,因此这里采用局部更新的方法

准备工作

    while True:
        for event in pygame.event.get():

这条语句实际上是以相当快的频率进行消息循环的。我们的游戏不需要这么高帧,因此需要自己定义一个事件,隔一段时间运行一次,在main.py中定义全局变量,要用的时候再settimer:

#定义
SNAKE_MOVE = pygame.USEREVENT
#调用
    pygame.time.set_timer(SNAKE_MOVE, 1000)
#取消调用
    pygame.time.set_timer(SNAKE_MOVE, 0)

这样就每隔1s调用一次SNAKE_MOVE事件了
为了调试的时候舒服,先让它能够随时暂停和继续:

# is_pause是新定义的变量,按p键暂停或开始
            if event.type == KEYDOWN:
                if event.key == pygame.K_p:
                    if is_pause == 0:
                        is_pause = 1
                        pygame.time.set_timer(SNAKE_MOVE, 0)
                    else:
                        is_pause = 0
                        pygame.time.set_timer(SNAKE_MOVE, 1000)

正式开始

下面开始编写SNAKE_MOVE函数,思路是只动头尾。
由于涉及擦除图像的一部分,因此先定一下背景,这里设为原谅绿。
背景插入图像步骤是一样的,也是screen.blit,不再赘述,最后会有完整代码。
具体思路:
1、找到头尾
2、把头和尾处擦掉,画上新头和旧头,这样每次只需要更新四个图,有效减少了内存的浪费
上代码(昨天写的逻辑上有修改,不过很小):
main.py:

import pygame
from pygame import *
from settings import Settings
from snake import Snake
import sys

SNAKE_MOVE = pygame.USEREVENT

def main():
    is_pause = 0
    pygame.init()  #初始化背景设置
    settings = Settings()  # 实例化
    snake = Snake(settings)
    screen = pygame.display.set_mode((settings.screen_width, settings.screen_height)) #调用属性设置屏幕的宽高
    pygame.display.set_caption("贪吃蛇")  #设置标题
    background = pygame.image.load("../Assets/background.jpg")
    screen.blit(background, (0, 0))
    snake.draw_snake(screen)
    pygame.time.set_timer(SNAKE_MOVE, 300)
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:#点击右上角的红叉关闭程序
                sys.exit()
            if event.type == SNAKE_MOVE:
                snake.redraw_snake(screen)
            if event.type == KEYDOWN:
                if event.key == pygame.K_p:
                    if is_pause == 0:
                        is_pause = 1
                        pygame.time.set_timer(SNAKE_MOVE, 0)
                    else:
                        is_pause = 0
                        pygame.time.set_timer(SNAKE_MOVE, 300)
main()

snake.py:

#snake.py
#基础设置参数都在这里
from numpy import *
import pygame
from pygame import *
from snakepic import SnakePic
class Snake():
    def __init__(self, settings):
        self.current_direction = 2  #1表示向上,2右,3下,4左
        self.settings = settings
        # 根据这个跟地图同维矩阵来确定蛇长什么样子
        # 0表示空,1、2、3、4表示方向,蛇在地图这个点的方向
        self.discribe = zeros((settings.map_x+2, settings.map_y+2), dtype=int)
        # 更详细的蛇的样子,0表示空,1~4表示头,5~8表示拐弯,9~12表示身子,13~16表示尾巴
        self.detail_discribe = zeros((settings.map_x+2, settings.map_y+2), dtype=int)
        self.read_snake_data()

    def detail_snake(self):
        for i in range(0, self.settings.map_x+2):
            for k in range(0, self.settings.map_y+2):
                if self.discribe[i, k] == 0:
                    self.detail_discribe[i, k] = 0
                    continue
                self.detail_discribe[i, k] = self.detail_judge(i, k)

    def detail_judge(self, i, k):
        if i == 1 and k == 2:
            c=0
        if self.discribe[i, k] == 1:
            if self.discribe[i+1, k] == 1 and self.discribe[i-1, k] != 0:
                return 9
            if self.discribe[i-1, k] == 0:
                return 1
            if self.discribe[i+1, k] != 1:
                if self.discribe[i, k-1] != 2 and self.discribe[i, k+1] != 4:
                    return 13
                if self.discribe[i, k+1] == 4:
                    return 7
                if self.discribe[i, k-1] == 2:
                    return 6

        if self.discribe[i, k] == 2:
            if self.discribe[i, k+1] != 0 and self.discribe[i, k-1] == 2:
                return 10
            if self.discribe[i, k+1] == 0:
                return 2
            if self.discribe[i, k-1] != 2:
                if self.discribe[i+1, k] != 1 and self.discribe[i-1, k] != 3:
                    return 14
                if self.discribe[i+1, k] == 1:
                    return 8
                if self.discribe[i-1, k] == 3:
                    return 7

        if self.discribe[i, k] == 3:
            if self.discribe[i+1, k] != 0 and self.discribe[i-1, k] == 3:
                return 11
            if self.discribe[i+1, k] == 0:
                return 3
            if self.discribe[i-1, k] != 3:
                if self.discribe[i, k+1] != 4 and self.discribe[i, k-1] != 2:
                    return 15
                if self.discribe[i, k+1] == 4:
                    return 8
                if self.discribe[i, k-1] == 2:
                    return 5

        if self.discribe[i, k] == 4:
            if self.discribe[i, k+1] == 4 and self.discribe[i, k-1] != 0:
                return 12
            if self.discribe[i, k-1] == 0:
                return 4
            if self.discribe[i, k+1] != 4:
                if self.discribe[i+1, k] != 1 and self.discribe[i-1, k] != 3:
                    return 16
                if self.discribe[i+1, k] == 1:
                    return 5
                if self.discribe[i-1, k] == 3:
                    return 6
        c=0

    def draw_snake(self, screen):
        self.detail_snake()
        for i in range(0, self.settings.map_x+2):
            for k in range(0, self.settings.map_y+2):
                if self.detail_discribe[i, k] == 0:
                    continue
                temp = SnakePic(self.detail_discribe[i, k])
                temp.blitme(screen, i, k)
        pygame.display.update()

    def read_snake_data(self):
        f = open('../Data/level1.txt')
        lines = f.readlines()
        A_row = 1
        for line in lines:
            list = line.split('\t')
            self.discribe[A_row, 1: self.settings.map_x + 1] = list[0: self.settings.map_x]
            A_row += 1

    def redraw_snake(self, screen):
        self.detail_snake()
        #先找到头和尾
        head = [0, 0]
        tail = [0, 0]
        head_new = [0, 0]
        tail_new = [0, 0]
        for i in range(0, self.settings.map_x+2):
            for k in range(0, self.settings.map_y+2):
                if self.detail_discribe[i, k] == 1:
                    head = [i, k]
                    head_new = [i-1, k]
                if self.detail_discribe[i, k] == 2:
                    head = [i, k]
                    head_new = [i, k+1]
                if self.detail_discribe[i, k] == 3:
                    head = [i, k]
                    head_new = [i+1, k]
                if self.detail_discribe[i, k] == 4:
                    head = [i, k]
                    head_new = [i, k-1]
                if self.detail_discribe[i, k] == 13:
                    tail = [i, k]
                    tail_new = [i-1, k]
                if self.detail_discribe[i, k] == 14:
                    tail = [i, k]
                    tail_new = [i, k+1]
                if self.detail_discribe[i, k] == 15:
                    tail = [i, k]
                    tail_new = [i+1, k]
                if self.detail_discribe[i, k] == 16:
                    tail = [i, k]
                    tail_new = [i, k-1]
        P = [head, head_new, tail_new]
        if self.discribe[head[0], head[1]] == 1:
            self.discribe[head[0]-1, head[1]] = 2
        if self.discribe[head[0], head[1]] == 2:
            self.discribe[head[0], head[1]+1] = 2
        if self.discribe[head[0], head[1]] == 3:
            self.discribe[head[0]+1, head[1]] = 2
        if self.discribe[head[0], head[1]] == 2:
            self.discribe[head[0], head[1]-1] = 2
        self.discribe[tail[0], tail[1]] = 0
        rect1 = pygame.Rect(50*(head[1]-1), 50*(head[0]-1), 50, 50)
        rect2 = pygame.Rect(50*(tail[1]-1), 50*(tail[0]-1), 50, 50)
        rect3 = pygame.Rect(50*(head_new[1]-1), 50*(head_new[0]-1), 50, 50)
        rect4 = pygame.Rect(50*(tail_new[1]-1), 50*(tail_new[0]-1), 50, 50)
        #把新头、旧头、新尾、旧尾擦掉
        screen.fill((0, 255, 0), rect1)
        screen.fill((0, 255, 0), rect2)
        screen.fill((0, 255, 0), rect3)
        screen.fill((0, 255, 0), rect4)
        #看看新蛇啥样
        self.detail_snake()
        for p in P:
            if self.detail_discribe[p[0], p[1]] == 0:
                c=0
            temp = SnakePic(self.detail_discribe[p[0], p[1]])
            temp.blitme(screen, p[0], p[1])
        pygame.display.update()

效果如下:


贪吃蛇 2020-03-14 12-58-57.gif

可见,画出来有点断断续续的,接下来会进行改进,让其变的流畅。
(未完待续)

你可能感兴趣的:(pygame制作贪吃蛇游戏教程(二))