Pygame实现自定义的生命游戏
2021-12-31
仅是尝试,还有待提高(v0)。
主要目的:想了解如何交互,获取鼠标点击位置并进行相应操作。
此次生命游戏的规则: 每一轮用户通过鼠标点击增加一个细胞; 所有细胞向其八邻域中的一个分裂新细胞; 细胞的八邻域若多于3个细胞,则认为营养不足、毒素增多,该细胞凋亡; 细胞最多只能存活三轮。
1 引入需要的包
import os
import sys
import time
import pygame
import random
import numpy as np
2 定义生命游戏
def count_score(current_cells):
'''
现在存在的细胞总数
'''
return np.sum(current_cells)
def add_new_cell(x,y,current_cells):
'''
加入一个新细胞
'''
current_cells[x][y] = 1
def add_cells_lives(current_cells,cells_life):
'''
对所有细胞增加细胞周期
'''
for i in range(len(cells_life)):
for j in range(len(cells_life[0])):
if(current_cells[i][j]==1):
cells_life[i][j] = cells_life[i][j]+1
def cells_death1(current_cells,cells_life):
'''
进行细胞凋亡操作(细胞活多于3周期,则死亡)
'''
for i in range(len(cells_life)):
for j in range(len(cells_life[0])):
if(cells_life[i][j] > 3):
cells_life[i][j] = 0
current_cells[i][j] = 0
def cells_death2(current_cells,cells_life):
'''
进行细胞凋亡操作(细胞周围八邻域多于3个细胞,则死亡)
'''
xn = [-1,-1,-1,0,1,1,1,0]
yn = [1,0,-1,-1,-1,0,1,1]
for i in range(len(current_cells)):
for j in range(len(current_cells[0])):
if(current_cells[i][j]==1):
count_n_cells = 0
for k in range(8):
xx = i+xn[k]
yy = j+yn[k]
if(xx>=0 and xx<len(current_cells) and yy>=0 and yy<len(current_cells[0]) and current_cells[xx][yy]==1):
count_n_cells += 1
if(count_n_cells>3):
current_cells[i][j] = 0
cells_life[i][j] = 0
def cells_division(current_cells):
'''
细胞分裂(细胞周围如果有空位,则分裂)(简便起见,先检测到哪就往哪分裂)
'''
xn = [-1,-1,-1,0,1,1,1,0]
yn = [1,0,-1,-1,-1,0,1,1]
for i in range(len(current_cells)):
for j in range(len(current_cells[0])):
if(current_cells[i][j]==1):
for k in range(8):
xx = i+xn[k]
yy = j+yn[k]
if(xx >=0 and xx<len(current_cells) and yy>=0 and yy<len(current_cells[0]) and current_cells[xx][yy]==0):
current_cells[xx][yy] = 2
break
for i in range(len(current_cells)):
for j in range(len(current_cells[0])):
if(current_cells[i][j]==2):
current_cells[i][j] = 1
def one_circle(x,y,current_cells,cells_life):
'''
一次交互,增加细胞,细胞分裂,细胞凋亡
'''
if(current_cells[x][y]==1):
return
else:
add_new_cell(x, y, current_cells)
cells_division(current_cells)
add_cells_lives(current_cells,cells_life)
cells_death1(current_cells,cells_life)
cells_death2(current_cells,cells_life)
score = count_score(current_cells)
print(score)
3 定义游戏的相关信息
WIDTH = 700
HEIGHT = 700
NUMGRID = 16
GRIDSIZE = 36
XMARGIN = (WIDTH - NUMGRID*GRIDSIZE) // 2
YMARGIN = (HEIGHT - NUMGRID*GRIDSIZE) // 2
score = 0
current_cells = np.zeros((NUMGRID,NUMGRID))
cells_life = np.zeros((NUMGRID,NUMGRID))
用于判断鼠标点击的方格位置:
BOARDRECTS = []
for x in range(WIDTH):
BOARDRECTS.append([])
for y in range(HEIGHT):
r = pygame.Rect((XMARGIN+x*GRIDSIZE),(YMARGIN+y*GRIDSIZE),GRIDSIZE,GRIDSIZE)
BOARDRECTS[x].append(r)
def CheckValidClick(pos):
'''
检查点击是否在面板上
'''
for x in range(WIDTH):
for y in range(HEIGHT):
if(BOARDRECTS[x][y].collidepoint(pos[0],pos[1])):
ans = [x,y]
return ans
return None
准备细胞图片和输出信息:
CELL = pygame.image.load('C:\\Users\\Administrator\\Desktop\\cell.jpg')
CELL = pygame.transform.scale(CELL, (GRIDSIZE-2,GRIDSIZE-2))
CELLNUMS = 0
ROUND = 0
SCORE = 0
POS1 = [20,20]
POS2 = [300,20]
POS3 = [520,20]
pygame.font.init()
font1 = pygame.font.Font(None,30)
4 游戏初始设置
pygame.init()
screen = pygame.display.set_mode((WIDTH,HEIGHT))
pygame.display.set_caption('Life Game')
screen.fill((255,255,220))
for x in range(NUMGRID):
for y in range(NUMGRID):
rect = pygame.Rect((XMARGIN+x*GRIDSIZE,YMARGIN+y*GRIDSIZE,GRIDSIZE,GRIDSIZE))
pygame.draw.rect(screen,(255,165,0),rect,2)
pygame.display.flip()
pygame.display.update()
5 游戏主循环
CLICKX = None
CLICKY = None
while True:
screen.fill((255,255,220))
for x in range(NUMGRID):
for y in range(NUMGRID):
rect = pygame.Rect((XMARGIN+x*GRIDSIZE,YMARGIN+y*GRIDSIZE,GRIDSIZE,GRIDSIZE))
pygame.draw.rect(screen,(255,165,0),rect,2)
ClickedSpace = None
for event in pygame.event.get():
if(event.type==pygame.QUIT):
pygame.quit()
sys.exit()
elif(event.type==pygame.MOUSEBUTTONDOWN):
CLICKX,CLICKY = event.pos
print(CLICKX,CLICKY)
elif(event.type==pygame.MOUSEBUTTONUP):
if(event.pos==(CLICKX,CLICKY)):
ClickedSpace = CheckValidClick(event.pos)
print('ClickedSpace: ',ClickedSpace)
if(ClickedSpace!=None):
if(current_cells[ClickedSpace[0]][ClickedSpace[1]]==1):
continue
one_circle(ClickedSpace[0],ClickedSpace[1], current_cells, cells_life)
CELLNUMS = count_score(current_cells)
ROUND = ROUND+1
SCORE = CELLNUMS + ROUND
surface1 = font1.render('Cellnums: %d'%CELLNUMS,1,(125,125,255))
surface2 = font1.render('Round: %d'%ROUND,1,(125,125,255))
surface3 = font1.render('Score: %d'%SCORE,1,(125,125,255))
screen.blit(surface1,POS1)
screen.blit(surface2,POS2)
screen.blit(surface3,POS3)
pygame.display.update()
for i in range(NUMGRID):
for j in range(NUMGRID):
if(current_cells[i][j]==1):
screen.blit(CELL,(BOARDRECTS[i][j][0],BOARDRECTS[i][j][1]))
pygame.display.update()
pygame.display.flip()
不足之处:
1、游戏的规则可以继续改进:比如只改变点击点周围的细胞的情况等。不管怎么点都不会得到一个差的结果,规则设置得没有让人思考的欲望; 2、采用每个循环都重新绘制,可以寻找动态显示出细胞分裂、凋亡的方法。
学习到的点:
1、pygame需要在循环中不断获取事件,不断更新,以达到动态游戏的目的。所以,如果没有这一步,窗口会显示无响应。 2、显示图像:先创建surface,再blit,再update。 3、获取鼠标点击相应位置的方法。
|