## Vara Network 链上游戏案例
<img src="https://hackmd.io/_uploads/ByRqBZKbR.png" width="640" alt="GEAR">
### Racing Cars
https://racing.vara.network
---
<img src="https://hackmd.io/_uploads/S1m9BbY-C.png" width="1200" alt="GEAR">
---
<img src="https://hackmd.io/_uploads/HkktUbKWA.png" width="1200" alt="GEAR">
---
<img src="https://hackmd.io/_uploads/ryAJw-F-A.png" width="1200" alt="GEAR">
---
## 游戏实例 (GameInstance)
```
pub struct Game {
pub cars: BTreeMap<ActorId, Car>,
pub car_ids: Vec<ActorId>,
pub current_turn: u8,
pub state: GameState,
pub result: Option<GameResult>,
pub current_round: u32,
pub last_time_step: u64,
}
```
向入口函数发送消息更新游戏状态:
- Init: `In<GameInit>`
- Handle: `InOut<GameAction, Result<GameReply, GameError>>`
---
## 初始状态 (Init)
```
#[no_mangle]
extern fn init() {
let init_msg: GameInit = msg::load().expect("Unable to load the message");
unsafe {
CONTRACT = Some(Contract {
admins: vec![msg::source()],
config: init_msg.config,
games: HashMap::with_capacity(20_000),
msg_id_to_game_id: HashMap::with_capacity(5_000),
..Default::default()
});
}
}
```
---
## 游戏动作
```
#[derive(Encode, Decode, TypeInfo, Debug)]
pub enum StrategyAction {
BuyAcceleration,
BuyShell,
Skip,
}
```
---
```
impl Game {
pub fn buy_acceleration(&mut self) {
let car_id = self.get_current_car_id();
let car = self.cars.get_mut(&car_id).expect("Get Car: Can't be None");
car.speed = car.speed.saturating_add(DEFAULT_SPEED);
car.car_actions.push(RoundAction::Accelerated);
}
pub fn buy_shell(&mut self) {
let car_id = self.get_current_car_id();
let shelled_car_id = self.find_car_to_shell(&car_id);
self.cars.entry(shelled_car_id).and_modify(|car| {
let new_speed = car.speed.saturating_sub(DEFAULT_SPEED);
car.speed = new_speed.max(DEFAULT_SPEED);
car.car_actions.push(RoundAction::SlowedDown);
});
}
```
---
## 更新状态
```
pub fn update_positions(&mut self, config: &Config) {
...
}
```
---
## 玩家逻辑
```
impl Game {
fn player_move(
&mut self,
msg_src: &ActorId,
strategy_move: StrategyAction,
) -> Result<GameReply, GameError> {
let game = self.get_game(msg_src);
if game.state != GameState::PlayerAction {
return Err(GameError::NotPlayerTurn);
}
match strategy_move {
StrategyAction::BuyAcceleration => {
game.buy_acceleration();
}
StrategyAction::BuyShell => {
game.buy_shell();
}
StrategyAction::Skip => {}
}
...
}
```
---
## 机器人算法
car-1: 一直加速
car-2: 加权随机
car-3: 按位置决定操作
---
## 状态清理
游戏结束一分钟后自动清理链上状态
```
fn send_messages(account: &ActorId, config: &Config) {
msg::send_with_gas_delayed(
exec::program_id(),
GameAction::RemoveGameInstance {
account_id: *account,
},
config.gas_to_remove_game,
0,
config.time_interval,
)
.expect("Error in sending message");
}
```
---
## References
https://wiki.gear-tech.io/docs/examples/Gaming/racingcars/
https://wiki.gear-tech.io/docs/developing-contracts/interactions-between-programs/
https://github.com/gear-foundation/dapps/tree/master/contracts/car-races
---
# Questions
<img src="https://hackmd.io/_uploads/SyK8P72d2.jpg" width="240" alt="GEAR">
<img src="https://hackmd.io/_uploads/By_kgE3_2.png" width="240" alt="VARA">
课后答疑频道: https://t.me/Gear_CN
{"title":"Racing Cars","slideOptions":"{\"theme\":\"dark\",\"spotlight\":{\"enabled\":false},\"width\":1600,\"height\":900}","description":"Racing Cars","image":"https://hackmd.io/_uploads/HJRhVbYZ0.png","contributors":"[{\"id\":\"94262fbf-81ae-4ed7-933c-561a41bd977a\",\"add\":8257,\"del\":4536}]"}