|
@@ -0,0 +1,265 @@
|
|
|
+<!DOCTYPE html>
|
|
|
+<html lang="en">
|
|
|
+
|
|
|
+<head>
|
|
|
+ <title>three.js webgl - minimap</title>
|
|
|
+ <meta charset="utf-8">
|
|
|
+ <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
|
|
|
+ <link type="text/css" rel="stylesheet" href="main.css">
|
|
|
+ <style>
|
|
|
+ a {
|
|
|
+ color: #08f;
|
|
|
+ }
|
|
|
+
|
|
|
+ b {
|
|
|
+ color: lightgreen;
|
|
|
+ }
|
|
|
+
|
|
|
+ #mask {
|
|
|
+ position: absolute;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ background-color: rgba(0, 0, 0, 0.4);
|
|
|
+ }
|
|
|
+
|
|
|
+ #text {
|
|
|
+ position: absolute;
|
|
|
+ font-size: 30px;
|
|
|
+ width: 100%;
|
|
|
+ top: 50%;
|
|
|
+ text-align: center;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+ </style>
|
|
|
+</head>
|
|
|
+
|
|
|
+<body>
|
|
|
+ <div id="info"><a href="http://threejs.org" target="_blank" rel="noopener">three.js</a><a> - minimap</a><br />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div id="mask">
|
|
|
+ <div id="text">Click to start</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <script type="module">
|
|
|
+
|
|
|
+ import * as THREE from '../build/three.module.js';
|
|
|
+ import { PointerLockControls } from './jsm/controls/PointerLockControls.js';
|
|
|
+ import { GUI } from './jsm/libs/dat.gui.module.js';
|
|
|
+ import { Minimap } from './jsm/misc/Minimap.js';
|
|
|
+
|
|
|
+ var camera, scene, renderer, controls;
|
|
|
+ var objects = [];
|
|
|
+ var raycaster;
|
|
|
+ var moveForward = false;
|
|
|
+ var moveBackward = false;
|
|
|
+ var moveLeft = false;
|
|
|
+ var moveRight = false;
|
|
|
+ var canJump = false;
|
|
|
+ var isPointerLocked = true;
|
|
|
+ var prevTime = performance.now();
|
|
|
+ var velocity = new THREE.Vector3();
|
|
|
+ var direction = new THREE.Vector3();
|
|
|
+ var vertex = new THREE.Vector3();
|
|
|
+ var color = new THREE.Color();
|
|
|
+ var params = {
|
|
|
+ viewRange: 300,
|
|
|
+ mapSize: 300
|
|
|
+ };
|
|
|
+ var minimap;
|
|
|
+
|
|
|
+ init();
|
|
|
+
|
|
|
+ animate();
|
|
|
+
|
|
|
+ function init() {
|
|
|
+ //
|
|
|
+ renderer = new THREE.WebGLRenderer({ antialias: true });
|
|
|
+ renderer.setPixelRatio(window.devicePixelRatio);
|
|
|
+ renderer.setSize(window.innerWidth, window.innerHeight);
|
|
|
+ document.body.appendChild(renderer.domElement);
|
|
|
+
|
|
|
+ camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1000);
|
|
|
+ camera.position.y = 10;
|
|
|
+ scene = new THREE.Scene();
|
|
|
+ scene.background = new THREE.Color(0xffffff);
|
|
|
+ scene.fog = new THREE.Fog(0xffffff, 0, 200);
|
|
|
+
|
|
|
+ var light = new THREE.HemisphereLight(0xeeeeff, 0x777788, 0.75);
|
|
|
+ light.position.set(0.5, 1, 0.75);
|
|
|
+ scene.add(light);
|
|
|
+
|
|
|
+ //camera controls
|
|
|
+ controls = new PointerLockControls(camera, renderer.domElement);
|
|
|
+ scene.add(controls.getObject());
|
|
|
+
|
|
|
+ var mask = document.getElementById('mask');
|
|
|
+ var text = document.getElementById('text');
|
|
|
+
|
|
|
+ mask.addEventListener('click', function () {
|
|
|
+ controls.lock();
|
|
|
+ }, false);
|
|
|
+
|
|
|
+ controls.addEventListener('lock', function () {
|
|
|
+ mask.style.display = 'none';
|
|
|
+ });
|
|
|
+ controls.addEventListener('unlock', function () {
|
|
|
+ mask.style.display = 'block';
|
|
|
+ text.innerText = 'Click to continue';
|
|
|
+ });
|
|
|
+
|
|
|
+ renderer.domElement.addEventListener('click', function () {
|
|
|
+ controls.unlock();
|
|
|
+ mask.style.display = 'block';
|
|
|
+ }, false);
|
|
|
+
|
|
|
+ var onKeyDown = function (event) {
|
|
|
+
|
|
|
+ if (!controls.isLocked) return;
|
|
|
+
|
|
|
+ switch (event.keyCode) {
|
|
|
+ case 38: // up
|
|
|
+ case 87: // w
|
|
|
+ moveForward = true;
|
|
|
+ break;
|
|
|
+ case 37: // left
|
|
|
+ case 65: // a
|
|
|
+ moveLeft = true;
|
|
|
+ break;
|
|
|
+ case 40: // down
|
|
|
+ case 83: // s
|
|
|
+ moveBackward = true;
|
|
|
+ break;
|
|
|
+ case 39: // right
|
|
|
+ case 68: // d
|
|
|
+ moveRight = true;
|
|
|
+ break;
|
|
|
+ case 32: // space
|
|
|
+ if (canJump === true) velocity.y += 250;
|
|
|
+ canJump = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ var onKeyUp = function (event) {
|
|
|
+ switch (event.keyCode) {
|
|
|
+ case 38: // up
|
|
|
+ case 87: // w
|
|
|
+ moveForward = false;
|
|
|
+ break;
|
|
|
+ case 37: // left
|
|
|
+ case 65: // a
|
|
|
+ moveLeft = false;
|
|
|
+ break;
|
|
|
+ case 40: // down
|
|
|
+ case 83: // s
|
|
|
+ moveBackward = false;
|
|
|
+ break;
|
|
|
+ case 39: // right
|
|
|
+ case 68: // d
|
|
|
+ moveRight = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ document.addEventListener('keydown', onKeyDown, false);
|
|
|
+ document.addEventListener('keyup', onKeyUp, false);
|
|
|
+
|
|
|
+ raycaster = new THREE.Raycaster(new THREE.Vector3(), new THREE.Vector3(0, - 1, 0), 0, 10);
|
|
|
+
|
|
|
+ // ground mesh
|
|
|
+ var groundGeometry = new THREE.PlaneBufferGeometry(2000, 2000, 100, 100);
|
|
|
+ groundGeometry.rotateX(- Math.PI / 2);
|
|
|
+ var groundMaterial = new THREE.MeshBasicMaterial({ color: new THREE.Color(0.2, 0.75, 0.5) });
|
|
|
+ var ground = new THREE.Mesh(groundGeometry, groundMaterial);
|
|
|
+ scene.add(ground);
|
|
|
+
|
|
|
+ // obstacles
|
|
|
+ for (var i = 0; i < 600; i++) {
|
|
|
+ var boxGeometry = new THREE.BoxBufferGeometry(20, 80, 20);
|
|
|
+ var boxMaterial = new THREE.MeshPhongMaterial({
|
|
|
+ specular: new THREE.Color(Math.random(), Math.random(), Math.random()),
|
|
|
+ flatShading: true
|
|
|
+ });
|
|
|
+ boxMaterial.color.setHSL(Math.random() * 0.2 + 0.4, 0.6, Math.random() * 0.3 + 0.75); //Math.random() * 0.2 + 0.5
|
|
|
+ var box = new THREE.Mesh(boxGeometry, boxMaterial);
|
|
|
+ box.position.x = Math.floor(Math.random() * 40 - 20) * 20;
|
|
|
+ box.position.z = Math.floor(Math.random() * 40 - 20) * 20;
|
|
|
+ if (box.position.x == 0 && box.position.z == 0) continue;
|
|
|
+ scene.add(box);
|
|
|
+ objects.push(box);
|
|
|
+ }
|
|
|
+
|
|
|
+ // init minimap
|
|
|
+ minimap = new Minimap(renderer, scene, camera, {
|
|
|
+ viewRange: params.viewRange,
|
|
|
+ mapSize: params.mapSize,
|
|
|
+ heightOffset: 100
|
|
|
+ });
|
|
|
+
|
|
|
+ var gui = new GUI();
|
|
|
+ gui.add(params, 'viewRange', 100, 800);
|
|
|
+ gui.add(params, 'mapSize', 100, 500);
|
|
|
+ gui.open();
|
|
|
+
|
|
|
+ //
|
|
|
+ window.addEventListener('resize', function () {
|
|
|
+ camera.aspect = window.innerWidth / window.innerHeight;
|
|
|
+ camera.updateProjectionMatrix();
|
|
|
+ renderer.setSize(window.innerWidth, window.innerHeight);
|
|
|
+ }, false);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ function animate() {
|
|
|
+
|
|
|
+ requestAnimationFrame(animate);
|
|
|
+
|
|
|
+ // first person control
|
|
|
+ raycaster.ray.origin.copy(controls.getObject().position);
|
|
|
+ raycaster.ray.origin.y -= 10;
|
|
|
+ var intersections = raycaster.intersectObjects(objects);
|
|
|
+ var onObject = intersections.length > 0;
|
|
|
+ var time = performance.now();
|
|
|
+ var delta = (time - prevTime) / 1000;
|
|
|
+ velocity.x -= velocity.x * 10.0 * delta;
|
|
|
+ velocity.z -= velocity.z * 10.0 * delta;
|
|
|
+ velocity.y -= 9.8 * 100.0 * delta; // 100.0 = mass
|
|
|
+ direction.z = Number(moveForward) - Number(moveBackward);
|
|
|
+ direction.x = Number(moveRight) - Number(moveLeft);
|
|
|
+ direction.normalize(); // this ensures consistent movements in all directions
|
|
|
+ if (moveForward || moveBackward) velocity.z -= direction.z * 400.0 * delta;
|
|
|
+ if (moveLeft || moveRight) velocity.x -= direction.x * 400.0 * delta;
|
|
|
+ if (onObject === true) {
|
|
|
+ velocity.y = Math.max(0, velocity.y);
|
|
|
+ canJump = true;
|
|
|
+ }
|
|
|
+ controls.moveRight(- velocity.x * delta);
|
|
|
+ controls.moveForward(- velocity.z * delta);
|
|
|
+ controls.getObject().position.y += (velocity.y * delta); // new behavior
|
|
|
+ if (controls.getObject().position.y < 10) {
|
|
|
+ velocity.y = 0;
|
|
|
+ controls.getObject().position.y = 10;
|
|
|
+ canJump = true;
|
|
|
+ }
|
|
|
+ prevTime = time;
|
|
|
+
|
|
|
+ // render main scene
|
|
|
+ minimap.setMinimapVisibility(false);
|
|
|
+ scene.fog.far = 200;
|
|
|
+ renderer.render(scene, camera);
|
|
|
+
|
|
|
+ // render minimap
|
|
|
+ scene.fog.far = 100000;
|
|
|
+ minimap.viewRange = params.viewRange;
|
|
|
+ minimap.mapSize = params.mapSize;
|
|
|
+ minimap.renderMinimap();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ </script>
|
|
|
+
|
|
|
+</body>
|
|
|
+
|
|
|
+</html>
|