Skip to content

Instantly share code, notes, and snippets.

@tkojitu
Last active August 29, 2015 13:56
Show Gist options
  • Save tkojitu/8965475 to your computer and use it in GitHub Desktop.
Save tkojitu/8965475 to your computer and use it in GitHub Desktop.
<!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>
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