Jmx0OyFET0NUWVBFIGh0bWwmZ3Q7CiZsdDtodG1sIGxhbmc9JnF1b3Q7ZW4mcXVvdDsmZ3Q7CiZsdDtoZWFkJmd0OwogICAgJmx0O21ldGEgY2hhcnNldD0mcXVvdDtVVEYtOCZxdW90OyZndDsKICAgICZsdDttZXRhIG5hbWU9JnF1b3Q7dmlld3BvcnQmcXVvdDsgY29udGVudD0mcXVvdDt3aWR0aD1kZXZpY2Utd2lkdGgsIGluaXRpYWwtc2NhbGU9MS4wJnF1b3Q7Jmd0OwogICAgJmx0O3RpdGxlJmd0O1RocmVlLmpzIGFuZCBDYW5ub24uanMgR2FtZSZsdDsvdGl0bGUmZ3Q7CiAgICAmbHQ7c2NyaXB0IHNyYz0mcXVvdDtodHRwczovL2MuLi5jb250ZW50LWF2YWlsYWJsZS10by1hdXRob3Itb25seS4uLmUuY29tL2FqYXgvbGlicy90aHJlZS5qcy9yMTI4L3RocmVlLm1pbi5qcyZxdW90OyZndDsmbHQ7L3NjcmlwdCZndDsKICAgICZsdDtzY3JpcHQgc3JjPSZxdW90O2h0dHBzOi8vYy4uLmNvbnRlbnQtYXZhaWxhYmxlLXRvLWF1dGhvci1vbmx5Li4uZS5jb20vYWpheC9saWJzL2Nhbm5vbi5qcy8wLjYuMi9jYW5ub24ubWluLmpzJnF1b3Q7Jmd0OyZsdDsvc2NyaXB0Jmd0OwogICAgJmx0O3NjcmlwdCBzcmM9JnF1b3Q7aHR0cHM6Ly9jLi4uY29udGVudC1hdmFpbGFibGUtdG8tYXV0aG9yLW9ubHkuLi5lLmNvbS9hamF4L2xpYnMvcDUuanMvMS40LjAvcDUubWluLmpzJnF1b3Q7Jmd0OyZsdDsvc2NyaXB0Jmd0OwogICAgJmx0O3N0eWxlJmd0OwogICAgICAgIGJvZHkgewogICAgICAgICAgICBtYXJnaW46IDA7CiAgICAgICAgICAgIG92ZXJmbG93OiBoaWRkZW47CiAgICAgICAgfQogICAgICAgIGNhbnZhcyB7CiAgICAgICAgICAgIGRpc3BsYXk6IGJsb2NrOwogICAgICAgIH0KICAgICZsdDsvc3R5bGUmZ3Q7CiZsdDsvaGVhZCZndDsKJmx0O2JvZHkmZ3Q7CiAgICAmbHQ7c2NyaXB0Jmd0OwogICAgICAgIGxldCBza2V0Y2ggPSBmdW5jdGlvbihwKSB7CiAgICAgICAgICAgIGxldCBzY2VuZSwgY2FtZXJhLCByZW5kZXJlciwgd29ybGQsIGdyb3VuZEJvZHksIGdyb3VuZE1lc2gsIGJveEJvZHksIGJveE1lc2gsIGNvbnRyb2xzLCB0ZXh0dXJlTG9hZGVyLCBzdG9yeVRleHQsIHRleHRNZXNoOwoKICAgICAgICAgICAgcC5zZXR1cCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgICAgcC5jcmVhdGVDYW52YXMocC53aW5kb3dXaWR0aCwgcC53aW5kb3dIZWlnaHQsIHAuV0VCR0wpOwogICAgICAgICAgICAgICAgc2NlbmUgPSBuZXcgVEhSRUUuU2NlbmUoKTsKICAgICAgICAgICAgICAgIGNhbWVyYSA9IG5ldyBUSFJFRS5QZXJzcGVjdGl2ZUNhbWVyYSg3NSwgcC53aW5kb3dXaWR0aCAvIHAud2luZG93SGVpZ2h0LCAwLjEsIDEwMDApOwogICAgICAgICAgICAgICAgcmVuZGVyZXIgPSBuZXcgVEhSRUUuV2ViR0xSZW5kZXJlcih7IGNhbnZhczogcC5jYW52YXMgfSk7CiAgICAgICAgICAgICAgICByZW5kZXJlci5zZXRTaXplKHAud2luZG93V2lkdGgsIHAud2luZG93SGVpZ2h0KTsKICAgICAgICAgICAgICAgIHJlbmRlcmVyLnNoYWRvd01hcC5lbmFibGVkID0gdHJ1ZTsKICAgICAgICAgICAgICAgIHJlbmRlcmVyLnNoYWRvd01hcC50eXBlID0gVEhSRUUuUENGU29mdFNoYWRvd01hcDsKICAgICAgICAgICAgICAgIHdvcmxkID0gbmV3IENBTk5PTi5Xb3JsZCgpOwogICAgICAgICAgICAgICAgd29ybGQuZ3Jhdml0eS5zZXQoMCwgLTkuODIsIDApOwogICAgICAgICAgICAgICAgd29ybGQuYnJvYWRwaGFzZSA9IG5ldyBDQU5OT04uTmFpdmVCcm9hZHBoYXNlKCk7CiAgICAgICAgICAgICAgICB3b3JsZC5zb2x2ZXIuaXRlcmF0aW9ucyA9IDEwOwogICAgICAgICAgICAgICAgbGV0IGdyb3VuZFNoYXBlID0gbmV3IENBTk5PTi5Cb3gobmV3IENBTk5PTi5WZWMzKDEwLCAxLCAxMCkpOwogICAgICAgICAgICAgICAgZ3JvdW5kQm9keSA9IG5ldyBDQU5OT04uQm9keSh7IG1hc3M6IDAgfSk7CiAgICAgICAgICAgICAgICBncm91bmRCb2R5LmFkZFNoYXBlKGdyb3VuZFNoYXBlKTsKICAgICAgICAgICAgICAgIGdyb3VuZEJvZHkucG9zaXRpb24uc2V0KDAsIC0xLCAwKTsKICAgICAgICAgICAgICAgIHdvcmxkLmFkZEJvZHkoZ3JvdW5kQm9keSk7CiAgICAgICAgICAgICAgICBsZXQgZ3JvdW5kR2VvbWV0cnkgPSBuZXcgVEhSRUUuQm94R2VvbWV0cnkoMjAsIDIsIDIwKTsKICAgICAgICAgICAgICAgIGxldCBncm91bmRNYXRlcmlhbCA9IG5ldyBUSFJFRS5NZXNoTGFtYmVydE1hdGVyaWFsKHsgY29sb3I6IDB4MDBmZjAwIH0pOwogICAgICAgICAgICAgICAgZ3JvdW5kTWVzaCA9IG5ldyBUSFJFRS5NZXNoKGdyb3VuZEdlb21ldHJ5LCBncm91bmRNYXRlcmlhbCk7CiAgICAgICAgICAgICAgICBncm91bmRNZXNoLnJlY2VpdmVTaGFkb3cgPSB0cnVlOwogICAgICAgICAgICAgICAgc2NlbmUuYWRkKGdyb3VuZE1lc2gpOwogICAgICAgICAgICAgICAgbGV0IGJveFNoYXBlID0gbmV3IENBTk5PTi5Cb3gobmV3IENBTk5PTi5WZWMzKDEsIDEsIDEpKTsKICAgICAgICAgICAgICAgIGJveEJvZHkgPSBuZXcgQ0FOTk9OLkJvZHkoeyBtYXNzOiAxIH0pOwogICAgICAgICAgICAgICAgYm94Qm9keS5hZGRTaGFwZShib3hTaGFwZSk7CiAgICAgICAgICAgICAgICBib3hCb2R5LnBvc2l0aW9uLnNldCgwLCAxMCwgMCk7CiAgICAgICAgICAgICAgICB3b3JsZC5hZGRCb2R5KGJveEJvZHkpOwogICAgICAgICAgICAgICAgbGV0IGJveEdlb21ldHJ5ID0gbmV3IFRIUkVFLkJveEdlb21ldHJ5KDIsIDIsIDIpOwogICAgICAgICAgICAgICAgdGV4dHVyZUxvYWRlciA9IG5ldyBUSFJFRS5UZXh0dXJlTG9hZGVyKCk7CiAgICAgICAgICAgICAgICBsZXQgYm94VGV4dHVyZSA9IHRleHR1cmVMb2FkZXIubG9hZCgnLi90ZXh0dXJlLmpwZycpOwogICAgICAgICAgICAgICAgbGV0IGJveE1hdGVyaWFsID0gbmV3IFRIUkVFLk1lc2hMYW1iZXJ0TWF0ZXJpYWwoeyBtYXA6IGJveFRleHR1cmUgfSk7CiAgICAgICAgICAgICAgICBib3hNZXNoID0gbmV3IFRIUkVFLk1lc2goYm94R2VvbWV0cnksIGJveE1hdGVyaWFsKTsKICAgICAgICAgICAgICAgIGJveE1lc2guY2FzdFNoYWRvdyA9IHRydWU7CiAgICAgICAgICAgICAgICBzY2VuZS5hZGQoYm94TWVzaCk7CiAgICAgICAgICAgICAgICBsZXQgYW1iaWVudExpZ2h0ID0gbmV3IFRIUkVFLkFtYmllbnRMaWdodCgweDQwNDA0MCwgMC40KTsKICAgICAgICAgICAgICAgIHNjZW5lLmFkZChhbWJpZW50TGlnaHQpOwogICAgICAgICAgICAgICAgbGV0IGRpcmVjdGlvbmFsTGlnaHQgPSBuZXcgVEhSRUUuRGlyZWN0aW9uYWxMaWdodCgweGZmZmZmZiwgMC42KTsKICAgICAgICAgICAgICAgIGRpcmVjdGlvbmFsTGlnaHQucG9zaXRpb24uc2V0KDEwLCAxMCwgNSk7CiAgICAgICAgICAgICAgICBkaXJlY3Rpb25hbExpZ2h0LmNhc3RTaGFkb3cgPSB0cnVlOwogICAgICAgICAgICAgICAgZGlyZWN0aW9uYWxMaWdodC5zaGFkb3cubWFwU2l6ZS53aWR0aCA9IDEwMjQ7CiAgICAgICAgICAgICAgICBkaXJlY3Rpb25hbExpZ2h0LnNoYWRvdy5tYXBTaXplLmhlaWdodCA9IDEwMjQ7CiAgICAgICAgICAgICAgICBzY2VuZS5hZGQoZGlyZWN0aW9uYWxMaWdodCk7CiAgICAgICAgICAgICAgICBjYW1lcmEucG9zaXRpb24uc2V0KDAsIDUsIDEwKTsKICAgICAgICAgICAgICAgIGNhbWVyYS5sb29rQXQoMCwgMCwgMCk7CiAgICAgICAgICAgICAgICBjb250cm9scyA9IHsKICAgICAgICAgICAgICAgICAgICBwaXRjaDogMCwKICAgICAgICAgICAgICAgICAgICB5YXc6IDAsCiAgICAgICAgICAgICAgICAgICAgc2Vuc2l0aXZpdHk6IDAuMDAyCiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgcC5jYW52YXMuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgKGV2ZW50KSA9Jmd0OyB7CiAgICAgICAgICAgICAgICAgICAgY29udHJvbHMueWF3IC09IGV2ZW50Lm1vdmVtZW50WCAqIGNvbnRyb2xzLnNlbnNpdGl2aXR5OwogICAgICAgICAgICAgICAgICAgIGNvbnRyb2xzLnBpdGNoIC09IGV2ZW50Lm1vdmVtZW50WSAqIGNvbnRyb2xzLnNlbnNpdGl2aXR5OwogICAgICAgICAgICAgICAgICAgIGNvbnRyb2xzLnBpdGNoID0gTWF0aC5tYXgoLU1hdGguUEkgLyAyLCBNYXRoLm1pbihNYXRoLlBJIC8gMiwgY29udHJvbHMucGl0Y2gpKTsKICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgcC5jYW52YXMucmVxdWVzdFBvaW50ZXJMb2NrID0gcC5jYW52YXMucmVxdWVzdFBvaW50ZXJMb2NrIHx8IHAuY2FudmFzLm1velJlcXVlc3RQb2ludGVyTG9jazsKICAgICAgICAgICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKCkgPSZndDsgewogICAgICAgICAgICAgICAgICAgIHAuY2FudmFzLnJlcXVlc3RQb2ludGVyTG9jaygpOwogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICBsZXQgZm9udExvYWRlciA9IG5ldyBUSFJFRS5Gb250TG9hZGVyKCk7CiAgICAgICAgICAgICAgICBmb250TG9hZGVyLmxvYWQoJ2h0dHBzOi8vdC4uLmNvbnRlbnQtYXZhaWxhYmxlLXRvLWF1dGhvci1vbmx5Li4ucy5vcmcvZXhhbXBsZXMvZm9udHMvaGVsdmV0aWtlcl9yZWd1bGFyLnR5cGVmYWNlLmpzb24nLCBmdW5jdGlvbihmb250KSB7CiAgICAgICAgICAgICAgICAgICAgbGV0IHRleHRHZW9tZXRyeSA9IG5ldyBUSFJFRS5UZXh0R2VvbWV0cnkoJ0Vyb3RpYyBBZHZlbnR1cmU6IEV4cGxvcmUgdGhlIEZvcmJpZGRlbiBCb3gnLCB7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvbnQ6IGZvbnQsCiAgICAgICAgICAgICAgICAgICAgICAgIHNpemU6IDAuNSwKICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiAwLjEsCiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnZlU2VnbWVudHM6IDEyLAogICAgICAgICAgICAgICAgICAgICAgICBiZXZlbEVuYWJsZWQ6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgIGJldmVsVGhpY2tuZXNzOiAwLjAxLAogICAgICAgICAgICAgICAgICAgICAgICBiZXZlbFNpemU6IDAuMDEsCiAgICAgICAgICAgICAgICAgICAgICAgIGJldmVsT2Zmc2V0OiAwLAogICAgICAgICAgICAgICAgICAgICAgICBiZXZlbFNlZ21lbnRzOiA1CiAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgbGV0IHRleHRNYXRlcmlhbCA9IG5ldyBUSFJFRS5NZXNoTGFtYmVydE1hdGVyaWFsKHsgY29sb3I6IDB4ZmY2OWI0IH0pOwogICAgICAgICAgICAgICAgICAgIHRleHRNZXNoID0gbmV3IFRIUkVFLk1lc2godGV4dEdlb21ldHJ5LCB0ZXh0TWF0ZXJpYWwpOwogICAgICAgICAgICAgICAgICAgIHRleHRNZXNoLnBvc2l0aW9uLnNldCgtNSwgMiwgMCk7CiAgICAgICAgICAgICAgICAgICAgc2NlbmUuYWRkKHRleHRNZXNoKTsKICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICB9OwogICAgICAgICAgICBwLmRyYXcgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICAgIHAuYmFja2dyb3VuZCgwKTsKICAgICAgICAgICAgICAgIHdvcmxkLnN0ZXAoMSAvIDYwKTsKICAgICAgICAgICAgICAgIGdyb3VuZE1lc2gucG9zaXRpb24uY29weShncm91bmRCb2R5LnBvc2l0aW9uKTsKICAgICAgICAgICAgICAgIGdyb3VuZE1lc2gucXVhdGVybmlvbi5jb3B5KGdyb3VuZEJvZHkucXVhdGVybmlvbik7CiAgICAgICAgICAgICAgICBib3hNZXNoLnBvc2l0aW9uLmNvcHkoYm94Qm9keS5wb3NpdGlvbik7CiAgICAgICAgICAgICAgICBib3hNZXNoLnF1YXRlcm5pb24uY29weShib3hCb2R5LnF1YXRlcm5pb24pOwogICAgICAgICAgICAgICAgY2FtZXJhLnBvc2l0aW9uLnggPSBNYXRoLnNpbihjb250cm9scy55YXcpICogMTA7CiAgICAgICAgICAgICAgICBjYW1lcmEucG9zaXRpb24ueiA9IE1hdGguY29zKGNvbnRyb2xzLnlhdykgKiAxMDsKICAgICAgICAgICAgICAgIGNhbWVyYS5wb3NpdGlvbi55ID0gTWF0aC5zaW4oY29udHJvbHMucGl0Y2gpICogMTAgKyA1OwogICAgICAgICAgICAgICAgY2FtZXJhLmxvb2tBdCgwLCAwLCAwKTsKICAgICAgICAgICAgICAgIHJlbmRlcmVyLnJlbmRlcihzY2VuZSwgY2FtZXJhKTsKICAgICAgICAgICAgfTsKICAgICAgICAgICAgcC53aW5kb3dSZXNpemVkID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgICBwLnJlc2l6ZUNhbnZhcyhwLndpbmRvd1dpZHRoLCBwLndpbmRvd0hlaWdodCk7CiAgICAgICAgICAgICAgICBjYW1lcmEuYXNwZWN0ID0gcC53aW5kb3dXaWR0aCAvIHAud2luZG93SGVpZ2h0OwogICAgICAgICAgICAgICAgY2FtZXJhLnVwZGF0ZVByb2plY3Rpb25NYXRyaXgoKTsKICAgICAgICAgICAgICAgIHJlbmRlcmVyLnNldFNpemUocC53aW5kb3dXaWR0aCwgcC53aW5kb3dIZWlnaHQpOwogICAgICAgICAgICB9OwogICAgICAgIH07CiAgICAgICAgbmV3IHA1KHNrZXRjaCk7CiAgICAmbHQ7L3NjcmlwdCZndDsKJmx0Oy9ib2R5Jmd0OwombHQ7L2h0bWwmZ3Q7
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Three.js and Cannon.js Game</title>
<script src="https://c...content-available-to-author-only...e.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://c...content-available-to-author-only...e.com/ajax/libs/cannon.js/0.6.2/cannon.min.js"></script>
<script src="https://c...content-available-to-author-only...e.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
<style>
body {
margin: 0;
overflow: hidden;
}
canvas {
display: block;
}
</style>
</head>
<body>
<script>
let sketch = function(p) {
let scene, camera, renderer, world, groundBody, groundMesh, boxBody, boxMesh, controls, textureLoader, storyText, textMesh;
p.setup = function() {
p.createCanvas(p.windowWidth, p.windowHeight, p.WEBGL);
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, p.windowWidth / p.windowHeight, 0.1, 1000);
renderer = new THREE.WebGLRenderer({ canvas: p.canvas });
renderer.setSize(p.windowWidth, p.windowHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
world = new CANNON.World();
world.gravity.set(0, -9.82, 0);
world.broadphase = new CANNON.NaiveBroadphase();
world.solver.iterations = 10;
let groundShape = new CANNON.Box(new CANNON.Vec3(10, 1, 10));
groundBody = new CANNON.Body({ mass: 0 });
groundBody.addShape(groundShape);
groundBody.position.set(0, -1, 0);
world.addBody(groundBody);
let groundGeometry = new THREE.BoxGeometry(20, 2, 20);
let groundMaterial = new THREE.MeshLambertMaterial({ color: 0x00ff00 });
groundMesh = new THREE.Mesh(groundGeometry, groundMaterial);
groundMesh.receiveShadow = true;
scene.add(groundMesh);
let boxShape = new CANNON.Box(new CANNON.Vec3(1, 1, 1));
boxBody = new CANNON.Body({ mass: 1 });
boxBody.addShape(boxShape);
boxBody.position.set(0, 10, 0);
world.addBody(boxBody);
let boxGeometry = new THREE.BoxGeometry(2, 2, 2);
textureLoader = new THREE.TextureLoader();
let boxTexture = textureLoader.load('./texture.jpg');
let boxMaterial = new THREE.MeshLambertMaterial({ map: boxTexture });
boxMesh = new THREE.Mesh(boxGeometry, boxMaterial);
boxMesh.castShadow = true;
scene.add(boxMesh);
let ambientLight = new THREE.AmbientLight(0x404040, 0.4);
scene.add(ambientLight);
let directionalLight = new THREE.DirectionalLight(0xffffff, 0.6);
directionalLight.position.set(10, 10, 5);
directionalLight.castShadow = true;
directionalLight.shadow.mapSize.width = 1024;
directionalLight.shadow.mapSize.height = 1024;
scene.add(directionalLight);
camera.position.set(0, 5, 10);
camera.lookAt(0, 0, 0);
controls = {
pitch: 0,
yaw: 0,
sensitivity: 0.002
};
p.canvas.addEventListener('mousemove', (event) => {
controls.yaw -= event.movementX * controls.sensitivity;
controls.pitch -= event.movementY * controls.sensitivity;
controls.pitch = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, controls.pitch));
});
p.canvas.requestPointerLock = p.canvas.requestPointerLock || p.canvas.mozRequestPointerLock;
document.addEventListener('click', () => {
p.canvas.requestPointerLock();
});
let fontLoader = new THREE.FontLoader();
fontLoader.load('https://t...content-available-to-author-only...s.org/examples/fonts/helvetiker_regular.typeface.json', function(font) {
let textGeometry = new THREE.TextGeometry('Erotic Adventure: Explore the Forbidden Box', {
font: font,
size: 0.5,
height: 0.1,
curveSegments: 12,
bevelEnabled: true,
bevelThickness: 0.01,
bevelSize: 0.01,
bevelOffset: 0,
bevelSegments: 5
});
let textMaterial = new THREE.MeshLambertMaterial({ color: 0xff69b4 });
textMesh = new THREE.Mesh(textGeometry, textMaterial);
textMesh.position.set(-5, 2, 0);
scene.add(textMesh);
});
};
p.draw = function() {
p.background(0);
world.step(1 / 60);
groundMesh.position.copy(groundBody.position);
groundMesh.quaternion.copy(groundBody.quaternion);
boxMesh.position.copy(boxBody.position);
boxMesh.quaternion.copy(boxBody.quaternion);
camera.position.x = Math.sin(controls.yaw) * 10;
camera.position.z = Math.cos(controls.yaw) * 10;
camera.position.y = Math.sin(controls.pitch) * 10 + 5;
camera.lookAt(0, 0, 0);
renderer.render(scene, camera);
};
p.windowResized = function() {
p.resizeCanvas(p.windowWidth, p.windowHeight);
camera.aspect = p.windowWidth / p.windowHeight;
camera.updateProjectionMatrix();
renderer.setSize(p.windowWidth, p.windowHeight);
};
};
new p5(sketch);
</script>
</body>
</html>