游戏系统

游戏内商店:橱窗、商品和价格

iDos Games 现成商店的运作方式:商品轮换的橱窗、用游戏货币或真实货币定价、免费礼物和购买限制,以及如何在后台无需代码完成设置。

商店是一个现成的系统:你游戏里的商店界面加上服务器端的购买逻辑。 你在后台设置橱窗和商品,每次购买时服务器都会自行检查价格、限购和轮换。购买无法在游戏中伪造,商店也不需要你自己的服务器。

玩家看到什么

  • 以标签页呈现的橱窗。 橱窗的第一个分区是轮播,其余是卡片网格。
  • 免费的每日礼物,领取前一直高亮。
  • 卡片上的计时器:“刷新倒计时”“开放倒计时”“已售罄”。
  • 购买确认弹窗(在手机上是底部弹出面板)。
  • “你获得了”动画:奖励飞向余额计数器。
  • 有免费商品待领取时,商店标签页上的徽标。
商店
12 450
320
每日1
货币
卡包
每日特惠 15:40:12 后刷新
每日礼物
免费
英雄之剑
1 200
装备宝箱
90
已售罄
500 金币
$0.99
最划算1 200 金币
$1.99
首购 x2
橱窗以标签页显示;徽标显示待领取的免费商品数。
轮换计时:结束时服务器会更换该槽位的商品。
免费每日礼物在领取前一直高亮。
“已售罄”:本时段的限购已用完。
角标和首购奖励来自商品设置。
示例. 玩家看到的商店界面,默认外观。外观在 src/ui.config.ts 中修改。

商店的结构

商店是一棵树:橱窗 → 分区 → 槽位 → 商品。

  • 商品:出售的东西,包括价格、奖励、限购、角标(“最划算”“x2”)。所有商品都放在同一个目录中。
  • 槽位:橱窗货架上的一个位置。商品只能通过槽位购买:不在任何槽位中的商品根本不会出售。
  • 轮换:槽位可以从一个商品池中展示商品,并按计划更换,就像每日商店。轮换由服务器计算,所以玩家在每台设备上看到的商店都一样。
橱窗“每日商店”
分区“每日特惠”
槽位
槽位 1:始终是每日礼物
槽位 2:6 个商品之一,每 24 小时更换
槽位 3:时段开启前为空
商品目录价格、奖励、限购
不在任何槽位中的商品不会出售
示例. 在后台中如何搭建橱窗:商品只能通过槽位出售。

价格

玩家支付什么如何运作
游戏货币、物品从玩家余额中扣除
真实货币在应用商店中购买;服务器验证收据
观看广告玩家消耗自己获得的一次广告观看(带广告的构建)
不付费免费商品;必须设置限购,否则服务器不会出售

你可以显示划线的“原价”,折扣百分比由服务器计算。一个商品可以有多个价格选项,例如金币或宝石。

购买限制

  • 终身:例如新手礼包只能买一次。
  • 每天:在 UTC 午夜重置。
  • 冷却:间隔一段时间后才能再次购买。
  • 每个轮换时段:商品在货架上期间该槽位的限购。

“首购”和“已售罄”标记以及计时器由服务器为每位玩家计算。

步骤 01把商店加入项目

放置 RPG 模板已经有一个带示例橱窗的商店。在其他任何项目中,由 AI 编程助手来添加:在聊天中写“加一个商店”。它会安装现成的系统,而不是从头写一个商店。有东西可卖之后,商店标签页才会对玩家显示。

步骤 02设置商品和橱窗

打开后台,选择你的项目,进入 实时运营 → v2 → 商店。

  • 在商品标签页创建商品:名称、价格、玩家获得什么以及限购。
  • 在橱窗标签页创建橱窗,为它添加分区和槽位,并把商品放进槽位。
  • 预设是可以一次应用到多个商品的共享设置。

后台会提醒没有槽位的商品和没有限购的免费商品。页面上的 AI 按钮会打开助手:描述你想卖什么(“一个 0.99 美元的 500 金币礼包和一个每日免费宝箱”),它会提出修改,你检查后点击保存。

步骤 03测试并发布

在应用的测试版中检查商店。设置通过单独的操作发送到正式应用,所以代码发布永远不会覆盖它们。更多内容见发布与链接。

开发者须知

商店通过 @idosgames/core 中的 client.store 工作。根据 getStorefront() 绘制界面:这是已经为当前玩家计算好的橱窗(轮换、限购、计时)。getDefinitions() 只是配置,对所有人都一样。

TypeScript
const res = await client.store.getStorefront()
if (!res.ok) return showError(res.error)

for (const store of res.data.Stores ?? [])
  for (const section of store.Sections ?? [])
    for (const slot of section.Slots ?? []) {
      // 空槽位会以 Offer === null 返回:绘制一个空框,避免货架跳动。
      if (!slot.Offer) continue
      drawCard(slot.Offer, slot.RefreshesAtUtc)
    }

const buy = await client.store.purchase(offer.OfferID, 1, {
  selectedOptionID: option.OptionID,
  slot: { storeID: store.StoreID, sectionID: section.SectionID, slotID: slot.SlotID },
})
  • 如果购买返回 OFFER_NOT_IN_ROTATION,说明橱窗已变化:直接重新加载,不要显示错误。
  • 请求进行中时禁用“购买”按钮:每次调用 purchase 都是一次单独的购买。
  • 计时器从响应中的 ServerTimeUtc 开始倒数,而不是设备时钟。
  • 剩余限购为 null 表示“不限”,0 表示“已售罄”。

每个字段都在技能 store-system 中有说明,由 SDK 的 MCP 服务器提供。

常见问题

为什么商品在目录里却买不到?

商品只能通过橱窗槽位购买。如果它不在任何槽位中,就根本无法购买。后台会把这类商品单独列在“不在任何货架上”的警告下。

可以做一个免费的每日礼物吗?

可以。没有价格的商品就是普通的免费商品,但它必须有限购,例如每天一次。服务器拒绝出售没有限购的免费商品。

需要在自己的服务器上验证购买吗?

不需要。iDos Games 服务器会在每次购买时检查价格、限购和轮换。游戏只负责显示橱窗并发起购买。

会员折扣会生效吗?

会。服务器会自动应用会员等级的折扣和加成。游戏从购买响应中读取实际扣除和发放的内容。

另请参阅

制作你自己的游戏

用一句话描述你的想法,AI 编程助手会把它做出来,并以独立链接上线。