저자: Magicblock, 출처: MetaCat
이 문서에서는 컴포넌트 재사용성을 촉진하는 Bolt 엔진의 엔티티 컴포넌트 시스템(ECS)을 사용하여 개발한 간단한 게임 예제를 보여드립니다. 사용자가 게임의 로직을 수정하고 확장할 수 있도록 지원합니다.
이 프레임워크는 계정 공간 및 프로그램 파생 주소와 같은 기본 개념을 추상화하여 솔라나 기반 개발을 크게 간소화합니다. 앵커 기반 프로그램과 비교하려면 이 튜토리얼을 참조하세요.
https://book.anchor-lang.com/anchor_in_depth/milestone_project_tic-tac-toe.html
볼트에 대한 자세한 설명은 공지사항 블로그 게시글을 참조하세요.
https://blog.magicblock.gg/bolt-v0.1/
개발 중인 틱택토
이 글의 첫 번째 부분에서는 Bolt 프레임워크를 사용하여 게임 로직을 구현하는 방법을 자세히 설명합니다. 두 번째 파트에서는 오픈 소스 Tic-Tac-Toe 구현부터 시작하여 React 기반 클라이언트를 애플리케이션과 통합하는 방법을 설명합니다.
이 예제의 전체 소스 코드는 여기에서 확인할 수 있나요?
https://github.com/magicblock-labs/bolt-tic-tac-toe
게임 로직: Bolt ECS를 사용하여 틱택토 구현하기 틱택토
먼저, bolt-cli
:
npm install @magicblock-labs/bolt-cli
설치합니다.
설치 후 다음 명령어로 새 프로젝트를 생성합니다:
bolt init tic-tac-toe
Create component ( Component)
필요한 데이터 구조를 정의해야 합니다. 간단하게 하기 위해 활성 플레이어를 포함하는 컴포넌트와 그리드 정보를 포함하는 컴포넌트 두 개를 만들겠습니다.
다음 명령을 사용하여 새 컴포넌트를 생성합니다.
bolt component players이 명령은 program-에 새 컴포넌트를 생성합니다. ecs/components에 플레이어 컴포넌트를 생성합니다. 두 플레이어의 공개 키를 보유하는 플레이어 컴포넌트는 다음과 같이 정의할 수 있습니다:
use bolt_lang::*;declare_id!("5Xz6iiE2FZdpqrvCKbGqDajNYt1tP8cRGXrq3THSFo1q");#[component]#[ 파생(기본값)]pub 구조 플레이어 { pub 플레이어: [옵션<Pubkey>; 2],}
두 번째 컴포넌트는 그리드 정보를 포함합니다. 다음 명령을 사용하여 생성합니다.
bolt component grid
그리드 컴포넌트는 다음과 같이 정의할 수 있습니다.
use bolt_lang::*;declare_. id!("rdiVoU6KomhXBDMLi6UXVHvmjEUtKqb5iDCWChxMzZ7");#[component]pub struct Grid { pub board: [[Option<Sign 3]; 3], pub state: GameState, pub is_first_player_turn: bool,}##[component_deserialize]#[derive(PartialEq)]pub enum GameState {   nbsp; Active, Tie, Won { winner: Pubkey },}##[ component_deserialize]#[derive(PartialEq)]pub enum Sign { X, O,}impl& Sign { pub fn from_usize(value: usize) -> Sign { from_usize(value: usize) -> Sign { △ 앤티 nbsp; match value { 0 => Sign::X, => Sign::O, 그리드에 대한 기본값은 { } }}impl Default { }입니다; fn default() -> Self { Self::new(GridInit{ board: [[None; 3]; 3], [[None; 3], ]) 상태: 게임 상태::활성, 게임 상태::활성 is_first_player_turn: true, }) }}
시스템 생성
시스템은 모듈 방식으로 게임 로직을 구현합니다. 시스템은 입력 컴포넌트 세트에서 작동하며 모든 연산을 수행할 수 있습니다. 시스템은 월드 인스턴스에서 구현되며 승인 정책을 준수합니다. 예를 들어, 어떤 월드에서는 누구나 새로운 시스템을 제출할 수 있는 반면, 다른 월드에서는 화이트리스트에 오른 당사자나 DAO의 승인이 필요할 수 있습니다.
우리가 구축하는 첫 번째 시스템은 플레이어가 게임에 참여할 수 있도록 합니다:
bolt system join-game로직을 ( program-ecs/systems/join-game.rs)를 다음 위치에 배치합니다:
#[system]pub mod join_game { pub fn  execute(ctx: Context<Components<, _args_p: Vec<u8<) - Result<Components {&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&! let idx = match players.player.iter_mut().position(|플레이어| player.is_none( )) { 일부(플레이어_인덱스) => 플레이어_인덱스, 플레이어.is_none( None => return Err(PlayersError::GameFull .into()), }; ctx.accounts.players. players[idx]= Some(*ctx.accounts.authority.key); Ok(ctx.accounts) 확인 nbsp; } #[system_input] pub struct Components { }  . pub players: Players, }}}
두 번째는 시스템은 게임의 핵심 로직을 구현합니다 :
1. 게임을 플레이할 시스템 생성 :
bolt system play2. 2. 구현 로직:
use bolt_lang::*;use grid::Grid;use players::Players;declare_id!(" DyUy1naq1kb3r7HYBrTf7YhnGMJ5k5NqS3Mhk65GfSih");#[system]pub mod play { pub fn execute(ctx: Context<Components , args: Args) - Result<Components {  . 그리드 = &mut ctx.accounts로 설정합니다. let players = &mut ctx.accounts.players; let players = &mut ctx. nbsp;authority = *ctx.accounts.authority.key; require!(players.players[0] == 일부(권한) || players.players[1] == 일부(권한), TicTacToeError::NotInGame); require!(grid.state == grid::GameState::Active, TicTacToeError::NotActive ); let player_idx : usize = if players.players[0]& nbsp;== 일부(권한) { 0 } else { 1 }; ;;;;;;;;;;;;;;;;;;;;;;; ; // 핵심 게임 로직 match args { tile @ Args {   nbsp; 행: 0. =2, 열: 0... =2, } => match grid.board[tile.row as usize][tile.column as usize] { as usize][tile.column as usize] { as usize Some(_) => return Err(TicTacToeError::TileAlreadySet.into()),  . 없음 =>{ 없음 ;;; 앤트맨 그리드 보드[tile.row as usize&][tile.column& as usize]= as usize][tile. Some(grid::Sign::from_usize(player_idx)); } }, },  . nbsp; => return Err(TicTacToeError::TileOutOfBounds .into()), } grid.is_first_player_. turn = !grid.is_first_player_turn; check_winner(grid, authority); check_winner(grid, authority); ! Ok(ctx.accounts) } #[system_input]& pub 구조 구성 요소 { pub 그리드: . 그리드, pub players: Players, } } } ... nbsp;#[인수] 구조체 Args { 행: u8,  column: u8, }}pub fn check_winner(grid: & mut Account<Grid>, player: Pubkey) { ...}} 자세한 내용은 전체 소스 코드를 참조하세요.
https://github.com/magicblock-labs/bolt-tic-tac-toe/blob/main/programs-ecs/systems/play/src/lib.rs<
보시다시피 구현은 매우 간단합니다. system_input
으로 표시된 구조는 execute
함수에서 액세스하고 사용할 수 있는 컴포넌트 입력 패키지를 정의합니다. arguments
라고 표시된 구조는 시스템이 입력으로 받을 수 있는 인수를 정의합니다.
프로그램 빌드 및 테스트
다음 명령을 사용하여 프로그램을 빌드합니다:
bolt build
< p style="text-align: left;">이 명령은 애플리케이션을 컴파일하고 클라이언트 측 통합을 위한 IDL 및 TypeScript 유형을 자동으로 생성합니다. 컴포넌트를 설정하고 시스템을 실행하는 과정은 다음 단계로 이루어집니다.
월드를 인스턴스화합니다.
매칭되는 엔티티를 생성합니다.
매칭되는 엔티티에 플레이어와 메시 컴포넌트를 붙입니다.
게임플레이를 용이하게 하는 시스템을 구현합니다.
Tic-Tac-Toe 게임용 타입스크립트 테스트는 여기에서 찾을 수 있나요?
React 클라이언트에 연결
타입의 동적 검색 및 생성, 그리고 Bolt TypeScript SDK에서 제공하는 유틸리티 기능 덕분에 React 클라이언트에 연결하는 것은 매우 쉽습니다.
종속성 추가하기:
yarn add -D @magicblock-labs/bolt-sdk
예를 들어, 시스템을 실행하려면:
// Components
const GRID_. COMPONENT = new PublicKey("rdiVoU6KomhXBDMLi6UXVHvmjEUtKqb5iDCWChxMzZ7");
const PLAYERS_COMPONENT = new PublicKey("5Xz6iiE2FZdpqrvCKbGqDajNYt1tP8cRGXrq3THSFo1q");
// 시스템
const JOIN_GAME = new PublicKey("2umhnxiCtmg5KTn4L9BLo24uLjb74gAh4tmpMLRKYndN");
const PLAY = new PublicKey("DyUy1naq1kb3r7HYBrTf7YhnGMJ5k5NqS3Mhk65GfSih");
const applySystem = await ApplySystem({
 . authority: publicKey,
system: JOIN_GAME,
ApplySystem = await ApplySystem({
) 엔티티,
구성요소: [PLAYERS_COMPONENT],
}).
const transaction = applySystem.transaction;
const signature = await submitTransaction(트랜잭션);
React로 만든 간단한 틱택토 UI는 여기에서 확인하세요.
. https://github.com/magicblock-labs/bolt-tic-tac-toe/tree/main/app/react-tic-tac-toe
중요하게 강조해야 할 부분은 < strong>구현 시스템과 인스턴스화된 컴포넌트에는 ID만 필요합니다. 이는 새로운 로직과 데이터 구조를 동적으로 생성하고 활용할 수 있어 모듈을 개발하고 게임의 동작을 변경할 수 있다는 것을 의미합니다.
결론
볼트 ECS를 사용한 간단한 틱택토 게임 구현을 통해 이를 React UI에 연결하는 방법을 보여드렸습니다. 는 프레임워크의 단순성과 유연성을 강조합니다. Solana를 추상화하고 인체인 로직을 재사용하는 것 외에도, 사용자 생성 로직과 모드를 도입할 때 BOLT가 가져올 가능성에 대해 기대가 큽니다. 다음 예시에서는 게임 개발자가 라이선스 없이 독립적으로 게임 로직을 확장하는 방법과 임시 롤업을 사용하여 짧은 지연 시간/높은 처리량의 트랜잭션을 구현하는 방법을 보여드리겠습니다.