python中怎么用pygame实现贪吃蛇游戏
这篇文章主要介绍"python中怎么用pygame实现贪吃蛇游戏",在日常操作中,相信很多人在python中怎么用pygame实现贪吃蛇游戏问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"python中怎么用pygame实现贪吃蛇游戏"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
创建蛇
首先,先分析一下蛇的移动,不然我们一定会吃亏的(别问,问就是自己写了一堆无效代码)。
蛇的移动其实并没有想象中那样复杂,每一个模块都需要有一个方向,按照方向进行移动。
其实实际上就是一个出队的感觉,即每一个元素都取代上一个元素的位置,然后再按照贪吃蛇当前的方向,移动一下头节点即可。
snake.py:
""""????类"""import pygameclass Snake(): def __init__(self,snake_color,snake_head_color,x,y,lattice_wh): self.color = snake_color self.head_color = snake_head_color # 格子的左上角坐标 self.pos = (x,y) self.lattice_wh = lattice_wh self.rect = pygame.Rect(x,y,self.lattice_wh,self.lattice_wh) self.move_distance = { 0:(0,0), 1:(0,-self.lattice_wh), 2:(0, self.lattice_wh), 3:(-self.lattice_wh,0), 4:( self.lattice_wh,0) } def move(self,direction): self.rect.x += self.move_distance[direction][0] self.rect.y += self.move_distance[direction][1] def forecast(self,direction): return (self.rect.x+self.move_distance[direction][0], self.rect.y+self.move_distance[direction][1])
创建蛇,需要给一个位置(坐标),同时也需要输入一个颜色。
这里为了区分头节点,我传入了两个颜色,一个为头节点的颜色,另一个为身子部分的颜色。
(其实颜色不需要给在这里,在update传入一个即可)
蛇的主要部分就是移动,这里我给出了两个方法:
1.移动方法,是针对头节点的移动
2.预测移动位置方法,是判断下一步蛇的移动的位置,看看是否会撞到自己/墙壁,或者吃到食物。
为了方便我们针对方向进行处理,我使用了哈希的方式(其实就是字典),将每一个方向移动一次(x,y)坐标变化量记录好。
【那个方向0,是最开始我们的蛇是固定的,所以我添加了一个(0,0)】
最开始,我们在main文件中创建一个snakes列表,来存储所有的蛇节点,并且添加了最开始的两个节点(头和第一部分的身子)
# 蛇头&1个蛇身snakes = []snakes.append(Snake(snake_color,snake_head_color,lattice_wh,24*lattice_wh,lattice_wh))snakes.append(Snake(snake_color,snake_head_color,0,24*lattice_wh,lattice_wh))
创建食物
这部分,主要就是随机生成一个位置,然后保证这个位置不在蛇身上即可。
食物类:
传入颜色、渲染的界面、一个格子的宽度以及坐标
另外我还提供了一个绘制圆的方法(pos为坐标,radius为直径)
circle函数参数:界面screen,颜色,位置(元组形式),直径,线条宽度。
这里我们将线条设置为直径,就能绘制一个圆盘。(注意宽度一定要是int类型,需要强转)
"""食物类"""import pygameclass Food(): def __init__(self,food_color,screen,lattice_wh,x,y): self.screen = screen self.food_color = food_color self.lattice_wh = lattice_wh self.radius = lattice_wh/2 self.x,self.y = x,y def draw(self): pos = (self.x+self.lattice_wh/2,self.y+self.lattice_wh/2) pygame.draw.circle(self.screen,self.food_color,pos,self.radius,int(self.radius))
fuc.py中,写了一个生成食物的函数:
def create_food(food_color,screen,lattice_wh,snakes): success = 0 x,y = 0,0 while not success: x,y = randint(0,24),randint(0,24) x *= lattice_wh y *= lattice_wh for i in snakes: if (x,y) != (i.rect.x,i.rect.y): success = 1 break food = Food(food_color,screen,lattice_wh,x,y) return food
randint生成一个整数位置,乘上格子的宽度,我们就能得到一个格子的左上角坐标,看看是否在蛇身上,不在就可以生成了。
蛇的移动
之前只给出了方法,现在我们来实现一下。
蛇的移动就三种情况:
撞到自己或者边界
吃到食物
正常移动
如果是第一种,直接结束游戏,第三中我们就按照上面说的,将身子向前移动一位,修改一下头节点即可。
但是第二种,涉及到了需要在snakes添加一个对象,我们就需要搞清楚添加的位置。
在即将碰到食物时,我们将食物位置添加到列表首项。
实现:
这里的game_stats为游戏种需要传递并需要被修改的项,整合成一个列表好看一点:
game_stats =[if_lose,direction,num,food]
游戏是否结束的状态变量、蛇头方向(1234:上下左右,0为静止)、吃到的食物个数、食物的实例
def going(snakes,snake_color,snake_head_color,lattice_wh,game_stats,food_color,screen): """蛇的移动和转向问题""" # 初始状态,不需要移动 if not game_stats[1]: return # 预测位置 (x,y) = snakes[0].forecast(game_stats[1]) # 撞到边界 if x == -lattice_wh or x == 25*lattice_wh or y == -lattice_wh or y == 25*lattice_wh: game_stats[0] = 0 return # 吃到食物 if (x,y) == (game_stats[3].x,game_stats[3].y): head = Snake(snake_color,snake_head_color,x,y,lattice_wh) snakes.insert(0,head) game_stats[2] += 1 game_stats[3] = create_food(food_color,screen,lattice_wh,snakes) return # 撞到蛇身 for i in snakes: if (x,y) == (i.rect.x,i.rect.y): game_stats[0] = 0 return # 都没有,就正常移动 for i in range(len(snakes)-1,0,-1): snakes[i].rect.x = snakes[i-1].rect.x snakes[i].rect.y = snakes[i-1].rect.y snakes[0].move(game_stats[1])
这里的正常移动,我们是否可以这样写?snake[i] = snakes[i-1
这样是不行的,在python中,赋值是将地址赋值过去,所以实际上我们是将两个实例指向一个地址。
对于snakes[1],当我们指向snakes[0],然后修改snakes[0]之后,两者会合并为一个,而整个蛇身就会缺失一部分。
按键感应
对于蛇方向的控制,我们是通过上下左右四个按键实现的,所以我们还需要修改一下check_events。
先说明一下,这里我没有使用正常的if-elif对每一个方向进行判断,其实都一样的。
首先,蛇不能在向上的情况下按向下,所以是有一个方向冲突的,拿小本本记下来。
# 方向冲突conflict = { pygame.K_RIGHT:4, pygame.K_LEFT :3, pygame.K_UP :1, pygame.K_DOWN :2, 0:0, # 这个纯属凑数,问题不大 1:2, 2:1, 3:4, 4:3}
事件检测:
def check_events(game_stats,conflict,snakes,snake_color,snake_head_color, lattice_wh,food_color,screen): for event in pygame.event.get(): if event.type == pygame.KEYDOWN: # 按键匹配 if event.key in conflict: ret = conflict[event.key] # 判断我们输入的方向和当前方向是否冲突,不冲突就可以修改,然后赋值 if conflict[ret] != game_stats[1]: game_stats[1] = ret # 调用移动函数 going(snakes,snake_color,snake_head_color, lattice_wh,game_stats,food_color,screen) elif event.type == pygame.QUIT: sys.exit()
(这部分,其实改变方向不使用going,也没什么问题)
整合部分
剩下的工作,就是将整体串起来。
换掉了之前的time.sleep,改成了设置帧率。
import pygamefrom fuc import *from snake import Snakefrom time import sleepfrom food import Food# 基本属性lattice_wh = 20 #长宽snake_color = (84, 255, 159)snake_head_color = (123, 104, 238)food_color = (255, 64, 64)# 绘制界面pygame.init()screen = pygame.display.set_mode((25*lattice_wh,25*lattice_wh))pygame.display.set_caption('贪吃蛇')# 设置帧率FPS=10level = 0.9 # 每吃掉一个,间隔时间缩短系数FPSClock=pygame.time.Clock()if_lose = 1if_food = 1# 蛇的方向direction = 0# 得分,吃一个一分num = 0# 蛇头&1个蛇身snakes = []snakes.append(Snake(snake_color,snake_head_color,lattice_wh,24*lattice_wh,lattice_wh))snakes.append(Snake(snake_color,snake_head_color,0,24*lattice_wh,lattice_wh))# 食物food = create_food(food_color,screen,lattice_wh,snakes)# 游戏状态打包game_stats =[if_lose,direction,num,food]# 方向冲突conflict = { pygame.K_RIGHT:4, pygame.K_LEFT :3, pygame.K_UP :1, pygame.K_DOWN :2, 0:0, 1:2, 2:1, 3:4, 4:3}while game_stats[0]: update(screen,lattice_wh,snakes,game_stats) check_events(game_stats,conflict,snakes,snake_color,snake_head_color, lattice_wh,food_color,screen) going(snakes,snake_color,snake_head_color,lattice_wh,game_stats,food_color,screen) FPSClock.tick(FPS* level**num)
然后修改一下update函数:
def update(screen,lattice_wh,snakes,game_stats): """屏幕刷新""" # 背景颜色 screen.fill((255,255,255)) # 画蛇,需要先画,不然网格会被盖住 pygame.draw.rect(screen,snakes[0].head_color,snakes[0].rect) for i in range(1,len(snakes)): pygame.draw.rect(screen,snakes[i].color,snakes[i].rect) # 绘制网格 for i in range(25): pygame.draw.line(screen,(105, 105, 105),(0,lattice_wh*i),(500,lattice_wh*i)) for i in range(25): pygame.draw.line(screen,(105, 105, 105),(lattice_wh*i,0),(lattice_wh*i,500)) # 绘制食物 game_stats[3].draw() pygame.display.flip()
到此,关于"python中怎么用pygame实现贪吃蛇游戏"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!