您现在的位置是:首页 >技术杂谈 >基于pygame开发——模拟人生游戏 网站首页技术杂谈

基于pygame开发——模拟人生游戏

想昵称是一件头疼的事 2025-02-21 12:01:02
简介基于pygame开发——模拟人生游戏

在掌握pygame的部分模块功能了以后应该如何来整一个大活呢!!那就来做一个完整的游戏吧!!传统的游戏开发除了要依靠程序员以外,对于图像素材的需求也是让大家在做游戏时候望而生畏的部分,我们在这个项目中所以的游戏角色都会以文字角色来实现,创建一个名副其实的文字游戏。那做什么主题的游戏呢!同学们在长大的过程中经常会抱怨自己不够自由,那就让我们来制作一个模拟人生的游戏吧,来自己决定自己的"人生"!


        首先我们来构建自己的主角,主角的构建去继承pygame的动画精灵,对于游戏角色的创建最重要的是角色图像和位置对象!因为本游戏是文字游戏所以我们不会通过导入的方式来进行图像的创建!而是通过pygame的font模块来渲染出来角色图像!在项目中角色图像的渲染会反复使用所以最好提前写一个函数来进行封装!

def wst(size,text):#文生图
    font=pygame.font.SysFont('SimHei',size) #系统默认黑体mac电脑可能需要更换 
    image=font.render(text,True,(0,0,0))
    return image

这个函数我们只需要提供的参数分别是文字内容和文字像素大小,返回的是图像surface对象啦

有了这个以后我们就可以进行主角的创建啦!主角的成长除了需要合理的培养德智体美劳这些属性以外,我们还加入了金币和压力这些有趣的属性,提升我们游戏的趣味性,金币可以给我们的游戏带来商城系统,压力可以给让玩家在刷属性的过程中需要考虑劳逸结合,除了上述的属性以外,我们还添加了移动的能力,并且设置了三个街区让主角可以充分撒野!与此同时还做了范围约束

class Me(pygame.sprite.Sprite):
    def __init__(self): #初始化
        pygame.sprite.Sprite.__init__(self)#初始化
        self.image=wst(30,'嘻嘻老师')
        self.rect = self.image.get_rect()
        self.rect.center = 400,300
        self.index = 0 #角色当前在第几个街区
        self.d = 0 #德
        self.z = 10 #智
        self.t = 0 #体
        self.m = 0 #美
        self.l = 0 #劳
        self.yl = 0 #压力
        self.jb = 0 #金币
        self.age = 0 #年龄
        #请你把位置的中心设为 屏幕的中间
    def update(self):
        key=pygame.key.get_pressed()
        ##请你设置上下移动的限制,向上下移动到边缘就不能动了
        if key[K_UP]and self.rect.top>=0:
            self.rect.y-=5
        if key[K_DOWN] and self.rect.bottom<=600:
            self.rect.y+=5
        if key[K_LEFT]: #
            self.rect.x-=5
            if self.rect.left<0 and self.index==-1:
                self.rect.left=0
            if self.rect.right<0:
                self.rect.left=800
                self.index-=1
        if key[K_RIGHT]:
            self.rect.x+=5
            if self.rect.right>800 and self.index==1:
                self.rect.right=800
            if self.rect.left>800:
                self.rect.right=0
                self.index+=1

主角创建完毕了以后我们来创建一下主角生活的‘街区’有不同建筑物所构成的街区!主角进入不同的建筑物可以获得不同属性的提升!

class Building(pygame.sprite.Sprite):
    def __init__(self,name,x,y):#初始化
        pygame.sprite.Sprite.__init__(self)#初始化
        self.image=wst(50,name)
        self.rect = self.image.get_rect()
        self.rect.center = x,y
        self.name =name #请你把位置的中心设为 屏幕的中间
b1=[Building('学校',100,100),Building('家',300,100),Building('黄兴公园',500,100),
    Building('补习班',100,500),Building('银行',300,500),Building('斯坦星球',500,500)]
b2=[Building('科技馆',100,100),Building('游乐场',300,100),Building('江湾体育场',600,100),
    Building('动物园',100,500),Building('电影院',300,500),Building('万达广场',500,500)]
b3=[Building('少科站',100,100),Building('小卖部',300,100),Building('志愿者服务站',650,100),
    Building('鬼屋',100,500),Building('打工中心',300,500),Building('游泳馆',550,500)]

在上述代码中我们通过创建了一个叫做Buliding的类来实例化建筑物,后期会通过动画精灵组来把这三个列表(b1,b2,b3)中的成员进行批量化的管理。Building('学校',100,100) 中分别需要给入建筑物的名字以及x,y的位置信息!在这里我们可以通过调整x,y两个参数进行一定的布局管理。

然后再稍微的配置一些变量就可以得到1.0版本的游戏了

import pygame,sys,random
from pygame.locals import *
pygame.init()
count=0 #次数
def wst(size,text):#文生图
    font=pygame.font.SysFont('SimHei',size)
    image=font.render(text,True,(0,0,0))
class Me(pygame.sprite.Sprite):
    def __init__(self): #初始化
        pygame.sprite.Sprite.__init__(self)#初始化
        self.image=wst(30,'嘻嘻老师')
        self.rect = self.image.get_rect()
        self.rect.center = 400,300
        self.index = 0 #角色当前在第几个街区
        self.speed1=5
        self.speed2=5
        self.d = 0
        self.z = 10
        self.t = 0
        self.m = 0
        self.l = 0
        self.yl = 0 #压力
        self.jb = 0 #金币
        self.age = 0 #年龄
        #请你把位置的中心设为 屏幕的中间
    def update(self):
        key=pygame.key.get_pressed()
        ##请你设置上下移动的限制,向上下移动到边缘就不能动了
        if key[K_UP]and self.rect.top>=0:
            self.rect.y-=5
        if key[K_DOWN] and self.rect.bottom<=600:
            self.rect.y+=5
        if key[K_LEFT]: #
            self.rect.x-=5
            if self.rect.left<0 and self.index==-1:
                self.rect.left=0
            if self.rect.right<0:
                self.rect.left=800
                self.index-=1
        if key[K_RIGHT]:
            self.rect.x+=5
            if self.rect.right>800 and self.index==1:
                self.rect.right=800
            if self.rect.left>800:
                self.rect.right=0
                self.index+=1
class Building(pygame.sprite.Sprite):
    def __init__(self,name,x,y):#初始化
        pygame.sprite.Sprite.__init__(self)#初始化
        self.image=wst(50,name)
        self.rect = self.image.get_rect()
        self.rect.center = x,y
        self.name =name #请你把位置的中心设为 屏幕的中间
b1=[Building('学校',100,100),Building('家',300,100),Building('黄兴公园',500,100),
    Building('补习班',100,500),Building('银行',300,500),Building('斯坦星球',500,500)]
b2=[Building('科技馆',100,100),Building('游乐场',300,100),Building('江湾体育场',600,100),
    Building('动物园',100,500),Building('电影院',300,500),Building('万达广场',500,500)]
b3=[Building('少科站',100,100),Building('小卖部',300,100),Building('志愿者服务站',650,100),
    Building('鬼屋',100,500),Building('打工中心',300,500),Building('游泳馆',550,500)]
size=width,height=800,600
screen = pygame.display.set_mode(size)
pygame.display.set_caption('人生模拟器')
bg=200,200,200
me=Me() #########
clock=pygame.time.Clock()
allgroup=pygame.sprite.Group()#精灵组
while True:
    if me.index == 0:
        for i in allgroup: #先清空所有建筑
            i.kill() #杀掉这个角色
        for i in b1: #再添加新的建筑
            allgroup.add(i)
    if me.index == -1:
        for i in allgroup: #先清空所有建筑
            i.kill() #杀掉这个角色
        for i in b2: #再添加新的建筑
            allgroup.add(i)
    if me.index == 1:
        for i in allgroup: #先清空所有建筑
            i.kill() #杀掉这个角色
        for i in b3: #再添加新的建筑
            allgroup.add(i)
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        if event.type == KEYDOWN:
            
            if event.key == K_SPACE:
                #继续进行碰撞检测判断
                a=pygame.sprite.spritecollide(me,allgroup,False)
                if a:
                    进入地图(a[0].name)#如果你碰到了建筑物又摁下了空格调用这个函数

    screen.fill(bg)
    screen.blit(me.image,me.rect)###############
    me.update()########################
    allgroup.draw(screen) #绘制精灵组
    pygame.display.update()

然后我们大致就会获得一个这样子的代码效果!可以逛来逛去了!,目前我们把角色都"码"在了窗口上,但是对于游戏来说,玩家和游戏的互动也非常的重要,我们通过按键以及角色之间碰撞检测来实现互动的效果!

我们在 触发了KEYDOWN事件了以后增加了 一个摁下TAB键查看属性,还有是摁下了空格以及接触到了建筑物触发进入建筑物这个函数 PS查看属性可以做一个界面

        if event.type == KEYDOWN:
            if event.key == K_TAB:
                print(f"""
                        你的年龄是{me.age}岁
                        你的德智体美劳分别是{me.d},{me.z},{me.t},{me.m},{me.l}
                        压力为{me.yl} 金币为{me.jb}
                      """)
            if event.key == K_SPACE:
                #继续进行碰撞检测判断
                a=pygame.sprite.spritecollide(me,allgroup,False)
                if a:
                    进入地图(a[0].name)#如果你碰到了建筑物又摁下了空格调用这个函数

接下来我们就需要来设计一下进入地图这个函数! 在这里我们可以设计一个小玩法,玩家每进入五个不同的建筑物年级就会长大一岁!然后我们根基玩家进入的建筑物不同,触发随机事件让玩家获得不同属性增加 下面的例子中做的随机比例是1:9  '不好的事件'vs '好的事件'

def 进入地图(name):
    global count
    count += 1
    if count==5:
        me.age+=1
        count=0
    if name=='家':
        bg = 255,0,0
        r=random.randint(1,10)
        if r>=9:
            image = wst(30,'家是温暖的港湾,在家里你获得了全面的属性提升')
            pos = image.get_rect() #获得位置信息
            pos.center = width//2,height//2 #设置位置信息的中点
            me.d += 2  #对于属性的改变
            me.z += 1
            me.t += 1
            me.m += 1
            me.l += 2
            me.yl += 1
            me.jb += 2
        else:
            image = wst(30,'"港湾今天天气有些风浪",你属性受到了全面的影响')
            pos = image.get_rect()  # 获得位置信息
            pos.center = width // 2, height // 2  # 设置位置信息的中点
            me.d -= 2
            me.z -= 1
            me.t -= 1
            me.m -= 1
            me.l -= 2
            me.yl += 3
        while True:
            for event in pygame.event.get():
                if event.type==QUIT:
                    pygame.quit()
                    sys.exit()
            key = pygame.key.get_pressed()
            if key[K_ESCAPE]:
                break
            screen.fill(bg)
            screen.blit(image,pos)
            pygame.display.update()

这边的代码同学可以自行进行扩写 按照 if name == '学校' 这个分支我们可以再根据你的街区中的建筑物的数量来进行扩写!!! 中心思想是每一个地点最好都各有突出的属性增加值 ,不要设计出一个 可以让主角属性全面大幅上涨的地方,这样游戏的趣味性就降低了。最后要设计这个游戏的大结局了,这个游戏的结局我写了一个例子,同学们可以参考一下 这个结局也可以进行一个if 分支扩写! 

    if me.age == 18:
        print('恭喜你成功的长大了!')
        if me.z > 800:
            print('你凭借从小的勤奋学习考入了北京大学!')
        #在这里请返回你想象力给我们的主角根据
        #他的属性值的范围来给予他一个称号
        break
#放在主循环里面

较于游戏的设计过程来说这个结局可能会有些简单,我建议同学们可以在结局中放入各种你们未来想去做的事情!然后再去思考如果我想要做成这件事情需要哪些属性,反向思考再来写条件阈值。最后放上所有的代码内容

import pygame,sys,random
from pycparser.c_ast import Break
from pygame.locals import *
pygame.init()
count=0 #次数
def wst(size,text):#文生图
    font=pygame.font.SysFont('SimHei',size)
    image=font.render(text,True,(0,0,0))
    return image
def 进入地图(name):
    global count
    count += 1
    if count==5:
        me.age+=1
        count=0
    if name=='家':
        bg = 255,0,0
        r=random.randint(1,10)
        if r>=9:
            image = wst(30,'家是温暖的港湾,在家里你获得了全面的属性提升')
            pos = image.get_rect() #获得位置信息
            pos.center = width//2,height//2 #设置位置信息的中点
            me.d += 2  #对于属性的改变
            me.z += 1
            me.t += 1
            me.m += 1
            me.l += 2
            me.yl += 1
            me.jb += 2
        else:
            image = wst(30,'"港湾今天天气有些风浪",你属性受到了全面的影响')
            pos = image.get_rect()  # 获得位置信息
            pos.center = width // 2, height // 2  # 设置位置信息的中点
            me.d -= 2
            me.z -= 1
            me.t -= 1
            me.m -= 1
            me.l -= 2
            me.yl += 3
        while True:
            for event in pygame.event.get():
                if event.type==QUIT:
                    pygame.quit()
                    sys.exit()
            key = pygame.key.get_pressed()
            if key[K_ESCAPE]:
                break
            screen.fill(bg)
            screen.blit(image,pos)
            pygame.display.update()
class Me(pygame.sprite.Sprite):
    def __init__(self): #初始化
        pygame.sprite.Sprite.__init__(self)#初始化
        self.image=wst(30,'嘻嘻老师')
        self.rect = self.image.get_rect()
        self.rect.center = 400,300
        self.index = 0 #角色当前在第几个街区
        self.speed1=5
        self.speed2=5
        self.d = 0
        self.z = 10
        self.t = 0
        self.m = 0
        self.l = 0
        self.yl = 0 #压力
        self.jb = 0 #金币
        self.age = 0 #年龄
        #请你把位置的中心设为 屏幕的中间
    def update(self):
        key=pygame.key.get_pressed()
        ##请你设置上下移动的限制,向上下移动到边缘就不能动了
        if key[K_UP]and self.rect.top>=0:
            self.rect.y-=5
        if key[K_DOWN] and self.rect.bottom<=600:
            self.rect.y+=5
        if key[K_LEFT]: #
            self.rect.x-=5
            if self.rect.left<0 and self.index==-1:
                self.rect.left=0
            if self.rect.right<0:
                self.rect.left=800
                self.index-=1
        if key[K_RIGHT]:
            self.rect.x+=5
            if self.rect.right>800 and self.index==1:
                self.rect.right=800
            if self.rect.left>800:
                self.rect.right=0
                self.index+=1
class Building(pygame.sprite.Sprite):
    def __init__(self,name,x,y):#初始化
        pygame.sprite.Sprite.__init__(self)#初始化
        self.image=wst(50,name)
        self.rect = self.image.get_rect()
        self.rect.center = x,y
        self.name =name #请你把位置的中心设为 屏幕的中间
b1=[Building('学校',100,100),Building('家',300,100),Building('黄兴公园',500,100),
    Building('补习班',100,500),Building('银行',300,500),Building('斯坦星球',500,500)]
b2=[Building('科技馆',100,100),Building('游乐场',300,100),Building('江湾体育场',600,100),
    Building('动物园',100,500),Building('电影院',300,500),Building('万达广场',500,500)]
b3=[Building('少科站',100,100),Building('小卖部',300,100),Building('志愿者服务站',650,100),
    Building('鬼屋',100,500),Building('打工中心',300,500),Building('游泳馆',550,500)]
size=width,height=800,600
screen = pygame.display.set_mode(size)
pygame.display.set_caption('人生模拟器')
bg=200,200,200
me=Me() #########
clock=pygame.time.Clock()
allgroup=pygame.sprite.Group()#精灵组
while True:
    if me.index == 0:
        for i in allgroup: #先清空所有建筑
            i.kill() #杀掉这个角色
        for i in b1: #再添加新的建筑
            allgroup.add(i)
    if me.index == -1:
        for i in allgroup: #先清空所有建筑
            i.kill() #杀掉这个角色
        for i in b2: #再添加新的建筑
            allgroup.add(i)
    if me.index == 1:
        for i in allgroup: #先清空所有建筑
            i.kill() #杀掉这个角色
        for i in b3: #再添加新的建筑
            allgroup.add(i)
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        if event.type == KEYDOWN:
            if event.key == K_TAB:
                print(f"""
你的年龄是{me.age}岁
你的德智体美劳分别是{me.d},{me.z},{me.t},{me.m},{me.l}
压力为{me.yl} 金币为{me.jb}
""")
            if event.key == K_SPACE:
                #继续进行碰撞检测判断
                a=pygame.sprite.spritecollide(me,allgroup,False)
                if a:
                    进入地图(a[0].name)#如果你碰到了建筑物又摁下了空格调用这个函数
    if me.age == 18:
        print('恭喜你成功的长大了!')
        if me.z > 800:
            print('你凭借从小的勤奋学习考入了北京大学!')
        #在这里请返回你想象力给我们的主角根据
        #他的属性值的范围来给予他一个称号
        break

    screen.fill(bg)
    screen.blit(me.image,me.rect)###############
    me.update()########################
    allgroup.draw(screen) #绘制精灵组
    pygame.display.update()

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。