主要算法:
创建一个二维矩阵映射到屏幕上的像素,逻辑在该矩阵中实现
移动通过4个矢量完成,矢量储存在列表中按照 上右下左 的顺序排列(顺时针90度),
当前矢量以0-3的数字表达,这样进行加二除余可以实现判断180度方向无效
蛇身以列表方式表达,每次游戏循环时在列表头部插入一个蛇头,如果没有吃到东西则把蛇尾去掉
关于按键太快会导致撞到自己:
pygame在检测到2个按键的时候有可能会把矢量反向
解决方法:
每一帧只计算一个按键
操作:
WSAD 方向
在游戏结束之后按R重新开始
import pygame as pg
import time
import randomclass Tile():def __init__(self,x,y): #主要是储存数据和绘制图形self.x,self.y = x,yself.connected = [0,0,0,0] # up,right,down,left 0 for not connectedself.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 => fruitdef draw(self,color = (0,0,0)): #x,y represents the tile coordinatespg.draw.rect(screen,tile_color[self.tile_type],self.rectangle) #绘制节点def generate_fruit():global fruitx,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 = 2def initialize():global scoreglobal game_lostglobal fruitglobal matrixglobal snakeglobal step_scoregame_lost = Falsescore = 0step_score = 200matrix = []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 = 1generate_fruit()def calculation():global game_lostglobal scoreglobal step_scorehead = snake[0]x,y = head.x,head.ydx,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 Trueif matrix[y+dy][x+dx].tile_type == 1:return Trueif matrix[y+dy][x+dx].tile_type == 2:score += step_scorestep_score = 200generate_fruit()else:snake[-1].tile_type = 0snake.pop(-1)snake.insert(0,matrix[y+dy][x+dx])snake[0].tile_type = 1if __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 = 0screen = 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 = Falset_start = time.time()screen.fill((255,255,255))step_score -= 1high_score = score if score > high_score else high_scoreevents = pg.event.get()for event in events:if event.type == pg.QUIT:run = Falsepg.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_vectorbreakif event.key == pg.K_r:replay = Trueif 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