python讲座2—贪吃蛇
作者:互联网
这次讲座讲了一下用pygame库写贪吃蛇的小游戏:
总览
首先贴出全部代码:
# 导入所需的模块
import enum
import sys
import pygame as pg
import random
WIDTH, HEIGHT = 400, 400
ROW_NUM = 20 # 行数
COL_NUM = 20 # 列数
BLOCK_WIDTH, BLOCK_HEIGHT = WIDTH / COL_NUM, HEIGHT / ROW_NUM
# R(Red) G(Green) B(Blue)
BODY_COLOR = (0, 255, 0)
HEAD_COLOR = (255, 0, 0)
FOOD_COLOR = (0, 0, 255)
# 使用pg之前必须初始化
pg.init()
# 设置主屏窗口
screen = pg.display.set_mode((WIDTH, HEIGHT))
# 设置窗口的标题,即游戏名称
pg.display.set_caption('贪吃蛇')
class Direction(enum.Enum):
Left = 0
Up = 1
Right = 3
Down = 2
class GameState(enum.Enum):
Die = 0
Playing = 1
Preparing = 2
# 初始化这条蛇
snakes = []
blocks = []
direction: Direction = Direction.Up
game_state: GameState = GameState.Playing
difficulty = 3
food = (10*BLOCK_WIDTH, 10*BLOCK_HEIGHT)
score = 0
max_score = 0
def init():
snakes.clear()
snakes.append((5*BLOCK_WIDTH, 5*BLOCK_HEIGHT))
snakes.append((5*BLOCK_WIDTH, 6*BLOCK_HEIGHT))
snakes.append((5*BLOCK_WIDTH, 7*BLOCK_HEIGHT))
global direction, game_state, difficulty, score, max_score
direction = Direction.Up
game_state = GameState.Playing
difficulty = 3
generate_food()
score = 0
def set_direction(d: Direction):
global direction
if(d.value + direction.value == 3):
return
direction = d
def generate_food():
global food
while True:
x = random.randint(0, COL_NUM-1) * BLOCK_WIDTH
y = random.randint(0, ROW_NUM-1) * BLOCK_HEIGHT
if (x, y) not in snakes and (x, y) not in blocks:
food = (x, y)
break
def move():
global game_state
cur_head: tuple[int, int] = snakes[0]
match direction:
case Direction.Left:
snakes.insert(0, (cur_head[0]-BLOCK_WIDTH, cur_head[1]))
case Direction.Right:
snakes.insert(0, (cur_head[0]+BLOCK_WIDTH, cur_head[1]))
case Direction.Down:
snakes.insert(0, (cur_head[0], cur_head[1]+BLOCK_HEIGHT))
case Direction.Up:
snakes.insert(0, (cur_head[0], cur_head[1]-BLOCK_HEIGHT))
if (head := snakes[0]) != food:
if head in snakes[1:] or head[0] < 0 or head[0] >= WIDTH or head[1] < 0 or head[1] >= HEIGHT:
game_state = GameState.Die
else:
snakes.pop()
else:
global difficulty, score, max_score
difficulty *= 1.0
score += 100
generate_food()
def draw_text(s: str, center, font_size=50, font_color=(255, 0, 0), back_color=(255, 255, 255)):
f = pg.font.Font('C:/Windows/Fonts/simhei.ttf', font_size)
# 生成文本信息,第一个参数文本内容;第二个参数,字体是否平滑;
# 第三个参数,RGB模式的字体颜色;第四个参数,RGB模式字体背景颜色;
text = f.render(s, True, font_color, back_color)
# 获得显示对象的rect区域坐标
textRect = text.get_rect()
# 设置显示对象居中
textRect.center = center
# 将准备好的文本信息,绘制到主屏幕 Screen 上。
screen.blit(text, textRect)
init()
clock = pg.time.Clock()
# 固定代码段,实现点击"X"号退出界面的功能,几乎所有的pg都会使用该段代码
while True:
clock.tick(2 * difficulty)
# 循环获取事件,监听事件状态
for event in pg.event.get():
# 判断用户是否点了"X"关闭按钮,并执行if代码段
match event.type:
case pg.QUIT:
pg.quit()
sys.exit()
case pg.MOUSEBUTTONDOWN:
#print("click")
if game_state == GameState.Die:
game_state = GameState.Playing
init()
case pg.KEYDOWN:
match event.key:
case pg.K_LEFT:
set_direction(Direction.Left)
case pg.K_RIGHT:
set_direction(Direction.Right)
case pg.K_UP:
set_direction(Direction.Up)
case pg.K_DOWN:
set_direction(Direction.Down)
case pg.K_0:
if game_state == GameState.Die:
game_state = GameState.Playing
init()
move()
screen.fill((255, 255, 255))
if game_state == GameState.Playing:
for i, block in enumerate(snakes):
if i == 0:
pg.draw.rect(screen, HEAD_COLOR,
(block[0], block[1], BLOCK_WIDTH, BLOCK_HEIGHT))
else:
pg.draw.rect(screen, BODY_COLOR,
(block[0], block[1], BLOCK_WIDTH, BLOCK_HEIGHT))
pg.draw.rect(screen, FOOD_COLOR,
(food[0], food[1], BLOCK_WIDTH, BLOCK_HEIGHT))
if score >= max_score:
max_score = score
draw_text(f"最高分数:{max_score}!", (60, 100), 18, (255, 0, 0))
else:
draw_text(f"最高分数:{max_score}", (60, 100), 18, (0, 0, 0))
draw_text(f"分数:{score}", (60, 50), 18, (0, 0, 0))
else:
draw_text("你输了!", (200, 200))
pg.display.flip() # 更新屏幕内容
模块导入:
把需要用的库都引用一下,一般有这几个:
import enum
import sys
import pygame as pg
import random
import ... as ...就是将库重命名了一下
设置一些常数
WIDTH, HEIGHT = 400, 400
ROW_NUM = 20 # 行数
COL_NUM = 20 # 列数
BLOCK_WIDTH, BLOCK_HEIGHT = WIDTH / COL_NUM, HEIGHT / ROW_NUM
# R(Red) G(Green) B(Blue)
BODY_COLOR = (0, 255, 0)
HEAD_COLOR = (255, 0, 0)
FOOD_COLOR = (0, 0, 255)
使用了RGB颜色
初始化窗口:
# 使用pg之前必须初始化
pg.init()
# 设置主屏窗口
screen = pg.display.set_mode((WIDTH, HEIGHT))
# 设置窗口的标题,即游戏名称
pg.display.set_caption('贪吃蛇')
class Direction(enum.Enum):
Left = 0
Up = 1
Right = 3
Down = 2
class GameState(enum.Enum):
Die = 0
Playing = 1
Preparing = 2
创建的两个类Direction和GameState继承了enum库,enum就是一个枚举,意思是这个类里面只存在Class里面枚举的键值对,其他都会报错,用于加强鲁棒性。
初始化参数:
snakes = []
blocks = []
direction: Direction = Direction.Up
game_state: GameState = GameState.Playing
difficulty = 3
food = (10*BLOCK_WIDTH, 10*BLOCK_HEIGHT)
score = 0
max_score = 0
这里采用元组的形式来建立蛇
定义主要函数:
初始化函数
def init():
snakes.clear()
snakes.append((5*BLOCK_WIDTH, 5*BLOCK_HEIGHT))
snakes.append((5*BLOCK_WIDTH, 6*BLOCK_HEIGHT))
snakes.append((5*BLOCK_WIDTH, 7*BLOCK_HEIGHT))
global direction, game_state, difficulty, score, max_score
direction = Direction.Up
game_state = GameState.Playing
difficulty = 3
generate_food()
score = 0
global + 变量名:将变量声明为全局变量,
在函数里面如果不加global,就像c语言中的形参一样,对于变量本身没有影响。
初始时蛇长定为3
定向函数:
def set_direction(d: Direction):
global direction
if(d.value + direction.value == 3):
return
direction = d
d.value + direction.value != 3是为了保证转向后不会向反方向走(其他方向都有可能)
产生食物:
def generate_food():
global food
while True:
x = random.randint(0, COL_NUM-1) * BLOCK_WIDTH
y = random.randint(0, ROW_NUM-1) * BLOCK_HEIGHT
if (x, y) not in snakes and (x, y) not in blocks:
food = (x, y)
break
食物随机产生,但不能生成在蛇身上和墙上。
蛇的抽抽:
def move():
global game_state
cur_head: tuple[int, int] = snakes[0]
match direction:
case Direction.Left:
snakes.insert(0, (cur_head[0]-BLOCK_WIDTH, cur_head[1]))
case Direction.Right:
snakes.insert(0, (cur_head[0]+BLOCK_WIDTH, cur_head[1]))
case Direction.Down:
snakes.insert(0, (cur_head[0], cur_head[1]+BLOCK_HEIGHT))
case Direction.Up:
snakes.insert(0, (cur_head[0], cur_head[1]-BLOCK_HEIGHT))
if (head := snakes[0]) != food:
if head in snakes[1:] or head[0] < 0 or head[0] >= WIDTH or head[1] < 0 or head[1] >= HEIGHT:
game_state = GameState.Die
else:
snakes.pop()
else:
global difficulty, score, max_score
difficulty *= 1.0
score += 100
generate_food()
产生文本:
def draw_text(s: str, center, font_size=50, font_color=(255, 0, 0), back_color=(255, 255, 255)):
f = pg.font.Font('C:/Windows/Fonts/simhei.ttf', font_size)
# 生成文本信息,第一个参数文本内容;第二个参数,字体是否平滑;
# 第三个参数,RGB模式的字体颜色;第四个参数,RGB模式字体背景颜色;
text = f.render(s, True, font_color, back_color)
# 获得显示对象的rect区域坐标
textRect = text.get_rect()
# 设置显示对象居中
textRect.center = center
# 将准备好的文本信息,绘制到主屏幕 Screen 上。
screen.blit(text, textRect)
设置font对象,渲染font对象,设置文本位置。
主循环:
init()
clock = pg.time.Clock()
# 固定代码段,实现点击"X"号退出界面的功能,几乎所有的pg都会使用该段代码
while True:
clock.tick(2 * difficulty)
# 循环获取事件,监听事件状态
for event in pg.event.get():
# 判断用户是否点了"X"关闭按钮,并执行if代码段
match event.type:
case pg.QUIT:
pg.quit()
sys.exit()
case pg.MOUSEBUTTONDOWN:
#print("click")
if game_state == GameState.Die:
game_state = GameState.Playing
init()
case pg.KEYDOWN:
match event.key:
case pg.K_LEFT:
set_direction(Direction.Left)
case pg.K_RIGHT:
set_direction(Direction.Right)
case pg.K_UP:
set_direction(Direction.Up)
case pg.K_DOWN:
set_direction(Direction.Down)
case pg.K_0:
if game_state == GameState.Die:
game_state = GameState.Playing
init()
move()
screen.fill((255, 255, 255))
if game_state == GameState.Playing:
for i, block in enumerate(snakes):
if i == 0:
pg.draw.rect(screen, HEAD_COLOR,
(block[0], block[1], BLOCK_WIDTH, BLOCK_HEIGHT))
else:
pg.draw.rect(screen, BODY_COLOR,
(block[0], block[1], BLOCK_WIDTH, BLOCK_HEIGHT))
pg.draw.rect(screen, FOOD_COLOR,
(food[0], food[1], BLOCK_WIDTH, BLOCK_HEIGHT))
if score >= max_score:
max_score = score
draw_text(f"最高分数:{max_score}!", (60, 100), 18, (255, 0, 0))
else:
draw_text(f"最高分数:{max_score}", (60, 100), 18, (0, 0, 0))
draw_text(f"分数:{score}", (60, 50), 18, (0, 0, 0))
else:
draw_text("你输了!", (200, 200))
pg.display.flip() # 更新屏幕内容
标签:head,snakes,python,WIDTH,讲座,pg,贪吃蛇,score,BLOCK 来源: https://www.cnblogs.com/misasteria/p/16290637.html