|
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
萌新最近在用renpy制作游戏,其中有解谜部分,于是研究出了一个简单的物品栏功能。
虽然尚未完善,但大体功能已经完成,见有许多同学需要,故先分享,以供参考与学习。
相关工程(暂未上传github,先用网盘分享了):
因为是边做游戏边造轮子,所以把物品栏功能单独分离出来塞新工程里了
相关工程 提取码: 2026
代码部分:
物品类定义:
[RenPy] 纯文本查看 复制代码 # 物品类定义
init -1 python:
""" 基础物品类 """
class InventoryItem:
def __init__(self, id, name, description, image_path,
usable=False, combinable=False, examine_text=None):
self.id = id # id
self.name = name # 名称
self.description = description # 简介
self.image_path = image_path # 物品图标路径
self.usable = usable # 是否可使用
self.combinable = combinable # 能否被组合(也许会用到)
self.examine_text = examine_text or description # 检查文本
# 运行时状态
self.selected = False #是否被选中
self.quantity = 1 # 物品数量(应该不会用到)
# 用于debug时返回物品的id与名称
def __repr__(self):
return f"Item({self.id}: {self.name})"
def __str__(self):
return self.name
# 检查 返回物品的简介与详细文本
def examine(self):
return self.examine_text
def description(self):
return self.description
# 使用物品 待完善,target 是目标对象或另一物品
def use(self, target=None):
return False # 子类重写
""" 文档物品类 (未完善,使用后呼出文档相关的界面)"""
class DocumentItem(InventoryItem):
def __init__(self, id, name, description, image_path,
content="", examine_text=None, screen_name=None):
super().__init__(id, name, description, image_path,
usable=True, combinable=False, examine_text=examine_text)
self.content = content # 文档内容
self.screen_name = screen_name # 交互后展示的界面
def examine(self):
return self.content
def show(self):
if screen_name:
renpy.show_screen(self.screen_name)
def close(self):
if screen_name:
renpy.hide_screen(self.screen_name)
# 物品栏类定义
""" 物品栏 """
class Inventory:
def __init__(self, max_slots=8):
self.items = {} # id -> Item 字典
self.max_slots = max_slots # 最大物品数 根据实际需要更改,俺这里是8
self.selected_item = None # 当前选中的物品
# 添加物品
def add(self, item):
if len(self.items) >= self.max_slots:
return False
if item.id in self.items:
# 可堆叠物品处理
self.items[item.id].quantity += 1
else:
self.items[item.id] = item
return True
# 移除物品
def remove(self, item_id):
if item_id in self.items:
self.items[item_id].quantity -= 1
if self.items[item_id].quantity <= 0:
del self.items[item_id]
# 如果物品被选中时移除,则取消选中状态
if self.selected_item and self.selected_item.id == item_id:
self.selected_item = None
return True
return False
def clear(self):
self.items.clear()
self.select_item = None
# 检查是否拥有物品
def has(self, item_id):
return item_id in self.items
# 获取物品
def get(self, item_id):
return self.items.get(item_id)
# 选中/取消选中物品
def select(self, item_id):
if item_id is None:
if self.selected_item:
self.selected_item.selected = False
self.selected_item = None
return None
# 如果重复选中则取消选中状态
if self.selected_item and self.selected_item.id == item_id:
# 取消选中
self.items[item_id].selected = False
self.selected_item = None
return None
else:
# 清除之前选中
if self.selected_item:
self.selected_item.selected = False
# 设置新选中
self.selected_item = self.items.get(item_id)
if self.selected_item:
self.selected_item.selected = True
return self.selected_item
# 组合物品(未实现,有需要可以完善)
# def combine(self, item1_id, item2_id, result_id):
# item1 = self.get(item1_id)
# item2 = self.get(item2_id)
# #判断双方是否可以组合
# if not (item1 and item2 and item1.combinable and item2.combinable):
# return None
# #判断是否在配方表里
# if "这里判断是否有这个配方"
# # 移除原材料
# self.remove(item1_id)
# self.remove(item2_id)
# # 添加结果(需要在某处定义所有物品的创建逻辑)
# return result_id
# return None
# 清除选中状态
def clear_selection(self):
if self.selected_item:
self.selected_item.selected = False
self.selected_item = None
init -1 python:
def select_item(inventory, item):
if item is None:
return None
return inventory.select(item.id)
def check_item(inventory):
if inventory.select_item.id:
return inventory.select_item.id
# ============================================
# 全局物品栏
# ============================================
# 全局物品栏
inventory = Inventory(max_slots=12)
# 物品数据库
def create_item(item_id):
items_test = {
"paper": InventoryItem(
"paper",
"皱巴巴的纸条",
"你忘了是谁给你的",
"images/items/paper.png",
usable=True
),
"knife": InventoryItem(
"knife",
"小刀",
"锋利的水果刀",
"images/items/knife.png",
usable=True
)
}
return items_test.get(item_id, None)
物品栏界面(screen)
[RenPy] 纯文本查看 复制代码 #物品栏
screen inventory_screen():
modal True
zorder 100
add Solid("#000000cc")
# 物品栏面板
frame:
xalign 0.5
yalign 0
xsize 0.75
ysize 500
vbox:
xalign 0.5
spacing 30
# 标题
text "物品栏" size 30 xalign 0.5
# 物品网格
grid 8 1:
spacing 15
xalign 0.5
# 遍历所有物品槽位
for i in range(8):
$ curItem = list(inventory.items.values())[i] if i < len(inventory.items) else None
button:
xsize 150
ysize 150
background Frame("#a29d81", 10, 10)
# 选中变色
if curItem and curItem.selected:
background Frame("#e22e2ea7", 10, 10)
action [
Function(select_item,inventory,curItem),
renpy.restart_interaction #重新启动当前交互行为
]
if curItem:
vbox:
xalign 0.5
yalign 0
spacing 10
# 物品图标
add curItem.image_path xalign 0.5
# 数量(大于1时显示)
if curItem.quantity > 1:
text str(curItem.quantity) size 40 xalign 1.0 offset (10,-45) color "#3a1919" outlines [(2,"#d5a209",0,0)]
# 物品名称
text curItem.name size 24 xalign 0.5
#物品简介:
if inventory.selected_item:
frame:
background None
xalign 0.5
xysize(0.8,0.5)
text inventory.selected_item.description:
align (0.5,0.5)
# 操作区域(可自行完善)
hbox:
xalign 0.5
yalign 1.0
spacing 20
# 检查按钮
if inventory.selected_item:
textbutton "检查":
action NullAction()
# 使用按钮
if inventory.selected_item:
textbutton "使用":
action [
SetVariable("using_item", inventory.selected_item),
SetVariable("default_mouse","item"),
Hide("inventory_screen")
]
# 关闭按钮
textbutton "关闭":
action [
Hide("inventory_screen")
]
关于交互界面:
[RenPy] 纯文本查看 复制代码 default using_item = None
default door_open = 0
# 物品栏按钮
screen inventory_button():
zorder 50
textbutton "打开背包":
text_color "#000000"
text_hover_color "#ff0000"
pos (0.05, 0.1)
action Show("inventory_screen")
screen house_screen:
frame:
xysize(1980,1080)
background None
if door_open==0:
add "images/house1.png" #背景
else:
add "images/house2.png"
if not inventory.has("knife"):
imagebutton:
pos(100,0.8)
idle "images/items/knife.png"
focus_mask True
action Jump("pickup")
#门
button:
idle_background None
pos(1050,250)
xysize(500,600)
if using_item is not None:
if (str(using_item.id)=="knife") and door_open==0:
action [SetVariable("using_item", None),Jump("knife_door")]
elif(str(using_item.id)=="paper"):
action [SetVariable("using_item", None),Jump("paper_door")]
else:
if door_open==0:
action Jump("check_door")
else:
action Jump("check_open")
# 使用物品模式下的特殊处理
if using_item:
# 显示当前使用的物品图标跟随鼠标
text "使用物品模式(右键取消)" pos (0.5,0.9) color "#4fbe33" size 48
# 点击空白处取消使用
key "mouseup_3" action [SetVariable("using_item", None), renpy.restart_interaction]
# 游戏在此开始。
label start:
$ door_open = 0
# 初始化物品栏(测试用)
python:
inventory.clear()
inventory.add(create_item("paper"))
show screen inventory_button
call screen house_screen with dissolve
jump house
label house:
show screen house_screen
window hide
$ renpy.pause(hard=True)
jump house
label check_door:
show screen house_screen
"好丑的门"
jump house
label check_open:
show screen house_screen
"你不能出去,因为这只是个演示项目\n并不是一个完整版游戏"
jump house
label pickup:
python:
inventory.add(create_item("knife"))
show screen house_screen
"你把刀捡了起来"
jump house
label knife_door:
show screen house_screen
"门被劈开了"
$ door_open=1
jump house
label paper_door:
show screen house_screen
"你把纸揉成一团丢向门,然后又捡了回来....."
jump house
其他:
这是萌新的第二个帖子(不会写帖子)所以排版会很糟糕
因为只是个简易代码,所以很多东西并不是很完善,可以根据需要以此扩展
使用物品功能只是草草在代码上实现,实际上可以通过切换鼠标样式弄出更好的演出效果
物品类方面还可以继续扩展,实现解谜游戏那样的组合或查看功能(没写完)
界面交互方面的代码感觉不够完美,仅供参考
|
评分
-
查看全部评分
|