209 lines
		
	
	
	
		
			5.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			209 lines
		
	
	
	
		
			5.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
const canvas = document.getElementById("skillbar");
 | 
						|
const context = canvas.getContext("2d");
 | 
						|
const W = canvas.width;
 | 
						|
const H = canvas.height;
 | 
						|
 | 
						|
const config = {
 | 
						|
    indicatorColor: "#FF0000",
 | 
						|
    backgroundArcColor: "#FFFFFF",
 | 
						|
    greenZoneColor: "#FFFFFF",
 | 
						|
    validKeys: [],
 | 
						|
    backgroundArcWidth: 2,
 | 
						|
    greenZoneWidth: 20,
 | 
						|
    indicatorLineWidth: 50,
 | 
						|
    keyPressColor: "#FFFFFF",
 | 
						|
    keyPressFontSize: "100px Arial", // adjust line 130 for centering if you change this
 | 
						|
};
 | 
						|
 | 
						|
const difficultySettings = {
 | 
						|
    easy: {
 | 
						|
        greenZoneSize: 10, // adjust this in small increments
 | 
						|
        speed: 15,
 | 
						|
        streaksRequired: 3,
 | 
						|
    },
 | 
						|
    medium: {
 | 
						|
        greenZoneSize: 8,
 | 
						|
        speed: 25,
 | 
						|
        streaksRequired: 4,
 | 
						|
    },
 | 
						|
    hard: {
 | 
						|
        greenZoneSize: 6,
 | 
						|
        speed: 35,
 | 
						|
        streaksRequired: 5,
 | 
						|
    },
 | 
						|
};
 | 
						|
 | 
						|
let lastTime = 0;
 | 
						|
let currentDifficulty;
 | 
						|
let needed = 1;
 | 
						|
let streak = 0;
 | 
						|
let time;
 | 
						|
let degrees = 0;
 | 
						|
let newDegrees = 0;
 | 
						|
let gStart;
 | 
						|
let gEnd;
 | 
						|
let keyToPress;
 | 
						|
let animationFrame;
 | 
						|
 | 
						|
// Util
 | 
						|
 | 
						|
const getRandomInteger = (min, max) => {
 | 
						|
    return Math.floor(Math.random() * (max - min + 1)) + min;
 | 
						|
};
 | 
						|
 | 
						|
const degreesToRadians = (degrees) => {
 | 
						|
    return (degrees * Math.PI) / 180;
 | 
						|
};
 | 
						|
 | 
						|
const radiansToDegrees = (radians) => {
 | 
						|
    return radians * (180 / Math.PI);
 | 
						|
};
 | 
						|
 | 
						|
// Main Functions
 | 
						|
 | 
						|
const startSkillbar = (difficulty, validKeys) => {
 | 
						|
    canvas.style.display = "block";
 | 
						|
    config.validKeys = validKeys.split("");
 | 
						|
    currentDifficulty = difficulty;
 | 
						|
    const settings = difficultySettings[currentDifficulty];
 | 
						|
    needed = settings.streaksRequired;
 | 
						|
    newDegrees = 360;
 | 
						|
    keyToPress = config.validKeys[getRandomInteger(0, config.validKeys.length - 1)];
 | 
						|
    gStart = getRandomInteger(20, 40) / 10;
 | 
						|
    gEnd = gStart + settings.greenZoneSize / 10;
 | 
						|
    degrees = 0;
 | 
						|
    animateSkillbar();
 | 
						|
};
 | 
						|
 | 
						|
const animateSkillbar = (timestamp) => {
 | 
						|
    if (timestamp !== undefined) {
 | 
						|
        if (lastTime === 0) {
 | 
						|
            lastTime = timestamp;
 | 
						|
        }
 | 
						|
 | 
						|
        const deltaTime = timestamp - lastTime;
 | 
						|
        const speedPerSecond = difficultySettings[currentDifficulty].speed;
 | 
						|
        const increment = (deltaTime / 1000) * speedPerSecond * 10;
 | 
						|
 | 
						|
        degrees += increment;
 | 
						|
 | 
						|
        if (degrees >= newDegrees) {
 | 
						|
            handleResult(false);
 | 
						|
        } else {
 | 
						|
            renderSkillbar();
 | 
						|
            lastTime = timestamp;
 | 
						|
            animationFrame = requestAnimationFrame(animateSkillbar);
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        animationFrame = requestAnimationFrame(animateSkillbar);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
const drawArc = (x, y, radius, startAngle, endAngle, strokeColor, lineWidth) => {
 | 
						|
    context.beginPath();
 | 
						|
    context.strokeStyle = strokeColor;
 | 
						|
    context.lineWidth = lineWidth;
 | 
						|
    context.arc(x, y, radius, startAngle, endAngle, false);
 | 
						|
    context.stroke();
 | 
						|
};
 | 
						|
 | 
						|
const renderSkillbar = () => {
 | 
						|
    context.clearRect(0, 0, W, H);
 | 
						|
 | 
						|
    // Draw the background arc - would like to move this so it's not redrawn but meh
 | 
						|
    drawArc(W / 2, H / 2, 100, 0, Math.PI * 2, config.backgroundArcColor, config.backgroundArcWidth);
 | 
						|
 | 
						|
    // Draw the green zone
 | 
						|
    drawArc(W / 2, H / 2, 100, gStart - Math.PI / 2, gEnd - Math.PI / 2, config.greenZoneColor, config.greenZoneWidth);
 | 
						|
 | 
						|
    // Draw the moving indicator
 | 
						|
    const radians = degreesToRadians(degrees);
 | 
						|
    drawArc(W / 2, H / 2, 100 - 10, radians - 0.1 - Math.PI / 2, radians - Math.PI / 2, config.indicatorColor, config.indicatorLineWidth);
 | 
						|
 | 
						|
    // Display the key to press
 | 
						|
    const text = keyToPress.toUpperCase();
 | 
						|
    context.fillStyle = config.keyPressColor;
 | 
						|
    context.font = config.keyPressFontSize;
 | 
						|
    context.textAlign = "center";
 | 
						|
    context.textBaseline = "middle";
 | 
						|
    context.fillText(text, W / 2, H / 2 + 5);
 | 
						|
};
 | 
						|
 | 
						|
const reanimateSkillbar = () => {
 | 
						|
    if (animationFrame) cancelAnimationFrame(animationFrame);
 | 
						|
    const settings = difficultySettings[currentDifficulty];
 | 
						|
    gStart = getRandomInteger(20, 40) / 10;
 | 
						|
    gEnd = gStart + settings.greenZoneSize / 10;
 | 
						|
    needed = settings.streaksRequired;
 | 
						|
    lastTime = 0;
 | 
						|
    degrees = 0;
 | 
						|
    newDegrees = 360;
 | 
						|
    keyToPress = config.validKeys[getRandomInteger(0, config.validKeys.length - 1)];
 | 
						|
    animateSkillbar();
 | 
						|
};
 | 
						|
 | 
						|
// Handlers
 | 
						|
 | 
						|
const handleResult = (isCorrect) => {
 | 
						|
    if (animationFrame) cancelAnimationFrame(animationFrame);
 | 
						|
    if (isCorrect) {
 | 
						|
        streak++;
 | 
						|
        if (streak === needed) {
 | 
						|
            endGame(true);
 | 
						|
        } else {
 | 
						|
            reanimateSkillbar();
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        endGame(false);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
const resetSkillbar = () => {
 | 
						|
    canvas.style.display = "none";
 | 
						|
    cancelAnimationFrame(animationFrame);
 | 
						|
    streak = 0;
 | 
						|
    needed = 1;
 | 
						|
    lastTime = 0;
 | 
						|
};
 | 
						|
 | 
						|
const endGame = (status) => {
 | 
						|
    document.removeEventListener("keydown", handleKeyDown);
 | 
						|
    fetch(`https://${GetParentResourceName()}/skillbarFinish`, {
 | 
						|
        method: "POST",
 | 
						|
        headers: {
 | 
						|
            "Content-Type": "application/json; charset=UTF-8",
 | 
						|
        },
 | 
						|
        body: JSON.stringify({ success: status }),
 | 
						|
    });
 | 
						|
    resetSkillbar();
 | 
						|
};
 | 
						|
 | 
						|
const handleKeyDown = (ev) => {
 | 
						|
    const keyPressed = ev.key;
 | 
						|
    if (config.validKeys.includes(keyPressed)) {
 | 
						|
        const d_start = radiansToDegrees(gStart);
 | 
						|
        const d_end = radiansToDegrees(gEnd);
 | 
						|
 | 
						|
        if (keyPressed === keyToPress && degrees >= d_start && degrees <= d_end) {
 | 
						|
            streak += 1;
 | 
						|
            if (streak === needed) {
 | 
						|
                endGame(true);
 | 
						|
            } else {
 | 
						|
                reanimateSkillbar();
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            endGame(false);
 | 
						|
        }
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
const handleWindowMessage = (event) => {
 | 
						|
    if (event.data.action === "openSkillbar") {
 | 
						|
        const difficulty = event.data.difficulty;
 | 
						|
        const validKeys = event.data.validKeys;
 | 
						|
        document.addEventListener("keydown", handleKeyDown);
 | 
						|
        startSkillbar(difficulty, validKeys);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
window.addEventListener("message", handleWindowMessage);
 |