Solana 游戏开发入门指南:构建你的第一个链上小游戏

·

本文将引导你使用 Solana 区块链和 Anchor 框架创建一个简单的链上游戏 "Tiny Adventure"。无需本地安装任何开发环境,我们将直接使用 Solana Playground 这一在线 IDE 完成编写、构建和部署的全过程。通过这个项目,你将学会如何创建基础游戏逻辑、存储玩家状态并与之交互。

开发环境与工具准备

我们将使用 Solana Playground 这一基于浏览器的集成开发环境。它省去了复杂的本地配置步骤,让开发者能专注于代码逻辑。

访问 Solana Playground 并创建新的 Anchor 项目。初次使用时,你需要创建一个 Playground 钱包并确保连接到 Devnet 测试网络。运行 solana airdrop 5 即可获取测试用 SOL 代币。

游戏程序结构与初始化

游戏的核心逻辑是一个 Solana 程序(智能合约),使用 Rust 语言和 Anchor 框架编写。

初始程序代码

创建项目后,将 lib.rs 文件中的默认代码替换为以下基础结构:

use anchor_lang::prelude::*;

declare_id!("11111111111111111111111111111111");

#[program]
mod tiny_adventure {
    use super::*;
    // 指令处理程序将在这里定义
}

// 结构体将在这里定义

fn print_player(player_position: u8) {
    if player_position == 0 {
        msg!("A Journey Begins!");
        msg!("o.......");
    } else if player_position == 1 {
        msg!("..o.....");
    } else if player_position == 2 {
        msg!("....o...");
    } else if player_position == 3 {
        msg!("........\\o/");
        msg!("You have reached the end! Super!");
    }
}

这个游戏开始时玩家位于位置 0,可以通过指令向左或向右移动。我们将使用消息日志来显示玩家的进度。

定义游戏数据账户

我们需要定义一个链上账户结构来存储玩家位置:

// 定义游戏数据账户结构
#[account]
pub struct GameDataAccount {
    player_position: u8,
}

该结构包含一个字段 player_position,以无符号 8 位整数存储玩家的当前位置。

程序指令设计

Tiny Adventure 程序包含三个指令处理器:

初始化指令

初始化指令负责创建 GameDataAccount(如果尚不存在),将 player_position 设置为 0,并打印初始消息。

// 初始化GameDataAccount并将位置设置为0的指令
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
    ctx.accounts.new_game_data_account.player_position = 0;
    msg!("A Journey Begins!");
    msg!("o.......");
    Ok(())
}

初始化指令需要三个账户:

我们使用程序派生地址(PDA)作为 GameDataAccount 的地址,使用单个固定值 "level1" 作为种子。这种设计允许我们确定性地定位地址,但限制了程序只能创建一个 GameDataAccount。

向左移动指令

move_left 指令让玩家更新其位置:向左移动意味着将 player_position 减 1,最低位置为 0。

// 向左移动的指令
pub fn move_left(ctx: Context<MoveLeft>) -> Result<()> {
    let game_data_account = &mut ctx.accounts.game_data_account;
    if game_data_account.player_position == 0 {
        msg!("You are back at the start.");
    } else {
        game_data_account.player_position -= 1;
        print_player(game_data_account.player_position);
    }
    Ok(())
}

向右移动指令

类似地,move_right 指令将 player_position 加 1,最高位置限制为 3。

// 向右移动的指令
pub fn move_right(ctx: Context<MoveRight>) -> Result<()> {
    let game_data_account = &mut ctx.accounts.game_data_account;
    if game_data_account.player_position == 3 {
        msg!("You have reached the end! Super!");
    } else {
        game_data_account.player_position = game_data_account.player_position + 1;
        print_player(game_data_account.player_position);
    }
    Ok(())
}

构建与部署

完成程序代码后,在 Solana Playground 中构建并部署程序。确保你已创建 Playground 钱包并连接到 Devnet 端点,且有足够的 SOL 用于部署。

👉 查看实时开发工具

客户端交互实现

现在我们将创建一个简单的客户端实现来与游戏交互。

派生游戏数据账户地址

首先,使用 findProgramAddress 函数派生 GameDataAccount 的 PDA:

// 每个人都可以通过这个PDA地址控制角色(如果与你的程序交互)
const [globalLevel1GameDataAccount, bump] = 
  await anchor.web3.PublicKey.findProgramAddress(
    [Buffer.from("level1", "utf8")],
    pg.program.programId,
  );

初始化游戏状态

接下来,尝试使用上一步的 PDA 获取游戏数据账户。如果账户不存在,我们将通过调用程序中的 initialize 指令来创建它。

左右移动功能

通过调用程序的 moveLeftmoveRight 指令并与 Solana 网络提交交易,实现与游戏的交互。你可以多次重复此步骤,每次都会在链上执行移动逻辑并更新玩家状态。

记录玩家位置

使用 switch 语句根据 gameDateAccount 中存储的 playerPosition 值记录角色位置,作为游戏中角色移动的视觉表示。

运行客户端程序

在 Solana Playground 中点击 "Run" 按钮运行客户端。输出应类似于:

Running client...
client.ts:
My address: 8ujtDmwpkQ4Bp4GU4zUWmzf65sc21utdcxFAELESca22
My balance: 4.649749614 SOL
Use 'solana confirm -v 4MRXEWfGqvmro1KsKb94Zz8qTZsPa9x99oMFbLBz2WicLnr8vdYYsQwT5u3pK5Vt1i9BDrVH5qqTXwtif6sCRJCy' to see the logs
Player position is: 1
... .o. ...

恭喜!你已成功从客户端构建、部署并调用了 Tiny Adventure 游戏。

进阶开发建议

完成基础游戏后,你可以发挥创意,独立实现自己的创意来丰富游戏体验:

  1. 修改游戏内文本,创建有趣的故事线。邀请朋友体验你设计的叙事,并观察链上交易的展开!
  2. 添加宝箱系统,用 SOL 奖励玩家,或让玩家在游戏进程中收集硬币并与代币交互
  3. 创建网格系统,允许玩家上下左右移动,并引入多个玩家以获得更动态的体验

常见问题

什么是 Solana Playground?

Solana Playground 是一个基于浏览器的集成开发环境,允许开发者无需本地安装即可编写、构建和部署 Solana 程序。它特别适合初学者和快速原型开发。

程序派生地址(PDA)有什么作用?

PDA 是一种特殊类型的地址,格式类似于公钥,但不由私钥控制。它们由程序 ID 和额外种子派生而来,允许程序以确定性的方式管理账户,而不需要私钥签名。

如何让每个玩家拥有独立的游戏状态?

在当前实现中,我们使用固定种子 "level1" 生成 PDA,这意味着所有玩家共享同一个游戏状态。要让每个玩家拥有独立状态,可以使用签名者的地址作为额外种子。

如何扩展这个基础游戏?

你可以添加更多移动方向、引入物品系统、设计多关卡进度或集成代币经济系统。Solana 的高性能和低交易成本为链上游戏开发提供了广阔可能性。

在哪里可以获取测试网 SOL?

在 Solana Playground 中,可以使用 solana airdrop 5 命令获取 Devnet 测试网 SOL。如果失败,可以尝试其他 Devnet 水龙头获取测试代币。

后续学习路径

完成本教程后,你可以继续学习 Tiny Adventure 游戏的第二部分,了解如何在程序中存储 SOL 并将其作为奖励分发给玩家。此外,还可以探索更多 Solana 游戏开发资源,包括入门指南、游戏 SDK、示例项目以及能量系统和 NFT 在游戏中的应用等专题。