找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 26824|回复: 5

[已解决] 如何大量生成随机NPC?

[复制链接]
发表于 2019-7-16 23:03:26 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
想要做一个高自由度养成游戏(类似太吾绘卷or皇帝成长计划之类的,不过格局并不宏大,流程也不复杂)对于代码比较小白,处于依葫芦画瓢的水平
大概就是每一个开局所有的人物都是随机生成的。
举个例子,主角是一个学生,然后开局会随即生成15~25个同学,每一个同学有不同的属性,关于命名空间的教程我大概看了一下有点明白了,但是现在只能一个一个地写代码,同学01、02、03,然后给每一个属性随机赋值……有比较方便一点的方法吗
比如我从15~25之间roll一个随机数X,之后创建X个同学,给每个同学的每个属性赋值,应该如何做到呢?
发表于 2019-7-17 18:41:48 | 显示全部楼层
本帖最后由 老司机飞飞飞 于 2019-8-30 13:57 编辑

[RenPy] 纯文本查看 复制代码
init python:
    from operator import attrgetter

    class Student_store(object):
        """学生商店."""
        def select_xs(self):
            pass

        def xs_order(self,xs_type):
            return self.select_xs(xs_type)

    class Yz_xs_store(Student_store):
        """一中学生商店."""

        #去一中学生商店下订单买一个学生
        def select_xs(self, xs_type):
            #商店又找厂家生产一个学生
            return Xs_factory().select_xs_type(xs_type)

    class Ez_xs_store(Student_store):
        """二中学生商店."""
        def select_xs(self, xs_type):
            return Xs_factory().select_xs_type(xs_type)

    class Xs_factory(object):
        """学生工厂"""

        def select_xs_type(self,xs_type):
            #如果学生的种类是一中学生,那就生产一中学生
            if xs_type == "一中":
                return Yz_xs()
            elif xs_type == "二中":
                return Ez_xs()

    class Student_sx(object):
        """学生属性基类."""
        def __init__(self, name, age, address):
            self.name = name
            self.age = age
            self.address = address

        def __eq__(self, other):
            """python中的对象是否相等有两个层面,一个层面是是否是同一个对象,及在内存中是否共用一个内存区域,
            用is判断,另一个是对象的值是否相等,用==判断"""
            return self.__dict__ == other.__dict__

        #学生属性随机化
        def xs_random(self):
            xing_list = ["王","刘","李","张"]
            ming_list = ["一","二","三","四"]
            address_list = ["山东","北京","上海","广东"]
            self.xing = renpy.random.choice(xing_list)
            self.ming = renpy.random.choice(ming_list)
            self.name = self.xing+self.ming
            self.age = renpy.random.randint(15,20)
            self.address = renpy.random.choice(address_list)

    class Yz_xs(Student_sx):
        """一中学生."""
        def __init__(self):
            Student_sx.xs_random(self)

    class Ez_xs(Student_sx):
        """二中学生."""
        def __init__(self):
            Student_sx.xs_random(self)

    yz_xs_store = Yz_xs_store() #一中学生商店
    ez_xs_store = Ez_xs_store()

    # Yz_xs1 = yz_xs_store.xs_order("一中") #一中学生商店找一中学生工厂生产一中学生1
    # Ez_xs1 = ez_xs_store.xs_order("二中") #二中学生商店找二中学生工厂生产二中学生1

    yz_xs_list = [] #一中学生列表
    ez_xs_list = []

    #学生数量,种类
    def main(num,type):
        if type == "一中":
            while len(yz_xs_list) <= num-1:
                a = yz_xs_store.xs_order("一中")
                #判断创造的实例是否与原有的实例属性相同
                if a not in yz_xs_list:
                    yz_xs_list.append(a)
                # c = set(yz_xs_list) #删除重复的元素,并不适合实例对象

        elif type == "二中":
            while len(ez_xs_list) <= num-1:
                a = ez_xs_store.xs_order("二中")
                if a not in ez_xs_list:
                    ez_xs_list.append(a)

        #全局变量
        global yz_xs_list
        yz_xs_list = sorted(yz_xs_list, key=attrgetter("name","age")) #先按名字,再按年龄排序,对中文似乎不太友好
        global ez_xs_list
        ez_xs_list = sorted(ez_xs_list, key=attrgetter("name","age"))

#界面
screen jm():
    frame:
        align(0.5,0.7)
        hbox:
            textbutton "一中学生列表" action ShowTransient("xs_jm", name = "一中学生列表", list = yz_xs_list)
            textbutton "二中学生列表" action ShowTransient("xs_jm", name = "二中学生列表", list = ez_xs_list)

#一中学生界面列表
screen xs_jm(name,list):
    viewport:
        xsize 350
        ysize 350
        align(0,0)
        draggable True
        mousewheel True
        arrowkeys True
        scrollbars "vertical"
        vbox:
            text "[name]"
            for i in list:
                #textbutton "[i.name]" action ShowTransient("xs_sx", xs = i)
                text "姓名:[i.name],年龄:[i.age],出生地:[i.address]"

#学生具体属性
screen xs_sx(xs):
    frame:
        align(0.8,0)
        vbox:
            xysize(200,230)
            text "名字:"+ xs.name
            text "年龄:" + str(xs.age)
            text "出生地:" + xs.address


label start:
    #$ main()
    #show expression aa
    "aaaaaaaa"
    "bbbbbbbb"
    #$ fj.main()#调用main函数启动
    $ main(100,"一中") #生产10个一中学生
    $ main(10,"二中")
    # $ a = renpy.random.randint(10,20)
    # $ main(a,"二中")
    "[yz_xs_list[0].name],[yz_xs_list[0].age],[yz_xs_list[0].address]"
    show screen jm()
    "ccccccccccc"

评分

参与人数 2干货 +3 收起 理由
龙氏 + 1 版区有你更精彩(*^_^*)
BuErShen + 2 感谢分享!

查看全部评分

回复 支持 3 抱歉 0

使用道具 举报

发表于 2020-1-9 15:40:28 | 显示全部楼层
本帖最后由 老司机飞飞飞 于 2020-1-9 15:42 编辑


////////////////////////////////////
最近在看设计模式,发现只有一中学生、二中学生....,只需要使用简单工厂模式
而如果是一中、二中,一中下面又有学生、老师、厨师、清洁人员等,就需要使用抽象工厂模式
所以修改了下
[RenPy] 纯文本查看 复制代码
#简单工厂设计模式
init python:
    from operator import attrgetter

    class StudentFactory(object):
        """学生工厂"""
        def instantiation_student(self,student_type):
            #如果学生的种类是一中学生,那就生产一中学生
            if student_type == "一中":
                return OneSchoolStudent()
            elif student_type == "二中":
                return TowSchoolStudent()

    class Student(object):
        """学生属性基类."""
        def __init__(self):
            self.name = ""
            self.age = 0
            self.address = ""

        #学生属性随机化
        def student_random(self):
            xing_list = ["王","刘","李","张"]
            ming_list = ["一","二","三","四"]
            address_list = ["山东","北京","上海","广东"]
            self.xing = renpy.random.choice(xing_list)
            self.ming = renpy.random.choice(ming_list)
            self.name = self.xing+self.ming
            self.age = renpy.random.randint(15,20)
            self.address = renpy.random.choice(address_list)

    class OneSchoolStudent(Student):
        """一中学生."""
        def __init__(self):
            Student.student_random(self)

    class TowSchoolStudent(Student):
        """二中学生."""
        def __init__(self):
            Student.student_random(self)

    factory = StudentFactory() #工厂的引用
    one_school_student_list = [] #一中学生列表
    tow_school_student_list = []

    #生产学生(学生列表,学生类型,学生数量)
    def production_student(student_list,student_type,student_num):
        #添加
        add_student(student_list,student_type,student_num)
        #排序,先按名字再按年龄(要按中文排序,百度)
        student_list.sort(key=attrgetter("name","age"))

    #单纯的添加学生到列表
    def add_student(student_list,student_type,student_num):
        #因为传入的列表是可变类型,所以可以直接修改列表里的值
        #用student_list = [],只是再函数里命名了一个名称为student_list的局部变量,不会改变传入的列表
        # 在python中,数据有两种类型:mutable(可变) 和 immutable (不可变)
        # list ,dict是mutable的;
        # int , string , float ,tuple是inmutable 的。
        # 在函数参数的传递过程中:
        # 对于inmutable object ,函数参数传递是值
        # 对于mutable object,函数参数传递是指针
        # 因此,当我们把list传入fun()函数时,实际是把list的指针传递给了inner_lst变量。
        # 所以,lst的值会随着inner_lst进行变化。
        del student_list[:]
        while len(student_list) <= student_num-1:
            #实例化
            a = factory.instantiation_student(student_type)
            if a not in student_list:
                student_list.append(a)

#学校界面
screen school_screen():
    frame:
        align(0.5,0.7)
        hbox:
            textbutton "一中学生列表" action ShowTransient("student_screen", name = "一中学生列表", student_list = one_school_student_list)
            textbutton "二中学生列表" action ShowTransient("student_screen", name = "二中学生列表", student_list = tow_school_student_list)

#学生界面列表
screen student_screen(name,student_list):
    viewport:
        xsize 350
        ysize 350
        align(0,0)
        draggable True
        mousewheel True
        arrowkeys True
        scrollbars "vertical"
        vbox:
            text "[name]"
            for i in student_list:
                #textbutton "[i.name]" action ShowTransient("student_attribute", student = i)
                text "姓名:[i.name],年龄:[i.age],出生地:[i.address]"

#学生具体属性
screen student_attribute(student):
    frame:
        align(0.8,0)
        vbox:
            xysize(200,230)
            text "名字:"+ student.name
            text "年龄:" + str(student.age)
            text "出生地:" + student.address

label start():
    $ production_student(one_school_student_list,"一中",100) #生产10个一中学生
    $ production_student(tow_school_student_list,"二中",10)
    #"[one_school_student_list[0].name],[one_school_student_list[0].age],[one_school_student_list[0].address]"
    call screen school_screen()
回复 支持 1 抱歉 0

使用道具 举报

 楼主| 发表于 2019-7-21 00:05:28 | 显示全部楼层
老司机飞飞飞 发表于 2019-7-17 18:41
[mw_shl_code=renpy,true]init python:
    from operator import itemgetter, attrgetter

可用!!太感谢了~~研究中
回复 支持 抱歉

使用道具 举报

发表于 2019-7-24 14:03:05 | 显示全部楼层
老司机飞飞飞 发表于 2019-7-17 18:41
[mw_shl_code=renpy,true]init python:
    from operator import itemgetter, attrgetter

学习了
回复 支持 抱歉

使用道具 举报

发表于 2019-7-30 17:36:52 | 显示全部楼层
老司机飞飞飞 发表于 2019-7-17 18:41
[mw_shl_code=renpy,true]init python:
    from operator import attrgetter

原先的有点问题重新改了下
回复 支持 抱歉

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|RenPy中文空间 ( 苏ICP备17067825号|苏公网安备 32092302000068号 )

GMT+8, 2024-3-28 20:12 , Processed in 0.049215 second(s), 16 queries , File On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表