RenPy中文空间

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 620|回复: 14

[原创] 商店/物品/背包 2022最新版本教程附加代码

[复制链接]
发表于 2022-5-6 02:59:40 | 显示全部楼层 |阅读模式

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

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

x
本帖最后由 blackpineapple 于 2022-8-7 04:36 编辑



08-07-2022 更新
如果存档遇到问题,请参考下面帖子修改代码。
https://www.renpy.cn/forum.php?mod=viewthread&tid=1221


代码下载:
https://github.com/red-moon-tea-party/renpy

使用规则
教程中的代码可以用于非商用/商用的游戏,不需要和本人联系,但是需要在发布的时候署名。
署名信息:

Black Pineapple

禁止事项
  • 非代码素材,比如美术,声音等,未经过本人许可,都禁止使用。
  • 代码禁止用于非游戏的商用场合,比如在付费的教程中使用本代码,再比如加工后单纯出售代码。


前言
本系列教程是Ren'Py的进阶教程,适合于有一定基础的同学。推荐至少读完了官方文档里起步,官方自带的教程(Ren’Py Launcher里那个),或者各大新手教程中的一个。


本教程是关于如何实现一个商店/物品系统。
物品类(ItemClass.rpy)
物品类在这个教程里有两个一个是基类Item,一个是派生类BoosterItem。简单的来说,Item就是所有的东西,BoosterItem是一个具体的东西,BoosterItem这里是使用来可以增加人物属性的东西。同学们后面可以自己定义别的类型的物品,比如可以无限次使用的耐用品。

关于继承方面的知识请查阅python Inheritance(继承), 关于类的知识请直接搜python class(类)。
Item
__init__函数
这是所有类都有的初始化函数,这里定义了两个变量,一个是name是物品的名字,一个是img是物品的图片。如果需要添加什么自己需要的变量,可以仿照name增加。


名字
类型
描述
例子
name
string
物品名字
“fox”
img
string
物品图片
“images/items/fox.png”


__eq__函数和__hash__函数
因为后面用了item这个类来做字典的键值,所以需要这两个函数,用来比较两个物品对象是不是一个物品。

请自行查阅python dict(字典),来了解字典相关知识。

get_icon函数
返回一个物品图片位置的字符串。e.g. “images/items/fox.png”
BoosterItem
__init__函数

名字
类型
描述
例子
name
string
物品名字
fox
price
int
物品价格
20
booster
dict
物品可以提升的属性,这个属性,需要和player class里的成员变量相对应。
dict(
        charisma = 5
    )

description
string
物品描述
“可以增加{color=#F37459}10点智力{/color}”

因为是派生类,所以会有下面的语句
super(BoosterItem, self).__init__(name, 'images/items/' + name + '.png')

所有图片的路径都被直接设定为:'images/items/' + name + '.png

use函数
这个函数会根据这个物品的booster属性,增加使用者对应的属性。

例子:

[RenPy] 纯文本查看 复制代码
label use_item(item):
    python:
        item.use(player)
        player_inventory.remove(item)

    call screen information(msg=item.description)
    return

如果在按钮里调用函数,可以参考Function
[RenPy] 纯文本查看 复制代码
textbutton _("use"):
    if isinstance(item, BoosterItem):
        action [Function(player_inventory.remove, item=item),
        Function(item.use, player=player)]
    elif isinstance(item, Toy):
        action Call(item.script)

关于物品的例子,可以参考0shop_items.rpy
Inventory(InventoryClass.rpy)
字典可以理解为一个储物柜,需要号码,才能找到具体是哪个格子,然后拿到里面的东西。关于字典的知识请直接搜python dict(字典)。这个类可以理解为一个储物柜,每种物品放一格,可以用于商店的库存,玩家的物品格等。


__init__函数

名字
类型
描述
例子
stock
dict(字典)
所有物品
{FOX: 10}


__str__函数
这个函数是用来在控制台debug的时候,可以打印出目前仓库里所有的东西和数量。

剩下的函数解释请看代码中的注释。

商店Shop (ShopClass.rpy)
名字
类型
描述
例子
inventory
Inventory
所有物品
参考上面Inventory的讲解

剩下的函数解释请看代码中的注释。
玩家Player(PlayerClass.rpy)
名字
类型
描述
例子
name
string
玩家的名字
“black pineapple”
intelligence
int
智力
5
fitness
int
身材
5
charisma
int
魅力
5
money
int
金钱
1000

函数定义请参考代码内注释

GridHelper(GridHelper.rpy)
这个函数是用来计算,格子的数量,配合grid关键字使用。

MINIMUM_NUM_ROWS 是格子至少有多少行,比如物品比较少的时候可能只有1行,但是制作者可以指定至少显示2行。

NUM_COLUMN 是有多少列。



评分

参与人数 1活力 +300 干货 +3 收起 理由
被诅咒的章鱼 + 300 + 3 感谢分享!

查看全部评分

发表于 2022-6-10 00:30:13 | 显示全部楼层
感谢分享,希望制作出更多的作品  
回复 支持 反对

使用道具 举报

发表于 2022-6-26 14:50:37 | 显示全部楼层
斯国一,太爱这种干货了
回复 支持 反对

使用道具 举报

发表于 2022-6-28 06:01:35 | 显示全部楼层
厉害了干货,感谢ll制作
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-7-17 10:48:33 | 显示全部楼层
因为好多人用不了github,下面是全部的代码。
物品声明 shop_items.rpy
[RenPy] 纯文本查看 复制代码
define CAT = BoosterItem(name='cat', description='可以增加{color=#F37459}10点智力{/color}',
    price=10,
    booster=dict(
        intelligence = 10,
        fitness = 10
    ))

define CHICKEN = BoosterItem(name='chicken', description='可以增加{color=#F37459}1点身材{/color}',
    price=80,
    booster=dict(
        fitness = 1
    ))

define DEER = BoosterItem(name='deer', description='可以增加{color=#F37459}5点魅力{/color}',
    price=18,
    booster=dict(
        charisma = 5
    ))

define DOG = BoosterItem(name='dog', description='可以增加{color=#F37459}20点身材{/color}',
    price=18,
    booster=dict(
        fitness = 20
    ))

define ELEPHANT = BoosterItem(name='elephant', description='可以增加{color=#F37459}10点身材{/color}',
    price=18,
    booster=dict(
        fitness = 10
    ))

define FOX = BoosterItem(name='fox', description='可以增加{color=#F37459}10点身材{/color}',
    price=18,
    booster=dict(
        fitness = 10
    ))

define MONKEY = BoosterItem(name='monkey', description='可以增加{color=#F37459}10点身材{/color}',
    price=18,
    booster=dict(
        fitness = 10
    ))

define OWL = BoosterItem(name='owl', description='可以增加{color=#F37459}10点身材{/color}',
    price=10,
    booster=dict(
        charisma = 10
    ))

define PANDA = BoosterItem(name='panda', description='可以增加{color=#F37459}10点魅力{/color}',
    price=10,
    booster=dict(
        charisma = 10
    ))

define PIG = BoosterItem(name='pig', description='可以增加{color=#F37459}10点魅力{/color}',
    price=2,
    booster=dict(
        charisma = 10
    ))

define RABBIT = BoosterItem(name='rabbit', description='可以增加{color=#F37459}10点智力{/color}',
    price=1,
    booster=dict(
        intelligence = 10
    ))

define RACCOON = BoosterItem(name='raccoon', description='可以增加{color=#F37459}10点智力{/color}',
    price=1,
    booster=dict(
        intelligence = 10
    ))

define SHEEP = BoosterItem(name='sheep', description='可以增加{color=#F37459}10点智力{/color}',
    price=1,
    booster=dict(
        intelligence = 10
    ))

define SQUIRREL = BoosterItem(name='squirrel', description='可以增加{color=#F37459}10点智力{/color}',
    price=1,
    booster=dict(
        intelligence = 10
    ))

回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-7-17 10:49:27 | 显示全部楼层
商店的声明
[RenPy] 纯文本查看 复制代码
init:
    define TOY_STORE_ITEMS = [
        (CAT, float('inf')),
        (CHICKEN, 10),
        (DEER, 10),
        (DOG, 2),
        (ELEPHANT, 2),
        (FOX, float('inf')),
        (MONKEY, float('inf')),
        (OWL, float('inf')),
        (PANDA, 1),
        (RACCOON, 1),
        (SHEEP, 1),
        (SQUIRREL, 1),
        (PIG, float('inf')),
        (RABBIT, float('inf')),
    ]
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-7-17 10:50:07 | 显示全部楼层
提示信息的screen
[RenPy] 纯文本查看 复制代码
init -1 python:
    def get_hovered(name):
        return im.MatrixColor(ImageReference(name), im.matrix.brightness(0.1))


screen information(msg):
    zorder 3

    button:
        xysize (1280, 720)
        action Return()

    frame:
        background Frame("gui/store/store_info_base.png")
        xysize (400, 400)
        xalign 0.5
        yalign 0.5

        text msg:
            xalign 0.5
            yalign 0.5
            outlines [ (absolute(4), "#000", absolute(2), absolute(0)) ]
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-7-17 10:50:51 | 显示全部楼层
辅助计算用多少空白填充grid格子的类
[RenPy] 纯文本查看 复制代码
init -2 python:
    class GridHelper:
        MINIMUM_NUM_ROWS = 2
        NUM_COLUMN = 3

        # 计算需要有多少空白格子来补位。
        @classmethod
        def get_num_fill(cls, total):
            return GridHelper.get_num_row(
                total) * GridHelper.NUM_COLUMN - total

        # 计算有多少行
        @classmethod
        def get_num_row(cls, total):
            return max(GridHelper.MINIMUM_NUM_ROWS,
                (total + GridHelper.NUM_COLUMN - 1) / GridHelper.NUM_COLUMN)
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-7-17 10:51:49 | 显示全部楼层
用来做背包逻辑的类,商店和玩家背包都有基于此类
[RenPy] 纯文本查看 复制代码
init -1 python:
    from collections import defaultdict
    class Inventory:
        def __init__(self):
            # dict(字典)
            # e.g. {FOX: 10}
            self.stock = defaultdict(int)

        # 这个函数是用来在控制台debug的时候,可以打印出目前仓库里所有的东西和数量。
        def __str__(self):
            res = ""
            for item in self.stock:
                res += item.name + ' ' + str(self.stock[item])
            return res

        # 检查物品是否存在,如果不存在,程序会直接报错。
        def check_item_exit(self, item):
            if not item in self.stock:
                raise Exception('Bag: item {:s} not in bag.', item.name)

        # 某种物品的数量增加1,或者增加count个,如果不传入count,就是增加1个。
        def add(self, item, count=1):
            self.stock[item] += count

        # 某种物品的数量减少1,或者减少count个
        def remove(self, item, count=1):
            self.check_item_exit(item)

            if self.stock[item] < count:
                raise "There is not enough {:s}".format(item.name)

            self.stock[item] -= count

        # 获得这个物品有几个
        def get_num_item(self, item):
            self.check_item_exit(item)
            return self.stock[item]

        # 返回背包里的物品,如果filter_empty是True,不返回数量为0的物品。
        def get_items(self, filter_empty=False):
            if filter_empty:
                return [x for x in self.stock.keys() if self.stock[x]]
            return self.stock.keys()
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-7-17 10:54:23 | 显示全部楼层
物品的class,大家可以写出适合自己情况的class。
我这里的情况是,用物品加属性。

[RenPy] 纯文本查看 复制代码
init -1 python:
    from collections import defaultdict
    class Item(object):
        def __init__(self, name, img):
            # 物品名字 (string)e.g. "fox"
            self.name = name

            # 物品图片 (string) e.g. "images/items/fox.png"
            self.img = img

        # 因为后面用了item这个类来做字典的键值,所以需要这两个函数,用来比较两个物品对象是不是一个物品。
        def __eq__(self, another):
            return hasattr(another, 'name') and self.name == another.name

        # 因为后面用了item这个类来做字典的键值,所以需要这两个函数,用来比较两个物品对象是不是一个物品。
        def __hash__(self):
            return hash(self.name)

        # 返回一个物品图片位置的字符串。e.g. “images/items/fox.png”
        def get_icon(self):
            return self.img

    class BoosterItem(Item):
        def __init__(self, name, price, booster, description=""):
            super(BoosterItem, self).__init__(name,
                'images/items/' + name + '.png')

            # 物品描述 (string)
            # e.g. “可以增加{color=#F37459}10点智力{/color}”
            self.description = description

            # 物品价格 (int)
            # 20
            self.price = price

            # 物品可以提升的属性,这个属性,需要和player class里的成员变量相对应。
            # dict
            # e.g. dict(charisma = 5)
            self.booster = booster

        # 这个函数会根据这个物品的booster属性,增加使用者对应的属性。
        def use(self, player):
            for attribute in self.booster:
                player.increase_by(attribute, self.booster[attribute])
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2022-8-8 21:30 , Processed in 0.049385 second(s), 13 queries , File On.

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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