import pygame,sys,random
from pygame.locals import *
pygame.init()
font36=pygame.font.SysFont('simhei',36)
font60=pygame.font.SysFont('simhei',60)
class Me(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = font36.render('孙启铭',True,(0,0,0))
self.rect = self.image.get_rect()
self.rect.center = width//2 ,height//2
self.德 = 10
self.智 = 10
self.体 = 10
self.美 = 10
self.劳 = 10
self.金币 = 0
self.压力 = 10
self.年龄 = 6
self.lasttime =0
def update(self):
now = pygame.time.get_ticks()
key = pygame.key.get_pressed()
if now - self.lasttime >50:
self.lasttime =now
if key[K_w]:
self.rect.y -=5
elif key[K_s]:
self.rect.y +=5
elif key[K_a]:
self.rect.x -=5
elif key[K_d]:
self.rect.x +=5
class 建筑物(pygame.sprite.Sprite):
def __init__(self,name,x,y):
pygame.sprite.Sprite.__init__(self)
self.image = font60.render(name,True,(0,0,0))
self.rect = self.image.get_rect()
self.rect.topleft = x,y
self.name = name #为了精灵组的检测
allgroup.add(self)
#创建一个宽800高600的窗口 背景颜色是白色 #
size=width,height=800,600
screen = pygame.display.set_mode(size)
bg=255,255,255
me=Me()
back=False
allgroup = pygame.sprite.Group()
#学校 广场 黄兴体育馆 补习班 剧场 打工中心 乐博乐博 小卖部 博物馆 奶奶家
学校=建筑物('学校',0,0)
公园=建筑物('公园',150,0)
黄兴体育馆=建筑物('江湾体育场',290,0)
奶奶家=建筑物('奶奶家',610,0)
补习班=建筑物('补习班',0,520)
澡堂=建筑物('澡堂',200,520)
打工中心=建筑物('打工中心',350,520)
博物馆=建筑物('博物馆',600,520)
乐博乐博=建筑物('乐博乐博',0,280)
小卖部=建筑物('小卖部',600,280)
def 显示文字(text,x,y):
image=font36.render(text,True,(0,0,0))
screen.blit(image,(x,y))
次数 = 0
while True:
if 次数 == 5:
次数 = 0
me.年龄 += 1
启动 = False
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_TAB:
back = True
if event.key == K_j:
启动=True
if back:
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_TAB:
back = False
if not back:
break
screen.fill(bg)
显示文字('孙启铭的详细属性:',250,20)
显示文字(f'德:{me.德}', 100, 100)
显示文字(f'智:{me.智}', 100, 150)
显示文字(f'体:{me.体}', 100, 200)
显示文字(f'美:{me.美}', 100, 250)
显示文字(f'劳:{me.劳}', 100, 300)
显示文字(f'金币:{me.金币}', 100, 350)
显示文字(f'压力:{me.压力}', 100, 400)
显示文字(f'年龄:{me.年龄}', 100, 450)
pygame.display.update()
screen.fill(bg)
screen.blit(me.image,me.rect) #
me.update()
#
allgroup.draw(screen)
allgroup.update()
hit = pygame.sprite.spritecollide(me,allgroup,False) #新的
if hit:
if hit[0].name =='学校' and 启动:
次数+=1
while 启动:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_k:
启动 = False
screen.fill((255,255,0))
pygame.display.update()
#摁下 k键返回街区
if hit[0].name =='公园' and 启动:
次数 += 1
while 启动:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_k:
启动 = False
screen.fill((0,255,0))
pygame.display.update()
if hit[0].name =='江湾体育场' and 启动:
次数 += 1
me.rect.center=width//2,height//2
data=0
计时器=pygame.time.get_ticks()
image = font36.render('',True,(0,0,0))
计时 = True
while 启动:
if me.rect.top <= 0 and 计时:
计时=False
ttime=pygame.time.get_ticks()-计时器
# print(ttime) #
image=font36.render(f"用时:{ttime/1000}秒",True,(0,0,0))
if ttime<=7000:
me.体+=5
me.美+=1
elif ttime <= 10000:
me.体+=4
me.美+=1
elif ttime <= 15000:
me.体 += 3
elif ttime <= 20000:
me.体 += 2
else:
me.体 += 1
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_g:
data+=1
if data>=2:
me.rect.y += 5
if event.key == K_h:
data-=1
if data==0:
me.rect.y-=5
else:
data=0
me.rect.y+=5
if event.key == K_k:
启动 = False
screen.fill((255,0,0))
screen.blit(me.image, me.rect)
rect = image.get_rect()
rect.center = width // 2, height // 2
screen.blit(image, rect)
pygame.display.update()
if hit[0].name =='奶奶家' and 启动:
次数 += 1
while 启动:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_k:
启动 = False
screen.fill((255,100,0))
pygame.display.update()
if hit[0].name =='乐博乐博' and 启动:
次数 += 1
while 启动:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_k:
启动 = False
screen.fill((100,100,255))
pygame.display.update()
if hit[0].name =='小卖部' and 启动:
次数 += 1
while 启动:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_k:
启动 = False
screen.fill((218,165,32))
pygame.display.update()
if hit[0].name =='澡堂' and 启动:
次数 += 1
while 启动:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_k:
启动 = False
screen.fill((50,100,200))
pygame.display.update()
if hit[0].name =='补习班' and 启动:
次数 += 1
while 启动:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_k:
启动 = False
screen.fill((0,0,0))
pygame.display.update()
if hit[0].name =='打工中心' and 启动:
次数 += 1
while 启动:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_k:
启动 = False
screen.fill((88,88,88))
pygame.display.update()
if hit[0].name =='博物馆' and 启动:
次数 += 1
while 启动:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_k:
启动 = False
screen.fill((210,180,140))
pygame.display.update()
pygame.display.update()
我们的角色
这个游戏我们为了节约导入图片素材的时间。所以计划所有的角色都用pygame的文字对象来进行实现,我们计划设计出一个 简易街区。里面包含了同学们从小到大都会遇到的一些建筑物(比喻学校 ,补习班,体育馆,乐博乐博hhhh),然后再创建一个可以移动的文字角色 包含德智体美劳等属性,通过角色和建筑物的交互进入不同的游戏完成以后可以获得各种属性。在若干个回合以后我们结合属性权值让他步入一所对应的大学。让同学们来体验一下养自己的过程。
from pygame.locals import *
import pygame,sys
pygame.init() #初始化
font36=pygame.font.SysFont('simhei',36)
class Me(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = font36.render('嘻嘻老师',True,(0,0,0))
self.photo = pygame.image.load(r'hmbb.jpg')
self.rect = self.image.get_rect()
self.rect.center = width//2,height//2
self.德 = 0
self.智 = 1
self.体 = 10
self.美 = 0
self.劳 = 0
self.金币 = 0
self.压力 = 0
self.lasttime = 0
def update(self):
now = pygame.time.get_ticks() #获取实时的时间
key = pygame.key.get_pressed() #键盘轮询
if now-self.lasttime > 50:
self.lasttime = now
if key[K_w]:
self.rect.y -=5
elif key[K_s]:
self.rect.y +=5
elif key[K_a]:
self.rect.x -=5
elif key[K_d]:
self.rect.x +=5
这里没有做边界处理大家可以自己尝试一下。这个边界就当是一个小bug来,可以做一个一键回到中心这样子也可以完成归位的任务。我们这个界面当中是没有做显示自己属性部分的,我们在这里需要使用一个额外的摁键来打开一个新的窗口来显示我们的属性。
不同界面窗口的设计
我们平时在玩游戏的时候经常会在游戏内打开多个新窗口(狗头),进行例如背包,属性查看,甚至下副本,结合pygame的画面显示机制以及我的理解,我准备做一个窗口内容的重绘。既然是重绘我们就要先复习一下 。窗口主循环绘制游戏角色是怎样的:
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
screen.fill()
screen.blit() or allgroup.draw()
pygame.display.update()
pygame他是需要把 背景的填充 角色的填充放到主循环里面来,通过pygame.display.update()中函数来进行不断刷新的。在循环中加上角色的update()就可以实现移动的效果了。贴上了屏幕显示详细教程
我在这里做了一个很蠢的事情,我创建了一个子循环。创建了一个back变量来控制被这个界面出现与否。然后就是这个子循环了! 这个循环里面我们会展现一个属性的显示界面,小小的设计了一下
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_TAB:
back = True
if back:
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_TAB:
back = False
if not back:
break
screen.fill(bg)
文字显示('嘻嘻老师的详细属性:',50,0)
文字显示(f'压力:{me.压力}', 450, 50)
文字显示(f'德:{me.德}', 450, 100)
文字显示(f'智:{me.智}', 450, 150)
文字显示(f'体:{me.体}',450, 200)
文字显示(f'美:{me.美}', 450, 250)
文字显示(f'劳:{me.劳}', 450, 300)
文字显示(f'金币:{me.金币}', 450, 350)
screen.blit(me.photo,(100,60))
pygame.display.update()
screen.fill(bg)
screen.blit(me.image,me.rect)
me.update()
pygame.display.update()
这样子通过 tap键可以控制 我们在主游戏界面和属性详情界面之间进行来回切换哩
街区的创建
街区的创建就稍微的肝了一点点真的就是一点点,里面比较有意义的就是和同学们对自己从小到大的遇到地方进行回顾,同学们的生活真的是太丰富了,这里我做了一个精灵组来对这些建筑物进行统一的管理。
class 建筑物(pygame.sprite.Sprite):
def __init__(self,name,x,y):
pygame.sprite.Sprite.__init__(self)
self.image = font60.render(name,True,(0,0,0))
self.rect = self.image.get_rect()
self.rect.topleft = x,y
self.name = name
allgroup.add(self)
这里再设计动画精灵的时候把位置和 name信息都留给我们再实例化的时候去做。name这个属性我是准备在后面做碰撞检测时候用来判断建筑物所以留了一手。接下来只要把建筑物肝出来就可以了,按照这个方法肝出整个五角场街道不是梦。
学校=建筑物('学校',0,0)
公园=建筑物('公园',150,0)
黄兴体育馆=建筑物('江湾体育场',290,0)
奶奶家=建筑物('奶奶家',610,0)
补习班=建筑物('补习班',0,520)
澡堂=建筑物('澡堂',200,520)
打工中心=建筑物('打工中心',350,520)
博物馆=建筑物('博物馆',600,520)
乐博乐博=建筑物('乐博乐博',0,280)
小卖部=建筑物('小卖部',600,280)
在街道做完了以后我就要去考虑设计整个街区每个建筑物的进入系统了,我本想通过一个函数或者一个子模块来封装的,但是在测试时候出了一些问题,为了赶上周末的课程,我继续借鉴了属性查看界面的进入方式 。。。所以这个代码在这个阶段就已经肉眼可见的肝了起来。先说一下进入机制然后再贴代码,和属性界面一样我们设计了一个bool变量来表示是否进入,玩家需要控制角色走到和对应建筑物重合的地方,然后再按下 j键就可以进入里面的场景了,这里实现会用到的pygame子模块大家可以先脑部一下。。。我先贴一张帅照在这里
是pygame的event 事件子模块 和 sprite子模块,在这里我们要做动画精灵的碰撞检测和按键检测两边代码写比较远就分别贴出来了
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_TAB:
back = True
if event.key == K_j:
启动=True
hit = pygame.sprite.spritecollide(me,allgroup,False) #新的
if hit:
if hit[0].name =='学校' and 启动:
次数+=1
while 启动:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_k:
启动 = False
screen.fill((255,255,0))
pygame.display.update()
没错这里又有一个循环!十个建筑没错我在后面做了十个循环,在循环中再加上键盘k键的侦测,要是碰到了k键我们会将循环结束进入到主循环里面去。后续计划在进入建筑以后每个建筑都会有一个对应的小游戏,目前已经在江湾体育场里面布置了一个小游戏了最后贴上源码。项目内的小游戏之后再来分析。
import pygame,sys,random
from pygame.locals import *
pygame.init()
font36=pygame.font.SysFont('simhei',36)
font60=pygame.font.SysFont('simhei',60)
class Me(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = font36.render('孙启铭',True,(0,0,0))
self.rect = self.image.get_rect()
self.rect.center = width//2 ,height//2
self.德 = 10
self.智 = 10
self.体 = 10
self.美 = 10
self.劳 = 10
self.金币 = 0
self.压力 = 10
self.年龄 = 6
self.lasttime =0
def update(self):
now = pygame.time.get_ticks()
key = pygame.key.get_pressed()
if now - self.lasttime >50:
self.lasttime =now
if key[K_w]:
self.rect.y -=5
elif key[K_s]:
self.rect.y +=5
elif key[K_a]:
self.rect.x -=5
elif key[K_d]:
self.rect.x +=5
class 建筑物(pygame.sprite.Sprite):
def __init__(self,name,x,y):
pygame.sprite.Sprite.__init__(self)
self.image = font60.render(name,True,(0,0,0))
self.rect = self.image.get_rect()
self.rect.topleft = x,y
self.name = name #为了精灵组的检测
allgroup.add(self)
#创建一个宽800高600的窗口 背景颜色是白色 #
size=width,height=800,600
screen = pygame.display.set_mode(size)
bg=255,255,255
me=Me()
back=False
allgroup = pygame.sprite.Group()
#学校 广场 黄兴体育馆 补习班 剧场 打工中心 乐博乐博 小卖部 博物馆 奶奶家
学校=建筑物('学校',0,0)
公园=建筑物('公园',150,0)
黄兴体育馆=建筑物('江湾体育场',290,0)
奶奶家=建筑物('奶奶家',610,0)
补习班=建筑物('补习班',0,520)
澡堂=建筑物('澡堂',200,520)
打工中心=建筑物('打工中心',350,520)
博物馆=建筑物('博物馆',600,520)
乐博乐博=建筑物('乐博乐博',0,280)
小卖部=建筑物('小卖部',600,280)
def 显示文字(text,x,y):
image=font36.render(text,True,(0,0,0))
screen.blit(image,(x,y))
次数 = 0
while True:
if 次数 == 5:
次数 = 0
me.年龄 += 1
启动 = False
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_TAB:
back = True
if event.key == K_j:
启动=True
if back:
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_TAB:
back = False
if not back:
break
screen.fill(bg)
显示文字('孙启铭的详细属性:',250,20)
显示文字(f'德:{me.德}', 100, 100)
显示文字(f'智:{me.智}', 100, 150)
显示文字(f'体:{me.体}', 100, 200)
显示文字(f'美:{me.美}', 100, 250)
显示文字(f'劳:{me.劳}', 100, 300)
显示文字(f'金币:{me.金币}', 100, 350)
显示文字(f'压力:{me.压力}', 100, 400)
显示文字(f'年龄:{me.年龄}', 100, 450)
pygame.display.update()
screen.fill(bg)
screen.blit(me.image,me.rect) #
me.update()
#
allgroup.draw(screen)
allgroup.update()
hit = pygame.sprite.spritecollide(me,allgroup,False) #新的
if hit:
if hit[0].name =='学校' and 启动:
次数+=1
while 启动:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_k:
启动 = False
screen.fill((255,255,0))
pygame.display.update()
#摁下 k键返回街区
if hit[0].name =='公园' and 启动:
次数 += 1
while 启动:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_k:
启动 = False
screen.fill((0,255,0))
pygame.display.update()
if hit[0].name =='江湾体育场' and 启动:
次数 += 1
me.rect.center=width//2,height//2
data=0
计时器=pygame.time.get_ticks()
image = font36.render('',True,(0,0,0))
计时 = True
while 启动:
if me.rect.top <= 0 and 计时:
计时=False
ttime=pygame.time.get_ticks()-计时器
# print(ttime) #
image=font36.render(f"用时:{ttime/1000}秒",True,(0,0,0))
if ttime<=7000:
me.体+=5
me.美+=1
elif ttime <= 10000:
me.体+=4
me.美+=1
elif ttime <= 15000:
me.体 += 3
elif ttime <= 20000:
me.体 += 2
else:
me.体 += 1
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_g:
data+=1
if data>=2:
me.rect.y += 5
if event.key == K_h:
data-=1
if data==0:
me.rect.y-=5
else:
data=0
me.rect.y+=5
if event.key == K_k:
启动 = False
screen.fill((255,0,0))
screen.blit(me.image, me.rect)
rect = image.get_rect()
rect.center = width // 2, height // 2
screen.blit(image, rect)
pygame.display.update()
if hit[0].name =='奶奶家' and 启动:
次数 += 1
while 启动:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_k:
启动 = False
screen.fill((255,100,0))
pygame.display.update()
if hit[0].name =='乐博乐博' and 启动:
次数 += 1
while 启动:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_k:
启动 = False
screen.fill((100,100,255))
pygame.display.update()
if hit[0].name =='小卖部' and 启动:
次数 += 1
while 启动:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_k:
启动 = False
screen.fill((218,165,32))
pygame.display.update()
if hit[0].name =='澡堂' and 启动:
次数 += 1
while 启动:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_k:
启动 = False
screen.fill((50,100,200))
pygame.display.update()
if hit[0].name =='补习班' and 启动:
次数 += 1
while 启动:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_k:
启动 = False
screen.fill((0,0,0))
pygame.display.update()
if hit[0].name =='打工中心' and 启动:
次数 += 1
while 启动:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_k:
启动 = False
screen.fill((88,88,88))
pygame.display.update()
if hit[0].name =='博物馆' and 启动:
次数 += 1
while 启动:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_k:
启动 = False
screen.fill((210,180,140))
pygame.display.update()
pygame.display.update()