主要算法:
创建一个二维矩阵映射到屏幕上的像素,逻辑在该矩阵中实现
移动通过4个矢量完成,矢量储存在列表中按照 上右下左 的顺序排列(顺时针90度),
当前矢量以0-3的数字表达,这样进行加二除余可以实现判断180度方向无效
蛇身以列表方式表达,每次游戏循环时在列表头部插入一个蛇头,如果没有吃到东西则把蛇尾去掉
关于按键太快会导致撞到自己:
pygame在检测到2个按键的时候有可能会把矢量反向
解决方法:
每一帧只计算一个按键
操作:
WSAD 方向
在游戏结束之后按R重新开始
import pygame as pg
import time
import random
class Tile():
def __init__(self,x,y): #主要是储存数据和绘制图形
self.x,self.y = x,y
self.connected = [0,0,0,0] # up,right,down,left 0 for not connected
self.tile_size = [(game_size[0]-100)/grid_size[0],(game_size[1]-100)/grid_size[1]]
self.rectangle = (self.x*self.tile_size[0]+50,self.y*self.tile_size[1]+50,self.tile_size[0],self.tile_size[1])
self.tile_type = 0 # 0 => empty, 1 => snake, 2 => fruit
def draw(self,color = (0,0,0)): #x,y represents the tile coordinates
pg.draw.rect(screen,tile_color[self.tile_type],self.rectangle) #绘制节点
def generate_fruit():
global fruit
x,y = random.randint(0,grid_size[0]),random.randint(0,grid_size[1])
while matrix[y][x].tile_type != 0:
x,y = random.randint(0,grid_size[0]),random.randint(0,grid_size[1])
fruit = matrix[y][x]
fruit.tile_type = 2
def initialize():
global score
global game_lost
global fruit
global matrix
global snake
global step_score
game_lost = False
score = 0
step_score = 200
matrix = []
for y in range(grid_size[1]+1):
temp = []
for x in range(grid_size[0]+1):
temp.append(Tile(x,y))
matrix.append(temp)
x,y = random.randint(0,grid_size[0]),random.randint(0,grid_size[1])
snake = [matrix[y][x]]
snake[0].tile_type = 1
generate_fruit()
def calculation():
global game_lost
global score
global step_score
head = snake[0]
x,y = head.x,head.y
dx,dy = vectors[current_vector]
if x+dx not in range(grid_size[0]+1) or y+dy not in range(grid_size[1]+1):
return True
if matrix[y+dy][x+dx].tile_type == 1:
return True
if matrix[y+dy][x+dx].tile_type == 2:
score += step_score
step_score = 200
generate_fruit()
else:
snake[-1].tile_type = 0
snake.pop(-1)
snake.insert(0,matrix[y+dy][x+dx])
snake[0].tile_type = 1
if __name__ != '__main__': #八股专用
exit()
#================================initialize parameter===================================
tile_color = [(0,0,0),(0,255,0),(255,0,0)]
vector_ref = {pg.K_w:0,pg.K_d:1,pg.K_s:2,pg.K_a:3} #starting up, clockwise
vectors = [[0,-1],[1,0],[0,1],[-1,0]]
current_vector = random.randint(0,3)
screen_size = [1200,800]
game_size = [800,800]
grid_size = [20,20]
dt = 0
screen = pg.display.set_mode(screen_size)
pg.init()
font = pg.font.Font('freesansbold.ttf', 32)
initialize()
high_score = 0
#================================game loop==============================================
run = True
while run:
replay = False
t_start = time.time()
screen.fill((255,255,255))
step_score -= 1
high_score = score if score > high_score else high_score
events = pg.event.get()
for event in events:
if event.type == pg.QUIT:
run = False
pg.quit()
if event.type == pg.KEYDOWN:
if event.key in vector_ref:
target_vector = vector_ref[event.key]
if (target_vector+2)%4 != current_vector:
current_vector = target_vector
break
if event.key == pg.K_r:
replay = True
if game_lost:
if replay:
initialize()
else:
game_lost = calculation()
for y in range(len(matrix)):
for x in range(len(matrix[y])):
matrix[y][x].draw()
score_text = font.render(f'score: {score}', True, (0,0,0), (255,255,255))
screen.blit(score_text,(850,200))
high_score_text = font.render(f'high score: {high_score}', True, (0,0,0), (255,255,255))
screen.blit(high_score_text,(850,300))
if dt != 0:
time_text = font.render(f'fps:{1/(dt)}', True, (0,0,0), (255,255,255))
screen.blit(time_text,(850,100))
pg.display.update()
time.sleep(0.1)
dt = time.time()-t_start