接下来先让蛇动起来,有两种思路:
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()
效果如下:
可见,画出来有点断断续续的,接下来会进行改进,让其变的流畅。
(未完待续)