Sui 卡牌对战小游戏

1. 背景

学习 Move 基础语法以来,自我感觉需要一个自行设计的小项目练手。

点击试玩

现设计一个卡牌对战小游戏功能如下:

css 复制代码
- [ ] 玩家每次参与对战获取一定对血量和行动值,回合制对战,直到一方血量归 0,游戏结束
- [ ] 卡牌拥有攻击力和防御力,卡牌参与对战后不可再作他用
- [ ] 每回合结束,双方卡牌随机变换攻击力与防御力,全靠运气
- [ ] 玩家每次行动消耗行动值,防守增加行动值
- [ ] 其他

合约部分 页面部分

2. 合约部分

2.1 初始化函数

需要两个共享对象记录卡牌与所有的对局,分别命名为CardRecord, BattleRecord

rust 复制代码
fun init(ctx: &mut TxContext) {
  let battle_record = BattleRecord {
    id: object::new(ctx),
    battles: vector::empty<ID>(),
  };
  let card_record = CardRecord {
    id: object::new(ctx),
    cards: vector::empty<ID>(),
  };

  share_object(battle_record);
  share_object(card_record)
}

2.2 铸造卡牌

rust 复制代码
fun mint_card(clock:&Clock,ctx: &mut TxContext) : Card {
  let (attack, defense) = random_strength_clock(clock);

  Card {
    id: object::new(ctx),
    attack,
    defense,
  }
}

这里用到随机数,有几种生成方式:

  1. 使用 CLOCK或者交易摘要生成;
  2. 使用天气预言机;

简单点就使用CLOCK获取时间戳作为随机数。

rust 复制代码
fun random_strength_clock(clock: &Clock) :(u64, u64){
  let ms = clock::timestamp_ms(clock);
  let random_attack = ms % MAX_ATTACK_DEFEND_STRENGTH;
  if (random_attack == 0) {
    random_attack = MAX_ATTACK_DEFEND_STRENGTH / 2;
  };

  (random_attack, MAX_ATTACK_DEFEND_STRENGTH - random_attack)
}

2.3 创建对局

结构体定义

rust 复制代码
struct Battle has key,store {
  id: UID,
  name: String,
  status: u64, // 记录对局状态
  cards: Table<address, Card>, // 对战人卡片
  players: vector<address>, // 玩家
  player_status: Table<address, PlayerStatus>, // 双方状态
  moves: Table<address, u64>, // 当前回合行动,判断是否回合结束
  winer: Option<address>,
}

2.4 行动

对应函数public entry fun move_choice(choice: u64, battle: &mut Battle, ctx: &mut TxContext)

当双方行动结束时结算当前玩家状态,对应函数fun resolve_battle(battle:&mut Battle,ctx: &TxContext)

2.5 部署到测试网

记录以下三个值

bash 复制代码
TESTNET_CARD_PACKAGE_ID = "0x43c21577794c10f7f36d3269d50736c45f9dc4d0c77e3c7d0f219b0a3fd0ae4d";

CARD_RECORD: string = "0x7d6444bffd59a7b348613637422a1f335305204e4fea5be1d86d325c3eaf108b";

BATTLE_RECORD = "0x2b1b5fc902bf675dc6acf48b61a13a27989383c4f9fba460c03c103c41faf800";

3. 页面部分

3.1 如何获取到对局中的玩家状态

思路:全剧共享对象BattleRecord获取到Battle_id,拿到当前对象。

接下来要用到动态字段获取才能知道玩家状态数据,这个过程需要多次查询请求。

jsx 复制代码
// 获取对局对象
const { battleData } = useSuiClientQuery("getObject", {
    id: battleId ? battleId : "",
    options: {
      showContent: true,
      showOwner: true,
    },
});

// 通过 table_id 获取内容
const { players } = client.getDynamicFields({
    parentId: battleData.player_status.fields.id.id,
})

4. 试玩

4.1 铸造卡牌

打开页面,首先连接钱包登陆。 点击Mint Card For Free铸造卡牌,稍等一会即可在All Your Cards区域看到你的卡牌。

4.2 创建对局

点击Begin Game跳转到新页面,输入房间名(仅英文)创建对局,此时默认使用你的第一张卡牌放入对局中(此卡牌已转移所有权,不再属于你)。

点击Join可以进入房间

4.2 另一玩家加入对局

另准备一个钱包地址,Mint Card --> Begin Game --> Join,即可加入目标房间进行战斗,默认使用你的第一张卡牌。

4.3 行动

接下来双方分别进行攻击和防御操作,直到一方血量归零,决出胜负为止。


星航计划 QQ群:79489587

相关推荐
Jerry.张蒙11 小时前
SAP业财一体化实现的“隐形桥梁”-价值串
大数据·数据库·人工智能·学习·区块链·aigc·运维开发
Biteagle14 小时前
SNARK的信任魔法:从「毒性仪式」到以太坊隐私圣杯
web3·区块链·智能合约
小明的小名叫小明16 小时前
区块链核心知识点梳理(11)- EVM 原理深度解析
区块链
古城小栈18 小时前
Spring Boot 集成区块链:智能合约调用接口开发全解析
spring boot·区块链·智能合约
软件工程小施同学20 小时前
区块链可投会议CCF A--ISSTA 2026 截止1.29 附录用率
区块链
fyihdg1 天前
在REMIX中使用OpenZeppelin集成透明升级合约和在HARDHAT中集成透明升级合约演示
区块链·智能合约
唐僧洗头爱飘柔95271 天前
【区块链技术(06)】为什么分布式系统会存在数据一致性问题?本文带你理解:CAP和FLP定理、拜占庭将军问题;Paxos和Raft两种分布式算法
分布式·区块链·数据一致性·raft算法·cap定理·paxos算法·拜占庭将军问题
野老杂谈1 天前
【Solidity学习】合约基本结构与状态变量
学习·区块链
小明的小名叫小明1 天前
区块链核心知识点梳理(6)-区块链浏览器解读
区块链
Sui_Network1 天前
备受期待的 POP 射击游戏 XOCIETY 正式在 Epic Games Store 开启体验
人工智能·游戏·rpc·区块链·量子计算·graphql