feat: sound, generator, etc.

This commit is contained in:
Mahdi Dibaiee
2018-12-28 23:04:00 +03:30
parent e983346ffc
commit d6eaa09346
17 changed files with 233 additions and 98 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+6
View File
@@ -31,7 +31,9 @@
<script src='lib/physics-module.js'></script>
<script src='lib/ammo.js'></script>
<script src='lib/mousetrap.js'></script>
<script src='lib/howler.min.js'></script>
<script src='lib/moment.min.js'></script>
<script src='lib/color-scheme.min.js'></script>
</head>
<body>
<div id='gui'>
@@ -44,10 +46,14 @@
<p>
Score: <span id='score'>000</span>
</p>
<p>
Hits: <span id='hits'>00</span>
</p>
</div>
<script src='src/utils.js'></script>
<script src='src/config.js'></script>
<script src='src/audio.js'></script>
<script src='src/gui.js'></script>
<script src='src/objects.js'></script>
<script src='src/world.js'></script>
+1
View File
File diff suppressed because one or more lines are too long
+4
View File
File diff suppressed because one or more lines are too long
+30
View File
@@ -0,0 +1,30 @@
const audio = {
fire: new Howl({
src: ['assets/audio/fire.wav'],
autoplay: true,
loop: true,
volume: 0.3
}),
music: new Howl({
src: ['assets/audio/music.mp3'],
autoplay: true,
loop: true,
volume: 0.1,
}),
rumble: new Howl({
src: ['assets/audio/rumble.wav'],
autoplay: false,
loop: true,
volume: 0.2,
}),
impacts: [0, 1, 2].map(i => new Howl({
src: [`assets/audio/impact-${i}.wav`],
volume: 0.5
})),
}
audio.fire.play();
audio.music.play();
+44 -57
View File
@@ -1,10 +1,5 @@
const RADIUS = 10;
const SEGMENTS = 40;
const material = new THREE.MeshLambertMaterial({
color: 0xFFFFFF,
emissive: 0xFF0000,
emissiveIntensity: 0.4,
});
const ballPhysics = new PHYSICS.SphereModule({
mass: 2,
friction: 0.5,
@@ -20,7 +15,11 @@ const ball = new WHS.Sphere({
z: -30,
y: 10
},
material,
material: new THREE.MeshLambertMaterial({
color: 0xFFFFFF,
emissive: 0xFF0000,
emissiveIntensity: 0.4,
}),
modules: [
new WHS.TextureModule({
@@ -30,21 +29,16 @@ const ball = new WHS.Sphere({
],
});
const fireLight = new WHS.PointLight({
color: 0xff0000,
intensity: 5,
});
ball.physics = ballPhysics;
ball.fireLight = fireLight;
ball.addTo(app);
ball.add(fireLight);
camera.native.target = ball.native;
ball.checkLife = () => {
if (ball.position.x > ground.geometry.parameters.width / 2 || ball.position.x < -ground.geometry.parameters.width / 2) {
if (ball.position.x > ground.geometry.parameters.width / 2
|| ball.position.x < -ground.geometry.parameters.width / 2
|| ball.position.z > -ground.SIZE) {
location.reload();
}
}
@@ -79,66 +73,37 @@ ball.checkLife = () => {
color: 0xffffff,
});
new THREE.Geometry();
var smokeCount = 2000,
smokes = new THREE.Geometry(),
smokeMaterial = new THREE.PointsMaterial({
size: 1.5,
transparent: true,
color: 0x666666,
opacity: 0.5,
});
const radius = ball.params.geometry.radius;
const start = ball.position;
for (var p = 0; p < particleCount; p++) {
// create a particle with random
// position values, -250 -> 250
var pX = start.x + THREE.Math.randFloatSpread(radius),
pY = start.y + THREE.Math.randFloatSpread(radius),
pZ = start.z + THREE.Math.randFloatSpread(radius),
particle = new THREE.Vector3(pX, pY, pZ)
particle.lifetime = ball.params.geometry.radius + THREE.Math.randFloat(1, 1 + FIRE_HEIGHT_RANDOMNESS) * FIRE_HEIGHT;
//particle.color.offsetHSL(Math.random(), 0, Math.random());
particle.lifetime = Math.random() < 0.5 ? 0 : ball.params.geometry.radius + THREE.Math.randFloat(0.5, 1 + FIRE_HEIGHT_RANDOMNESS) * FIRE_HEIGHT;
// add it to the geometry
particles.vertices.push(particle);
particles.colors.push(new THREE.Color(1, 0, 0));
}
particles.colorsNeedUpdate = true;
for (var i = 0; i < spriteCount; i++) {
var pX = start.x + THREE.Math.randFloatSpread(radius),
pY = start.y + THREE.Math.randFloatSpread(radius),
pZ = start.z + THREE.Math.randFloatSpread(radius),
particle = new THREE.Vector3(pX, pY, pZ)
particle.lifetime = ball.params.geometry.radius + THREE.Math.randFloat(1, 1 + FIRE_HEIGHT_RANDOMNESS) * FIRE_HEIGHT;
particle.lifetime = Math.random() < 0.5 ? 0 : ball.params.geometry.radius + THREE.Math.randFloat(0.5, 1 + FIRE_HEIGHT_RANDOMNESS) * FIRE_HEIGHT;
sprites.vertices.push(particle);
}
for (var i = 0; i < smokeCount; i++) {
var pX = start.x + THREE.Math.randFloatSpread(radius),
pY = start.y + THREE.Math.randFloat(radius),
pZ = start.z + THREE.Math.randFloatSpread(radius),
particle = new THREE.Vector3(pX, pY, pZ);
particle.lifetime = ball.params.geometry.radius + THREE.Math.randFloat(1, 1 + FIRE_HEIGHT_RANDOMNESS) * FIRE_HEIGHT * 1.5;
smokes.vertices.push(particle);
}
// create the particle system
var points = WHS.MeshComponent.from(new THREE.Points(particles, pMaterial));
var spritesPoints = WHS.MeshComponent.from(new THREE.Points(sprites, spriteMaterial));
var smokePoints = WHS.MeshComponent.from(new THREE.Points(smokes, smokeMaterial));
smokePoints.isSmoke = true;
ball.fire = [points, spritesPoints, smokePoints];
ball.fire = [points, spritesPoints];
ball.fire.forEach(fire => {
fire.addTo(app);
})
@@ -154,25 +119,32 @@ ball.checkLife = () => {
);
fire.geometry.vertices.forEach((v, i) => {
v.y += THREE.Math.randFloat(0, SPREAD_SPEED / 4);
v.x += THREE.Math.randFloatSpread(SPREAD_SPEED) + velocity.x * -0.02;
v.z += THREE.Math.randFloatSpread(SPREAD_SPEED) + velocity.z * -0.01;
let x = v.x + THREE.Math.randFloatSpread(SPREAD_SPEED) + velocity.x * -0.02;
let y = v.y + THREE.Math.randFloat(0, SPREAD_SPEED / 4);
let z = v.z + THREE.Math.randFloatSpread(SPREAD_SPEED) + velocity.z * -0.01;
if (fire.material.vertexColors === THREE.VertexColors) {
v.set(x, y, z);
if (!v.isSmoke && fire.material.vertexColors === THREE.VertexColors) {
fire.geometry.colors[i].offsetHSL(7e-4, 0, 0);
}
if (v.y >= v.lifetime) {
if (fire.isSmoke) {
v.y = FIRE_HEIGHT/3 + THREE.Math.randFloat(0, FIRE_HEIGHT_RANDOMNESS);
if (!v.isSmoke && fire.material.vertexColors === THREE.VertexColors) {
v.isSmoke = true;
fire.geometry.colors[i].setHex(0x444444)
v.lifetime += FIRE_HEIGHT * 0.5;
} else {
v.y = Math.min(radius, radius * velocity.z / -50);
}
y = Math.min(radius, radius * velocity.z / -50);
v.x = 0;
v.z = -ball.params.geometry.radius * 3;
x = 0;
z = -ball.params.geometry.radius * 3;
v.lifetime = ball.params.geometry.radius + THREE.Math.randFloat(1, 1 + FIRE_HEIGHT_RANDOMNESS) * FIRE_HEIGHT * (fire.isSmoke ? 1.5 : 1);
v.lifetime = ball.params.geometry.radius + THREE.Math.randFloat(1, 1 + FIRE_HEIGHT_RANDOMNESS) * FIRE_HEIGHT;
v.set(x, y, z);
v.isSmoke = false;
if (fire.material.vertexColors === THREE.VertexColors) {
const r = THREE.Math.randFloat(0.8, 1);
@@ -181,6 +153,7 @@ ball.checkLife = () => {
fire.geometry.colors[i].setRGB(r, g, b);
}
}
}
});
if (fire.material.vertexColors === THREE.VertexColors) {
@@ -189,5 +162,19 @@ ball.checkLife = () => {
fire.geometry.verticesNeedUpdate = true;
});
});
const fireLight = new WHS.PointLight({
color: 0xff0000,
intensity: 5,
});
ball.fireLight = fireLight;
ball.add(fireLight);
}());
let hits = 0;
ball.on('collision', (o, v, r, cn) => {
if (o.uuid === ground.native.uuid) return;
rand(audio.impacts).play();
hits++;
GUI.setHits(hits);
});
+19 -15
View File
@@ -1,14 +1,18 @@
const DFORCE = 3e3;
const DFORCE = 6e3;
const AFORCE = 500;
const VFORCE = 1e4;
Mousetrap.bind('left', () => {
if (!ball.started) return;
const v = ball.physics.getLinearVelocity();
ball.physics.setLinearVelocity({ x: Math.min(0, v.x), y: v.y, z: v.z });
ball.physics.applyCentralForce({ x: -DFORCE, y: 0, z: 0 });
});
Mousetrap.bind('right', () => {
if (!ball.started) return;
const v = ball.physics.getLinearVelocity();
ball.physics.setLinearVelocity({ x: Math.max(0, v.x), y: v.y, z: v.z });
ball.physics.applyCentralForce({ x: DFORCE, y: 0, z: 0 });
});
@@ -19,20 +23,20 @@ Mousetrap.bind('up', () => {
//ball.methods.updateVelocity();
});
Mousetrap.bind('space', () => {
if (!ball.started) return;
if (ball.physics.data.touches.length) {
ball.physics.applyCentralForce({ x: 0, y: VFORCE, z: 0 });
}
//ball.speed = Math.min(config.MAX_SPEED, Math.max(config.FINAL_SPEED, ball.speed + config.SPEED_INCREASE));
//ball.methods.updateVelocity();
});
//Mousetrap.bind('space', () => {
//if (!ball.started) return;
//if (ball.physics.data.touches.length) {
//ball.physics.applyCentralForce({ x: 0, y: VFORCE, z: 0 });
//}
////ball.speed = Math.min(config.MAX_SPEED, Math.max(config.FINAL_SPEED, ball.speed + config.SPEED_INCREASE));
////ball.methods.updateVelocity();
//});
Mousetrap.bind('down', () => {
if (!ball.started) return;
ball.physics.applyCentralForce({ x: 0, y: 0, z: AFORCE * 3 });
//ball.speed = Math.min(config.MAX_SPEED, Math.max(config.FINAL_SPEED, ball.speed - config.SPEED_INCREASE));
//ball.methods.updateVelocity();
});
//Mousetrap.bind('down', () => {
//if (!ball.started) return;
//ball.physics.applyCentralForce({ x: 0, y: 0, z: AFORCE * 3 });
////ball.speed = Math.min(config.MAX_SPEED, Math.max(config.FINAL_SPEED, ball.speed - config.SPEED_INCREASE));
////ball.methods.updateVelocity();
//});
+4
View File
@@ -3,6 +3,7 @@ const GUI = {
score: document.getElementById('score'),
speed: document.getElementById('speed'),
time: document.getElementById('time'),
hits: document.getElementById('hits'),
},
setScore(s) {
GUI.elements.score.textContent = Math.floor(s).toString().padStart(3, '0');
@@ -13,6 +14,9 @@ const GUI = {
setStartingTime() {
GUI.startingTime = moment();
},
setHits(s) {
GUI.elements.hits.textContent = Math.floor(s).toString().padStart(2, '0');
},
tickTime() {
const now = moment();
const diff = moment.duration(now.diff(GUI.startingTime));
+109 -18
View File
@@ -1,36 +1,127 @@
function level0() {
function jumpBoard(x, z) {
const cylinder = new WHS.Cylinder({
const step = rad(10);
const tan = Math.tan(step);
const BOX_SIZE = 100;
function add({ x, y, z } = {}, { width, depth, height } = {}, rotation = {}) {
y = y || (tan * z) + BOX_SIZE/2;
width = width || BOX_SIZE;
height = height || BOX_SIZE;
depth = depth || BOX_SIZE;
rotation.x = rotation.x || -step;
const box = new WHS.Box({
geometry: {
radiusTop: 50,
radiusBottom: 1,
radiusSegments: 3,
heightSegments: 1,
height: 2,
width,
depth,
height,
},
material: new THREE.MeshPhongMaterial({
color: 0xffff00,
color: 0xffffff,
}),
position: [x, 0, z],
rotation: [Math.PI, rad(-35), 0],
position: [x, y, z],
rotation,
modules: [
new PHYSICS.CylinderModule({
new PHYSICS.BoxModule({
mass: 0,
friction: 1,
restitution: 0,
})
]
});
//cylinder.addTo(app);
ground.add(cylinder);
box.addTo(app);
return box;
}
//jumpBoard(5, -50);
//jumpBoard(5, -100);
//
//ring({ x: 0, y: 10, z: -150 });
const SPACE_UNIT = 250;
const patterns = [{
items: [3,4,5],
randoms: {
startX() {
return Math.random() > 0.5 ? 200 : -200;
},
},
x(i, props) {
return props.startX + i * 50 * (props.startX === 200 ? -1 : 1);
},
z(i) {
return i * -BOX_SIZE;
},
}, {
items: [3,4,6],
props: {
side: 150,
},
rot: {
y(i, props) {
if (i % 3 == 0) {
return THREE.Math.randFloatSpread(Math.PI);
}
return 0;
}
},
size(i, props) {
return THREE.Math.randInt(BOX_SIZE * 0.8, BOX_SIZE * 1.2);
},
x(i, props) {
if (i % 3 == 0) {
return 0;
} else {
return i % 3 == 1 ? props.side : -props.side;
}
},
z(i) {
if (i % 3 == 0) {
return i * -SPACE_UNIT;
} else {
return i % 3 == 1 ? i * -SPACE_UNIT : (i - 1) * -SPACE_UNIT;
}
}
}];
const applyPattern = (sz, { items, x, z, rot, props, randoms, space, size } = {}) => {
props = props || {};
randoms = randoms || {};
space = space || SPACE_UNIT;
rot = rot || {};
const count = rand(items);
const rs = {};
Object.entries(randoms).forEach(([key, value]) => {
rs[key] = value();
});
Object.assign(props, rs);
let zz;
for (let i = 0; i < count; i++) {
zz = sz + z(i, props);
const rotation = {};
Object.entries(rot).forEach(([key, value]) => {
rotation[key] = value(i, props);
});
let boxSize = BOX_SIZE;
if (size) {
boxSize = size(i, props);
}
add({ x: x(i, props), z: zz }, { width: boxSize, height: boxSize, depth: boxSize }, rotation);
}
return zz - space;
}
let sz = -300;
while (-sz < ground.SIZE) {
const pattern = rand(patterns);
sz = applyPattern(sz, pattern);
}
}
level0();
+5 -1
View File
@@ -40,9 +40,13 @@ const entrance = () => {
GUI.setStartingTime();
const diff = camera.position.y - ball.position.y;
ball.started = true;
level0();
audio.rumble.play();
app.physics.addEventListener('update', function() {
camera.position.set(camera.position.x, ball.position.y + diff, ball.position.z + 130);
//camera.position.set(camera.position.x, ball.position.y + diff, ball.position.z + 130);
camera.position.set(ball.position.x, ball.position.y + diff, ball.position.z + 130);
camera.native.lookAt(ball.position);
directionalLight.position.set(directionalLight.position.x, directionalLight.position.y, ball.position.z - 300);
GUI.setScore(-ball.position.z / 100);
+2
View File
@@ -1,2 +1,4 @@
const rad = (deg) => deg * Math.PI / 180;
const rand = (items) => items[Math.floor(Math.random() * items.length)];
+4 -2
View File
@@ -34,7 +34,7 @@ let ground;
(function groundinit() {
const WIDTH = 500;
const SIZE = 1e5;
const mesh = new WHS.Plane({
ground = new WHS.Plane({
geometry: {
width: WIDTH,
height: SIZE,
@@ -51,12 +51,14 @@ let ground;
}),
new PHYSICS.PlaneModule({
mass: 0,
restitution: 0,
}),
],
material: new THREE.MeshPhongMaterial({ color: 0xffffff })
});
ground = mesh;
ground.SIZE = SIZE;
ground.addTo(app);
}());