From dd9834a7792626ab1d02b270b779d0bfbc490546 Mon Sep 17 00:00:00 2001 From: Gon Pombo Date: Wed, 21 Aug 2024 16:50:50 -0300 Subject: [PATCH] update readme (#25) --- README.md | 196 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 149 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index d295dc3..f9305db 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,64 @@ -# SDK Utils Player Library +# SDK Mini Games Library -This library provides utilities for managing player queues and active players in a scene. -## Exported Functions +## [Step 1: Install & Init Library](https://github.com/decentraland/sdk-mini-games/pull/19/files) -### initLibrary(_engine: IEngine, syncEntity: typeof syncEntity, playersApi: typeof players)` +#### Install @dcl-sdk/mini-games Library in your scene +```ts +// Run the following command in the scene terminal +npm install @dcl-sdk/mini-games@next +``` +#### Copy all the assets needed for the UI, Scoreboard and other models inside your scene. +```ts +// Run the following command in the scene terminal +node ./node_modules/@dcl-sdk/mini-games/scripts/postinstall.js +// This will create the `mini-games-assets` folder inside your scene with all the models that the library uses. +``` -Initializes the library with the necessary dependencies. Returns listeners that can be overridden with callbacks. +### Import Mini Games library in your scene +```ts +// game.ts file +import { initLibrary } from '@dcl-sdk/mini-games/src' +import { syncEntity } from '@dcl/sdk/network' +import players from '@dcl/sdk/players' -### setNextPlayer() +// make sure to put this line outside the main function. +initLibrary(engine, syncEntity, players, { + environment: 'dev', + gameId: 'game-id-here' +}) + +function main() { + // code scene here +} +``` -Sets the next player in the queue as active and removes the current active player. +## [Step 2: Players queue](https://github.com/decentraland/sdk-mini-games/pull/20/files) -### addPlayer() +The library provides all the logic behind to handle the multiplayers queue. + +### Queue Players Functions +```ts +import { queue } from '@dcl-sdk/mini-games/src' +``` + +#### queue.addPlayer(): void Adds the current player to the queue if they're not already in it. -### isActive(): boolean +#### queue.setNextPlayer(): void +Removes current player from the queue (if its the active one), and set the next player in the queue as active. +#### queue.isActive(): boolean Checks if the current user is the active player. -### getQueue() +#### queue.getQueue(): Player[] +Returns an array of players in the queue, sorted by the ime they join the queue. -Returns an array of players in the queue, sorted by join time. +### Listener for active player updates +#### listeners.onActivePlayerChange -## Exported Types - -### PlayerType +### Player Type ```typescript type PlayerType = { @@ -36,48 +68,118 @@ type PlayerType = { active: boolean; } ``` +## [Step 3: Scene Rotation + Game Area Checker + Timeout](https://github.com/decentraland/sdk-mini-games/pull/21/files) + +### Scene Rotation +Set the orientation of the scene. You can set any number but ideally you want to set 0, 90, 180 or 270. +This would add a RootEntity and then you can parent all the entities to this root entity so they all point to the same orientation. + + +### Game Area Check +You can define your play game area. So if the active player decides to leave the area, it switches automatically to the next player. +Also if a player finds a way to enter the game area and is not the active player, it will be kicked out. + +### Timeout check +Set a max amout of time that a player can play the game without being kicked. +If the player is alone in the game, it will continue playing till a new user arrives. + + +This can be done by passing extra params to the initLibrary +```ts +import { initLibrary, sceneParentEntity } from '@dcl-sdk/mini-games/src' +const _1_SEC = 1000 +const _1_MIN = _1_SEC * 60 + +miniGames.initLibrary(engine as any, syncEntity, playersApi, { + gameId: "4ee1d308-5e1e-4b2b-9e91-9091878a7e3d", + environment: "dev", + // time in ms + gameTimeoutMs: _1_MIN, + // game area rectangle + gameArea: { + // top left point + topLeft: Vector3.create(5.15, 0, 2.23), + // bottom right point + bottomRight: Vector3.create(13.77, 0, 13.77), + // point outside the game area to exit players + exitSpawnPoint: Vector3.create(0,0,7) + } +}) +function main() { + const gameArea = engine.addEntity() + Transform.create(gameArea, { parent: sceneParentEntity, position, ...etc }) +} +``` -## Exported Listeners -### onActivePlayerChange: (player: PlayerType) => void +## [Step 4: UI](https://github.com/decentraland/sdk-mini-games/pull/22/files) -You can override this listener to perform custom actions when the active player changes. +We already implement the generic UI to use inside the mini-games. Like the Play Game sign, Music On/Off, Levels, etc. -## Example -```typescript -import { engine } from '@dcl/sdk/ecs' -import { syncEntity } from '@dcl/sdk/network' -import playersApi from '@dcl/sdk/players' -import { initPlayersQueue, listeners, addPlayer, isActive, getQueue, setNextPlayer } from './sdk-utils-player' +#### Menu Button UI -// Initialize the library -initPlayersQueue(engine, syncEntity, playersApi) +```ts +// MenuButton(position: TransformType, assetShape, assetIcon, hoverText, callback) +import { ui } from '@dcl-sdk/mini-games/src' -// Override the onActivePlayerChange listener -listeners.onActivePlayerChange = (player) => { - console.log(`New active player: ${player.address}`) -} -const startCube = createCube(2, 1, 2) -const finishCube = createCube(2, 4, 2) +// All the available icons +const icons = ui.uiAssets.icons +// All the available Shapes & Colors +const shapes = ui.uiAssets.shapes -// Listen to changes on the queue -listeners.onActivePlayerChange = (player) => { - console.log('active player changed', player) -} -// Add player to the queue -pointerEventsSystem.onPointerDown({ entity: startCube, opts: { hoverText: 'Add player to queue' } }, () => { - addPlayer() -}) +new ui.MenuButton( + { + parent: sceneParentEntity, + position: Vector3.create(-3.74, 1.03, 0), + rotation: Quaternion.fromEulerDegrees(-45, 90, 0), + scale: Vector3.create(1.2, 1.2, 1.2) + }, + ui.uiAssets.shapes.RECT_GREEN, + ui.uiAssets.icons.playText, + "PLAY GAME", + () => { + queue.addPlayer() + } +) +``` + +## [Step 5: Progress API](https://github.com/decentraland/sdk-mini-games/pull/23/files) +We manage all the Progress API for you. We use the gameId set on the initLibrary, so be sure to update this value ! + +### Get last user progress of the game +```ts +type ProgressKey = 'level' | 'score' | 'moves' | 'time' +const userProgress = await progress.getProgress('level', progress.SortDirection.DESC, 1) +``` + +### Upsert the user progress based on the game. +```ts +import { progress } from '@dcl-sdk/mini-games/src' -// Finish game and set the next player -pointerEventsSystem.onPointerDown({ entity: finishCube, opts: { hoverText: 'Finish game'} }, () => { - setNextPlayer() +await progress.upsertProgress({ + level: gameData.currentLevel, + time: gameData.levelFinishedAt - gameData.levelStartedAt, + moves: gameData.moves }) +``` -// Check if current player is active -console.log(`Is current player active? ${isActive()}`); +## [Step 6: ScoreBoard](https://github.com/decentraland/sdk-mini-games/pull/24/files) +Initialize the scoreboard and that's it ! +```ts +// Add scoreboard + const width = 2.5 + const height = 2.8 + const scale = 1.2 + new ui.ScoreBoard( + { + // parent: sideSignB, + position: Vector3.create(1.3, 4, 0.15), + rotation: Quaternion.fromEulerDegrees(0, 180, 0) + }, + width, + height, + scale, + ui.TIME_LEVEL + ) -// Get the current Queue -const queue = getQueue(); -console.log('Current queue:', queue); ``` \ No newline at end of file