TON 区块链适用于游戏
教程内容
在本教程中,我们将探讨如何将 TON 区块链添加到游戏中。作为示例,我们将使用 Phaser 编写的 Flappy Bird 克隆游戏,并逐步添加 GameFi 功能。在教程中,我们将使用短代码片段和伪代码来增加可读性。同时,我们还将提供指向真实代码块的链接,以帮助您更好地理解。完整的实现可以在演示库中找到。
我们将实现以下功能:
- 成就奖励。让我们用 SBTs 奖励我们的用户。成就系统是增加用户参与度的绝佳工具。
- 游戏货币。在 TON 区块链上,启动自己的代币(jetton)很容易。代币可以用来创建游戏内经济。我们的用户将能够赚取游戏币并在之后消费它们。
- 游戏商店。我们将为用户提供使用游戏货币或 TON 代币购买游戏内物品的可能性。
准备工作
安装 GameFi SDK
首先,我们将设置游戏环境。为此,我们需要安装 assets-sdk
。该包旨在准备开发者集成区块链到游戏中所需的一切。该库可以从 CLI 或 Node.js 脚本中使用。在本教程中,我们选择 CLI 方法。
npm install -g @ton-community/assets-sdk@beta
创建主钱包
接下来,我们需要创建一个主钱包。主钱包是我们将用来铸造 jetton、收藏品、NFT、SBT 和接收支付的钱包。
assets-cli setup-env
您将被问及几个问题:
字段 | 提示 |
---|---|
网络 | 选择 testnet ,因为它是测试游戏。 |
类型 | 选择 highload-v2 类型的钱包,因为它是用作主钱包的最佳、最高性能选项。 |
存储 | 用于存储 NFT /SBT 文件的存储。可以选择 Amazon S3 (集中式)或 Pinata (去中心化)。 对于本教程,让我们使用 Pinata ,因为去中心化存储对 Web3 游戏更具说明性。 |
IPFS 网关 | 从中加载资产元数据的服务:pinata 、ipfs.io 或输入其他服务 URL。 |
脚本输出您可以打开的链接,以查看创建的钱包状态。
如您所见,钱包实际上还没有创建。要想钱包真正创建,我们需要往里面存一些资金。在现实世界场景中,您可以使用任何喜欢的方式通过钱包地址存入钱包。在我们的案例中,我们将使用 Testgiver TON Bot。请打开它领取 5 个测试 TON 代币。
稍后您将看到钱包中有 5 个 TON,并且其状态变为 Uninit
。钱包准备就绪。首次使用后,其状态会变为 Active
。
铸造游戏货币
我们打算创建游戏货币,以奖励用户:
assets-cli deploy-jetton
您将被问及几个问题:
字段 | 提示 |
---|---|
名称 | 代币名称,例如 Flappy Jetton 。 |
描述 | 代币描述,例如:来自 Flappy Bird 宇宙的生动数字代币。 |
图片 | 下载预备好的 jetton 标志 并指定文件路径。当然,您也可以使用任何图片。 |
符号 | FLAP 或输入您想使用的任何缩写。 |
小数位 | 货币小数点后将有多少个零。在我们的案例中,让它为 0 。 |
脚本输出您可以打开的链接,以查看创建的 jetton 状态。它将具有 Active
状态。钱包状态将从 Uninit
变为 Active
。
为 SBT 创建收藏品
仅作为示例,演示游戏中我们将奖励用户玩第一次和第五次游戏。因此,我们将铸造两个收藏品,以便在用户达到相关条件(第一次和第五次玩游戏)时将 SBT 放入其中:
assets-cli deploy-nft-collection
字段 | 第一次游戏 | 第五次游戏 |
---|---|---|
类型 | sbt | sbt |
名称 | Flappy First Flight | Flappy High Fiver |
描述 | 纪念您在 Flappy Bird 游戏中的首次旅行! | 以 Flappy High Fiver NFT 庆祝您的持续游戏! |
图片 | 您可以在此处下载图片 | 您可以在此处下载图片 |
我们已经做好充分准备。接下来,让我们进入逻辑实现。
连接钱包
一切从用户连接其钱包开始。因此,让我们添加钱包连接集成。要从客户端操作区块链,我们需要为 Phaser 安装 GameFi SDK:
npm install --save @ton/phaser-sdk@beta
现在,让我们设置 GameFi SDK 并创建它的实例:
import { GameFi } from '@ton/phaser-sdk'
const gameFi = await GameFi.create({
network: 'testnet'
connector: {
// if tonconnect-manifest.json is placed in the root you can skip this option
manifestUrl: '/assets/tonconnect-manifest.json',
actionsConfiguration: {
// address of your Telegram Mini App to return to after the wallet is connected
// url you provided to BothFather during the app creation process
// to read more please read https://github.com/ton-community/flappy-bird#telegram-bot--telegram-web-app
twaReturnUrl: URL_YOU_ASSIGNED_TO_YOUR_APP
},
contentResolver: {
// some NFT marketplaces don't support CORS, so we need to use a proxy
// you are able to use any format of the URL, %URL% will be replaced with the actual URL
urlProxy: `${YOUR_BACKEND_URL}/${PROXY_URL}?url=%URL%`
},
// where in-game purchases come to
merchant: {
// in-game jetton purchases (FLAP)
// use address you got running `assets-cli deploy-jetton`
jettonAddress: FLAP_ADDRESS,
// in-game TON purchases
// use master wallet address you got running `assets-cli setup-env`
tonAddress: MASTER_WALLET_ADDRESS
}
},
})
要了解更多关于初始化选项,请阅读库文档。
要了解什么是
tonconnect-manifest.json
,请查看 ton-connect manifest描述。
现在我们准备创建一个连接钱包按钮。让我们在 Phaser 中创建一个 UI 场景,该场景将包含连接按钮:
class UiScene extends Phaser.Scene {
// receive gameFi instance via constructor
private gameFi: GameFi;
create() {
this.button = this.gameFi.createConnectButton({
scene: this,
// you can calculate the position for the button in your UI scene
x: 0,
y: 0,
button: {
onError: (error) => {
console.error(error)
}
// other options, read the docs
}
})
}
}
要监控用户何时连接或断开其钱包,让我们使用以下代码片段:
function onWalletChange(wallet: Wallet | null) {
if (wallet) {
// wallet is ready to use
} else {
// wallet is disconnected
}
}
const unsubscribe = gameFi.onWalletChange(onWalletChange)
要了解更多复杂场景,请查看钱包连接流程的完整实现。
阅读如何实现游戏 UI 管理。
现在我们已经连接了用户钱包,可以继续进行了。
实现成就和奖励
为了实现成就和奖励系统,我们需要准备一个端点,每个用户尝试时都会请求该端点。
/played
端点
我们需要创建一个 /played
端点,该端点必须完成以下操作:
- 接收带有用户钱包地址和 Mini App 启动时传递给 Mini App 的 Telegram 初始数据的正文。需要解析初始数据以提取认证数据,并确保用户只代表其自身发送请求。
- 该端点必须计算并存储用户玩的游戏数。
- 该端点必须检查是否是用户的第一次或第五次游戏,如果是,便使用相关的 SBT 奖励用户。
- 该端点必须为每次游戏奖励用户 1 FLAP。
阅读/played 端点的代码。
请求 /played
端点
每次小鸟撞到管道或掉落时,客户端代码必须调用 /played
端点并传递正确的正文:
async function submitPlayed(endpoint: string, walletAddress: string) {
return await (await fetch(endpoint + '/played', {
body: JSON.stringify({
tg_data: (window as any).Telegram.WebApp.initData,
wallet: walletAddress
}),
headers: {
'content-type': 'application/json'
},
method: 'POST'
})).json()
}
const playedInfo = await submitPlayed('http://localhost:3001', wallet.account.address);
阅读submitPlayer 函数的代码。
让我们玩第一次,确保我们将获得 FLAP 代币和 SBT 的奖励。点击 Play 按钮,穿过一个或两个管道,然后撞到一个管道上。好的,一切都在工作!
再次玩 4 次以获得第二个 SBT,然后打开您的钱包,TON Space。这里是您的收藏品:
实现游戏商店
要拥有游戏内商店,我们需要两个组件。第一个是提供关于用户购买的信息的端点。第二个是全局循环,以监视用户交易并为其所有者分配游戏属性。
/purchases
端点
该端点执行以下操作:
- 接收带有 Telegram Mini Apps 初始数据的
auth
get 参数。 - 该端点获取用户购买的物品并以物品列表的形式做出响应。
阅读/purchases端点的代码。
购买循环
要知道用户何时进行支付,我们需要监视主钱包的交易记录。每笔交易都必须包含消息 userId
:itemId
。我们将记住最后处理的交易,只获取新的交易,使用 userId
和 itemId
为用户分配他们购买的属性,重写最后一笔交易的哈希。这将在无限循环中工作。
阅读购买循环的代码。
客户端的商店
在客户端,我们有进入商店的按钮。
当用户点击按钮时,将打开商店场景。商店场景包含用户可以购买的物品列表。每个物品都有价格和购买按钮。当用户点击购买按钮时,将进行购买。
打开商店会触发购买商品的加载,并每 10 秒更新一次:
// inside of fetchPurchases function
await fetch('http://localhost:3000/purchases?auth=' + encodeURIComponent((window as any).Telegram.WebApp.initData))
// watch for purchases
setTimeout(() => { fetchPurchases() }, 10000)
阅读showShop 函数的代码。
现在我们需要实现购买本身。为此,我们首先将创建 GameFi SDK 实例,然后使用 buyWithJetton
方法:
gameFi.buyWithJetton({
amount: BigInt(price),
forwardAmount: BigInt(1),
forwardPayload: (window as any).Telegram.WebApp.initDataUnsafe.user.id + ':' + itemId
});
也可以用 TON 代币支付:
import { toNano } from '@ton/phaser-sdk'
gameFi.buyWithTon({
amount: toNano(0.5),
comment: (window as any).Telegram.WebApp.initDataUnsafe.user.id + ':' + 1
});
后记
本教程到此结束!我们考虑了基本的 GameFi 功能,但 SDK 提供了更多功能,如玩家之间的转账、操作 NFT 和收藏品的工具等。将来我们会提供更多功能。
要了解所有可用的 GameFi 功能,请阅读 ton-org/game-engines-sdk 和 @ton-community/assets-sdk 的文档。
所以,请在讨论区告诉我们您的想法!
完整的实现可在 flappy-bird 库中找到。