|
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
本帖最后由 Maz马 于 2026-5-18 01:20 编辑
全随机游戏就是肉鸽Rogue了...
26/5/17 重构了类和变量的命名风格,让局部变量语义更清晰一些,代码应该更干净健壮了
组件可以对接的功能
1随机取名,随机属性的角色
2随机取名,随机属性的道具
3随机地点,发生随机事件
4随机房间,放置随机家具
...
组件本身是定义了随机组装的规则而不是生产具体的对象
所以这是一个核心
在使用上需要自行设计接收者,可以是类,也可以是函数
这里主要还是提供一个“心脏”提供一个思路
如果只想使用,完全不关心内部
你只要知道,在配置好树图后,系统提交给你的是
一枚 随机种子
格式为字典:
{"units":单元列表,"nodes":节点列表,"votes":投票字典}
系统不知道你的节点内容,单元内容,给哪个tag投票
只根据你设计的路径图进行收集组装。
过去的思路是写表,在结构简单时还行
随机创建角色
但一旦可能性变多,分支复用,写表穷举就会十分臃肿
然后就演变成以下
第一部分:RG系统(直接复制为一个文件)
[RenPy] 纯文本查看 复制代码 # ============== 节点加权随机器 ================
# @ Maz马
# 简单理解 节点系统,图或者树取决于节点的组织方式
# RG_node ➡ RG_node RG_node ➡ RG_unit
# | |
# ➡ RG_node ➡ RG_unit
# | |
# ➡ RG_node ➡ RG_unit
# 你可以视作你在玩大富翁,你通过投骰子 随机选择路径 到达 下一个地点(节点)
#
# 你到达这个地点,在人堆里选一个人对话(单元),他会告诉你"你变强了,也变高了"(投票➡{"强":1,"高":1})
#
# 重复这个过程直到你到达终点,你就会记录下 你去过的地点,和谁说过话,都说过什么
#
# 也就是一枚 包含了多种预设信息的 随机种子
# 随机种子注册表单 不建议直接访问
default _RG_SYS = {}
init python:
import random
class RG_unit:
def __init__(self,_name,_roll=None,_node=None,_vote=None):
self._name = _name # 名称
self._roll = _roll or 1 # 权重 数值越大概率越大,正数非0
self._node = _node # 所属节点(NODE对象)
self._vote = _vote or {} # 投票字典/词缀系统 {tags:value}
class RG_node:
def __init__(self,_name,_roll=None,_units=None,_parents=None,_childs=None):
self._name = _name # 名称
self._roll = _roll or 1 # 权重 数值越大概率越大,正数非0
self._units = _units or [] # 关联单元(UNIT对象池)
self._parents = _parents or [] # 父级节点(NODE对象池)
self._childs = _childs or [] # 子级节点(NODE对象池)
class RG_seed:
def __init__(self,_units=None,_nodes=None):
self._units = _units or [] # 收集到的单元(UNIT对象池)
self._nodes = _nodes or [] # 收集到的节点(NODE对象池)
@property # 随机种子
def _seed(self):
votes = {}
for unit in self._units:
if not unit._vote:
continue
for k,v in unit._vote.items():
votes[k] = votes.get(k,0) + v
# 创建种子
result = {}
result["units"] = [unit._name for unit in self._units]
result["nodes"] = [node._name for node in self._nodes]
result["votes"] = votes
return result
# 树图管理器
class RG_graph:
def __init__(self,_name,_registry):
self._name = _name # 树图名称
self._node_pool = {} # 节点表 NODE名 -> NODE对象
self._unit_pool = {} # 单元表 NODE名 -> UNIT对象列表
self._cache_roots = [] # 所有根 [str,str...]
self._cache_paths = [] # 节点路径 [str,str...]
self._cache_index = {} # 路径索引 {str:[str...]}
self._registry = _registry # 注册表单 {_name:{_id:_seed}}
# 接入随机种子注册表单
def set_graph(self):
if self._name not in self._registry:
self._registry[self._name] = {}
print(f"※ 已接入ID:{self._name} 的树图")
# 节点和单元一旦被删除或覆盖,会导致种子无法追溯
# 虽然不会发生错误,但会在流程调试困难
# 所以不提供删除方法,但可以断连孤立,不参与树图业务
# 节点创建 关联 断连
def set_node(self,_node_name,_roll=None):
if _node_name not in self._node_pool:
self._node_pool[_node_name] = RG_node(_node_name,_roll=_roll)
def link_node(self,_node_name,_node_names):
for k in _node_names:
if k not in self._node_pool:
continue
if self._node_pool[_node_name] not in self._node_pool[k]._parents:
self._node_pool[k]._parents.append(self._node_pool[_node_name])
if self._node_pool[k] not in self._node_pool[_node_name]._childs:
self._node_pool[_node_name]._childs.append(self._node_pool[k])
def unlink_node(self,_node_name,_node_names):
if _node_name not in self._node_pool:
return
for k in _node_names:
if k not in self._node_pool:
continue
if self._node_pool[_node_name] in self._node_pool[k]._parents:
self._node_pool[k]._parents.remove(self._node_pool[_node_name])
if self._node_pool[k] in self._node_pool[_node_name]._childs:
self._node_pool[_node_name]._childs.remove(self._node_pool[k])
# 单元创建 关联 断连
def set_unit(self,_node_name,_unit_names):
# _unit_names 格式允许混合使用
# [_name,_name...]
# 或
# [(_name,_roll,_vote),(_name,_roll,_vote)...]
# 或
# [(_name,_roll,_vote),[_name,_roll,_vote]...]
if _node_name not in self._node_pool:
print(f"!!!节点'{_node_name}'不存在,请先创建节点")
return
if _node_name not in self._unit_pool:
self._unit_pool[_node_name] = []
exist = {unit._name for unit in self._unit_pool[_node_name]}
for i in _unit_names:
if isinstance(i,(tuple,list)):
i1 = i[0]
i2 = i[1] if len(i) > 1 else None
i3 = i[2] if len(i) > 2 else None
if i2:
if not isinstance(i2,(int,float)):
print(f"!!!单元'{i1}'的权重不是数值,忽略该写入")
i2 = None
if i3:
if not isinstance(i3,dict):
print(f"!!!单元'{i1}'的投票字典不是字典类型,忽略写入")
i3 = None
else:
for k,v in i3.items():
if not isinstance(v,(int,float)):
print(f"!!!单元'{i1}'的投票字典中键'{k}'的值'{v}'不是数值,忽略该键值对")
# 设为0忽略
i3[k] = 0
else:
i1 = i
i2 = None
i3 = None
if i1 not in exist:
self._unit_pool[_node_name].append(RG_unit(i1,_roll=i2,_vote=i3))
def link_unit(self,_node_name=None):
# 关联单个节点和节点下所有单元
if _node_name:
if _node_name not in self._unit_pool:
print(f"??? 节点'{_node_name}'下没有任何关联单元")
return
if _node_name in self._unit_pool:
self._node_pool[_node_name]._units = self._unit_pool[_node_name]
for unit in self._unit_pool[_node_name]:
unit._node = self._node_pool[_node_name]
# 关联所有节点和节点下所有单元
else:
for k in self._node_pool:
if k not in self._unit_pool:
print(f"??? 节点'{k}'下没有任何关联单元")
for k in self._unit_pool:
self._node_pool[k]._units = self._unit_pool[k]
for unit in self._unit_pool[k]:
unit._node = self._node_pool[k]
def unlink_unit(self,_node_name,_unit_names):
if _node_name not in self._unit_pool:
return
for i in _unit_names:
# 遍历副本
for unit in self._unit_pool[_node_name][:]:
if unit._name == i:
self._unit_pool[_node_name].remove(unit)
break
# 同步更新节点表
if _node_name in self._node_pool:
self._node_pool[_node_name]._units = self._unit_pool.get(_node_name,[])
# 打印报告 用缓存打印树图结构(无报错)
def _path_check(self):
print(f"======= {self._name}树图报告 =======")
print("!!! 注意核对根节点 !!!")
print("!!!根节点不正常则环位于根 !!!")
print()
print("!!! 注意核对路径 !!!")
print("!!!不检测*跳过节点*的逆向环!!!")
if self._cache_roots:
print(f"共 {len(self._node_pool)} 个节点,{len(self._cache_roots)} 个根节点")
print()
for i in self._cache_roots:
print(f"根节点: {i}")
else:
print("!!! 未找到根节点 !!!")
if self._cache_paths:
print(f"共 {len(self._cache_paths)} 条路径")
print()
for i,p in enumerate(self._cache_paths,1):
print(f"{i:3}. {' → '.join(p)}")
else:
print("!!! 未找到路径 !!!")
print("请先调用 _path_update() 构建缓存")
print("如果已经缓存,则节点未进行连接")
print("====================================")
print("\n\n\n")
# 深度优先搜索/DFS 从指定节点出发 检测环 并 收集路径
def _path_dfs(self,node,path,paths,visit):
if node._name in visit:
loop = path[visit[node._name]:] + [node._name]
print(f"!!!检测到环: {' → '.join(loop)}")
return
visit[node._name] = len(path)
# 每次加入节点
path.append(node._name)
# 开始递归
# path [1]➡[1,2]➡[1,2,3]
# paths []
if node._childs:
for child in node._childs:
self._path_dfs(child,path,paths,visit.copy())
# 递归到最深处后把路径加入路径列表
# path [1,2,3]
# paths [[1,2,3]]
else:
paths.append(path.copy())
# 弹出最后一个节点,检查2除了3能不能继续,逐级回退检查
# paths [[1,2,3]]
path.pop()
# 遍历树图 报告错误,初始化缓存
def _path_update(self):
# 清空旧缓存
self._cache_roots = []
self._cache_paths = []
self._cache_index = {}
# 遍历节点池,锁定根,缓存根
for node in self._node_pool.values():
if not node._parents:
self._cache_roots.append(node._name)
# 从根开始,DFS检测,缓存路径
self._path_dfs(node,[],self._cache_paths,{})
# 缓存索引 {节点:[包含节点的路径]}
for path in self._cache_paths:
for k in path:
if k not in self._cache_index:
self._cache_index[k] = []
self._cache_index[k].append(path)
# 输出缓存信息
self._path_check()
# 随机游走
def _random_root(self,_node_name):
# 追溯到根,返回根到节点路径
current = self._node_pool[_node_name]
path = [current]
while current._parents:
# 权重随机父节点
weight_nodes = [node._roll for node in current._parents]
current = random.choices(current._parents,weights=weight_nodes,k=1)[0]
path.insert(0,current)
return path
def _random_path(self,_node_name):
# === 追溯,逆向树随机 ===
root_to_current = self._random_root(_node_name)
current = root_to_current[-1]
select_nodes = root_to_current.copy()
select_units = []
for node in root_to_current:
# 按权重随机收集单元
if node._units:
weight_units = [unit._roll for unit in node._units]
select_units.append(random.choices(node._units,weights=weight_units,k=1)[0])
# === 延伸,正向树随机 ===
while current._childs:
weight_nodes = [node._roll for node in current._childs]
current = random.choices(current._childs,weights=weight_nodes,k=1)[0]
select_nodes.append(current)
# 按权重随机收集单元
if current._units:
weight_units = [unit._roll for unit in current._units]
select_units.append(random.choices(current._units,weights=weight_units,k=1)[0])
return RG_seed(_units=select_units,_nodes=select_nodes)
# 对外接口
def obj_random(self,_id,_node_name=None):
# _id 从 随机种子注册表单 提取 结果对象 的 唯一标识
if not self._cache_roots:
print("!!!未初始化 树图")
return
if _node_name and _node_name not in self._node_pool:
print(f"!!!节点'{_node_name}'不存在,请先创建节点")
return
if not _node_name:
_node_name = random.choice(self._cache_roots)
# 存储 随机种子 到 随机种子注册表单
self._registry[self._name][_id] = self._random_path(_node_name)._seed
return self._registry[self._name][_id]
def obj_del(self,_id):
if _id not in self._registry[self._name]:
print("!!!未记录的id,删除无效")
return
del self._registry[self._name][_id]
return
def obj_get(self,_id):
if _id not in self._registry[self._name]:
print("!!!未记录的id,请先创建随机种子")
return
return self._registry[self._name].get(_id)
def obj_ids(self):
ids = list(self._registry[self._name].keys())
print(f"树图 '{self._name}' 中共有 {len(ids)} 个随机种子: {ids}")
return ids
第二部分 需要编写的部分:
[RenPy] 纯文本查看 复制代码 init python:
# 命令式编写树图
def init_tree1():
# _()是支持多语言,可以不写。内部逻辑是原字符串,不会因为翻译导致系统错误。
# 创建姓名树
store.RGcnchar = RG_graph(_name="中文姓名",_registry=_RG_SYS)
store.RGcnchar.set_graph()
# ==================== 注册节点 ====================
# 这一步注册你的节点,_roll是概率,数值越大出现的概率越大,不填则默认1,也就是均等概率
store.RGcnchar.set_node(_("角色"))
# 4/4+7的概率生成男角色,7/4+7的概率生成女角色
store.RGcnchar.set_node(_("男"),_roll=4)
store.RGcnchar.set_node(_("女"),_roll=7)
store.RGcnchar.set_node(_("男前名"))
store.RGcnchar.set_node(_("男中名"))
store.RGcnchar.set_node(_("男后名"))
store.RGcnchar.set_node(_("女前名"))
store.RGcnchar.set_node(_("女中名"))
store.RGcnchar.set_node(_("女后名"))
# ================ 回调绑定节点父子关系 ================
# 树:绑定时,节点只有一个父级节点。输出风格被逐级影响,需要追溯唯一路径的结构
# 连接节点,_node_names代表这个节点可以前往哪个节点
store.RGcnchar.link_node(_("角色"),_node_names=[_("男"),_("女")])
store.RGcnchar.link_node(_("男"),_node_names=[_("男前名")])
store.RGcnchar.link_node(_("女"),_node_names=[_("女前名")])
store.RGcnchar.link_node(_("男前名"),_node_names=[_("男中名")])
store.RGcnchar.link_node(_("女前名"),_node_names=[_("女中名")])
store.RGcnchar.link_node(_("男中名"),_node_names=[_("男后名")])
store.RGcnchar.link_node(_("女中名"),_node_names=[_("女后名")])
# ===================== 注册单元 =======================
# 注册节点的内容单元,经过这个节点得到的东西,节点可以无单元
store.RGcnchar.set_unit(_("男前名"),[
_("赵"),_("钱"),_("孙"),_("李"),_("周"),_("吴"),_("郑"),_("王"),
_("冯"),_("陈"),_("蒋"),_("沈"),_("韩"),_("杨"),_("朱"),_("秦"),
_("许"),_("何"),_("吕"),_("张"),_("孔"),_("曹"),_("魏"),_("陶"),
_("姜"),_("韦"),_("马"),_("袁"),_("柳"),_("史"),_("姚"),_("汪"),
_("朱"),_("董"),_("梁"),_("杜"),_("阮"),_("蓝"),_("贾"),_("童"),
_("武"),_("司马"),_("上官"),_("欧阳"),_("夏侯"),_("诸葛"),_("东方"),
_("公孙"),_("宇文"),_("长孙"),_("慕容")])
store.RGcnchar.set_unit(_("女前名"),[
_("赵"),_("钱"),_("孙"),_("李"),_("周"),_("吴"),_("郑"),_("王"),
_("冯"),_("陈"),_("蒋"),_("沈"),_("韩"),_("杨"),_("朱"),_("秦"),
_("许"),_("何"),_("吕"),_("张"),_("孔"),_("曹"),_("魏"),_("陶"),
_("姜"),_("韦"),_("马"),_("袁"),_("柳"),_("史"),_("姚"),_("汪"),
_("朱"),_("董"),_("梁"),_("杜"),_("阮"),_("蓝"),_("贾"),_("童"),
_("武"),_("司马"),_("上官"),_("欧阳"),_("夏侯"),_("诸葛"),_("东方"),
_("公孙"),_("宇文"),_("长孙"),_("慕容")])
# 允许便捷录入,但必须按照 _name字符,_roll数值,_vote字典 的顺序,否则忽略
store.RGcnchar.set_unit(_("男中名"),[
_("伯"),_("仲"),_("叔"),_("季"),_("子"),_("作"),_("文"),_("武"),
_("元"),_("宇"),_("冠"),_("世"),_("震"),_("晓"),_("克"),_("轩"),
_("昂"),_("光"),_("修"),_("柯"),_("云"),[_(""),15,{}]])
# 例如 这里有22个字,空字符串的概率15,也就是15/15+22-1的概率生成 赵柔 这种没有中间字的名字
store.RGcnchar.set_unit(_("女中名"),[
_("温"),_("婉"),_("绮"),_("诗"),_("润"),_("涵"),_("曼"),_("玉"),
_("元"),_("语"),_("言"),_("怜"),_("惜"),_("清"),_("雨"),_("文"),
_("汶"),_("嫣"),_("芷"),_("初"),_("乐"),[_(""),15]])
# 可以在 投票字典 里给任意词条投任意票,随机种子只执行收集、携带、统计,不管携带物的作用
store.RGcnchar.set_unit(_("男后名"),[
_("杰"),_("和"),_("祖"),_("雄"),_("长"),_("德"),_("儒"),[_("冲"),1,{"令狐冲就是个没有道德观念的SB":10}],
_("高"),_("龙"),_("炎"),_("霖"),_("彻"),_("南"),_("爽"),[_("过"),1,{"杨过帅":10086,"杨过强":100}],
_("谋"),_("晏"),_("天"),_("农"),_("坤")])
store.RGcnchar.set_unit(_("女后名"),[
_("柔"),_("珊"),_("怡"),_("容"),_("婷"),_("梦"),_("卿"),_("岚"),
_("清"),_("琴"),_("瑶"),_("璇"),_("萱"),_("琪"),_("晴"),_("彤"),
_("若"),_("凤"),_("稚"),_("乐"),_("然")])
# ================= 节点与内容绑定关联 ===================
# 注册顺序必须先set_node再set_unit,连接则无所谓,但必须先set再link
# link_unit(节点名) 关联目标节点和节点下单元,无参则关联所有节点,单元
store.RGcnchar.link_unit()
# ====== 刷新树图数据,检测结构是否健康,在控制台输出 =======
# 必须在连接变更后调用,因为性能消耗比较高,所以不封装,请记得手动调用
store.RGcnchar._path_update()
# 控制台输出树图结构,仅查看缓存,不刷新数据
store.RGcnchar._path_check()
def init_tree2():
# 创建道具树
store.RGitem = RG_graph(_name="修仙道具",_registry=_RG_SYS)
store.RGitem.set_graph()
# ==================== 注册空节点 ====================
store.RGitem.set_node(_("道具"))
store.RGitem.set_node(_("秘籍"))
store.RGitem.set_node(_("药品"))
store.RGitem.set_node(_("天阶"),_roll=0.05)
store.RGitem.set_node(_("地阶"),_roll=0.15)
store.RGitem.set_node(_("玄阶"),_roll=0.30)
store.RGitem.set_node(_("黄阶"),_roll=0.50)
store.RGitem.set_node(_("极品"),_roll=0.10)
store.RGitem.set_node(_("上品"),_roll=0.20)
store.RGitem.set_node(_("中品"),_roll=0.30)
store.RGitem.set_node(_("下品"),_roll=0.40)
store.RGitem.set_node(_("功法"),_roll=1.0)
store.RGitem.set_node(_("身法"),_roll=1.0)
store.RGitem.set_node(_("武技"),_roll=1.0)
store.RGitem.set_node(_("战技"),_roll=1.0)
store.RGitem.set_node(_("九品"),_roll=0.35)
store.RGitem.set_node(_("六品"),_roll=0.30)
store.RGitem.set_node(_("三品"),_roll=0.20)
store.RGitem.set_node(_("一品"),_roll=0.15)
store.RGitem.set_node(_("丹药"),_roll=0.50)
store.RGitem.set_node(_("灵植"),_roll=0.50)
# ================ 回调绑定节点父子关系 ================
# 有向无环图:绑定时,节点有多个父级节点。
# 输出风格不被逐级影响,只有递进关系的
store.RGitem.link_node(_("道具"),_node_names=[_("秘籍"),_("药品")])
store.RGitem.link_node(_("秘籍"),_node_names=[_("天阶"),_("地阶"),_("玄阶"),_("黄阶")])
store.RGitem.link_node(_("天阶"),_node_names=[_("极品"),_("上品"),_("中品"),_("下品")])
store.RGitem.link_node(_("地阶"),_node_names=[_("极品"),_("上品"),_("中品"),_("下品")])
store.RGitem.link_node(_("玄阶"),_node_names=[_("极品"),_("上品"),_("中品"),_("下品")])
store.RGitem.link_node(_("黄阶"),_node_names=[_("极品"),_("上品"),_("中品"),_("下品")])
store.RGitem.link_node(_("极品"),_node_names=[_("功法"),_("身法"),_("武技"),_("战技")])
store.RGitem.link_node(_("上品"),_node_names=[_("功法"),_("身法"),_("武技"),_("战技")])
store.RGitem.link_node(_("中品"),_node_names=[_("功法"),_("身法"),_("武技"),_("战技")])
store.RGitem.link_node(_("下品"),_node_names=[_("功法"),_("身法"),_("武技"),_("战技")])
store.RGitem.link_node(_("药品"),_node_names=[_("九品"),_("六品"),_("三品"),_("一品")])
store.RGitem.link_node(_("九品"),_node_names=[_("丹药"),_("灵植")])
store.RGitem.link_node(_("六品"),_node_names=[_("丹药"),_("灵植")])
store.RGitem.link_node(_("三品"),_node_names=[_("丹药"),_("灵植")])
store.RGitem.link_node(_("一品"),_node_names=[_("丹药"),_("灵植")])
# ===================== 注册内容 =======================
store.RGitem.set_unit(_("天阶"),[_("大天衍"),_("无极"),_("万象"),_("九转"),_("四象")])
store.RGitem.set_unit(_("地阶"),[_("阴阳"),_("梵天"),_("破军"),_("八荒"),_("天罡")])
store.RGitem.set_unit(_("玄阶"),[_("两仪"),_("星月"),_("七杀"),_("镇狱"),_("地煞")])
store.RGitem.set_unit(_("黄阶"),[_("孤峰"),_("崩山"),_("沧澜"),_("断水"),_("叠浪")])
store.RGitem.set_unit(_("极品"),[_("真龙"),_("白虎"),_("朱雀"),_("真武"),_("鲲鹏")])
store.RGitem.set_unit(_("上品"),[_("赤炎"),_("寒霜"),_("风雷"),_("穿云"),_("金刚")])
store.RGitem.set_unit(_("中品"),[_("游龙"),_("伏虎"),_("贪狼"),_("长春"),_("灵蛇")])
store.RGitem.set_unit(_("下品"),[_("一"),_("九"),_("十三"),_("二十四"),_("三十六"),""])
store.RGitem.set_unit(_("功法"),[_("法"),_("经"),_("诀"),_("功"),_("残篇")])
store.RGitem.set_unit(_("身法"),[_("变"),_("纵"),_("步"),_("遁"),_("闪")])
store.RGitem.set_unit(_("武技"),[_("破"),_("斩"),_("掌"),_("拳"),_("指")])
store.RGitem.set_unit(_("战技"),[_("术"),_("击"),_("剑"),_("刀"),_("枪")])
store.RGitem.set_unit(_("九品"),[_("还魂"),_("断肠"),_("妖"),_("仙"),_("异域")])
store.RGitem.set_unit(_("六品"),[_("金"),_("银"),_("暴血"),_("聚灵"),_("破境")])
store.RGitem.set_unit(_("三品"),[_("固本"),_("培元"),_("金创"),_("提气"),_("补神")])
store.RGitem.set_unit(_("一品"),[_("练气"),_("筑基"),_("回气"),_("益血"),_("治愈")])
store.RGitem.set_unit(_("丹药"),[_("丹"),_("散"),_("汤"),_("液"),_("药")])
store.RGitem.set_unit(_("灵植"),[_("叶"),_("花"),_("草"),_("果"),_("根")])
# ================= 节点与内容绑定关联 ===================
store.RGitem.link_unit()
# ====================== 检测报告 =======================
store.RGitem._path_update()
# 在renpy完全启动后再初始化树图
config.start_callbacks += [init_tree1,init_tree2,init_tree3]
第三部分 使用方法:
[RenPy] 纯文本查看 复制代码 # 使用方法
label RGUSE_test1:
# 随机种子格式为 {"units":单元列表,"nodes":节点列表,"votes":投票字典}
# 系统只负责生成和存储,不负责你如何使用
# 用 xxx.obj_random("任意字符") 取得随机种子
$ a = RGcnchar.obj_random('随机1')
# 用 xxx.obj_random("任意字符",节点名) 取得定向随机种子
$ b = RGcnchar.obj_random('随机1',"男")
# 因为使用的是不同的树图,所以用同样的字符也没问题
$ c = RGitem.obj_random('随机1')
# 因为使用的是一样的树图,所以用同样的字符会覆盖原来的种子
$ d = RGcnchar.obj_random('随机1')
# 用 xxx.obj_get(_id) 获取已创建的种子
$ e = RGcnchar.obj_get('随机1')
# 用 xxx.obj_del(_id) 删除已创建的种子
$ f = RGcnchar.obj_del('随机1')
# 用 xxx.obj_ids() 查看所有已创建的随机种子ID
$ g = RGcnchar.obj_ids()
return
第四部分 高级业务类拓展:
[RenPy] 纯文本查看 复制代码 # 接收随机种子的例子
init python:
# 道具类
class Item:
def __init__(self,name=None,kind=None,level=None,price=None,buff=None,atk=None,**kwargs):
self.name = name
self.kind = kind
self.level = level
self.price = price
self.buff = buff
self.atk = atk
# 按你自己希望的方式解析种子,只在调用方法时覆盖属性
def use_seed(self,seed):
# 读取种子投票字典的词条,翻译成实际数据
self.price = seed["votes"].get("价格",0)*20
self.buff = seed["votes"].get("燃烧",0)
self.atk = seed["votes"].get("攻击",0)
# 把种子的单元列表组合起来,翻译多语言当作名字 (北冥+神+功)
self.name = renpy.translate_string("".join(seed["units"]))
# 把种子的节点列表倒数第1个节点,翻译多语言当作种类(道具》天阶》极品》功法,取功法)
self.kind = renpy.translate_string("".join(seed["nodes"][-1]))
# 把种子的节点列表第2个节点开始,赋予颜色,翻译多语言当作级别(天阶+极品+功法)
result = renpy.translate_string("".join(seed["nodes"][1:]))
if self.price <= 200:
pass
elif self.price <= 400:
result = "{color=#39FF14}" + result + "{/color}"
elif self.price <= 600:
result = "{color=#00BFFF}" + result + "{/color}"
elif self.price <= 800:
result = "{color=#BF00FF}" + result + "{/color}"
elif self.price <= 900:
result = "{color=#FF3333}" + result + "{/color}"
elif self.price <= 1000:
result = "{color=#FFBF00}" + result + "{/color}"
self.level = result
return
# 角色类
class Char:
def __init__(self,_name=None,_kind=None,**kwargs):
self._name = _name
self._kind = _kind
# 需要多语言时,使用装饰器进行一层包装,实际使用还是a.name或a.kind,但实际修改则是修改a._name
@property
def name(self):
if self._name == None:
return
elif isinstance(self._name,list):
return "".join(renpy.translate_string(item) for item in self._name)
else:
return renpy.translate_string(self._name)
@property
def kind(self):
return renpy.translate_string(self._kind)
def use_seed(self,seed):
self._name = seed["units"].copy() #孙+伯+符
self._kind = seed["nodes"][1] #角色》男》男前名》男中名》男后名,取男
# 原生角色类 用 猴子补丁 注入种子方法
def use_seed(self,seed):
self._name = seed["units"].copy()
def adv_set_name(self,value):
self._name = value
def adv_cover_name(self):
if self._name is None:
return
if isinstance(self._name, list):
return "".join(renpy.translate_string(item) for item in self._name)
else:
return renpy.translate_string(self._name)
# 新增覆盖属性
ADVCharacter._name = None
# 注入方法
ADVCharacter.use_seed = use_seed
# 注入覆盖方法
ADVCharacter.name = property(adv_cover_name,adv_set_name)
# 使用方法
label RGUSE_test2:
# 取得随机种子
$ a = RGcnchar.obj_random('随机1')
# 创建原生角色
$ xx = Character("测试角色")
# 调用解析种子的方法,更新这个对象的数据一次
$ xx.use_seed(a)
"现在xx的数据是解析种子得到的,名字是[xx.name]"
# 创建上面接收种子的示例对象
$ b = Char(_name="默认数据",_kind="默认数据")
# 调用解析种子的方法,更新这个对象的数据一次
$ b.use_seed(a)
"现在b的数据是解析种子得到的,名字是[b.name],类别是[b.kind]"
# 可以重复覆盖
$ b._name = "后续覆盖"
"解析种子不影响你的修改,只是赋值了一次,名字是[b.name],类别是[b.kind]"
return
注意,此处只是数据实现,假设要批量的,自动管理多角色、多道具
请查阅 多数据管理技巧
#点击头像 查看我写的更多屎
粉身碎骨浑不怕,要留答辩在人间
|
|