Last active
August 29, 2015 13:56
-
-
Save tkojitu/8965475 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<script type="text/javascript" src="../libs/three.js"></script> | |
<script src="squash.js"></script> | |
<style> | |
body{ | |
margin: 0; | |
overflow: hidden; | |
} | |
#slider{ | |
-webkit-appearance: none; | |
width: 100%; | |
background-color: gray; | |
} | |
#slider::-webkit-slider-thumb { | |
-webkit-appearance: none; | |
width: 20px; | |
height: 50px; | |
border-radius: 10%; | |
background: lightGray; | |
} | |
</style> | |
</head> | |
<body onload="onLoad()"> | |
<div id="output"></div> | |
<input type="range" id="slider" min="-100" max="100"> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function onLoad() { | |
var COLOR_GREEN = new THREE.Color("green"); | |
var COLOR_RED = new THREE.Color("red"); | |
var HIT_NONE = 0; | |
var HIT_SMALL = 1; | |
var HIT_CENTER = 2; | |
var HIT_LARGE = 3; | |
var ball; | |
var camera; | |
var dx = 0.2; | |
var dz = 0.2; | |
var paddle; | |
var renderer; | |
var scene; | |
var v3 = new THREE.Vector3(0, 0, 0); | |
function setupScene() { | |
scene = newScene(); | |
renderer = newRenderer(); | |
camera = newCamera(scene.position); | |
var div = document.getElementById("output"); | |
div.appendChild(renderer.domElement); | |
} | |
function newScene() { | |
var scene = new THREE.Scene(); | |
var field = newField(); | |
scene.add(field); | |
ball = newBall(); | |
scene.add(ball); | |
paddle = newPaddle(); | |
scene.add(paddle); | |
var spotLight = newLight(); | |
scene.add(spotLight); | |
return scene; | |
} | |
function newRenderer() { | |
var renderer = new THREE.WebGLRenderer(); | |
renderer.setClearColorHex(0xEEEEEE, 1.0); | |
var size = getRendererSize(); | |
renderer.setSize(size.width, size.height); | |
renderer.shadowMapEnabled = true; | |
return renderer; | |
} | |
function getRendererSize() { | |
var sliderSize = getSliderSize(); | |
return { | |
width: window.innerWidth | |
,height: window.innerHeight - sliderSize.height - 5 | |
}; | |
} | |
function getSliderSize() { | |
var slider = document.getElementById("slider"); | |
return { | |
width: slider.clientWidth | |
,height: slider.clientHeight | |
}; | |
} | |
function newField() { | |
var box = getFieldBox(); | |
box.size(v3); | |
var geo = new THREE.CubeGeometry(v3.x, v3.y, v3.z); | |
var mat = new THREE.MeshLambertMaterial({color: 0xffffff}); | |
var field = new THREE.Mesh(geo, mat); | |
field.receiveShadow = true; | |
box.center(v3); | |
field.position.x = v3.x; | |
field.position.y = v3.y; | |
field.position.z = v3.z; | |
return field; | |
} | |
function getFieldBox() { | |
return new THREE.Box3( | |
new THREE.Vector3(-30, -1, -10), | |
new THREE.Vector3(30, 0, 10)); | |
} | |
function newBall() { | |
var geo = new THREE.CubeGeometry(1, 1, 1); | |
var mat = new THREE.MeshLambertMaterial({color: 0x7777ff}); | |
var ball = new THREE.Mesh(geo, mat); | |
ball.position.x = 0; | |
ball.position.y = 2; | |
ball.position.z = 0; | |
ball.castShadow = true; | |
return ball; | |
} | |
function newPaddle() { | |
var size = getPaddleSize(); | |
var geo = new THREE.CubeGeometry(size.x, size.y, size.z); | |
var mat = new THREE.MeshLambertMaterial({color: 0xff0000}); | |
var paddle = new THREE.Mesh(geo, mat); | |
paddle.castShadow = true; | |
var pos = getInitialPaddlePosition(); | |
paddle.position.x = pos.x; | |
paddle.position.y = pos.y; | |
paddle.position.z = pos.z; | |
return paddle; | |
} | |
function getPaddleSize() { | |
return new THREE.Vector3(1, 2, 4); | |
} | |
function getInitialPaddlePosition() { | |
return new THREE.Vector3(-30, 2, 0); | |
} | |
function getPaddleBox() { | |
var center = paddle.position; | |
var size = getPaddleSize(); | |
var min = new THREE.Vector3( | |
center.x - size.x / 2.0, | |
center.y - size.y / 2.0, | |
center.z - size.z / 2.0); | |
var max = new THREE.Vector3( | |
center.x + size.x / 2.0, | |
center.y + size.y / 2.0, | |
center.z + size.z / 2.0); | |
return new THREE.Box3(min, max); | |
} | |
function newLight() { | |
var spotLight = new THREE.SpotLight(0xffffff); | |
spotLight.position.set(-40, 60, -10); | |
spotLight.castShadow = true; | |
return spotLight; | |
} | |
function newCamera(lookAt) { | |
var ratio = getAspectRatio(); | |
var camera = new THREE.PerspectiveCamera(45, ratio, 0.1, 1000); | |
camera.position.x = -50; | |
camera.position.y = 10; | |
camera.position.z = 0; | |
camera.lookAt(lookAt); | |
return camera; | |
} | |
function getAspectRatio() { | |
var size = getRendererSize(); | |
return size.width / size.height; | |
} | |
function render() { | |
window.requestAnimationFrame(render); | |
renderer.render(scene, camera); | |
moveBall(); | |
resetBall(); | |
} | |
function moveBall() { | |
var hit = hitsBall(); | |
if (hit == HIT_SMALL || hit == HIT_LARGE) { | |
changePaddleColor(); | |
dx = -dx; | |
if (dz < 0) { | |
dz -= 0.1; | |
} else { | |
dz += 0.1; | |
} | |
} else if (hit == HIT_CENTER) { | |
changePaddleColor(); | |
if (dx < 0) { | |
dx -= 0.1; | |
} else { | |
dx += 0.1; | |
} | |
dx = -dx; | |
} else { | |
var box = getFieldBox(); | |
if (box.max.x < ball.position.x) { | |
dx = -dx; | |
} | |
if (ball.position.x >= paddle.position.x | |
&& (ball.position.z < box.min.z | |
|| box.max.z < ball.position.z)) { | |
dz = -dz; | |
} | |
} | |
limitSpeed(); | |
ball.position.x += dx; | |
ball.position.z += dz; | |
} | |
function hitsBall() { | |
if (ball.position.x > paddle.position.x) { | |
return false; | |
} | |
var paddleBox = getPaddleBox(); | |
if (ball.position.z < paddleBox.min.z) { | |
return HIT_NONE; | |
} else if (ball.position.z > paddleBox.max.z) { | |
return HIT_NONE; | |
} else if (hitsPaddleSmall(ball.position.z)) { | |
return HIT_SMALL; | |
} else if (hitsPaddleCenter(ball.position.z)) { | |
return HIT_CENTER; | |
} else if (hitsPaddleLarge(ball.position.z)) { | |
return HIT_LARGE; | |
} else { | |
return HIT_NONE; | |
} | |
} | |
function hitsPaddleSmall(z) { | |
var box = getPaddleBox(); | |
var len = Math.abs(box.max.z - box.min.z) / 3.0; | |
return box.min.z <= z | |
&& z< box.min.z + len; | |
} | |
function hitsPaddleCenter(z) { | |
var box = getPaddleBox(); | |
var len = Math.abs(box.max.z - box.min.z) / 3.0; | |
return box.min.z + len <= z | |
&& z <= box.min.z + len * 2; | |
} | |
function hitsPaddleLarge(z) { | |
var box = getPaddleBox(); | |
var len = Math.abs(box.max.z - box.min.z) / 3.0; | |
return box.min.z + len * 2 < z | |
&& z <= box.max.z; | |
} | |
function limitSpeed() { | |
if (-0.2 < dx && dx < 0) { | |
dx = -0.2; | |
} else if (0 <= dx && dx < 0.2) { | |
dx = 0.2; | |
} | |
if (-0.2 < dz && dz < 0) { | |
dz = -0.2; | |
} else if (0 <= dz && dz < 0.2) { | |
dz = 0.2; | |
} | |
} | |
function changePaddleColor() { | |
if (COLOR_RED.equals(paddle.material.color)) { | |
paddle.material.color = COLOR_GREEN; | |
} else { | |
paddle.material.color = COLOR_RED; | |
} | |
} | |
function resetBall() { | |
var box = getFieldBox(); | |
if (ball.position.x < box.min.x - 30 | |
|| ball.position.x > box.max.x + 30 | |
|| ball.position.y < box.min.y - 30 | |
|| ball.position.y > box.max.y + 30 | |
|| ball.position.z < box.min.z - 30 | |
|| ball.position.z > box.max.z + 30) { | |
ball.position.x = 0; | |
ball.position.y = 2; | |
ball.position.z = 0; | |
dx = 0.2; | |
dz = 0.2; | |
} | |
} | |
function addSliderListener() { | |
var slider = document.getElementById("slider"); | |
slider.addEventListener("input", function(e){onInput(e);}, false); | |
} | |
function onInput(event) { | |
var z = event.target.value / 10.0; | |
var min = getPaddleMinZ(); | |
var max = getPaddleMaxZ(); | |
if (z < min) { | |
z = min; | |
} else if (z > max) { | |
z = max; | |
} | |
paddle.position.z = z; | |
} | |
function getPaddleMinZ() { | |
var fieldBox = getFieldBox(); | |
var paddleSize = getPaddleSize(); | |
return fieldBox.min.z + paddleSize.z / 2.0; | |
} | |
function getPaddleMaxZ() { | |
return getPaddleMinZ() * -1.0; | |
} | |
setupScene(); | |
render(); | |
addSliderListener(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment