Skip to content

Commit

Permalink
scene: avatar-swap (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
pravusjif authored Nov 29, 2022
1 parent 21cbc1c commit 01172be
Show file tree
Hide file tree
Showing 14 changed files with 280 additions and 0 deletions.
14 changes: 14 additions & 0 deletions avatar-swap/.dclignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.*
package.json
package-lock.json
yarn-lock.json
build.json
export
tsconfig.json
tslint.json
node_modules
*.ts
*.tsx
Dockerfile
dist
screenshots
6 changes: 6 additions & 0 deletions avatar-swap/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"extends": "@dcl/eslint-config/sdk",
"parserOptions": {
"project": ["tsconfig.json"]
}
}
7 changes: 7 additions & 0 deletions avatar-swap/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package-lock.json
node_modules
bin
*.swp
*.*~
export
.idea/
40 changes: 40 additions & 0 deletions avatar-swap/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Avatar Swap
A scene that uses `AvatarModifier` component to swap out the default avatar for another character model. This way the player's character style can match that of the enviroment's.

![](screenshots/avatar-swap.gif)

This scene shows:
- How to add a 3D model
- How to play animations from a 3D model
- How to hide an avatar using `AvatarModifier` component
- How to attach an entity to the Player
- How to get the Player's entity `Transform` and its position

## Instructions
Run over to the area covered in grass to automatically switch avatars. Use your mouse to look around and <kbd>W</kbd> <kbd>A</kbd> <kbd>S</kbd> <kbd>D</kbd> keys on your keyboard to move forward, left, backward and right respectively.

## Try it out

**Install the CLI**

Download and install the Decentraland CLI by running the following command inside this scene root directory:

```bash
npm install @dcl/sdk@next
```

**Previewing the scene**

Inside this scene root directory run:

```
dcl start
```

## Copyright info

This scene is protected with a standard Apache 2 licence. See the terms and conditions in the [LICENSE](/LICENSE) file.

## Acknowledgements

Model and animations from https://www.mixamo.com/
Binary file added avatar-swap/models/arissa.glb
Binary file not shown.
Binary file added avatar-swap/models/baseGrass.glb
Binary file not shown.
16 changes: 16 additions & 0 deletions avatar-swap/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "avatar-swap",
"version": "1.0.0",
"description": "Avatar Swap",
"scripts": {
"start": "dcl start",
"build": "build-ecs",
"watch": "build-ecs --watch",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix"
},
"devDependencies": {
"@dcl/eslint-config": "^1.0.1",
"@dcl/sdk": "next"
}
}
37 changes: 37 additions & 0 deletions avatar-swap/scene.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"ecs7": true,
"display": {
"title": "avatar-swap",
"favicon": "favicon_asset"
},
"contact": {
"name": "decentraland",
"email": ""
},
"owner": "",
"scene": {
"parcels": [
"23,23"
],
"base": "23,23"
},
"requiredPermissions": [],
"main": "bin/game.js",
"tags": [],
"spawnPoints": [
{
"name": "spawn1",
"default": true,
"position": {
"x": 0,
"y": 0,
"z": 0
},
"cameraTarget": {
"x": 8,
"y": 1,
"z": 8
}
}
]
}
Binary file added avatar-swap/screenshots/avatar-swap.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions avatar-swap/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export * from '@dcl/sdk'
import { engine, GltfContainer, Transform } from '@dcl/sdk/ecs'
import { Vector3 } from '@dcl/sdk/math'
import { attachEntityToPlayer } from "./modules/utils";
import { createArissaCharacter } from "./modules/arissa";
import { createAvatarSwappingArea, avatarSwappingSystem } from "./modules/avatarSwappingArea";

function setup() {
// Instantiate ground model
const groundEntity = engine.addEntity()
GltfContainer.create(groundEntity, {
src: "models/baseGrass.glb"
})

// Instantiate 'Arissa' character animated model
const arissaCharaEntity = createArissaCharacter()
attachEntityToPlayer(Transform.get(arissaCharaEntity).parent)

// Set avatar modifier area to swap player avatar
createAvatarSwappingArea(Vector3.create(8, 2, 10.5), Vector3.create(16, 4, 11), arissaCharaEntity)

// Register avatar swapping system
engine.addSystem(avatarSwappingSystem)
}

setup()


38 changes: 38 additions & 0 deletions avatar-swap/src/modules/arissa.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {
engine,
Entity,
GltfContainer,
Transform,
Animator
} from '@dcl/sdk/ecs'
import { Vector3 } from "@dcl/sdk/math";

export function createArissaCharacter() : Entity {
const parentEntity = engine.addEntity()
const entity = engine.addEntity()

GltfContainer.create(entity, {
src: "models/arissa.glb"
})
Transform.create(entity, {
position: Vector3.create(0, 1.75, 0),
scale: Vector3.create(0, 0, 0),
parent: parentEntity
})
Animator.create(entity, {
states: [
{
name: "Running",
clip: "Running",
loop: true
},
{
name: "Idle",
clip: "Idle",
loop: true
}
]
})

return entity
}
76 changes: 76 additions & 0 deletions avatar-swap/src/modules/avatarSwappingArea.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import {
engine,
Entity,
Transform,
Animator,
AvatarModifierArea,
AvatarModifierType
} from '@dcl/sdk/ecs'
import { Vector3 } from '@dcl/sdk/math'

let areaCenter: Vector3
let areaSize: Vector3
let areaMinPosition: Vector3
let areaMaxPosition: Vector3

function setupAreaData(center: Vector3, size: Vector3) {
areaCenter = center
areaSize = size

const halfSize = Vector3.scale(size, 0.5)
areaMinPosition = Vector3.create(
areaCenter.x - halfSize.x,
areaCenter.y - halfSize.y,
areaCenter.z - halfSize.z
)
areaMaxPosition = Vector3.create(
areaCenter.x + halfSize.x,
areaCenter.y + halfSize.y,
areaCenter.z + halfSize.z
)
}

function isPositionInsideArea(targetPosition: Vector3): boolean {
return targetPosition.x > areaMinPosition.x
&& targetPosition.y > areaMinPosition.y
&& targetPosition.z > areaMinPosition.z
&& targetPosition.x < areaMaxPosition.x
&& targetPosition.y < areaMaxPosition.y
&& targetPosition.z < areaMaxPosition.z
}

let otherAvatarEntity: Entity
export function createAvatarSwappingArea(center: Vector3, size: Vector3, avatarEntity: Entity) {
setupAreaData(center, size)
otherAvatarEntity = avatarEntity
const avatarHiderAreaEntity = engine.addEntity()
AvatarModifierArea.create(avatarHiderAreaEntity, {
area: areaSize,
modifiers: [AvatarModifierType.AMT_HIDE_AVATARS],
excludeIds: []
})
Transform.create(avatarHiderAreaEntity, {
position: areaCenter
})
}

let lastPlayerPos: Vector3 | undefined = undefined
export function avatarSwappingSystem (dt: number) {
if (!Transform.has(engine.PlayerEntity)) return

const playerPos = Transform.get(engine.PlayerEntity).position
const moved = playerPos != lastPlayerPos

Animator.getClip(otherAvatarEntity, "Idle").playing = !moved
Animator.getClip(otherAvatarEntity, "Running").playing = moved

if (!moved) return

const playerIsInsideHidingArea = isPositionInsideArea(playerPos)
const otherAvatarTransform = Transform.getMutable(otherAvatarEntity)
otherAvatarTransform.scale.x = playerIsInsideHidingArea ? 1.1 : 0
otherAvatarTransform.scale.y = playerIsInsideHidingArea ? 1.1 : 0
otherAvatarTransform.scale.z = playerIsInsideHidingArea ? 1.1 : 0

lastPlayerPos = playerPos
}
13 changes: 13 additions & 0 deletions avatar-swap/src/modules/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { AvatarAnchorPointType, AvatarAttach, Entity } from "@dcl/sdk/ecs";
import { getUserData } from "~system/UserIdentity"

export async function attachEntityToPlayer (entity: Entity){
let userData = await getUserData({})
if(!userData.data) return
console.log(`userId: ${userData.data.userId}`)

AvatarAttach.create(entity, {
anchorPointId: AvatarAnchorPointType.AAPT_POSITION,
avatarId: userData.data.userId
})
}
5 changes: 5 additions & 0 deletions avatar-swap/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"compilerOptions": {},
"include": ["src/**/*.ts", "@dcl/ecs"],
"extends": "@dcl/sdk/types/tsconfig.ecs7.strict.json"
}

0 comments on commit 01172be

Please sign in to comment.