}
function start(game) {
-
- function pinwheelPositionUpdate(game, viewportX, viewportY) {
- const vFOV = THREE.MathUtils.degToRad(game.view.camera.fov);
- const viewportHeight = 2 * Math.tan(vFOV / 2) * (game.view.camera.position.z - game.objects.pinwheel.position.z);
- game.objects.pinwheel.cameraX = viewportHeight * viewportX;
- game.objects.pinwheel.cameraY = - viewportHeight * viewportY;
- }
-
- function cursorMoveEvent(canvasLocalX, canvasLocalY) {
- const canvasBb = game.view.canvas.getBoundingClientRect();
- // Intentional division by height instead of width in the following line, since
- // three.js controls the vertical FOV. So if we ever change the aspect ratio from 1:1,
- // y will still be in range (-0.5, 0.5), but the range for x will be smaller or larger.
- const x = (canvasLocalX - canvasBb.x - (canvasBb.width / 2)) / canvasBb.height;
- const y = (canvasLocalY - canvasBb.y - (canvasBb.height / 2)) / canvasBb.height;
- pinwheelPositionUpdate(game, x, y);
- }
-
- document.body.addEventListener('mousemove', e => cursorMoveEvent(e.clientX, e.clientY));
- document.body.addEventListener('touchmove', e => cursorMoveEvent(e.touches[0].clientX, e.touches[0].clientY));
}
function init(game, canvas) {
const pinwheelMaterial = new THREE.MeshPhongMaterial({
map: game.assets.textures.pinwheel,
transparent: true,
- alphaTest: 0.5,
+ alphaTest: 0.01,
+ opacity: 0.0,
});
game.objects.pinwheel = new THREE.Mesh(pinwheelGeometry, [null, null, null, null, pinwheelMaterial, null]);
game.objects.pinwheel.position.setY(2);
game.view.camera.position.set(-5, -game.courseRadius, game.view.camera.position.z);
+ function pinwheelPositionUpdate(game, viewportX, viewportY) {
+ const vFOV = THREE.MathUtils.degToRad(game.view.camera.fov);
+ const viewportHeight = 2 * Math.tan(vFOV / 2) * (game.view.camera.position.z - game.objects.pinwheel.position.z);
+ game.objects.pinwheel.cameraX = viewportHeight * viewportX;
+ game.objects.pinwheel.cameraY = - viewportHeight * viewportY;
+ }
+
+ function cursorMoveEvent(canvasLocalX, canvasLocalY) {
+ const canvasBb = game.view.canvas.getBoundingClientRect();
+ // Intentional division by height instead of width in the following line, since
+ // three.js controls the vertical FOV. So if we ever change the aspect ratio from 1:1,
+ // y will still be in range (-0.5, 0.5), but the range for x will be smaller or larger.
+ const x = (canvasLocalX - canvasBb.x - (canvasBb.width / 2)) / canvasBb.height;
+ const y = (canvasLocalY - canvasBb.y - (canvasBb.height / 2)) / canvasBb.height;
+ pinwheelPositionUpdate(game, x, y);
+ }
+
+ document.body.addEventListener('mousemove', e => cursorMoveEvent(e.clientX, e.clientY));
+ document.body.addEventListener('touchmove', e => cursorMoveEvent(e.touches[0].clientX, e.touches[0].clientY));
+
// All vectors used by the game loop (no allocations inside)
game.var = {};
game.var.featherLocalPos = new THREE.Vector3();
let delta = Math.min(game.view.clock.getDeltaTime(), 1 / 12);
game.timeProgress = (game.timeProgress + delta);
+ game.objects.pinwheel.rotation.z -= 5 * delta;
+ game.objects.pinwheel.position.x = game.view.camera.position.x + game.objects.pinwheel.cameraX;
+ game.objects.pinwheel.position.y = game.view.camera.position.y + game.objects.pinwheel.cameraY;
+
if(game.ui.currentPage != 'gameplay') {
let cameraSwayFactor = 1;
let cameraX = 0;
game.objects.feather.position.setX(-11.45 + 12 * Math.min(1, easeInOut(Math.max(0, game.timeProgress - 4) / 4)));
game.objects.feather.position.setY(-game.courseRadius - 4.2 + 4 * Math.min(1, easeInOut(Math.max(0, game.timeProgress - 4) / 4)));
game.objects.feather.position.setZ(-6.6 + 6.6 * Math.min(1, easeInOut(Math.max(0, game.timeProgress - 4) / 4)));
+ game.objects.pinwheel.material[4].opacity = easeInOut(Math.max(0, (game.timeProgress - 7)));
if(game.timeProgress >= 8) {
- game.ui.currentPage = 'gameplay';
- game.timeProgress = 0;
+ game.ui.moveToPage('gameplay', true);
start(game);
}
}
- game.view.camera.position.setY(-game.courseRadius + 0.03 * cameraSwayFactor * Math.sin(game.view.clock.getElapsedTime() * 0.5));
- game.view.camera.position.setX(cameraX + 0.015 * cameraSwayFactor * Math.sin(game.view.clock.getElapsedTime() * 0.7));
+ game.view.camera.position.setY(-game.courseRadius + 0.07 * cameraSwayFactor * Math.sin(game.view.clock.getElapsedTime() * 0.5));
+ game.view.camera.position.setX(cameraX + 0.05 * cameraSwayFactor * Math.sin(game.view.clock.getElapsedTime() * 0.7));
renderer.render(scene, game.view.camera);
return;
}
game.objects.feather.twistSpeed = Math.min(0.13, game.objects.feather.twistSpeed);
game.objects.feather.rotation.x = (game.objects.feather.rotation.x + game.objects.feather.twistSpeed) % (2 * Math.PI);
- game.objects.pinwheel.rotation.z -= 5 * delta;
- game.objects.pinwheel.position.x = game.view.camera.position.x + game.objects.pinwheel.cameraX;
- game.objects.pinwheel.position.y = game.view.camera.position.y + game.objects.pinwheel.cameraY;
let collectedScale = lerp(0.6, 0.3, 1 - Math.pow(1 - game.objects.words.collectedCount / game.objects.words.length, 2));
for(let i = 0; i < game.objects.words.length; i++) {
window['game'] = {
state: 'loadingAssets',
ui: {
- root: document.querySelector('.game'),
+ root: document.querySelector('.game-upintheair'),
},
};
-game.ui.moveToPage = (target) => {
- const fadeDuration = 250;
+game.ui.moveToPage = (target, skipFade = false) => {
+ let fadeDuration = 250;
+ if(skipFade) {
+ fadeDuration = 0;
+ }
// After the gameplay page is shown for the first time, always keep it around as a backdrop
game.ui.root.querySelectorAll('.ui-page:not(.' + target + '):not(.gameplay)').forEach((page) => {
page.style.opacity = '0';
game.startTime = game.view.clock.getElapsedTime();
}
};
+game.ui.root.style.fontSize = (game.ui.root.clientWidth / 50) + 'px';
+window.addEventListener('resize', () => {
+ game.ui.root.style.fontSize = (game.ui.root.clientWidth / 50) + 'px';
+});
loadAllAssets(game, (progress) => {
let percentage = Math.floor(100 * progress);
- document.querySelector('.ui-page.loading progress').value = percentage;
- document.querySelector('.ui-page.loading span').innerText = percentage;
+ game.ui.root.querySelector('.ui-page.loading progress').value = percentage;
+ game.ui.root.querySelector('.ui-page.loading span').innerText = percentage;
}).then(() => {
+ if(window.location.hostname == 'fietkau.media') {
+ game.ui.root.querySelector('.ui-page.title .footer span:last-child').remove();
+ }
game.ui.moveToPage('title');
- init(window['game'], document.querySelector('canvas'));
- document.querySelector('#enableMusic').addEventListener('change', () => toggleMusic(window['game']));
+ init(window['game'], game.ui.root.querySelector('canvas'));
+ game.ui.root.querySelector('#enableMusic').addEventListener('change', () => toggleMusic(window['game']));
}, (err) => {
console.error(err);
});