Skip to content

Commit a558e63

Browse files
committed
Adding keyboard movement, half-portal example
Adding keyboard class to simplify keyboard interaction, demo mesh movement and camera movement examples, and "portal to another world" effect (still a work in progress).
1 parent 18911c1 commit a558e63

23 files changed

+654
-0
lines changed

images/arrow-curved.png

3.31 KB
Loading

images/arrow-double.png

1.27 KB
Loading

images/arrow-single.png

1.35 KB
Loading

images/demo/camera-movement.png

64.9 KB
Loading

images/demo/mesh-movement.png

62.9 KB
Loading
68.7 KB
Loading

images/key-blank.png

1.22 KB
Loading

images/movement-controls.png

26.2 KB
Loading

images/scene-sphere.jpg

229 KB
Loading

images/sphere-colored.png

3.62 KB
Loading

images/sphere-pos-neg.png

46 KB
Loading

images/xneg.png

9.97 KB
Loading

images/xpos.png

10.7 KB
Loading

images/yneg.png

13.7 KB
Loading

images/ypos.png

9.47 KB
Loading

images/zneg.png

9.99 KB
Loading

images/zpos.png

10.7 KB
Loading

index.html

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,26 @@
127127
out from a cylindrical hole (displayed above a Hiro marker), and being absorbed into the floor. </p>
128128
</div>
129129

130+
<div class="fancy">
131+
<a href="keyboard-mesh-move.html" target="_blank">
132+
<img src="images/demo/mesh-movement.png" class="superImage" />
133+
<br/>Keyboard-Based Object Movement</a>
134+
<p class ="superText"> Move a cube around the screen with the keyboard. Controls (<a href="images/movement-controls.png">image</a>): <br>W/A/S/D -- move Forward/Left/Backward/Right (standard), <br>Q/E -- rotate Left/Right, <br>R/F -- move Up/Down (think: <b>R</b>ise/<b>F</b>all), <br>T/G -- tilt Up/Down (think: look at <b>T</b>ower/<b>G</b>round).</p>
135+
</div>
130136

137+
<div class="fancy">
138+
<a href="keyboard-camera-move.html" target="_blank">
139+
<img src="images/demo/camera-movement.png" class="superImage" />
140+
<br/>Keyboard-Based Camera Movement</a>
141+
<p class ="superText"> Move a camera around the screen with the keyboard. <br>Uses same controls as Object Movement example. </p>
142+
</div>
143+
144+
<div class="fancy">
145+
<a href="portal-half-keyboard-test.html" target="_blank">
146+
<img src="images/demo/portal-half-keyboard-test.png" class="superImage" />
147+
<br/>Portal Test</a>
148+
<p class ="superText"> Creating a "portal to another world" effect. Camera moves using same controls as Object Movement example. Only visible from one side. </p>
149+
</div>
131150

132151
<!--
133152
<div class="fancy">

js/keyboard.js

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/*
2+
Keyboard.js - a class for simplifying keyboard interaction.
3+
Created by Lee Stemkoski.
4+
5+
Usage:
6+
// initialize keyboard
7+
var keyboard = new Keyboard();
8+
9+
// in update loop
10+
keyboard.update();
11+
12+
// check for discrete input (on key down/up event)
13+
keyboard.isKeyDown("Space");
14+
keyboard.isKeyUp("X");
15+
16+
// check for continuous input (true between key down and key up events)
17+
keyboard.isKeyPressed("ArrowUp");
18+
*/
19+
20+
class Keyboard
21+
{
22+
constructor()
23+
{
24+
// Event listeners add keys to Queues.
25+
// Update method updates Sets accordingly.
26+
this.keyDownQueue = new Set();
27+
this.keyUpQueue = new Set();
28+
29+
this.keyDownSet = new Set();
30+
this.keyPressedSet = new Set();
31+
this.keyUpSet = new Set();
32+
33+
this.onKeyDown = function(key) {};
34+
this.onKeyUp = function(key) {};
35+
36+
let self = this;
37+
38+
document.addEventListener( "keydown",
39+
function(eventData)
40+
{
41+
let key = eventData.key;
42+
if (key == " ")
43+
key = "Space";
44+
if (key.length == 1)
45+
key = key.toUpperCase();
46+
self.keyDownQueue.add( key );
47+
// activate callback function (only once)
48+
if ( !self.keyPressedSet.has(key) )
49+
self.onKeyDown(key);
50+
}
51+
);
52+
53+
document.addEventListener( "keyup",
54+
function(eventData)
55+
{
56+
let key = eventData.key;
57+
if (key == " ")
58+
key = "Space";
59+
if (key.length == 1)
60+
key = key.toUpperCase();
61+
self.keyUpQueue.add( key );
62+
// activate callback function
63+
self.onKeyUp(key);
64+
}
65+
);
66+
};
67+
68+
update()
69+
{
70+
// clear previous discrete event status
71+
this.keyDownSet.clear();
72+
this.keyUpSet.clear();
73+
74+
// update current event status
75+
for (let k of this.keyDownQueue)
76+
{
77+
// avoid multiple keydown events while holding key
78+
if ( !this.keyPressedSet.has(k) )
79+
{
80+
this.keyDownSet.add(k);
81+
this.keyPressedSet.add(k);
82+
}
83+
}
84+
85+
for (let k of this.keyUpQueue)
86+
{
87+
this.keyPressedSet.delete(k);
88+
this.keyUpSet.add(k);
89+
}
90+
91+
// clear the queues used to store events
92+
this.keyDownQueue.clear();
93+
this.keyUpQueue.clear();
94+
};
95+
96+
// only true for a single frame after key down
97+
isKeyDown( keyName )
98+
{
99+
return ( this.keyDownSet.has(keyName) );
100+
};
101+
102+
// true between key down and key up events
103+
isKeyPressed( keyName )
104+
{
105+
return ( this.keyPressedSet.has(keyName) );
106+
};
107+
108+
// only true for a single frame after key up
109+
isKeyUp( keyName )
110+
{
111+
return ( this.keyUpSet.has(keyName) );
112+
};
113+
114+
// set callback function
115+
setOnKeyDown( callbackFunction )
116+
{
117+
this.onKeyDown = callbackFunction;
118+
};
119+
120+
// set callback function
121+
setOnKeyUp( callbackFunction )
122+
{
123+
this.onKeyUp = callbackFunction;
124+
};
125+
126+
}

keyboard-camera-move.html

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
<!DOCTYPE html>
2+
<head>
3+
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
4+
<title>Hello, world!</title>
5+
<script src='js/keyboard.js'></script>
6+
<!-- include three.js library -->
7+
<script src='js/three.js'></script>
8+
</head>
9+
10+
<body style='margin : 0px; overflow: hidden; font-family: Monospace;'>
11+
12+
<!--
13+
Example created by Lee Stemkoski: https://github.com/stemkoski
14+
-->
15+
16+
<script>
17+
18+
var scene, camera, renderer, clock, deltaTime, totalTime, keyboard;
19+
20+
var mover;
21+
22+
initialize();
23+
animate();
24+
25+
function initialize()
26+
{
27+
scene = new THREE.Scene();
28+
29+
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 1000 );
30+
31+
mover = new THREE.Group();
32+
mover.add( camera );
33+
mover.position.set(0, 2, 4);
34+
scene.add( mover );
35+
36+
//camera.position.set(0, 2, 4);
37+
//camera.lookAt( scene.position );
38+
//scene.add( camera );
39+
40+
let ambientLight = new THREE.AmbientLight( 0xcccccc, 1.00 );
41+
scene.add( ambientLight );
42+
43+
// let pointLight = new THREE.PointLight();
44+
// camera.add( pointLight );
45+
46+
renderer = new THREE.WebGLRenderer({
47+
antialias : true,
48+
alpha: false
49+
});
50+
renderer.setClearColor(new THREE.Color('lightgrey'), 0)
51+
renderer.setSize( window.innerWidth, window.innerHeight );
52+
renderer.domElement.style.position = 'absolute'
53+
renderer.domElement.style.top = '0px'
54+
renderer.domElement.style.left = '0px'
55+
document.body.appendChild( renderer.domElement );
56+
window.addEventListener( 'resize', onWindowResize, false );
57+
58+
clock = new THREE.Clock();
59+
deltaTime = 0;
60+
totalTime = 0;
61+
62+
keyboard = new Keyboard();
63+
64+
let loader = new THREE.TextureLoader();
65+
66+
// floor
67+
let floorGeometry = new THREE.PlaneGeometry(10,10);
68+
let floorMaterial = new THREE.MeshBasicMaterial({
69+
map: loader.load( 'images/color-grid.png' )
70+
});
71+
let floorMesh = new THREE.Mesh( floorGeometry, floorMaterial );
72+
floorMesh.rotation.x = -Math.PI/2;
73+
scene.add( floorMesh );
74+
75+
let cubeGeometry = new THREE.BoxGeometry(1,1,1);
76+
let materialArray = [
77+
new THREE.MeshBasicMaterial( { map: loader.load("images/xpos.png") } ),
78+
new THREE.MeshBasicMaterial( { map: loader.load("images/xneg.png") } ),
79+
new THREE.MeshBasicMaterial( { map: loader.load("images/ypos.png") } ),
80+
new THREE.MeshBasicMaterial( { map: loader.load("images/yneg.png") } ),
81+
new THREE.MeshBasicMaterial( { map: loader.load("images/zpos.png") } ),
82+
new THREE.MeshBasicMaterial( { map: loader.load("images/zneg.png") } ),
83+
];
84+
let cubeMesh = new THREE.Mesh( cubeGeometry, materialArray );
85+
cubeMesh.position.y = 0.5;
86+
scene.add( cubeMesh );
87+
}
88+
89+
function update()
90+
{
91+
keyboard.update();
92+
93+
let translateSpeed = 0.5; // units per second
94+
let distance = translateSpeed * deltaTime;
95+
let rotateSpeed = Math.PI/6; // radians per second
96+
let angle = rotateSpeed * deltaTime;
97+
98+
if (keyboard.isKeyPressed("W"))
99+
mover.translateZ( -distance );
100+
if (keyboard.isKeyPressed("S"))
101+
mover.translateZ( distance );
102+
103+
if (keyboard.isKeyPressed("A"))
104+
mover.translateX( -distance );
105+
if (keyboard.isKeyPressed("D"))
106+
mover.translateX( distance );
107+
108+
if (keyboard.isKeyPressed("R"))
109+
mover.translateY( distance );
110+
if (keyboard.isKeyPressed("F"))
111+
mover.translateY( -distance );
112+
113+
if (keyboard.isKeyPressed("Q"))
114+
mover.rotateY( angle );
115+
if (keyboard.isKeyPressed("E"))
116+
mover.rotateY( -angle );
117+
118+
if (keyboard.isKeyPressed("T"))
119+
mover.children[0].rotateX( angle );
120+
if (keyboard.isKeyPressed("G"))
121+
mover.children[0].rotateX( -angle );
122+
123+
124+
//mesh.rotation.y += 0.01;
125+
}
126+
127+
function render()
128+
{
129+
renderer.render( scene, camera );
130+
}
131+
132+
function animate()
133+
{
134+
requestAnimationFrame(animate);
135+
deltaTime = clock.getDelta();
136+
totalTime += deltaTime;
137+
update();
138+
render();
139+
}
140+
141+
function onWindowResize()
142+
{
143+
camera.aspect = window.innerWidth / window.innerHeight;
144+
camera.updateProjectionMatrix();
145+
renderer.setSize( window.innerWidth, window.innerHeight );
146+
}
147+
148+
</script>
149+
150+
</body>
151+
</html>

0 commit comments

Comments
 (0)