Skip to content

Commit

Permalink
Adding keyboard movement, half-portal example
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
stemkoski committed Jun 1, 2018
1 parent 18911c1 commit a558e63
Show file tree
Hide file tree
Showing 23 changed files with 654 additions and 0 deletions.
Binary file added images/arrow-curved.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/arrow-double.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/arrow-single.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/demo/camera-movement.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/demo/mesh-movement.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/demo/portal-half-keyboard-test.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/key-blank.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/movement-controls.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/scene-sphere.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/sphere-colored.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/sphere-pos-neg.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/xneg.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/xpos.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/yneg.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/ypos.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/zneg.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/zpos.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 19 additions & 0 deletions index.html
Expand Up @@ -127,7 +127,26 @@
out from a cylindrical hole (displayed above a Hiro marker), and being absorbed into the floor. </p>
</div>

<div class="fancy">
<a href="keyboard-mesh-move.html" target="_blank">
<img src="images/demo/mesh-movement.png" class="superImage" />
<br/>Keyboard-Based Object Movement</a>
<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>
</div>

<div class="fancy">
<a href="keyboard-camera-move.html" target="_blank">
<img src="images/demo/camera-movement.png" class="superImage" />
<br/>Keyboard-Based Camera Movement</a>
<p class ="superText"> Move a camera around the screen with the keyboard. <br>Uses same controls as Object Movement example. </p>
</div>

<div class="fancy">
<a href="portal-half-keyboard-test.html" target="_blank">
<img src="images/demo/portal-half-keyboard-test.png" class="superImage" />
<br/>Portal Test</a>
<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>
</div>

<!--
<div class="fancy">
Expand Down
126 changes: 126 additions & 0 deletions js/keyboard.js
@@ -0,0 +1,126 @@
/*
Keyboard.js - a class for simplifying keyboard interaction.
Created by Lee Stemkoski.
Usage:
// initialize keyboard
var keyboard = new Keyboard();
// in update loop
keyboard.update();
// check for discrete input (on key down/up event)
keyboard.isKeyDown("Space");
keyboard.isKeyUp("X");
// check for continuous input (true between key down and key up events)
keyboard.isKeyPressed("ArrowUp");
*/

class Keyboard
{
constructor()
{
// Event listeners add keys to Queues.
// Update method updates Sets accordingly.
this.keyDownQueue = new Set();
this.keyUpQueue = new Set();

this.keyDownSet = new Set();
this.keyPressedSet = new Set();
this.keyUpSet = new Set();

this.onKeyDown = function(key) {};
this.onKeyUp = function(key) {};

let self = this;

document.addEventListener( "keydown",
function(eventData)
{
let key = eventData.key;
if (key == " ")
key = "Space";
if (key.length == 1)
key = key.toUpperCase();
self.keyDownQueue.add( key );
// activate callback function (only once)
if ( !self.keyPressedSet.has(key) )
self.onKeyDown(key);
}
);

document.addEventListener( "keyup",
function(eventData)
{
let key = eventData.key;
if (key == " ")
key = "Space";
if (key.length == 1)
key = key.toUpperCase();
self.keyUpQueue.add( key );
// activate callback function
self.onKeyUp(key);
}
);
};

update()
{
// clear previous discrete event status
this.keyDownSet.clear();
this.keyUpSet.clear();

// update current event status
for (let k of this.keyDownQueue)
{
// avoid multiple keydown events while holding key
if ( !this.keyPressedSet.has(k) )
{
this.keyDownSet.add(k);
this.keyPressedSet.add(k);
}
}

for (let k of this.keyUpQueue)
{
this.keyPressedSet.delete(k);
this.keyUpSet.add(k);
}

// clear the queues used to store events
this.keyDownQueue.clear();
this.keyUpQueue.clear();
};

// only true for a single frame after key down
isKeyDown( keyName )
{
return ( this.keyDownSet.has(keyName) );
};

// true between key down and key up events
isKeyPressed( keyName )
{
return ( this.keyPressedSet.has(keyName) );
};

// only true for a single frame after key up
isKeyUp( keyName )
{
return ( this.keyUpSet.has(keyName) );
};

// set callback function
setOnKeyDown( callbackFunction )
{
this.onKeyDown = callbackFunction;
};

// set callback function
setOnKeyUp( callbackFunction )
{
this.onKeyUp = callbackFunction;
};

}
151 changes: 151 additions & 0 deletions keyboard-camera-move.html
@@ -0,0 +1,151 @@
<!DOCTYPE html>
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<title>Hello, world!</title>
<script src='js/keyboard.js'></script>
<!-- include three.js library -->
<script src='js/three.js'></script>
</head>

<body style='margin : 0px; overflow: hidden; font-family: Monospace;'>

<!--
Example created by Lee Stemkoski: https://github.com/stemkoski
-->

<script>

var scene, camera, renderer, clock, deltaTime, totalTime, keyboard;

var mover;

initialize();
animate();

function initialize()
{
scene = new THREE.Scene();

camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 1000 );

mover = new THREE.Group();
mover.add( camera );
mover.position.set(0, 2, 4);
scene.add( mover );

//camera.position.set(0, 2, 4);
//camera.lookAt( scene.position );
//scene.add( camera );

let ambientLight = new THREE.AmbientLight( 0xcccccc, 1.00 );
scene.add( ambientLight );

// let pointLight = new THREE.PointLight();
// camera.add( pointLight );

renderer = new THREE.WebGLRenderer({
antialias : true,
alpha: false
});
renderer.setClearColor(new THREE.Color('lightgrey'), 0)
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.domElement.style.position = 'absolute'
renderer.domElement.style.top = '0px'
renderer.domElement.style.left = '0px'
document.body.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );

clock = new THREE.Clock();
deltaTime = 0;
totalTime = 0;

keyboard = new Keyboard();

let loader = new THREE.TextureLoader();

// floor
let floorGeometry = new THREE.PlaneGeometry(10,10);
let floorMaterial = new THREE.MeshBasicMaterial({
map: loader.load( 'images/color-grid.png' )
});
let floorMesh = new THREE.Mesh( floorGeometry, floorMaterial );
floorMesh.rotation.x = -Math.PI/2;
scene.add( floorMesh );

let cubeGeometry = new THREE.BoxGeometry(1,1,1);
let materialArray = [
new THREE.MeshBasicMaterial( { map: loader.load("images/xpos.png") } ),
new THREE.MeshBasicMaterial( { map: loader.load("images/xneg.png") } ),
new THREE.MeshBasicMaterial( { map: loader.load("images/ypos.png") } ),
new THREE.MeshBasicMaterial( { map: loader.load("images/yneg.png") } ),
new THREE.MeshBasicMaterial( { map: loader.load("images/zpos.png") } ),
new THREE.MeshBasicMaterial( { map: loader.load("images/zneg.png") } ),
];
let cubeMesh = new THREE.Mesh( cubeGeometry, materialArray );
cubeMesh.position.y = 0.5;
scene.add( cubeMesh );
}

function update()
{
keyboard.update();

let translateSpeed = 0.5; // units per second
let distance = translateSpeed * deltaTime;
let rotateSpeed = Math.PI/6; // radians per second
let angle = rotateSpeed * deltaTime;

if (keyboard.isKeyPressed("W"))
mover.translateZ( -distance );
if (keyboard.isKeyPressed("S"))
mover.translateZ( distance );

if (keyboard.isKeyPressed("A"))
mover.translateX( -distance );
if (keyboard.isKeyPressed("D"))
mover.translateX( distance );

if (keyboard.isKeyPressed("R"))
mover.translateY( distance );
if (keyboard.isKeyPressed("F"))
mover.translateY( -distance );

if (keyboard.isKeyPressed("Q"))
mover.rotateY( angle );
if (keyboard.isKeyPressed("E"))
mover.rotateY( -angle );

if (keyboard.isKeyPressed("T"))
mover.children[0].rotateX( angle );
if (keyboard.isKeyPressed("G"))
mover.children[0].rotateX( -angle );


//mesh.rotation.y += 0.01;
}

function render()
{
renderer.render( scene, camera );
}

function animate()
{
requestAnimationFrame(animate);
deltaTime = clock.getDelta();
totalTime += deltaTime;
update();
render();
}

function onWindowResize()
{
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}

</script>

</body>
</html>

0 comments on commit a558e63

Please sign in to comment.