# 04-bookshelf
Start with 04-bookshelf-playground
Resources:
# Spinning an Object
Inside of room4.ts
start by adding in the Movable Entities for the Scene:
const bookshelf = new MovableEntity(
new GLTFShape("models/room4/Puzzle04_LibraryDoor.glb"),
new Transform({
position: new Vector3(20.6557, 5.4996, 15.041)
}),
new AudioClip("sounds/move_object1.mp3"),
new Vector3(1.5, 0, 0)
);
const movableBook = new MovableEntity(
new GLTFShape("models/room4/Puzzle04_Book2.glb"),
new Transform({
position: new Vector3(20.41, 6.4118, 10.4922)
}),
new AudioClip("sounds/move_object1.mp3"),
new Vector3(0, 0, -0.2)
);
movableBook.addComponent(
new OnClick((): void => {
movableBook.getComponent(utils.ToggleComponent).toggle();
})
);
const wineGlass = new MovableEntity(
new GLTFShape("models/room4/Puzzle04_WGlass.glb"),
new Transform({
position: new Vector3(25.7505, 6.95786, 10.5917)
}),
new AudioClip("sounds/move_object2.mp3"),
new Vector3(0.2, 0, 0)
);
wineGlass.addComponent(
new OnClick((): void => {
wineGlass.getComponent(utils.ToggleComponent).toggle();
})
);
Create a copy of movableEntity.ts
and call it rotatableEntity.ts
and adjust the code to instead rotate the object:
import utils from "../../node_modules/decentraland-ecs-utils/index";
export class RotatableEntity extends Entity {
constructor(
model: GLTFShape,
transform: TranformConstructorArgs,
audio: AudioClip,
rotation: Quaternion
) {
super();
engine.addEntity(this);
this.addComponent(model);
this.addComponent(new Transform(transform));
this.addComponent(new AudioSource(audio));
// Save the positions to move between
const startRot = transform.rotation;
const endRot = rotation;
// Add a Toggle component which defaults to Off
this.addComponent(
new utils.ToggleComponent(utils.ToggleState.Off, (value): void => {
if (value == utils.ToggleState.On) {
// Rotate to the endRot when toggled on
this.addComponentOrReplace(
new utils.RotateTransformComponent(
this.getComponent(Transform).rotation,
endRot,
0.5
)
);
} else {
// Rotate to the startRot when toggled on
this.addComponentOrReplace(
new utils.RotateTransformComponent(
this.getComponent(Transform).rotation,
startRot,
0.5
)
);
}
// Play the sound effect
this.getComponent(AudioSource).playOnce();
})
);
}
}
Now go back to room4.ts
and add in additional objects:
const telescope = new RotatableEntity(
new GLTFShape("models/room4/Puzzle04_Telescope.glb"),
new Transform({
position: new Vector3(22.6554, 7.02615, 10.6208)
}),
new AudioClip("sounds/move_object1.mp3"),
Quaternion.Euler(0, 127, 0)
);
telescope.addComponent(
new OnClick((): void => {
telescope.getComponent(utils.ToggleComponent).toggle();
})
);
const globe = new RotatableEntity(
new GLTFShape("models/room4/Puzzle04_Globe.glb"),
new Transform({
position: new Vector3(21.2191, 7.11234, 10.6817),
rotation: Quaternion.Euler(0.146, 34.9, -33.8)
}),
new AudioClip("sounds/move_object1.mp3"),
Quaternion.Euler(174, -26.43, -149.37)
);
globe.addComponent(
new OnClick((): void => {
globe.getComponent(utils.ToggleComponent).toggle();
})
);
const rotatableBook = new RotatableEntity(
new GLTFShape("models/room4/Puzzle04_Book1.glb"),
new Transform({
position: new Vector3(15.8321, 7.83095, 14.1252)
}),
new AudioClip("sounds/move_object1.mp3"),
Quaternion.Euler(0, 0, -25)
);
rotatableBook.addComponent(
new OnClick((): void => {
rotatableBook.getComponent(utils.ToggleComponent).toggle();
})
);
Now add a rotatableEntity that will open the bookshelf:
const candleHolder = new RotatableEntity(
new GLTFShape("models/room4/Puzzle04_CandleHolder.glb"),
new Transform({
position: new Vector3(17.5056, 7.61611, 15.3835)
}),
new AudioClip("sounds/move_object2.mp3"),
Quaternion.Euler(0, 0, 30)
);
candleHolder.addComponent(
new OnClick((): void => {
candleHolder.getComponent(utils.ToggleComponent).toggle();
bookshelf.getComponent(utils.ToggleComponent).toggle();
})
);
Go into movableEntity.ts
and add an additional argument to adjust the speed of the move animation and give it a default value:
constructor(
model: GLTFShape,
transform: TranformConstructorArgs,
sound: AudioClip,
deltaPosition: Vector3,
moveTime = 0.5
)
...
this.addComponent(
new utils.ToggleComponent(utils.ToggleState.Off, (value): void => {
if (value == utils.ToggleState.On) {
this.addComponentOrReplace(
new utils.MoveTransformComponent(
this.getComponent(Transform).position,
endPos,
moveTime
)
);
...
Finally update the bookshelf in room4.ts
to move slower
const bookshelf = new MovableEntity(
new GLTFShape("models/room4/Puzzle04_LibraryDoor.glb"),
new Transform({
position: new Vector3(20.6557, 5.4996, 15.041)
}),
new AudioClip("sounds/move_object1.mp3"),
new Vector3(1.5, 0, 0),
// Set a longer move time for the bookshelf
3
);
# Refactor
Inside the src
folder create a new file called resources.ts
and add all the audio clips and models as a default export:
export default {
sounds: {
button: new AudioClip("sounds/button.mp3"),
doorSqueak: new AudioClip("sounds/door_squeak.mp3"),
moveObject1: new AudioClip("sounds/move_object1.mp3"),
moveObject2: new AudioClip("sounds/move_object2.mp3"),
whip: new AudioClip("sounds/room3/whip.mp3")
},
models: {
book1: new GLTFShape("models/room4/Puzzle04_Book1.glb"),
book2: new GLTFShape("models/room4/Puzzle04_Book2.glb"),
candleHolder: new GLTFShape("models/room4/Puzzle04_CandleHolder.glb"),
door1: new GLTFShape("models/room1/Puzzle01_Door.glb"),
door2: new GLTFShape("models/room2/Puzzle02_Door.glb"),
door3: new GLTFShape("models/room3/Puzzle03_Door.glb"),
door4: new GLTFShape("models/room4/Puzzle04_LibraryDoor.glb"),
glass: new GLTFShape("models/room4/Puzzle04_WGlass.glb"),
globe: new GLTFShape("models/room4/Puzzle04_Globe.glb"),
plant1: new GLTFShape("models/room3/Puzzle03_Plant1.glb"),
plant2: new GLTFShape("models/room3/Puzzle03_Plant2.glb"),
plant3: new GLTFShape("models/room3/Puzzle03_Plant3.glb"),
plant4: new GLTFShape("models/room3/Puzzle03_Plant4.glb"),
roundButton: new GLTFShape("models/generic/Round_Button.glb"),
scene: new GLTFShape("models/scene.glb"),
squareButton: new GLTFShape("models/room2/Square_Button.glb"),
telescope: new GLTFShape("models/room4/Puzzle04_Telescope.glb")
}
};
Now inside of room4.ts
import the resources file and change the models and audio to use the ones located in said resources:
import resources from "../resources";
export function CreateRoom4(): void {
const bookshelf = new MovableEntity(
resources.models.door4,
new Transform({
position: new Vector3(20.6557, 5.4996, 15.041)
}),
resources.sounds.moveObject1,
new Vector3(1.5, 0, 0),
3
);
const movableBook = new MovableEntity(
resources.models.book2,
new Transform({
position: new Vector3(20.41, 6.4118, 10.4922)
}),
resources.sounds.moveObject1,
new Vector3(0, 0, -0.2)
);
movableBook.addComponent(
new OnClick((): void => {
movableBook.getComponent(utils.ToggleComponent).toggle();
})
);
...