Files
shooting-word/js/intro.js
T

154 lines
4.6 KiB
JavaScript

function runIntro() {
introPlaying = true;
const I = CONFIG.intro;
const ih = H / 1000;
const IS = {
fontSize: Math.round(I.fontSize * ih),
glow: Math.round(I.glow * ih),
trailGlow: Math.round(I.trailGlow * ih),
projectileGlow: Math.round(I.projectileGlow * ih),
projectileRadius: Math.round(I.projectileRadius * ih),
trailRect: Math.round(I.trailRect * ih),
subtitleFont: Math.round(I.subtitleFont * ih),
subtitleGlow: Math.round(I.subtitleGlow * ih),
subtitleYOffset: Math.round(I.subtitleYOffset * ih),
};
const TEXT_Y = Math.round(H * I.textYR);
ctx.save();
ctx.font = `bold ${IS.fontSize}px "Courier New", monospace`;
const totalW = ctx.measureText("SHOOTING WORLD").width;
const worW = ctx.measureText("SHOOTING WOR").width;
const lW = ctx.measureText("L").width;
const dW = ctx.measureText("D").width;
ctx.restore();
const cx = W / 2;
const lTargetX = cx - totalW / 2 + worW + lW / 2;
const lTargetY = TEXT_Y;
const shooterX = cx;
const shooterY = H - S.shooterOffset;
let frame = 0;
let textAlpha = 0;
let p1 = [];
let shots = [];
function drawPartialWorld(alpha, dSlide) {
ctx.save();
ctx.font = `bold ${IS.fontSize}px "Courier New", monospace`;
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.globalAlpha = alpha;
ctx.fillStyle = CONFIG.colors.primary;
ctx.shadowColor = CONFIG.colors.primaryGlow;
ctx.shadowBlur = IS.glow;
ctx.fillText("SHOOTING WOR", cx - totalW / 2 + worW / 2, TEXT_Y);
const lFade = Math.max(0, 1 - dSlide);
if (lFade > 0) {
ctx.globalAlpha = alpha * lFade;
ctx.fillText("L", cx - totalW / 2 + worW + lW / 2, TEXT_Y);
}
const dOffset = lW * dSlide;
ctx.globalAlpha = alpha;
ctx.fillText("D", cx - totalW / 2 + worW + lW + dW / 2 - dOffset, TEXT_Y);
ctx.restore();
}
function drawShotProjectile(s) {
const x = shooterX + (lTargetX - shooterX) * s.progress;
const y = shooterY + (lTargetY - shooterY) * s.progress;
ctx.save();
for (let t of s.trail) {
ctx.globalAlpha = t.life * I.trailAlpha;
ctx.fillStyle = CONFIG.colors.primary;
ctx.shadowColor = CONFIG.colors.primary;
ctx.shadowBlur = IS.trailGlow;
ctx.fillRect(t.x - IS.trailRect / 2, t.y - IS.trailRect / 2, IS.trailRect, IS.trailRect);
}
if (!s.done) {
ctx.globalAlpha = 1;
ctx.fillStyle = CONFIG.colors.primary;
ctx.shadowColor = CONFIG.colors.primary;
ctx.shadowBlur = IS.projectileGlow;
ctx.beginPath();
ctx.arc(x, y, IS.projectileRadius, 0, Math.PI * 2);
ctx.fill();
}
ctx.restore();
}
function introLoop() {
frame++;
if (frame <= I.fadeInFrames) {
textAlpha = Math.min(1, frame / I.fadeInFrames);
}
if (frame === I.shot1Frame) shots.push({ progress: 0, trail: [], done: false });
if (frame === I.shot2Frame) shots.push({ progress: 0, trail: [], done: false });
if (frame === I.shot3Frame) shots.push({ progress: 0, trail: [], done: false });
for (let s of shots) {
if (s.done) continue;
s.progress = Math.min(1, s.progress + I.shotSpeed);
const x = shooterX + (lTargetX - shooterX) * s.progress;
const y = shooterY + (lTargetY - shooterY) * s.progress;
s.trail.push({ x, y, life: 1 });
if (s.trail.length > I.trailMax) s.trail.shift();
for (let t of s.trail) t.life -= I.trailDecay;
s.trail = s.trail.filter((t) => t.life > 0);
if (s.progress >= 1) {
s.done = true;
for (let i = 0; i < I.particleCountPerHit; i++) {
p1.push(new Particle(lTargetX, lTargetY, CONFIG.colors.primary));
}
}
}
let dSlide = 0;
if (frame >= I.slideStartFrame) {
dSlide = Math.min(1, (frame - I.slideStartFrame) / I.slideDuration);
}
for (let p of p1) p.update();
p1 = p1.filter((p) => p.life > 0);
ctx.clearRect(0, 0, W, H);
drawGrid();
drawPartialWorld(textAlpha, dSlide);
for (let s of shots) drawShotProjectile(s);
for (let p of p1) p.draw();
if (frame < I.totalFrames) {
requestAnimationFrame(introLoop);
} else {
p1 = [];
introPlaying = false;
ctx.clearRect(0, 0, W, H);
drawGrid();
drawPartialWorld(1, 1);
ctx.save();
ctx.font = `${IS.subtitleFont}px "Courier New", monospace`;
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillStyle = CONFIG.colors.primaryDim;
ctx.shadowColor = CONFIG.colors.primary;
ctx.shadowBlur = IS.subtitleGlow;
ctx.fillText(CONFIG.texts.startSubtitle, cx, TEXT_Y + IS.subtitleYOffset);
ctx.restore();
}
}
setTimeout(introLoop, I.startDelay);
}