本次做一个最简单的贪食蛇雏形游戏,就是一个小蛇在画面上移动,我们可以控制蛇的移动方向,但是不能吃东西,蛇不会长大。但是基础的有了,完整版的贪食蛇还远吗?双人贪食蛇不也就那么回事吗?
先做一个简单的,有机会再放出不那么简单,但依旧简陋的标准贪食蛇和双人贪食蛇。
首先,pygam的各种配置参数,直接使用之前的配置,多退少补。
import random import time import pygame fps = 30 fps_clock = pygame.time.Clock() screen_width = 640 screen_height = 480 display = pygame.display.set_mode((screen_width, screen_height), 0, 32) pygame.display.set_caption('贪食蛇') tile_size = 20 tile_width = 20 tile_height = 20 #横纵间距 x_margin = 100 y_margin = 100 #列 columns = int((screen_width - 100) / 20) #行 rows = int((screen_height - 100) / 20) directions = ['up', 'down', 'left', 'right'] #配色RGB white = 'white' black = 'black' bg_color = 'sky blue' border_color = white if __name__ == '__main__': while True: display.fill(bg_color) for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() pygame.display.update() fps_clock.tick(fps)
基本的配置函数,棋盘类游戏常规操作。
运行游戏会得到一个天蓝色的画布,什么都没有。
接下来,在画布上画出二维棋盘,也就是贪食蛇运动的场地。这里我们有几种选择,此处我选择一种最简单的方式,也就是整个棋盘不对应二维列表,只为贪食蛇本身创建一个列表,用来储存贪食蛇的身体。
首先绘制一个大棋盘。
def draw_chest(): for i in range(rows + 1): pygame.draw.line(display, border_color, (x_margin/2, y_margin/2 + i * tile_size), (x_margin/2 + (columns * tile_size), y_margin/2 + i * tile_size), 2) for j in range(columns + 1): pygame.draw.line(display, border_color, (x_margin/2 + j * tile_size, y_margin/2), (x_margin/2 + j * tile_size, y_margin/2 + (rows * tile_size)), 2)
然后主循环里调用,然后运行程序。
贪食蛇的运动空间已经出现了。
创建一个列表,用来存放贪食蛇的身体。默认贪食蛇的长度为3。具体大小可以根据自己的喜欢修改,我就写3了。
那么需要基于这两个数值来生成蛇的身体的第一个位置。例如,我们生成的蛇的身体的第一个位置是[3][3],那么对应的在屏幕中[3][3]所对应的坐标位置,绘制一个小方块,同时默认蛇的身体是往右延伸,那么蛇的身体参数则为[3][3],[3][4],[3][5]
考虑到让蛇随机出现在画面中的某些地方,所以生成蛇的身体是照顾到各方,随机数的范围如下:
在主循坏外创建列表,添加身体,身体保持在画面中央部分。
snake_body = [] snake_x = random.randint(5, rows - 5) snake_y = random.randint(5, columns - 5) snake_body.append([snake_x, snake_y]) snake_body.append([snake_x, snake_y + 1]) snake_body.append([snake_x, snake_y + 2]) return snake_body
为绘制蛇的身体,编写绘制函数。
def draw_snake_shape(shapes): for shape in shapes: left_position = shape[1] * tile_size + x_margin/2 top_position = shape[0] * tile_size + y_margin/2 # 画出整个身体背景色 pygame.draw.rect(display, body_color, (left_position, top_position, tile_size, tile_size)) # 画出内部颜色 pygame.draw.rect(display, inter_body_color, (left_position+4, top_position+4, tile_size-8, tile_size-8))
在主循环中调用,运行游戏,每次运行,蛇都在不同的位置,同时不会出现在边缘。
接下来就是让蛇动起来。
让蛇动起来的核心思想就是,根据蛇当前的前进方向,增加和删除snake_body中的坐标值。比如,下一步蛇的运动方向是up,那么确认当前up方向是合法的时候,即往上走一步不会走到边界,或者当前正在往下走,那么,我们得出新的坐标点,加入到snake_body中,同时删除列表最后一个数据,因为当前没有苹果可以吃嘛。
先定义一个判断下一个坐标点是否合法的函数。
def is_right_direction(body, x_location, y_location): valid_direction = False if 0 <= x_location <= rows-1 and 0 <= y_location <= columns - 1: valid_direction = True return valid_direction
在主循环中加入程序处理贪食蛇按照某个固定的方向移动时对于贪食蛇身体列表的操作。
首先在进入主循环前,获取当前需要移动的方向
direction = directions[random.randint(0, 3)] while True:
在主循环内部,增加代码处理身体移动
#未按下按键时,默认的初识移动方向 new_body_location = (None, None) match direction: case 'left': new_body_location = snake_body[0][0], snake_body[0][1] - 1 case 'right': new_body_location = snake_body[0][0], snake_body[0][1] + 1 case 'up': new_body_location = snake_body[0][0] - 1, snake_body[0][1] case 'down': new_body_location = snake_body[0][0] + 1, snake_body[0][1] snake_body.insert(0, new_body_location) del snake_body[-1]
此时运行程序,贪食蛇会像闪电一般快速移动到屏幕边缘。
根本来不及截图,因为我们的刷新率是30帧每秒,所以太快了,此时有多种解决方案,最简单的一种是修改刷新率,比如修改为2,那么就会看到蛇缓慢移动了。非常简单啦。也可以考虑在移动部分做定时,或者做累加延迟等等。这里我修改了fps=2。
接下来增加控制部分,这部分很简单。
在按键部分设定上下左右按键控制方向,同时要注意,贪食蛇不能直接掉头走。
#键盘控制改变贪食蛇的方向 elif event.type == pygame.KEYUP: if event.key == pygame.K_LEFT and direction != 'right': direction = 'left' elif event.key == pygame.K_RIGHT and direction != 'left': direction = 'right' elif event.key == pygame.K_UP and direction != 'down': direction = 'up' elif event.key == pygame.K_DOWN and direction != 'up': direction = 'down'
游戏结束机制,也就是蛇碰到边界游戏结束。
if is_right_direction(snake_body, new_body_location[0], new_body_location[1]): snake_body.insert(0, new_body_location) del snake_body[-1] else: snake_body = [] snake_x = random.randint(5, columns - 5) snake_y = random.randint(5, rows - 5) snake_body.append([snake_x, snake_y]) snake_body.append([snake_x, snake_y + 1]) snake_body.append([snake_x, snake_y + 2])
框架级别的贪食蛇制作完成了,如果再加入一个小苹果,增加一个增加身体条件就有一个完整的贪食蛇了。再追加一个追尾机制,和一条新的蛇就可以双人对战了。